Skip to content

Commit e912abd

Browse files
committed
feat: add Cslib/Foundations/Data/Nat/Segment.lean
1 parent 0e28a18 commit e912abd

File tree

2 files changed

+265
-0
lines changed

2 files changed

+265
-0
lines changed

Cslib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import Cslib.Foundations.Control.Monad.Free.Effects
1111
import Cslib.Foundations.Control.Monad.Free.Fold
1212
import Cslib.Foundations.Data.FinFun
1313
import Cslib.Foundations.Data.HasFresh
14+
import Cslib.Foundations.Data.Nat.Segment
1415
import Cslib.Foundations.Data.OmegaSequence.Defs
1516
import Cslib.Foundations.Data.OmegaSequence.Init
1617
import Cslib.Foundations.Data.Relation
Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
/-
2+
Copyright (c) 2025 Ching-Tsun Chou. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Ching-Tsun Chou
5+
-/
6+
7+
import Mathlib.Algebra.Order.Sub.Basic
8+
import Mathlib.Data.Nat.Nth
9+
import Mathlib.Tactic
10+
11+
namespace Cslib
12+
13+
open Function Set
14+
15+
/-!
16+
Given a strictly monotonic function `φ : ℕ → ℕ` and `k : ℕ` with `k ≥ ϕ 0`,
17+
`Nat.segment φ k` is the unique `m : ℕ` such that `φ m ≤ k < φ (k + 1)`.
18+
`Nat.segment φ k` is defined to be 0 for `k < ϕ 0`.
19+
This file defines `Nat.segment` and proves various properties aboout it.
20+
-/
21+
noncomputable def Nat.segment (φ : ℕ → ℕ) (k : ℕ) : ℕ :=
22+
open scoped Classical in
23+
Nat.count (· ∈ range φ) (k + 1) - 1
24+
25+
variable {φ : ℕ → ℕ}
26+
27+
/-- Any strictly monotonic function `φ : ℕ → ℕ` has an infinite range. -/
28+
theorem Nat.strict_mono_infinite (hm : StrictMono φ) :
29+
(range φ).Infinite := by
30+
exact infinite_range_of_injective hm.injective
31+
32+
/-- Any infinite suset of `ℕ` is the range of a strictly monotonic function. -/
33+
theorem Nat.infinite_strict_mono {ns : Set ℕ} (h : ns.Infinite) :
34+
∃ φ : ℕ → ℕ, StrictMono φ ∧ range φ = ns := by
35+
use Nat.nth (· ∈ ns) ; constructor
36+
· exact Nat.nth_strictMono h
37+
· exact Nat.range_nth_of_infinite h
38+
39+
open scoped Classical in
40+
/-- There is a gap between two successive occurrences of a predicate `p : ℕ → Prop`,
41+
assuming `p` (as a set) is infinite. -/
42+
theorem Nat.nth_succ_gap {p : ℕ → Prop} (hf : (setOf p).Infinite) (n : ℕ) :
43+
∀ k < Nat.nth p (n + 1) - Nat.nth p n, k > 0 → ¬ p (k + Nat.nth p n) := by
44+
intro k h_k1 h_k0 h_p_k
45+
let m := Nat.count p (k + Nat.nth p n)
46+
have h_k_ex : Nat.nth p m = k + Nat.nth p n := by simp [m, Nat.nth_count h_p_k]
47+
have h_n_m : n < m := by apply (Nat.nth_lt_nth hf).mp ; omega
48+
have h_m_n : m < n + 1 := by apply (Nat.nth_lt_nth hf).mp ; omega
49+
omega
50+
51+
/-- For a strictly monotonic function `φ : ℕ → ℕ`, `φ n` is exactly the n-th
52+
element of the range of `φ`. -/
53+
theorem Nat.nth_of_strict_mono (hm : StrictMono φ) (n : ℕ) :
54+
φ n = Nat.nth (· ∈ range φ) n := by
55+
rw [← Nat.nth_comp_of_strictMono hm (by simp)]
56+
· simp
57+
intro hf ; exfalso
58+
have : (range φ).Infinite := strict_mono_infinite hm
59+
exact absurd hf this
60+
61+
open scoped Classical in
62+
/-- If `φ 0 = 0`, then `0` is below any `n` not in the range of `φ`. -/
63+
theorem Nat.count_notin_range_pos (h0 : φ 0 = 0) (n : ℕ) (hn : n ∉ range φ) :
64+
Nat.count (· ∈ range φ) n > 0 := by
65+
have h0' : 0 ∈ range φ := by use 0
66+
have h1 : n ≠ 0 := by rintro ⟨rfl⟩ ; contradiction
67+
have h2 : 1 ≤ n := by omega
68+
have h3 := Nat.count_monotone (· ∈ range φ) h2
69+
simp only [Nat.count_succ, Nat.count_zero, h0', ↓reduceIte, zero_add, gt_iff_lt] at h3 ⊢
70+
omega
71+
72+
/-- For a strictly monotonic function `φ : ℕ → ℕ`, no number (strictly) between
73+
`φ m` and ` φ (m + 1)` is in the range of `φ`. -/
74+
theorem Nat.strict_mono_range_gap (hm : StrictMono φ) {m k : ℕ}
75+
(hl : φ m < k) (hu : k < φ (m + 1)) : k ∉ range φ := by
76+
rw [nth_of_strict_mono hm m] at hl
77+
rw [nth_of_strict_mono hm (m + 1)] at hu
78+
have h_inf := strict_mono_infinite hm
79+
have h_gap := nth_succ_gap (p := (· ∈ range φ)) h_inf m
80+
(k - Nat.nth (· ∈ range φ) m) (by omega) (by omega)
81+
rw [(show k - Nat.nth (· ∈ range φ) m + Nat.nth (· ∈ range φ) m = k by omega)] at h_gap
82+
exact h_gap
83+
84+
open scoped Classical in
85+
/-- For a strictly monotonic function `φ : ℕ → ℕ`, the segment of `φ k` is `k`. -/
86+
theorem Nat.segment_idem (hm : StrictMono φ) (k : ℕ) :
87+
segment φ (φ k) = k := by
88+
have h1 : Nat.count (· ∈ range φ) (φ k + 1) = Nat.count (· ∈ range φ) (φ k) + 1 := by
89+
apply Nat.count_succ_eq_succ_count ; simp
90+
rw [segment, h1, Nat.add_one_sub_one, nth_of_strict_mono hm]
91+
have h_eq := Nat.count_nth_of_infinite (p := (· ∈ range φ)) <| strict_mono_infinite hm
92+
rw [h_eq]
93+
94+
open scoped Classical in
95+
/-- For a strictly monotonic function `φ : ℕ → ℕ`, `segment φ k = 0` for all `k < φ 0`. -/
96+
theorem Nat.segment_pre_zero (hm : StrictMono φ) {k : ℕ} (h : k < φ 0) :
97+
segment φ k = 0 := by
98+
have h1 : Nat.count (· ∈ range φ) (k + 1) = 0 := by
99+
apply Nat.count_of_forall_not
100+
rintro n h_n ⟨i, rfl⟩
101+
have := StrictMono.monotone hm <| zero_le i
102+
omega
103+
rw [segment, h1]
104+
105+
/-- For a strictly monotonic function `φ : ℕ → ℕ` with `φ 0 = 0`, `segment φ 0 = 0`. -/
106+
theorem Nat.segment_zero (hm : StrictMono φ) (h0 : φ 0 = 0) :
107+
segment φ 0 = 0 := by
108+
calc _ = segment φ (φ 0) := by simp [h0]
109+
_ = _ := by simp [segment_idem hm]
110+
111+
open scoped Classical in
112+
/-- A slight restatement of the definition of `segment` which has proven useful. -/
113+
theorem Nat.segment_plus_one (h0 : φ 0 = 0) (k : ℕ) :
114+
segment φ k + 1 = Nat.count (· ∈ range φ) (k + 1) := by
115+
suffices _ : Nat.count (· ∈ range φ) (k + 1) ≠ 0 by unfold segment ; omega
116+
apply Nat.count_ne_iff_exists.mpr ; use 0 ; grind
117+
118+
open scoped Classical in
119+
/-- For a strictly monotonic function `φ : ℕ → ℕ` with `φ 0 = 0`,
120+
`k < φ (segment φ k + 1)` for all `k : ℕ`. -/
121+
theorem Nat.segment_upper_bound (hm : StrictMono φ) (h0 : φ 0 = 0) (k : ℕ) :
122+
k < φ (segment φ k + 1) := by
123+
rw [nth_of_strict_mono hm (segment φ k + 1), segment_plus_one h0 k]
124+
suffices _ : k + 1 ≤ Nat.nth (· ∈ range φ) (Nat.count (· ∈ range φ) (k + 1)) by omega
125+
apply Nat.le_nth_count
126+
exact strict_mono_infinite hm
127+
128+
open scoped Classical in
129+
/-- For a strictly monotonic function `φ : ℕ → ℕ` with `φ 0 = 0`,
130+
`φ (segment φ k) ≤ k` for all `k : ℕ`. -/
131+
theorem Nat.segment_lower_bound (hm : StrictMono φ) (h0 : φ 0 = 0) (k : ℕ) :
132+
φ (segment φ k) ≤ k := by
133+
rw [nth_of_strict_mono hm (segment φ k), segment]
134+
rcases Classical.em (k ∈ range φ) with h_k | h_k
135+
· have h1 : Nat.count (· ∈ range φ) (k + 1) = Nat.count (· ∈ range φ) k + 1 := by
136+
exact Nat.count_succ_eq_succ_count h_k
137+
rw [h1, Nat.add_one_sub_one, Nat.nth_count h_k]
138+
· have h2 : Nat.count (· ∈ range φ) (k + 1) = Nat.count (· ∈ range φ) k := by
139+
exact Nat.count_succ_eq_count h_k
140+
rw [h2]
141+
suffices _ : Nat.nth (· ∈ range φ) (Nat.count (· ∈ range φ) k - 1) < k by omega
142+
apply Nat.nth_lt_of_lt_count
143+
have : Nat.count (· ∈ range φ) k > 0 := by exact count_notin_range_pos h0 k h_k
144+
omega
145+
146+
open scoped Classical in
147+
/-- For a strictly monotonic function `φ : ℕ → ℕ`, all `k` satisfying `φ m ≤ k < φ (m + 1)`
148+
has `segment φ k = m`. -/
149+
theorem Nat.segment_range_val (hm : StrictMono φ) {m k : ℕ}
150+
(hl : φ m ≤ k) (hu : k < φ (m + 1)) : segment φ k = m := by
151+
obtain (rfl | hu') := show φ m = k ∨ φ m < k by omega
152+
· exact segment_idem hm m
153+
obtain ⟨j, h_j, rfl⟩ : ∃ j < φ (m + 1) - φ m - 1, k = j + φ m + 1 := by use (k - φ m - 1) ; omega
154+
induction j
155+
case zero =>
156+
have h1 : Nat.count (· ∈ range φ) (φ m + 1) = Nat.count (· ∈ range φ) (φ m) + 1 := by
157+
apply Nat.count_succ_eq_succ_count ; use m
158+
have h2 : Nat.count (· ∈ range φ) (φ m + 1 + 1) = Nat.count (· ∈ range φ) (φ m + 1) := by
159+
apply Nat.count_succ_eq_count
160+
apply strict_mono_range_gap hm (show φ m < φ m + 1 by omega) ; omega
161+
have h3 := nth_of_strict_mono hm m
162+
rw [segment, zero_add, h2, h1, Nat.add_one_sub_one, h3]
163+
apply Nat.count_nth_of_infinite (strict_mono_infinite hm)
164+
case succ j h_ind =>
165+
specialize h_ind (by omega) (by omega) (by omega) (by omega)
166+
have h1 : Nat.count (· ∈ range φ) (j + 1 + φ m + 1) = Nat.count (· ∈ range φ) (j + 1 + φ m) := by
167+
apply Nat.count_succ_eq_count
168+
apply strict_mono_range_gap hm (show φ m < j + 1 + φ m by omega) ; omega
169+
have h2 : Nat.count (· ∈ range φ) (j + 1 + φ m + 1 + 1) =
170+
Nat.count (· ∈ range φ) (j + 1 + φ m + 1) := by
171+
apply Nat.count_succ_eq_count
172+
apply strict_mono_range_gap hm (show φ m < j + 1 + φ m + 1 by omega) ; omega
173+
rw [segment, (show j + «φ» m + 1 = j + 1 + φ m by omega), h1] at h_ind
174+
rw [segment, h2, h1, h_ind]
175+
176+
/-- For a strictly monotonic function `φ : ℕ → ℕ` with `φ 0 = 0`,
177+
`φ` and `segment φ` form a Galois connection. -/
178+
theorem Nat.segment_galois_connection (hm : StrictMono φ) (h0 : φ 0 = 0) :
179+
GaloisConnection φ (segment φ) := by
180+
intro m k ; constructor
181+
· intro h
182+
by_contra! h_con
183+
have h1 : segment φ k + 1 ≤ m := by omega
184+
have := (StrictMono.le_iff_le hm).mpr h1
185+
have := segment_upper_bound hm h0 k
186+
omega
187+
· intro h
188+
by_contra! h_con
189+
have := (StrictMono.le_iff_le hm).mpr h
190+
have := segment_lower_bound hm h0 k
191+
omega
192+
193+
/-- Nat.segment' is a helper function that will be proved to be equal to `Nat.segment`.
194+
It facilitates the proofs of some theorems below. -/
195+
noncomputable def Nat.segment' (φ : ℕ → ℕ) (k : ℕ) : ℕ :=
196+
segment (φ · - φ 0) (k - φ 0)
197+
198+
private lemma base_zero_shift (φ : ℕ → ℕ) :
199+
(φ · - φ 0) 0 = 0 := by
200+
simp
201+
202+
private lemma base_zero_strict_mono (hm : StrictMono φ) :
203+
StrictMono (φ · - φ 0) := by
204+
intro m n h_m_n ; simp
205+
have := hm h_m_n
206+
have : φ 0 ≤ φ m := by simp [StrictMono.le_iff_le hm]
207+
have : φ 0 ≤ φ n := by simp [StrictMono.le_iff_le hm]
208+
omega
209+
210+
open scoped Classical in
211+
/-- For a strictly monotonic function `φ : ℕ → ℕ`,
212+
`segment' φ` and `segment φ` are actually equal. -/
213+
theorem Nat.segment'_eq_segment (hm : StrictMono φ) :
214+
segment' φ = segment φ := by
215+
ext k ; unfold segment'
216+
rcases (show k < φ 0 ∨ k ≥ φ 0 by omega) with h_k | h_k
217+
· have h0 : segment (φ · - φ 0) (k - φ 0) = 0 := by
218+
rw [show k - φ 0 = 0 by omega]
219+
exact segment_zero (base_zero_strict_mono hm) (base_zero_shift φ)
220+
rw [h0, segment_pre_zero hm h_k]
221+
unfold segment ; congr 1
222+
simp only [Nat.count_eq_card_filter_range]
223+
suffices h : ∃ f, BijOn f
224+
({x ∈ Finset.range (k - φ 0 + 1) | x ∈ range fun x => φ x - φ 0}).toSet
225+
({x ∈ Finset.range (k + 1) | x ∈ range φ}).toSet by
226+
obtain ⟨f, h_bij⟩ := h
227+
exact BijOn.finsetCard_eq f h_bij
228+
use (fun n ↦ n + φ 0) ; unfold BijOn ; constructorm* _ ∧ _
229+
· intro n ; simp only [mem_range, Finset.coe_filter, Finset.mem_range, mem_setOf_eq]
230+
rintro ⟨h_n, i, rfl⟩
231+
have := StrictMono.monotone hm <| zero_le i
232+
constructor
233+
· omega
234+
· use i ; omega
235+
· apply injOn_of_injective ; intro i j ; grind
236+
· intro n ; simp only [mem_range, Finset.coe_filter, Finset.mem_range, mem_setOf_eq, mem_image]
237+
rintro ⟨h_n, i, rfl⟩
238+
have := StrictMono.monotone hm <| zero_le i
239+
use (φ i - φ 0) ; constructorm* _ ∧ _
240+
· omega
241+
· use i
242+
· omega
243+
244+
/-- For a strictly monotonic function `φ : ℕ → ℕ`, `segment φ k = 0` for all `k ≤ φ 0`. -/
245+
theorem Nat.segment_zero' (hm : StrictMono φ) {k : ℕ} (h : k ≤ φ 0) :
246+
segment φ k = 0 := by
247+
rw [← segment'_eq_segment hm, segment', (show k - φ 0 = 0 by omega)]
248+
exact segment_zero (base_zero_strict_mono hm) (base_zero_shift φ)
249+
250+
/-- For a strictly monotonic function `φ : ℕ → ℕ`, `k < φ (segment φ k + 1)` for all `k ≥ φ 0`. -/
251+
theorem Nat.segment_upper_bound' (hm : StrictMono φ) {k : ℕ} (h : φ 0 ≤ k) :
252+
k < φ (segment φ k + 1) := by
253+
rw [← segment'_eq_segment hm, segment']
254+
have := segment_upper_bound (base_zero_strict_mono hm) (base_zero_shift φ) (k - φ 0)
255+
omega
256+
257+
/-- For a strictly monotonic function `φ : ℕ → ℕ`, `φ (segment φ k) ≤ k` for all `k ≥ φ 0`. -/
258+
theorem Nat.segment_lower_bound' (hm : StrictMono φ) {k : ℕ} (h : φ 0 ≤ k) :
259+
φ (segment φ k) ≤ k := by
260+
rw [← segment'_eq_segment hm, segment']
261+
have := segment_lower_bound (base_zero_strict_mono hm) (base_zero_shift φ) (k - φ 0)
262+
omega
263+
264+
end Cslib

0 commit comments

Comments
 (0)