@@ -4,6 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE.
44Authors: Mario Carneiro, Vasilii Nesterov
55-/
66import Mathlib.Data.Seq.Defs
7+ import Mathlib.Data.ENat.Basic
8+ import Mathlib.Tactic.ENatToNat
9+ import Mathlib.Tactic.ApplyFun
710
811/-!
912# Basic properties of sequences (possibly infinite lists)
@@ -20,6 +23,101 @@ namespace Seq
2023
2124variable {α : Type u} {β : Type v} {γ : Type w}
2225
26+ section length
27+
28+ theorem length'_of_terminates {s : Seq α} (h : s.Terminates) :
29+ s.length' = s.length h := by
30+ simp [length', h]
31+
32+ theorem length'_of_not_terminates {s : Seq α} (h : ¬ s.Terminates) :
33+ s.length' = ⊤ := by
34+ simp [length', h]
35+
36+ @[simp]
37+ theorem length_nil : length (nil : Seq α) terminates_nil = 0 := rfl
38+
39+ @[simp]
40+ theorem length'_nil : length' (nil : Seq α) = 0 := by
41+ simp -implicitDefEqProofs [length']
42+
43+ theorem length_cons {x : α} {s : Seq α} (h : s.Terminates) :
44+ (cons x s).length (terminates_cons_iff.mpr h) = s.length h + 1 := by
45+ apply Nat.find_comp_succ
46+ simp
47+
48+ @[simp]
49+ theorem length'_cons (x : α) (s : Seq α) :
50+ (cons x s).length' = s.length' + 1 := by
51+ by_cases h : (cons x s).Terminates <;> have h' := h <;> rw [terminates_cons_iff] at h'
52+ · simp [length'_of_terminates h, length'_of_terminates h', length_cons h']
53+ · simp [length'_of_not_terminates h, length'_of_not_terminates h']
54+
55+ @[simp]
56+ theorem length_eq_zero {s : Seq α} {h : s.Terminates} :
57+ s.length h = 0 ↔ s = nil := by
58+ simp [length, TerminatedAt]
59+
60+ @[simp]
61+ theorem length'_eq_zero_iff_nil (s : Seq α) :
62+ s.length' = 0 ↔ s = nil := by
63+ cases s <;> simp
64+
65+ theorem length'_ne_zero_iff_cons (s : Seq α) :
66+ s.length' ≠ 0 ↔ ∃ x s', s = cons x s' := by
67+ cases s <;> simp
68+
69+ /-- The statement of `length_le_iff'` does not assume that the sequence terminates. For a
70+ simpler statement of the theorem where the sequence is known to terminate see `length_le_iff`. -/
71+ theorem length_le_iff' {s : Seq α} {n : ℕ} :
72+ (∃ h, s.length h ≤ n) ↔ s.TerminatedAt n := by
73+ simp only [length, Nat.find_le_iff, TerminatedAt, Terminates, exists_prop]
74+ refine ⟨?_, ?_⟩
75+ · rintro ⟨_, k, hkn, hk⟩
76+ exact le_stable s hkn hk
77+ · intro hn
78+ exact ⟨⟨n, hn⟩, ⟨n, le_rfl, hn⟩⟩
79+
80+ /-- The statement of `length_le_iff` assumes that the sequence terminates. For a
81+ statement of the where the sequence is not known to terminate see `length_le_iff'`. -/
82+ theorem length_le_iff {s : Seq α} {n : ℕ} {h : s.Terminates} :
83+ s.length h ≤ n ↔ s.TerminatedAt n := by
84+ rw [← length_le_iff']; simp [h]
85+
86+ theorem length'_le_iff {s : Seq α} {n : ℕ} :
87+ s.length' ≤ n ↔ s.TerminatedAt n := by
88+ by_cases h : s.Terminates
89+ · simpa [length'_of_terminates h] using length_le_iff
90+ · simpa [length'_of_not_terminates h] using forall_not_of_not_exists h n
91+
92+ /-- The statement of `lt_length_iff'` does not assume that the sequence terminates. For a
93+ simpler statement of the theorem where the sequence is known to terminate see `lt_length_iff`. -/
94+ theorem lt_length_iff' {s : Seq α} {n : ℕ} :
95+ (∀ h : s.Terminates, n < s.length h) ↔ ∃ a, a ∈ s.get? n := by
96+ simp only [Terminates, TerminatedAt, length, Nat.lt_find_iff, forall_exists_index, Option.mem_def,
97+ ← Option.ne_none_iff_exists', ne_eq]
98+ refine ⟨?_, ?_⟩
99+ · intro h hn
100+ exact h n hn n le_rfl hn
101+ · intro hn _ _ k hkn hk
102+ exact hn <| le_stable s hkn hk
103+
104+ /-- The statement of `length_le_iff` assumes that the sequence terminates. For a
105+ statement of the where the sequence is not known to terminate see `length_le_iff'`. -/
106+ theorem lt_length_iff {s : Seq α} {n : ℕ} {h : s.Terminates} :
107+ n < s.length h ↔ ∃ a, a ∈ s.get? n := by
108+ rw [← lt_length_iff']; simp [h]
109+
110+ theorem lt_length'_iff {s : Seq α} {n : ℕ} :
111+ n < s.length' ↔ ∃ a, a ∈ s.get? n := by
112+ by_cases h : s.Terminates
113+ · simpa [length'_of_terminates h] using lt_length_iff
114+ · simp only [length'_of_not_terminates h, ENat.coe_lt_top, Option.mem_def, true_iff]
115+ rw [not_terminates_iff] at h
116+ rw [← Option.isSome_iff_exists]
117+ exact h n
118+
119+ end length
120+
23121section OfStream
24122
25123@[simp]
@@ -69,8 +167,7 @@ theorem getElem?_take : ∀ (n k : ℕ) (s : Seq α),
69167 rw [destruct_eq_cons h]
70168 match n with
71169 | 0 => simp
72- | n+1 =>
73- simp [List.getElem?_cons_succ, Nat.add_lt_add_iff_right, getElem?_take]
170+ | n+1 => simp [List.getElem?_cons_succ, getElem?_take]
74171
75172theorem get?_mem_take {s : Seq α} {m n : ℕ} (h_mn : m < n) {x : α}
76173 (h_get : s.get? m = some x) : x ∈ s.take n := by
@@ -285,6 +382,13 @@ theorem length_map {s : Seq α} {f : α → β} (h : (s.map f).Terminates) :
285382 ext
286383 simp
287384
385+ @[simp]
386+ theorem length'_map {s : Seq α} {f : α → β} :
387+ (s.map f).length' = s.length' := by
388+ by_cases h : (s.map f).Terminates <;> have h' := h <;> rw [terminates_map_iff] at h'
389+ · rw [length'_of_terminates h, length'_of_terminates h', length_map h]
390+ · rw [length'_of_not_terminates h, length'_of_not_terminates h']
391+
288392theorem mem_map (f : α → β) {a : α} : ∀ {s : Seq α}, a ∈ s → f a ∈ map f s
289393 | ⟨_, _⟩ => Stream'.mem_map (Option.map f)
290394
@@ -397,6 +501,9 @@ theorem head_dropn (s : Seq α) (n) : head (drop s n) = get? s n := by
397501 | zero => rfl
398502 | succ n IH => rw [← get?_tail, ← dropn_tail]; apply IH
399503
504+ @[simp]
505+ theorem drop_zero {s : Seq α} : s.drop 0 = s := rfl
506+
400507@[simp]
401508theorem drop_succ_cons {x : α} {s : Seq α} {n : ℕ} :
402509 (cons x s).drop (n + 1 ) = s.drop n := by
@@ -408,6 +515,21 @@ theorem drop_nil {n : ℕ} : (@nil α).drop n = nil := by
408515 | zero => simp [drop]
409516 | succ m ih => simp [← dropn_tail, ih]
410517
518+ @[simp]
519+ theorem drop_length' {n : ℕ} {s : Seq α} :
520+ (s.drop n).length' = s.length' - n := by
521+ cases n with
522+ | zero => simp
523+ | succ n =>
524+ cases s with
525+ | nil => simp
526+ | cons x s =>
527+ simp only [drop_succ_cons, length'_cons, Nat.cast_add, Nat.cast_one]
528+ convert drop_length' using 1
529+ generalize s.length' = m
530+ enat_to_nat
531+ omega
532+
411533theorem take_drop {s : Seq α} {n m : ℕ} :
412534 (s.take n).drop m = (s.drop m).take (n - m) := by
413535 induction m generalizing n s with
@@ -604,6 +726,222 @@ theorem drop_set_of_lt (s : Seq α) {m n : ℕ} (h : m < n) : (s.set m x).drop n
604726
605727end Update
606728
729+ section All
730+
731+ theorem all_cons {p : α → Prop } {hd : α} {tl : Seq α} (h_hd : p hd) (h_tl : ∀ x ∈ tl, p x) :
732+ (∀ x ∈ (cons hd tl), p x) := by
733+ simp only [mem_cons_iff, forall_eq_or_imp] at *
734+ exact ⟨h_hd, h_tl⟩
735+
736+ theorem all_get {p : α → Prop } {s : Seq α} (h : ∀ x ∈ s, p x) {n : ℕ} {x : α}
737+ (hx : s.get? n = .some x) :
738+ p x := by
739+ exact h _ (get?_mem hx)
740+
741+ theorem all_of_get {p : α → Prop } {s : Seq α} (h : ∀ n x, s.get? n = .some x → p x) :
742+ ∀ x ∈ s, p x := by
743+ simp only [mem_iff_exists_get?]
744+ grind
745+
746+ private lemma all_coind_drop_motive {s : Seq α} (motive : Seq α → Prop ) (base : motive s)
747+ (step : ∀ hd tl, motive (.cons hd tl) → motive tl) (n : ℕ) :
748+ motive (s.drop n) := by
749+ induction n with
750+ | zero => simpa
751+ | succ m ih =>
752+ simp only [drop]
753+ generalize s.drop m = t at *
754+ cases t
755+ · simpa
756+ · exact step _ _ ih
757+
758+ /-- Coinductive principle for `All`. -/
759+ theorem all_coind {s : Seq α} {p : α → Prop }
760+ (motive : Seq α → Prop ) (base : motive s)
761+ (step : ∀ hd tl, motive (.cons hd tl) → p hd ∧ motive tl) :
762+ ∀ x ∈ s, p x := by
763+ apply all_of_get
764+ intro n
765+ have := all_coind_drop_motive motive base (fun hd tl ih ↦ (step hd tl ih).right) n
766+ rw [← head_dropn]
767+ generalize s.drop n = s' at this
768+ cases s' with
769+ | nil => simp
770+ | cons hd tl => simp [(step hd tl this).left]
771+
772+ theorem map_all_iff {β : Type u} {f : α → β} {p : β → Prop } {s : Seq α} :
773+ (∀ x ∈ (s.map f), p x) ↔ (∀ x ∈ s, (p ∘ f) x) := by
774+ refine ⟨fun _ _ hx ↦ ?_, fun _ _ hx ↦ ?_⟩
775+ · solve_by_elim [mem_map f hx]
776+ · obtain ⟨_, _, hx'⟩ := exists_of_mem_map hx
777+ rw [← hx']
778+ solve_by_elim
779+
780+ theorem take_all {s : Seq α} {p : α → Prop } (h_all : ∀ x ∈ s, p x) {n : ℕ} {x : α}
781+ (hx : x ∈ s.take n) : p x := by
782+ induction n generalizing s with
783+ | zero => simp [take] at hx
784+ | succ m ih =>
785+ cases s with
786+ | nil => simp at hx
787+ | cons hd tl =>
788+ simp only [take_succ_cons, List.mem_cons, mem_cons_iff, forall_eq_or_imp] at hx h_all
789+ rcases hx with (rfl | hx)
790+ exacts [h_all.left, ih h_all.right hx]
791+
792+ theorem set_all {p : α → Prop } {s : Seq α} (h_all : ∀ x ∈ s, p x) {n : ℕ} {x : α}
793+ (hx : p x) : ∀ y ∈ (s.set n x), p y := by
794+ intro y hy
795+ simp only [mem_iff_exists_get?] at hy
796+ obtain ⟨m, hy⟩ := hy
797+ rcases eq_or_ne n m with (rfl | h_nm)
798+ · by_cases h_term : s.TerminatedAt n
799+ · simp [get?_set_of_terminatedAt _ h_term] at hy
800+ · simp_all [get?_set_of_not_terminatedAt _ h_term]
801+ · rw [get?_set_of_ne _ _ h_nm.symm] at hy
802+ apply h_all _ (get?_mem hy.symm)
803+
804+ end All
805+
806+ section Pairwise
807+
808+ @[simp]
809+ theorem Pairwise.nil {R : α → α → Prop } : Pairwise R (@nil α) := by
810+ simp [Pairwise]
811+
812+ theorem Pairwise.cons {R : α → α → Prop } {hd : α} {tl : Seq α}
813+ (h_hd : ∀ x ∈ tl, R hd x)
814+ (h_tl : Pairwise R tl) : Pairwise R (cons hd tl) := by
815+ simp only [Pairwise] at *
816+ intro i j h_ij x hx y hy
817+ cases j with
818+ | zero => simp at h_ij
819+ | succ k =>
820+ simp only [get?_cons_succ] at hy
821+ cases i with
822+ | zero =>
823+ simp only [get?_cons_zero, Option.mem_def, Option.some.injEq] at hx
824+ exact hx ▸ all_get h_hd hy
825+ | succ n => exact h_tl n k (by omega) x hx y hy
826+
827+ theorem Pairwise.cons_elim {R : α → α → Prop } {hd : α} {tl : Seq α}
828+ (h : Pairwise R (.cons hd tl)) : (∀ x ∈ tl, R hd x) ∧ Pairwise R tl := by
829+ simp only [Pairwise] at *
830+ refine ⟨?_, fun i j h_ij ↦ h (i + 1 ) (j + 1 ) (by omega)⟩
831+ intro x hx
832+ rw [mem_iff_exists_get?] at hx
833+ obtain ⟨n, hx⟩ := hx
834+ simpa [← hx] using h 0 (n + 1 ) (by omega)
835+
836+ @[simp]
837+ theorem Pairwise_cons_nil {R : α → α → Prop } {hd : α} : Pairwise R (cons hd nil) := by
838+ apply Pairwise.cons <;> simp
839+
840+ theorem Pairwise_cons_cons_head {R : α → α → Prop } {hd tl_hd : α} {tl_tl : Seq α}
841+ (h : Pairwise R (cons hd (cons tl_hd tl_tl))) :
842+ R hd tl_hd := by
843+ simp only [Pairwise] at h
844+ simpa using h 0 1 Nat.one_pos
845+
846+ theorem Pairwise.cons_cons_of_trans {R : α → α → Prop } [IsTrans _ R] {hd tl_hd : α} {tl_tl : Seq α}
847+ (h_hd : R hd tl_hd)
848+ (h_tl : Pairwise R (.cons tl_hd tl_tl)) : Pairwise R (.cons hd (.cons tl_hd tl_tl)) := by
849+ apply Pairwise.cons _ h_tl
850+ simp only [mem_cons_iff, forall_eq_or_imp]
851+ exact ⟨h_hd, fun x hx ↦ Trans.simple h_hd ((cons_elim h_tl).left x hx)⟩
852+
853+
854+ /-- Coinductive principle for `Pairwise`. -/
855+ theorem Pairwise.coind {R : α → α → Prop } {s : Seq α}
856+ (motive : Seq α → Prop ) (base : motive s)
857+ (step : ∀ hd tl, motive (.cons hd tl) → (∀ x ∈ tl, R hd x) ∧ motive tl) : Pairwise R s := by
858+ simp only [Pairwise]
859+ intro i j h_ij x hx y hy
860+ obtain ⟨k, hj⟩ := Nat.exists_eq_add_of_lt h_ij
861+ rw [← head_dropn] at hx
862+ rw [hj, ← head_dropn, Nat.add_assoc, dropn_add, head_dropn] at hy
863+ have := all_coind_drop_motive motive base (fun hd tl ih ↦ (step hd tl ih).right) i
864+ generalize s.drop i = s' at *
865+ cases s' with
866+ | nil => simp at hx
867+ | cons hd tl =>
868+ simp at hx hy
869+ exact hx ▸ all_get (step hd tl this).left hy
870+
871+ /-- Coinductive principle for `Pairwise` that assumes that `R` is transitive. Compared to
872+ `Pairwise.coind`, this allows you to prove `R hd tl.head` instead of `tl.All (R hd ·)` in `step`.
873+ -/
874+ theorem Pairwise.coind_trans {R : α → α → Prop } [IsTrans α R] {s : Seq α}
875+ (motive : Seq α → Prop ) (base : motive s)
876+ (step : ∀ hd tl, motive (.cons hd tl) → (∀ x ∈ tl.head, R hd x) ∧ motive tl) :
877+ Pairwise R s := by
878+ have h_succ {n} {x y} (hx : s.get? n = some x) (hy : s.get? (n + 1 ) = some y) : R x y := by
879+ rw [← head_dropn] at hx
880+ have := all_coind_drop_motive motive base (fun hd tl ih ↦ (step hd tl ih).right)
881+ exact (step x (s.drop (n + 1 )) (head_eq_some hx ▸ this n)).left _ (by simpa)
882+ simp only [Pairwise]
883+ intro i j h_ij x hx y hy
884+ obtain ⟨k, rfl⟩ := Nat.exists_eq_add_of_lt h_ij
885+ clear h_ij
886+ induction k generalizing y with
887+ | zero => exact h_succ hx hy
888+ | succ k ih =>
889+ obtain ⟨z, hz⟩ := ge_stable (m := i + k + 1 ) _ (by omega) hy
890+ exact _root_.trans (ih z hz) <| h_succ hz hy
891+
892+ theorem Pairwise_tail {R : α → α → Prop } {s : Seq α} (h : s.Pairwise R) :
893+ s.tail.Pairwise R := by
894+ cases s
895+ · simp
896+ · simp [h.cons_elim.right]
897+
898+ theorem Pairwise_drop {R : α → α → Prop } {s : Seq α} (h : s.Pairwise R) {n : ℕ} :
899+ (s.drop n).Pairwise R := by
900+ induction n with
901+ | zero => simpa
902+ | succ m ih => simp [drop, Pairwise_tail ih]
903+
904+ end Pairwise
905+
906+ /-- Coinductive principle for proving `b.length' ≤ a.length'` for two sequences `a` and `b`. -/
907+ theorem at_least_as_long_as_coind {a : Seq α} {b : Seq β}
908+ (motive : Seq α → Seq β → Prop ) (base : motive a b)
909+ (step : ∀ a b, motive a b →
910+ (∀ b_hd b_tl, (b = .cons b_hd b_tl) → ∃ a_hd a_tl, a = .cons a_hd a_tl ∧ motive a_tl b_tl)) :
911+ b.length' ≤ a.length' := by
912+ have (n) (hb : b.drop n ≠ .nil) : motive (a.drop n) (b.drop n) := by
913+ induction n with
914+ | zero => simpa
915+ | succ m ih =>
916+ simp only [drop] at hb ⊢
917+ generalize b.drop m = tb at *
918+ cases tb with
919+ | nil => simp at hb
920+ | cons tb_hd tb_tl =>
921+ simp only [ne_eq, cons_ne_nil, not_false_eq_true, forall_const] at ih
922+ obtain ⟨a_hd, a_tl, ha, h_tail⟩ := step (a.drop m) (.cons tb_hd tb_tl) ih _ _ rfl
923+ simpa [ha]
924+ by_cases ha : a.Terminates; swap
925+ · simp [length'_of_not_terminates ha]
926+ simp [length'_of_terminates ha, length'_le_iff]
927+ by_contra! hb
928+ have hb_cons : b.drop (a.length ha) ≠ .nil := by
929+ intro hb'
930+ simp only [← length'_eq_zero_iff_nil, drop_length', tsub_eq_zero_iff_le, length'_le_iff] at hb'
931+ contradiction
932+ specialize this (a.length ha) hb_cons
933+ generalize b.drop (a.length ha) = b' at *
934+ cases b' with
935+ | nil =>
936+ contradiction
937+ | cons b_hd b_tl =>
938+ obtain ⟨a_hd, a_tl, ha', _⟩ := step _ _ this _ _ rfl
939+ apply_fun length' at ha'
940+ simp only [drop_length', length'_of_terminates ha, tsub_self, length'_cons] at ha'
941+ generalize a_tl.length' = u at ha'
942+ enat_to_nat
943+ omega
944+
607945instance : Functor Seq where map := @map
608946
609947instance : LawfulFunctor Seq where
0 commit comments