Module docstring
{"# Series of a relation
If r is a relation on α then a relation series of length n is a series
a_0, a_1, ..., a_n such that r a_i a_{i+1} for all i < n
"}
{"# Series of a relation
If r is a relation on α then a relation series of length n is a series
a_0, a_1, ..., a_n such that r a_i a_{i+1} for all i < n
"}
RelSeries
structure
/--
Let `r` be a relation on `α`, a relation series of `r` of length `n` is a series
`a_0, a_1, ..., a_n` such that `r a_i a_{i+1}` for all `i < n`
-/
structure RelSeries where
/-- The number of inequalities in the series -/
length : ℕ
/-- The underlying function of a relation series -/
toFun : Fin (length + 1) → α
/-- Adjacent elements are related -/
step : ∀ (i : Fin length), r (toFun (Fin.castSucc i)) (toFun i.succ)
RelSeries.instCoeFunForallFinHAddNatLengthOfNat
instance
: CoeFun (RelSeries r) (fun x ↦ Fin (x.length + 1) → α)
RelSeries.singleton
definition
(a : α) : RelSeries r
RelSeries.instIsEmpty
instance
[IsEmpty α] : IsEmpty (RelSeries r)
instance [IsEmpty α] : IsEmpty (RelSeries r) where
false x := IsEmpty.false (x 0)
RelSeries.instInhabited
instance
[Inhabited α] : Inhabited (RelSeries r)
RelSeries.instNonempty
instance
[Nonempty α] : Nonempty (RelSeries r)
instance [Nonempty α] : Nonempty (RelSeries r) :=
Nonempty.map (singleton r) inferInstance
RelSeries.ext
theorem
{x y : RelSeries r} (length_eq : x.length = y.length) (toFun_eq : x.toFun = y.toFun ∘ Fin.cast (by rw [length_eq])) :
x = y
RelSeries.rel_of_lt
theorem
[IsTrans α r] (x : RelSeries r) {i j : Fin (x.length + 1)} (h : i < j) : r (x i) (x j)
RelSeries.rel_or_eq_of_le
theorem
[IsTrans α r] (x : RelSeries r) {i j : Fin (x.length + 1)} (h : i ≤ j) : r (x i) (x j) ∨ x i = x j
lemma rel_or_eq_of_le [IsTrans α r] (x : RelSeries r) {i j : Fin (x.length + 1)} (h : i ≤ j) :
r (x i) (x j) ∨ x i = x j :=
(Fin.lt_or_eq_of_le h).imp (x.rel_of_lt ·) (by rw [·])
RelSeries.ofLE
definition
(x : RelSeries r) {s : Rel α α} (h : r ≤ s) : RelSeries s
RelSeries.coe_ofLE
theorem
(x : RelSeries r) {s : Rel α α} (h : r ≤ s) : (x.ofLE h : _ → _) = x
RelSeries.toList
definition
(x : RelSeries r) : List α
RelSeries.length_toList
theorem
(x : RelSeries r) : x.toList.length = x.length + 1
@[simp]
lemma length_toList (x : RelSeries r) : x.toList.length = x.length + 1 :=
List.length_ofFn
RelSeries.toList_chain'
theorem
(x : RelSeries r) : x.toList.Chain' r
lemma toList_chain' (x : RelSeries r) : x.toList.Chain' r := by
rw [List.chain'_iff_get]
intros i h
convert x.step ⟨i, by simpa [toList] using h⟩ <;> apply List.get_ofFn
RelSeries.toList_ne_nil
theorem
(x : RelSeries r) : x.toList ≠ []
lemma toList_ne_nil (x : RelSeries r) : x.toList ≠ [] := fun m =>
List.eq_nil_iff_forall_not_mem.mp m (x 0) <| List.mem_ofFn.mpr ⟨_, rfl⟩
RelSeries.fromListChain'
definition
(x : List α) (x_ne_nil : x ≠ []) (hx : x.Chain' r) : RelSeries r
/-- Every nonempty list satisfying the chain condition gives a relation series -/
@[simps]
def fromListChain' (x : List α) (x_ne_nil : x ≠ []) (hx : x.Chain' r) : RelSeries r where
length := x.length - 1
toFun i := x[Fin.cast (Nat.succ_pred_eq_of_pos <| List.length_pos_iff.mpr x_ne_nil) i]
step i := List.chain'_iff_get.mp hx i i.2
RelSeries.Equiv
definition
: RelSeries r ≃ {x : List α | x ≠ [] ∧ x.Chain' r}
/-- Relation series of `r` and nonempty list of `α` satisfying `r`-chain condition bijectively
corresponds to each other. -/
protected def Equiv : RelSeriesRelSeries r ≃ {x : List α | x ≠ [] ∧ x.Chain' r} where
toFun x := ⟨_, x.toList_ne_nil, x.toList_chain'⟩
invFun x := fromListChain' _ x.2.1 x.2.2
left_inv x := ext (by simp [toList]) <| by ext; dsimp; apply List.get_ofFn
right_inv x := by
refine Subtype.ext (List.ext_get ?_ fun n hn1 _ => by dsimp; apply List.get_ofFn)
have := Nat.succ_pred_eq_of_pos <| List.length_pos_iff.mpr x.2.1
simp_all [toList]
RelSeries.toList_injective
theorem
: Function.Injective (RelSeries.toList (r := r))
lemma toList_injective : Function.Injective (RelSeries.toList (r := r)) :=
fun _ _ h ↦ (RelSeries.Equiv).injective <| Subtype.ext h
Rel.FiniteDimensional
structure
/-- A relation `r` is said to be finite dimensional iff there is a relation series of `r` with the
maximum length. -/
@[mk_iff]
class FiniteDimensional : Prop where
/-- A relation `r` is said to be finite dimensional iff there is a relation series of `r` with the
maximum length. -/
exists_longest_relSeries : ∃ x : RelSeries r, ∀ y : RelSeries r, y.length ≤ x.length
Rel.InfiniteDimensional
structure
/-- A relation `r` is said to be infinite dimensional iff there exists relation series of arbitrary
length. -/
@[mk_iff]
class InfiniteDimensional : Prop where
/-- A relation `r` is said to be infinite dimensional iff there exists relation series of
arbitrary length. -/
exists_relSeries_with_length : ∀ n : ℕ, ∃ x : RelSeries r, x.length = n
RelSeries.longestOf
definition
[r.FiniteDimensional] : RelSeries r
/-- The longest relational series when a relation is finite dimensional -/
protected noncomputable def longestOf [r.FiniteDimensional] : RelSeries r :=
Rel.FiniteDimensional.exists_longest_relSeries.choose
RelSeries.length_le_length_longestOf
theorem
[r.FiniteDimensional] (x : RelSeries r) : x.length ≤ (RelSeries.longestOf r).length
lemma length_le_length_longestOf [r.FiniteDimensional] (x : RelSeries r) :
x.length ≤ (RelSeries.longestOf r).length :=
Rel.FiniteDimensional.exists_longest_relSeries.choose_spec _
RelSeries.withLength
definition
[r.InfiniteDimensional] (n : ℕ) : RelSeries r
/-- A relation series with length `n` if the relation is infinite dimensional -/
protected noncomputable def withLength [r.InfiniteDimensional] (n : ℕ) : RelSeries r :=
(Rel.InfiniteDimensional.exists_relSeries_with_length n).choose
RelSeries.length_withLength
theorem
[r.InfiniteDimensional] (n : ℕ) : (RelSeries.withLength r n).length = n
@[simp] lemma length_withLength [r.InfiniteDimensional] (n : ℕ) :
(RelSeries.withLength r n).length = n :=
(Rel.InfiniteDimensional.exists_relSeries_with_length n).choose_spec
RelSeries.nonempty_of_infiniteDimensional
theorem
[r.InfiniteDimensional] : Nonempty α
/-- If a relation on `α` is infinite dimensional, then `α` is nonempty. -/
lemma nonempty_of_infiniteDimensional [r.InfiniteDimensional] : Nonempty α :=
⟨RelSeries.withLength r 0 0⟩
RelSeries.nonempty_of_finiteDimensional
theorem
[r.FiniteDimensional] : Nonempty α
lemma nonempty_of_finiteDimensional [r.FiniteDimensional] : Nonempty α := by
obtain ⟨p, _⟩ := (Rel.finiteDimensional_iff r).mp ‹_›
exact ⟨p 0⟩
RelSeries.membership
instance
: Membership α (RelSeries r)
instance membership : Membership α (RelSeries r) :=
⟨Function.swap (· ∈ Set.range ·)⟩
RelSeries.mem_def
theorem
: x ∈ s ↔ x ∈ Set.range s
theorem mem_def : x ∈ sx ∈ s ↔ x ∈ Set.range s := Iff.rfl
RelSeries.mem_toList
theorem
: x ∈ s.toList ↔ x ∈ s
@[simp] theorem mem_toList : x ∈ s.toListx ∈ s.toList ↔ x ∈ s := by
rw [RelSeries.toList, List.mem_ofFn', RelSeries.mem_def]
RelSeries.subsingleton_of_length_eq_zero
theorem
(hs : s.length = 0) : {x | x ∈ s}.Subsingleton
theorem subsingleton_of_length_eq_zero (hs : s.length = 0) : {x | x ∈ s}.Subsingleton := by
rintro - ⟨i, rfl⟩ - ⟨j, rfl⟩
congr!
exact finCongr (by rw [hs, zero_add]) |>.injective <| Subsingleton.elim (α := Fin 1) _ _
RelSeries.length_ne_zero_of_nontrivial
theorem
(h : {x | x ∈ s}.Nontrivial) : s.length ≠ 0
theorem length_ne_zero_of_nontrivial (h : {x | x ∈ s}.Nontrivial) : s.length ≠ 0 :=
fun hs ↦ h.not_subsingleton <| subsingleton_of_length_eq_zero hs
RelSeries.length_pos_of_nontrivial
theorem
(h : {x | x ∈ s}.Nontrivial) : 0 < s.length
theorem length_pos_of_nontrivial (h : {x | x ∈ s}.Nontrivial) : 0 < s.length :=
Nat.pos_iff_ne_zero.mpr <| length_ne_zero_of_nontrivial h
RelSeries.length_ne_zero
theorem
(irrefl : Irreflexive r) : s.length ≠ 0 ↔ {x | x ∈ s}.Nontrivial
theorem length_ne_zero (irrefl : Irreflexive r) : s.length ≠ 0s.length ≠ 0 ↔ {x | x ∈ s}.Nontrivial := by
refine ⟨fun h ↦ ⟨s 0, by simp [mem_def], s 1, by simp [mem_def], fun rid ↦ irrefl (s 0) ?_⟩,
length_ne_zero_of_nontrivial⟩
nth_rw 2 [rid]
convert s.step ⟨0, by omega⟩
ext
simpa [Nat.pos_iff_ne_zero]
RelSeries.length_pos
theorem
(irrefl : Irreflexive r) : 0 < s.length ↔ {x | x ∈ s}.Nontrivial
theorem length_pos (irrefl : Irreflexive r) : 0 < s.length ↔ {x | x ∈ s}.Nontrivial :=
Nat.pos_iff_ne_zero.trans <| length_ne_zero irrefl
RelSeries.length_eq_zero
theorem
(irrefl : Irreflexive r) : s.length = 0 ↔ {x | x ∈ s}.Subsingleton
lemma length_eq_zero (irrefl : Irreflexive r) : s.length = 0 ↔ {x | x ∈ s}.Subsingleton := by
rw [← not_ne_iff, length_ne_zero irrefl, Set.not_nontrivial_iff]
RelSeries.head
definition
(x : RelSeries r) : α
RelSeries.last
definition
(x : RelSeries r) : α
RelSeries.apply_last
theorem
(x : RelSeries r) : x (Fin.last <| x.length) = x.last
RelSeries.head_mem
theorem
(x : RelSeries r) : x.head ∈ x
lemma head_mem (x : RelSeries r) : x.head ∈ x := ⟨_, rfl⟩
RelSeries.last_mem
theorem
(x : RelSeries r) : x.last ∈ x
lemma last_mem (x : RelSeries r) : x.last ∈ x := ⟨_, rfl⟩
RelSeries.head_singleton
theorem
{r : Rel α α} (x : α) : (singleton r x).head = x
RelSeries.last_singleton
theorem
{r : Rel α α} (x : α) : (singleton r x).last = x
RelSeries.append
definition
(p q : RelSeries r) (connect : r p.last q.head) : RelSeries r
/--
If `a₀ -r→ a₁ -r→ ... -r→ aₙ` and `b₀ -r→ b₁ -r→ ... -r→ bₘ` are two strict series
such that `r aₙ b₀`, then there is a chain of length `n + m + 1` given by
`a₀ -r→ a₁ -r→ ... -r→ aₙ -r→ b₀ -r→ b₁ -r→ ... -r→ bₘ`.
-/
@[simps length]
def append (p q : RelSeries r) (connect : r p.last q.head) : RelSeries r where
length := p.length + q.length + 1
toFun := Fin.appendFin.append p q ∘ Fin.cast (by omega)
step i := by
obtain hi | rfl | hi :=
lt_trichotomy i (Fin.castLE (by omega) (Fin.last _ : Fin (p.length + 1)))
· convert p.step ⟨i.1, hi⟩ <;> convert Fin.append_left p q _ <;> rfl
· convert connect
· convert Fin.append_left p q _
· convert Fin.append_right p q _; rfl
· set x := _; set y := _
change r (Fin.append p q x) (Fin.append p q y)
have hx : x = Fin.natAdd _ ⟨i - (p.length + 1), Nat.sub_lt_left_of_lt_add hi <|
i.2.trans <| by omega⟩ := by
ext; dsimp [x, y]; rw [Nat.add_sub_cancel']; exact hi
have hy : y = Fin.natAdd _ ⟨i - p.length, Nat.sub_lt_left_of_lt_add (le_of_lt hi)
(by exact i.2)⟩ := by
ext
dsimp
conv_rhs => rw [Nat.add_comm p.length 1, add_assoc,
Nat.add_sub_cancel' <| le_of_lt (show p.length < i.1 from hi), add_comm]
rfl
rw [hx, Fin.append_right, hy, Fin.append_right]
convert q.step ⟨i - (p.length + 1), Nat.sub_lt_left_of_lt_add hi <| by omega⟩
rw [Fin.succ_mk, Nat.sub_eq_iff_eq_add (le_of_lt hi : p.length ≤ i),
Nat.add_assoc _ 1, add_comm 1, Nat.sub_add_cancel]
exact hi
RelSeries.append_apply_left
theorem
(p q : RelSeries r) (connect : r p.last q.head) (i : Fin (p.length + 1)) :
p.append q connect ((i.castAdd (q.length + 1)).cast (by dsimp; omega)) = p i
lemma append_apply_left (p q : RelSeries r) (connect : r p.last q.head)
(i : Fin (p.length + 1)) :
p.append q connect ((i.castAdd (q.length + 1)).cast (by dsimp; omega)) = p i := by
delta append
simp only [Function.comp_apply]
convert Fin.append_left _ _ _
RelSeries.append_apply_right
theorem
(p q : RelSeries r) (connect : r p.last q.head) (i : Fin (q.length + 1)) :
p.append q connect (i.natAdd p.length + 1) = q i
lemma append_apply_right (p q : RelSeries r) (connect : r p.last q.head)
(i : Fin (q.length + 1)) :
p.append q connect (i.natAdd p.length + 1) = q i := by
delta append
simp only [Fin.coe_natAdd, Nat.cast_add, Function.comp_apply]
convert Fin.append_right _ _ _
ext
simp only [Fin.coe_cast, Fin.coe_natAdd]
conv_rhs => rw [add_assoc, add_comm 1, ← add_assoc]
change _ % _ = _
simp only [Nat.add_mod_mod, Nat.mod_add_mod, Nat.one_mod, Nat.mod_succ_eq_iff_lt]
omega
RelSeries.head_append
theorem
(p q : RelSeries r) (connect : r p.last q.head) : (p.append q connect).head = p.head
@[simp] lemma head_append (p q : RelSeries r) (connect : r p.last q.head) :
(p.append q connect).head = p.head :=
append_apply_left p q connect 0
RelSeries.last_append
theorem
(p q : RelSeries r) (connect : r p.last q.head) : (p.append q connect).last = q.last
@[simp] lemma last_append (p q : RelSeries r) (connect : r p.last q.head) :
(p.append q connect).last = q.last := by
delta last
convert append_apply_right p q connect (Fin.last _)
ext
change _ = _ % _
simp only [append_length, Fin.val_last, Fin.natAdd_last, Nat.one_mod, Nat.mod_add_mod,
Nat.mod_succ]
RelSeries.map
definition
(p : RelSeries r) (f : r →r s) : RelSeries s
/--
For two types `α, β` and relation on them `r, s`, if `f : α → β` preserves relation `r`, then an
`r`-series can be pushed out to an `s`-series by
`a₀ -r→ a₁ -r→ ... -r→ aₙ ↦ f a₀ -s→ f a₁ -s→ ... -s→ f aₙ`
-/
@[simps length]
def map (p : RelSeries r) (f : r →r s) : RelSeries s where
length := p.length
toFun := f.1.comp p
step := (f.2 <| p.step ·)
RelSeries.map_apply
theorem
(p : RelSeries r) (f : r →r s) (i : Fin (p.length + 1)) : p.map f i = f (p i)
RelSeries.head_map
theorem
(p : RelSeries r) (f : r →r s) : (p.map f).head = f p.head
RelSeries.last_map
theorem
(p : RelSeries r) (f : r →r s) : (p.map f).last = f p.last
RelSeries.insertNth
definition
(p : RelSeries r) (i : Fin p.length) (a : α) (prev_connect : r (p (Fin.castSucc i)) a)
(connect_next : r a (p i.succ)) : RelSeries r
/--
If `a₀ -r→ a₁ -r→ ... -r→ aₙ` is an `r`-series and `a` is such that
`aᵢ -r→ a -r→ a_ᵢ₊₁`, then
`a₀ -r→ a₁ -r→ ... -r→ aᵢ -r→ a -r→ aᵢ₊₁ -r→ ... -r→ aₙ`
is another `r`-series
-/
@[simps]
def insertNth (p : RelSeries r) (i : Fin p.length) (a : α)
(prev_connect : r (p (Fin.castSucc i)) a) (connect_next : r a (p i.succ)) : RelSeries r where
length := p.length + 1
toFun := (Fin.castSucc i.succ).insertNth a p
step m := by
set x := _; set y := _; change r x y
obtain hm | hm | hm := lt_trichotomy m.1 i.1
· convert p.step ⟨m, hm.trans i.2⟩
· show Fin.insertNth _ _ _ _ = _
rw [Fin.insertNth_apply_below]
pick_goal 2
· exact hm.trans (lt_add_one _)
simp
· show Fin.insertNth _ _ _ _ = _
rw [Fin.insertNth_apply_below]
pick_goal 2
· change m.1 + 1 < i.1 + 1; rwa [add_lt_add_iff_right]
simp; rfl
· rw [show x = p m from show Fin.insertNth _ _ _ _ = _ by
rw [Fin.insertNth_apply_below]
pick_goal 2
· show m.1 < i.1 + 1; exact hm ▸ lt_add_one _
simp]
convert prev_connect
· ext; exact hm
· change Fin.insertNth _ _ _ _ = _
rw [show m.succ = i.succ.castSucc by ext; change _ + 1 = _ + 1; rw [hm],
Fin.insertNth_apply_same]
· rw [Nat.lt_iff_add_one_le, le_iff_lt_or_eq] at hm
obtain hm | hm := hm
· convert p.step ⟨m.1 - 1, Nat.sub_lt_right_of_lt_add (by omega) m.2⟩
· change Fin.insertNth _ _ _ _ = _
rw [Fin.insertNth_apply_above (h := hm)]
aesop
· change Fin.insertNth _ _ _ _ = _
rw [Fin.insertNth_apply_above]
swap
· exact hm.trans (lt_add_one _)
simp only [Fin.val_succ, Fin.pred_succ, eq_rec_constant, Fin.succ_mk]
congr
exact Fin.ext <| Eq.symm <| Nat.succ_pred_eq_of_pos (lt_trans (Nat.zero_lt_succ _) hm)
· convert connect_next
· change Fin.insertNth _ _ _ _ = _
rw [show m.castSucc = i.succ.castSucc from Fin.ext hm.symm, Fin.insertNth_apply_same]
· change Fin.insertNth _ _ _ _ = _
rw [Fin.insertNth_apply_above]
swap
· change i.1 + 1 < m.1 + 1; omega
simp only [Fin.pred_succ, eq_rec_constant]
congr; ext; exact hm.symm
RelSeries.reverse
definition
(p : RelSeries r) : RelSeries (fun (a b : α) ↦ r b a)
/--
A relation series `a₀ -r→ a₁ -r→ ... -r→ aₙ` of `r` gives a relation series of the reverse of `r`
by reversing the series `aₙ ←r- aₙ₋₁ ←r- ... ←r- a₁ ←r- a₀`.
-/
@[simps length]
def reverse (p : RelSeries r) : RelSeries (fun (a b : α) ↦ r b a) where
length := p.length
toFun := p ∘ Fin.rev
step i := by
rw [Function.comp_apply, Function.comp_apply]
have hi : i.1 + 1 ≤ p.length := by omega
convert p.step ⟨p.length - (i.1 + 1), Nat.sub_lt_self (by omega) hi⟩
· ext; simp
· ext
simp only [Fin.val_rev, Fin.coe_castSucc, Fin.val_succ]
omega
RelSeries.reverse_apply
theorem
(p : RelSeries r) (i : Fin (p.length + 1)) : p.reverse i = p i.rev
RelSeries.last_reverse
theorem
(p : RelSeries r) : p.reverse.last = p.head
@[simp] lemma last_reverse (p : RelSeries r) : p.reverse.last = p.head := by
simp [RelSeries.last, RelSeries.head]
RelSeries.head_reverse
theorem
(p : RelSeries r) : p.reverse.head = p.last
@[simp] lemma head_reverse (p : RelSeries r) : p.reverse.head = p.last := by
simp [RelSeries.last, RelSeries.head]
RelSeries.reverse_reverse
theorem
{r : Rel α α} (p : RelSeries r) : p.reverse.reverse = p
@[simp] lemma reverse_reverse {r : Rel α α} (p : RelSeries r) : p.reverse.reverse = p := by
ext <;> simp
RelSeries.cons
definition
(p : RelSeries r) (newHead : α) (rel : r newHead p.head) : RelSeries r
/--
Given a series `a₀ -r→ a₁ -r→ ... -r→ aₙ` and an `a` such that `a₀ -r→ a` holds, there is
a series of length `n+1`: `a -r→ a₀ -r→ a₁ -r→ ... -r→ aₙ`.
-/
@[simps! length]
def cons (p : RelSeries r) (newHead : α) (rel : r newHead p.head) : RelSeries r :=
(singleton r newHead).append p rel
RelSeries.head_cons
theorem
(p : RelSeries r) (newHead : α) (rel : r newHead p.head) : (p.cons newHead rel).head = newHead
RelSeries.last_cons
theorem
(p : RelSeries r) (newHead : α) (rel : r newHead p.head) : (p.cons newHead rel).last = p.last
RelSeries.cons_cast_succ
theorem
(s : RelSeries r) (a : α) (h : r a s.head) (i : Fin (s.length + 1)) : (s.cons a h) (.cast (by simp) (.succ i)) = s i
lemma cons_cast_succ (s : RelSeries r) (a : α) (h : r a s.head) (i : Fin (s.length + 1)) :
(s.cons a h) (.cast (by simp) (.succ i)) = s i := by
dsimp [cons]
convert append_apply_right (singleton r a) s h i
ext
show i.1 + 1 = _ % _
simpa using (Nat.mod_eq_of_lt (by simp)).symm
RelSeries.snoc
definition
(p : RelSeries r) (newLast : α) (rel : r p.last newLast) : RelSeries r
/--
Given a series `a₀ -r→ a₁ -r→ ... -r→ aₙ` and an `a` such that `aₙ -r→ a` holds, there is
a series of length `n+1`: `a₀ -r→ a₁ -r→ ... -r→ aₙ -r→ a`.
-/
@[simps! length]
def snoc (p : RelSeries r) (newLast : α) (rel : r p.last newLast) : RelSeries r :=
p.append (singleton r newLast) rel
RelSeries.head_snoc
theorem
(p : RelSeries r) (newLast : α) (rel : r p.last newLast) : (p.snoc newLast rel).head = p.head
RelSeries.last_snoc
theorem
(p : RelSeries r) (newLast : α) (rel : r p.last newLast) : (p.snoc newLast rel).last = newLast
RelSeries.snoc_cast_castSucc
theorem
(s : RelSeries r) (a : α) (h : r s.last a) (i : Fin (s.length + 1)) :
(s.snoc a h) (.cast (by simp) (.castSucc i)) = s i
lemma snoc_cast_castSucc (s : RelSeries r) (a : α) (h : r s.last a) (i : Fin (s.length + 1)) :
(s.snoc a h) (.cast (by simp) (.castSucc i)) = s i :=
append_apply_left s (singleton r a) h i
RelSeries.last_snoc'
theorem
(p : RelSeries r) (newLast : α) (rel : r p.last newLast) : p.snoc newLast rel (Fin.last (p.length + 1)) = newLast
@[simp] lemma last_snoc' (p : RelSeries r) (newLast : α) (rel : r p.last newLast) :
p.snoc newLast rel (Fin.last (p.length + 1)) = newLast := last_append _ _ _
RelSeries.snoc_castSucc
theorem
(s : RelSeries r) (a : α) (connect : r s.last a) (i : Fin (s.length + 1)) : snoc s a connect (Fin.castSucc i) = s i
@[simp] lemma snoc_castSucc (s : RelSeries r) (a : α) (connect : r s.last a)
(i : Fin (s.length + 1)) : snoc s a connect (Fin.castSucc i) = s i :=
Fin.append_left _ _ i
RelSeries.mem_snoc
theorem
{p : RelSeries r} {newLast : α} {rel : r p.last newLast} {x : α} : x ∈ p.snoc newLast rel ↔ x ∈ p ∨ x = newLast
lemma mem_snoc {p : RelSeries r} {newLast : α} {rel : r p.last newLast} {x : α} :
x ∈ p.snoc newLast relx ∈ p.snoc newLast rel ↔ x ∈ p ∨ x = newLast := by
simp only [snoc, append, singleton_length, Nat.add_zero, Nat.reduceAdd, Fin.cast_refl,
Function.comp_id, mem_def, id_eq, Set.mem_range]
constructor
· rintro ⟨i, rfl⟩
exact Fin.lastCases (Or.inr <| Fin.append_right _ _ 0) (fun i => Or.inl ⟨⟨i.1, i.2⟩,
(Fin.append_left _ _ _).symm⟩) i
· intro h
rcases h with (⟨i, rfl⟩ | rfl)
· exact ⟨i.castSucc, Fin.append_left _ _ _⟩
· exact ⟨Fin.last _, Fin.append_right _ _ 0⟩
RelSeries.tail
definition
(p : RelSeries r) (len_pos : p.length ≠ 0) : RelSeries r
/--
If a series `a₀ -r→ a₁ -r→ ...` has positive length, then `a₁ -r→ ...` is another series
-/
@[simps]
def tail (p : RelSeries r) (len_pos : p.length ≠ 0) : RelSeries r where
length := p.length - 1
toFun := Fin.tailFin.tail p ∘ (Fin.cast <| Nat.succ_pred_eq_of_pos <| Nat.pos_of_ne_zero len_pos)
step i := p.step ⟨i.1 + 1, Nat.lt_pred_iff.mp i.2⟩
RelSeries.head_tail
theorem
(p : RelSeries r) (len_pos : p.length ≠ 0) : (p.tail len_pos).head = p 1
@[simp] lemma head_tail (p : RelSeries r) (len_pos : p.length ≠ 0) :
(p.tail len_pos).head = p 1 := by
show p (Fin.succ _) = p 1
congr
ext
show (1 : ℕ) = (1 : ℕ) % _
rw [Nat.mod_eq_of_lt]
simpa only [lt_add_iff_pos_left, Nat.pos_iff_ne_zero]
RelSeries.last_tail
theorem
(p : RelSeries r) (len_pos : p.length ≠ 0) : (p.tail len_pos).last = p.last
@[simp] lemma last_tail (p : RelSeries r) (len_pos : p.length ≠ 0) :
(p.tail len_pos).last = p.last := by
show p _ = p _
congr
ext
simp only [tail_length, Fin.val_succ, Fin.coe_cast, Fin.val_last]
exact Nat.succ_pred_eq_of_pos (by simpa [Nat.pos_iff_ne_zero] using len_pos)
RelSeries.eraseLast
definition
(p : RelSeries r) : RelSeries r
/--
If a series ``a₀ -r→ a₁ -r→ ... -r→ aₙ``, then `a₀ -r→ a₁ -r→ ... -r→ aₙ₋₁` is
another series -/
@[simps]
def eraseLast (p : RelSeries r) : RelSeries r where
length := p.length - 1
toFun i := p ⟨i, lt_of_lt_of_le i.2 (Nat.succ_le_succ (Nat.sub_le _ _))⟩
step i := p.step ⟨i, lt_of_lt_of_le i.2 (Nat.sub_le _ _)⟩
RelSeries.head_eraseLast
theorem
(p : RelSeries r) : p.eraseLast.head = p.head
RelSeries.last_eraseLast
theorem
(p : RelSeries r) : p.eraseLast.last = p ⟨p.length.pred, Nat.lt_succ_iff.2 (Nat.pred_le _)⟩
@[simp] lemma last_eraseLast (p : RelSeries r) :
p.eraseLast.last = p ⟨p.length.pred, Nat.lt_succ_iff.2 (Nat.pred_le _)⟩ := rfl
RelSeries.eraseLast_last_rel_last
theorem
(p : RelSeries r) (h : p.length ≠ 0) : r p.eraseLast.last p.last
/-- In a non-trivial series `p`, the last element of `p.eraseLast` is related to `p.last` -/
lemma eraseLast_last_rel_last (p : RelSeries r) (h : p.length ≠ 0) :
r p.eraseLast.last p.last := by
simp only [last, Fin.last, eraseLast_length, eraseLast_toFun]
convert p.step ⟨p.length - 1, by omega⟩
simp only [Nat.succ_eq_add_one, Fin.succ_mk]; omega
RelSeries.smash
definition
(p q : RelSeries r) (connect : p.last = q.head) : RelSeries r
/--
Given two series of the form `a₀ -r→ ... -r→ X` and `X -r→ b ---> ...`,
then `a₀ -r→ ... -r→ X -r→ b ...` is another series obtained by combining the given two.
-/
@[simps length]
def smash (p q : RelSeries r) (connect : p.last = q.head) : RelSeries r where
length := p.length + q.length
toFun := Fin.addCases (m := p.length) (n := q.length + 1) (p ∘ Fin.castSucc) q
step := by
apply Fin.addCases <;> intro i
· simp_rw [Fin.castSucc_castAdd, Fin.addCases_left, Fin.succ_castAdd]
convert p.step i
split_ifs with h
· rw [Fin.addCases_right, h, ← last, connect, head]
· apply Fin.addCases_left
simpa only [Fin.castSucc_natAdd, Fin.succ_natAdd, Fin.addCases_right] using q.step i
RelSeries.smash_castLE
theorem
{p q : RelSeries r} (h : p.last = q.head) (i : Fin (p.length + 1)) : p.smash q h (i.castLE (by simp)) = p i
lemma smash_castLE {p q : RelSeries r} (h : p.last = q.head) (i : Fin (p.length + 1)) :
p.smash q h (i.castLE (by simp)) = p i := by
refine i.lastCases ?_ fun _ ↦ by dsimp only [smash]; apply Fin.addCases_left
show p.smash q h (Fin.natAdd p.length (0 : Fin (q.length + 1))) = _
simpa only [smash, Fin.addCases_right] using h.symm
RelSeries.smash_castAdd
theorem
{p q : RelSeries r} (h : p.last = q.head) (i : Fin p.length) : p.smash q h (i.castAdd q.length).castSucc = p i.castSucc
RelSeries.smash_succ_castAdd
theorem
{p q : RelSeries r} (h : p.last = q.head) (i : Fin p.length) : p.smash q h (i.castAdd q.length).succ = p i.succ
RelSeries.smash_natAdd
theorem
{p q : RelSeries r} (h : p.last = q.head) (i : Fin q.length) : smash p q h (i.natAdd p.length).castSucc = q i.castSucc
lemma smash_natAdd {p q : RelSeries r} (h : p.last = q.head) (i : Fin q.length) :
smash p q h (i.natAdd p.length).castSucc = q i.castSucc := by
dsimp only [smash, Fin.castSucc_natAdd]
apply Fin.addCases_right
RelSeries.smash_succ_natAdd
theorem
{p q : RelSeries r} (h : p.last = q.head) (i : Fin q.length) : smash p q h (i.natAdd p.length).succ = q i.succ
lemma smash_succ_natAdd {p q : RelSeries r} (h : p.last = q.head) (i : Fin q.length) :
smash p q h (i.natAdd p.length).succ = q i.succ := by
dsimp only [smash, Fin.succ_natAdd]
apply Fin.addCases_right
RelSeries.head_smash
theorem
{p q : RelSeries r} (h : p.last = q.head) : (smash p q h).head = p.head
@[simp] lemma head_smash {p q : RelSeries r} (h : p.last = q.head) :
(smash p q h).head = p.head := by
obtain ⟨_ | _, _⟩ := p
· simpa [Fin.addCases] using h.symm
dsimp only [smash, head]
exact Fin.addCases_left 0
RelSeries.last_smash
theorem
{p q : RelSeries r} (h : p.last = q.head) : (smash p q h).last = q.last
@[simp] lemma last_smash {p q : RelSeries r} (h : p.last = q.head) :
(smash p q h).last = q.last := by
dsimp only [smash, last]
rw [← Fin.natAdd_last, Fin.addCases_right]
RelSeries.take
definition
{r : Rel α α} (p : RelSeries r) (i : Fin (p.length + 1)) : RelSeries r
/-- Given the series `a₀ -r→ … -r→ aᵢ -r→ … -r→ aₙ`, the series `a₀ -r→ … -r→ aᵢ`. -/
@[simps! length]
def take {r : Rel α α} (p : RelSeries r) (i : Fin (p.length + 1)) : RelSeries r where
length := i
toFun := fun ⟨j, h⟩ => p.toFun ⟨j, by omega⟩
step := fun ⟨j, h⟩ => p.step ⟨j, by omega⟩
RelSeries.head_take
theorem
(p : RelSeries r) (i : Fin (p.length + 1)) : (p.take i).head = p.head
RelSeries.last_take
theorem
(p : RelSeries r) (i : Fin (p.length + 1)) : (p.take i).last = p i
RelSeries.drop
definition
(p : RelSeries r) (i : Fin (p.length + 1)) : RelSeries r
/-- Given the series `a₀ -r→ … -r→ aᵢ -r→ … -r→ aₙ`, the series `aᵢ₊₁ -r→ … -r→ aᵢ`. -/
@[simps! length]
def drop (p : RelSeries r) (i : Fin (p.length + 1)) : RelSeries r where
length := p.length - i
toFun := fun ⟨j, h⟩ => p.toFun ⟨j+i, by omega⟩
step := fun ⟨j, h⟩ => by
convert p.step ⟨j+i.1, by omega⟩
simp only [Nat.succ_eq_add_one, Fin.succ_mk]; omega
RelSeries.head_drop
theorem
(p : RelSeries r) (i : Fin (p.length + 1)) : (p.drop i).head = p.toFun i
RelSeries.last_drop
theorem
(p : RelSeries r) (i : Fin (p.length + 1)) : (p.drop i).last = p.last
Rel.not_finiteDimensional_iff
theorem
[Nonempty α] : ¬r.FiniteDimensional ↔ r.InfiniteDimensional
lemma Rel.not_finiteDimensional_iff [Nonempty α] :
¬ r.FiniteDimensional¬ r.FiniteDimensional ↔ r.InfiniteDimensional := by
rw [finiteDimensional_iff, infiniteDimensional_iff]
push_neg
constructor
· intro H n
induction n with
| zero => refine ⟨⟨0, ![Nonempty.some ‹_›], by simp⟩, by simp⟩
| succ n IH =>
obtain ⟨l, hl⟩ := IH
obtain ⟨l', hl'⟩ := H l
exact ⟨l'.take ⟨n + 1, by simpa [hl] using hl'⟩, rfl⟩
· intro H l
obtain ⟨l', hl'⟩ := H (l.length + 1)
exact ⟨l', by simp [hl']⟩
Rel.not_infiniteDimensional_iff
theorem
[Nonempty α] : ¬r.InfiniteDimensional ↔ r.FiniteDimensional
Rel.finiteDimensional_or_infiniteDimensional
theorem
[Nonempty α] : r.FiniteDimensional ∨ r.InfiniteDimensional
lemma Rel.finiteDimensional_or_infiniteDimensional [Nonempty α] :
r.FiniteDimensional ∨ r.InfiniteDimensional := by
rw [← not_finiteDimensional_iff]
exact em r.FiniteDimensional
Rel.FiniteDimensional.swap
instance
[FiniteDimensional r] : FiniteDimensional (Function.swap r)
instance Rel.FiniteDimensional.swap [FiniteDimensional r] : FiniteDimensional (Function.swap r) :=
⟨.reverse (.longestOf r), fun s ↦ s.reverse.length_le_length_longestOf⟩
Rel.finiteDimensional_swap_iff
theorem
: FiniteDimensional (Function.swap r) ↔ FiniteDimensional r
Rel.InfiniteDimensional.swap
instance
[InfiniteDimensional r] : InfiniteDimensional (Function.swap r)
instance Rel.InfiniteDimensional.swap [InfiniteDimensional r] :
InfiniteDimensional (Function.swap r) :=
⟨fun n ↦ ⟨.reverse (.withLength r n), RelSeries.length_withLength r n⟩⟩
Rel.infiniteDimensional_swap_iff
theorem
: InfiniteDimensional (Function.swap r) ↔ InfiniteDimensional r
Rel.wellFounded_swap_of_finiteDimensional
theorem
[Rel.FiniteDimensional r] : WellFounded (Function.swap r)
lemma Rel.wellFounded_swap_of_finiteDimensional [Rel.FiniteDimensional r] :
WellFounded (Function.swap r) := by
rw [WellFounded.wellFounded_iff_no_descending_seq]
refine ⟨fun ⟨f, hf⟩ ↦ ?_⟩
let s := RelSeries.mk (r := r) ((RelSeries.longestOf r).length + 1) (f ·) (hf ·)
exact (RelSeries.longestOf r).length.lt_succ_self.not_le s.length_le_length_longestOf
Rel.wellFounded_of_finiteDimensional
theorem
[Rel.FiniteDimensional r] : WellFounded r
lemma Rel.wellFounded_of_finiteDimensional [Rel.FiniteDimensional r] : WellFounded r :=
have : (Rel.FiniteDimensional (Function.swap r)) := Rel.finiteDimensional_swap_iff.mp ‹_›
wellFounded_swap_of_finiteDimensional (Function.swap r)
FiniteDimensionalOrder
abbrev
(γ : Type*) [Preorder γ]
/-- A type is finite dimensional if its `LTSeries` has bounded length. -/
abbrev FiniteDimensionalOrder (γ : Type*) [Preorder γ] :=
Rel.FiniteDimensional ((· < ·) : γ → γ → Prop)
FiniteDimensionalOrder.ofUnique
instance
(γ : Type*) [Preorder γ] [Unique γ] : FiniteDimensionalOrder γ
instance FiniteDimensionalOrder.ofUnique (γ : Type*) [Preorder γ] [Unique γ] :
FiniteDimensionalOrder γ where
exists_longest_relSeries := ⟨.singleton _ default, fun x ↦ by
by_contra! r
exact (x.step ⟨0, by omega⟩).ne <| Subsingleton.elim _ _⟩
InfiniteDimensionalOrder
abbrev
(γ : Type*) [Preorder γ]
/-- A type is infinite dimensional if it has `LTSeries` of at least arbitrary length -/
abbrev InfiniteDimensionalOrder (γ : Type*) [Preorder γ] :=
Rel.InfiniteDimensional ((· < ·) : γ → γ → Prop)
LTSeries
abbrev
LTSeries.longestOf
definition
[FiniteDimensionalOrder α] : LTSeries α
/-- The longest `<`-series when a type is finite dimensional -/
protected noncomputable def longestOf [FiniteDimensionalOrder α] : LTSeries α :=
RelSeries.longestOf _
LTSeries.withLength
definition
[InfiniteDimensionalOrder α] (n : ℕ) : LTSeries α
/-- A `<`-series with length `n` if the relation is infinite dimensional -/
protected noncomputable def withLength [InfiniteDimensionalOrder α] (n : ℕ) : LTSeries α :=
RelSeries.withLength _ n
LTSeries.length_withLength
theorem
[InfiniteDimensionalOrder α] (n : ℕ) : (LTSeries.withLength α n).length = n
@[simp] lemma length_withLength [InfiniteDimensionalOrder α] (n : ℕ) :
(LTSeries.withLength α n).length = n :=
RelSeries.length_withLength _ _
LTSeries.nonempty_of_infiniteDimensionalOrder
theorem
[InfiniteDimensionalOrder α] : Nonempty α
/-- if `α` is infinite dimensional, then `α` is nonempty. -/
lemma nonempty_of_infiniteDimensionalOrder [InfiniteDimensionalOrder α] : Nonempty α :=
⟨LTSeries.withLength α 0 0⟩
LTSeries.nonempty_of_finiteDimensionalOrder
theorem
[FiniteDimensionalOrder α] : Nonempty α
lemma nonempty_of_finiteDimensionalOrder [FiniteDimensionalOrder α] : Nonempty α := by
obtain ⟨p, _⟩ := (Rel.finiteDimensional_iff _).mp ‹_›
exact ⟨p 0⟩
LTSeries.longestOf_is_longest
theorem
[FiniteDimensionalOrder α] (x : LTSeries α) : x.length ≤ (LTSeries.longestOf α).length
lemma longestOf_is_longest [FiniteDimensionalOrder α] (x : LTSeries α) :
x.length ≤ (LTSeries.longestOf α).length :=
RelSeries.length_le_length_longestOf _ _
LTSeries.longestOf_len_unique
theorem
[FiniteDimensionalOrder α] (p : LTSeries α) (is_longest : ∀ (q : LTSeries α), q.length ≤ p.length) :
p.length = (LTSeries.longestOf α).length
lemma longestOf_len_unique [FiniteDimensionalOrder α] (p : LTSeries α)
(is_longest : ∀ (q : LTSeries α), q.length ≤ p.length) :
p.length = (LTSeries.longestOf α).length :=
le_antisymm (longestOf_is_longest _) (is_longest _)
LTSeries.strictMono
theorem
(x : LTSeries α) : StrictMono x
lemma strictMono (x : LTSeries α) : StrictMono x :=
fun _ _ h => x.rel_of_lt h
LTSeries.monotone
theorem
(x : LTSeries α) : Monotone x
lemma monotone (x : LTSeries α) : Monotone x :=
x.strictMono.monotone
LTSeries.head_le_last
theorem
(x : LTSeries α) : x.head ≤ x.last
lemma head_le_last (x : LTSeries α) : x.head ≤ x.last :=
LTSeries.monotone x (Fin.zero_le _)
LTSeries.mk
definition
(length : ℕ) (toFun : Fin (length + 1) → α) (strictMono : StrictMono toFun) : LTSeries α
/-- An alternative constructor of `LTSeries` from a strictly monotone function. -/
@[simps]
def mk (length : ℕ) (toFun : Fin (length + 1) → α) (strictMono : StrictMono toFun) :
LTSeries α where
length := length
toFun := toFun
step i := strictMono <| lt_add_one i.1
LTSeries.injStrictMono
definition
(n : ℕ) : { f : (l : Fin n) × (Fin (l + 1) → α) // StrictMono f.2 } ↪ LTSeries α
/-- An injection from the type of strictly monotone functions with limited length to `LTSeries`. -/
def injStrictMono (n : ℕ) :
{f : (l : Fin n) × (Fin (l + 1) → α) // StrictMono f.2}{f : (l : Fin n) × (Fin (l + 1) → α) // StrictMono f.2} ↪ LTSeries α where
toFun f := mk f.1.1 f.1.2 f.2
inj' f g e := by
obtain ⟨⟨lf, f⟩, mf⟩ := f
obtain ⟨⟨lg, g⟩, mg⟩ := g
dsimp only at mf mg e
have leq := congr($(e).length)
rw [mk_length lf f mf, mk_length lg g mg, Fin.val_eq_val] at leq
subst leq
simp_rw [Subtype.mk_eq_mk, Sigma.mk.inj_iff, heq_eq_eq, true_and]
have feq := fun i ↦ congr($(e).toFun i)
simp_rw [mk_toFun lf f mf, mk_toFun lf g mg, mk_length lf f mf] at feq
rwa [funext_iff]
LTSeries.map
definition
(p : LTSeries α) (f : α → β) (hf : StrictMono f) : LTSeries β
/--
For two preorders `α, β`, if `f : α → β` is strictly monotonic, then a strict chain of `α`
can be pushed out to a strict chain of `β` by
`a₀ < a₁ < ... < aₙ ↦ f a₀ < f a₁ < ... < f aₙ`
-/
@[simps!]
def map (p : LTSeries α) (f : α → β) (hf : StrictMono f) : LTSeries β :=
LTSeries.mk p.length (f.comp p) (hf.comp p.strictMono)
LTSeries.head_map
theorem
(p : LTSeries α) (f : α → β) (hf : StrictMono f) : (p.map f hf).head = f p.head
LTSeries.last_map
theorem
(p : LTSeries α) (f : α → β) (hf : StrictMono f) : (p.map f hf).last = f p.last
LTSeries.comap
definition
(p : LTSeries β) (f : α → β) (comap : ∀ ⦃x y⦄, f x < f y → x < y) (surjective : Function.Surjective f) : LTSeries α
/--
For two preorders `α, β`, if `f : α → β` is surjective and strictly comonotonic, then a
strict series of `β` can be pulled back to a strict chain of `α` by
`b₀ < b₁ < ... < bₙ ↦ f⁻¹ b₀ < f⁻¹ b₁ < ... < f⁻¹ bₙ` where `f⁻¹ bᵢ` is an arbitrary element in the
preimage of `f⁻¹ {bᵢ}`.
-/
@[simps!]
noncomputable def comap (p : LTSeries β) (f : α → β)
(comap : ∀ ⦃x y⦄, f x < f y → x < y)
(surjective : Function.Surjective f) :
LTSeries α := mk p.length (fun i ↦ (surjective (p i)).choose)
(fun i j h ↦ comap (by simpa only [(surjective _).choose_spec] using p.strictMono h))
LTSeries.range
definition
(n : ℕ) : LTSeries ℕ
/-- The strict series `0 < … < n` in `ℕ`. -/
def range (n : ℕ) : LTSeries ℕ where
length := n
toFun := fun i => i
step i := Nat.lt_add_one i
LTSeries.length_range
theorem
(n : ℕ) : (range n).length = n
@[simp] lemma length_range (n : ℕ) : (range n).length = n := rfl
LTSeries.range_apply
theorem
(n : ℕ) (i : Fin (n + 1)) : (range n) i = i
@[simp] lemma range_apply (n : ℕ) (i : Fin (n+1)) : (range n) i = i := rfl
LTSeries.head_range
theorem
(n : ℕ) : (range n).head = 0
@[simp] lemma head_range (n : ℕ) : (range n).head = 0 := rfl
LTSeries.last_range
theorem
(n : ℕ) : (range n).last = n
@[simp] lemma last_range (n : ℕ) : (range n).last = n := rfl
LTSeries.exists_relSeries_covBy
theorem
{α} [PartialOrder α] [WellFoundedLT α] [WellFoundedGT α] (s : LTSeries α) :
∃ (t : RelSeries (α := α) (· ⋖ ·)) (i : Fin (s.length + 1) ↪ Fin (t.length + 1)),
t ∘ i = s ∧ i 0 = 0 ∧ i (.last _) = .last _
/-- Any `LTSeries` can be refined to a `CovBy`-`RelSeries`
in a bidirectionally well-founded order. -/
theorem exists_relSeries_covBy
{α} [PartialOrder α] [WellFoundedLT α] [WellFoundedGT α] (s : LTSeries α) :
∃ (t : RelSeries (α := α) (· ⋖ ·)) (i : Fin (s.length + 1) ↪ Fin (t.length + 1)),
t ∘ i = s ∧ i 0 = 0 ∧ i (.last _) = .last _ := by
obtain ⟨n, s, h⟩ := s
induction n with
| zero => exact ⟨⟨0, s, nofun⟩, (Equiv.refl _).toEmbedding, rfl, rfl, rfl⟩
| succ n IH =>
obtain ⟨t₁, i, ht, hi₁, hi₂⟩ := IH (s ∘ Fin.castSucc) fun _ ↦ h _
obtain ⟨t₂, h₁, m, h₂, ht₂⟩ :=
exists_covBy_seq_of_wellFoundedLT_wellFoundedGT_of_le (h (.last _)).le
let t₃ : RelSeries (α := α) (· ⋖ ·) := ⟨m, (t₂ ·), fun i ↦ by simpa using ht₂ i⟩
have H : t₁.last = t₂ 0 := (congr(t₁ $hi₂.symm).trans (congr_fun ht _)).trans h₁.symm
refine ⟨t₁.smash t₃ H, ⟨Fin.snoc (Fin.castLE (by simp) ∘ i) (.last _), ?_⟩, ?_, ?_, ?_⟩
· refine Fin.lastCases (Fin.lastCases (fun _ ↦ rfl) fun j eq ↦ ?_) fun j ↦ Fin.lastCases
(fun eq ↦ ?_) fun k eq ↦ Fin.ext (congr_arg Fin.val (by simpa using eq) :)
on_goal 2 => rw [eq_comm] at eq
all_goals
rw [Fin.snoc_castSucc] at eq
obtain rfl : m = 0 := by simpa [t₃] using (congr_arg Fin.val eq).trans_lt (i j).2
cases (h (.last _)).ne' (h₂.symm.trans h₁)
· refine funext (Fin.lastCases ?_ fun j ↦ ?_)
· convert h₂; simpa using RelSeries.last_smash ..
convert congr_fun ht j using 1
simp [RelSeries.smash_castLE]
all_goals simp [Fin.snoc, Fin.castPred_zero, hi₁]
LTSeries.exists_relSeries_covBy_and_head_eq_bot_and_last_eq_bot
theorem
{α} [PartialOrder α] [BoundedOrder α] [WellFoundedLT α] [WellFoundedGT α] (s : LTSeries α) :
∃ (t : RelSeries (α := α) (· ⋖ ·)) (i : Fin (s.length + 1) ↪ Fin (t.length + 1)), t ∘ i = s ∧ t.head = ⊥ ∧ t.last = ⊤
theorem exists_relSeries_covBy_and_head_eq_bot_and_last_eq_bot
{α} [PartialOrder α] [BoundedOrder α] [WellFoundedLT α] [WellFoundedGT α] (s : LTSeries α) :
∃ (t : RelSeries (α := α) (· ⋖ ·)) (i : Fin (s.length + 1) ↪ Fin (t.length + 1)),
t ∘ i = s ∧ t.head = ⊥ ∧ t.last = ⊤ := by
wlog h₁ : s.head = ⊥
· obtain ⟨t, i, hi, ht⟩ := this (s.cons ⊥ (bot_lt_iff_ne_bot.mpr h₁)) rfl
exact ⟨t, ⟨fun j ↦ i (j.succ.cast (by simp)), fun _ _ ↦ by simp⟩,
funext fun j ↦ (congr_fun hi _).trans (RelSeries.cons_cast_succ _ _ _ _), ht⟩
wlog h₂ : s.last = ⊤
· obtain ⟨t, i, hi, ht⟩ := this (s.snoc ⊤ (lt_top_iff_ne_top.mpr h₂)) (by simp [h₁]) (by simp)
exact ⟨t, ⟨fun j ↦ i (.cast (by simp) j.castSucc), fun _ _ ↦ by simp⟩,
funext fun j ↦ (congr_fun hi _).trans (RelSeries.snoc_cast_castSucc _ _ _ _), ht⟩
obtain ⟨t, i, hit, hi₁, hi₂⟩ := s.exists_relSeries_covBy
refine ⟨t, i, hit, ?_, ?_⟩
· rw [← h₁, RelSeries.head, RelSeries.head, ← hi₁, ← hit, Function.comp]
· rw [← h₂, RelSeries.last, RelSeries.last, ← hi₂, ← hit, Function.comp]
LTSeries.apply_add_index_le_apply_add_index_nat
theorem
(p : LTSeries ℕ) (i j : Fin (p.length + 1)) (hij : i ≤ j) : p i + j ≤ p j + i
/--
In ℕ, two entries in an `LTSeries` differ by at least the difference of their indices.
(Expressed in a way that avoids subtraction).
-/
lemma apply_add_index_le_apply_add_index_nat (p : LTSeries ℕ) (i j : Fin (p.length + 1))
(hij : i ≤ j) : p i + j ≤ p j + i := by
have ⟨i, hi⟩ := i
have ⟨j, hj⟩ := j
simp only [Fin.mk_le_mk] at hij
simp only at *
induction j, hij using Nat.le_induction with
| base => simp
| succ j _hij ih =>
specialize ih (Nat.lt_of_succ_lt hj)
have step : p ⟨j, _⟩ < p ⟨j + 1, _⟩ := p.step ⟨j, by omega⟩
norm_cast at *; omega
LTSeries.apply_add_index_le_apply_add_index_int
theorem
(p : LTSeries ℤ) (i j : Fin (p.length + 1)) (hij : i ≤ j) : p i + j ≤ p j + i
/--
In ℤ, two entries in an `LTSeries` differ by at least the difference of their indices.
(Expressed in a way that avoids subtraction).
-/
lemma apply_add_index_le_apply_add_index_int (p : LTSeries ℤ) (i j : Fin (p.length + 1))
(hij : i ≤ j) : p i + j ≤ p j + i := by
-- The proof is identical to `LTSeries.apply_add_index_le_apply_add_index_nat`, but seemed easier
-- to copy rather than to abstract
have ⟨i, hi⟩ := i
have ⟨j, hj⟩ := j
simp only [Fin.mk_le_mk] at hij
simp only at *
induction j, hij using Nat.le_induction with
| base => simp
| succ j _hij ih =>
specialize ih (Nat.lt_of_succ_lt hj)
have step : p ⟨j, _⟩ < p ⟨j + 1, _⟩:= p.step ⟨j, by omega⟩
norm_cast at *; omega
LTSeries.head_add_length_le_nat
theorem
(p : LTSeries ℕ) : p.head + p.length ≤ p.last
/-- In ℕ, the head and tail of an `LTSeries` differ at least by the length of the series -/
lemma head_add_length_le_nat (p : LTSeries ℕ) : p.head + p.length ≤ p.last :=
LTSeries.apply_add_index_le_apply_add_index_nat _ _ (Fin.last _) (Fin.zero_le _)
LTSeries.head_add_length_le_int
theorem
(p : LTSeries ℤ) : p.head + p.length ≤ p.last
/-- In ℤ, the head and tail of an `LTSeries` differ at least by the length of the series -/
lemma head_add_length_le_int (p : LTSeries ℤ) : p.head + p.length ≤ p.last := by
simpa using LTSeries.apply_add_index_le_apply_add_index_int _ _ (Fin.last _) (Fin.zero_le _)
LTSeries.length_lt_card
theorem
(s : LTSeries α) : s.length < Fintype.card α
lemma length_lt_card (s : LTSeries α) : s.length < Fintype.card α := by
by_contra! h
obtain ⟨i, j, hn, he⟩ := Fintype.exists_ne_map_eq_of_card_lt s (by rw [Fintype.card_fin]; omega)
wlog hl : i < j generalizing i j
· exact this j i hn.symm he.symm (by omega)
exact absurd he (s.strictMono hl).ne
LTSeries.instFintypeOfDecidableLT
instance
[DecidableLT α] : Fintype (LTSeries α)
instance [DecidableLT α] : Fintype (LTSeries α) where
elems := Finset.univ.map (injStrictMono (Fintype.card α))
complete s := by
have bl := s.length_lt_card
obtain ⟨l, f, mf⟩ := s
simp_rw [Finset.mem_map, Finset.mem_univ, true_and, Subtype.exists]
use ⟨⟨l, bl⟩, f⟩, Fin.strictMono_iff_lt_succ.mpr mf; rfl
not_finiteDimensionalOrder_iff
theorem
[Preorder α] [Nonempty α] : ¬FiniteDimensionalOrder α ↔ InfiniteDimensionalOrder α
not_infiniteDimensionalOrder_iff
theorem
[Preorder α] [Nonempty α] : ¬InfiniteDimensionalOrder α ↔ FiniteDimensionalOrder α
finiteDimensionalOrder_or_infiniteDimensionalOrder
theorem
[Preorder α] [Nonempty α] : FiniteDimensionalOrder α ∨ InfiniteDimensionalOrder α
infiniteDimensionalOrder_of_strictMono
theorem
[Preorder α] [Preorder β] (f : α → β) (hf : StrictMono f) [InfiniteDimensionalOrder α] : InfiniteDimensionalOrder β
/-- If `f : α → β` is a strictly monotonic function and `α` is an infinite dimensional type then so
is `β`. -/
lemma infiniteDimensionalOrder_of_strictMono [Preorder α] [Preorder β]
(f : α → β) (hf : StrictMono f) [InfiniteDimensionalOrder α] :
InfiniteDimensionalOrder β :=
⟨fun n ↦ ⟨(LTSeries.withLength _ n).map f hf, LTSeries.length_withLength α n⟩⟩