Merge pull request #130 from HEPLean/Tensors_with_indices
refactor: Index notation
This commit is contained in:
commit
ab48e86d84
25 changed files with 3034 additions and 4407 deletions
15
HepLean.lean
15
HepLean.lean
|
@ -76,20 +76,21 @@ import HepLean.SpaceTime.LorentzTensor.EinsteinNotation.Basic
|
|||
import HepLean.SpaceTime.LorentzTensor.EinsteinNotation.IndexNotation
|
||||
import HepLean.SpaceTime.LorentzTensor.EinsteinNotation.Lemmas
|
||||
import HepLean.SpaceTime.LorentzTensor.EinsteinNotation.RisingLowering
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.AreDual
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.Basic
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.Color
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.ColorIndexList.Append
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.ColorIndexList.Basic
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.ColorIndexList.Contraction
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.ColorIndexList.Relations
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.Contraction
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.GetDual
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Basic
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Color
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Contraction
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.CountId
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Duals
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Equivs
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.OnlyUniqueDuals
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Subperm
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexString
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.OnlyUniqueDuals
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.TensorIndex
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.WithDual
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.WithUniqueDual
|
||||
import HepLean.SpaceTime.LorentzTensor.MulActionTensor
|
||||
import HepLean.SpaceTime.LorentzTensor.Real.Basic
|
||||
import HepLean.SpaceTime.LorentzTensor.Real.IndexNotation
|
||||
|
|
|
@ -61,7 +61,7 @@ noncomputable def fromIndexStringColor {R : Type} [CommSemiring R]
|
|||
(T : (einsteinTensor R m).Tensor cn) (s : String)
|
||||
(hs : listCharIsIndexString einsteinTensorColor.Color s.toList = true)
|
||||
(hn : n = (toIndexList' s hs).length)
|
||||
(hD : (toIndexList' s hs).withDual = (toIndexList' s hs).withUniqueDual)
|
||||
(hD : (toIndexList' s hs).OnlyUniqueDuals)
|
||||
(hC : IndexList.ColorCond.bool (toIndexList' s hs))
|
||||
(hd : TensorColor.ColorMap.DualMap.boolFin'
|
||||
(toIndexList' s hs).colorMap (cn ∘ Fin.cast hn.symm)) :
|
||||
|
@ -76,7 +76,7 @@ lemma fromIndexStringColor_indexList {R : Type} [CommSemiring R]
|
|||
(T : (einsteinTensor R m).Tensor cn) (s : String)
|
||||
(hs : listCharIsIndexString einsteinTensorColor.Color s.toList = true)
|
||||
(hn : n = (toIndexList' s hs).length)
|
||||
(hD : (toIndexList' s hs).withDual = (toIndexList' s hs).withUniqueDual)
|
||||
(hD : (toIndexList' s hs).OnlyUniqueDuals)
|
||||
(hC : IndexList.ColorCond.bool (toIndexList' s hs))
|
||||
(hd : TensorColor.ColorMap.DualMap.boolFin'
|
||||
(toIndexList' s hs).colorMap (cn ∘ Fin.cast hn.symm)) :
|
||||
|
@ -93,7 +93,7 @@ macro "dualMapTactic" : tactic =>
|
|||
Conditions are checked automatically. -/
|
||||
notation:20 T "|" S:21 => fromIndexStringColor T S
|
||||
(by decide)
|
||||
(by decide) (by decide)
|
||||
(by decide) (by rfl)
|
||||
(by decide)
|
||||
(by dualMapTactic)
|
||||
|
||||
|
@ -102,7 +102,7 @@ macro "prodTactic" : tactic =>
|
|||
`(tactic| {
|
||||
apply (ColorIndexList.AppendCond.iff_bool _ _).mpr
|
||||
change @ColorIndexList.AppendCond.bool einsteinTensorColor
|
||||
instIndexNotationColorEinsteinTensorColor instDecidableEqColorEinsteinTensorColor _ _
|
||||
instDecidableEqColorEinsteinTensorColor _ _
|
||||
simp only [prod_toIndexList, indexNotation_eq_color, fromIndexStringColor, mkDualMap,
|
||||
toTensorColor_eq, decidableEq_eq_color]
|
||||
decide})
|
||||
|
|
|
@ -1,120 +0,0 @@
|
|||
/-
|
||||
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.Basic
|
||||
/-!
|
||||
|
||||
# Indices which are dual in an index list
|
||||
|
||||
Given an list of indices we say two indices are dual if they have the same id.
|
||||
|
||||
For example the `0`, `2` and `3` index in `l₁ := ['ᵘ¹', 'ᵘ²', 'ᵤ₁', 'ᵘ¹']` are pairwise dual to
|
||||
one another. The `1` (`'ᵘ²'`) index is not dual to any other index in the list.
|
||||
|
||||
We also define the notion of dual indices in different lists. For example,
|
||||
the `1` index in `l₁` is dual to the `1` and the `4` indices in
|
||||
`l₂ := ['ᵘ³', 'ᵘ²', 'ᵘ⁴', 'ᵤ₂']`.
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
/-!
|
||||
|
||||
## Are dual indices
|
||||
|
||||
-/
|
||||
|
||||
/-- Two indices are dual if they are not equivalent, but have the same id. -/
|
||||
def AreDualInSelf (i j : Fin l.length) : Prop :=
|
||||
i ≠ j ∧ l.idMap i = l.idMap j
|
||||
|
||||
/-- Two indices in different `IndexLists` are dual to one another if they have the same `id`. -/
|
||||
def AreDualInOther (i : Fin l.length) (j : Fin l2.length) :
|
||||
Prop := l.idMap i = l2.idMap j
|
||||
|
||||
namespace AreDualInSelf
|
||||
|
||||
variable {l l2 : IndexList X} {i j : Fin l.length}
|
||||
|
||||
instance (i j : Fin l.length) : Decidable (l.AreDualInSelf i j) :=
|
||||
instDecidableAnd
|
||||
|
||||
@[symm]
|
||||
lemma symm (h : l.AreDualInSelf i j) : l.AreDualInSelf j i := by
|
||||
simp only [AreDualInSelf] at h ⊢
|
||||
exact ⟨h.1.symm, h.2.symm⟩
|
||||
|
||||
@[simp]
|
||||
lemma self_false (i : Fin l.length) : ¬ l.AreDualInSelf i i := by
|
||||
simp [AreDualInSelf]
|
||||
|
||||
@[simp]
|
||||
lemma append_inl_inl : (l ++ l2).AreDualInSelf (appendEquiv (Sum.inl i)) (appendEquiv (Sum.inl j))
|
||||
↔ l.AreDualInSelf i j := by
|
||||
simp [AreDualInSelf]
|
||||
|
||||
@[simp]
|
||||
lemma append_inr_inr (l l2 : IndexList X) (i j : Fin l2.length) :
|
||||
(l ++ l2).AreDualInSelf (appendEquiv (Sum.inr i)) (appendEquiv (Sum.inr j))
|
||||
↔ l2.AreDualInSelf i j := by
|
||||
simp [AreDualInSelf]
|
||||
|
||||
@[simp]
|
||||
lemma append_inl_inr (l l2 : IndexList X) (i : Fin l.length) (j : Fin l2.length) :
|
||||
(l ++ l2).AreDualInSelf (appendEquiv (Sum.inl i)) (appendEquiv (Sum.inr j)) =
|
||||
l.AreDualInOther l2 i j := by
|
||||
simp [AreDualInSelf, AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma append_inr_inl (l l2 : IndexList X) (i : Fin l2.length) (j : Fin l.length) :
|
||||
(l ++ l2).AreDualInSelf (appendEquiv (Sum.inr i)) (appendEquiv (Sum.inl j)) =
|
||||
l2.AreDualInOther l i j := by
|
||||
simp [AreDualInSelf, AreDualInOther]
|
||||
|
||||
end AreDualInSelf
|
||||
|
||||
namespace AreDualInOther
|
||||
|
||||
variable {l l2 l3 : IndexList X} {i : Fin l.length} {j : Fin l2.length}
|
||||
|
||||
instance {l : IndexList X} {l2 : IndexList X} (i : Fin l.length) (j : Fin l2.length) :
|
||||
Decidable (l.AreDualInOther l2 i j) := (l.idMap i).decEq (l2.idMap j)
|
||||
|
||||
@[symm]
|
||||
lemma symm (h : l.AreDualInOther l2 i j) : l2.AreDualInOther l j i := by
|
||||
rw [AreDualInOther] at h ⊢
|
||||
exact h.symm
|
||||
|
||||
@[simp]
|
||||
lemma append_of_inl (i : Fin l.length) (j : Fin l3.length) :
|
||||
(l ++ l2).AreDualInOther l3 (appendEquiv (Sum.inl i)) j ↔ l.AreDualInOther l3 i j := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma append_of_inr (i : Fin l2.length) (j : Fin l3.length) :
|
||||
(l ++ l2).AreDualInOther l3 (appendEquiv (Sum.inr i)) j ↔ l2.AreDualInOther l3 i j := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma of_append_inl (i : Fin l.length) (j : Fin l2.length) :
|
||||
l.AreDualInOther (l2 ++ l3) i (appendEquiv (Sum.inl j)) ↔ l.AreDualInOther l2 i j := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma of_append_inr (i : Fin l.length) (j : Fin l3.length) :
|
||||
l.AreDualInOther (l2 ++ l3) i (appendEquiv (Sum.inr j)) ↔ l.AreDualInOther l3 i j := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
end AreDualInOther
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -3,9 +3,6 @@ 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 Mathlib.Data.Set.Finite
|
||||
import Mathlib.Logic.Equiv.Fin
|
||||
import Mathlib.Data.Finset.Sort
|
||||
import Mathlib.Tactic.FinCases
|
||||
/-!
|
||||
|
||||
|
@ -101,27 +98,61 @@ instance : Decidable (listCharIndex X l) :=
|
|||
|
||||
/-!
|
||||
|
||||
## The definition of an index and its properties
|
||||
## The definition of an index
|
||||
|
||||
-/
|
||||
|
||||
/-- An index is a non-empty string satisfying the condtion `listCharIndex`,
|
||||
e.g. `ᵘ¹²` or `ᵤ₄₃` etc. -/
|
||||
def Index : Type := {s : String // listCharIndex X s.toList ∧ s.toList ≠ []}
|
||||
/-- An index for `X` is an pair of an element of `X` (the color of the index) and a natural
|
||||
number (the id of the index). -/
|
||||
def Index : Type := X × ℕ
|
||||
|
||||
instance : DecidableEq (Index X) := Subtype.instDecidableEq
|
||||
instance : DecidableEq (Index X) := instDecidableEqProd
|
||||
|
||||
namespace Index
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
|
||||
/-- Creats an index from a non-empty list of characters satisfying `listCharIndex`. -/
|
||||
def ofCharList (l : List Char) (h : listCharIndex X l ∧ l ≠ []) : Index X := ⟨l.asString, h⟩
|
||||
/-- The color associated to an index. -/
|
||||
def toColor (I : Index X) : X := I.1
|
||||
|
||||
instance : ToString (Index X) := ⟨fun i => i.val⟩
|
||||
/-- The natural number representating the id of an index. -/
|
||||
def id (I : Index X) : ℕ := I.2
|
||||
|
||||
lemma eq_iff_color_eq_and_id_eq (I J : Index X) : I = J ↔ I.toColor = J.toColor ∧ I.id = J.id := by
|
||||
refine Iff.intro ?_ ?_
|
||||
· intro h
|
||||
simp [h]
|
||||
· intro h
|
||||
cases I
|
||||
cases J
|
||||
simp [toColor, id] at h
|
||||
simp [h]
|
||||
|
||||
end Index
|
||||
|
||||
/-!
|
||||
|
||||
## The definition of an index and its properties
|
||||
|
||||
-/
|
||||
|
||||
/-- An index rep is a non-empty string satisfying the condtion `listCharIndex`,
|
||||
e.g. `ᵘ¹²` or `ᵤ₄₃` etc. -/
|
||||
def IndexRep : Type := {s : String // listCharIndex X s.toList ∧ s.toList ≠ []}
|
||||
|
||||
instance : DecidableEq (IndexRep X) := Subtype.instDecidableEq
|
||||
|
||||
namespace IndexRep
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
|
||||
/-- Creats an index from a non-empty list of characters satisfying `listCharIndex`. -/
|
||||
def ofCharList (l : List Char) (h : listCharIndex X l ∧ l ≠ []) : IndexRep X := ⟨l.asString, h⟩
|
||||
|
||||
instance : ToString (IndexRep X) := ⟨fun i => i.val⟩
|
||||
|
||||
/-- Gets the first character in an index e.g. `ᵘ` as an element of `charList X`. -/
|
||||
def head (s : Index X) : charList X :=
|
||||
def head (s : IndexRep X) : charList X :=
|
||||
⟨s.val.toList.head (s.prop.2), by
|
||||
have h := s.prop.1
|
||||
have h2 := s.prop.2
|
||||
|
@ -130,7 +161,7 @@ def head (s : Index X) : charList X :=
|
|||
simpa [isNotationChar] using h.1⟩
|
||||
|
||||
/-- The color associated to an index. -/
|
||||
def toColor (s : Index X) : X := (IndexNotation.notaEquiv).invFun s.head
|
||||
def toColor (s : IndexRep X) : X := (IndexNotation.notaEquiv).invFun s.head
|
||||
|
||||
/-- A map from super and subscript numerical characters to the natural numbers,
|
||||
returning `0` on all other characters. -/
|
||||
|
@ -159,397 +190,16 @@ def charToNat (c : Char) : Nat :=
|
|||
| _ => 0
|
||||
|
||||
/-- The numerical characters associated with an index. -/
|
||||
def tail (s : Index X) : List Char := s.val.toList.tail
|
||||
def tail (s : IndexRep X) : List Char := s.val.toList.tail
|
||||
|
||||
/-- The natural numbers assocaited with an index. -/
|
||||
def tailNat (s : Index X) : List Nat := s.tail.map charToNat
|
||||
def tailNat (s : IndexRep X) : List ℕ := s.tail.map charToNat
|
||||
|
||||
/-- The id of an index, as a natural number. -/
|
||||
def id (s : Index X) : Nat := s.tailNat.foldl (fun a b => 10 * a + b) 0
|
||||
def id (s : IndexRep X) : ℕ := s.tailNat.foldl (fun a b => 10 * a + b) 0
|
||||
|
||||
end Index
|
||||
|
||||
/-!
|
||||
|
||||
## List of indices
|
||||
|
||||
-/
|
||||
|
||||
/-- The type of lists of indices. -/
|
||||
structure IndexList where
|
||||
/-- The list of index values. For example `['ᵘ¹','ᵘ²','ᵤ₁']`. -/
|
||||
val : List (Index X)
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
|
||||
variable (l : IndexList X)
|
||||
|
||||
/-- The number of indices in an index list. -/
|
||||
def length : ℕ := l.val.length
|
||||
|
||||
lemma ext (h : l.val = l2.val) : l = l2 := by
|
||||
cases l
|
||||
cases l2
|
||||
simp_all
|
||||
|
||||
/-- The index list constructed by prepending an index to the list. -/
|
||||
def cons (i : Index X) : IndexList X := {val := i :: l.val}
|
||||
|
||||
@[simp]
|
||||
lemma cons_val (i : Index X) : (l.cons i).val = i :: l.val := by
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma cons_length (i : Index X) : (l.cons i).length = l.length + 1 := by
|
||||
rfl
|
||||
|
||||
/-- The tail of an index list. That is, the index list with the first index dropped. -/
|
||||
def tail : IndexList X := {val := l.val.tail}
|
||||
|
||||
@[simp]
|
||||
lemma tail_val : l.tail.val = l.val.tail := by
|
||||
rfl
|
||||
|
||||
/-- The first index in a non-empty index list. -/
|
||||
def head (h : l ≠ {val := ∅}) : Index X := l.val.head (by cases' l; simpa using h)
|
||||
|
||||
lemma head_cons_tail (h : l ≠ {val := ∅}) : l = (l.tail.cons (l.head h)) := by
|
||||
apply ext
|
||||
simp only [cons_val, tail_val]
|
||||
simp only [head, List.head_cons_tail]
|
||||
|
||||
lemma induction {P : IndexList X → Prop } (h_nil : P {val := ∅})
|
||||
(h_cons : ∀ (x : Index X) (xs : IndexList X), P xs → P (xs.cons x)) (l : IndexList X) : P l := by
|
||||
cases' l with val
|
||||
induction val with
|
||||
| nil => exact h_nil
|
||||
| cons x xs ih =>
|
||||
exact h_cons x ⟨xs⟩ ih
|
||||
|
||||
/-- The map of from `Fin s.numIndices` into colors associated to an index list. -/
|
||||
def colorMap : Fin l.length → X :=
|
||||
fun i => (l.val.get i).toColor
|
||||
|
||||
/-- The map of from `Fin s.numIndices` into the natural numbers associated to an index list. -/
|
||||
def idMap : Fin l.length → Nat :=
|
||||
fun i => (l.val.get i).id
|
||||
|
||||
lemma idMap_cast {l1 l2 : IndexList X} (h : l1 = l2) (i : Fin l1.length) :
|
||||
l1.idMap i = l2.idMap (Fin.cast (by rw [h]) i) := by
|
||||
subst h
|
||||
rfl
|
||||
|
||||
/-- Given a list of indices a subset of `Fin l.numIndices × Index X`
|
||||
of pairs of positions in `l` and the corresponding item in `l`. -/
|
||||
def toPosSet (l : IndexList X) : Set (Fin l.length × Index X) :=
|
||||
{(i, l.val.get i) | i : Fin l.length}
|
||||
|
||||
/-- Equivalence between `toPosSet` and `Fin l.numIndices`. -/
|
||||
def toPosSetEquiv (l : IndexList X) : l.toPosSet ≃ Fin l.length where
|
||||
toFun := fun x => x.1.1
|
||||
invFun := fun x => ⟨(x, l.val.get x), by simp [toPosSet]⟩
|
||||
left_inv x := by
|
||||
have hx := x.prop
|
||||
simp [toPosSet] at hx
|
||||
simp only [List.get_eq_getElem]
|
||||
obtain ⟨i, hi⟩ := hx
|
||||
have hi2 : i = x.1.1 := by
|
||||
obtain ⟨val, property⟩ := x
|
||||
obtain ⟨fst, snd⟩ := val
|
||||
simp_all only [Prod.mk.injEq]
|
||||
subst hi2
|
||||
simp_all only [Subtype.coe_eta]
|
||||
right_inv := by
|
||||
intro x
|
||||
rfl
|
||||
|
||||
lemma toPosSet_is_finite (l : IndexList X) : l.toPosSet.Finite :=
|
||||
Finite.intro l.toPosSetEquiv
|
||||
|
||||
instance : Fintype l.toPosSet where
|
||||
elems := Finset.map l.toPosSetEquiv.symm.toEmbedding Finset.univ
|
||||
complete := by
|
||||
intro x
|
||||
simp_all only [Finset.mem_map_equiv, Equiv.symm_symm, Finset.mem_univ]
|
||||
|
||||
/-- Given a list of indices a finite set of `Fin l.length × Index X`
|
||||
of pairs of positions in `l` and the corresponding item in `l`. -/
|
||||
def toPosFinset (l : IndexList X) : Finset (Fin l.length × Index X) :=
|
||||
l.toPosSet.toFinset
|
||||
|
||||
/-- The construction of a list of indices from a map
|
||||
from `Fin n` to `Index X`. -/
|
||||
def fromFinMap {n : ℕ} (f : Fin n → Index X) : IndexList X where
|
||||
val := (Fin.list n).map f
|
||||
|
||||
@[simp]
|
||||
lemma fromFinMap_numIndices {n : ℕ} (f : Fin n → Index X) :
|
||||
(fromFinMap f).length = n := by
|
||||
simp [fromFinMap, length]
|
||||
|
||||
/-!
|
||||
|
||||
## Appending index lists.
|
||||
|
||||
-/
|
||||
|
||||
section append
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
instance : HAppend (IndexList X) (IndexList X) (IndexList X) where
|
||||
hAppend := fun l l2 => {val := l.val ++ l2.val}
|
||||
|
||||
@[simp]
|
||||
lemma cons_append (i : Index X) : (l.cons i) ++ l2 = (l ++ l2).cons i := by
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma append_length : (l ++ l2).length = l.length + l2.length := by
|
||||
simp [IndexList.length]
|
||||
exact List.length_append l.val l2.val
|
||||
|
||||
lemma append_assoc : l ++ l2 ++ l3 = l ++ (l2 ++ l3) := by
|
||||
apply ext
|
||||
change l.val ++ l2.val ++ l3.val = l.val ++ (l2.val ++ l3.val)
|
||||
exact List.append_assoc l.val l2.val l3.val
|
||||
|
||||
/-- An equivalence between the sum of the types of indices of `l` an `l2` and the type
|
||||
of indices of the joined index list `l ++ l2`. -/
|
||||
def appendEquiv {l l2 : IndexList X} : Fin l.length ⊕ Fin l2.length ≃ Fin (l ++ l2).length :=
|
||||
finSumFinEquiv.trans (Fin.castOrderIso (List.length_append _ _).symm).toEquiv
|
||||
|
||||
/-- The inclusion of the indices of `l` into the indices of `l ++ l2`. -/
|
||||
def appendInl : Fin l.length ↪ Fin (l ++ l2).length where
|
||||
toFun := appendEquiv ∘ Sum.inl
|
||||
inj' := by
|
||||
intro i j h
|
||||
simp [Function.comp] at h
|
||||
exact h
|
||||
|
||||
/-- The inclusion of the indices of `l2` into the indices of `l ++ l2`. -/
|
||||
def appendInr : Fin l2.length ↪ Fin (l ++ l2).length where
|
||||
toFun := appendEquiv ∘ Sum.inr
|
||||
inj' := by
|
||||
intro i j h
|
||||
simp [Function.comp] at h
|
||||
exact h
|
||||
|
||||
@[simp]
|
||||
lemma appendInl_appendEquiv :
|
||||
(l.appendInl l2).trans appendEquiv.symm.toEmbedding =
|
||||
{toFun := Sum.inl, inj' := Sum.inl_injective} := by
|
||||
ext i
|
||||
simp [appendInl]
|
||||
|
||||
@[simp]
|
||||
lemma appendInr_appendEquiv :
|
||||
(l.appendInr l2).trans appendEquiv.symm.toEmbedding =
|
||||
{toFun := Sum.inr, inj' := Sum.inr_injective} := by
|
||||
ext i
|
||||
simp [appendInr]
|
||||
|
||||
@[simp]
|
||||
lemma append_val {l l2 : IndexList X} : (l ++ l2).val = l.val ++ l2.val := by
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma idMap_append_inl {l l2 : IndexList X} (i : Fin l.length) :
|
||||
(l ++ l2).idMap (appendEquiv (Sum.inl i)) = l.idMap i := by
|
||||
simp [appendEquiv, idMap]
|
||||
rw [List.getElem_append_left]
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma idMap_append_inr {l l2 : IndexList X} (i : Fin l2.length) :
|
||||
(l ++ l2).idMap (appendEquiv (Sum.inr i)) = l2.idMap i := by
|
||||
simp [appendEquiv, idMap, IndexList.length]
|
||||
rw [List.getElem_append_right]
|
||||
· simp only [Nat.add_sub_cancel_left]
|
||||
· omega
|
||||
· omega
|
||||
|
||||
@[simp]
|
||||
lemma colorMap_append_inl {l l2 : IndexList X} (i : Fin l.length) :
|
||||
(l ++ l2).colorMap (appendEquiv (Sum.inl i)) = l.colorMap i := by
|
||||
simp [appendEquiv, colorMap, IndexList.length]
|
||||
rw [List.getElem_append_left]
|
||||
|
||||
@[simp]
|
||||
lemma colorMap_append_inl' :
|
||||
(l ++ l2).colorMap ∘ appendEquiv ∘ Sum.inl = l.colorMap := by
|
||||
funext i
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
lemma colorMap_append_inr {l l2 : IndexList X} (i : Fin l2.length) :
|
||||
(l ++ l2).colorMap (appendEquiv (Sum.inr i)) = l2.colorMap i := by
|
||||
simp [appendEquiv, colorMap, IndexList.length]
|
||||
rw [List.getElem_append_right]
|
||||
· simp only [Nat.add_sub_cancel_left]
|
||||
· omega
|
||||
· omega
|
||||
|
||||
@[simp]
|
||||
lemma colorMap_append_inr' :
|
||||
(l ++ l2).colorMap ∘ appendEquiv ∘ Sum.inr = l2.colorMap := by
|
||||
funext i
|
||||
simp
|
||||
|
||||
lemma colorMap_sumELim (l1 l2 : IndexList X) :
|
||||
Sum.elim l1.colorMap l2.colorMap =
|
||||
(l1 ++ l2).colorMap ∘ appendEquiv := by
|
||||
funext x
|
||||
match x with
|
||||
| Sum.inl i => simp
|
||||
| Sum.inr i => simp
|
||||
|
||||
end append
|
||||
|
||||
/-!
|
||||
|
||||
## countId
|
||||
|
||||
-/
|
||||
|
||||
/-- The number of times the id of an index `I` appears in a list of indices `l`. -/
|
||||
def countId (I : Index X) : ℕ :=
|
||||
l.val.countP (fun J => I.id = J.id)
|
||||
|
||||
@[simp]
|
||||
lemma countId_append (I : Index X) : (l ++ l2).countId I = l.countId I + l2.countId I := by
|
||||
simp [countId]
|
||||
|
||||
lemma countId_eq_length_filter (I : Index X) :
|
||||
l.countId I = (l.val.filter (fun J => I.id = J.id)).length := by
|
||||
simp [countId]
|
||||
rw [List.countP_eq_length_filter]
|
||||
|
||||
lemma countId_index_neq_zero (i : Fin l.length) : l.countId (l.val.get i) ≠ 0 := by
|
||||
rw [countId_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
|
||||
|
||||
lemma countId_append_symm (I : Index X) : (l ++ l2).countId I = (l2 ++ l).countId I := by
|
||||
simp only [countId_append]
|
||||
omega
|
||||
|
||||
lemma countId_eq_one_append_mem_right_self_eq_one {I : Index X} (hI : I ∈ l2.val)
|
||||
(h : (l ++ l2).countId I = 1) : l2.countId I = 1 := by
|
||||
simp at h
|
||||
have hmem : I ∈ l2.val.filter (fun J => I.id = J.id) := by
|
||||
simp [List.mem_filter, decide_True, and_true, hI]
|
||||
have h1 : l2.countId I ≠ 0 := by
|
||||
rw [countId_eq_length_filter]
|
||||
by_contra hn
|
||||
rw [@List.length_eq_zero] at hn
|
||||
rw [hn] at hmem
|
||||
simp at hmem
|
||||
omega
|
||||
|
||||
lemma countId_eq_one_append_mem_right_other_eq_zero {I : Index X} (hI : I ∈ l2.val)
|
||||
(h : (l ++ l2).countId I = 1) : l.countId I = 0 := by
|
||||
simp at h
|
||||
have hmem : I ∈ l2.val.filter (fun J => I.id = J.id) := by
|
||||
simp [List.mem_filter, decide_True, and_true, hI]
|
||||
have h1 : l2.countId I ≠ 0 := by
|
||||
rw [countId_eq_length_filter]
|
||||
by_contra hn
|
||||
rw [@List.length_eq_zero] at hn
|
||||
rw [hn] at hmem
|
||||
simp at hmem
|
||||
omega
|
||||
|
||||
@[simp]
|
||||
lemma countId_cons_eq_two {I : Index X} :
|
||||
(l.cons I).countId I = 2 ↔ l.countId I = 1 := by
|
||||
simp [countId]
|
||||
|
||||
lemma countId_congr {I J : Index X} (h : I.id = J.id) : l.countId I = l.countId J := by
|
||||
simp [countId, h]
|
||||
|
||||
lemma countId_neq_zero_mem (I : Index X) (h : l.countId I ≠ 0) :
|
||||
∃ I', I' ∈ l.val ∧ I.id = I'.id := by
|
||||
rw [countId_eq_length_filter] at h
|
||||
have h' := List.isEmpty_iff_length_eq_zero.mp.mt h
|
||||
simp only at h'
|
||||
have h'' := eq_false_of_ne_true h'
|
||||
rw [List.isEmpty_false_iff_exists_mem] at h''
|
||||
obtain ⟨I', hI'⟩ := h''
|
||||
simp only [List.mem_filter, decide_eq_true_eq] at hI'
|
||||
exact ⟨I', hI'⟩
|
||||
|
||||
lemma countId_mem (I : Index X) (hI : I ∈ l.val) : l.countId I ≠ 0 := by
|
||||
rw [countId_eq_length_filter]
|
||||
by_contra hn
|
||||
rw [List.length_eq_zero] at hn
|
||||
have hIme : I ∈ List.filter (fun J => decide (I.id = J.id)) l.val := by
|
||||
simp [hI]
|
||||
rw [hn] at hIme
|
||||
simp at hIme
|
||||
|
||||
/-!
|
||||
|
||||
## Filter id
|
||||
|
||||
-/
|
||||
/-! 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
|
||||
/-- The index associated with a `IndexRep`. -/
|
||||
def toIndex (s : IndexRep X) : Index X := (s.toColor, s.id)
|
||||
|
||||
end IndexRep
|
||||
end IndexNotation
|
||||
|
|
|
@ -1,589 +0,0 @@
|
|||
/-
|
||||
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.OnlyUniqueDuals
|
||||
import HepLean.SpaceTime.LorentzTensor.Basic
|
||||
import Init.Data.List.Lemmas
|
||||
/-!
|
||||
|
||||
# Index lists and color
|
||||
|
||||
In this file we look at the interaction of index lists and color.
|
||||
|
||||
The main definition of this file is `ColorCond`.
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {𝓒 : TensorColor}
|
||||
variable [IndexNotation 𝓒.Color] [Fintype 𝓒.Color] [DecidableEq 𝓒.Color]
|
||||
variable (l l2 l3 : IndexList 𝓒.Color)
|
||||
|
||||
/-- The condition an index and its' dual, when it exists, have dual colors. -/
|
||||
def ColorCond : Prop := Option.map l.colorMap ∘
|
||||
l.getDual? = Option.map (𝓒.τ ∘ l.colorMap) ∘
|
||||
Option.guard fun i => (l.getDual? i).isSome
|
||||
|
||||
namespace ColorCond
|
||||
|
||||
variable {l l2 l3 : IndexList 𝓒.Color}
|
||||
|
||||
lemma iff_withDual :
|
||||
l.ColorCond ↔ ∀ (i : l.withDual), 𝓒.τ
|
||||
(l.colorMap ((l.getDual? i).get (l.withDual_isSome i))) = l.colorMap i := by
|
||||
refine Iff.intro (fun h i => ?_) (fun h => ?_)
|
||||
· have h' := congrFun h i
|
||||
simp at h'
|
||||
rw [show l.getDual? i = some ((l.getDual? i).get (l.withDual_isSome i)) by simp] at h'
|
||||
have h'' : (Option.guard (fun i => (l.getDual? i).isSome = true) ↑i) = i := by
|
||||
apply Option.guard_eq_some.mpr
|
||||
simp [l.withDual_isSome i]
|
||||
rw [h'', Option.map_some', Option.map_some'] at h'
|
||||
simp at h'
|
||||
rw [h']
|
||||
exact 𝓒.τ_involutive (l.colorMap i)
|
||||
· funext i
|
||||
by_cases hi : (l.getDual? i).isSome
|
||||
· have h'' : (Option.guard (fun i => (l.getDual? i).isSome = true) ↑i) = i := by
|
||||
apply Option.guard_eq_some.mpr
|
||||
simp only [true_and]
|
||||
exact hi
|
||||
simp only [Function.comp_apply, h'', Option.map_some']
|
||||
rw [show l.getDual? ↑i = some ((l.getDual? i).get hi) by simp]
|
||||
rw [Option.map_some']
|
||||
simp only [Option.some.injEq]
|
||||
have hii := h ⟨i, by simp [withDual, hi]⟩
|
||||
simp at hii
|
||||
rw [← hii]
|
||||
exact (𝓒.τ_involutive _).symm
|
||||
· simp [Option.guard, hi]
|
||||
exact Option.not_isSome_iff_eq_none.mp hi
|
||||
|
||||
lemma iff_on_isSome : l.ColorCond ↔ ∀ (i : Fin l.length) (h : (l.getDual? i).isSome), 𝓒.τ
|
||||
(l.colorMap ((l.getDual? i).get h)) = l.colorMap i := by
|
||||
rw [iff_withDual]
|
||||
simp only [Subtype.forall, mem_withDual_iff_isSome]
|
||||
|
||||
lemma color_quot_filter_of_countP_two (hl : l.withUniqueDual = l.withDual) (i : Fin l.length)
|
||||
(hi : (l.getDual? i).isSome) :
|
||||
(l.val.filter (fun J => (l.val.get i).id = J.id)).countP
|
||||
(fun J => (l.val.get i).toColor = J.toColor ∨ (l.val.get i).toColor = 𝓒.τ (J.toColor)) =
|
||||
(l.val.filter (fun J => (l.val.get i).id = J.id)).length ↔
|
||||
(l.colorMap i = l.colorMap ((l.getDual? i).get hi) ∨
|
||||
l.colorMap i = 𝓒.τ (l.colorMap ((l.getDual? i).get hi))) := by
|
||||
have hi1 := hi
|
||||
rw [← mem_withDual_iff_isSome, ← hl, mem_withUniqueDual_iff_countId_eq_two] at hi1
|
||||
rcases l.filter_id_of_countId_eq_two hi1 with hf | hf
|
||||
all_goals
|
||||
erw [hf]
|
||||
simp [List.countP, List.countP.go]
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· by_contra hn
|
||||
have hn' : (decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor) ||
|
||||
decide (l.val[↑i].toColor = 𝓒.τ l.val[↑((l.getDual? i).get hi)].toColor)) = false := by
|
||||
simpa using hn
|
||||
erw [hn'] at h
|
||||
simp at h
|
||||
· have hn' : (decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor) ||
|
||||
decide (l.val[↑i].toColor = 𝓒.τ l.val[↑((l.getDual? i).get hi)].toColor)) = true := by
|
||||
simpa using h
|
||||
erw [hn']
|
||||
simp
|
||||
|
||||
lemma color_dual_eq_self_filter_of_countP_two (hl : l.withUniqueDual = l.withDual)
|
||||
(i : Fin l.length) (hi : (l.getDual? i).isSome) :
|
||||
(l.val.filter (fun J => (l.val.get i).id = J.id)).countP
|
||||
(fun J => (l.val.get i).toColor = J.toColor) =
|
||||
(l.val.filter (fun J => (l.val.get i).id = J.id)).countP
|
||||
(fun J => (l.val.get i).toColor = 𝓒.τ (J.toColor))
|
||||
↔ l.colorMap i = 𝓒.τ (l.colorMap ((l.getDual? i).get hi))
|
||||
∨ (l.colorMap i) = 𝓒.τ (l.colorMap i) := by
|
||||
have hi1 := hi
|
||||
rw [← mem_withDual_iff_isSome, ← hl, mem_withUniqueDual_iff_countId_eq_two] at hi1
|
||||
rcases l.filter_id_of_countId_eq_two hi1 with hf | hf
|
||||
all_goals
|
||||
erw [hf]
|
||||
simp [List.countP, List.countP.go]
|
||||
by_cases hn : l.colorMap i = 𝓒.τ (l.colorMap ((l.getDual? i).get hi))
|
||||
· simp [hn]
|
||||
have hn' : decide (l.val[↑i].toColor = 𝓒.τ l.val[↑((l.getDual? i).get hi)].toColor)
|
||||
= true := by simpa [colorMap] using hn
|
||||
erw [hn']
|
||||
simp only [cond_true]
|
||||
have hτ : l.colorMap ((l.getDual? i).get hi) = 𝓒.τ (l.colorMap i) := by
|
||||
rw [hn]
|
||||
exact (𝓒.τ_involutive _).symm
|
||||
simp [colorMap] at hτ
|
||||
erw [hτ]
|
||||
· have hn' : decide (l.val[↑i].toColor = 𝓒.τ l.val[↑((l.getDual? i).get hi)].toColor) =
|
||||
false := by simpa [colorMap] using hn
|
||||
erw [hn']
|
||||
simp [hn]
|
||||
by_cases hm : l.colorMap i = 𝓒.τ (l.colorMap i)
|
||||
· trans True
|
||||
· simp
|
||||
have hm' : decide (l.val[↑i].toColor = 𝓒.τ l.val[↑i].toColor) = true := by simpa using hm
|
||||
erw [hm']
|
||||
simp only [cond_true]
|
||||
have hm'' : decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor)
|
||||
= false := by
|
||||
simp only [Fin.getElem_fin, decide_eq_false_iff_not]
|
||||
simp [colorMap] at hm
|
||||
erw [hm]
|
||||
by_contra hn'
|
||||
have hn'' : l.colorMap i = 𝓒.τ (l.colorMap ((l.getDual? i).get hi)) := by
|
||||
simp [colorMap]
|
||||
rw [← hn']
|
||||
exact (𝓒.τ_involutive _).symm
|
||||
exact hn hn''
|
||||
erw [hm'']
|
||||
simp
|
||||
· exact true_iff_iff.mpr hm
|
||||
· simp [hm]
|
||||
simp [colorMap] at hm
|
||||
have hm' : decide (l.val[↑i].toColor = 𝓒.τ l.val[↑i].toColor) = false := by simpa using hm
|
||||
erw [hm']
|
||||
simp only [cond_false, ne_eq]
|
||||
by_cases hm'' : decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor) = true
|
||||
· erw [hm'']
|
||||
simp
|
||||
· have hm''' : decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor)
|
||||
= false := by
|
||||
simpa using hm''
|
||||
erw [hm''']
|
||||
simp
|
||||
|
||||
/-- A condition on an index list `l` and and index `I`. If the id of `I` appears
|
||||
twice in `l` (and `I` at least once) then this condition is equivalent to the dual of `I` having
|
||||
dual color to `I`, but written totally in terms of lists. -/
|
||||
abbrev countColorCond (l : IndexList 𝓒.Color) (I : Index 𝓒.Color) : Prop :=
|
||||
(l.val.filter (fun J => I.id = J.id)).countP
|
||||
(fun J => I.toColor = J.toColor ∨ I.toColor = 𝓒.τ (J.toColor)) =
|
||||
(l.val.filter (fun J => I.id = J.id)).length ∧
|
||||
(l.val.filter (fun J => I.id = J.id)).countP (fun J => I.toColor = J.toColor) =
|
||||
(l.val.filter (fun J => I.id = J.id)).countP (fun J => I.toColor = 𝓒.τ (J.toColor))
|
||||
|
||||
lemma countColorCond_cons_neg (l : IndexList 𝓒.Color) (I I' : Index 𝓒.Color) (hid : I.id ≠ I'.id) :
|
||||
countColorCond (l.cons I) I' ↔ countColorCond l I' := by
|
||||
have h1 : (l.cons I).val.filter (fun J => I'.id = J.id) =
|
||||
l.val.filter (fun J => I'.id = J.id) := by
|
||||
simp only [cons]
|
||||
rw [List.filter_cons_of_neg]
|
||||
simp only [decide_eq_true_eq]
|
||||
exact id (Ne.symm hid)
|
||||
rw [countColorCond, countColorCond, h1]
|
||||
|
||||
lemma countColorCond_of_filter_eq (l l2 : IndexList 𝓒.Color) {I : Index 𝓒.Color}
|
||||
(hf : l.val.filter (fun J => I.id = J.id) = l2.val.filter (fun J => I.id = J.id))
|
||||
(h1 : countColorCond l I) : countColorCond l2 I := by
|
||||
rw [countColorCond, ← hf]
|
||||
exact h1
|
||||
|
||||
lemma color_eq_of_countColorCond_cons_pos (l : IndexList 𝓒.Color) (I I' : Index 𝓒.Color)
|
||||
(hl : countColorCond (l.cons I) I') (hI : I.id = I'.id) : I.toColor = I'.toColor ∨
|
||||
I.toColor = 𝓒.τ I'.toColor := by
|
||||
have hl1 := hl.1
|
||||
rw [List.countP_eq_length] at hl1
|
||||
have h2 := hl1 I (by simp; exact hI.symm)
|
||||
simp at h2
|
||||
rcases h2 with h2 | h2
|
||||
· simp [h2]
|
||||
· rw [h2]
|
||||
apply Or.inr (𝓒.τ_involutive _).symm
|
||||
|
||||
lemma iff_countColorCond_isSome (hl : l.withUniqueDual = l.withDual) :
|
||||
l.ColorCond ↔
|
||||
∀ (i : Fin l.length) (_ : (l.getDual? i).isSome), countColorCond l (l.val.get i) := by
|
||||
rw [iff_on_isSome]
|
||||
simp only [countColorCond]
|
||||
refine Iff.intro (fun h i hi => ?_) (fun h i hi => ?_)
|
||||
· rw [color_quot_filter_of_countP_two hl i hi, color_dual_eq_self_filter_of_countP_two hl i hi]
|
||||
have hi' := h i hi
|
||||
exact And.intro (Or.inr hi'.symm) (Or.inl hi'.symm)
|
||||
· have hi' := h i hi
|
||||
rw [color_quot_filter_of_countP_two hl i hi,
|
||||
color_dual_eq_self_filter_of_countP_two hl i hi] at hi'
|
||||
rcases hi'.1 with hi1 | hi1
|
||||
<;> rcases hi'.2 with hi2 | hi2
|
||||
· exact hi2.symm
|
||||
· rw [← hi1]
|
||||
exact hi2.symm
|
||||
· exact hi1.symm
|
||||
· exact hi1.symm
|
||||
|
||||
lemma iff_countColorCond (hl : l.withUniqueDual = l.withDual) :
|
||||
l.ColorCond ↔ ∀ (i : Fin l.length), l.countId (l.val.get i) = 2
|
||||
→ countColorCond l (l.val.get i) := by
|
||||
rw [iff_countColorCond_isSome hl]
|
||||
refine Iff.intro (fun h i hi => ?_) (fun h i hi => ?_)
|
||||
· rw [← mem_withUniqueDual_iff_countId_eq_two] at hi
|
||||
exact h i (mem_withUniqueDual_isSome l i hi)
|
||||
· rw [← mem_withDual_iff_isSome, ← hl, mem_withUniqueDual_iff_countId_eq_two] at hi
|
||||
exact h i hi
|
||||
|
||||
lemma iff_countColorCond_mem (hl : l.withUniqueDual = l.withDual) :
|
||||
l.ColorCond ↔ ∀ (I : Index 𝓒.Color) (_ : I ∈ l.val),
|
||||
l.countId I = 2 → countColorCond l I := by
|
||||
rw [iff_countColorCond hl]
|
||||
refine Iff.intro (fun h I hI hi => ?_) (fun h i hi => ?_)
|
||||
· 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] at hi ⊢
|
||||
exact h ⟨i, hi'⟩ hi
|
||||
· exact h (l.val.get i) (List.getElem_mem l.val (↑i) i.isLt) hi
|
||||
|
||||
/-- The lemma `ColorCond` written totally in terms of lists. -/
|
||||
lemma iff_countColorCond_all (hl : l.withUniqueDual = l.withDual) :
|
||||
l.ColorCond ↔ l.val.all (fun I =>
|
||||
(l.countId I = 2 → countColorCond l I)) := by
|
||||
rw [iff_countColorCond_mem hl]
|
||||
simp only [List.all_eq_true, decide_eq_true_eq]
|
||||
|
||||
@[simp]
|
||||
lemma consDual_color {I : Index 𝓒.Color} (hI : l.countId I = 1)
|
||||
(hI2 : (l.countId I =
|
||||
l.val.countP (fun J => I.id = J.id ∧ I.toColor = 𝓒.τ (J.toColor)))) :
|
||||
(l.consDual hI).toColor = 𝓒.τ I.toColor := by
|
||||
have h1 : l.val.countP (fun J => I.id = J.id ∧ I.toColor = 𝓒.τ (J.toColor))
|
||||
= (l.val.filter (fun J => I.id = J.id)).countP (fun J => I.toColor = 𝓒.τ (J.toColor)) := by
|
||||
rw [List.countP_filter]
|
||||
apply congrFun
|
||||
apply congrArg
|
||||
funext J
|
||||
simp only [Bool.decide_and, decide_eq_true_eq]
|
||||
exact Bool.and_comm (decide (I.id = J.id)) (decide (I.toColor = 𝓒.τ J.toColor))
|
||||
rw [h1, countId, List.countP_eq_length_filter, l.consDual_filter hI] at hI2
|
||||
symm at hI2
|
||||
rw [List.countP_eq_length] at hI2
|
||||
simp only [List.mem_singleton, decide_eq_true_eq, forall_eq] at hI2
|
||||
rw [hI2, 𝓒.τ_involutive]
|
||||
|
||||
lemma of_cons (I : Index 𝓒.Color) (h : (l.cons I).ColorCond)
|
||||
(hl : (l.cons I).withUniqueDual = (l.cons I).withDual) : l.ColorCond := by
|
||||
rw [iff_countColorCond_mem hl] at h
|
||||
have hl' : l.withUniqueDual = l.withDual := withUniqueDual_eq_withDual_of_cons l hl
|
||||
rw [iff_countColorCond_mem hl']
|
||||
intro I' hI'mem hi
|
||||
have hI''mem : I' ∈ (l.cons I).val := by
|
||||
simp [hI'mem]
|
||||
have hI'' := h I' hI''mem
|
||||
by_cases hI'id : I'.id ≠ I.id
|
||||
· rw [countId_eq_length_filter, cons_val, List.filter_cons_of_neg,
|
||||
countColorCond_cons_neg] at hI''
|
||||
· rw [countId_eq_length_filter] at hi
|
||||
exact hI'' hi
|
||||
· exact id (Ne.symm hI'id)
|
||||
· simpa using hI'id
|
||||
· simp at hI'id
|
||||
rw [countId_eq_length_filter, hI'id] at hi
|
||||
rw [propext (withUniqueDual_eq_withDual_cons_iff l I hl'), countId_eq_length_filter, hi] at hl
|
||||
simp at hl
|
||||
|
||||
lemma countId_of_cons (I : Index 𝓒.Color) (h : (l.cons I).ColorCond)
|
||||
(hl : (l.cons I).withUniqueDual = (l.cons I).withDual) :
|
||||
l.countId I =
|
||||
l.val.countP (fun J => I.id = J.id ∧ I.toColor = 𝓒.τ (J.toColor)) := by
|
||||
have h1 := (l.withUniqueDual_eq_withDual_cons_iff I
|
||||
(l.withUniqueDual_eq_withDual_of_cons hl)).mp hl
|
||||
rw [List.countP_eq_length_filter]
|
||||
trans (l.val.filter (fun J => I.id = J.id)).countP (fun J => I.toColor = 𝓒.τ (J.toColor))
|
||||
· by_cases hc : l.countId I = 1
|
||||
· rw [l.consDual_filter hc]
|
||||
simp [List.countP, List.countP.go]
|
||||
rw [iff_withDual] at h
|
||||
have h' := h ⟨⟨0, by simp⟩, (by
|
||||
rw [mem_withDual_iff_countId_gt_one]
|
||||
simp_all [countId])⟩
|
||||
change 𝓒.τ (l.consDual hc).toColor = _ at h'
|
||||
rw [h']
|
||||
simpa [colorMap] using hc
|
||||
· have hc' : l.countId I = 0 := by
|
||||
omega
|
||||
rw [countId_eq_length_filter, List.length_eq_zero] at hc'
|
||||
simp [hc']
|
||||
omega
|
||||
· rw [List.countP_filter]
|
||||
simp only [decide_eq_true_eq, Bool.decide_and]
|
||||
rw [← List.countP_eq_length_filter]
|
||||
apply congrFun
|
||||
apply congrArg
|
||||
funext J
|
||||
exact Bool.and_comm (decide (I.toColor = 𝓒.τ J.toColor)) (decide (I.id = J.id))
|
||||
|
||||
lemma cons_of_countP (h : l.ColorCond) (I : Index 𝓒.Color) (hl : l.withUniqueDual = l.withDual)
|
||||
(hI1 : l.countId I ≤ 1)
|
||||
(hI2 : l.countId I =
|
||||
l.val.countP (fun J => I.id = J.id ∧ I.toColor = 𝓒.τ (J.toColor))) :
|
||||
(l.cons I).ColorCond := by
|
||||
rw [iff_countColorCond_mem]
|
||||
· intro I' hI'
|
||||
by_cases hI'' : I' ≠ I
|
||||
· have hI'mem : I' ∈ l.val := by
|
||||
simp only [cons, List.mem_cons] at hI'
|
||||
rcases hI' with hI' | hI'
|
||||
· exact False.elim (hI'' hI')
|
||||
· exact hI'
|
||||
by_cases hI'id : I'.id ≠ I.id
|
||||
· rw [countId_eq_length_filter, cons_val, List.filter_cons_of_neg]
|
||||
· rw [iff_countColorCond_mem] at h
|
||||
rw [countColorCond_cons_neg l I I' hI'id.symm]
|
||||
· rw [← countId_eq_length_filter]
|
||||
exact h I' hI'mem
|
||||
· exact hl
|
||||
· simpa using hI'id
|
||||
· simp at hI'id
|
||||
intro hI
|
||||
rw [countId_eq_length_filter, hI'id] at hI
|
||||
simp at hI
|
||||
rw [← List.countP_eq_length_filter] at hI
|
||||
have hI'dual : I' = l.consDual hI := by
|
||||
simp [consDual_iff, hI'id, hI'mem]
|
||||
subst hI'dual
|
||||
rw [countColorCond, l.filter_of_constDual hI]
|
||||
simp only [List.countP, List.countP.go, Bool.decide_or, true_or, decide_True, zero_add,
|
||||
Nat.reduceAdd, cond_true, List.length_cons, List.length_singleton]
|
||||
rw [consDual_color hI hI2, 𝓒.τ_involutive]
|
||||
simp
|
||||
· simp only [ne_eq, Decidable.not_not] at hI''
|
||||
symm at hI''
|
||||
subst hI''
|
||||
intro hIf
|
||||
rw [countId_cons_eq_two] at hIf
|
||||
rw [countColorCond]
|
||||
simp only [Bool.decide_or, cons_val, decide_True, List.filter_cons_of_pos, Bool.true_or,
|
||||
List.countP_cons_of_pos, List.length_cons, add_left_inj]
|
||||
rw [l.consDual_filter hIf]
|
||||
simp only [List.countP, List.countP.go, zero_add, List.length_singleton, Nat.reduceAdd]
|
||||
rw [consDual_color hIf hI2, 𝓒.τ_involutive]
|
||||
simp only [decide_True, Bool.or_true, cond_true, true_and]
|
||||
by_cases h1 : (I.toColor = 𝓒.τ I.toColor)
|
||||
· have h1' : decide (I.toColor = 𝓒.τ I.toColor) = true := by simpa using h1
|
||||
simp [h1']
|
||||
· have h1' : decide (I.toColor = 𝓒.τ I.toColor) = false := by simpa using h1
|
||||
simp [h1']
|
||||
· exact (withUniqueDual_eq_withDual_cons_iff l I hl).mpr hI1
|
||||
|
||||
lemma cons_iff (I : Index 𝓒.Color) :
|
||||
(l.cons I).withUniqueDual = (l.cons I).withDual ∧
|
||||
(l.cons I).ColorCond ↔
|
||||
l.withUniqueDual = l.withDual ∧ l.ColorCond ∧
|
||||
l.countId I ≤ 1 ∧
|
||||
(l.countId I =
|
||||
l.val.countP (fun J => I.id = J.id ∧ I.toColor = 𝓒.τ (J.toColor))) := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· apply And.intro
|
||||
· exact l.withUniqueDual_eq_withDual_of_cons h.1
|
||||
· apply And.intro
|
||||
· exact of_cons I h.2 h.1
|
||||
· apply And.intro
|
||||
· exact (l.withUniqueDual_eq_withDual_cons_iff I
|
||||
(l.withUniqueDual_eq_withDual_of_cons h.1)).mp h.1
|
||||
· exact countId_of_cons I h.2 h.1
|
||||
· apply And.intro
|
||||
· rw [withUniqueDual_eq_withDual_cons_iff]
|
||||
· exact h.2.2.1
|
||||
· exact h.1
|
||||
· exact cons_of_countP h.2.1 I h.1 h.2.2.1 h.2.2.2
|
||||
|
||||
lemma assoc (h : ColorCond (l ++ l2 ++ l3)) : ColorCond (l ++ (l2 ++ l3)) := by
|
||||
rw [← append_assoc]
|
||||
exact h
|
||||
|
||||
lemma inl (h : ColorCond (l ++ l2)) : ColorCond l := by
|
||||
rw [iff_withDual] at h ⊢
|
||||
intro i
|
||||
simpa only [withDual_isSome, getDual?_append_inl_of_getDual?_isSome, Option.get_some,
|
||||
colorMap_append_inl] using h ⟨appendEquiv (Sum.inl i), by simp only [mem_withDual_iff_isSome,
|
||||
withDual_isSome, getDual?_append_inl_of_getDual?_isSome, Option.isSome_some]⟩
|
||||
|
||||
lemma symm (hu : (l ++ l2).withUniqueDual = (l ++ l2).withDual) (h : ColorCond (l ++ l2)) :
|
||||
ColorCond (l2 ++ l) := by
|
||||
rw [iff_on_isSome] at h ⊢
|
||||
intro j hj
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
rw [append_withDual_eq_withUniqueDual_symm] at hu
|
||||
rw [← mem_withDual_iff_isSome, ← hu] at hj
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
have hn := l2.append_inl_not_mem_withDual_of_withDualInOther l k hj
|
||||
by_cases hk' : (l2.getDual? k).isSome
|
||||
· simp_all only [mem_withDual_iff_isSome, getDual?_append_inl_of_getDual?_isSome,
|
||||
Option.isSome_some, mem_withInDualOther_iff_isSome, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, true_iff, Option.get_some, colorMap_append_inl]
|
||||
have hk'' := h (appendEquiv (Sum.inr k))
|
||||
simp only [getDual?_isSome_append_inr_iff, colorMap_append_inr] at hk''
|
||||
simp_all only [getDual?_append_inl_of_getDual?_isSome, Option.isSome_some, Option.isSome_none,
|
||||
Bool.false_eq_true, or_false, Option.isNone_none,
|
||||
getDual?_inr_getDualInOther?_isNone_getDual?_isSome, Option.get_some, colorMap_append_inr,
|
||||
true_implies]
|
||||
· simp_all only [mem_withDual_iff_isSome, Bool.false_eq_true, mem_withInDualOther_iff_isSome,
|
||||
Bool.not_eq_true, Option.not_isSome, Option.isNone_iff_eq_none, false_iff, Option.isNone_none,
|
||||
colorMap_append_inl]
|
||||
have hn' : (l2.getDualInOther? l k).isSome := by
|
||||
simp_all only [Option.isNone_none, getDual?_isSome_append_inl_iff, Option.isSome_none,
|
||||
Bool.false_eq_true, false_or]
|
||||
have hk'' := h (appendEquiv (Sum.inr k))
|
||||
simp only [getDual?_isSome_append_inr_iff, colorMap_append_inr] at hk''
|
||||
simp_all only [Option.isSome_none, Bool.false_eq_true, or_true,
|
||||
getDual?_append_inr_getDualInOther?_isSome, Option.get_some, colorMap_append_inl,
|
||||
true_implies, Option.isNone_none, getDual?_inl_of_getDual?_isNone_getDualInOther?_isSome,
|
||||
colorMap_append_inr]
|
||||
| Sum.inr k =>
|
||||
have hn := l2.append_inr_not_mem_withDual_of_withDualInOther l k hj
|
||||
by_cases hk' : (l.getDual? k).isSome
|
||||
· simp_all only [mem_withDual_iff_isSome, mem_withInDualOther_iff_isSome, Bool.not_eq_true,
|
||||
Option.not_isSome, Option.isNone_iff_eq_none, true_iff, Option.isNone_none,
|
||||
getDual?_inr_getDualInOther?_isNone_getDual?_isSome, Option.get_some, colorMap_append_inr]
|
||||
have hk'' := h (appendEquiv (Sum.inl k))
|
||||
simp only [getDual?_isSome_append_inl_iff, colorMap_append_inl] at hk''
|
||||
simp_all only [Option.isNone_none, getDual?_inr_getDualInOther?_isNone_getDual?_isSome,
|
||||
Option.isSome_some, Option.isSome_none, Bool.false_eq_true, or_false,
|
||||
getDual?_append_inl_of_getDual?_isSome, Option.get_some, colorMap_append_inl, true_implies]
|
||||
· simp_all only [mem_withDual_iff_isSome, Bool.false_eq_true, mem_withInDualOther_iff_isSome,
|
||||
Bool.not_eq_true, Option.not_isSome, Option.isNone_iff_eq_none, false_iff,
|
||||
colorMap_append_inr]
|
||||
have hn' : (l.getDualInOther? l2 k).isSome := by
|
||||
exact Option.ne_none_iff_isSome.mp hn
|
||||
have hk'' := h (appendEquiv (Sum.inl k))
|
||||
simp only [getDual?_isSome_append_inl_iff, colorMap_append_inl] at hk''
|
||||
simp_all only [Option.isSome_none, Bool.false_eq_true, or_true, Option.isNone_none,
|
||||
getDual?_inl_of_getDual?_isNone_getDualInOther?_isSome, Option.get_some,
|
||||
colorMap_append_inr, true_implies, getDual?_append_inr_getDualInOther?_isSome,
|
||||
colorMap_append_inl]
|
||||
|
||||
lemma inr (hu : (l ++ l2).withUniqueDual = (l ++ l2).withDual) (h : ColorCond (l ++ l2)) :
|
||||
ColorCond l2 := inl (symm hu h)
|
||||
|
||||
lemma triple_right (hu : (l ++ l2 ++ l3).withUniqueDual = (l ++ l2 ++ l3).withDual)
|
||||
(h : ColorCond (l ++ l2 ++ l3)) : ColorCond (l2 ++ l3) := by
|
||||
have h1 := assoc h
|
||||
rw [append_assoc] at hu
|
||||
exact h1.inr hu
|
||||
|
||||
lemma triple_drop_mid (hu : (l ++ l2 ++ l3).withUniqueDual = (l ++ l2 ++ l3).withDual)
|
||||
(h : ColorCond (l ++ l2 ++ l3)) : ColorCond (l ++ l3) := by
|
||||
rw [append_assoc] at hu
|
||||
refine (((assoc h).symm hu).assoc.inr ?_).symm ?_
|
||||
· rw [append_withDual_eq_withUniqueDual_symm, append_assoc] at hu
|
||||
exact hu
|
||||
· rw [append_withDual_eq_withUniqueDual_symm, append_assoc] at hu
|
||||
exact append_withDual_eq_withUniqueDual_inr _ _ hu
|
||||
|
||||
lemma swap (hu : (l ++ l2 ++ l3).withUniqueDual = (l ++ l2 ++ l3).withDual)
|
||||
(h : ColorCond (l ++ l2 ++ l3)) :
|
||||
ColorCond (l2 ++ l ++ l3) := by
|
||||
have hC := h
|
||||
have hu' := hu
|
||||
rw [iff_on_isSome] at h ⊢
|
||||
intro j hj
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
have hj' := hj
|
||||
rw [append_withDual_eq_withUniqueDual_swap] at hu
|
||||
rw [← mem_withDual_iff_isSome, ← hu] at hj'
|
||||
have hn := (l2 ++ l).append_inl_not_mem_withDual_of_withDualInOther l3 k hj'
|
||||
simp only [mem_withDual_iff_isSome, mem_withInDualOther_iff_isSome, Bool.not_eq_true,
|
||||
Option.not_isSome, Option.isNone_iff_eq_none] at hn
|
||||
simp only [getDual?_isSome_append_inl_iff] at hj
|
||||
by_cases hk' : ((l2 ++ l).getDual? k).isSome
|
||||
· simp only [hk', getDual?_append_inl_of_getDual?_isSome, Option.get_some, colorMap_append_inl]
|
||||
have hu' := append_withDual_eq_withUniqueDual_inl (l2 ++ l) l3 hu
|
||||
have hC' := hC.inl.symm ((append_withDual_eq_withUniqueDual_symm l2 l).mp hu')
|
||||
rw [iff_on_isSome] at hC'
|
||||
exact hC' k hk'
|
||||
· simp only [hk', Bool.false_eq_true, false_iff] at hn
|
||||
rw [← @Option.not_isSome_iff_eq_none, not_not] at hn
|
||||
simp_all only [mem_withDual_iff_isSome, Bool.false_eq_true, or_true, Bool.not_eq_true,
|
||||
Option.not_isSome, Option.isNone_iff_eq_none, Option.isNone_none,
|
||||
getDual?_inl_of_getDual?_isNone_getDualInOther?_isSome, Option.get_some,
|
||||
colorMap_append_inr, colorMap_append_inl]
|
||||
obtain ⟨k', hk'⟩ := appendEquiv.surjective k
|
||||
subst hk'
|
||||
match k' with
|
||||
| Sum.inl k' =>
|
||||
simp only [getDualInOther?_append_of_inl] at hn
|
||||
simp only [getDualInOther?_append_of_inl, colorMap_append_inl]
|
||||
have hL := triple_right hu' hC
|
||||
rw [iff_on_isSome] at hL
|
||||
have hL' := hL (appendEquiv (Sum.inl k')) (by simp only [getDual?_isSome_append_inl_iff, hn,
|
||||
or_true])
|
||||
simp_all only [Option.isNone_none, getDualInOther?_append_of_inl,
|
||||
getDual?_inl_of_getDual?_isNone_getDualInOther?_isSome, Option.isSome_some,
|
||||
getDual?_eq_none_append_inl_iff, Option.get_some, colorMap_append_inr,
|
||||
colorMap_append_inl]
|
||||
| Sum.inr k' =>
|
||||
simp only [getDualInOther?_append_of_inr] at hn
|
||||
simp only [getDualInOther?_append_of_inr, colorMap_append_inr]
|
||||
have hR := triple_drop_mid hu' hC
|
||||
rw [iff_on_isSome] at hR
|
||||
have hR' := hR (appendEquiv (Sum.inl k')) (by simp only [getDual?_isSome_append_inl_iff, hn,
|
||||
or_true])
|
||||
simp_all only [Option.isNone_none, getDualInOther?_append_of_inr,
|
||||
getDual?_inl_of_getDual?_isNone_getDualInOther?_isSome, Option.isSome_some,
|
||||
getDual?_eq_none_append_inr_iff, Option.get_some, colorMap_append_inr,
|
||||
colorMap_append_inl]
|
||||
| Sum.inr k =>
|
||||
have hj' := hj
|
||||
rw [append_withDual_eq_withUniqueDual_swap] at hu
|
||||
rw [← mem_withDual_iff_isSome, ← hu] at hj'
|
||||
have hn := (l2 ++ l).append_inr_not_mem_withDual_of_withDualInOther l3 k hj'
|
||||
simp only [mem_withDual_iff_isSome, mem_withInDualOther_iff_isSome,
|
||||
getDualInOther?_isSome_of_append_iff, not_or, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none] at hn
|
||||
by_cases hk' : (l3.getDual? k).isSome
|
||||
· simp_all only [mem_withDual_iff_isSome, true_iff, Option.isNone_iff_eq_none,
|
||||
getDualInOther?_eq_none_of_append_iff, and_self,
|
||||
getDual?_inr_getDualInOther?_isNone_getDual?_isSome, Option.get_some, colorMap_append_inr]
|
||||
have hRR := hC.inr hu'
|
||||
rw [iff_on_isSome] at hRR
|
||||
exact hRR k hk'
|
||||
· simp_all only [mem_withDual_iff_isSome, Bool.false_eq_true, false_iff, not_and,
|
||||
Bool.not_eq_true, Option.not_isSome, Option.isNone_iff_eq_none, colorMap_append_inr]
|
||||
by_cases hk'' : (l3.getDualInOther? l2 k).isSome
|
||||
· simp_all only [getDualInOther?_of_append_of_isSome, Option.isSome_some,
|
||||
getDual?_append_inr_getDualInOther?_isSome, Option.get_some, colorMap_append_inl]
|
||||
have hL := triple_right hu' hC
|
||||
rw [iff_on_isSome] at hL
|
||||
have hL' := hL (appendEquiv (Sum.inr k)) (by simp [hk''])
|
||||
simp_all only [getDualInOther?_of_append_of_isSome, Option.isSome_some,
|
||||
getDual?_append_inr_getDualInOther?_isSome, Option.get_some, colorMap_append_inl,
|
||||
colorMap_append_inr]
|
||||
· simp_all only [Bool.not_eq_true, Option.not_isSome, Option.isNone_iff_eq_none,
|
||||
true_implies]
|
||||
rw [← Option.not_isSome_iff_eq_none, not_not] at hn
|
||||
simp_all only [getDualInOther?_of_append_of_isNone_isSome, Option.isSome_some,
|
||||
getDual?_append_inr_getDualInOther?_isSome, Option.get_some, colorMap_append_inl,
|
||||
colorMap_append_inr]
|
||||
have hR := triple_drop_mid hu' hC
|
||||
rw [iff_on_isSome] at hR
|
||||
have hR' := hR (appendEquiv (Sum.inr k)) (by simp [hn])
|
||||
simp_all only [getDualInOther?_of_append_of_isNone_isSome, Option.isSome_some,
|
||||
getDual?_append_inr_getDualInOther?_isSome, Option.get_some, colorMap_append_inl,
|
||||
colorMap_append_inr]
|
||||
|
||||
/-- A bool which is true for an index list if and only if every index and its' dual, when it exists,
|
||||
have dual colors. -/
|
||||
def bool (l : IndexList 𝓒.Color) : Bool :=
|
||||
if (∀ (i : l.withDual), 𝓒.τ
|
||||
(l.colorMap ((l.getDual? i).get (l.withDual_isSome i))) = l.colorMap i) then
|
||||
true
|
||||
else false
|
||||
|
||||
lemma iff_bool : l.ColorCond ↔ bool l := by
|
||||
rw [iff_withDual, bool]
|
||||
simp only [Subtype.forall, mem_withDual_iff_isSome, Bool.if_false_right, Bool.and_true,
|
||||
decide_eq_true_eq]
|
||||
|
||||
end ColorCond
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -11,7 +11,9 @@ import Init.Data.List.Lemmas
|
|||
|
||||
# Appending two ColorIndexLists
|
||||
|
||||
We define the contraction of ColorIndexLists.
|
||||
We define conditional appending of `ColorIndexList`'s.
|
||||
|
||||
It is conditional on `AppendCond` being true, which we define.
|
||||
|
||||
-/
|
||||
|
||||
|
@ -35,14 +37,13 @@ open IndexList TensorColor
|
|||
Note: `AppendCond` does not form an equivalence relation as it is not reflexive or
|
||||
transitive. -/
|
||||
def AppendCond : Prop :=
|
||||
(l.toIndexList ++ l2.toIndexList).withUniqueDual = (l.toIndexList ++ l2.toIndexList).withDual
|
||||
∧ ColorCond (l.toIndexList ++ l2.toIndexList)
|
||||
(l.toIndexList ++ l2.toIndexList).OnlyUniqueDuals ∧ ColorCond (l.toIndexList ++ l2.toIndexList)
|
||||
|
||||
/-- Given two `ColorIndexList`s satisfying `AppendCond`. The correponding combined
|
||||
`ColorIndexList`. -/
|
||||
def append (h : AppendCond l l2) : ColorIndexList 𝓒 where
|
||||
toIndexList := l.toIndexList ++ l2.toIndexList
|
||||
unique_duals := h.1.symm
|
||||
unique_duals := h.1
|
||||
dual_color := h.2
|
||||
|
||||
/-- The join of two `ColorIndexList` satisfying the condition `AppendCond` that they
|
||||
|
@ -51,8 +52,7 @@ scoped[IndexNotation.ColorIndexList] notation l " ++["h"] " l2 => append l l2 h
|
|||
|
||||
@[simp]
|
||||
lemma append_toIndexList (h : AppendCond l l2) :
|
||||
(l ++[h] l2).toIndexList = l.toIndexList ++ l2.toIndexList := by
|
||||
rfl
|
||||
(l ++[h] l2).toIndexList = l.toIndexList ++ l2.toIndexList := rfl
|
||||
|
||||
namespace AppendCond
|
||||
|
||||
|
@ -61,7 +61,7 @@ variable {l l2 l3 : ColorIndexList 𝓒}
|
|||
@[symm]
|
||||
lemma symm (h : AppendCond l l2) : AppendCond l2 l := by
|
||||
apply And.intro _ (h.2.symm h.1)
|
||||
rw [append_withDual_eq_withUniqueDual_symm]
|
||||
rw [OnlyUniqueDuals.symm]
|
||||
exact h.1
|
||||
|
||||
lemma inr (h : AppendCond l l2) (h' : AppendCond (l ++[h] l2) l3) :
|
||||
|
@ -70,7 +70,7 @@ lemma inr (h : AppendCond l l2) (h' : AppendCond (l ++[h] l2) l3) :
|
|||
· have h1 := h'.1
|
||||
simp at h1
|
||||
rw [append_assoc] at h1
|
||||
exact l.append_withDual_eq_withUniqueDual_inr (l2.toIndexList ++ l3.toIndexList) h1
|
||||
exact OnlyUniqueDuals.inr h1
|
||||
· have h1 := h'.2
|
||||
simp at h1
|
||||
rw [append_assoc] at h1
|
||||
|
@ -92,95 +92,19 @@ lemma swap (h : AppendCond l l2) (h' : AppendCond (l ++[h] l2) l3) :
|
|||
AppendCond (l2 ++[h.symm] l) l3:= by
|
||||
apply And.intro
|
||||
· simp only [append_toIndexList]
|
||||
rw [← append_withDual_eq_withUniqueDual_swap]
|
||||
apply OnlyUniqueDuals.swap
|
||||
simpa using h'.1
|
||||
· exact ColorCond.swap h'.1 h'.2
|
||||
|
||||
/-- If `AppendCond l l2` then `AppendCond l.contr l2`. Note that the inverse
|
||||
is generally not true. -/
|
||||
lemma contr_left (h : AppendCond l l2) : AppendCond l.contr l2 := by
|
||||
apply And.intro (append_withDual_eq_withUniqueDual_contr_left l.toIndexList l2.toIndexList h.1)
|
||||
· rw [ColorCond.iff_countColorCond_all]
|
||||
· simp only [append_val, countId_append, List.all_append, Bool.and_eq_true, List.all_eq_true,
|
||||
decide_eq_true_eq]
|
||||
apply And.intro
|
||||
· intro I hI hI2
|
||||
have hIC1 : l.contr.countId I = 1 :=
|
||||
mem_contrIndexList_countId_contrIndexList l.toIndexList hI
|
||||
have hIC2 : l2.countId I = 1 := by omega
|
||||
obtain ⟨I1, hI1, hI1'⟩ := countId_neq_zero_mem l.contr I (by omega)
|
||||
apply ColorCond.countColorCond_of_filter_eq (l.toIndexList ++ l2.toIndexList) _ _
|
||||
· have h2 := h.2
|
||||
rw [ColorCond.iff_countColorCond_all] at h2
|
||||
· simp only [append_val, countId_append, List.all_append, Bool.and_eq_true,
|
||||
List.all_eq_true, decide_eq_true_eq] at h2
|
||||
have hn := h2.1 I (List.mem_of_mem_filter hI)
|
||||
have hc : l.countId I + l2.countId I = 2 := by
|
||||
rw [contr, countId_contrIndexList_eq_one_iff_countId_eq_one] at hIC1
|
||||
omega
|
||||
exact hn hc
|
||||
· exact h.1
|
||||
· erw [List.filter_append, List.filter_append]
|
||||
apply congrFun
|
||||
apply congrArg
|
||||
rw [countId_congr _ hI1'] at hIC1
|
||||
rw [hI1', filter_id_of_countId_eq_one_mem l.contr hI1 hIC1]
|
||||
simp [contr, contrIndexList] at hI1
|
||||
exact filter_id_of_countId_eq_one_mem l hI1.1 hI1.2
|
||||
· intro I hI1 hI2
|
||||
by_cases hICz : l2.countId I = 0
|
||||
· rw [hICz] at hI2
|
||||
have hx : l.contr.countId I ≤ 1 := countId_contrIndexList_le_one l.toIndexList I
|
||||
omega
|
||||
· by_cases hICo : l2.countId I = 1
|
||||
· have hIC1 : l.contr.countId I = 1 := by omega
|
||||
obtain ⟨I1, hI', hI1'⟩ := countId_neq_zero_mem l.contr I (by omega)
|
||||
apply ColorCond.countColorCond_of_filter_eq (l.toIndexList ++ l2.toIndexList) _ _
|
||||
· have h2 := h.2
|
||||
rw [ColorCond.iff_countColorCond_all] at h2
|
||||
· simp only [append_val, countId_append, List.all_append, Bool.and_eq_true,
|
||||
List.all_eq_true, decide_eq_true_eq] at h2
|
||||
refine h2.2 I hI1 ?_
|
||||
rw [contr, countId_contrIndexList_eq_one_iff_countId_eq_one] at hIC1
|
||||
omega
|
||||
· exact h.1
|
||||
· erw [List.filter_append, List.filter_append]
|
||||
apply congrFun
|
||||
apply congrArg
|
||||
rw [hI1']
|
||||
rw [countId_congr _ hI1'] at hIC1
|
||||
rw [filter_id_of_countId_eq_one_mem l.contr hI' hIC1]
|
||||
simp [contr, contrIndexList] at hI'
|
||||
exact filter_id_of_countId_eq_one_mem l hI'.1 hI'.2
|
||||
· have hICt : l2.countId I = 2 := by
|
||||
omega
|
||||
apply ColorCond.countColorCond_of_filter_eq l2 _ _
|
||||
· have hl2C := l2.dual_color
|
||||
rw [ColorCond.iff_countColorCond_all] at hl2C
|
||||
· simp only [List.all_eq_true, decide_eq_true_eq] at hl2C
|
||||
exact hl2C I hI1 hICt
|
||||
· exact l2.unique_duals.symm
|
||||
· erw [List.filter_append]
|
||||
rw [filter_id_of_countId_eq_zero' l.contr.toIndexList]
|
||||
· rfl
|
||||
· omega
|
||||
· exact append_withDual_eq_withUniqueDual_contr_left l.toIndexList l2.toIndexList h.1
|
||||
lemma contr_left (h : AppendCond l l2) : AppendCond l.contr l2 :=
|
||||
And.intro (OnlyUniqueDuals.contrIndexList_left h.1) (ColorCond.contrIndexList_left h.1 h.2)
|
||||
|
||||
lemma contr_right (h : AppendCond l l2) : AppendCond l l2.contr := (contr_left h.symm).symm
|
||||
|
||||
lemma contr (h : AppendCond l l2) : AppendCond l.contr l2.contr := contr_left (contr_right h)
|
||||
|
||||
lemma of_eq (h1 : l.withUniqueDual = l.withDual)
|
||||
(h2 : l2.withUniqueDual = l2.withDual)
|
||||
(h3 : l.withUniqueDualInOther l2 = l.withDualInOther l2)
|
||||
(h4 : l2.withUniqueDualInOther l = l2.withDualInOther l)
|
||||
(h5 : ColorCond.bool (l.toIndexList ++ l2.toIndexList)) :
|
||||
AppendCond l l2 := by
|
||||
rw [AppendCond]
|
||||
rw [append_withDual_eq_withUniqueDual_iff']
|
||||
simp_all
|
||||
exact ColorCond.iff_bool.mpr h5
|
||||
|
||||
/-- A boolean which is true for two index lists `l` and `l2` if on appending
|
||||
they can form a `ColorIndexList`. -/
|
||||
def bool (l l2 : IndexList 𝓒.Color) : Bool :=
|
||||
|
@ -198,18 +122,17 @@ lemma iff_bool (l l2 : ColorIndexList 𝓒) : AppendCond l l2 ↔ bool l.toIndex
|
|||
simp [bool]
|
||||
rw [ColorCond.iff_bool]
|
||||
simp
|
||||
exact fun _ => Eq.to_iff rfl
|
||||
|
||||
lemma countId_contr_fst_eq_zero_mem_snd (h : AppendCond l l2) {I : Index 𝓒.Color}
|
||||
(hI : I ∈ l2.val) : l.contr.countId I = 0 ↔ l.countId I = 0 := by
|
||||
rw [countId_contr_eq_zero_iff]
|
||||
refine Iff.intro (fun h' => ?_) (fun h' => ?_)
|
||||
· have h1 := h.1
|
||||
rw [withUniqueDual_eq_withDual_iff_countId_leq_two'] at h1
|
||||
have h1I := h1 I
|
||||
simp at h1I
|
||||
have h2 : l2.countId I ≠ 0 := countId_mem l2.toIndexList I hI
|
||||
omega
|
||||
· simp [h']
|
||||
have h1 := countId_mem l2.toIndexList I hI
|
||||
have h1I := h.1
|
||||
rw [OnlyUniqueDuals.iff_countId_leq_two'] at h1I
|
||||
have h1I' := h1I I
|
||||
simp at h1I'
|
||||
omega
|
||||
|
||||
lemma countId_contr_snd_eq_zero_mem_fst (h : AppendCond l l2) {I : Index 𝓒.Color}
|
||||
(hI : I ∈ l.val) : l2.contr.countId I = 0 ↔ l2.countId I = 0 := by
|
||||
|
|
|
@ -3,8 +3,7 @@ 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.Color
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.OnlyUniqueDuals
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Color
|
||||
import HepLean.SpaceTime.LorentzTensor.Basic
|
||||
import Init.Data.List.Lemmas
|
||||
/-!
|
||||
|
@ -33,7 +32,7 @@ variable [IndexNotation 𝓒.Color] [Fintype 𝓒.Color] [DecidableEq 𝓒.Color
|
|||
structure ColorIndexList (𝓒 : TensorColor) [IndexNotation 𝓒.Color] extends IndexList 𝓒.Color where
|
||||
/-- The condition that for index with a dual, that dual is the unique other index with
|
||||
an identical `id`. -/
|
||||
unique_duals : toIndexList.withDual = toIndexList.withUniqueDual
|
||||
unique_duals : toIndexList.OnlyUniqueDuals
|
||||
/-- The condition that for an index with a dual, that dual has dual color to the index. -/
|
||||
dual_color : IndexList.ColorCond toIndexList
|
||||
|
||||
|
@ -90,122 +89,14 @@ def empty : ColorIndexList 𝓒 where
|
|||
unique_duals := rfl
|
||||
dual_color := rfl
|
||||
|
||||
/-- The `ColorIndexList` obtained by adding an index, subject to some conditions,
|
||||
to the start of `l`. -/
|
||||
def cons (I : Index 𝓒.Color) (hI1 : l.val.countP (fun J => I.id = J.id) ≤ 1)
|
||||
(hI2 : l.val.countP (fun J => I.id = J.id) =
|
||||
l.val.countP (fun J => I.id = J.id ∧ I.toColor = 𝓒.τ J.toColor)) : ColorIndexList 𝓒 where
|
||||
toIndexList := l.toIndexList.cons I
|
||||
unique_duals := by
|
||||
symm
|
||||
rw [withUniqueDual_eq_withDual_cons_iff]
|
||||
· exact hI1
|
||||
· exact l.unique_duals.symm
|
||||
dual_color := by
|
||||
have h1 : (l.toIndexList.cons I).withUniqueDual = (l.toIndexList.cons I).withDual ∧
|
||||
(l.toIndexList.cons I).ColorCond := by
|
||||
rw [ColorCond.cons_iff]
|
||||
exact ⟨l.unique_duals.symm, l.dual_color, hI1, hI2⟩
|
||||
exact h1.2
|
||||
|
||||
/-- The tail of a `ColorIndexList`. In other words, the `ColorIndexList` with the first index
|
||||
removed. -/
|
||||
def tail (l : ColorIndexList 𝓒) : ColorIndexList 𝓒 where
|
||||
toIndexList := l.toIndexList.tail
|
||||
unique_duals := by
|
||||
by_cases hl : l.toIndexList = {val := []}
|
||||
· rw [hl]
|
||||
simp [IndexList.tail]
|
||||
rfl
|
||||
· have hl' := l.head_cons_tail hl
|
||||
have h1 := l.unique_duals
|
||||
rw [hl'] at h1
|
||||
exact (withUniqueDual_eq_withDual_of_cons _ h1.symm).symm
|
||||
dual_color := by
|
||||
by_cases hl : l.toIndexList = {val := []}
|
||||
· rw [hl]
|
||||
simp [IndexList.tail]
|
||||
rfl
|
||||
· have hl' := l.head_cons_tail hl
|
||||
have h1 := l.unique_duals
|
||||
have h2 := l.dual_color
|
||||
rw [hl'] at h1 h2
|
||||
exact (ColorCond.of_cons _ h2 h1.symm)
|
||||
|
||||
@[simp]
|
||||
lemma tail_toIndexList : l.tail.toIndexList = l.toIndexList.tail := by
|
||||
rfl
|
||||
|
||||
/-- The first index in a `ColorIndexList`. -/
|
||||
def head (h : l ≠ empty) : Index 𝓒.Color :=
|
||||
l.toIndexList.head (by
|
||||
cases' l
|
||||
simpa [empty] using h)
|
||||
|
||||
lemma head_uniqueDual (h : l ≠ empty) :
|
||||
l.tail.val.countP (fun J => (l.head h).id = J.id) ≤ 1 := by
|
||||
have h1 := l.unique_duals.symm
|
||||
have hl : l.toIndexList = (l.tail.toIndexList.cons (l.head h)) := by
|
||||
simpa using l.head_cons_tail _
|
||||
rw [hl] at h1
|
||||
rw [withUniqueDual_eq_withDual_cons_iff'] at h1
|
||||
exact h1.2
|
||||
|
||||
lemma head_color_dual (h : l ≠ empty) :
|
||||
l.tail.val.countP (fun J => (l.head h).id = J.id) =
|
||||
l.tail.val.countP (fun J => (l.head h).id = J.id ∧ (l.head h).toColor = 𝓒.τ J.toColor) := by
|
||||
have h1 : l.withUniqueDual = l.withDual ∧ ColorCond l := ⟨l.unique_duals.symm, l.dual_color⟩
|
||||
have hl : l.toIndexList = (l.tail.toIndexList.cons (l.head h)) := by
|
||||
simpa using l.head_cons_tail _
|
||||
rw [hl, ColorCond.cons_iff] at h1
|
||||
exact h1.2.2.2
|
||||
|
||||
lemma head_cons_tail (h : l ≠ empty) :
|
||||
l = (l.tail).cons (l.head h) (l.head_uniqueDual h) (l.head_color_dual h) := by
|
||||
apply ext'
|
||||
exact IndexList.head_cons_tail _ _
|
||||
|
||||
/-!
|
||||
|
||||
## Induction for `ColorIndexList`
|
||||
|
||||
-/
|
||||
|
||||
lemma induction {P : ColorIndexList 𝓒 → Prop } (h_nil : P empty)
|
||||
(h_cons : ∀ (I : Index 𝓒.Color) (l : ColorIndexList 𝓒)
|
||||
(hI1 : l.val.countP (fun J => I.id = J.id) ≤ 1) (hI2 : l.val.countP (fun J => I.id = J.id) =
|
||||
l.val.countP (fun J => I.id = J.id ∧ I.toColor = 𝓒.τ J.toColor)), P l → P (l.cons I hI1 hI2))
|
||||
(l : ColorIndexList 𝓒) : P l := by
|
||||
by_cases h : l = empty
|
||||
· subst l
|
||||
exact h_nil
|
||||
· rw [l.head_cons_tail h]
|
||||
refine h_cons (l.head h) (l.tail) (l.head_uniqueDual h) (l.head_color_dual h) ?_
|
||||
exact induction h_nil h_cons l.tail
|
||||
termination_by l.length
|
||||
decreasing_by {
|
||||
by_cases hn : l = empty
|
||||
· subst hn
|
||||
simp
|
||||
exact False.elim (h rfl)
|
||||
· have h1 : l.tail.length < l.length := by
|
||||
simp [IndexList.tail, length]
|
||||
by_contra hn'
|
||||
simp at hn'
|
||||
have hv : l = empty := ext hn'
|
||||
exact False.elim (hn hv)
|
||||
exact h1
|
||||
}
|
||||
|
||||
/-!
|
||||
|
||||
## CountId for `ColorIndexList`
|
||||
|
||||
-/
|
||||
|
||||
lemma countId_le_two (l : ColorIndexList 𝓒) (I : Index 𝓒.Color) :
|
||||
l.countId I ≤ 2 :=
|
||||
(withUniqueDual_eq_withDual_iff_countId_leq_two' l.toIndexList).mp l.unique_duals.symm I
|
||||
lemma countId_le_two (l : ColorIndexList 𝓒) (I : Index 𝓒.Color) : l.countId I ≤ 2 :=
|
||||
(OnlyUniqueDuals.iff_countId_leq_two').mp l.unique_duals I
|
||||
|
||||
end ColorIndexList
|
||||
end IndexNotation
|
||||
|
|
|
@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
|||
Authors: Joseph Tooby-Smith
|
||||
-/
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.ColorIndexList.Basic
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.Contraction
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Contraction
|
||||
import HepLean.SpaceTime.LorentzTensor.Contraction
|
||||
import HepLean.SpaceTime.LorentzTensor.Basic
|
||||
import Init.Data.List.Lemmas
|
||||
|
@ -36,7 +36,7 @@ open IndexList TensorColor
|
|||
def contr : ColorIndexList 𝓒 where
|
||||
toIndexList := l.toIndexList.contrIndexList
|
||||
unique_duals := by
|
||||
simp
|
||||
simp [OnlyUniqueDuals]
|
||||
dual_color := by
|
||||
funext i
|
||||
simp [Option.guard]
|
||||
|
@ -114,17 +114,9 @@ lemma contr_countId_eq_filter (I : Index 𝓒.Color) :
|
|||
exact Bool.and_comm (decide (I.id = J.id))
|
||||
(decide (List.countP (fun j => decide (J.id = j.id)) l.val = 1))
|
||||
|
||||
lemma countId_contr_le_one_of_countId (I : Index 𝓒.Color) (hI1 : l.countId I ≤ 1) :
|
||||
lemma countId_contr_le_one (I : Index 𝓒.Color) :
|
||||
l.contr.countId I ≤ 1 := by
|
||||
rw [contr_countId_eq_filter]
|
||||
by_cases hI1 : l.countId I = 0
|
||||
· rw [l.filter_id_of_countId_eq_zero' hI1]
|
||||
simp
|
||||
· have hI1 : l.countId I = 1 := by
|
||||
omega
|
||||
rw [l.consDual_filter hI1]
|
||||
apply (List.countP_le_length _).trans
|
||||
rfl
|
||||
exact l.countId_contrIndexList_le_one I
|
||||
|
||||
lemma countId_contr_eq_zero_iff (I : Index 𝓒.Color) :
|
||||
l.contr.countId I = 0 ↔ l.countId I = 0 ∨ l.countId I = 2 := by
|
||||
|
@ -155,7 +147,8 @@ lemma countId_contr_eq_zero_iff (I : Index 𝓒.Color) :
|
|||
def contrEquiv : (l.withUniqueDualLT ⊕ l.withUniqueDualLT) ⊕ Fin l.contr.length ≃ Fin l.length :=
|
||||
(Equiv.sumCongr (l.withUniqueLTGTEquiv) (Equiv.refl _)).trans <|
|
||||
(Equiv.sumCongr (Equiv.subtypeEquivRight (by
|
||||
simp only [l.unique_duals, implies_true]))
|
||||
rw [l.unique_duals]
|
||||
simp only [mem_withDual_iff_isSome, implies_true]))
|
||||
(Fin.castOrderIso l.contrIndexList_length).toEquiv).trans <|
|
||||
l.dualEquiv
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
|||
Authors: Joseph Tooby-Smith
|
||||
-/
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.ColorIndexList.Contraction
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Subperm
|
||||
import HepLean.SpaceTime.LorentzTensor.Basic
|
||||
import Init.Data.List.Lemmas
|
||||
/-!
|
||||
|
@ -122,7 +123,7 @@ To prevent choice problems, this has to be done after contraction.
|
|||
-/
|
||||
def ContrPerm : Prop :=
|
||||
l.contr.length = l'.contr.length ∧
|
||||
l.contr.withUniqueDualInOther l'.contr = Finset.univ ∧
|
||||
IndexList.Subperm l.contr l'.contr.toIndexList ∧
|
||||
l'.contr.colorMap' ∘ Subtype.val ∘ (l.contr.getDualInOtherEquiv l'.contr)
|
||||
= l.contr.colorMap' ∘ Subtype.val
|
||||
|
||||
|
@ -130,47 +131,181 @@ namespace ContrPerm
|
|||
|
||||
variable {l l' l2 l3 : ColorIndexList 𝓒}
|
||||
|
||||
lemma getDualInOtherEquiv_eq (h : l.ContrPerm l2) (i : Fin l.contr.length) :
|
||||
l2.contr.val.get (l.contr.getDualInOtherEquiv l2.contr ⟨i, by
|
||||
rw [h.2.1]
|
||||
exact Finset.mem_univ i⟩).1 = l.contr.val.get i := by
|
||||
rw [Index.eq_iff_color_eq_and_id_eq]
|
||||
apply And.intro
|
||||
· trans (l2.contr.colorMap' ∘ Subtype.val ∘ (l.contr.getDualInOtherEquiv l2.contr)) ⟨i, by
|
||||
rw [h.2.1]
|
||||
exact Finset.mem_univ i⟩
|
||||
· simp
|
||||
rfl
|
||||
· simp only [h.2.2]
|
||||
rfl
|
||||
· trans l2.contr.idMap (l.contr.getDualInOtherEquiv l2.contr ⟨i, by
|
||||
rw [h.2.1]
|
||||
exact Finset.mem_univ i⟩).1
|
||||
· simp
|
||||
rfl
|
||||
· simp [getDualInOtherEquiv]
|
||||
rfl
|
||||
|
||||
lemma mem_snd_of_mem_snd (h : l.ContrPerm l2) {I : Index 𝓒.Color} (hI : I ∈ l.contr.val) :
|
||||
I ∈ l2.contr.val := by
|
||||
have h1 : l.contr.val.indexOf I < l.contr.val.length := List.indexOf_lt_length.mpr hI
|
||||
have h2 : I = l.contr.val.get ⟨l.contr.val.indexOf I, h1⟩ := (List.indexOf_get h1).symm
|
||||
rw [h2]
|
||||
rw [← getDualInOtherEquiv_eq h ⟨l.contr.val.indexOf I, h1⟩]
|
||||
simp only [List.get_eq_getElem]
|
||||
exact List.getElem_mem _ _ _
|
||||
|
||||
lemma countSelf_eq_one_snd_of_countSelf_eq_one_fst (h : l.ContrPerm l2) {I : Index 𝓒.Color}
|
||||
(h1 : l.contr.countSelf I = 1) : l2.contr.countSelf I = 1 := by
|
||||
refine countSelf_eq_one_of_countId_eq_one l2.contr I ?_ (mem_snd_of_mem_snd h ?_)
|
||||
· have h2 := h.2.1
|
||||
rw [Subperm.iff_countId] at h2
|
||||
refine (h2 I).2 ?_
|
||||
have h1 := h2 I
|
||||
have h2' := countSelf_le_countId l.contr.toIndexList I
|
||||
omega
|
||||
· rw [← countSelf_neq_zero, h1]
|
||||
simp
|
||||
|
||||
lemma getDualInOtherEquiv_eq_of_countSelf
|
||||
(hn : IndexList.Subperm l.contr l2.contr.toIndexList) (i : Fin l.contr.length)
|
||||
(h1 : l2.contr.countId (l.contr.val.get i) = 1)
|
||||
(h2 : l2.contr.countSelf (l.contr.val.get i) = 1) :
|
||||
l2.contr.val.get (l.contr.getDualInOtherEquiv l2.contr ⟨i, by
|
||||
rw [hn]
|
||||
exact Finset.mem_univ i⟩).1 = l.contr.val.get i := by
|
||||
have h1' : (l.contr.val.get i) ∈ l2.contr.val := by
|
||||
rw [← countSelf_neq_zero, h2]
|
||||
simp
|
||||
rw [← List.mem_singleton, ← filter_id_of_countId_eq_one_mem l2.contr.toIndexList h1' h1]
|
||||
simp only [List.get_eq_getElem, List.mem_filter, decide_eq_true_eq]
|
||||
apply And.intro (List.getElem_mem _ _ _)
|
||||
simp [getDualInOtherEquiv]
|
||||
change _ = l2.contr.idMap (l.contr.getDualInOtherEquiv l2.contr ⟨i, by
|
||||
rw [hn]
|
||||
exact Finset.mem_univ i⟩).1
|
||||
simp [getDualInOtherEquiv]
|
||||
rfl
|
||||
|
||||
lemma colorMap_eq_of_countSelf (hn : IndexList.Subperm l.contr l2.contr.toIndexList)
|
||||
(h2 : ∀ i, l.contr.countSelf (l.contr.val.get i) = 1
|
||||
→ l2.contr.countSelf (l.contr.val.get i) = 1) :
|
||||
l2.contr.colorMap' ∘ Subtype.val ∘ (l.contr.getDualInOtherEquiv l2.contr)
|
||||
= l.contr.colorMap' ∘ Subtype.val := by
|
||||
funext a
|
||||
simp [colorMap', colorMap]
|
||||
change _ = (l.contr.val.get a.1).toColor
|
||||
rw [← getDualInOtherEquiv_eq_of_countSelf hn a.1]
|
||||
· rfl
|
||||
· rw [@Subperm.iff_countId_fin] at hn
|
||||
exact (hn a.1).2
|
||||
· refine h2 a.1
|
||||
(countSelf_eq_one_of_countId_eq_one l.contr.toIndexList (l.contr.val.get a.1) ?h1 ?hme)
|
||||
· rw [Subperm.iff_countId_fin] at hn
|
||||
exact (hn a.1).1
|
||||
· simp
|
||||
exact List.getElem_mem l.contr.val (↑↑a) a.1.isLt
|
||||
|
||||
lemma iff_count_fin : l.ContrPerm l2 ↔
|
||||
l.contr.length = l2.contr.length ∧ IndexList.Subperm l.contr l2.contr.toIndexList ∧
|
||||
∀ i, l.contr.countSelf (l.contr.val.get i) = 1 →
|
||||
l2.contr.countSelf (l.contr.val.get i) = 1 := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· refine And.intro h.1 (And.intro h.2.1 ?_)
|
||||
exact fun i a => countSelf_eq_one_snd_of_countSelf_eq_one_fst h a
|
||||
· refine And.intro h.1 (And.intro h.2.1 ?_)
|
||||
apply colorMap_eq_of_countSelf h.2.1 h.2.2
|
||||
|
||||
lemma iff_count' : l.ContrPerm l2 ↔
|
||||
l.contr.length = l2.contr.length ∧ IndexList.Subperm l.contr l2.contr.toIndexList ∧
|
||||
∀ I, l.contr.countSelf I = 1 → l2.contr.countSelf I = 1 := by
|
||||
rw [iff_count_fin]
|
||||
simp_all only [List.get_eq_getElem, and_congr_right_iff]
|
||||
intro _ _
|
||||
apply Iff.intro
|
||||
· intro ha I hI1
|
||||
have hI : I ∈ l.contr.val := by
|
||||
rw [← countSelf_neq_zero, hI1]
|
||||
simp
|
||||
have hId : l.contr.val.indexOf I < l.contr.val.length := List.indexOf_lt_length.mpr hI
|
||||
have hI' : I = l.contr.val.get ⟨l.contr.val.indexOf I, hId⟩ := (List.indexOf_get hId).symm
|
||||
rw [hI'] at hI1 ⊢
|
||||
exact ha ⟨l.contr.val.indexOf I, hId⟩ hI1
|
||||
· intro a_2 i a_3
|
||||
simp_all only
|
||||
|
||||
lemma iff_count : l.ContrPerm l2 ↔ l.contr.length = l2.contr.length ∧
|
||||
∀ I, l.contr.countSelf I = 1 → l2.contr.countSelf I = 1 := by
|
||||
rw [iff_count']
|
||||
refine Iff.intro (fun h => And.intro h.1 h.2.2) (fun h => And.intro h.1 (And.intro ?_ h.2))
|
||||
rw [Subperm.iff_countId]
|
||||
intro I
|
||||
apply And.intro (countId_contr_le_one l I)
|
||||
intro h'
|
||||
obtain ⟨I', hI1, hI2⟩ := countId_neq_zero_mem l.contr I (by omega)
|
||||
rw [countId_congr _ hI2] at h' ⊢
|
||||
have hi := h.2 I' (countSelf_eq_one_of_countId_eq_one l.contr.toIndexList I' h' hI1)
|
||||
have h1 := countSelf_le_countId l2.contr.toIndexList I'
|
||||
have h2 := countId_contr_le_one l2 I'
|
||||
omega
|
||||
|
||||
/-- The relation `ContrPerm` is symmetric. -/
|
||||
@[symm]
|
||||
lemma symm (h : ContrPerm l l') : ContrPerm l' l := by
|
||||
rw [ContrPerm] at h ⊢
|
||||
apply And.intro h.1.symm
|
||||
apply And.intro (l.contr.withUniqueDualInOther_eq_univ_symm l'.contr h.1 h.2.1)
|
||||
apply And.intro (Subperm.symm h.2.1 h.1)
|
||||
rw [← Function.comp.assoc, ← h.2.2, Function.comp.assoc, Function.comp.assoc]
|
||||
rw [show (l.contr.getDualInOtherEquiv l'.contr) =
|
||||
(l'.contr.getDualInOtherEquiv l.contr).symm from rfl]
|
||||
simp only [Equiv.symm_comp_self, CompTriple.comp_eq]
|
||||
|
||||
lemma iff_countSelf : l.ContrPerm l2 ↔ ∀ I, l.contr.countSelf I = l2.contr.countSelf I := by
|
||||
refine Iff.intro (fun h I => ?_) (fun h => ?_)
|
||||
· have hs := h.symm
|
||||
rw [iff_count] at hs h
|
||||
have ht := Iff.intro (fun h1 => h.2 I h1) (fun h2 => hs.2 I h2)
|
||||
have h1 : l.contr.countSelf I ≤ 1 := countSelf_contrIndexList_le_one l.toIndexList I
|
||||
have h2 : l2.contr.countSelf I ≤ 1 := countSelf_contrIndexList_le_one l2.toIndexList I
|
||||
omega
|
||||
· rw [iff_count]
|
||||
apply And.intro
|
||||
· have h1 : l.contr.val.Perm l2.contr.val := by
|
||||
rw [List.perm_iff_count]
|
||||
intro I
|
||||
rw [← countSelf_count, ← countSelf_count]
|
||||
exact h I
|
||||
exact List.Perm.length_eq h1
|
||||
· intro I
|
||||
rw [h I]
|
||||
simp
|
||||
|
||||
lemma contr_perm (h : l.ContrPerm l2) : l.contr.val.Perm l2.contr.val := by
|
||||
rw [List.perm_iff_count]
|
||||
intro I
|
||||
rw [← countSelf_count, ← countSelf_count]
|
||||
exact iff_countSelf.mp h I
|
||||
|
||||
/-- The relation `ContrPerm` is reflexive. -/
|
||||
@[simp]
|
||||
lemma refl (l : ColorIndexList 𝓒) : ContrPerm l l := by
|
||||
apply And.intro rfl
|
||||
apply And.intro l.withUniqueDualInOther_eq_univ_contr_refl
|
||||
simp only [getDualInOtherEquiv_self_refl, Equiv.coe_refl, CompTriple.comp_eq]
|
||||
rw [iff_countSelf]
|
||||
exact fun I => rfl
|
||||
|
||||
/-- The relation `ContrPerm` is transitive. -/
|
||||
@[trans]
|
||||
lemma trans (h1 : ContrPerm l l2) (h2 : ContrPerm l2 l3) : ContrPerm l l3 := by
|
||||
apply And.intro (h1.1.trans h2.1)
|
||||
apply And.intro (l.contr.withUniqueDualInOther_eq_univ_trans l2.contr l3.contr h1.2.1 h2.2.1)
|
||||
funext i
|
||||
simp only [Function.comp_apply]
|
||||
have h1' := congrFun h1.2.2 ⟨i, by simp [h1.2.1]⟩
|
||||
simp only [Function.comp_apply] at h1'
|
||||
rw [← h1']
|
||||
have h2' := congrFun h2.2.2 ⟨
|
||||
↑((l.contr.getDualInOtherEquiv l2.contr.toIndexList) ⟨↑i, by simp [h1.2.1]⟩), by simp [h2.2.1]⟩
|
||||
simp only [Function.comp_apply] at h2'
|
||||
rw [← h2']
|
||||
apply congrArg
|
||||
simp only [getDualInOtherEquiv, Equiv.coe_fn_mk]
|
||||
rw [← eq_getDualInOther?_get_of_withUniqueDualInOther_iff]
|
||||
· simp only [AreDualInOther, getDualInOther?_id]
|
||||
· rw [h2.2.1]
|
||||
simp
|
||||
rw [iff_countSelf] at h1 h2 ⊢
|
||||
exact fun I => (h1 I).trans (h2 I)
|
||||
|
||||
/-- `ContrPerm` forms an equivalence relation. -/
|
||||
lemma equivalence : Equivalence (@ContrPerm 𝓒 _) where
|
||||
lemma equivalence : Equivalence (@ContrPerm 𝓒 _ _) where
|
||||
refl := refl
|
||||
symm := symm
|
||||
trans := trans
|
||||
|
@ -181,12 +316,9 @@ lemma symm_trans (h1 : ContrPerm l l2) (h2 : ContrPerm l2 l3) :
|
|||
|
||||
@[simp]
|
||||
lemma contr_self : ContrPerm l l.contr := by
|
||||
rw [ContrPerm]
|
||||
simp only [contr_contr, true_and]
|
||||
have h1 := @refl _ _ l
|
||||
apply And.intro h1.2.1
|
||||
rw [show l.contr.contr = l.contr by simp]
|
||||
simp only [getDualInOtherEquiv_self_refl, Equiv.coe_refl, CompTriple.comp_eq]
|
||||
rw [iff_countSelf]
|
||||
intro I
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
lemma self_contr : ContrPerm l.contr l := by
|
||||
|
@ -203,7 +335,9 @@ lemma mem_withUniqueDualInOther_of_no_contr (h : l.ContrPerm l') (h1 : l.withDua
|
|||
(h2 : l'.withDual = ∅) : ∀ (x : Fin l.length), x ∈ l.withUniqueDualInOther l'.toIndexList := by
|
||||
simp only [ContrPerm] at h
|
||||
rw [contr_of_withDual_empty l h1, contr_of_withDual_empty l' h2] at h
|
||||
simp [h.2.1]
|
||||
rw [h.2.1]
|
||||
intro x
|
||||
exact Finset.mem_univ x
|
||||
|
||||
end ContrPerm
|
||||
|
||||
|
@ -220,9 +354,9 @@ open ContrPerm
|
|||
permutation between the contracted indices. -/
|
||||
def contrPermEquiv {l l' : ColorIndexList 𝓒} (h : ContrPerm l l') :
|
||||
Fin l.contr.length ≃ Fin l'.contr.length :=
|
||||
(Equiv.subtypeUnivEquiv (by simp [h.2])).symm.trans <|
|
||||
(Equiv.subtypeUnivEquiv (by rw [h.2.1]; exact fun x => Finset.mem_univ x)).symm.trans <|
|
||||
(l.contr.getDualInOtherEquiv l'.contr.toIndexList).trans <|
|
||||
Equiv.subtypeUnivEquiv (by simp [h.symm.2])
|
||||
Equiv.subtypeUnivEquiv (by rw [h.symm.2.1]; exact fun x => Finset.mem_univ x)
|
||||
|
||||
lemma contrPermEquiv_colorMap_iso {l l' : ColorIndexList 𝓒} (h : ContrPerm l l') :
|
||||
ColorMap.MapIso (contrPermEquiv h).symm l'.contr.colorMap' l.contr.colorMap' := by
|
||||
|
@ -244,7 +378,7 @@ lemma contrPermEquiv_colorMap_iso' {l l' : ColorIndexList 𝓒} (h : ContrPerm l
|
|||
exact contrPermEquiv_colorMap_iso h
|
||||
|
||||
@[simp]
|
||||
lemma contrPermEquiv_refl : contrPermEquiv (@ContrPerm.refl 𝓒 _ l) = Equiv.refl _ := by
|
||||
lemma contrPermEquiv_refl : contrPermEquiv (ContrPerm.refl l) = Equiv.refl _ := by
|
||||
simp [contrPermEquiv, ContrPerm.refl]
|
||||
|
||||
@[simp]
|
||||
|
@ -262,14 +396,24 @@ lemma contrPermEquiv_trans {l l2 l3 : ColorIndexList 𝓒}
|
|||
simp only [getDualInOtherEquiv, Equiv.trans_apply, Equiv.subtypeUnivEquiv_symm_apply,
|
||||
Equiv.coe_fn_mk, Equiv.subtypeUnivEquiv_apply]
|
||||
apply congrArg
|
||||
rw [← eq_getDualInOther?_get_of_withUniqueDualInOther_iff]
|
||||
· simp [AreDualInOther]
|
||||
· rw [(h1.trans h2).2.1]
|
||||
simp
|
||||
have h1' : l.contr.countSelf (l.contr.val.get x) = 1 := by simp [contr]
|
||||
rw [iff_countSelf.mp h1, iff_countSelf.mp h2] at h1'
|
||||
have h3 : l3.contr.countId (l.contr.val.get x) = 1 := by
|
||||
have h' := countSelf_le_countId l3.contr.toIndexList (l.contr.val.get x)
|
||||
have h'' := countId_contr_le_one l3 (l.contr.val.get x)
|
||||
omega
|
||||
rw [countId_get_other, List.countP_eq_length_filter, List.length_eq_one] at h3
|
||||
obtain ⟨a, ha⟩ := h3
|
||||
trans a
|
||||
· rw [← List.mem_singleton, ← ha]
|
||||
simp [AreDualInOther]
|
||||
· symm
|
||||
rw [← List.mem_singleton, ← ha]
|
||||
simp [AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma contrPermEquiv_self_contr {l : ColorIndexList 𝓒} :
|
||||
contrPermEquiv (by simp : ContrPerm l l.contr) =
|
||||
contrPermEquiv (contr_self : ContrPerm l l.contr) =
|
||||
(Fin.castOrderIso (by simp)).toEquiv := by
|
||||
simp [contrPermEquiv]
|
||||
ext1 x
|
||||
|
@ -277,11 +421,21 @@ lemma contrPermEquiv_self_contr {l : ColorIndexList 𝓒} :
|
|||
Equiv.coe_fn_mk, Equiv.subtypeUnivEquiv_apply, RelIso.coe_fn_toEquiv, Fin.castOrderIso_apply,
|
||||
Fin.coe_cast]
|
||||
symm
|
||||
rw [← eq_getDualInOther?_get_of_withUniqueDualInOther_iff]
|
||||
· simp only [AreDualInOther, contr_contr_idMap, Fin.cast_trans, Fin.cast_eq_self]
|
||||
· have h1 : ContrPerm l l.contr := by simp
|
||||
rw [h1.2.1]
|
||||
simp
|
||||
have h1' : l.contr.countSelf (l.contr.val.get x) = 1 := by simp [contr]
|
||||
rw [iff_countSelf.mp contr_self] at h1'
|
||||
have h3 : l.contr.contr.countId (l.contr.val.get x) = 1 := by
|
||||
have h' := countSelf_le_countId l.contr.contr.toIndexList (l.contr.val.get x)
|
||||
have h'' := countId_contr_le_one l.contr (l.contr.val.get x)
|
||||
omega
|
||||
rw [countId_get_other, List.countP_eq_length_filter, List.length_eq_one] at h3
|
||||
obtain ⟨a, ha⟩ := h3
|
||||
trans a
|
||||
· rw [← List.mem_singleton, ← ha]
|
||||
simp [AreDualInOther]
|
||||
· symm
|
||||
rw [← List.mem_singleton, ← ha]
|
||||
simp only [AreDualInOther, List.mem_filter, List.mem_finRange,
|
||||
decide_eq_true_eq, true_and, getDualInOther?_id]
|
||||
|
||||
@[simp]
|
||||
lemma contrPermEquiv_contr_self {l : ColorIndexList 𝓒} :
|
||||
|
|
|
@ -1,630 +0,0 @@
|
|||
/-
|
||||
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
|
||||
import Mathlib.Tactic.FinCases
|
||||
/-!
|
||||
|
||||
# Contraction of an index list.
|
||||
|
||||
In this file we define the contraction of an index list `l` to be the index list formed by
|
||||
by the subset of indices of `l` which do not have a dual in `l`.
|
||||
|
||||
For example, the contraction of the index list `['ᵘ¹', 'ᵘ²', 'ᵤ₁', 'ᵘ¹']` is the index list
|
||||
`['ᵘ²']`.
|
||||
|
||||
We also define the following finite sets
|
||||
- `l.withoutDual` the finite set of indices of `l` which do not have a dual in `l`.
|
||||
- `l.withUniqueDualLT` the finite set of those indices of `l` which have a unique dual, and
|
||||
for which that dual is greater-then (determined by the ordering on `Fin`) then the index itself.
|
||||
- `l.withUniqueDualGT` the finite set of those indices of `l` which have a unique dual, and
|
||||
for which that dual is less-then (determined by the ordering on `Fin`) then the index itself.
|
||||
|
||||
We define an equivalence `l.withUniqueDualLT ⊕ l.withUniqueDualLT ≃ l.withUniqueDual`.
|
||||
|
||||
We prove properties related to when `l.withUniqueDualInOther l2 = Finset.univ` for two
|
||||
index lists `l` and `l2`.
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
/-!
|
||||
|
||||
## Indices which do not have duals.
|
||||
|
||||
-/
|
||||
|
||||
/-- The finite set of indices of an index list which do not have a dual. -/
|
||||
def withoutDual : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => (l.getDual? i).isNone) Finset.univ
|
||||
|
||||
lemma withDual_disjoint_withoutDual : Disjoint l.withDual l.withoutDual := by
|
||||
rw [Finset.disjoint_iff_ne]
|
||||
intro a ha b hb
|
||||
by_contra hn
|
||||
subst hn
|
||||
simp_all only [withDual, Finset.mem_filter, Finset.mem_univ, true_and, withoutDual,
|
||||
Option.isNone_iff_eq_none, Option.isSome_none, Bool.false_eq_true]
|
||||
|
||||
lemma not_mem_withDual_of_mem_withoutDual (i : Fin l.length) (h : i ∈ l.withoutDual) :
|
||||
i ∉ l.withDual := by
|
||||
have h1 := l.withDual_disjoint_withoutDual
|
||||
exact Finset.disjoint_right.mp h1 h
|
||||
|
||||
lemma withDual_union_withoutDual : l.withDual ∪ l.withoutDual = Finset.univ := by
|
||||
rw [Finset.eq_univ_iff_forall]
|
||||
intro i
|
||||
by_cases h : (l.getDual? i).isSome
|
||||
· simp [withDual, Finset.mem_filter, Finset.mem_univ, h]
|
||||
· simp at h
|
||||
simp [withoutDual, Finset.mem_filter, Finset.mem_univ, h]
|
||||
|
||||
lemma mem_withoutDual_iff_countId_eq_one (i : Fin l.length) :
|
||||
i ∈ l.withoutDual ↔ l.countId (l.val.get i) = 1 := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· exact countId_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_countId_gt_one] at h
|
||||
omega
|
||||
|
||||
/-- An equivalence from `Fin l.withoutDual.card` to `l.withoutDual` determined by
|
||||
the order on `l.withoutDual` inherted from `Fin`. -/
|
||||
def withoutDualEquiv : Fin l.withoutDual.card ≃ l.withoutDual :=
|
||||
(Finset.orderIsoOfFin l.withoutDual (by rfl)).toEquiv
|
||||
|
||||
lemma list_ofFn_withoutDualEquiv_eq_sort :
|
||||
List.ofFn (Subtype.val ∘ l.withoutDualEquiv) = l.withoutDual.sort (fun i j => i ≤ j) := by
|
||||
rw [@List.ext_get_iff]
|
||||
refine And.intro ?_ (fun n h1 h2 => ?_)
|
||||
· simp only [List.length_ofFn, Finset.length_sort]
|
||||
· simp only [List.get_eq_getElem, List.getElem_ofFn, Function.comp_apply]
|
||||
rfl
|
||||
|
||||
lemma withoutDual_sort_eq_filter : l.withoutDual.sort (fun i j => i ≤ j) =
|
||||
(List.finRange l.length).filter (fun i => i ∈ l.withoutDual) := by
|
||||
rw [withoutDual]
|
||||
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
|
||||
|
||||
/-- An equivalence splitting the indices of an index list `l` into those indices
|
||||
which have a dual in `l` and those which do not have a dual in `l`. -/
|
||||
def dualEquiv : l.withDual ⊕ Fin l.withoutDual.card ≃ Fin l.length :=
|
||||
(Equiv.sumCongr (Equiv.refl _) l.withoutDualEquiv).trans <|
|
||||
(Equiv.Finset.union _ _ l.withDual_disjoint_withoutDual).trans <|
|
||||
Equiv.subtypeUnivEquiv (by simp [withDual_union_withoutDual])
|
||||
|
||||
/-!
|
||||
|
||||
## The contraction list
|
||||
|
||||
-/
|
||||
|
||||
/-- The index list formed from `l` by selecting only those indices in `l` which
|
||||
do not have a dual. -/
|
||||
def contrIndexList : IndexList X where
|
||||
val := l.val.filter (fun I => l.countId I = 1)
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_empty : (⟨[]⟩ : IndexList X).contrIndexList = { val := [] } := by
|
||||
apply ext
|
||||
simp [contrIndexList]
|
||||
|
||||
lemma contrIndexList_val : l.contrIndexList.val =
|
||||
l.val.filter (fun I => l.countId I = 1) := by
|
||||
rfl
|
||||
|
||||
/-- An alternative form of the contracted index list. -/
|
||||
@[simp]
|
||||
def contrIndexList' : IndexList X where
|
||||
val := List.ofFn (l.val.get ∘ Subtype.val ∘ l.withoutDualEquiv)
|
||||
|
||||
lemma contrIndexList_eq_contrIndexList' : l.contrIndexList = l.contrIndexList' := by
|
||||
apply ext
|
||||
simp only [contrIndexList']
|
||||
trans List.map l.val.get (List.ofFn (Subtype.val ∘ ⇑l.withoutDualEquiv))
|
||||
· rw [list_ofFn_withoutDualEquiv_eq_sort, withoutDual_sort_eq_filter]
|
||||
simp only [contrIndexList]
|
||||
let f1 : Index X → Bool := fun (I : Index X) => l.countId I = 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 := by
|
||||
funext i
|
||||
simp only [mem_withoutDual_iff_countId_eq_one l, List.get_eq_getElem, Function.comp_apply, f2,
|
||||
f1]
|
||||
rw [hf, ← List.filter_map]
|
||||
apply congrArg
|
||||
simp [length]
|
||||
· simp only [List.map_ofFn]
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_length : l.contrIndexList.length = l.withoutDual.card := by
|
||||
simp [contrIndexList_eq_contrIndexList', withoutDual, length]
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_idMap (i : Fin l.contrIndexList.length) : l.contrIndexList.idMap i
|
||||
= l.idMap (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)).1 := by
|
||||
simp [contrIndexList_eq_contrIndexList', idMap]
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_colorMap (i : Fin l.contrIndexList.length) : l.contrIndexList.colorMap i
|
||||
= l.colorMap (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)).1 := by
|
||||
simp [contrIndexList_eq_contrIndexList', colorMap]
|
||||
rfl
|
||||
|
||||
lemma contrIndexList_areDualInSelf (i j : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.AreDualInSelf i j ↔
|
||||
l.AreDualInSelf (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)).1
|
||||
(l.withoutDualEquiv (Fin.cast l.contrIndexList_length j)).1 := by
|
||||
simp [AreDualInSelf]
|
||||
intro _
|
||||
trans ¬ (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)) =
|
||||
(l.withoutDualEquiv (Fin.cast l.contrIndexList_length j))
|
||||
· rw [l.withoutDualEquiv.apply_eq_iff_eq]
|
||||
simp [Fin.ext_iff]
|
||||
· exact Iff.symm Subtype.coe_ne_coe
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_getDual? (i : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.getDual? i = none := by
|
||||
rw [← Option.not_isSome_iff_eq_none, ← mem_withDual_iff_isSome, mem_withDual_iff_exists]
|
||||
simp only [contrIndexList_areDualInSelf, not_exists]
|
||||
have h1 := (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)).2
|
||||
have h1' := Finset.disjoint_right.mp l.withDual_disjoint_withoutDual h1
|
||||
rw [mem_withDual_iff_exists] at h1'
|
||||
exact fun x => forall_not_of_not_exists h1'
|
||||
↑(l.withoutDualEquiv (Fin.cast (contrIndexList_length l) x))
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_withDual : l.contrIndexList.withDual = ∅ := by
|
||||
rw [Finset.eq_empty_iff_forall_not_mem]
|
||||
intro x
|
||||
simp [withDual]
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_areDualInSelf_false (i j : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.AreDualInSelf i j ↔ False := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => False.elim h)
|
||||
have h1 : i ∈ l.contrIndexList.withDual := by
|
||||
rw [@mem_withDual_iff_exists]
|
||||
exact Exists.intro j h
|
||||
simp_all
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_of_withDual_empty (h : l.withDual = ∅) : l.contrIndexList = l := by
|
||||
have h1 := l.withDual_union_withoutDual
|
||||
rw [h, Finset.empty_union] at h1
|
||||
apply ext
|
||||
rw [@List.ext_get_iff]
|
||||
change l.contrIndexList.length = l.length ∧ _
|
||||
rw [contrIndexList_length, h1]
|
||||
simp only [Finset.card_univ, Fintype.card_fin, List.get_eq_getElem, true_and]
|
||||
intro n h1' h2
|
||||
simp [contrIndexList_eq_contrIndexList']
|
||||
congr
|
||||
simp [withoutDualEquiv]
|
||||
simp [h1]
|
||||
rw [(Finset.orderEmbOfFin_unique' _
|
||||
(fun x => Finset.mem_univ ((Fin.castOrderIso _).toOrderEmbedding x))).symm]
|
||||
· exact Eq.symm (Nat.add_zero n)
|
||||
· rw [h1]
|
||||
exact Finset.card_fin l.length
|
||||
|
||||
lemma contrIndexList_contrIndexList : l.contrIndexList.contrIndexList = l.contrIndexList := by
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_getDualInOther?_self (i : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.getDualInOther? l.contrIndexList i = some i := by
|
||||
simp [getDualInOther?]
|
||||
rw [@Fin.find_eq_some_iff]
|
||||
simp [AreDualInOther]
|
||||
intro j hj
|
||||
have h1 : i = j := by
|
||||
by_contra hn
|
||||
have h : l.contrIndexList.AreDualInSelf i j := by
|
||||
simp only [AreDualInSelf]
|
||||
simp [hj]
|
||||
exact hn
|
||||
exact (contrIndexList_areDualInSelf_false l i j).mp h
|
||||
exact Fin.ge_of_eq (id (Eq.symm h1))
|
||||
|
||||
lemma mem_contrIndexList_countId {I : Index X} (h : I ∈ l.contrIndexList.val) :
|
||||
l.countId I = 1 := by
|
||||
simp only [contrIndexList, List.mem_filter, decide_eq_true_eq] at h
|
||||
exact h.2
|
||||
|
||||
lemma mem_contrIndexList_filter {I : Index X} (h : I ∈ l.contrIndexList.val) :
|
||||
l.val.filter (fun J => I.id = J.id) = [I] := by
|
||||
have h1 : (l.val.filter (fun J => I.id = J.id)).length = 1 := by
|
||||
rw [← List.countP_eq_length_filter]
|
||||
exact l.mem_contrIndexList_countId h
|
||||
have h2 : I ∈ l.val.filter (fun J => I.id = J.id) := by
|
||||
simp only [List.mem_filter, decide_True, and_true]
|
||||
simp only [contrIndexList, List.mem_filter, decide_eq_true_eq] at h
|
||||
exact h.1
|
||||
rw [List.length_eq_one] at h1
|
||||
obtain ⟨J, hJ⟩ := h1
|
||||
rw [hJ] at h2
|
||||
simp at h2
|
||||
subst h2
|
||||
exact hJ
|
||||
|
||||
lemma cons_contrIndexList_of_countId_eq_zero {I : Index X}
|
||||
(h : l.countId I = 0) :
|
||||
(l.cons I).contrIndexList = l.contrIndexList.cons I := by
|
||||
apply ext
|
||||
simp [contrIndexList, countId]
|
||||
rw [List.filter_cons_of_pos]
|
||||
· apply congrArg
|
||||
apply List.filter_congr
|
||||
intro J hJ
|
||||
simp only [decide_eq_decide]
|
||||
rw [countId, List.countP_eq_zero] at h
|
||||
simp only [decide_eq_true_eq] at h
|
||||
rw [List.countP_cons_of_neg]
|
||||
simp only [decide_eq_true_eq]
|
||||
exact fun a => h J hJ (id (Eq.symm a))
|
||||
· simp only [decide_True, List.countP_cons_of_pos, add_left_eq_self, decide_eq_true_eq]
|
||||
exact h
|
||||
|
||||
lemma cons_contrIndexList_of_countId_neq_zero {I : Index X} (h : l.countId I ≠ 0) :
|
||||
(l.cons I).contrIndexList.val = l.contrIndexList.val.filter (fun J => ¬ I.id = J.id) := by
|
||||
simp only [contrIndexList, countId, cons_val, decide_not, List.filter_filter, Bool.not_eq_true',
|
||||
decide_eq_false_iff_not, decide_eq_true_eq, Bool.decide_and]
|
||||
rw [List.filter_cons_of_neg]
|
||||
· apply List.filter_congr
|
||||
intro J hJ
|
||||
by_cases hI : I.id = J.id
|
||||
· simp only [hI, decide_True, List.countP_cons_of_pos, add_left_eq_self, Bool.not_true,
|
||||
Bool.false_and, decide_eq_false_iff_not, countId]
|
||||
rw [countId, hI] at h
|
||||
simp only [h, not_false_eq_true]
|
||||
· simp only [hI, decide_False, Bool.not_false, Bool.true_and, decide_eq_decide]
|
||||
rw [List.countP_cons_of_neg]
|
||||
simp only [decide_eq_true_eq]
|
||||
exact fun a => hI (id (Eq.symm a))
|
||||
· simp only [decide_True, List.countP_cons_of_pos, add_left_eq_self, decide_eq_true_eq]
|
||||
exact h
|
||||
|
||||
lemma mem_contrIndexList_countId_contrIndexList {I : Index X} (h : I ∈ l.contrIndexList.val) :
|
||||
l.contrIndexList.countId I = 1 := by
|
||||
trans (l.val.filter (fun J => I.id = J.id)).countP
|
||||
(fun i => l.val.countP (fun j => i.id = j.id) = 1)
|
||||
· rw [contrIndexList]
|
||||
simp only [countId]
|
||||
rw [List.countP_filter, List.countP_filter]
|
||||
simp only [decide_eq_true_eq, Bool.decide_and]
|
||||
congr
|
||||
funext a
|
||||
rw [Bool.and_comm]
|
||||
· rw [l.mem_contrIndexList_filter h, List.countP_cons_of_pos]
|
||||
· rfl
|
||||
· simp only [decide_eq_true_eq]
|
||||
exact mem_contrIndexList_countId l h
|
||||
|
||||
lemma countId_contrIndexList_zero_of_countId (I : Index X)
|
||||
(h : l.countId I = 0) : l.contrIndexList.countId I = 0 := by
|
||||
trans (l.val.filter (fun J => I.id = J.id)).countP
|
||||
(fun i => l.val.countP (fun j => i.id = j.id) = 1)
|
||||
· rw [contrIndexList]
|
||||
simp only [countId]
|
||||
rw [List.countP_filter, List.countP_filter]
|
||||
simp only [decide_eq_true_eq, Bool.decide_and]
|
||||
congr
|
||||
funext a
|
||||
rw [Bool.and_comm]
|
||||
· rw [countId_eq_length_filter, List.length_eq_zero] at h
|
||||
rw [h]
|
||||
simp only [List.countP_nil]
|
||||
|
||||
lemma countId_contrIndexList_le_one (I : Index X) :
|
||||
l.contrIndexList.countId I ≤ 1 := by
|
||||
by_cases h : l.contrIndexList.countId I = 0
|
||||
· simp [h]
|
||||
· obtain ⟨I', hI1, hI2⟩ := countId_neq_zero_mem l.contrIndexList I h
|
||||
rw [countId_congr l.contrIndexList hI2, mem_contrIndexList_countId_contrIndexList l hI1]
|
||||
|
||||
lemma countId_contrIndexList_eq_one_iff_countId_eq_one (I : Index X) :
|
||||
l.contrIndexList.countId I = 1 ↔ l.countId I = 1 := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· obtain ⟨I', hI1, hI2⟩ := countId_neq_zero_mem l.contrIndexList I (by omega)
|
||||
simp [contrIndexList] at hI1
|
||||
rw [countId_congr l hI2]
|
||||
exact hI1.2
|
||||
· obtain ⟨I', hI1, hI2⟩ := countId_neq_zero_mem l I (by omega)
|
||||
rw [countId_congr l hI2] at h
|
||||
rw [countId_congr _ hI2]
|
||||
refine mem_contrIndexList_countId_contrIndexList l ?_
|
||||
simp [contrIndexList]
|
||||
exact ⟨hI1, h⟩
|
||||
|
||||
lemma countId_contrIndexList_le_countId (I : Index X) :
|
||||
l.contrIndexList.countId I ≤ l.countId I := by
|
||||
by_cases h : l.contrIndexList.countId I = 0
|
||||
· exact StrictMono.minimal_preimage_bot (fun ⦃a b⦄ a => a) h (l.countId I)
|
||||
· have ho : l.contrIndexList.countId I = 1 := by
|
||||
have h1 := l.countId_contrIndexList_le_one I
|
||||
omega
|
||||
rw [ho]
|
||||
rw [countId_contrIndexList_eq_one_iff_countId_eq_one] at ho
|
||||
rw [ho]
|
||||
|
||||
/-!
|
||||
|
||||
## Append
|
||||
|
||||
-/
|
||||
|
||||
lemma contrIndexList_append_eq_filter : (l ++ l2).contrIndexList.val =
|
||||
l.contrIndexList.val.filter (fun I => l2.countId I = 0) ++
|
||||
l2.contrIndexList.val.filter (fun I => l.countId I = 0) := by
|
||||
simp [contrIndexList]
|
||||
congr 1
|
||||
· apply List.filter_congr
|
||||
intro I hI
|
||||
have hIz : l.countId I ≠ 0 := countId_mem l I hI
|
||||
have hx : l.countId I + l2.countId I = 1 ↔ (l2.countId I = 0 ∧ l.countId I = 1) := by
|
||||
omega
|
||||
simp only [hx, Bool.decide_and]
|
||||
· apply List.filter_congr
|
||||
intro I hI
|
||||
have hIz : l2.countId I ≠ 0 := countId_mem l2 I hI
|
||||
have hx : l.countId I + l2.countId I = 1 ↔ (l2.countId I = 1 ∧ l.countId I = 0) := by
|
||||
omega
|
||||
simp only [hx, Bool.decide_and]
|
||||
exact Bool.and_comm (decide (l2.countId I = 1)) (decide (l.countId I = 0))
|
||||
|
||||
/-!
|
||||
|
||||
## Splitting withUniqueDual
|
||||
|
||||
-/
|
||||
|
||||
instance (i j : Option (Fin l.length)) : Decidable (i < j) :=
|
||||
match i, j with
|
||||
| none, none => isFalse (fun a => a)
|
||||
| none, some _ => isTrue (by trivial)
|
||||
| some _, none => isFalse (fun a => a)
|
||||
| some i, some j => Fin.decLt i j
|
||||
|
||||
/-- The finite set of those indices of `l` which have a unique dual, and for which
|
||||
that dual is greater-then (determined by the ordering on `Fin`) then the index itself. -/
|
||||
def withUniqueDualLT : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => i < l.getDual? i) l.withUniqueDual
|
||||
|
||||
/-- The casting of an element of `withUniqueDualLT` to an element of `withUniqueDual`. -/
|
||||
def withUniqueDualLTToWithUniqueDual (i : l.withUniqueDualLT) : l.withUniqueDual :=
|
||||
⟨i.1, Finset.mem_of_mem_filter i.1 i.2⟩
|
||||
|
||||
instance : Coe l.withUniqueDualLT l.withUniqueDual where
|
||||
coe := l.withUniqueDualLTToWithUniqueDual
|
||||
|
||||
/-- The finite set of those indices of `l` which have a unique dual, and for which
|
||||
that dual is less-then (determined by the ordering on `Fin`) then the index itself. -/
|
||||
def withUniqueDualGT : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => ¬ i < l.getDual? i) l.withUniqueDual
|
||||
|
||||
/-- The casting of an element in `withUniqueDualGT` to an element of `withUniqueDual`. -/
|
||||
def withUniqueDualGTToWithUniqueDual (i : l.withUniqueDualGT) : l.withUniqueDual :=
|
||||
⟨i.1, Finset.mem_of_mem_filter _ i.2⟩
|
||||
|
||||
instance : Coe l.withUniqueDualGT l.withUniqueDual where
|
||||
coe := l.withUniqueDualGTToWithUniqueDual
|
||||
|
||||
lemma withUniqueDualLT_disjoint_withUniqueDualGT :
|
||||
Disjoint l.withUniqueDualLT l.withUniqueDualGT := by
|
||||
rw [Finset.disjoint_iff_inter_eq_empty]
|
||||
exact @Finset.filter_inter_filter_neg_eq (Fin l.length) _ _ _ _ _
|
||||
|
||||
lemma withUniqueDualLT_union_withUniqueDualGT :
|
||||
l.withUniqueDualLT ∪ l.withUniqueDualGT = l.withUniqueDual :=
|
||||
Finset.filter_union_filter_neg_eq _ _
|
||||
|
||||
/-! TODO: Replace with a mathlib lemma. -/
|
||||
lemma option_not_lt (i j : Option (Fin l.length)) : i < j → i ≠ j → ¬ j < i := by
|
||||
match i, j with
|
||||
| none, none =>
|
||||
exact fun a _ _ => a
|
||||
| none, some k =>
|
||||
exact fun _ _ a => a
|
||||
| some i, none =>
|
||||
exact fun h _ _ => h
|
||||
| some i, some j =>
|
||||
intro h h'
|
||||
simp_all
|
||||
change i < j at h
|
||||
change ¬ j < i
|
||||
exact Fin.lt_asymm h
|
||||
|
||||
/-! TODO: Replace with a mathlib lemma. -/
|
||||
lemma lt_option_of_not (i j : Option (Fin l.length)) : ¬ j < i → i ≠ j → i < j := by
|
||||
match i, j with
|
||||
| none, none =>
|
||||
exact fun a b => a (a (a (b rfl)))
|
||||
| none, some k =>
|
||||
exact fun _ _ => trivial
|
||||
| some i, none =>
|
||||
exact fun a _ => a trivial
|
||||
| some i, some j =>
|
||||
intro h h'
|
||||
simp_all
|
||||
change ¬ j < i at h
|
||||
change i < j
|
||||
omega
|
||||
|
||||
/-- The equivalence between `l.withUniqueDualLT` and `l.withUniqueDualGT` obtained by
|
||||
taking an index to its dual. -/
|
||||
def withUniqueDualLTEquivGT : l.withUniqueDualLT ≃ l.withUniqueDualGT where
|
||||
toFun i := ⟨l.getDualEquiv i, by
|
||||
have hi := i.2
|
||||
simp only [withUniqueDualGT, Finset.mem_filter, Finset.coe_mem, true_and]
|
||||
simp only [getDualEquiv, Equiv.coe_fn_mk, Option.some_get, Finset.coe_mem,
|
||||
getDual?_getDual?_get_of_withUniqueDual]
|
||||
simp only [withUniqueDualLT, Finset.mem_filter] at hi
|
||||
apply option_not_lt
|
||||
· simpa [withUniqueDualLTToWithUniqueDual] using hi.2
|
||||
· exact Ne.symm (getDual?_neq_self l i)⟩
|
||||
invFun i := ⟨l.getDualEquiv.symm i, by
|
||||
have hi := i.2
|
||||
simp only [withUniqueDualLT, Finset.mem_filter, Finset.coe_mem, true_and, gt_iff_lt]
|
||||
simp only [getDualEquiv, Equiv.coe_fn_symm_mk, Option.some_get, Finset.coe_mem,
|
||||
getDual?_getDual?_get_of_withUniqueDual]
|
||||
simp only [withUniqueDualGT, Finset.mem_filter] at hi
|
||||
apply lt_option_of_not
|
||||
· simpa [withUniqueDualLTToWithUniqueDual] using hi.2
|
||||
· exact (getDual?_neq_self l i)⟩
|
||||
left_inv x := SetCoe.ext (by simp [withUniqueDualGTToWithUniqueDual,
|
||||
withUniqueDualLTToWithUniqueDual])
|
||||
right_inv x := SetCoe.ext (by simp [withUniqueDualGTToWithUniqueDual,
|
||||
withUniqueDualLTToWithUniqueDual])
|
||||
|
||||
/-- An equivalence from `l.withUniqueDualLT ⊕ l.withUniqueDualLT` to `l.withUniqueDual`.
|
||||
The first `l.withUniqueDualLT` are taken to themselves, whilst the second copy are
|
||||
taken to their dual. -/
|
||||
def withUniqueLTGTEquiv : l.withUniqueDualLT ⊕ l.withUniqueDualLT ≃ l.withUniqueDual := by
|
||||
apply (Equiv.sumCongr (Equiv.refl _) l.withUniqueDualLTEquivGT).trans
|
||||
apply (Equiv.Finset.union _ _ l.withUniqueDualLT_disjoint_withUniqueDualGT).trans
|
||||
apply (Equiv.subtypeEquivRight (by simp only [l.withUniqueDualLT_union_withUniqueDualGT,
|
||||
implies_true]))
|
||||
|
||||
/-!
|
||||
|
||||
## withUniqueDualInOther equal univ
|
||||
|
||||
-/
|
||||
|
||||
/-! TODO: There is probably a better place for this section. -/
|
||||
|
||||
lemma withUniqueDualInOther_eq_univ_fst_withDual_empty
|
||||
(h : l.withUniqueDualInOther l2 = Finset.univ) : l.withDual = ∅ := by
|
||||
rw [@Finset.eq_empty_iff_forall_not_mem]
|
||||
intro x
|
||||
have hx : x ∈ l.withUniqueDualInOther l2 := by
|
||||
rw [h]
|
||||
exact Finset.mem_univ x
|
||||
rw [withUniqueDualInOther] at hx
|
||||
simp only [mem_withDual_iff_isSome, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, mem_withInDualOther_iff_isSome, Finset.mem_filter, Finset.mem_univ,
|
||||
true_and] at hx
|
||||
simpa using hx.1
|
||||
|
||||
lemma withUniqueDualInOther_eq_univ_fst_eq_contrIndexList
|
||||
(h : l.withUniqueDualInOther l2 = Finset.univ) :
|
||||
l = l.contrIndexList := by
|
||||
refine Eq.symm (contrIndexList_of_withDual_empty l ?h)
|
||||
exact withUniqueDualInOther_eq_univ_fst_withDual_empty l l2 h
|
||||
|
||||
lemma withUniqueDualInOther_eq_univ_symm (hl : l.length = l2.length)
|
||||
(h : l.withUniqueDualInOther l2 = Finset.univ) :
|
||||
l2.withUniqueDualInOther l = Finset.univ := by
|
||||
let S' : Finset (Fin l2.length) :=
|
||||
Finset.map ⟨Subtype.val, Subtype.val_injective⟩
|
||||
(Equiv.finsetCongr
|
||||
(l.getDualInOtherEquiv l2) Finset.univ)
|
||||
have hSCard : S'.card = l2.length := by
|
||||
rw [Finset.card_map]
|
||||
simp only [Finset.univ_eq_attach, Equiv.finsetCongr_apply, Finset.card_map, Finset.card_attach]
|
||||
rw [h, ← hl]
|
||||
exact Finset.card_fin l.length
|
||||
have hsCardUn : S'.card = (@Finset.univ (Fin l2.length)).card := by
|
||||
rw [hSCard]
|
||||
exact Eq.symm (Finset.card_fin l2.length)
|
||||
have hS'Eq : S' = (l2.withUniqueDualInOther l) := by
|
||||
rw [@Finset.ext_iff]
|
||||
intro a
|
||||
simp only [S']
|
||||
simp
|
||||
rw [hS'Eq] at hsCardUn
|
||||
exact (Finset.card_eq_iff_eq_univ (l2.withUniqueDualInOther l)).mp hsCardUn
|
||||
|
||||
lemma withUniqueDualInOther_eq_univ_contr_refl :
|
||||
l.contrIndexList.withUniqueDualInOther l.contrIndexList = Finset.univ := by
|
||||
rw [@Finset.eq_univ_iff_forall]
|
||||
intro x
|
||||
simp only [withUniqueDualInOther, mem_withDual_iff_isSome,
|
||||
Option.isSome_none, Bool.false_eq_true, not_false_eq_true, mem_withInDualOther_iff_isSome,
|
||||
getDualInOther?_self_isSome, true_and, Finset.mem_filter, Finset.mem_univ]
|
||||
simp only [contrIndexList_getDual?, Option.isSome_none, Bool.false_eq_true, not_false_eq_true,
|
||||
contrIndexList_getDualInOther?_self, Option.some.injEq, true_and]
|
||||
intro j hj
|
||||
have h1 : j = x := by
|
||||
by_contra hn
|
||||
have hj : l.contrIndexList.AreDualInSelf x j := by
|
||||
simp [AreDualInOther] at hj
|
||||
simp only [AreDualInSelf, ne_eq, contrIndexList_idMap, hj, and_true]
|
||||
exact fun a => hn (id (Eq.symm a))
|
||||
exact (contrIndexList_areDualInSelf_false l x j).mp hj
|
||||
exact h1
|
||||
|
||||
lemma withUniqueDualInOther_eq_univ_trans (h : l.withUniqueDualInOther l2 = Finset.univ)
|
||||
(h' : l2.withUniqueDualInOther l3 = Finset.univ) :
|
||||
l.withUniqueDualInOther l3 = Finset.univ := by
|
||||
rw [Finset.eq_univ_iff_forall]
|
||||
intro i
|
||||
simp only [withUniqueDualInOther, mem_withDual_iff_isSome, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, mem_withInDualOther_iff_isSome, Finset.mem_filter, Finset.mem_univ,
|
||||
true_and]
|
||||
have hi : i ∈ l.withUniqueDualInOther l2 := by
|
||||
rw [h]
|
||||
exact Finset.mem_univ i
|
||||
simp only [withUniqueDualInOther, mem_withDual_iff_isSome, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, mem_withInDualOther_iff_isSome, Finset.mem_filter, Finset.mem_univ,
|
||||
true_and] at hi
|
||||
have hi2 : ((l.getDualInOther? l2 i).get hi.2.1) ∈ l2.withUniqueDualInOther l3 := by
|
||||
rw [h']
|
||||
exact Finset.mem_univ ((l.getDualInOther? l2 i).get hi.right.left)
|
||||
simp only [withUniqueDualInOther, mem_withDual_iff_isSome, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, mem_withInDualOther_iff_isSome, Finset.mem_filter, Finset.mem_univ,
|
||||
true_and] at hi2
|
||||
apply And.intro hi.1
|
||||
apply And.intro
|
||||
· rw [@getDualInOther?_isSome_iff_exists]
|
||||
use (l2.getDualInOther? l3 ((l.getDualInOther? l2 i).get hi.2.1)).get hi2.2.1
|
||||
simp only [AreDualInOther, getDualInOther?_id]
|
||||
intro j hj
|
||||
have hj' : j = (l2.getDualInOther? l3 ((l.getDualInOther? l2 i).get hi.2.1)).get hi2.2.1 := by
|
||||
rw [← eq_getDualInOther?_get_of_withUniqueDualInOther_iff]
|
||||
simpa only [AreDualInOther, getDualInOther?_id] using hj
|
||||
rw [h']
|
||||
exact Finset.mem_univ ((l.getDualInOther? l2 i).get hi.right.left)
|
||||
have hs : (l.getDualInOther? l3 i).isSome := by
|
||||
rw [@getDualInOther?_isSome_iff_exists]
|
||||
exact Exists.intro j hj
|
||||
have hs' : (l.getDualInOther? l3 i).get hs = (l2.getDualInOther? l3
|
||||
((l.getDualInOther? l2 i).get hi.2.1)).get hi2.2.1 := by
|
||||
rw [← eq_getDualInOther?_get_of_withUniqueDualInOther_iff]
|
||||
simp only [AreDualInOther, getDualInOther?_id]
|
||||
rw [h']
|
||||
exact Finset.mem_univ ((l.getDualInOther? l2 i).get hi.right.left)
|
||||
rw [← hj'] at hs'
|
||||
rw [← hs']
|
||||
exact Eq.symm (Option.eq_some_of_isSome hs)
|
||||
|
||||
lemma withUniqueDualInOther_eq_univ_iff_forall :
|
||||
l.withUniqueDualInOther l2 = Finset.univ ↔
|
||||
∀ (x : Fin l.length), l.getDual? x = none ∧ (l.getDualInOther? l2 x).isSome = true ∧
|
||||
∀ (j : Fin l2.length), l.AreDualInOther l2 x j → some j = l.getDualInOther? l2 x := by
|
||||
rw [Finset.eq_univ_iff_forall]
|
||||
simp only [withUniqueDualInOther, mem_withDual_iff_isSome, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, mem_withInDualOther_iff_isSome, Finset.mem_filter, Finset.mem_univ,
|
||||
true_and]
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -1,519 +0,0 @@
|
|||
/-
|
||||
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.AreDual
|
||||
import Mathlib.Algebra.Order.Ring.Nat
|
||||
/-!
|
||||
|
||||
# Getting dual index
|
||||
|
||||
Using the option-monad we define two functions:
|
||||
- For a list of indices `l₁` the function `getDual?` takes in an index `i` in `l₁` and retruns
|
||||
the the first index in `l₁` dual to `i`. If no such index exists, it returns `none`.
|
||||
- For two lists of indices `l₁` and `l₂` the function `getDualInOther?` takes in an index `i`
|
||||
in `l₁` and returns the first index in `l₂` dual to `i`. If no such index exists,
|
||||
it returns `none`.
|
||||
|
||||
For example, given the lists `l₁ := ['ᵘ¹', 'ᵘ²', 'ᵤ₁', 'ᵘ¹']`, we have
|
||||
- `getDual? 0 = some 2`, `getDual? 1 = none`, `getDual? 2 = some 0`, `getDual? 3 = some 0`.
|
||||
|
||||
Given the lists `l₁ := ['ᵘ¹', 'ᵘ²', 'ᵤ₁', 'ᵘ¹']` and `l₂ := ['ᵘ³', 'ᵘ²', 'ᵘ⁴', 'ᵤ₂']`, we have
|
||||
- `l₁.getDualInOther? l₂ 0 = none`, `l₁.getDualInOther? l₂ 1 = some 1`,
|
||||
`l₁.getDualInOther? l₂ 2 = none`, `l₁.getDualInOther? l₂ 3 = none`.
|
||||
|
||||
We prove some basic properties of `getDual?` and `getDualInOther?`. In particular,
|
||||
we prove lemmas related to how `getDual?` and `getDualInOther?` behave when we appending
|
||||
two index lists.
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 : IndexList X)
|
||||
|
||||
/-!
|
||||
|
||||
## The getDual? Function
|
||||
|
||||
-/
|
||||
|
||||
/-- Given an `i`, if a dual exists in the same list,
|
||||
outputs the first such dual, otherwise outputs `none`. -/
|
||||
def getDual? (i : Fin l.length) : Option (Fin l.length) :=
|
||||
Fin.find (fun j => l.AreDualInSelf i j)
|
||||
|
||||
/-- Given an `i`, if a dual exists in the other list,
|
||||
outputs the first such dual, otherwise outputs `none`. -/
|
||||
def getDualInOther? (i : Fin l.length) : Option (Fin l2.length) :=
|
||||
Fin.find (fun j => l.AreDualInOther l2 i j)
|
||||
|
||||
/-!
|
||||
|
||||
## Basic properties of getDual?
|
||||
|
||||
-/
|
||||
|
||||
lemma getDual?_isSome_iff_exists (i : Fin l.length) :
|
||||
(l.getDual? i).isSome ↔ ∃ j, l.AreDualInSelf i j := by
|
||||
rw [getDual?, Fin.isSome_find_iff]
|
||||
|
||||
lemma getDual?_of_areDualInSelf (h : l.AreDualInSelf i j) :
|
||||
l.getDual? j = i ∨ l.getDual? i = j ∨ l.getDual? j = l.getDual? i := by
|
||||
have h3 : (l.getDual? i).isSome := by
|
||||
simpa [getDual?, Fin.isSome_find_iff] using ⟨j, h⟩
|
||||
obtain ⟨k, hk⟩ := Option.isSome_iff_exists.mp h3
|
||||
rw [hk]
|
||||
rw [getDual?, Fin.find_eq_some_iff] at hk
|
||||
by_cases hik : i < k
|
||||
· apply Or.inl
|
||||
rw [getDual?, Fin.find_eq_some_iff]
|
||||
apply And.intro h.symm
|
||||
intro k' hk'
|
||||
by_cases hik' : i = k'
|
||||
· exact Fin.ge_of_eq (id (Eq.symm hik'))
|
||||
· have hik'' : l.AreDualInSelf i k' := by
|
||||
simp [AreDualInSelf, hik']
|
||||
simp_all [AreDualInSelf]
|
||||
have hk'' := hk.2 k' hik''
|
||||
exact (lt_of_lt_of_le hik hk'').le
|
||||
· by_cases hjk : j ≤ k
|
||||
· apply Or.inr
|
||||
apply Or.inl
|
||||
have hj := hk.2 j h
|
||||
simp only [Option.some.injEq]
|
||||
exact Fin.le_antisymm hj hjk
|
||||
· apply Or.inr
|
||||
apply Or.inr
|
||||
rw [getDual?, Fin.find_eq_some_iff]
|
||||
apply And.intro
|
||||
· simp_all [AreDualInSelf]
|
||||
exact Fin.ne_of_gt hjk
|
||||
intro k' hk'
|
||||
by_cases hik' : i = k'
|
||||
· subst hik'
|
||||
exact Lean.Omega.Fin.le_of_not_lt hik
|
||||
· have hik'' : l.AreDualInSelf i k' := by
|
||||
simp [AreDualInSelf, hik']
|
||||
simp_all [AreDualInSelf]
|
||||
exact hk.2 k' hik''
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_neq_self (i : Fin l.length) : ¬ l.getDual? i = some i := by
|
||||
intro h
|
||||
simp [getDual?] at h
|
||||
rw [Fin.find_eq_some_iff] at h
|
||||
simp [AreDualInSelf] at h
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_get_neq_self (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
¬ (l.getDual? i).get h = i := by
|
||||
have h1 := l.getDual?_neq_self i
|
||||
by_contra hn
|
||||
have h' : l.getDual? i = some i := by
|
||||
nth_rewrite 2 [← hn]
|
||||
exact Option.eq_some_of_isSome h
|
||||
exact h1 h'
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_get_id (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
l.idMap ((l.getDual? i).get h) = l.idMap i := by
|
||||
have h1 : l.getDual? i = some ((l.getDual? i).get h) := Option.eq_some_of_isSome h
|
||||
nth_rewrite 1 [getDual?] at h1
|
||||
rw [Fin.find_eq_some_iff] at h1
|
||||
simp [AreDualInSelf] at h1
|
||||
exact h1.1.2.symm
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_get_areDualInSelf (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
l.AreDualInSelf ((l.getDual? i).get h) i := by
|
||||
simp [AreDualInSelf]
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_areDualInSelf_get (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
l.AreDualInSelf i ((l.getDual? i).get h) :=
|
||||
AreDualInSelf.symm (getDual?_get_areDualInSelf l i h)
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_getDual?_get_isSome (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
(l.getDual? ((l.getDual? i).get h)).isSome := by
|
||||
rw [getDual?, Fin.isSome_find_iff]
|
||||
exact ⟨i, getDual?_get_areDualInSelf l i h⟩
|
||||
|
||||
/-!
|
||||
|
||||
## Basic properties of getDualInOther?
|
||||
|
||||
-/
|
||||
|
||||
lemma getDualInOther?_isSome_iff_exists (i : Fin l.length) :
|
||||
(l.getDualInOther? l2 i).isSome ↔ ∃ j, l.AreDualInOther l2 i j := by
|
||||
rw [getDualInOther?, Fin.isSome_find_iff]
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_id (i : Fin l.length) (h : (l.getDualInOther? l2 i).isSome) :
|
||||
l2.idMap ((l.getDualInOther? l2 i).get h) = l.idMap i := by
|
||||
have h1 : l.getDualInOther? l2 i = some ((l.getDualInOther? l2 i).get h) :=
|
||||
Option.eq_some_of_isSome h
|
||||
nth_rewrite 1 [getDualInOther?] at h1
|
||||
rw [Fin.find_eq_some_iff] at h1
|
||||
simp [AreDualInOther] at h1
|
||||
exact h1.1.symm
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_get_areDualInOther (i : Fin l.length) (h : (l.getDualInOther? l2 i).isSome) :
|
||||
l2.AreDualInOther l ((l.getDualInOther? l2 i).get h) i := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_areDualInOther_get (i : Fin l.length) (h : (l.getDualInOther? l2 i).isSome) :
|
||||
l.AreDualInOther l2 i ((l.getDualInOther? l2 i).get h) :=
|
||||
AreDualInOther.symm (getDualInOther?_get_areDualInOther l l2 i h)
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_getDualInOther?_get_isSome (i : Fin l.length)
|
||||
(h : (l.getDualInOther? l2 i).isSome) :
|
||||
(l2.getDualInOther? l ((l.getDualInOther? l2 i).get h)).isSome := by
|
||||
rw [getDualInOther?, Fin.isSome_find_iff]
|
||||
exact ⟨i, getDualInOther?_get_areDualInOther l l2 i h⟩
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_self_isSome (i : Fin l.length) :
|
||||
(l.getDualInOther? l i).isSome := by
|
||||
simp [getDualInOther?]
|
||||
rw [@Fin.isSome_find_iff]
|
||||
exact ⟨i, rfl⟩
|
||||
|
||||
/-!
|
||||
|
||||
## Append properties of getDual?
|
||||
|
||||
-/
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_isSome_append_inl_iff (i : Fin l.length) :
|
||||
((l ++ l2).getDual? (appendEquiv (Sum.inl i))).isSome ↔
|
||||
(l.getDual? i).isSome ∨ (l.getDualInOther? l2 i).isSome := by
|
||||
rw [getDual?_isSome_iff_exists, getDual?_isSome_iff_exists, getDualInOther?_isSome_iff_exists]
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· obtain ⟨j, hj⟩ := h
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
exact Or.inl ⟨k, AreDualInSelf.append_inl_inl.mp hj⟩
|
||||
| Sum.inr k =>
|
||||
exact Or.inr ⟨k, by simpa only [AreDualInSelf.append_inl_inr] using hj⟩
|
||||
· cases' h with h h <;>
|
||||
obtain ⟨j, hj⟩ := h
|
||||
· exact ⟨appendEquiv (Sum.inl j), AreDualInSelf.append_inl_inl.mpr hj⟩
|
||||
· use appendEquiv (Sum.inr j)
|
||||
simpa only [AreDualInSelf.append_inl_inr] using hj
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_isSome_append_inr_iff (i : Fin l2.length) :
|
||||
((l ++ l2).getDual? (appendEquiv (Sum.inr i))).isSome ↔
|
||||
(l2.getDual? i).isSome ∨ (l2.getDualInOther? l i).isSome := by
|
||||
rw [getDual?_isSome_iff_exists, getDual?_isSome_iff_exists, getDualInOther?_isSome_iff_exists]
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· obtain ⟨j, hj⟩ := h
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
exact Or.inr ⟨k, by simpa using hj⟩
|
||||
| Sum.inr k =>
|
||||
exact Or.inl ⟨k, (AreDualInSelf.append_inr_inr l l2 i k).mp hj⟩
|
||||
· cases' h with h h <;>
|
||||
obtain ⟨j, hj⟩ := h
|
||||
· exact ⟨appendEquiv (Sum.inr j), (AreDualInSelf.append_inr_inr l l2 i j).mpr hj⟩
|
||||
· use appendEquiv (Sum.inl j)
|
||||
simpa only [AreDualInSelf.append_inr_inl] using hj
|
||||
|
||||
lemma getDual?_isSome_append_symm (i : Fin l.length) :
|
||||
((l ++ l2).getDual? (appendEquiv (Sum.inl i))).isSome ↔
|
||||
((l2 ++ l).getDual? (appendEquiv (Sum.inr i))).isSome := by
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_eq_none_append_inl_iff (i : Fin l.length) :
|
||||
(l ++ l2).getDual? (appendEquiv (Sum.inl i)) = none ↔
|
||||
l.getDual? i = none ∧ l.getDualInOther? l2 i = none := by
|
||||
apply Iff.intro
|
||||
· intro h
|
||||
have h1 := (l.getDual?_isSome_append_inl_iff l2 i).mpr.mt
|
||||
simp only [not_or, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, imp_self] at h1
|
||||
exact h1 h
|
||||
· intro h
|
||||
have h1 := (l.getDual?_isSome_append_inl_iff l2 i).mp.mt
|
||||
simp only [not_or, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, imp_self] at h1
|
||||
exact h1 h
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_eq_none_append_inr_iff (i : Fin l2.length) :
|
||||
(l ++ l2).getDual? (appendEquiv (Sum.inr i)) = none ↔
|
||||
(l2.getDual? i = none ∧ l2.getDualInOther? l i = none) := by
|
||||
apply Iff.intro
|
||||
· intro h
|
||||
have h1 := (l.getDual?_isSome_append_inr_iff l2 i).mpr.mt
|
||||
simp only [not_or, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, imp_self] at h1
|
||||
exact h1 h
|
||||
· intro h
|
||||
have h1 := (l.getDual?_isSome_append_inr_iff l2 i).mp.mt
|
||||
simp only [not_or, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, imp_self] at h1
|
||||
exact h1 h
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_append_inl_of_getDual?_isSome (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
(l ++ l2).getDual? (appendEquiv (Sum.inl i)) =
|
||||
some (appendEquiv (Sum.inl ((l.getDual? i).get h))) := by
|
||||
rw [getDual?, Fin.find_eq_some_iff, AreDualInSelf.append_inl_inl]
|
||||
apply And.intro (getDual?_get_areDualInSelf l i h).symm
|
||||
intro j hj
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
simp only [appendEquiv, Equiv.trans_apply, finSumFinEquiv_apply_left, RelIso.coe_fn_toEquiv,
|
||||
Fin.castOrderIso_apply, ge_iff_le]
|
||||
rw [Fin.le_def]
|
||||
have h2 : l.getDual? i = some (((l.getDual? i).get h)) := Option.eq_some_of_isSome h
|
||||
nth_rewrite 1 [getDual?] at h2
|
||||
rw [Fin.find_eq_some_iff] at h2
|
||||
exact h2.2 k (AreDualInSelf.append_inl_inl.mp hj)
|
||||
| Sum.inr k =>
|
||||
simp only [appendEquiv, Equiv.trans_apply, finSumFinEquiv_apply_left, RelIso.coe_fn_toEquiv,
|
||||
Fin.castOrderIso_apply, finSumFinEquiv_apply_right, ge_iff_le]
|
||||
rw [Fin.le_def]
|
||||
simp only [length, append_val, RelIso.coe_fn_toEquiv, Fin.castOrderIso_apply, Fin.coe_cast,
|
||||
Fin.coe_castAdd, Fin.coe_natAdd]
|
||||
omega
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_inl_of_getDual?_isNone_getDualInOther?_isSome (i : Fin l.length)
|
||||
(hi : (l.getDual? i).isNone) (h : (l.getDualInOther? l2 i).isSome) :
|
||||
(l ++ l2).getDual? (appendEquiv (Sum.inl i)) = some
|
||||
(appendEquiv (Sum.inr ((l.getDualInOther? l2 i).get h))) := by
|
||||
rw [getDual?, Fin.find_eq_some_iff, AreDualInSelf.append_inl_inr]
|
||||
apply And.intro (getDualInOther?_areDualInOther_get l l2 i h)
|
||||
intro j hj
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
rw [AreDualInSelf.append_inl_inl] at hj
|
||||
simp only [getDual?, Finset.mem_filter, Finset.mem_univ, true_and, Bool.not_eq_true,
|
||||
Option.not_isSome, Option.isNone_iff_eq_none, Fin.find_eq_none_iff] at hi
|
||||
exact False.elim (hi k hj)
|
||||
| Sum.inr k =>
|
||||
simp [appendEquiv]
|
||||
rw [Fin.le_def]
|
||||
have h1 : l.getDualInOther? l2 i = some (((l.getDualInOther? l2 i).get h)) :=
|
||||
Option.eq_some_of_isSome h
|
||||
nth_rewrite 1 [getDualInOther?] at h1
|
||||
rw [Fin.find_eq_some_iff] at h1
|
||||
simp only [length, append_val, RelIso.coe_fn_toEquiv, Fin.castOrderIso_apply, Fin.coe_cast,
|
||||
Fin.coe_natAdd, add_le_add_iff_left, Fin.val_fin_le, ge_iff_le]
|
||||
refine h1.2 k (by simpa using hj)
|
||||
|
||||
lemma getDual?_append_inl (i : Fin l.length) : (l ++ l2).getDual? (appendEquiv (Sum.inl i)) =
|
||||
Option.or (Option.map (appendEquiv ∘ Sum.inl) (l.getDual? i))
|
||||
(Option.map (appendEquiv ∘ Sum.inr) (l.getDualInOther? l2 i)) := by
|
||||
by_cases h : (l.getDual? i).isSome
|
||||
· simp_all
|
||||
rw [congrArg (Option.map (appendEquiv ∘ Sum.inl)) (Option.eq_some_of_isSome h)]
|
||||
rfl
|
||||
by_cases ho : (l.getDualInOther? l2 i).isSome
|
||||
· simp_all
|
||||
rw [congrArg (Option.map (appendEquiv ∘ Sum.inr)) (Option.eq_some_of_isSome ho)]
|
||||
rfl
|
||||
simp_all
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_append_inr_getDualInOther?_isSome (i : Fin l2.length)
|
||||
(h : (l2.getDualInOther? l i).isSome) :
|
||||
(l ++ l2).getDual? (appendEquiv (Sum.inr i)) =
|
||||
some (appendEquiv (Sum.inl ((l2.getDualInOther? l i).get h))) := by
|
||||
rw [getDual?, Fin.find_eq_some_iff, AreDualInSelf.append_inr_inl]
|
||||
apply And.intro (getDualInOther?_areDualInOther_get l2 l i h)
|
||||
intro j hj
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
simp only [appendEquiv, Equiv.trans_apply, finSumFinEquiv_apply_left, RelIso.coe_fn_toEquiv,
|
||||
Fin.castOrderIso_apply, ge_iff_le]
|
||||
rw [Fin.le_def]
|
||||
have h1 : l2.getDualInOther? l i = some (((l2.getDualInOther? l i).get h)) :=
|
||||
Option.eq_some_of_isSome h
|
||||
nth_rewrite 1 [getDualInOther?] at h1
|
||||
rw [Fin.find_eq_some_iff] at h1
|
||||
simp only [Fin.coe_cast, Fin.coe_natAdd, add_le_add_iff_left, Fin.val_fin_le, ge_iff_le]
|
||||
refine h1.2 k (by simpa using hj)
|
||||
| Sum.inr k =>
|
||||
simp only [appendEquiv, Equiv.trans_apply, finSumFinEquiv_apply_left, RelIso.coe_fn_toEquiv,
|
||||
Fin.castOrderIso_apply, finSumFinEquiv_apply_right, ge_iff_le]
|
||||
rw [Fin.le_def]
|
||||
simp only [length, append_val, RelIso.coe_fn_toEquiv, Fin.castOrderIso_apply, Fin.coe_cast,
|
||||
Fin.coe_castAdd, Fin.coe_natAdd]
|
||||
omega
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_inr_getDualInOther?_isNone_getDual?_isSome (i : Fin l2.length)
|
||||
(h : (l2.getDualInOther? l i).isNone) (hi : (l2.getDual? i).isSome) :
|
||||
(l ++ l2).getDual? (appendEquiv (Sum.inr i)) = some
|
||||
(appendEquiv (Sum.inr ((l2.getDual? i).get hi))) := by
|
||||
rw [getDual?, Fin.find_eq_some_iff, AreDualInSelf.append_inr_inr]
|
||||
apply And.intro (getDual?_areDualInSelf_get l2 i hi)
|
||||
intro j hj
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
simp at hj
|
||||
simp only [getDualInOther?, Option.isNone_iff_eq_none, Fin.find_eq_none_iff] at h
|
||||
exact False.elim (h k hj)
|
||||
| Sum.inr k =>
|
||||
simp [appendEquiv, IndexList.length]
|
||||
rw [Fin.le_def]
|
||||
simp only [Fin.coe_cast, Fin.coe_natAdd, add_le_add_iff_left, Fin.val_fin_le]
|
||||
have h2 : l2.getDual? i = some ((l2.getDual? i).get hi) := Option.eq_some_of_isSome hi
|
||||
nth_rewrite 1 [getDual?] at h2
|
||||
rw [Fin.find_eq_some_iff] at h2
|
||||
simp only [AreDualInSelf.append_inr_inr] at hj
|
||||
exact h2.2 k hj
|
||||
|
||||
lemma getDual?_append_inr (i : Fin l2.length) :
|
||||
(l ++ l2).getDual? (appendEquiv (Sum.inr i)) =
|
||||
Option.or (Option.map (appendEquiv ∘ Sum.inl) (l2.getDualInOther? l i))
|
||||
(Option.map (appendEquiv ∘ Sum.inr) (l2.getDual? i)) := by
|
||||
by_cases h : (l2.getDualInOther? l i).isSome
|
||||
· simp_all
|
||||
rw [congrArg (Option.map (appendEquiv ∘ Sum.inl)) (Option.eq_some_of_isSome h)]
|
||||
rfl
|
||||
by_cases ho : (l2.getDual? i).isSome
|
||||
· simp_all
|
||||
rw [congrArg (Option.map (appendEquiv ∘ Sum.inr)) (Option.eq_some_of_isSome ho)]
|
||||
rfl
|
||||
simp_all
|
||||
|
||||
/-!
|
||||
|
||||
## Properties of getDualInOther? and append
|
||||
|
||||
-/
|
||||
variable (l3 : IndexList X)
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_append_of_inl (i : Fin l.length) :
|
||||
(l ++ l2).getDualInOther? l3 (appendEquiv (Sum.inl i)) = l.getDualInOther? l3 i := by
|
||||
simp [getDualInOther?]
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_append_of_inr (i : Fin l2.length) :
|
||||
(l ++ l2).getDualInOther? l3 (appendEquiv (Sum.inr i)) = l2.getDualInOther? l3 i := by
|
||||
simp [getDualInOther?]
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_isSome_of_append_iff (i : Fin l.length) :
|
||||
(l.getDualInOther? (l2 ++ l3) i).isSome ↔
|
||||
(l.getDualInOther? l2 i).isSome ∨ (l.getDualInOther? l3 i).isSome := by
|
||||
rw [getDualInOther?_isSome_iff_exists, getDualInOther?_isSome_iff_exists,
|
||||
getDualInOther?_isSome_iff_exists]
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· obtain ⟨j, hj⟩ := h
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
exact Or.inl ⟨k, by simpa using hj⟩
|
||||
| Sum.inr k =>
|
||||
exact Or.inr ⟨k, (AreDualInOther.of_append_inr i k).mp hj⟩
|
||||
· cases' h with h h <;>
|
||||
obtain ⟨j, hj⟩ := h
|
||||
· use appendEquiv (Sum.inl j)
|
||||
exact (AreDualInOther.of_append_inl i j).mpr hj
|
||||
· use appendEquiv (Sum.inr j)
|
||||
exact (AreDualInOther.of_append_inr i j).mpr hj
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_eq_none_of_append_iff (i : Fin l.length) :
|
||||
(l.getDualInOther? (l2 ++ l3) i) = none ↔
|
||||
(l.getDualInOther? l2 i) = none ∧ (l.getDualInOther? l3 i) = none := by
|
||||
apply Iff.intro
|
||||
· intro h
|
||||
have h1 := (l.getDualInOther?_isSome_of_append_iff l2 l3 i).mpr.mt
|
||||
simp only [not_or, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, imp_self] at h1
|
||||
exact h1 h
|
||||
· intro h
|
||||
have h1 := (l.getDualInOther?_isSome_of_append_iff l2 l3 i).mp.mt
|
||||
simp only [not_or, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none, imp_self] at h1
|
||||
exact h1 h
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_of_append_of_isSome (i : Fin l.length)
|
||||
(hi : (l.getDualInOther? l2 i).isSome) : l.getDualInOther? (l2 ++ l3) i =
|
||||
some (appendEquiv (Sum.inl ((l.getDualInOther? l2 i).get hi))) := by
|
||||
rw [getDualInOther?, Fin.find_eq_some_iff, AreDualInOther.of_append_inl]
|
||||
apply And.intro (getDualInOther?_areDualInOther_get l l2 i hi)
|
||||
intro j hj
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
simp only [appendEquiv, Equiv.trans_apply, finSumFinEquiv_apply_left, RelIso.coe_fn_toEquiv,
|
||||
Fin.castOrderIso_apply, ge_iff_le]
|
||||
rw [Fin.le_def]
|
||||
have h1 : l.getDualInOther? l2 i = some (((l.getDualInOther? l2 i).get hi)) :=
|
||||
Option.eq_some_of_isSome hi
|
||||
nth_rewrite 1 [getDualInOther?] at h1
|
||||
rw [Fin.find_eq_some_iff] at h1
|
||||
simp only [Fin.coe_cast, Fin.coe_natAdd, add_le_add_iff_left, Fin.val_fin_le, ge_iff_le]
|
||||
refine h1.2 k ((AreDualInOther.of_append_inl i k).mp hj)
|
||||
| Sum.inr k =>
|
||||
simp only [appendEquiv, Equiv.trans_apply, finSumFinEquiv_apply_left, RelIso.coe_fn_toEquiv,
|
||||
Fin.castOrderIso_apply, finSumFinEquiv_apply_right, ge_iff_le]
|
||||
rw [Fin.le_def]
|
||||
simp only [length, append_val, RelIso.coe_fn_toEquiv, Fin.castOrderIso_apply, Fin.coe_cast,
|
||||
Fin.coe_castAdd, Fin.coe_natAdd]
|
||||
omega
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_of_append_of_isNone_isSome (i : Fin l.length)
|
||||
(hi : (l.getDualInOther? l2 i) = none) (h2 : (l.getDualInOther? l3 i).isSome) :
|
||||
l.getDualInOther? (l2 ++ l3) i =
|
||||
some (appendEquiv (Sum.inr ((l.getDualInOther? l3 i).get h2))) := by
|
||||
rw [getDualInOther?, Fin.find_eq_some_iff, AreDualInOther.of_append_inr]
|
||||
apply And.intro (getDualInOther?_areDualInOther_get l l3 i h2)
|
||||
intro j hj
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective j
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
simp at hj
|
||||
simp only [getDualInOther?, Option.isNone_iff_eq_none, Fin.find_eq_none_iff] at hi
|
||||
exact False.elim (hi k hj)
|
||||
| Sum.inr k =>
|
||||
simp [appendEquiv, IndexList.length]
|
||||
rw [Fin.le_def]
|
||||
simp only [Fin.coe_cast, Fin.coe_natAdd, add_le_add_iff_left, Fin.val_fin_le]
|
||||
have h1 : l.getDualInOther? l3 i = some ((l.getDualInOther? l3 i).get h2) :=
|
||||
Option.eq_some_of_isSome h2
|
||||
nth_rewrite 1 [getDualInOther?] at h1
|
||||
rw [Fin.find_eq_some_iff] at h1
|
||||
simp only [AreDualInOther.of_append_inr] at hj
|
||||
exact h1.2 k hj
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -0,0 +1,315 @@
|
|||
/-
|
||||
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 Mathlib.Data.Set.Finite
|
||||
import Mathlib.Logic.Equiv.Fin
|
||||
import Mathlib.Data.Finset.Sort
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.Basic
|
||||
/-!
|
||||
|
||||
# Index lists
|
||||
|
||||
i.e. lists of indices.
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
variable (X : Type) [IndexNotation X]
|
||||
variable [Fintype X] [DecidableEq X]
|
||||
|
||||
/-- The type of lists of indices. -/
|
||||
structure IndexList where
|
||||
/-- The list of index values. For example `['ᵘ¹','ᵘ²','ᵤ₁']`. -/
|
||||
val : List (Index X)
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
|
||||
variable (l : IndexList X)
|
||||
|
||||
/-- The number of indices in an index list. -/
|
||||
def length : ℕ := l.val.length
|
||||
|
||||
lemma ext (h : l.val = l2.val) : l = l2 := by
|
||||
cases l
|
||||
cases l2
|
||||
simp_all
|
||||
|
||||
/-- The index list constructed by prepending an index to the list. -/
|
||||
def cons (i : Index X) : IndexList X := {val := i :: l.val}
|
||||
|
||||
@[simp]
|
||||
lemma cons_val (i : Index X) : (l.cons i).val = i :: l.val := by
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma cons_length (i : Index X) : (l.cons i).length = l.length + 1 := by
|
||||
rfl
|
||||
|
||||
/-- The tail of an index list. That is, the index list with the first index dropped. -/
|
||||
def tail : IndexList X := {val := l.val.tail}
|
||||
|
||||
@[simp]
|
||||
lemma tail_val : l.tail.val = l.val.tail := by
|
||||
rfl
|
||||
|
||||
/-- The first index in a non-empty index list. -/
|
||||
def head (h : l ≠ {val := ∅}) : Index X := l.val.head (by cases' l; simpa using h)
|
||||
|
||||
lemma head_cons_tail (h : l ≠ {val := ∅}) : l = (l.tail.cons (l.head h)) := by
|
||||
apply ext
|
||||
simp only [cons_val, tail_val]
|
||||
simp only [head, List.head_cons_tail]
|
||||
|
||||
lemma induction {P : IndexList X → Prop } (h_nil : P {val := ∅})
|
||||
(h_cons : ∀ (x : Index X) (xs : IndexList X), P xs → P (xs.cons x)) (l : IndexList X) : P l := by
|
||||
cases' l with val
|
||||
induction val with
|
||||
| nil => exact h_nil
|
||||
| cons x xs ih =>
|
||||
exact h_cons x ⟨xs⟩ ih
|
||||
|
||||
/-- The map of from `Fin s.numIndices` into colors associated to an index list. -/
|
||||
def colorMap : Fin l.length → X :=
|
||||
fun i => (l.val.get i).toColor
|
||||
|
||||
/-- The map of from `Fin s.numIndices` into the natural numbers associated to an index list. -/
|
||||
def idMap : Fin l.length → Nat :=
|
||||
fun i => (l.val.get i).id
|
||||
|
||||
lemma idMap_cast {l1 l2 : IndexList X} (h : l1 = l2) (i : Fin l1.length) :
|
||||
l1.idMap i = l2.idMap (Fin.cast (by rw [h]) i) := by
|
||||
subst h
|
||||
rfl
|
||||
|
||||
/-- Given a list of indices a subset of `Fin l.numIndices × Index X`
|
||||
of pairs of positions in `l` and the corresponding item in `l`. -/
|
||||
def toPosSet (l : IndexList X) : Set (Fin l.length × Index X) :=
|
||||
{(i, l.val.get i) | i : Fin l.length}
|
||||
|
||||
/-- Equivalence between `toPosSet` and `Fin l.numIndices`. -/
|
||||
def toPosSetEquiv (l : IndexList X) : l.toPosSet ≃ Fin l.length where
|
||||
toFun := fun x => x.1.1
|
||||
invFun := fun x => ⟨(x, l.val.get x), by simp [toPosSet]⟩
|
||||
left_inv x := by
|
||||
have hx := x.prop
|
||||
simp [toPosSet] at hx
|
||||
simp only [List.get_eq_getElem]
|
||||
obtain ⟨i, hi⟩ := hx
|
||||
have hi2 : i = x.1.1 := by
|
||||
obtain ⟨val, property⟩ := x
|
||||
obtain ⟨fst, snd⟩ := val
|
||||
simp_all only [Prod.mk.injEq]
|
||||
subst hi2
|
||||
simp_all only [Subtype.coe_eta]
|
||||
right_inv := by
|
||||
intro x
|
||||
rfl
|
||||
|
||||
lemma toPosSet_is_finite (l : IndexList X) : l.toPosSet.Finite :=
|
||||
Finite.intro l.toPosSetEquiv
|
||||
|
||||
instance : Fintype l.toPosSet where
|
||||
elems := Finset.map l.toPosSetEquiv.symm.toEmbedding Finset.univ
|
||||
complete := by
|
||||
intro x
|
||||
simp_all only [Finset.mem_map_equiv, Equiv.symm_symm, Finset.mem_univ]
|
||||
|
||||
/-- Given a list of indices a finite set of `Fin l.length × Index X`
|
||||
of pairs of positions in `l` and the corresponding item in `l`. -/
|
||||
def toPosFinset (l : IndexList X) : Finset (Fin l.length × Index X) :=
|
||||
l.toPosSet.toFinset
|
||||
|
||||
/-- The construction of a list of indices from a map
|
||||
from `Fin n` to `Index X`. -/
|
||||
def fromFinMap {n : ℕ} (f : Fin n → Index X) : IndexList X where
|
||||
val := (Fin.list n).map f
|
||||
|
||||
@[simp]
|
||||
lemma fromFinMap_numIndices {n : ℕ} (f : Fin n → Index X) :
|
||||
(fromFinMap f).length = n := by
|
||||
simp [fromFinMap, length]
|
||||
|
||||
/-!
|
||||
|
||||
## Appending index lists.
|
||||
|
||||
-/
|
||||
|
||||
section append
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
instance : HAppend (IndexList X) (IndexList X) (IndexList X) where
|
||||
hAppend := fun l l2 => {val := l.val ++ l2.val}
|
||||
|
||||
@[simp]
|
||||
lemma cons_append (i : Index X) : (l.cons i) ++ l2 = (l ++ l2).cons i := by
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma append_length : (l ++ l2).length = l.length + l2.length := by
|
||||
simp [IndexList.length]
|
||||
exact List.length_append l.val l2.val
|
||||
|
||||
lemma append_assoc : l ++ l2 ++ l3 = l ++ (l2 ++ l3) := by
|
||||
apply ext
|
||||
change l.val ++ l2.val ++ l3.val = l.val ++ (l2.val ++ l3.val)
|
||||
exact List.append_assoc l.val l2.val l3.val
|
||||
|
||||
/-- An equivalence between the sum of the types of indices of `l` an `l2` and the type
|
||||
of indices of the joined index list `l ++ l2`. -/
|
||||
def appendEquiv {l l2 : IndexList X} : Fin l.length ⊕ Fin l2.length ≃ Fin (l ++ l2).length :=
|
||||
finSumFinEquiv.trans (Fin.castOrderIso (List.length_append _ _).symm).toEquiv
|
||||
|
||||
/-- The inclusion of the indices of `l` into the indices of `l ++ l2`. -/
|
||||
def appendInl : Fin l.length ↪ Fin (l ++ l2).length where
|
||||
toFun := appendEquiv ∘ Sum.inl
|
||||
inj' := by
|
||||
intro i j h
|
||||
simp [Function.comp] at h
|
||||
exact h
|
||||
|
||||
/-- The inclusion of the indices of `l2` into the indices of `l ++ l2`. -/
|
||||
def appendInr : Fin l2.length ↪ Fin (l ++ l2).length where
|
||||
toFun := appendEquiv ∘ Sum.inr
|
||||
inj' := by
|
||||
intro i j h
|
||||
simp [Function.comp] at h
|
||||
exact h
|
||||
|
||||
@[simp]
|
||||
lemma appendInl_appendEquiv :
|
||||
(l.appendInl l2).trans appendEquiv.symm.toEmbedding =
|
||||
{toFun := Sum.inl, inj' := Sum.inl_injective} := by
|
||||
ext i
|
||||
simp [appendInl]
|
||||
|
||||
@[simp]
|
||||
lemma appendInr_appendEquiv :
|
||||
(l.appendInr l2).trans appendEquiv.symm.toEmbedding =
|
||||
{toFun := Sum.inr, inj' := Sum.inr_injective} := by
|
||||
ext i
|
||||
simp [appendInr]
|
||||
|
||||
@[simp]
|
||||
lemma append_val {l l2 : IndexList X} : (l ++ l2).val = l.val ++ l2.val := by
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma idMap_append_inl {l l2 : IndexList X} (i : Fin l.length) :
|
||||
(l ++ l2).idMap (appendEquiv (Sum.inl i)) = l.idMap i := by
|
||||
simp [appendEquiv, idMap]
|
||||
rw [List.getElem_append_left]
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma idMap_append_inr {l l2 : IndexList X} (i : Fin l2.length) :
|
||||
(l ++ l2).idMap (appendEquiv (Sum.inr i)) = l2.idMap i := by
|
||||
simp [appendEquiv, idMap, IndexList.length]
|
||||
rw [List.getElem_append_right]
|
||||
· simp only [Nat.add_sub_cancel_left]
|
||||
· omega
|
||||
· omega
|
||||
|
||||
@[simp]
|
||||
lemma colorMap_append_inl {l l2 : IndexList X} (i : Fin l.length) :
|
||||
(l ++ l2).colorMap (appendEquiv (Sum.inl i)) = l.colorMap i := by
|
||||
simp [appendEquiv, colorMap, IndexList.length]
|
||||
rw [List.getElem_append_left]
|
||||
|
||||
@[simp]
|
||||
lemma colorMap_append_inl' :
|
||||
(l ++ l2).colorMap ∘ appendEquiv ∘ Sum.inl = l.colorMap := by
|
||||
funext i
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
lemma colorMap_append_inr {l l2 : IndexList X} (i : Fin l2.length) :
|
||||
(l ++ l2).colorMap (appendEquiv (Sum.inr i)) = l2.colorMap i := by
|
||||
simp [appendEquiv, colorMap, IndexList.length]
|
||||
rw [List.getElem_append_right]
|
||||
· simp only [Nat.add_sub_cancel_left]
|
||||
· omega
|
||||
· omega
|
||||
|
||||
@[simp]
|
||||
lemma colorMap_append_inr' :
|
||||
(l ++ l2).colorMap ∘ appendEquiv ∘ Sum.inr = l2.colorMap := by
|
||||
funext i
|
||||
simp
|
||||
|
||||
lemma colorMap_sumELim (l1 l2 : IndexList X) :
|
||||
Sum.elim l1.colorMap l2.colorMap =
|
||||
(l1 ++ l2).colorMap ∘ appendEquiv := by
|
||||
funext x
|
||||
match x with
|
||||
| Sum.inl i => simp
|
||||
| Sum.inr i => simp
|
||||
|
||||
end append
|
||||
|
||||
/-!
|
||||
|
||||
## Filter id
|
||||
|
||||
-/
|
||||
|
||||
/-! 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
|
|
@ -0,0 +1,583 @@
|
|||
/-
|
||||
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.IndexList.Contraction
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.OnlyUniqueDuals
|
||||
import HepLean.SpaceTime.LorentzTensor.Basic
|
||||
import Init.Data.List.Lemmas
|
||||
/-!
|
||||
|
||||
# Index lists and color
|
||||
|
||||
In this file we look at the interaction of index lists and color.
|
||||
|
||||
The main definition of this file is `ColorCond`.
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace Index
|
||||
|
||||
variable {𝓒 : TensorColor}
|
||||
variable [IndexNotation 𝓒.Color] [Fintype 𝓒.Color] [DecidableEq 𝓒.Color]
|
||||
variable (I : Index 𝓒.Color)
|
||||
|
||||
/-- The dual of an index is the index with the same id, but opposite color. -/
|
||||
def dual : Index 𝓒.Color := ⟨𝓒.τ I.toColor, I.id⟩
|
||||
|
||||
@[simp]
|
||||
lemma dual_dual : I.dual.dual = I := by
|
||||
simp [dual, toColor, id]
|
||||
rw [𝓒.τ_involutive]
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma dual_id : I.dual.id = I.id := by
|
||||
simp [dual, id]
|
||||
|
||||
@[simp]
|
||||
lemma dual_color : I.dual.toColor = 𝓒.τ I.toColor := by
|
||||
simp [dual, toColor]
|
||||
|
||||
end Index
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {𝓒 : TensorColor}
|
||||
variable [IndexNotation 𝓒.Color] [Fintype 𝓒.Color] [DecidableEq 𝓒.Color]
|
||||
variable (l l2 l3 : IndexList 𝓒.Color)
|
||||
|
||||
/-- The number of times `I` or its dual appears in an `IndexList`. -/
|
||||
def countColorQuot (I : Index 𝓒.Color) : ℕ := l.val.countP (fun J => I = J ∨ I.dual = J)
|
||||
|
||||
lemma countColorQuot_eq_filter_id_countP (I : Index 𝓒.Color) :
|
||||
l.countColorQuot I =
|
||||
(l.val.filter (fun J => I.id = J.id)).countP
|
||||
(fun J => I.toColor = J.toColor ∨ I.toColor = 𝓒.τ (J.toColor)) := by
|
||||
simp [countColorQuot]
|
||||
rw [List.countP_filter]
|
||||
apply List.countP_congr
|
||||
intro I' _
|
||||
simp [Index.eq_iff_color_eq_and_id_eq]
|
||||
apply Iff.intro
|
||||
· intro a_1
|
||||
cases a_1 with
|
||||
| inl h => simp_all only [true_or, and_self]
|
||||
| inr h_1 =>
|
||||
simp_all only [and_true]
|
||||
obtain ⟨left, _⟩ := h_1
|
||||
rw [← left]
|
||||
rw [𝓒.τ_involutive]
|
||||
simp
|
||||
· intro a_1
|
||||
simp_all only [and_true]
|
||||
obtain ⟨left, _⟩ := a_1
|
||||
cases left with
|
||||
| inl h => simp_all only [true_or]
|
||||
| inr h_1 =>
|
||||
simp_all only
|
||||
rw [𝓒.τ_involutive]
|
||||
simp
|
||||
|
||||
lemma countColorQuot_eq_filter_color_countP (I : Index 𝓒.Color) :
|
||||
l.countColorQuot I =
|
||||
(l.val.filter (fun J => I.toColor = J.toColor ∨ I.toColor = 𝓒.τ (J.toColor))).countP
|
||||
(fun J => I.id = J.id) := by
|
||||
rw [countColorQuot_eq_filter_id_countP]
|
||||
rw [List.countP_filter, List.countP_filter]
|
||||
apply List.countP_congr
|
||||
intro I' _
|
||||
simpa using And.comm
|
||||
|
||||
@[simp]
|
||||
lemma countColorQuot_append (I : Index 𝓒.Color) :
|
||||
(l ++ l2).countColorQuot I = countColorQuot l I + countColorQuot l2 I := by
|
||||
simp [countColorQuot]
|
||||
|
||||
lemma countColorQuot_eq_countId_iff_of_isSome (hl : l.OnlyUniqueDuals) (i : Fin l.length)
|
||||
(hi : (l.getDual? i).isSome) :
|
||||
l.countColorQuot (l.val.get i) = l.countId (l.val.get i) ↔
|
||||
(l.colorMap i = l.colorMap ((l.getDual? i).get hi) ∨
|
||||
l.colorMap i = 𝓒.τ (l.colorMap ((l.getDual? i).get hi))) := by
|
||||
rw [countColorQuot_eq_filter_id_countP, countId_eq_length_filter]
|
||||
have hi1 := hi
|
||||
rw [← mem_withDual_iff_isSome, ← hl, mem_withUniqueDual_iff_countId_eq_two] at hi1
|
||||
rcases l.filter_id_of_countId_eq_two hi1 with hf | hf
|
||||
all_goals
|
||||
erw [hf]
|
||||
simp [List.countP, List.countP.go]
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· by_contra hn
|
||||
have hn' : (decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor) ||
|
||||
decide (l.val[↑i].toColor = 𝓒.τ l.val[↑((l.getDual? i).get hi)].toColor)) = false := by
|
||||
simpa using hn
|
||||
erw [hn'] at h
|
||||
simp at h
|
||||
· have hn' : (decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor) ||
|
||||
decide (l.val[↑i].toColor = 𝓒.τ l.val[↑((l.getDual? i).get hi)].toColor)) = true := by
|
||||
simpa using h
|
||||
erw [hn']
|
||||
simp
|
||||
|
||||
lemma countColorQuot_of_countId_zero {I : Index 𝓒.Color} (h : l.countId I = 0) :
|
||||
l.countColorQuot I = 0 := by
|
||||
rw [countColorQuot_eq_filter_id_countP]
|
||||
rw [countId_eq_length_filter, List.length_eq_zero] at h
|
||||
simp [h, countColorQuot]
|
||||
|
||||
lemma countColorQuot_le_countId (I : Index 𝓒.Color) :
|
||||
l.countColorQuot I ≤ l.countId I := by
|
||||
rw [countColorQuot_eq_filter_color_countP, countId]
|
||||
apply List.Sublist.countP_le
|
||||
exact List.filter_sublist l.val
|
||||
|
||||
lemma countColorQuot_contrIndexList_le_one (I : Index 𝓒.Color) :
|
||||
l.contrIndexList.countColorQuot I ≤ 1 :=
|
||||
(l.contrIndexList.countColorQuot_le_countId I).trans
|
||||
(countId_contrIndexList_le_one l I)
|
||||
|
||||
lemma countColorQuot_contrIndexList_eq_zero_or_one (I : Index 𝓒.Color) :
|
||||
l.contrIndexList.countColorQuot I = 0 ∨ l.contrIndexList.countColorQuot I = 1 := by
|
||||
have h1 := countColorQuot_contrIndexList_le_one l I
|
||||
omega
|
||||
|
||||
lemma countColorQuot_contrIndexList_le_countColorQuot (I : Index 𝓒.Color) :
|
||||
l.contrIndexList.countColorQuot I ≤ l.countColorQuot I := by
|
||||
rw [countColorQuot_eq_filter_color_countP, countColorQuot_eq_filter_color_countP]
|
||||
apply List.Sublist.countP_le
|
||||
exact List.Sublist.filter _ (List.filter_sublist l.val)
|
||||
|
||||
lemma countColorQuot_contrIndexList_eq_of_countId_eq
|
||||
(h1 : l.contrIndexList.countId I = l.countId I) :
|
||||
l.contrIndexList.countColorQuot I = l.countColorQuot I := by
|
||||
rw [countColorQuot_eq_filter_id_countP,
|
||||
l.filter_id_contrIndexList_eq_of_countId_contrIndexList I h1,
|
||||
countColorQuot_eq_filter_id_countP]
|
||||
|
||||
/-- The number of times an index `I` appears in an index list. -/
|
||||
def countSelf (I : Index 𝓒.Color) : ℕ := l.val.countP (fun J => I = J)
|
||||
|
||||
lemma countSelf_eq_filter_id_countP : l.countSelf I =
|
||||
(l.val.filter (fun J => I.id = J.id)).countP (fun J => I.toColor = J.toColor) := by
|
||||
simp [countSelf]
|
||||
rw [List.countP_filter]
|
||||
apply List.countP_congr
|
||||
intro I' _
|
||||
simp [Index.eq_iff_color_eq_and_id_eq]
|
||||
|
||||
lemma countSelf_eq_filter_color_countP :
|
||||
l.countSelf I =
|
||||
(l.val.filter (fun J => I.toColor = J.toColor)).countP (fun J => I.id = J.id) := by
|
||||
simp [countSelf]
|
||||
rw [List.countP_filter]
|
||||
apply List.countP_congr
|
||||
intro I' _
|
||||
simpa [Index.eq_iff_color_eq_and_id_eq] using And.comm
|
||||
|
||||
lemma countSelf_of_countId_zero {I : Index 𝓒.Color} (h : l.countId I = 0) :
|
||||
l.countSelf I = 0 := by
|
||||
rw [countId_eq_length_filter, List.length_eq_zero] at h
|
||||
simp [h, countSelf_eq_filter_id_countP]
|
||||
|
||||
lemma countSelf_count (I : Index 𝓒.Color) : l.countSelf I = l.val.count I := by
|
||||
rw [countSelf, List.count]
|
||||
apply List.countP_congr
|
||||
intro I' _
|
||||
simp only [decide_eq_true_eq, beq_iff_eq]
|
||||
exact eq_comm
|
||||
|
||||
lemma countSelf_eq_zero (I : Index 𝓒.Color) : l.countSelf I = 0 ↔ I ∉ l.val := by
|
||||
rw [countSelf_count]
|
||||
exact List.count_eq_zero
|
||||
|
||||
lemma countSelf_neq_zero (I : Index 𝓒.Color) : l.countSelf I ≠ 0 ↔ I ∈ l.val := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· simpa using (l.countSelf_eq_zero I).mpr.mt h
|
||||
· exact (l.countSelf_eq_zero I).mp.mt (by simpa using h)
|
||||
|
||||
@[simp]
|
||||
lemma countSelf_append (I : Index 𝓒.Color) :
|
||||
(l ++ l2).countSelf I = countSelf l I + countSelf l2 I := by
|
||||
simp [countSelf]
|
||||
|
||||
lemma countSelf_le_countId (I : Index 𝓒.Color) :
|
||||
l.countSelf I ≤ l.countId I := by
|
||||
rw [countSelf_eq_filter_color_countP, countId]
|
||||
apply List.Sublist.countP_le
|
||||
exact List.filter_sublist l.val
|
||||
|
||||
lemma countSelf_eq_one_of_countId_eq_one (I : Index 𝓒.Color) (h1 : l.countId I = 1)
|
||||
(hme : I ∈ l.val) : l.countSelf I = 1 := by
|
||||
rw [countSelf_eq_filter_id_countP]
|
||||
rw [filter_id_of_countId_eq_one_mem l hme h1]
|
||||
simp
|
||||
|
||||
lemma countSelf_contrIndexList_le_one (I : Index 𝓒.Color) :
|
||||
l.contrIndexList.countSelf I ≤ 1 :=
|
||||
(l.contrIndexList.countSelf_le_countId I).trans (countId_contrIndexList_le_one l I)
|
||||
|
||||
lemma countSelf_contrIndexList_eq_zero_or_one (I : Index 𝓒.Color) :
|
||||
l.contrIndexList.countSelf I = 0 ∨ l.contrIndexList.countSelf I = 1 := by
|
||||
have h1 := countSelf_contrIndexList_le_one l I
|
||||
omega
|
||||
|
||||
lemma countSelf_contrIndexList_eq_zero_of_zero (I : Index 𝓒.Color) (h : l.countSelf I = 0) :
|
||||
l.contrIndexList.countSelf I = 0 := by
|
||||
rw [countSelf_eq_zero] at h ⊢
|
||||
simp_all [contrIndexList]
|
||||
|
||||
lemma countSelf_contrIndexList_le_countSelf (I : Index 𝓒.Color) :
|
||||
l.contrIndexList.countSelf I ≤ l.countSelf I := by
|
||||
rw [countSelf_eq_filter_color_countP, countSelf_eq_filter_color_countP]
|
||||
apply List.Sublist.countP_le
|
||||
exact List.Sublist.filter _ (List.filter_sublist l.val)
|
||||
|
||||
lemma countSelf_contrIndexList_eq_of_countId_eq
|
||||
(h1 : l.contrIndexList.countId I = l.countId I) :
|
||||
l.contrIndexList.countSelf I = l.countSelf I := by
|
||||
rw [countSelf_eq_filter_id_countP,
|
||||
l.filter_id_contrIndexList_eq_of_countId_contrIndexList I h1,
|
||||
countSelf_eq_filter_id_countP]
|
||||
|
||||
@[simp]
|
||||
lemma countSelf_contrIndexList_get (i : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.countSelf l.contrIndexList.val[Fin.val i] = 1 := by
|
||||
refine countSelf_eq_one_of_countId_eq_one _ _ ?h1 ?hme
|
||||
· refine mem_contrIndexList_countId_contrIndexList l ?_
|
||||
exact List.getElem_mem l.contrIndexList.val (↑i) _
|
||||
· exact List.getElem_mem l.contrIndexList.val (↑i) _
|
||||
|
||||
/-- The number of times the dual of an index `I` appears in an index list. -/
|
||||
def countDual (I : Index 𝓒.Color) : ℕ := l.val.countP (fun J => I.dual = J)
|
||||
|
||||
lemma countDual_eq_countSelf_Dual (I : Index 𝓒.Color) : l.countDual I = l.countSelf I.dual := by
|
||||
rw [countDual, countSelf]
|
||||
|
||||
lemma countDual_eq_filter_id_countP : l.countDual I =
|
||||
(l.val.filter (fun J => I.id = J.id)).countP (fun J => I.toColor = 𝓒.τ (J.toColor)) := by
|
||||
simp [countDual]
|
||||
rw [List.countP_filter]
|
||||
apply List.countP_congr
|
||||
intro I' _
|
||||
simp [Index.eq_iff_color_eq_and_id_eq, Index.dual, Index.toColor, Index.id]
|
||||
intro _
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· rw [← h]
|
||||
exact (𝓒.τ_involutive _).symm
|
||||
· rw [h]
|
||||
exact (𝓒.τ_involutive _)
|
||||
|
||||
lemma countDual_of_countId_zero {I : Index 𝓒.Color} (h : l.countId I = 0) :
|
||||
l.countDual I = 0 := by
|
||||
rw [countId_eq_length_filter, List.length_eq_zero] at h
|
||||
simp [h, countDual_eq_filter_id_countP]
|
||||
|
||||
@[simp]
|
||||
lemma countDual_append (I : Index 𝓒.Color) :
|
||||
(l ++ l2).countDual I = countDual l I + countDual l2 I := by
|
||||
simp [countDual]
|
||||
|
||||
lemma countDual_contrIndexList_eq_of_countId_eq
|
||||
(h1 : l.contrIndexList.countId I = l.countId I) :
|
||||
l.contrIndexList.countDual I = l.countDual I := by
|
||||
rw [countDual_eq_countSelf_Dual, countDual_eq_countSelf_Dual]
|
||||
refine countSelf_contrIndexList_eq_of_countId_eq l h1
|
||||
|
||||
lemma countSelf_eq_countDual_iff_of_isSome (hl : l.OnlyUniqueDuals)
|
||||
(i : Fin l.length) (hi : (l.getDual? i).isSome) :
|
||||
l.countSelf (l.val.get i) = l.countDual (l.val.get i) ↔
|
||||
l.colorMap i = 𝓒.τ (l.colorMap ((l.getDual? i).get hi))
|
||||
∨ (l.colorMap i) = 𝓒.τ (l.colorMap i) := by
|
||||
rw [countSelf_eq_filter_id_countP, countDual_eq_filter_id_countP]
|
||||
have hi1 := hi
|
||||
rw [← mem_withDual_iff_isSome, ← hl, mem_withUniqueDual_iff_countId_eq_two] at hi1
|
||||
rcases l.filter_id_of_countId_eq_two hi1 with hf | hf
|
||||
all_goals
|
||||
erw [hf]
|
||||
simp [List.countP, List.countP.go]
|
||||
by_cases hn : l.colorMap i = 𝓒.τ (l.colorMap ((l.getDual? i).get hi))
|
||||
· simp [hn]
|
||||
have hn' : decide (l.val[↑i].toColor = 𝓒.τ l.val[↑((l.getDual? i).get hi)].toColor)
|
||||
= true := by simpa [colorMap] using hn
|
||||
erw [hn']
|
||||
simp only [cond_true]
|
||||
have hτ : l.colorMap ((l.getDual? i).get hi) = 𝓒.τ (l.colorMap i) := by
|
||||
rw [hn]
|
||||
exact (𝓒.τ_involutive _).symm
|
||||
simp [colorMap] at hτ
|
||||
erw [hτ]
|
||||
· have hn' : decide (l.val[↑i].toColor = 𝓒.τ l.val[↑((l.getDual? i).get hi)].toColor) =
|
||||
false := by simpa [colorMap] using hn
|
||||
erw [hn']
|
||||
simp [hn]
|
||||
by_cases hm : l.colorMap i = 𝓒.τ (l.colorMap i)
|
||||
· trans True
|
||||
· simp
|
||||
have hm' : decide (l.val[↑i].toColor = 𝓒.τ l.val[↑i].toColor) = true := by simpa using hm
|
||||
erw [hm']
|
||||
simp only [cond_true]
|
||||
have hm'' : decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor)
|
||||
= false := by
|
||||
simp only [Fin.getElem_fin, decide_eq_false_iff_not]
|
||||
simp [colorMap] at hm
|
||||
erw [hm]
|
||||
by_contra hn'
|
||||
have hn'' : l.colorMap i = 𝓒.τ (l.colorMap ((l.getDual? i).get hi)) := by
|
||||
simp [colorMap]
|
||||
rw [← hn']
|
||||
exact (𝓒.τ_involutive _).symm
|
||||
exact hn hn''
|
||||
erw [hm'']
|
||||
simp
|
||||
· exact true_iff_iff.mpr hm
|
||||
· simp [hm]
|
||||
simp [colorMap] at hm
|
||||
have hm' : decide (l.val[↑i].toColor = 𝓒.τ l.val[↑i].toColor) = false := by simpa using hm
|
||||
erw [hm']
|
||||
simp only [cond_false, ne_eq]
|
||||
by_cases hm'' : decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor) = true
|
||||
· erw [hm'']
|
||||
simp
|
||||
· have hm''' : decide (l.val[↑i].toColor = l.val[↑((l.getDual? i).get hi)].toColor)
|
||||
= false := by
|
||||
simpa using hm''
|
||||
erw [hm''']
|
||||
simp
|
||||
|
||||
/-- The condition an index and its' dual, when it exists, have dual colors. -/
|
||||
def ColorCond : Prop := Option.map l.colorMap ∘
|
||||
l.getDual? = Option.map (𝓒.τ ∘ l.colorMap) ∘
|
||||
Option.guard fun i => (l.getDual? i).isSome
|
||||
|
||||
namespace ColorCond
|
||||
|
||||
variable {l l2 l3 : IndexList 𝓒.Color}
|
||||
|
||||
lemma iff_withDual :
|
||||
l.ColorCond ↔ ∀ (i : l.withDual), 𝓒.τ
|
||||
(l.colorMap ((l.getDual? i).get (l.withDual_isSome i))) = l.colorMap i := by
|
||||
refine Iff.intro (fun h i => ?_) (fun h => ?_)
|
||||
· have h' := congrFun h i
|
||||
simp at h'
|
||||
rw [show l.getDual? i = some ((l.getDual? i).get (l.withDual_isSome i)) by simp] at h'
|
||||
have h'' : (Option.guard (fun i => (l.getDual? i).isSome = true) ↑i) = i := by
|
||||
apply Option.guard_eq_some.mpr
|
||||
simp [l.withDual_isSome i]
|
||||
rw [h'', Option.map_some', Option.map_some'] at h'
|
||||
simp at h'
|
||||
rw [h']
|
||||
exact 𝓒.τ_involutive (l.colorMap i)
|
||||
· funext i
|
||||
by_cases hi : (l.getDual? i).isSome
|
||||
· have h'' : (Option.guard (fun i => (l.getDual? i).isSome = true) ↑i) = i := by
|
||||
apply Option.guard_eq_some.mpr
|
||||
simp only [true_and]
|
||||
exact hi
|
||||
simp only [Function.comp_apply, h'', Option.map_some']
|
||||
rw [show l.getDual? ↑i = some ((l.getDual? i).get hi) by simp]
|
||||
rw [Option.map_some']
|
||||
simp only [Option.some.injEq]
|
||||
have hii := h ⟨i, by simp [withDual, hi]⟩
|
||||
simp at hii
|
||||
rw [← hii]
|
||||
exact (𝓒.τ_involutive _).symm
|
||||
· simp [Option.guard, hi]
|
||||
exact Option.not_isSome_iff_eq_none.mp hi
|
||||
|
||||
lemma iff_on_isSome : l.ColorCond ↔ ∀ (i : Fin l.length) (h : (l.getDual? i).isSome), 𝓒.τ
|
||||
(l.colorMap ((l.getDual? i).get h)) = l.colorMap i := by
|
||||
rw [iff_withDual]
|
||||
simp only [Subtype.forall, mem_withDual_iff_isSome]
|
||||
|
||||
/-- A condition on an index list `l` and and index `I`. If the id of `I` appears
|
||||
twice in `l` (and `I` at least once) then this condition is equivalent to the dual of `I` having
|
||||
dual color to `I`, but written totally in terms of lists. -/
|
||||
@[simp]
|
||||
abbrev countColorCond (l : IndexList 𝓒.Color) (I : Index 𝓒.Color) : Prop :=
|
||||
l.countColorQuot I = l.countId I ∧
|
||||
l.countSelf I = l.countDual I
|
||||
|
||||
lemma countColorCond_of_filter_eq (l l2 : IndexList 𝓒.Color) {I : Index 𝓒.Color}
|
||||
(hf : l.val.filter (fun J => I.id = J.id) = l2.val.filter (fun J => I.id = J.id))
|
||||
(h1 : countColorCond l I) : countColorCond l2 I := by
|
||||
rw [countColorCond, countColorQuot_eq_filter_id_countP, countId_eq_length_filter,
|
||||
countSelf_eq_filter_id_countP, countDual_eq_filter_id_countP, ← hf]
|
||||
rw [countColorCond, countColorQuot_eq_filter_id_countP, countId_eq_length_filter,
|
||||
countSelf_eq_filter_id_countP, countDual_eq_filter_id_countP] at h1
|
||||
exact h1
|
||||
|
||||
lemma iff_countColorCond_isSome (hl : l.OnlyUniqueDuals) : l.ColorCond ↔
|
||||
∀ (i : Fin l.length) (_ : (l.getDual? i).isSome), countColorCond l (l.val.get i) := by
|
||||
rw [iff_on_isSome]
|
||||
simp only [countColorCond]
|
||||
refine Iff.intro (fun h i hi => ?_) (fun h i hi => ?_)
|
||||
· rw [l.countColorQuot_eq_countId_iff_of_isSome hl i hi,
|
||||
l.countSelf_eq_countDual_iff_of_isSome hl i hi]
|
||||
have hi' := h i hi
|
||||
exact And.intro (Or.inr hi'.symm) (Or.inl hi'.symm)
|
||||
· have hi' := h i hi
|
||||
rw [l.countColorQuot_eq_countId_iff_of_isSome hl i hi,
|
||||
l.countSelf_eq_countDual_iff_of_isSome hl i hi] at hi'
|
||||
rcases hi'.1 with hi1 | hi1
|
||||
<;> rcases hi'.2 with hi2 | hi2
|
||||
· exact hi2.symm
|
||||
· rw [← hi1]
|
||||
exact hi2.symm
|
||||
· exact hi1.symm
|
||||
· exact hi1.symm
|
||||
|
||||
lemma iff_countColorCond_index (hl : l.OnlyUniqueDuals) :
|
||||
l.ColorCond ↔ ∀ (i : Fin l.length), l.countId (l.val.get i) = 2
|
||||
→ countColorCond l (l.val.get i) := by
|
||||
rw [iff_countColorCond_isSome hl]
|
||||
refine Iff.intro (fun h i hi => ?_) (fun h i hi => ?_)
|
||||
· rw [← mem_withUniqueDual_iff_countId_eq_two] at hi
|
||||
exact h i (mem_withUniqueDual_isSome l i hi)
|
||||
· rw [← mem_withDual_iff_isSome, ← hl, mem_withUniqueDual_iff_countId_eq_two] at hi
|
||||
exact h i hi
|
||||
|
||||
lemma iff_countColorCond_mem (hl : l.OnlyUniqueDuals) :
|
||||
l.ColorCond ↔ ∀ (I : Index 𝓒.Color) (_ : I ∈ l.val),
|
||||
l.countId I = 2 → countColorCond l I := by
|
||||
rw [iff_countColorCond_index hl]
|
||||
refine Iff.intro (fun h I hI hi => ?_) (fun h i hi => ?_)
|
||||
· 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] at hi ⊢
|
||||
exact h ⟨i, hi'⟩ hi
|
||||
· exact h (l.val.get i) (List.getElem_mem l.val (↑i) i.isLt) hi
|
||||
|
||||
lemma mem_iff_dual_mem (hl : l.OnlyUniqueDuals) (hc : l.ColorCond) (I : Index 𝓒.Color)
|
||||
(hId : l.countId I = 2) : I ∈ l.val ↔ I.dual ∈ l.val := by
|
||||
rw [iff_countColorCond_mem hl] at hc
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· have hc' := hc I h hId
|
||||
simp only [countColorCond] at hc'
|
||||
rw [← countSelf_neq_zero] at h
|
||||
rw [← countSelf_neq_zero, ← countDual_eq_countSelf_Dual]
|
||||
omega
|
||||
· have hIdd : l.countId I.dual = 2 := by
|
||||
rw [← hId]
|
||||
apply countId_congr
|
||||
simp
|
||||
have hc' := (hc I.dual h hIdd).2
|
||||
simp at hc'
|
||||
rw [← countSelf_neq_zero]
|
||||
rw [← countSelf_neq_zero] at h
|
||||
rw [countDual_eq_countSelf_Dual] at hc'
|
||||
simp at hc'
|
||||
omega
|
||||
|
||||
lemma iff_countColorCond (hl : l.OnlyUniqueDuals) :
|
||||
l.ColorCond ↔ ∀ I, l.countSelf I ≠ 0 → l.countId I = 2 → countColorCond l I := by
|
||||
refine Iff.intro (fun h I hIs hi => ?_) (fun h => ?_)
|
||||
· rw [countSelf_neq_zero] at hIs
|
||||
rw [iff_countColorCond_mem hl] at h
|
||||
exact h I hIs hi
|
||||
· rw [iff_countColorCond_mem hl]
|
||||
intro I hmem hi
|
||||
refine h I ?_ hi
|
||||
rw [countSelf_neq_zero]
|
||||
exact hmem
|
||||
|
||||
lemma assoc (h : ColorCond (l ++ l2 ++ l3)) : ColorCond (l ++ (l2 ++ l3)) := by
|
||||
rw [← append_assoc]
|
||||
exact h
|
||||
|
||||
lemma symm (hl : (l ++ l2).OnlyUniqueDuals) (h : ColorCond (l ++ l2)) :
|
||||
ColorCond (l2 ++ l) := by
|
||||
rw [iff_countColorCond hl] at h
|
||||
rw [iff_countColorCond (OnlyUniqueDuals.symm' hl)]
|
||||
intro I hI1 hI2
|
||||
have hI' := h I (by simp_all; omega) (by simp_all; omega)
|
||||
simp_all
|
||||
omega
|
||||
|
||||
lemma inl (hl : (l ++ l2).OnlyUniqueDuals) (h : ColorCond (l ++ l2)) : ColorCond l := by
|
||||
rw [iff_countColorCond hl] at h
|
||||
rw [iff_countColorCond (OnlyUniqueDuals.inl hl)]
|
||||
intro I hI1 hI2
|
||||
have hI2' : l2.countId I = 0 := by
|
||||
rw [OnlyUniqueDuals.iff_countId_leq_two'] at hl
|
||||
have hlI := hl I
|
||||
simp at hlI
|
||||
omega
|
||||
have hI' := h I (by
|
||||
simp only [countSelf_append, ne_eq, add_eq_zero, not_and, hI1, false_implies])
|
||||
(by simp_all)
|
||||
simp at hI'
|
||||
rw [l2.countColorQuot_of_countId_zero hI2', l2.countSelf_of_countId_zero hI2',
|
||||
l2.countDual_of_countId_zero hI2', hI2'] at hI'
|
||||
simp at hI'
|
||||
omega
|
||||
|
||||
lemma inr (hl : (l ++ l2).OnlyUniqueDuals) (h : ColorCond (l ++ l2)) : ColorCond l2 := by
|
||||
have hs := symm hl h
|
||||
rw [OnlyUniqueDuals.symm] at hl
|
||||
exact inl hl hs
|
||||
|
||||
lemma swap (hl : (l ++ l2 ++ l3).OnlyUniqueDuals) (h : ColorCond (l ++ l2 ++ l3)) :
|
||||
ColorCond (l2 ++ l ++ l3) := by
|
||||
rw [iff_countColorCond hl] at h
|
||||
rw [iff_countColorCond (OnlyUniqueDuals.swap hl)]
|
||||
intro I hI1 hI2
|
||||
have hI' := h I (by simp_all) (by simp_all; omega)
|
||||
simp_all only [countSelf_append, ne_eq, add_eq_zero, not_and, and_imp, countId_append,
|
||||
countColorCond, countColorQuot_append, countDual_append, not_false_eq_true, implies_true]
|
||||
omega
|
||||
|
||||
/-!
|
||||
|
||||
## Contractions
|
||||
|
||||
-/
|
||||
|
||||
lemma contrIndexList : ColorCond l.contrIndexList := by
|
||||
funext i
|
||||
simp [Option.guard]
|
||||
|
||||
lemma contrIndexList_left (hl : (l ++ l2).OnlyUniqueDuals) (h1 : (l ++ l2).ColorCond) :
|
||||
ColorCond (l.contrIndexList ++ l2) := by
|
||||
rw [iff_countColorCond hl] at h1
|
||||
rw [iff_countColorCond (OnlyUniqueDuals.contrIndexList_left hl)]
|
||||
intro I hI1 hI2
|
||||
simp only [countSelf_append, ne_eq] at hI1
|
||||
have hc := countSelf_contrIndexList_le_countSelf l I
|
||||
have h2 := (countId_eq_two_ofcontrIndexList_left_of_OnlyUniqueDuals l l2 hl I hI2)
|
||||
have hI1' := h1 I (by simp_all; omega) h2
|
||||
have hIdEq : l.contrIndexList.countId I = l.countId I := by
|
||||
simp at h2 hI2
|
||||
omega
|
||||
simp only [countColorCond, countColorQuot_append, countId_append, countSelf_append,
|
||||
countDual_append]
|
||||
rw [l.countColorQuot_contrIndexList_eq_of_countId_eq hIdEq,
|
||||
l.countSelf_contrIndexList_eq_of_countId_eq hIdEq,
|
||||
l.countDual_contrIndexList_eq_of_countId_eq hIdEq, hIdEq]
|
||||
simpa using hI1'
|
||||
|
||||
/-!
|
||||
|
||||
## Bool
|
||||
|
||||
-/
|
||||
/-- A bool which is true for an index list if and only if every index and its' dual, when it exists,
|
||||
have dual colors. -/
|
||||
def bool (l : IndexList 𝓒.Color) : Bool :=
|
||||
if (∀ (i : l.withDual), 𝓒.τ
|
||||
(l.colorMap ((l.getDual? i).get (l.withDual_isSome i))) = l.colorMap i) then
|
||||
true
|
||||
else false
|
||||
|
||||
lemma iff_bool : l.ColorCond ↔ bool l := by
|
||||
rw [iff_withDual, bool]
|
||||
simp only [Subtype.forall, mem_withDual_iff_isSome, Bool.if_false_right, Bool.and_true,
|
||||
decide_eq_true_eq]
|
||||
|
||||
end ColorCond
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -0,0 +1,341 @@
|
|||
/-
|
||||
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.IndexList.Equivs
|
||||
import Mathlib.Algebra.Order.Ring.Nat
|
||||
import Mathlib.Data.Finset.Sort
|
||||
import Mathlib.Tactic.FinCases
|
||||
/-!
|
||||
|
||||
# Contraction of an index list.
|
||||
|
||||
In this file we define the contraction of an index list `l` to be the index list formed by
|
||||
by the subset of indices of `l` which do not have a dual in `l`.
|
||||
|
||||
For example, the contraction of the index list `['ᵘ¹', 'ᵘ²', 'ᵤ₁', 'ᵘ¹']` is the index list
|
||||
`['ᵘ²']`.
|
||||
|
||||
We also define the following finite sets
|
||||
- `l.withoutDual` the finite set of indices of `l` which do not have a dual in `l`.
|
||||
- `l.withUniqueDualLT` the finite set of those indices of `l` which have a unique dual, and
|
||||
for which that dual is greater-then (determined by the ordering on `Fin`) then the index itself.
|
||||
- `l.withUniqueDualGT` the finite set of those indices of `l` which have a unique dual, and
|
||||
for which that dual is less-then (determined by the ordering on `Fin`) then the index itself.
|
||||
|
||||
We define an equivalence `l.withUniqueDualLT ⊕ l.withUniqueDualLT ≃ l.withUniqueDual`.
|
||||
|
||||
We prove properties related to when `l.withUniqueDualInOther l2 = Finset.univ` for two
|
||||
index lists `l` and `l2`.
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
/-- The index list formed from `l` by selecting only those indices in `l` which
|
||||
do not have a dual. -/
|
||||
def contrIndexList : IndexList X where
|
||||
val := l.val.filter (fun I => l.countId I = 1)
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_empty : (⟨[]⟩ : IndexList X).contrIndexList = { val := [] } := by
|
||||
apply ext
|
||||
simp [contrIndexList]
|
||||
|
||||
lemma contrIndexList_val : l.contrIndexList.val =
|
||||
l.val.filter (fun I => l.countId I = 1) := by
|
||||
rfl
|
||||
|
||||
/-- An alternative form of the contracted index list. -/
|
||||
@[simp]
|
||||
def contrIndexList' : IndexList X where
|
||||
val := List.ofFn (l.val.get ∘ Subtype.val ∘ l.withoutDualEquiv)
|
||||
|
||||
lemma withoutDual_sort_eq_filter : l.withoutDual.sort (fun i j => i ≤ j) =
|
||||
(List.finRange l.length).filter (fun i => i ∈ l.withoutDual) := by
|
||||
rw [withoutDual]
|
||||
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
|
||||
|
||||
lemma contrIndexList_eq_contrIndexList' : l.contrIndexList = l.contrIndexList' := by
|
||||
apply ext
|
||||
simp only [contrIndexList']
|
||||
trans List.map l.val.get (List.ofFn (Subtype.val ∘ ⇑l.withoutDualEquiv))
|
||||
· rw [list_ofFn_withoutDualEquiv_eq_sort, withoutDual_sort_eq_filter]
|
||||
simp only [contrIndexList]
|
||||
let f1 : Index X → Bool := fun (I : Index X) => l.countId I = 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 := by
|
||||
funext i
|
||||
simp only [mem_withoutDual_iff_countId_eq_one l, List.get_eq_getElem, Function.comp_apply, f2,
|
||||
f1]
|
||||
rw [hf, ← List.filter_map]
|
||||
apply congrArg
|
||||
simp [length]
|
||||
· simp only [List.map_ofFn]
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_length : l.contrIndexList.length = l.withoutDual.card := by
|
||||
simp [contrIndexList_eq_contrIndexList', withoutDual, length]
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_idMap (i : Fin l.contrIndexList.length) : l.contrIndexList.idMap i
|
||||
= l.idMap (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)).1 := by
|
||||
simp [contrIndexList_eq_contrIndexList', idMap]
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_colorMap (i : Fin l.contrIndexList.length) : l.contrIndexList.colorMap i
|
||||
= l.colorMap (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)).1 := by
|
||||
simp [contrIndexList_eq_contrIndexList', colorMap]
|
||||
rfl
|
||||
|
||||
lemma contrIndexList_areDualInSelf (i j : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.AreDualInSelf i j ↔
|
||||
l.AreDualInSelf (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)).1
|
||||
(l.withoutDualEquiv (Fin.cast l.contrIndexList_length j)).1 := by
|
||||
simp [AreDualInSelf]
|
||||
intro _
|
||||
trans ¬ (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)) =
|
||||
(l.withoutDualEquiv (Fin.cast l.contrIndexList_length j))
|
||||
· rw [l.withoutDualEquiv.apply_eq_iff_eq]
|
||||
simp [Fin.ext_iff]
|
||||
· exact Iff.symm Subtype.coe_ne_coe
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_getDual? (i : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.getDual? i = none := by
|
||||
rw [← Option.not_isSome_iff_eq_none, ← mem_withDual_iff_isSome, mem_withDual_iff_exists]
|
||||
simp only [contrIndexList_areDualInSelf, not_exists]
|
||||
have h1 := (l.withoutDualEquiv (Fin.cast l.contrIndexList_length i)).2
|
||||
have h1' := Finset.disjoint_right.mp l.withDual_disjoint_withoutDual h1
|
||||
rw [mem_withDual_iff_exists] at h1'
|
||||
exact fun x => forall_not_of_not_exists h1'
|
||||
↑(l.withoutDualEquiv (Fin.cast (contrIndexList_length l) x))
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_withDual : l.contrIndexList.withDual = ∅ := by
|
||||
rw [Finset.eq_empty_iff_forall_not_mem]
|
||||
intro x
|
||||
simp [withDual]
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_withUniqueDual : l.contrIndexList.withUniqueDual = ∅ := by
|
||||
rw [withUniqueDual]
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_areDualInSelf_false (i j : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.AreDualInSelf i j ↔ False := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => False.elim h)
|
||||
have h1 : i ∈ l.contrIndexList.withDual := by
|
||||
rw [@mem_withDual_iff_exists]
|
||||
exact Exists.intro j h
|
||||
simp_all
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_of_withDual_empty (h : l.withDual = ∅) : l.contrIndexList = l := by
|
||||
have h1 := l.withDual_union_withoutDual
|
||||
rw [h, Finset.empty_union] at h1
|
||||
apply ext
|
||||
rw [@List.ext_get_iff]
|
||||
change l.contrIndexList.length = l.length ∧ _
|
||||
rw [contrIndexList_length, h1]
|
||||
simp only [Finset.card_univ, Fintype.card_fin, List.get_eq_getElem, true_and]
|
||||
intro n h1' h2
|
||||
simp [contrIndexList_eq_contrIndexList']
|
||||
congr
|
||||
simp [withoutDualEquiv]
|
||||
simp [h1]
|
||||
rw [(Finset.orderEmbOfFin_unique' _
|
||||
(fun x => Finset.mem_univ ((Fin.castOrderIso _).toOrderEmbedding x))).symm]
|
||||
· exact Eq.symm (Nat.add_zero n)
|
||||
· rw [h1]
|
||||
exact Finset.card_fin l.length
|
||||
|
||||
lemma contrIndexList_contrIndexList : l.contrIndexList.contrIndexList = l.contrIndexList := by
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
lemma contrIndexList_getDualInOther?_self (i : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.getDualInOther? l.contrIndexList i = some i := by
|
||||
simp [getDualInOther?]
|
||||
rw [@Fin.find_eq_some_iff]
|
||||
simp [AreDualInOther]
|
||||
intro j hj
|
||||
have h1 : i = j := by
|
||||
by_contra hn
|
||||
have h : l.contrIndexList.AreDualInSelf i j := by
|
||||
simp only [AreDualInSelf]
|
||||
simp [hj]
|
||||
exact hn
|
||||
exact (contrIndexList_areDualInSelf_false l i j).mp h
|
||||
exact Fin.ge_of_eq (id (Eq.symm h1))
|
||||
|
||||
lemma cons_contrIndexList_of_countId_eq_zero {I : Index X}
|
||||
(h : l.countId I = 0) :
|
||||
(l.cons I).contrIndexList = l.contrIndexList.cons I := by
|
||||
apply ext
|
||||
simp [contrIndexList, countId]
|
||||
rw [List.filter_cons_of_pos]
|
||||
· apply congrArg
|
||||
apply List.filter_congr
|
||||
intro J hJ
|
||||
simp only [decide_eq_decide]
|
||||
rw [countId, List.countP_eq_zero] at h
|
||||
simp only [decide_eq_true_eq] at h
|
||||
rw [List.countP_cons_of_neg]
|
||||
simp only [decide_eq_true_eq]
|
||||
exact fun a => h J hJ (id (Eq.symm a))
|
||||
· simp only [decide_True, List.countP_cons_of_pos, add_left_eq_self, decide_eq_true_eq]
|
||||
exact h
|
||||
|
||||
lemma cons_contrIndexList_of_countId_neq_zero {I : Index X} (h : l.countId I ≠ 0) :
|
||||
(l.cons I).contrIndexList.val = l.contrIndexList.val.filter (fun J => ¬ I.id = J.id) := by
|
||||
simp only [contrIndexList, countId, cons_val, decide_not, List.filter_filter, Bool.not_eq_true',
|
||||
decide_eq_false_iff_not, decide_eq_true_eq, Bool.decide_and]
|
||||
rw [List.filter_cons_of_neg]
|
||||
· apply List.filter_congr
|
||||
intro J hJ
|
||||
by_cases hI : I.id = J.id
|
||||
· simp only [hI, decide_True, List.countP_cons_of_pos, add_left_eq_self, Bool.not_true,
|
||||
Bool.false_and, decide_eq_false_iff_not, countId]
|
||||
rw [countId, hI] at h
|
||||
simp only [h, not_false_eq_true]
|
||||
· simp only [hI, decide_False, Bool.not_false, Bool.true_and, decide_eq_decide]
|
||||
rw [List.countP_cons_of_neg]
|
||||
simp only [decide_eq_true_eq]
|
||||
exact fun a => hI (id (Eq.symm a))
|
||||
· simp only [decide_True, List.countP_cons_of_pos, add_left_eq_self, decide_eq_true_eq]
|
||||
exact h
|
||||
|
||||
lemma mem_contrIndexList_countId {I : Index X} (h : I ∈ l.contrIndexList.val) :
|
||||
l.countId I = 1 := by
|
||||
simp only [contrIndexList, List.mem_filter, decide_eq_true_eq] at h
|
||||
exact h.2
|
||||
|
||||
lemma mem_contrIndexList_filter {I : Index X} (h : I ∈ l.contrIndexList.val) :
|
||||
l.val.filter (fun J => I.id = J.id) = [I] := by
|
||||
have h1 : (l.val.filter (fun J => I.id = J.id)).length = 1 := by
|
||||
rw [← List.countP_eq_length_filter]
|
||||
exact l.mem_contrIndexList_countId h
|
||||
have h2 : I ∈ l.val.filter (fun J => I.id = J.id) := by
|
||||
simp only [List.mem_filter, decide_True, and_true]
|
||||
simp only [contrIndexList, List.mem_filter, decide_eq_true_eq] at h
|
||||
exact h.1
|
||||
rw [List.length_eq_one] at h1
|
||||
obtain ⟨J, hJ⟩ := h1
|
||||
rw [hJ] at h2
|
||||
simp at h2
|
||||
subst h2
|
||||
exact hJ
|
||||
|
||||
lemma mem_contrIndexList_countId_contrIndexList {I : Index X} (h : I ∈ l.contrIndexList.val) :
|
||||
l.contrIndexList.countId I = 1 := by
|
||||
trans (l.val.filter (fun J => I.id = J.id)).countP
|
||||
(fun i => l.val.countP (fun j => i.id = j.id) = 1)
|
||||
· rw [contrIndexList]
|
||||
simp only [countId]
|
||||
rw [List.countP_filter, List.countP_filter]
|
||||
simp only [decide_eq_true_eq, Bool.decide_and]
|
||||
congr
|
||||
funext a
|
||||
rw [Bool.and_comm]
|
||||
· rw [l.mem_contrIndexList_filter h, List.countP_cons_of_pos]
|
||||
· rfl
|
||||
· simp only [decide_eq_true_eq]
|
||||
exact mem_contrIndexList_countId l h
|
||||
|
||||
lemma countId_contrIndexList_zero_of_countId (I : Index X)
|
||||
(h : l.countId I = 0) : l.contrIndexList.countId I = 0 := by
|
||||
trans (l.val.filter (fun J => I.id = J.id)).countP
|
||||
(fun i => l.val.countP (fun j => i.id = j.id) = 1)
|
||||
· rw [contrIndexList]
|
||||
simp only [countId]
|
||||
rw [List.countP_filter, List.countP_filter]
|
||||
simp only [decide_eq_true_eq, Bool.decide_and]
|
||||
congr
|
||||
funext a
|
||||
rw [Bool.and_comm]
|
||||
· rw [countId_eq_length_filter, List.length_eq_zero] at h
|
||||
rw [h]
|
||||
simp only [List.countP_nil]
|
||||
|
||||
lemma countId_contrIndexList_le_one (I : Index X) :
|
||||
l.contrIndexList.countId I ≤ 1 := by
|
||||
by_cases h : l.contrIndexList.countId I = 0
|
||||
· simp [h]
|
||||
· obtain ⟨I', hI1, hI2⟩ := countId_neq_zero_mem l.contrIndexList I h
|
||||
rw [countId_congr l.contrIndexList hI2, mem_contrIndexList_countId_contrIndexList l hI1]
|
||||
|
||||
lemma countId_contrIndexList_eq_one_iff_countId_eq_one (I : Index X) :
|
||||
l.contrIndexList.countId I = 1 ↔ l.countId I = 1 := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· obtain ⟨I', hI1, hI2⟩ := countId_neq_zero_mem l.contrIndexList I (by omega)
|
||||
simp [contrIndexList] at hI1
|
||||
rw [countId_congr l hI2]
|
||||
exact hI1.2
|
||||
· obtain ⟨I', hI1, hI2⟩ := countId_neq_zero_mem l I (by omega)
|
||||
rw [countId_congr l hI2] at h
|
||||
rw [countId_congr _ hI2]
|
||||
refine mem_contrIndexList_countId_contrIndexList l ?_
|
||||
simp [contrIndexList]
|
||||
exact ⟨hI1, h⟩
|
||||
|
||||
lemma countId_contrIndexList_le_countId (I : Index X) :
|
||||
l.contrIndexList.countId I ≤ l.countId I := by
|
||||
by_cases h : l.contrIndexList.countId I = 0
|
||||
· exact StrictMono.minimal_preimage_bot (fun ⦃a b⦄ a => a) h (l.countId I)
|
||||
· have ho : l.contrIndexList.countId I = 1 := by
|
||||
have h1 := l.countId_contrIndexList_le_one I
|
||||
omega
|
||||
rw [ho]
|
||||
rw [countId_contrIndexList_eq_one_iff_countId_eq_one] at ho
|
||||
rw [ho]
|
||||
|
||||
@[simp]
|
||||
lemma countId_contrIndexList_get (i : Fin l.contrIndexList.length) :
|
||||
l.contrIndexList.countId l.contrIndexList.val[Fin.val i] = 1 := by
|
||||
refine mem_contrIndexList_countId_contrIndexList l ?_
|
||||
exact List.getElem_mem l.contrIndexList.val (↑i) _
|
||||
|
||||
lemma filter_id_contrIndexList_eq_of_countId_contrIndexList (I : Index X)
|
||||
(h : l.contrIndexList.countId I = l.countId I) :
|
||||
l.contrIndexList.val.filter (fun J => I.id = J.id) =
|
||||
l.val.filter (fun J => I.id = J.id) := by
|
||||
apply List.Sublist.eq_of_length
|
||||
· rw [contrIndexList, List.filter_comm]
|
||||
exact List.filter_sublist (List.filter (fun J => decide (I.id = J.id)) l.val)
|
||||
· rw [← countId_eq_length_filter, h, countId_eq_length_filter]
|
||||
|
||||
lemma contrIndexList_append_eq_filter : (l ++ l2).contrIndexList.val =
|
||||
l.contrIndexList.val.filter (fun I => l2.countId I = 0) ++
|
||||
l2.contrIndexList.val.filter (fun I => l.countId I = 0) := by
|
||||
simp [contrIndexList]
|
||||
congr 1
|
||||
· apply List.filter_congr
|
||||
intro I hI
|
||||
have hIz : l.countId I ≠ 0 := countId_mem l I hI
|
||||
have hx : l.countId I + l2.countId I = 1 ↔ (l2.countId I = 0 ∧ l.countId I = 1) := by
|
||||
omega
|
||||
simp only [hx, Bool.decide_and]
|
||||
· apply List.filter_congr
|
||||
intro I hI
|
||||
have hIz : l2.countId I ≠ 0 := countId_mem l2 I hI
|
||||
have hx : l.countId I + l2.countId I = 1 ↔ (l2.countId I = 1 ∧ l.countId I = 0) := by
|
||||
omega
|
||||
simp only [hx, Bool.decide_and]
|
||||
exact Bool.and_comm (decide (l2.countId I = 1)) (decide (l.countId I = 0))
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -0,0 +1,535 @@
|
|||
/-
|
||||
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.IndexList.Duals
|
||||
/-!
|
||||
|
||||
# Counting ids
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
/-!
|
||||
|
||||
## countId
|
||||
|
||||
-/
|
||||
|
||||
/-- The number of times the id of an index `I` appears in a list of indices `l`. -/
|
||||
def countId (I : Index X) : ℕ :=
|
||||
l.val.countP (fun J => I.id = J.id)
|
||||
|
||||
/-!
|
||||
|
||||
## Basic properties
|
||||
|
||||
-/
|
||||
@[simp]
|
||||
lemma countId_append (I : Index X) : (l ++ l2).countId I = l.countId I + l2.countId I := by
|
||||
simp [countId]
|
||||
|
||||
lemma countId_eq_length_filter (I : Index X) :
|
||||
l.countId I = (l.val.filter (fun J => I.id = J.id)).length := by
|
||||
simp [countId]
|
||||
rw [List.countP_eq_length_filter]
|
||||
|
||||
lemma countId_index_neq_zero (i : Fin l.length) : l.countId (l.val.get i) ≠ 0 := by
|
||||
rw [countId_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
|
||||
|
||||
lemma countId_append_symm (I : Index X) : (l ++ l2).countId I = (l2 ++ l).countId I := by
|
||||
simp only [countId_append]
|
||||
omega
|
||||
|
||||
lemma countId_eq_one_append_mem_right_self_eq_one {I : Index X} (hI : I ∈ l2.val)
|
||||
(h : (l ++ l2).countId I = 1) : l2.countId I = 1 := by
|
||||
simp at h
|
||||
have hmem : I ∈ l2.val.filter (fun J => I.id = J.id) := by
|
||||
simp [List.mem_filter, decide_True, and_true, hI]
|
||||
have h1 : l2.countId I ≠ 0 := by
|
||||
rw [countId_eq_length_filter]
|
||||
by_contra hn
|
||||
rw [@List.length_eq_zero] at hn
|
||||
rw [hn] at hmem
|
||||
simp at hmem
|
||||
omega
|
||||
|
||||
lemma countId_eq_one_append_mem_right_other_eq_zero {I : Index X} (hI : I ∈ l2.val)
|
||||
(h : (l ++ l2).countId I = 1) : l.countId I = 0 := by
|
||||
simp at h
|
||||
have hmem : I ∈ l2.val.filter (fun J => I.id = J.id) := by
|
||||
simp [List.mem_filter, decide_True, and_true, hI]
|
||||
have h1 : l2.countId I ≠ 0 := by
|
||||
rw [countId_eq_length_filter]
|
||||
by_contra hn
|
||||
rw [@List.length_eq_zero] at hn
|
||||
rw [hn] at hmem
|
||||
simp at hmem
|
||||
omega
|
||||
|
||||
@[simp]
|
||||
lemma countId_cons_eq_two {I : Index X} :
|
||||
(l.cons I).countId I = 2 ↔ l.countId I = 1 := by
|
||||
simp [countId]
|
||||
|
||||
lemma countId_congr {I J : Index X} (h : I.id = J.id) : l.countId I = l.countId J := by
|
||||
simp [countId, h]
|
||||
|
||||
lemma countId_neq_zero_mem (I : Index X) (h : l.countId I ≠ 0) :
|
||||
∃ I', I' ∈ l.val ∧ I.id = I'.id := by
|
||||
rw [countId_eq_length_filter] at h
|
||||
have h' := List.isEmpty_iff_length_eq_zero.mp.mt h
|
||||
simp only at h'
|
||||
have h'' := eq_false_of_ne_true h'
|
||||
rw [List.isEmpty_false_iff_exists_mem] at h''
|
||||
obtain ⟨I', hI'⟩ := h''
|
||||
simp only [List.mem_filter, decide_eq_true_eq] at hI'
|
||||
exact ⟨I', hI'⟩
|
||||
|
||||
lemma countId_mem (I : Index X) (hI : I ∈ l.val) : l.countId I ≠ 0 := by
|
||||
rw [countId_eq_length_filter]
|
||||
by_contra hn
|
||||
rw [List.length_eq_zero] at hn
|
||||
have hIme : I ∈ List.filter (fun J => decide (I.id = J.id)) l.val := by
|
||||
simp [hI]
|
||||
rw [hn] at hIme
|
||||
simp at hIme
|
||||
|
||||
lemma countId_get_other (i : Fin l.length) : l2.countId (l.val.get i) =
|
||||
(List.finRange l2.length).countP (fun j => l.AreDualInOther l2 i j) := by
|
||||
rw [countId_eq_length_filter]
|
||||
rw [List.countP_eq_length_filter]
|
||||
have hl2 : l2.val = List.map l2.val.get (List.finRange l2.length) := by
|
||||
simp only [length, List.finRange_map_get]
|
||||
nth_rewrite 1 [hl2]
|
||||
rw [List.filter_map, List.length_map]
|
||||
apply congrArg
|
||||
refine List.filter_congr (fun j _ => ?_)
|
||||
simp [AreDualInOther, idMap]
|
||||
|
||||
/-! TODO: Replace with mathlib lemma. -/
|
||||
lemma filter_finRange (i : Fin l.length) :
|
||||
List.filter (fun j => i = j) (List.finRange l.length) = [i] := by
|
||||
have h3 : (List.filter (fun j => i = j) (List.finRange l.length)).length = 1 := by
|
||||
rw [← List.countP_eq_length_filter]
|
||||
trans List.count i (List.finRange l.length)
|
||||
· simp [List.count]
|
||||
apply List.countP_congr (fun j _ => ?_)
|
||||
simp only [decide_eq_true_eq, beq_iff_eq]
|
||||
exact eq_comm
|
||||
· exact List.nodup_iff_count_eq_one.mp (List.nodup_finRange l.length) _ (List.mem_finRange i)
|
||||
have h4 : i ∈ List.filter (fun j => i = j) (List.finRange l.length) := by
|
||||
simp
|
||||
rw [@List.length_eq_one] at h3
|
||||
obtain ⟨a, ha⟩ := h3
|
||||
rw [ha] at h4
|
||||
simp at h4
|
||||
subst h4
|
||||
exact ha
|
||||
|
||||
lemma countId_get (i : Fin l.length) : l.countId (l.val.get i) =
|
||||
(List.finRange l.length).countP (fun j => l.AreDualInSelf i j) + 1 := by
|
||||
rw [countId_get_other l l]
|
||||
have h1 : (List.finRange l.length).countP (fun j => l.AreDualInSelf i j)
|
||||
= ((List.finRange l.length).filter (fun j => l.AreDualInOther l i j)).countP
|
||||
(fun j => ¬ i = j) := by
|
||||
rw [List.countP_filter]
|
||||
refine List.countP_congr ?_
|
||||
intro j _
|
||||
simp [AreDualInSelf, AreDualInOther]
|
||||
rw [h1]
|
||||
have h1 := List.length_eq_countP_add_countP (fun j => i = j)
|
||||
((List.finRange l.length).filter (fun j => l.AreDualInOther l i j))
|
||||
have h2 : List.countP (fun j => i = j)
|
||||
(List.filter (fun j => l.AreDualInOther l i j) (List.finRange l.length)) =
|
||||
List.countP (fun j => l.AreDualInOther l i j)
|
||||
(List.filter (fun j => i = j) (List.finRange l.length)) := by
|
||||
rw [List.countP_filter, List.countP_filter]
|
||||
refine List.countP_congr (fun j _ => ?_)
|
||||
simpa using And.comm
|
||||
have ha := l.filter_finRange
|
||||
rw [ha] at h2
|
||||
rw [h2] at h1
|
||||
rw [List.countP_eq_length_filter, h1, add_comm]
|
||||
simp only [decide_eq_true_eq, decide_not, add_right_inj]
|
||||
simp [List.countP, List.countP.go, AreDualInOther]
|
||||
|
||||
/-!
|
||||
|
||||
## Duals and countId
|
||||
|
||||
-/
|
||||
|
||||
lemma countId_gt_zero_of_mem_withDual (i : Fin l.length) (h : i ∈ l.withDual) :
|
||||
1 < l.countId (l.val.get i) := by
|
||||
rw [countId_get]
|
||||
by_contra hn
|
||||
simp at hn
|
||||
rw [List.countP_eq_length_filter, List.length_eq_zero] at hn
|
||||
rw [mem_withDual_iff_exists] at h
|
||||
obtain ⟨j, hj⟩ := h
|
||||
have hjmem : j ∈ (List.finRange l.length).filter (fun j => decide (l.AreDualInSelf i j)) := by
|
||||
simpa using hj
|
||||
rw [hn] at hjmem
|
||||
simp at hjmem
|
||||
|
||||
lemma countId_of_not_mem_withDual (i : Fin l.length)(h : i ∉ l.withDual) :
|
||||
l.countId (l.val.get i) = 1 := by
|
||||
rw [countId_get]
|
||||
simp only [add_left_eq_self]
|
||||
rw [List.countP_eq_length_filter]
|
||||
simp only [List.length_eq_zero]
|
||||
rw [List.filter_eq_nil]
|
||||
simp only [List.mem_finRange, decide_eq_true_eq, true_implies]
|
||||
rw [mem_withDual_iff_exists] at h
|
||||
simpa using h
|
||||
|
||||
lemma mem_withDual_iff_countId_gt_one (i : Fin l.length) :
|
||||
i ∈ l.withDual ↔ 1 < l.countId (l.val.get i) := by
|
||||
refine Iff.intro (fun h => countId_gt_zero_of_mem_withDual l i h) (fun h => ?_)
|
||||
by_contra hn
|
||||
have hn' := countId_of_not_mem_withDual l i hn
|
||||
omega
|
||||
|
||||
lemma countId_neq_zero_of_mem_withDualInOther (i : Fin l.length) (h : i ∈ l.withDualInOther l2) :
|
||||
l2.countId (l.val.get i) ≠ 0 := by
|
||||
rw [mem_withInDualOther_iff_exists] at h
|
||||
rw [countId_eq_length_filter]
|
||||
by_contra hn
|
||||
rw [List.length_eq_zero] at hn
|
||||
obtain ⟨j, hj⟩ := h
|
||||
have hjmem : l2.val.get j ∈ List.filter (fun J => decide ((l.val.get i).id = J.id)) l2.val := by
|
||||
simp only [List.get_eq_getElem, List.mem_filter, decide_eq_true_eq]
|
||||
apply And.intro
|
||||
· exact List.getElem_mem l2.val (↑j) j.isLt
|
||||
· simpa [AreDualInOther] using hj
|
||||
rw [hn] at hjmem
|
||||
simp at hjmem
|
||||
|
||||
lemma countId_of_not_mem_withDualInOther (i : Fin l.length) (h : i ∉ l.withDualInOther l2) :
|
||||
l2.countId (l.val.get i) = 0 := by
|
||||
by_contra hn
|
||||
rw [countId_eq_length_filter] at hn
|
||||
rw [← List.isEmpty_iff_length_eq_zero] at hn
|
||||
have hx := eq_false_of_ne_true hn
|
||||
rw [List.isEmpty_false_iff_exists_mem] at hx
|
||||
obtain ⟨j, hj⟩ := hx
|
||||
have hjmem : j ∈ l2.val := List.mem_of_mem_filter hj
|
||||
have hj' : l2.val.indexOf j < l2.length := List.indexOf_lt_length.mpr hjmem
|
||||
rw [mem_withInDualOther_iff_exists] at h
|
||||
simp at h
|
||||
have hj' := h ⟨l2.val.indexOf j, hj'⟩
|
||||
simp [AreDualInOther, idMap] at hj'
|
||||
simp at hj
|
||||
simp_all only [List.get_eq_getElem, List.isEmpty_eq_true, List.getElem_indexOf, not_true_eq_false]
|
||||
|
||||
lemma mem_withDualInOther_iff_countId_neq_zero (i : Fin l.length) :
|
||||
i ∈ l.withDualInOther l2 ↔ l2.countId (l.val.get i) ≠ 0 := by
|
||||
refine Iff.intro (fun h => countId_neq_zero_of_mem_withDualInOther l l2 i h)
|
||||
(fun h => ?_)
|
||||
by_contra hn
|
||||
have hn' := countId_of_not_mem_withDualInOther l l2 i hn
|
||||
omega
|
||||
|
||||
lemma mem_withoutDual_iff_countId_eq_one (i : Fin l.length) :
|
||||
i ∈ l.withoutDual ↔ l.countId (l.val.get i) = 1 := by
|
||||
refine Iff.intro (fun h => ?_) (fun h => ?_)
|
||||
· exact countId_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_countId_gt_one] at h
|
||||
omega
|
||||
|
||||
lemma countId_eq_two_of_mem_withUniqueDual (i : Fin l.length) (h : i ∈ l.withUniqueDual) :
|
||||
l.countId (l.val.get i) = 2 := by
|
||||
rw [countId_get]
|
||||
simp only [Nat.reduceEqDiff]
|
||||
let i' := (l.getDual? i).get (mem_withUniqueDual_isSome l i h)
|
||||
have h1 : [i'] = (List.finRange l.length).filter (fun j => (l.AreDualInSelf i j)) := by
|
||||
trans List.filter (fun j => (l.AreDualInSelf i j)) [i']
|
||||
· simp [List.filter, i']
|
||||
trans List.filter (fun j => (l.AreDualInSelf i j))
|
||||
((List.finRange l.length).filter (fun j => j = i'))
|
||||
· apply congrArg
|
||||
rw [← filter_finRange l i']
|
||||
apply List.filter_congr (fun j _ => ?_)
|
||||
simpa using eq_comm
|
||||
trans List.filter (fun j => j = i')
|
||||
((List.finRange l.length).filter (fun j => (l.AreDualInSelf i j)))
|
||||
· simp
|
||||
apply List.filter_congr (fun j _ => ?_)
|
||||
exact Bool.and_comm (decide (l.AreDualInSelf i j)) (decide (j = i'))
|
||||
· simp
|
||||
refine List.filter_congr (fun j _ => ?_)
|
||||
simp only [Bool.and_iff_right_iff_imp, decide_eq_true_eq]
|
||||
simp [withUniqueDual] at h
|
||||
intro hj
|
||||
have hj' := h.2 j hj
|
||||
apply Option.some_injective
|
||||
rw [hj']
|
||||
simp [i']
|
||||
rw [List.countP_eq_length_filter, ← h1]
|
||||
simp
|
||||
|
||||
lemma mem_withUniqueDual_of_countId_eq_two (i : Fin l.length)
|
||||
(h : l.countId (l.val.get i) = 2) : i ∈ l.withUniqueDual := by
|
||||
have hw : i ∈ l.withDual := by
|
||||
rw [mem_withDual_iff_countId_gt_one, h]
|
||||
exact Nat.one_lt_two
|
||||
simp [withUniqueDual]
|
||||
apply And.intro ((mem_withDual_iff_isSome l i).mp hw)
|
||||
intro j hj
|
||||
rw [@countId_get] at h
|
||||
simp [List.countP_eq_length_filter] at h
|
||||
rw [List.length_eq_one] at h
|
||||
obtain ⟨a, ha⟩ := h
|
||||
have hj : j ∈ List.filter (fun j => decide (l.AreDualInSelf i j)) (List.finRange l.length) := by
|
||||
simpa using hj
|
||||
rw [ha] at hj
|
||||
simp at hj
|
||||
subst hj
|
||||
have ht : (l.getDual? i).get ((mem_withDual_iff_isSome l i).mp hw) ∈
|
||||
(List.finRange l.length).filter (fun j => decide (l.AreDualInSelf i j)) := by
|
||||
simp
|
||||
rw [ha] at ht
|
||||
simp at ht
|
||||
subst ht
|
||||
simp
|
||||
|
||||
lemma mem_withUniqueDual_iff_countId_eq_two (i : Fin l.length) :
|
||||
i ∈ l.withUniqueDual ↔ l.countId (l.val.get i) = 2 :=
|
||||
Iff.intro (fun h => l.countId_eq_two_of_mem_withUniqueDual i h)
|
||||
(fun h => l.mem_withUniqueDual_of_countId_eq_two i h)
|
||||
|
||||
lemma countId_eq_one_of_mem_withUniqueDualInOther (i : Fin l.length)
|
||||
(h : i ∈ l.withUniqueDualInOther l2) :
|
||||
l.countId (l.val.get i) = 1 ∧ l2.countId (l.val.get i) = 1 := by
|
||||
let i' := (l.getDualInOther? l2 i).get (mem_withUniqueDualInOther_isSome l l2 i h)
|
||||
have h1 : [i'] = (List.finRange l2.length).filter (fun j => (l.AreDualInOther l2 i j)) := by
|
||||
trans List.filter (fun j => (l.AreDualInOther l2 i j)) [i']
|
||||
· simp [List.filter, i']
|
||||
trans List.filter (fun j => (l.AreDualInOther l2 i j))
|
||||
((List.finRange l2.length).filter (fun j => j = i'))
|
||||
· apply congrArg
|
||||
rw [← filter_finRange l2 i']
|
||||
apply List.filter_congr (fun j _ => ?_)
|
||||
simpa using eq_comm
|
||||
trans List.filter (fun j => j = i')
|
||||
((List.finRange l2.length).filter (fun j => (l.AreDualInOther l2 i j)))
|
||||
· simp
|
||||
apply List.filter_congr (fun j _ => ?_)
|
||||
exact Bool.and_comm (decide (l.AreDualInOther l2 i j)) (decide (j = i'))
|
||||
· simp
|
||||
refine List.filter_congr (fun j _ => ?_)
|
||||
simp [withUniqueDualInOther] at h
|
||||
simp only [Bool.and_iff_right_iff_imp, decide_eq_true_eq]
|
||||
intro hj
|
||||
have hj' := h.2.2 j hj
|
||||
apply Option.some_injective
|
||||
rw [hj']
|
||||
simp [i']
|
||||
apply And.intro
|
||||
· simp only [withUniqueDualInOther, Finset.mem_filter, Finset.mem_univ, true_and] at h
|
||||
rw [mem_withDual_iff_countId_gt_one] at h
|
||||
have h2 := countId_index_neq_zero l i
|
||||
omega
|
||||
· rw [countId_get_other, List.countP_eq_length_filter, ← h1]
|
||||
simp
|
||||
|
||||
lemma mem_withUniqueDualInOther_of_countId_eq_one (i : Fin l.length)
|
||||
(h : l.countId (l.val.get i) = 1 ∧ l2.countId (l.val.get i) = 1) :
|
||||
i ∈ l.withUniqueDualInOther l2 := by
|
||||
have hw : i ∈ l.withDualInOther l2 := by
|
||||
rw [mem_withDualInOther_iff_countId_neq_zero, h.2]
|
||||
exact Nat.one_ne_zero
|
||||
simp only [withUniqueDualInOther, Finset.mem_filter, Finset.mem_univ, true_and]
|
||||
apply And.intro
|
||||
· rw [mem_withDual_iff_countId_gt_one]
|
||||
omega
|
||||
· apply And.intro
|
||||
· rw [mem_withDualInOther_iff_countId_neq_zero]
|
||||
omega
|
||||
· intro j hj
|
||||
have h2 := h.2
|
||||
rw [countId_get_other l l2, List.countP_eq_length_filter, List.length_eq_one] at h2
|
||||
obtain ⟨a, ha⟩ := h2
|
||||
have hj : j ∈ List.filter (fun j => decide (l.AreDualInOther l2 i j))
|
||||
(List.finRange l2.length) := by
|
||||
simpa using hj
|
||||
rw [ha] at hj
|
||||
simp at hj
|
||||
subst hj
|
||||
have ht : (l.getDualInOther? l2 i).get ((mem_withInDualOther_iff_isSome l l2 i).mp hw) ∈
|
||||
(List.finRange l2.length).filter (fun j => decide (l.AreDualInOther l2 i j)) := by
|
||||
simp
|
||||
rw [ha] at ht
|
||||
simp at ht
|
||||
subst ht
|
||||
simp
|
||||
|
||||
lemma mem_withUniqueDualInOther_iff_countId_eq_one (i : Fin l.length) :
|
||||
i ∈ l.withUniqueDualInOther l2 ↔ l.countId (l.val.get i) = 1 ∧ l2.countId (l.val.get i) = 1 :=
|
||||
Iff.intro (fun h => l.countId_eq_one_of_mem_withUniqueDualInOther l2 i h)
|
||||
(fun h => l.mem_withUniqueDualInOther_of_countId_eq_one l2 i h)
|
||||
|
||||
/-!
|
||||
|
||||
## getDual? and countId
|
||||
|
||||
-/
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_countId (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
l.countId (l.val[Fin.val ((l.getDual? i).get h)]) = l.countId (l.val.get i) := by
|
||||
apply countId_congr
|
||||
change l.idMap ((l.getDual? i).get h) = _
|
||||
simp
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_countId_right (i : Fin l.length) (h : (l.getDualInOther? l2 i).isSome) :
|
||||
l2.countId (l2.val[Fin.val ((l.getDualInOther? l2 i).get h)]) = l2.countId (l.val.get i) := by
|
||||
apply countId_congr
|
||||
change l2.idMap ((l.getDualInOther? l2 i).get h) = _
|
||||
simp
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_countId_left (i : Fin l.length) (h : (l.getDualInOther? l2 i).isSome) :
|
||||
l.countId (l2.val[Fin.val ((l.getDualInOther? l2 i).get h)]) = l.countId (l.val.get i) := by
|
||||
apply countId_congr
|
||||
change l2.idMap ((l.getDualInOther? l2 i).get h) = _
|
||||
simp
|
||||
rfl
|
||||
|
||||
lemma getDual?_isSome_of_countId_eq_two {i : Fin l.length}
|
||||
(h : l.countId (l.val.get i) = 2) : (l.getDual? i).isSome := by
|
||||
rw [← l.mem_withUniqueDual_iff_countId_eq_two] at h
|
||||
exact mem_withUniqueDual_isSome l i h
|
||||
|
||||
/-!
|
||||
|
||||
## Filters
|
||||
|
||||
-/
|
||||
|
||||
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 := h
|
||||
rw [countId_eq_length_filter] at hc
|
||||
by_cases hi : i < ((l.getDual? i).get (l.getDual?_isSome_of_countId_eq_two h))
|
||||
· refine Or.inl (List.Sublist.eq_of_length ?_ ?_).symm
|
||||
· 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)],
|
||||
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
|
||||
refine Or.inr (List.Sublist.eq_of_length ?_ ?_).symm
|
||||
· 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
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -0,0 +1,423 @@
|
|||
/-
|
||||
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.IndexList.Basic
|
||||
/-!
|
||||
|
||||
# Indices which are dual in an index list
|
||||
|
||||
Given an list of indices we say two indices are dual if they have the same id.
|
||||
|
||||
For example the `0`, `2` and `3` index in `l₁ := ['ᵘ¹', 'ᵘ²', 'ᵤ₁', 'ᵘ¹']` are pairwise dual to
|
||||
one another. The `1` (`'ᵘ²'`) index is not dual to any other index in the list.
|
||||
|
||||
We also define the notion of dual indices in different lists. For example,
|
||||
the `1` index in `l₁` is dual to the `1` and the `4` indices in
|
||||
`l₂ := ['ᵘ³', 'ᵘ²', 'ᵘ⁴', 'ᵤ₂']`.
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
/-!
|
||||
|
||||
## Definitions
|
||||
|
||||
-/
|
||||
|
||||
/-- Two indices are dual if they are not equivalent, but have the same id. -/
|
||||
def AreDualInSelf (i j : Fin l.length) : Prop :=
|
||||
i ≠ j ∧ l.idMap i = l.idMap j
|
||||
|
||||
instance (i j : Fin l.length) : Decidable (l.AreDualInSelf i j) :=
|
||||
instDecidableAnd
|
||||
|
||||
/-- Two indices in different `IndexLists` are dual to one another if they have the same `id`. -/
|
||||
def AreDualInOther (i : Fin l.length) (j : Fin l2.length) :
|
||||
Prop := l.idMap i = l2.idMap j
|
||||
|
||||
instance {l : IndexList X} {l2 : IndexList X} (i : Fin l.length) (j : Fin l2.length) :
|
||||
Decidable (l.AreDualInOther l2 i j) := (l.idMap i).decEq (l2.idMap j)
|
||||
|
||||
/-- Given an `i`, if a dual exists in the same list,
|
||||
outputs the first such dual, otherwise outputs `none`. -/
|
||||
def getDual? (i : Fin l.length) : Option (Fin l.length) :=
|
||||
Fin.find (fun j => l.AreDualInSelf i j)
|
||||
|
||||
/-- Given an `i`, if a dual exists in the other list,
|
||||
outputs the first such dual, otherwise outputs `none`. -/
|
||||
def getDualInOther? (i : Fin l.length) : Option (Fin l2.length) :=
|
||||
Fin.find (fun j => l.AreDualInOther l2 i j)
|
||||
|
||||
/-- The finite set of indices of an index list which have a dual in that index list. -/
|
||||
def withDual : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => (l.getDual? i).isSome) Finset.univ
|
||||
|
||||
/-- The finite set of indices of an index list which do not have a dual. -/
|
||||
def withoutDual : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => (l.getDual? i).isNone) Finset.univ
|
||||
|
||||
/-- The finite set of indices of an index list which have a dual in another provided index list. -/
|
||||
def withDualInOther : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => (l.getDualInOther? l2 i).isSome) Finset.univ
|
||||
|
||||
/-- The finite set of indices of an index list which have a unique dual in that index list. -/
|
||||
def withUniqueDual : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => i ∈ l.withDual ∧
|
||||
∀ j, l.AreDualInSelf i j → j = l.getDual? i) Finset.univ
|
||||
|
||||
instance (i j : Option (Fin l.length)) : Decidable (i < j) :=
|
||||
match i, j with
|
||||
| none, none => isFalse (fun a => a)
|
||||
| none, some _ => isTrue (by trivial)
|
||||
| some _, none => isFalse (fun a => a)
|
||||
| some i, some j => Fin.decLt i j
|
||||
|
||||
/-- The finite set of those indices of `l` which have a unique dual, and for which
|
||||
that dual is greater-then (determined by the ordering on `Fin`) then the index itself. -/
|
||||
def withUniqueDualLT : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => i < l.getDual? i) l.withUniqueDual
|
||||
|
||||
/-- The finite set of those indices of `l` which have a unique dual, and for which
|
||||
that dual is less-then (determined by the ordering on `Fin`) then the index itself. -/
|
||||
def withUniqueDualGT : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => ¬ i < l.getDual? i) l.withUniqueDual
|
||||
|
||||
/-- The finite set of indices of an index list which have a unique dual in another, provided, index
|
||||
list. -/
|
||||
def withUniqueDualInOther : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => i ∉ l.withDual ∧ i ∈ l.withDualInOther l2
|
||||
∧ (∀ j, l.AreDualInOther l2 i j → j = l.getDualInOther? l2 i)) Finset.univ
|
||||
|
||||
/-!
|
||||
|
||||
## Basic properties
|
||||
|
||||
-/
|
||||
|
||||
@[simp, nolint simpNF]
|
||||
lemma mem_withDual_of_mem_withUniqueDual (i : Fin l.length) (h : i ∈ l.withUniqueDual) :
|
||||
i ∈ l.withDual := by
|
||||
simp only [withUniqueDual, Finset.mem_filter, Finset.mem_univ, true_and] at h
|
||||
simpa using h.1
|
||||
|
||||
lemma mem_withDual_of_withUniqueDual (i : l.withUniqueDual) :
|
||||
i.1 ∈ l.withDual :=
|
||||
mem_withDual_of_mem_withUniqueDual l (↑i) i.2
|
||||
|
||||
lemma not_mem_withDual_of_withUniqueDualInOther (i : l.withUniqueDualInOther l2) :
|
||||
i.1 ∉ l.withDual := by
|
||||
have hi := i.2
|
||||
simp only [withUniqueDualInOther, Finset.univ_eq_attach, Finset.mem_filter, Finset.mem_attach,
|
||||
true_and] at hi
|
||||
exact hi.2.1
|
||||
|
||||
lemma mem_withDualInOther_of_withUniqueDualInOther (i : l.withUniqueDualInOther l2) :
|
||||
i.1 ∈ l.withDualInOther l2 := by
|
||||
have hi := i.2
|
||||
simp only [withUniqueDualInOther, Finset.univ_eq_attach, Finset.mem_filter, Finset.mem_attach,
|
||||
true_and] at hi
|
||||
exact hi.2.2.1
|
||||
|
||||
@[simp]
|
||||
lemma withDual_isSome (i : l.withDual) : (l.getDual? i).isSome := by
|
||||
simpa [withDual] using i.2
|
||||
|
||||
@[simp]
|
||||
lemma mem_withDual_iff_isSome (i : Fin l.length) : i ∈ l.withDual ↔ (l.getDual? i).isSome := by
|
||||
simp [withDual]
|
||||
|
||||
@[simp]
|
||||
lemma mem_withUniqueDual_isSome (i : Fin l.length) (h : i ∈ l.withUniqueDual) :
|
||||
(l.getDual? i).isSome := by
|
||||
simpa [withDual] using mem_withDual_of_mem_withUniqueDual l i h
|
||||
|
||||
@[simp]
|
||||
lemma mem_withInDualOther_iff_isSome (i : Fin l.length) :
|
||||
i ∈ l.withDualInOther l2 ↔ (l.getDualInOther? l2 i).isSome := by
|
||||
simp only [withDualInOther, getDualInOther?, Finset.mem_filter, Finset.mem_univ, true_and]
|
||||
|
||||
@[simp]
|
||||
lemma mem_withUniqueDualInOther_isSome (i : Fin l.length) (hi : i ∈ l.withUniqueDualInOther l2) :
|
||||
(l.getDualInOther? l2 i).isSome := by
|
||||
simp only [withUniqueDualInOther, Finset.mem_filter, Finset.mem_univ, true_and] at hi
|
||||
exact (mem_withInDualOther_iff_isSome l l2 i).mp hi.2.1
|
||||
|
||||
lemma not_mem_withDual_iff_isNone (i : Fin l.length) :
|
||||
i ∉ l.withDual ↔ (l.getDual? i).isNone := by
|
||||
simp only [mem_withDual_iff_isSome, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none]
|
||||
|
||||
lemma mem_withDual_iff_exists : i ∈ l.withDual ↔ ∃ j, l.AreDualInSelf i j := by
|
||||
simp [withDual, Finset.mem_filter, Finset.mem_univ, getDual?]
|
||||
exact Fin.isSome_find_iff
|
||||
|
||||
lemma mem_withInDualOther_iff_exists :
|
||||
i ∈ l.withDualInOther l2 ↔ ∃ (j : Fin l2.length), l.AreDualInOther l2 i j := by
|
||||
simp [withDualInOther, Finset.mem_filter, Finset.mem_univ, getDualInOther?]
|
||||
exact Fin.isSome_find_iff
|
||||
|
||||
lemma withDual_disjoint_withoutDual : Disjoint l.withDual l.withoutDual := by
|
||||
rw [Finset.disjoint_iff_ne]
|
||||
intro a ha b hb
|
||||
by_contra hn
|
||||
subst hn
|
||||
simp_all only [withDual, Finset.mem_filter, Finset.mem_univ, true_and, withoutDual,
|
||||
Option.isNone_iff_eq_none, Option.isSome_none, Bool.false_eq_true]
|
||||
|
||||
lemma not_mem_withDual_of_mem_withoutDual (i : Fin l.length) (h : i ∈ l.withoutDual) :
|
||||
i ∉ l.withDual := by
|
||||
have h1 := l.withDual_disjoint_withoutDual
|
||||
exact Finset.disjoint_right.mp h1 h
|
||||
|
||||
lemma withDual_union_withoutDual : l.withDual ∪ l.withoutDual = Finset.univ := by
|
||||
rw [Finset.eq_univ_iff_forall]
|
||||
intro i
|
||||
by_cases h : (l.getDual? i).isSome
|
||||
· simp [withDual, Finset.mem_filter, Finset.mem_univ, h]
|
||||
· simp at h
|
||||
simp [withoutDual, Finset.mem_filter, Finset.mem_univ, h]
|
||||
|
||||
lemma mem_withUniqueDual_of_mem_withUniqueDualLt (i : Fin l.length) (h : i ∈ l.withUniqueDualLT) :
|
||||
i ∈ l.withUniqueDual := by
|
||||
simp only [withUniqueDualLT, Finset.mem_filter, Finset.mem_univ, true_and] at h
|
||||
exact h.1
|
||||
|
||||
lemma mem_withUniqueDual_of_mem_withUniqueDualGt (i : Fin l.length) (h : i ∈ l.withUniqueDualGT) :
|
||||
i ∈ l.withUniqueDual := by
|
||||
simp only [withUniqueDualGT, Finset.mem_filter, Finset.mem_univ, true_and] at h
|
||||
exact h.1
|
||||
|
||||
lemma withUniqueDualLT_disjoint_withUniqueDualGT :
|
||||
Disjoint l.withUniqueDualLT l.withUniqueDualGT := by
|
||||
rw [Finset.disjoint_iff_inter_eq_empty]
|
||||
exact @Finset.filter_inter_filter_neg_eq (Fin l.length) _ _ _ _ _
|
||||
|
||||
lemma withUniqueDualLT_union_withUniqueDualGT :
|
||||
l.withUniqueDualLT ∪ l.withUniqueDualGT = l.withUniqueDual :=
|
||||
Finset.filter_union_filter_neg_eq _ _
|
||||
/-!
|
||||
## Are dual properties
|
||||
-/
|
||||
|
||||
namespace AreDualInSelf
|
||||
|
||||
variable {l l2 : IndexList X} {i j : Fin l.length}
|
||||
|
||||
instance (i j : Fin l.length) : Decidable (l.AreDualInSelf i j) :=
|
||||
instDecidableAnd
|
||||
|
||||
@[symm]
|
||||
lemma symm (h : l.AreDualInSelf i j) : l.AreDualInSelf j i := by
|
||||
simp only [AreDualInSelf] at h ⊢
|
||||
exact ⟨h.1.symm, h.2.symm⟩
|
||||
|
||||
@[simp]
|
||||
lemma self_false (i : Fin l.length) : ¬ l.AreDualInSelf i i := by
|
||||
simp [AreDualInSelf]
|
||||
|
||||
@[simp]
|
||||
lemma append_inl_inl : (l ++ l2).AreDualInSelf (appendEquiv (Sum.inl i)) (appendEquiv (Sum.inl j))
|
||||
↔ l.AreDualInSelf i j := by
|
||||
simp [AreDualInSelf]
|
||||
|
||||
@[simp]
|
||||
lemma append_inr_inr (l l2 : IndexList X) (i j : Fin l2.length) :
|
||||
(l ++ l2).AreDualInSelf (appendEquiv (Sum.inr i)) (appendEquiv (Sum.inr j))
|
||||
↔ l2.AreDualInSelf i j := by
|
||||
simp [AreDualInSelf]
|
||||
|
||||
@[simp]
|
||||
lemma append_inl_inr (l l2 : IndexList X) (i : Fin l.length) (j : Fin l2.length) :
|
||||
(l ++ l2).AreDualInSelf (appendEquiv (Sum.inl i)) (appendEquiv (Sum.inr j)) =
|
||||
l.AreDualInOther l2 i j := by
|
||||
simp [AreDualInSelf, AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma append_inr_inl (l l2 : IndexList X) (i : Fin l2.length) (j : Fin l.length) :
|
||||
(l ++ l2).AreDualInSelf (appendEquiv (Sum.inr i)) (appendEquiv (Sum.inl j)) =
|
||||
l2.AreDualInOther l i j := by
|
||||
simp [AreDualInSelf, AreDualInOther]
|
||||
|
||||
end AreDualInSelf
|
||||
|
||||
namespace AreDualInOther
|
||||
|
||||
variable {l l2 l3 : IndexList X} {i : Fin l.length} {j : Fin l2.length}
|
||||
|
||||
instance {l : IndexList X} {l2 : IndexList X} (i : Fin l.length) (j : Fin l2.length) :
|
||||
Decidable (l.AreDualInOther l2 i j) := (l.idMap i).decEq (l2.idMap j)
|
||||
|
||||
@[symm]
|
||||
lemma symm (h : l.AreDualInOther l2 i j) : l2.AreDualInOther l j i := by
|
||||
rw [AreDualInOther] at h ⊢
|
||||
exact h.symm
|
||||
|
||||
@[simp]
|
||||
lemma append_of_inl (i : Fin l.length) (j : Fin l3.length) :
|
||||
(l ++ l2).AreDualInOther l3 (appendEquiv (Sum.inl i)) j ↔ l.AreDualInOther l3 i j := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma append_of_inr (i : Fin l2.length) (j : Fin l3.length) :
|
||||
(l ++ l2).AreDualInOther l3 (appendEquiv (Sum.inr i)) j ↔ l2.AreDualInOther l3 i j := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma of_append_inl (i : Fin l.length) (j : Fin l2.length) :
|
||||
l.AreDualInOther (l2 ++ l3) i (appendEquiv (Sum.inl j)) ↔ l.AreDualInOther l2 i j := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma of_append_inr (i : Fin l.length) (j : Fin l3.length) :
|
||||
l.AreDualInOther (l2 ++ l3) i (appendEquiv (Sum.inr j)) ↔ l.AreDualInOther l3 i j := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
end AreDualInOther
|
||||
|
||||
/-!
|
||||
|
||||
## Basic properties of getDual?
|
||||
|
||||
-/
|
||||
|
||||
lemma getDual?_isSome_iff_exists (i : Fin l.length) :
|
||||
(l.getDual? i).isSome ↔ ∃ j, l.AreDualInSelf i j := by
|
||||
rw [getDual?, Fin.isSome_find_iff]
|
||||
|
||||
lemma getDual?_of_areDualInSelf (h : l.AreDualInSelf i j) :
|
||||
l.getDual? j = i ∨ l.getDual? i = j ∨ l.getDual? j = l.getDual? i := by
|
||||
have h3 : (l.getDual? i).isSome := by
|
||||
simpa [getDual?, Fin.isSome_find_iff] using ⟨j, h⟩
|
||||
obtain ⟨k, hk⟩ := Option.isSome_iff_exists.mp h3
|
||||
rw [hk]
|
||||
rw [getDual?, Fin.find_eq_some_iff] at hk
|
||||
by_cases hik : i < k
|
||||
· apply Or.inl
|
||||
rw [getDual?, Fin.find_eq_some_iff]
|
||||
apply And.intro h.symm
|
||||
intro k' hk'
|
||||
by_cases hik' : i = k'
|
||||
· exact Fin.ge_of_eq (id (Eq.symm hik'))
|
||||
· have hik'' : l.AreDualInSelf i k' := by
|
||||
simp [AreDualInSelf, hik']
|
||||
simp_all [AreDualInSelf]
|
||||
have hk'' := hk.2 k' hik''
|
||||
exact (lt_of_lt_of_le hik hk'').le
|
||||
· by_cases hjk : j ≤ k
|
||||
· apply Or.inr
|
||||
apply Or.inl
|
||||
have hj := hk.2 j h
|
||||
simp only [Option.some.injEq]
|
||||
exact Fin.le_antisymm hj hjk
|
||||
· apply Or.inr
|
||||
apply Or.inr
|
||||
rw [getDual?, Fin.find_eq_some_iff]
|
||||
apply And.intro
|
||||
· simp_all [AreDualInSelf]
|
||||
exact Fin.ne_of_gt hjk
|
||||
intro k' hk'
|
||||
by_cases hik' : i = k'
|
||||
· subst hik'
|
||||
exact Lean.Omega.Fin.le_of_not_lt hik
|
||||
· have hik'' : l.AreDualInSelf i k' := by
|
||||
simp [AreDualInSelf, hik']
|
||||
simp_all [AreDualInSelf]
|
||||
exact hk.2 k' hik''
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_neq_self (i : Fin l.length) : ¬ l.getDual? i = some i := by
|
||||
intro h
|
||||
simp [getDual?] at h
|
||||
rw [Fin.find_eq_some_iff] at h
|
||||
simp [AreDualInSelf] at h
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_get_neq_self (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
¬ (l.getDual? i).get h = i := by
|
||||
have h1 := l.getDual?_neq_self i
|
||||
by_contra hn
|
||||
have h' : l.getDual? i = some i := by
|
||||
nth_rewrite 2 [← hn]
|
||||
exact Option.eq_some_of_isSome h
|
||||
exact h1 h'
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_get_id (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
l.idMap ((l.getDual? i).get h) = l.idMap i := by
|
||||
have h1 : l.getDual? i = some ((l.getDual? i).get h) := Option.eq_some_of_isSome h
|
||||
nth_rewrite 1 [getDual?] at h1
|
||||
rw [Fin.find_eq_some_iff] at h1
|
||||
simp [AreDualInSelf] at h1
|
||||
exact h1.1.2.symm
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_get_areDualInSelf (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
l.AreDualInSelf ((l.getDual? i).get h) i := by
|
||||
simp [AreDualInSelf]
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_areDualInSelf_get (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
l.AreDualInSelf i ((l.getDual? i).get h) :=
|
||||
AreDualInSelf.symm (getDual?_get_areDualInSelf l i h)
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_getDual?_get_isSome (i : Fin l.length) (h : (l.getDual? i).isSome) :
|
||||
(l.getDual? ((l.getDual? i).get h)).isSome := by
|
||||
rw [getDual?, Fin.isSome_find_iff]
|
||||
exact ⟨i, getDual?_get_areDualInSelf l i h⟩
|
||||
|
||||
/-!
|
||||
|
||||
## Basic properties of getDualInOther?
|
||||
|
||||
-/
|
||||
|
||||
lemma getDualInOther?_isSome_iff_exists (i : Fin l.length) :
|
||||
(l.getDualInOther? l2 i).isSome ↔ ∃ j, l.AreDualInOther l2 i j := by
|
||||
rw [getDualInOther?, Fin.isSome_find_iff]
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_id (i : Fin l.length) (h : (l.getDualInOther? l2 i).isSome) :
|
||||
l2.idMap ((l.getDualInOther? l2 i).get h) = l.idMap i := by
|
||||
have h1 : l.getDualInOther? l2 i = some ((l.getDualInOther? l2 i).get h) :=
|
||||
Option.eq_some_of_isSome h
|
||||
nth_rewrite 1 [getDualInOther?] at h1
|
||||
rw [Fin.find_eq_some_iff] at h1
|
||||
simp [AreDualInOther] at h1
|
||||
exact h1.1.symm
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_get_areDualInOther (i : Fin l.length) (h : (l.getDualInOther? l2 i).isSome) :
|
||||
l2.AreDualInOther l ((l.getDualInOther? l2 i).get h) i := by
|
||||
simp [AreDualInOther]
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_areDualInOther_get (i : Fin l.length) (h : (l.getDualInOther? l2 i).isSome) :
|
||||
l.AreDualInOther l2 i ((l.getDualInOther? l2 i).get h) :=
|
||||
AreDualInOther.symm (getDualInOther?_get_areDualInOther l l2 i h)
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_getDualInOther?_get_isSome (i : Fin l.length)
|
||||
(h : (l.getDualInOther? l2 i).isSome) :
|
||||
(l2.getDualInOther? l ((l.getDualInOther? l2 i).get h)).isSome := by
|
||||
rw [getDualInOther?, Fin.isSome_find_iff]
|
||||
exact ⟨i, getDualInOther?_get_areDualInOther l l2 i h⟩
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOther?_self_isSome (i : Fin l.length) :
|
||||
(l.getDualInOther? l i).isSome := by
|
||||
simp [getDualInOther?]
|
||||
rw [@Fin.isSome_find_iff]
|
||||
exact ⟨i, rfl⟩
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -0,0 +1,269 @@
|
|||
/-
|
||||
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.IndexList.CountId
|
||||
import Mathlib.Data.Finset.Sort
|
||||
import Mathlib.Tactic.FinCases
|
||||
/-!
|
||||
|
||||
# Equivalences between finsets.
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
/-!
|
||||
|
||||
## withoutDualEquiv
|
||||
-/
|
||||
|
||||
/-- An equivalence from `Fin l.withoutDual.card` to `l.withoutDual` determined by
|
||||
the order on `l.withoutDual` inherted from `Fin`. -/
|
||||
def withoutDualEquiv : Fin l.withoutDual.card ≃ l.withoutDual :=
|
||||
(Finset.orderIsoOfFin l.withoutDual (by rfl)).toEquiv
|
||||
|
||||
lemma list_ofFn_withoutDualEquiv_eq_sort :
|
||||
List.ofFn (Subtype.val ∘ l.withoutDualEquiv) = l.withoutDual.sort (fun i j => i ≤ j) := by
|
||||
rw [@List.ext_get_iff]
|
||||
refine And.intro ?_ (fun n h1 h2 => ?_)
|
||||
· simp only [List.length_ofFn, Finset.length_sort]
|
||||
· simp only [List.get_eq_getElem, List.getElem_ofFn, Function.comp_apply]
|
||||
rfl
|
||||
|
||||
/-- An equivalence splitting the indices of an index list `l` into those indices
|
||||
which have a dual in `l` and those which do not have a dual in `l`. -/
|
||||
def dualEquiv : l.withDual ⊕ Fin l.withoutDual.card ≃ Fin l.length :=
|
||||
(Equiv.sumCongr (Equiv.refl _) l.withoutDualEquiv).trans <|
|
||||
(Equiv.Finset.union _ _ l.withDual_disjoint_withoutDual).trans <|
|
||||
Equiv.subtypeUnivEquiv (by simp [withDual_union_withoutDual])
|
||||
|
||||
/-!
|
||||
|
||||
## getDualEquiv
|
||||
|
||||
-/
|
||||
|
||||
/-- An equivalence from `l.withUniqueDual` to itself obtained by taking the dual index. -/
|
||||
def getDualEquiv : l.withUniqueDual ≃ l.withUniqueDual where
|
||||
toFun x := ⟨(l.getDual? x).get (l.mem_withUniqueDual_isSome x.1 x.2), by
|
||||
rw [mem_withUniqueDual_iff_countId_eq_two]
|
||||
simpa using l.countId_eq_two_of_mem_withUniqueDual x.1 x.2⟩
|
||||
invFun x := ⟨(l.getDual? x).get (l.mem_withUniqueDual_isSome x.1 x.2), by
|
||||
rw [mem_withUniqueDual_iff_countId_eq_two]
|
||||
simpa using l.countId_eq_two_of_mem_withUniqueDual x.1 x.2⟩
|
||||
left_inv x := SetCoe.ext <| by
|
||||
let d := (l.getDual? x).get (l.mem_withUniqueDual_isSome x.1 x.2)
|
||||
have h1 : l.countId (l.val.get d) = 2 := by
|
||||
simpa [d] using l.countId_eq_two_of_mem_withUniqueDual x.1 x.2
|
||||
have h2 : ((List.finRange l.length).filter (fun j => l.AreDualInSelf d j)).length = 1 := by
|
||||
rw [countId_get, List.countP_eq_length_filter] at h1
|
||||
omega
|
||||
obtain ⟨a, ha⟩ := List.length_eq_one.mp h2
|
||||
trans a
|
||||
· rw [← List.mem_singleton, ← ha]
|
||||
simp [d]
|
||||
· symm
|
||||
rw [← List.mem_singleton, ← ha]
|
||||
simp [d]
|
||||
right_inv x := SetCoe.ext <| by
|
||||
let d := (l.getDual? x).get (l.mem_withUniqueDual_isSome x.1 x.2)
|
||||
have h1 : l.countId (l.val.get d) = 2 := by
|
||||
simpa [d] using l.countId_eq_two_of_mem_withUniqueDual x.1 x.2
|
||||
have h2 : ((List.finRange l.length).filter (fun j => l.AreDualInSelf d j)).length = 1 := by
|
||||
rw [countId_get, List.countP_eq_length_filter] at h1
|
||||
omega
|
||||
obtain ⟨a, ha⟩ := List.length_eq_one.mp h2
|
||||
trans a
|
||||
· rw [← List.mem_singleton, ← ha]
|
||||
simp [d]
|
||||
· symm
|
||||
rw [← List.mem_singleton, ← ha]
|
||||
simp [d]
|
||||
|
||||
@[simp]
|
||||
lemma getDual?_getDualEquiv (i : l.withUniqueDual) : l.getDual? (l.getDualEquiv i) = i := by
|
||||
have h1 := (Equiv.apply_symm_apply l.getDualEquiv i).symm
|
||||
nth_rewrite 2 [h1]
|
||||
nth_rewrite 2 [getDualEquiv]
|
||||
simp
|
||||
rfl
|
||||
|
||||
/-- An equivalence from `l.withUniqueDualInOther l2 ` to
|
||||
`l2.withUniqueDualInOther l` obtained by taking the dual index. -/
|
||||
def getDualInOtherEquiv : l.withUniqueDualInOther l2 ≃ l2.withUniqueDualInOther l where
|
||||
toFun x := ⟨(l.getDualInOther? l2 x).get (l.mem_withUniqueDualInOther_isSome l2 x.1 x.2), by
|
||||
rw [mem_withUniqueDualInOther_iff_countId_eq_one]
|
||||
simpa using And.comm.mpr (l.countId_eq_one_of_mem_withUniqueDualInOther l2 x.1 x.2)⟩
|
||||
invFun x := ⟨(l2.getDualInOther? l x).get (l2.mem_withUniqueDualInOther_isSome l x.1 x.2), by
|
||||
rw [mem_withUniqueDualInOther_iff_countId_eq_one]
|
||||
simpa using And.comm.mpr (l2.countId_eq_one_of_mem_withUniqueDualInOther l x.1 x.2)⟩
|
||||
left_inv x := SetCoe.ext <| by
|
||||
let d := (l.getDualInOther? l2 x).get (l.mem_withUniqueDualInOther_isSome l2 x.1 x.2)
|
||||
have h1 : l.countId (l2.val.get d) = 1 := by
|
||||
simpa [d] using (l.countId_eq_one_of_mem_withUniqueDualInOther l2 x.1 x.2).1
|
||||
have h2 : ((List.finRange l.length).filter (fun j => l2.AreDualInOther l d j)).length = 1 := by
|
||||
rw [countId_get_other, List.countP_eq_length_filter] at h1
|
||||
omega
|
||||
obtain ⟨a, ha⟩ := List.length_eq_one.mp h2
|
||||
trans a
|
||||
· rw [← List.mem_singleton, ← ha]
|
||||
simp [d]
|
||||
· symm
|
||||
rw [← List.mem_singleton, ← ha]
|
||||
simp [d]
|
||||
right_inv x := SetCoe.ext <| by
|
||||
let d := (l2.getDualInOther? l x).get (l2.mem_withUniqueDualInOther_isSome l x.1 x.2)
|
||||
have h1 : l2.countId (l.val.get d) = 1 := by
|
||||
simpa [d] using (l2.countId_eq_one_of_mem_withUniqueDualInOther l x.1 x.2).1
|
||||
have h2 : ((List.finRange l2.length).filter (fun j => l.AreDualInOther l2 d j)).length = 1 := by
|
||||
rw [countId_get_other, List.countP_eq_length_filter] at h1
|
||||
omega
|
||||
obtain ⟨a, ha⟩ := List.length_eq_one.mp h2
|
||||
trans a
|
||||
· rw [← List.mem_singleton, ← ha]
|
||||
simp [d]
|
||||
· symm
|
||||
rw [← List.mem_singleton, ← ha]
|
||||
simp [d]
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOtherEquiv_self_refl : l.getDualInOtherEquiv l = Equiv.refl _ := by
|
||||
apply Equiv.ext
|
||||
intro x
|
||||
simp [getDualInOtherEquiv]
|
||||
apply Subtype.eq
|
||||
simp only
|
||||
have hx2 := x.2
|
||||
simp [withUniqueDualInOther] at hx2
|
||||
apply Option.some_injective
|
||||
rw [hx2.2 x.1 (by simp [AreDualInOther])]
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
lemma getDualInOtherEquiv_symm : (l.getDualInOtherEquiv l2).symm = l2.getDualInOtherEquiv l := by
|
||||
rfl
|
||||
|
||||
/-- An equivalence casting `withUniqueDualInOther` based on an equality of the left index list. -/
|
||||
def withUniqueDualCastLeft (h : l = l3) :
|
||||
l.withUniqueDualInOther l2 ≃ l3.withUniqueDualInOther l2 where
|
||||
toFun x := ⟨Fin.cast (by rw [h]) x.1, by subst h; exact x.prop⟩
|
||||
invFun x := ⟨Fin.cast (by rw [h]) x.1, by subst h; exact x.prop⟩
|
||||
left_inv x := SetCoe.ext rfl
|
||||
right_inv x := SetCoe.ext rfl
|
||||
|
||||
/-- An equivalence casting `withUniqueDualInOther` based on an equality of the right index list. -/
|
||||
def withUniqueDualCastRight (h : l2 = l3) :
|
||||
l.withUniqueDualInOther l2 ≃ l.withUniqueDualInOther l3 where
|
||||
toFun x := ⟨x.1, by subst h; exact x.prop⟩
|
||||
invFun x := ⟨x.1, by subst h; exact x.prop⟩
|
||||
left_inv x := SetCoe.ext rfl
|
||||
right_inv x := SetCoe.ext rfl
|
||||
|
||||
/-- An equivalence casting `withUniqueDualInOther` based on an equality of both index lists. -/
|
||||
def withUniqueDualCast {l1 l2 l1' l2' : IndexList X} (h : l1 = l1') (h2 : l2 = l2') :
|
||||
l1.withUniqueDualInOther l2 ≃ l1'.withUniqueDualInOther l2' where
|
||||
toFun x := ⟨Fin.cast (by rw [h]) x.1, by subst h h2; exact x.prop⟩
|
||||
invFun x := ⟨Fin.cast (by rw [h]) x.1, by subst h h2; exact x.prop⟩
|
||||
left_inv x := SetCoe.ext rfl
|
||||
right_inv x := SetCoe.ext rfl
|
||||
|
||||
lemma getDualInOtherEquiv_cast_left (h : l = l3) :
|
||||
l.getDualInOtherEquiv l2 = ((withUniqueDualCastLeft l l2 l3 h).trans
|
||||
(l3.getDualInOtherEquiv l2)).trans (withUniqueDualCastRight l2 l l3 h).symm := by
|
||||
subst h
|
||||
rfl
|
||||
|
||||
lemma getDualInOtherEquiv_cast_right (h : l2 = l3) :
|
||||
l.getDualInOtherEquiv l2 = ((withUniqueDualCastRight l l2 l3 h).trans
|
||||
(l.getDualInOtherEquiv l3)).trans (withUniqueDualCastLeft l2 l l3 h).symm := by
|
||||
subst h
|
||||
rfl
|
||||
|
||||
lemma getDualInOtherEquiv_cast {l1 l2 l1' l2' : IndexList X} (h : l1 = l1') (h2 : l2 = l2') :
|
||||
l1.getDualInOtherEquiv l2 = ((withUniqueDualCast h h2).trans
|
||||
(l1'.getDualInOtherEquiv l2')).trans (withUniqueDualCast h2 h).symm := by
|
||||
subst h h2
|
||||
rfl
|
||||
|
||||
/-!
|
||||
|
||||
## Equivalences involving `withUniqueDualLT` and `withUniqueDualGT`.
|
||||
|
||||
-/
|
||||
|
||||
/-! TODO: Replace with a mathlib lemma. -/
|
||||
lemma option_not_lt (i j : Option (Fin l.length)) : i < j → i ≠ j → ¬ j < i := by
|
||||
match i, j with
|
||||
| none, none =>
|
||||
exact fun a _ _ => a
|
||||
| none, some k =>
|
||||
exact fun _ _ a => a
|
||||
| some i, none =>
|
||||
exact fun h _ _ => h
|
||||
| some i, some j =>
|
||||
intro h h'
|
||||
simp_all
|
||||
change i < j at h
|
||||
change ¬ j < i
|
||||
exact Fin.lt_asymm h
|
||||
|
||||
/-! TODO: Replace with a mathlib lemma. -/
|
||||
lemma lt_option_of_not (i j : Option (Fin l.length)) : ¬ j < i → i ≠ j → i < j := by
|
||||
match i, j with
|
||||
| none, none =>
|
||||
exact fun a b => a (a (a (b rfl)))
|
||||
| none, some k =>
|
||||
exact fun _ _ => trivial
|
||||
| some i, none =>
|
||||
exact fun a _ => a trivial
|
||||
| some i, some j =>
|
||||
intro h h'
|
||||
simp_all
|
||||
change ¬ j < i at h
|
||||
change i < j
|
||||
omega
|
||||
|
||||
/-- The equivalence between `l.withUniqueDualLT` and `l.withUniqueDualGT` obtained by
|
||||
taking an index to its dual. -/
|
||||
def withUniqueDualLTEquivGT : l.withUniqueDualLT ≃ l.withUniqueDualGT where
|
||||
toFun i := ⟨l.getDualEquiv ⟨i, l.mem_withUniqueDual_of_mem_withUniqueDualLt i i.2⟩, by
|
||||
have hi := i.2
|
||||
simp only [withUniqueDualGT, Finset.mem_filter, Finset.coe_mem, true_and]
|
||||
simp only [withUniqueDualLT, Finset.mem_filter] at hi
|
||||
apply option_not_lt
|
||||
· rw [getDual?_getDualEquiv]
|
||||
simpa only [getDualEquiv, Equiv.coe_fn_mk, Option.some_get] using hi.2
|
||||
· simp only [ne_eq, getDual?_neq_self, not_false_eq_true]⟩
|
||||
invFun i := ⟨l.getDualEquiv.symm ⟨i, l.mem_withUniqueDual_of_mem_withUniqueDualGt i i.2⟩, by
|
||||
have hi := i.2
|
||||
simp only [withUniqueDualLT, Finset.mem_filter, Finset.coe_mem, true_and, gt_iff_lt]
|
||||
simp only [withUniqueDualGT, Finset.mem_filter] at hi
|
||||
apply lt_option_of_not
|
||||
· erw [getDual?_getDualEquiv]
|
||||
simpa [getDualEquiv] using hi.2
|
||||
· symm
|
||||
simp⟩
|
||||
left_inv x := SetCoe.ext <| by
|
||||
simp
|
||||
right_inv x := SetCoe.ext <| by
|
||||
simp
|
||||
|
||||
/-- An equivalence from `l.withUniqueDualLT ⊕ l.withUniqueDualLT` to `l.withUniqueDual`.
|
||||
The first `l.withUniqueDualLT` are taken to themselves, whilst the second copy are
|
||||
taken to their dual. -/
|
||||
def withUniqueLTGTEquiv : l.withUniqueDualLT ⊕ l.withUniqueDualLT ≃ l.withUniqueDual := by
|
||||
apply (Equiv.sumCongr (Equiv.refl _) l.withUniqueDualLTEquivGT).trans
|
||||
apply (Equiv.Finset.union _ _ l.withUniqueDualLT_disjoint_withUniqueDualGT).trans
|
||||
apply (Equiv.subtypeEquivRight (by simp only [l.withUniqueDualLT_union_withUniqueDualGT,
|
||||
implies_true]))
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -0,0 +1,175 @@
|
|||
/-
|
||||
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.IndexList.CountId
|
||||
import HepLean.SpaceTime.LorentzTensor.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}
|
||||
|
||||
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)
|
||||
|
||||
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] 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 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
|
||||
simp at hI
|
||||
omega
|
||||
|
||||
lemma inr (h : (l ++ l2).OnlyUniqueDuals) : l2.OnlyUniqueDuals := by
|
||||
rw [iff_countId_leq_two'] at h ⊢
|
||||
intro I
|
||||
have hI := h I
|
||||
simp at hI
|
||||
omega
|
||||
|
||||
lemma symm' (h : (l ++ l2).OnlyUniqueDuals) : (l2 ++ l).OnlyUniqueDuals := by
|
||||
rw [iff_countId_leq_two'] at h ⊢
|
||||
intro I
|
||||
have hI := h I
|
||||
simp 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 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 ⊢
|
||||
intro I
|
||||
have hI := h I
|
||||
have h1 := countId_contrIndexList_le_countId l I
|
||||
omega
|
||||
|
||||
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
|
||||
omega
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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 at h3 h'
|
||||
omega
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -0,0 +1,99 @@
|
|||
/-
|
||||
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.IndexList.CountId
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Contraction
|
||||
import Mathlib.Algebra.Order.Ring.Nat
|
||||
import Mathlib.Data.Finset.Sort
|
||||
import Mathlib.Tactic.FinCases
|
||||
/-!
|
||||
|
||||
# Subperm for index lists.
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
/-- An IndexList `l` is a subpermutation of `l2` if there are no duals in `l`, and
|
||||
every element of `l` has a unique dual in `l2`. -/
|
||||
def Subperm : Prop := l.withUniqueDualInOther l2 = Finset.univ
|
||||
|
||||
namespace Subperm
|
||||
|
||||
variable {l l2 l3 : IndexList X}
|
||||
|
||||
lemma iff_countId_fin : l.Subperm l2 ↔
|
||||
∀ i, l.countId (l.val.get i) = 1 ∧ l2.countId (l.val.get i) = 1 := by
|
||||
refine Iff.intro (fun h i => ?_) (fun h => ?_)
|
||||
· have hi : i ∈ l.withUniqueDualInOther l2 := by
|
||||
rw [h]
|
||||
exact Finset.mem_univ i
|
||||
exact countId_eq_one_of_mem_withUniqueDualInOther l l2 i hi
|
||||
· rw [Subperm, Finset.eq_univ_iff_forall]
|
||||
exact fun x => mem_withUniqueDualInOther_of_countId_eq_one l l2 x (h x)
|
||||
|
||||
lemma iff_countId : l.Subperm l2 ↔
|
||||
∀ I, l.countId I ≤ 1 ∧ (l.countId I = 1 → l2.countId I = 1) := by
|
||||
rw [iff_countId_fin]
|
||||
refine Iff.intro (fun h I => ?_) (fun h i => ?_)
|
||||
· by_cases h' : l.countId I = 0
|
||||
· simp_all
|
||||
· obtain ⟨I', hI'1, hI'2⟩ := l.countId_neq_zero_mem I h'
|
||||
rw [countId_congr _ hI'2, countId_congr _ hI'2]
|
||||
have hi' : l.val.indexOf I' < l.val.length := List.indexOf_lt_length.mpr hI'1
|
||||
have hIi' : I' = l.val.get ⟨l.val.indexOf I', hi'⟩ := (List.indexOf_get (hi')).symm
|
||||
have hi' := h ⟨l.val.indexOf I', hi'⟩
|
||||
rw [← hIi'] at hi'
|
||||
rw [hi'.1, hi'.2]
|
||||
simp
|
||||
· have hi := h (l.val.get i)
|
||||
have h1 : l.countId (l.val.get i) ≠ 0 := countId_index_neq_zero l i
|
||||
omega
|
||||
|
||||
lemma trans (h1 : l.Subperm l2) (h2 : l2.Subperm l3) : l.Subperm l3 := by
|
||||
rw [iff_countId] at *
|
||||
intro I
|
||||
have h1 := h1 I
|
||||
have h2 := h2 I
|
||||
omega
|
||||
|
||||
lemma fst_eq_contrIndexList (h : l.Subperm l2) : l.contrIndexList = l := by
|
||||
rw [iff_countId] at *
|
||||
apply ext
|
||||
simp [contrIndexList]
|
||||
intro I hI
|
||||
have h' := countId_mem l I hI
|
||||
have hI' := h I
|
||||
omega
|
||||
|
||||
lemma symm (h : l.Subperm l2) (hl : l.length = l2.length) : l2.Subperm l := by
|
||||
refine (Finset.card_eq_iff_eq_univ (l2.withUniqueDualInOther l)).mp ?_
|
||||
trans (Finset.map ⟨Subtype.val, Subtype.val_injective⟩ (Equiv.finsetCongr
|
||||
(l.getDualInOtherEquiv l2) Finset.univ)).card
|
||||
· apply congrArg
|
||||
simp [Finset.ext_iff]
|
||||
· trans l2.length
|
||||
· simp only [Finset.univ_eq_attach, Equiv.finsetCongr_apply, Finset.card_map,
|
||||
Finset.card_attach]
|
||||
rw [h, ← hl]
|
||||
exact Finset.card_fin l.length
|
||||
· exact Eq.symm (Finset.card_fin l2.length)
|
||||
|
||||
lemma contr_refl : l.contrIndexList.Subperm l.contrIndexList := by
|
||||
rw [iff_countId]
|
||||
intro I
|
||||
simp only [imp_self, and_true]
|
||||
exact countId_contrIndexList_le_one l I
|
||||
|
||||
end Subperm
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
|
@ -61,7 +61,7 @@ def toCharList (s : IndexString X) : List Char := s.val.toList
|
|||
/-- Takes a list of characters to the correpsonding index if it exists else to `none`. -/
|
||||
def charListToOptionIndex (l : List Char) : Option (Index X) :=
|
||||
if h : listCharIndex X l && l ≠ [] then
|
||||
some (Index.ofCharList l (by simpa using h))
|
||||
some (IndexRep.ofCharList l (by simpa using h)).toIndex
|
||||
else
|
||||
none
|
||||
|
||||
|
@ -97,7 +97,7 @@ open IndexNotation ColorIndexList IndexString
|
|||
noncomputable def fromIndexString (T : 𝓣.Tensor cn) (s : String)
|
||||
(hs : listCharIsIndexString 𝓣.toTensorColor.Color s.toList = true)
|
||||
(hn : n = (toIndexList' s hs).length)
|
||||
(hD : (toIndexList' s hs).withDual = (toIndexList' s hs).withUniqueDual)
|
||||
(hD : IndexList.OnlyUniqueDuals (toIndexList' s hs))
|
||||
(hC : IndexList.ColorCond (toIndexList' s hs))
|
||||
(hd : TensorColor.ColorMap.DualMap (toIndexList' s hs).colorMap
|
||||
(cn ∘ Fin.cast hn.symm)) : 𝓣.TensorIndex :=
|
||||
|
|
|
@ -1,618 +0,0 @@
|
|||
/-
|
||||
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
|
|
@ -3,7 +3,7 @@ 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.Color
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.IndexList.Color
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.ColorIndexList.Relations
|
||||
import HepLean.SpaceTime.LorentzTensor.IndexNotation.ColorIndexList.Append
|
||||
import HepLean.SpaceTime.LorentzTensor.Basic
|
||||
|
@ -153,7 +153,7 @@ lemma contr_of_withDual_empty (T : 𝓣.TensorIndex) (h : T.withDual = ∅) :
|
|||
intro x hx
|
||||
have hx' : x ∈ i.withUniqueDual := by
|
||||
exact Finset.mem_of_mem_filter x hx
|
||||
rw [i.unique_duals] at h
|
||||
rw [← i.unique_duals] at h
|
||||
rw [h] at hx'
|
||||
simp_all only [Finset.not_mem_empty]
|
||||
erw [TensorStructure.contr_tprod_isEmpty]
|
||||
|
@ -238,7 +238,7 @@ lemma trans {T₁ T₂ T₃ : 𝓣.TensorIndex} (h1 : Rel T₁ T₂) (h2 : Rel T
|
|||
simp only [contrPermEquiv_trans, contrPermEquiv_symm]
|
||||
|
||||
/-- Rel forms an equivalence relation. -/
|
||||
lemma isEquivalence : Equivalence (@Rel _ _ 𝓣 _) where
|
||||
lemma isEquivalence : Equivalence (@Rel _ _ 𝓣 _ _) where
|
||||
refl := Rel.refl
|
||||
symm := Rel.symm
|
||||
trans := Rel.trans
|
||||
|
|
|
@ -1,229 +0,0 @@
|
|||
/-
|
||||
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.GetDual
|
||||
import Mathlib.Algebra.Order.Ring.Nat
|
||||
import Mathlib.Tactic.FinCases
|
||||
/-!
|
||||
|
||||
# Indices with duals.
|
||||
|
||||
In this file we define the following finite sets:
|
||||
|
||||
- Given an index list `l₁`, the finite set, `l₁.withDual`, of (positions in) `l₁`
|
||||
corresponding to those indices which have a dual in `l₁`. This is equivalent to those indices
|
||||
of `l₁` for which `getDual?` is `some`.
|
||||
- Given two index lists `l₁` and `l₂`, the finite set, `l₁.withDualInOther l₂` of (positions in)
|
||||
`l₁` corresponding to those indices which have a dual in `l₂`. This is equivalent to those indices
|
||||
of `l₁` for which `l₁.getDualInOther? l₂` is `some`.
|
||||
|
||||
For example for `l₁ := ['ᵘ¹', 'ᵘ²', 'ᵤ₁', 'ᵘ¹']` and `l₂ := ['ᵘ³', 'ᵘ²', 'ᵘ⁴', 'ᵤ₂']` we have
|
||||
`l₁.withDual = {0, 2, 3}` and `l₁.withDualInOther l₂ = {1}`.
|
||||
|
||||
We prove some properties of these finite sets. In particular, we prove properties
|
||||
related to how they interact with appending two index lists.
|
||||
|
||||
-/
|
||||
|
||||
namespace IndexNotation
|
||||
|
||||
namespace IndexList
|
||||
|
||||
variable {X : Type} [IndexNotation X] [Fintype X] [DecidableEq X]
|
||||
variable (l l2 l3 : IndexList X)
|
||||
|
||||
/-!
|
||||
|
||||
## Finsets on which getDual? and getDualInOther? are some.
|
||||
|
||||
-/
|
||||
|
||||
/-- The finite set of indices of an index list which have a dual in that index list. -/
|
||||
def withDual : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => (l.getDual? i).isSome) Finset.univ
|
||||
|
||||
/-- The finite set of indices of an index list which have a dual in another provided index list. -/
|
||||
def withDualInOther : Finset (Fin l.length) :=
|
||||
Finset.filter (fun i => (l.getDualInOther? l2 i).isSome) Finset.univ
|
||||
|
||||
/-!
|
||||
|
||||
## Basic properties of withDual
|
||||
|
||||
-/
|
||||
|
||||
@[simp]
|
||||
lemma withDual_isSome (i : l.withDual) : (l.getDual? i).isSome := by
|
||||
simpa [withDual] using i.2
|
||||
|
||||
@[simp]
|
||||
lemma mem_withDual_iff_isSome (i : Fin l.length) : i ∈ l.withDual ↔ (l.getDual? i).isSome := by
|
||||
simp [withDual]
|
||||
|
||||
lemma not_mem_withDual_iff_isNone (i : Fin l.length) :
|
||||
i ∉ l.withDual ↔ (l.getDual? i).isNone := by
|
||||
simp only [mem_withDual_iff_isSome, Bool.not_eq_true, Option.not_isSome,
|
||||
Option.isNone_iff_eq_none]
|
||||
|
||||
lemma mem_withDual_iff_exists : i ∈ l.withDual ↔ ∃ j, l.AreDualInSelf i j := by
|
||||
simp [withDual, Finset.mem_filter, Finset.mem_univ, getDual?]
|
||||
exact Fin.isSome_find_iff
|
||||
|
||||
/-!
|
||||
|
||||
## Relationship between membership of withDual and countP on id.
|
||||
|
||||
-/
|
||||
|
||||
lemma countId_gt_zero_of_mem_withDual (i : Fin l.length) (h : i ∈ l.withDual) :
|
||||
1 < l.countId (l.val.get i) := by
|
||||
rw [countId]
|
||||
rw [mem_withDual_iff_exists] at h
|
||||
obtain ⟨j, hj⟩ := h
|
||||
simp [AreDualInSelf, idMap] at hj
|
||||
by_contra hn
|
||||
have hn' := l.countId_index_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 countId_of_not_mem_withDual (i : Fin l.length)(h : i ∉ l.withDual) :
|
||||
l.countId (l.val.get i) = 1 := by
|
||||
rw [countId]
|
||||
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_countId_gt_one (i : Fin l.length) :
|
||||
i ∈ l.withDual ↔ 1 < l.countId (l.val.get i) := by
|
||||
refine Iff.intro (fun h => countId_gt_zero_of_mem_withDual l i h) (fun h => ?_)
|
||||
by_contra hn
|
||||
have hn' := countId_of_not_mem_withDual l i hn
|
||||
omega
|
||||
|
||||
/-!
|
||||
|
||||
## Basic properties of withDualInOther
|
||||
|
||||
-/
|
||||
|
||||
@[simp]
|
||||
lemma mem_withInDualOther_iff_isSome (i : Fin l.length) :
|
||||
i ∈ l.withDualInOther l2 ↔ (l.getDualInOther? l2 i).isSome := by
|
||||
simp only [withDualInOther, getDualInOther?, Finset.mem_filter, Finset.mem_univ, true_and]
|
||||
|
||||
lemma mem_withInDualOther_iff_exists :
|
||||
i ∈ l.withDualInOther l2 ↔ ∃ (j : Fin l2.length), l.AreDualInOther l2 i j := by
|
||||
simp [withDualInOther, Finset.mem_filter, Finset.mem_univ, getDualInOther?]
|
||||
exact Fin.isSome_find_iff
|
||||
|
||||
/-!
|
||||
|
||||
## Append properties of withDual
|
||||
|
||||
-/
|
||||
|
||||
lemma withDual_append_eq_disjSum : (l ++ l2).withDual =
|
||||
Equiv.finsetCongr appendEquiv
|
||||
((l.withDual ∪ l.withDualInOther l2).disjSum
|
||||
(l2.withDual ∪ l2.withDualInOther l)) := by
|
||||
ext i
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective i
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
simp
|
||||
| Sum.inr k =>
|
||||
simp
|
||||
|
||||
/-!
|
||||
|
||||
## Append properties of withDualInOther
|
||||
|
||||
-/
|
||||
|
||||
lemma append_withDualInOther_eq :
|
||||
(l ++ l2).withDualInOther l3 =
|
||||
Equiv.finsetCongr appendEquiv ((l.withDualInOther l3).disjSum (l2.withDualInOther l3)) := by
|
||||
rw [Finset.ext_iff]
|
||||
intro i
|
||||
obtain ⟨k, hk⟩ := appendEquiv.surjective i
|
||||
subst hk
|
||||
match k with
|
||||
| Sum.inl k =>
|
||||
simp
|
||||
| Sum.inr k =>
|
||||
simp
|
||||
|
||||
lemma withDualInOther_append_eq : l.withDualInOther (l2 ++ l3) =
|
||||
l.withDualInOther l2 ∪ l.withDualInOther l3 := by
|
||||
ext i
|
||||
simp
|
||||
|
||||
end IndexList
|
||||
|
||||
end IndexNotation
|
File diff suppressed because it is too large
Load diff
|
@ -78,7 +78,7 @@ noncomputable def fromIndexStringColor {cn : Fin n → realTensorColor.Color}
|
|||
(T : (realLorentzTensor d).Tensor cn) (s : String)
|
||||
(hs : listCharIsIndexString realTensorColor.Color s.toList = true)
|
||||
(hn : n = (toIndexList' s hs).length)
|
||||
(hD : (toIndexList' s hs).withDual = (toIndexList' s hs).withUniqueDual)
|
||||
(hD : (toIndexList' s hs).OnlyUniqueDuals)
|
||||
(hC : IndexList.ColorCond.bool (toIndexList' s hs))
|
||||
(hd : TensorColor.ColorMap.DualMap.boolFin
|
||||
(toIndexList' s hs).colorMap (cn ∘ Fin.cast hn.symm)) :
|
||||
|
@ -103,7 +103,7 @@ macro "prodTactic" : tactic =>
|
|||
`(tactic| {
|
||||
apply (ColorIndexList.AppendCond.iff_bool _ _).mpr
|
||||
change @ColorIndexList.AppendCond.bool realTensorColor
|
||||
instIndexNotationColorRealTensorColor instDecidableEqColorRealTensorColor _ _
|
||||
instDecidableEqColorRealTensorColor _ _
|
||||
simp only [prod_toIndexList, indexNotation_eq_color, fromIndexStringColor, mkDualMap,
|
||||
toTensorColor_eq, decidableEq_eq_color]
|
||||
rfl})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue