Skip to content

Commit 7c9da28

Browse files
committed
feat: Array.ofFn and lemmas (#381)
This adds the `Array.ofFn` function which is analogous to `List.ofFn` as well as characterizing lemmas.
1 parent 9d27bb9 commit 7c9da28

File tree

3 files changed

+129
-0
lines changed

3 files changed

+129
-0
lines changed

Mathlib/Data/Array/Basic.lean

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import Mathlib.Data.List.Basic
22
import Mathlib.Tactic.HaveI
3+
import Mathlib.Tactic.Simpa
34

45
macro_rules | `($x[$i]'$h) => `(getElem $x $i $h)
56

@@ -94,4 +95,117 @@ lemma get_set (a : Array α) (i j : Nat) (hi : i < a.size) (hj : j < a.size) (v
9495
(a.set ⟨i, hi⟩ v)[j]'(by simp_all) = if i = j then v else a[j] := by
9596
by_cases i = j <;> simp [*]
9697

98+
@[simp]
99+
theorem size_mkEmpty : (mkEmpty n : Array α).size = 0 := rfl
100+
101+
@[simp]
102+
theorem size_mapIdxM_map (as : Array α) (bs : Array β) (f : Fin as.size → α → Id β) (i j h) (hj : j = bs.size) :
103+
(Array.mapIdxM.map as f i j h bs).size = as.size := by
104+
induction i generalizing j bs
105+
case zero => subst hj; simp [mapIdxM.map, ← h]
106+
case succ i ih =>
107+
simp only [mapIdxM.map, Id.bind_eq]
108+
rw [ih]
109+
simp [hj]
110+
111+
@[simp]
112+
theorem size_mapIdxM_Id (a : Array α) (f : Fin a.size → α → Id β) :
113+
(a.mapIdxM f).size = a.size := by
114+
simp [mapIdxM, size_mapIdxM_map]
115+
116+
@[simp]
117+
theorem size_mapIdx (a : Array α) (f : Fin a.size → α → β) : (a.mapIdx f).size = a.size := by
118+
simp [mapIdx, Id.run]
119+
120+
theorem getElem_mapIdxM_map (as : Array α) (bs : Array β) (f : Fin as.size → α → Id β) (i j h)
121+
(hj : j = bs.size) (k) (hk : k < as.size)
122+
(hbs : ∀ k' (hk' : k' < bs.size),
123+
haveI : k' < as.size := by rw [← h, hj, Nat.add_comm]; exact Nat.lt_add_right _ _ _ hk'
124+
bs[k'] = f ⟨k', this⟩ as[k']) :
125+
(Id.run (Array.mapIdxM.map as f i j h bs))[k]'(by simp_all [Id.run]) = f ⟨k, hk⟩ as[k] := by
126+
induction i generalizing j bs
127+
case zero => erw [hbs]
128+
case succ i ih =>
129+
simp only [mapIdxM.map, Id.bind_eq]
130+
rw [ih]
131+
· simp [hj]
132+
· intro k' hk'
133+
rw [get_push]
134+
cases (lt_or_eq_of_le <| Nat.le_of_lt_succ (by simpa using hk'))
135+
case inl hk' => simp [hk', hbs]
136+
case inr hk' => simp_all
137+
138+
@[simp]
139+
theorem getElem_mapIdx (a : Array α) (f : Fin a.size → α → β) (i : Nat) (h) :
140+
haveI : i < a.size := by simp_all
141+
(a.mapIdx f)[i]'(h) = f ⟨i, this⟩ a[i] := by
142+
simp only [mapIdx, mapIdxM]
143+
rw [getElem_mapIdxM_map]
144+
· simp
145+
· intro k hk; simp at hk; contradiction
146+
147+
@[simp]
148+
theorem size_swap! (a : Array α) (i j) (hi : i < a.size) (hj : j < a.size) : (a.swap! i j).size = a.size := by
149+
simp [swap!, hi, hj]
150+
151+
theorem size_reverse_rev (mid i) (a : Array α) (h : mid ≤ a.size) : (Array.reverse.rev a.size mid a i).size = a.size :=
152+
if hi : i < mid then by
153+
unfold Array.reverse.rev
154+
have : i < a.size := lt_of_lt_of_le hi h
155+
have : a.size - i - 1 < a.size := Nat.sub_lt_self i.zero_lt_succ this
156+
have := Array.size_reverse_rev mid (i+1) (a.swap! i (a.size - i - 1))
157+
simp_all
158+
else by
159+
unfold Array.reverse.rev
160+
simp [dif_neg hi]
161+
termination_by _ => mid - i
162+
163+
@[simp]
164+
theorem size_reverse (a : Array α) : a.reverse.size = a.size := by
165+
have := size_reverse_rev (a.size / 2) 0 a (Nat.div_le_self ..)
166+
simp only [reverse, this]
167+
168+
@[simp]
169+
theorem size_ofFn_loop (n) (f : Fin n → α) (i acc) : (ofFn.loop n f i acc).size = acc.size + (n - i) :=
170+
if hin : i < n then by
171+
unfold ofFn.loop
172+
have : 1 + (n - (i + 1)) = n - i :=
173+
Nat.sub_sub .. ▸ Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. ▸ hin))
174+
rw [dif_pos hin, size_ofFn_loop n f (i+1), size_push, Nat.add_assoc, this]
175+
else by
176+
have : n - i = 0 := Nat.sub_eq_zero_of_le (le_of_not_lt hin)
177+
unfold ofFn.loop
178+
simp [hin, this]
179+
termination_by size_ofFn_loop n f i acc => n - i
180+
181+
@[simp]
182+
theorem size_ofFn (f : Fin n → α) : (ofFn n f).size = n := by
183+
simp [ofFn]
184+
185+
@[simp]
186+
theorem getElem_ofFn_loop (n) (f : Fin n → α) (i acc) (k : Nat) (hki : k < n) (hin : i ≤ n) (hi : i = acc.size)
187+
(hacc : ∀ j, ∀ hj : j < acc.size, acc[j] = f ⟨j, lt_of_lt_of_le hj (by simp_all)⟩) :
188+
haveI : acc.size + (n - acc.size) = n := Nat.add_sub_cancel' (hi ▸ hin)
189+
(ofFn.loop n f i acc)[k]'(by simp_all) = f ⟨k, hki⟩ :=
190+
if hin : i < n then by
191+
unfold ofFn.loop
192+
have : 1 + (n - (i + 1)) = n - i :=
193+
Nat.sub_sub .. ▸ Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. ▸ hin))
194+
simp only [dif_pos hin]
195+
rw [getElem_ofFn_loop n f (i+1) _ k _ hin (by simp_all) (fun j hj => ?hacc)]
196+
cases (lt_or_eq_of_le <| Nat.le_of_lt_succ (by simpa using hj))
197+
case inl hj => simp [get_push, hj, hacc j hj]
198+
case inr hj => simp_all [get_push]
199+
else by
200+
unfold ofFn.loop
201+
simp [hin, hacc k (lt_of_lt_of_le hki (le_of_not_gt (hi ▸ hin)))]
202+
termination_by
203+
getElem_ofFn_loop n f i acc k hki hin hi hacc => n - i
204+
205+
@[simp]
206+
theorem getElem_ofFn (f : Fin n → α) (i : Nat) (h) : (ofFn n f)[i] = f ⟨i, by simp_all⟩ := by
207+
unfold ofFn
208+
rw [getElem_ofFn_loop] <;> try {simp}
209+
· intro j hj; simp at hj; contradiction
210+
97211
end Array

Mathlib/Data/Array/Defs.lean

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ proofs about these definitions, those are contained in other files in `Mathlib.D
1313

1414
namespace Array
1515

16+
/-- The array `#[f 0, ..., f n]` -/
17+
def ofFn (n : Nat) (f : Fin n → α) : Array α :=
18+
loop 0 (mkEmpty n)
19+
where
20+
/-- Implementation detail of `Array.ofFn`. -/
21+
loop (i : Nat) (acc : Array α) : Array α :=
22+
if h : i < n then
23+
let acc := acc.push (f ⟨i, h⟩)
24+
loop (i + 1) acc
25+
else
26+
acc
27+
termination_by
28+
loop i acc => n - i
29+
1630
/-- The array `#[0, 1, ..., n - 1]`. -/
1731
def range (n : Nat) : Array Nat :=
1832
n.fold (flip Array.push) #[]

Mathlib/Init/Data/Nat/Lemmas.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ protected def strong_rec_on {p : ℕ → Sort u}
190190
(n : ℕ) (H : ∀ n, (∀ m, m < n → p m) → p n) : p n :=
191191
Nat.lt_wfRel.wf.fix' H n
192192

193+
@[elabAsElim]
193194
protected lemma strong_induction_on {p : Nat → Prop} (n : Nat) (h : ∀ n, (∀ m, m < n → p m) → p n) : p n :=
194195
Nat.strong_rec_on n h
195196

0 commit comments

Comments
 (0)