Skip to content

Commit

Permalink
chore: cleanup of Array lemmas (#6337)
Browse files Browse the repository at this point in the history
This PRs continues cleaning up Array lemmas and improving alignment with
List.
  • Loading branch information
kim-em authored Dec 8, 2024
1 parent 4dd182c commit 6abb8aa
Show file tree
Hide file tree
Showing 11 changed files with 143 additions and 245 deletions.
2 changes: 2 additions & 0 deletions src/Init/Data/Array/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ theorem ext' {as bs : Array α} (h : as.toList = bs.toList) : as = bs := by

@[simp] theorem getElem_toList {a : Array α} {i : Nat} (h : i < a.size) : a.toList[i] = a[i] := rfl

@[simp] theorem getElem?_toList {a : Array α} {i : Nat} : a.toList[i]? = a[i]? := rfl

/-- `a ∈ as` is a predicate which asserts that `a` is in the array `as`. -/
-- NB: This is defined as a structure rather than a plain def so that a lemma
-- like `sizeOf_lt_of_mem` will not apply with no actual arrays around.
Expand Down
263 changes: 79 additions & 184 deletions src/Init/Data/Array/Lemmas.lean

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/Init/Data/Array/TakeDrop.lean
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Array
theorem exists_of_uset (self : Array α) (i d h) :
∃ l₁ l₂, self.toList = l₁ ++ self[i] :: l₂ ∧ List.length l₁ = i.toNat ∧
(self.uset i d h).toList = l₁ ++ d :: l₂ := by
simpa only [ugetElem_eq_getElem, getElem_eq_getElem_toList, uset, toList_set] using
simpa only [ugetElem_eq_getElem, ← getElem_toList, uset, toList_set] using
List.exists_of_set _

end Array
45 changes: 24 additions & 21 deletions src/Init/Data/List/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -220,15 +220,6 @@ We simplify `l[n]!` to `(l[n]?).getD default`.

/-! ### getElem? and getElem -/

@[simp] theorem getElem?_eq_getElem {l : List α} {n} (h : n < l.length) : l[n]? = some l[n] := by
simp only [getElem?_def, h, ↓reduceDIte]

theorem getElem?_eq_some_iff {l : List α} : l[n]? = some a ↔ ∃ h : n < l.length, l[n] = a := by
simp only [← get?_eq_getElem?, get?_eq_some_iff, get_eq_getElem]

theorem some_eq_getElem?_iff {l : List α} : some a = l[n]? ↔ ∃ h : n < l.length, l[n] = a := by
rw [eq_comm, getElem?_eq_some_iff]

@[simp] theorem getElem?_eq_none_iff : l[n]? = none ↔ length l ≤ n := by
simp only [← get?_eq_getElem?, get?_eq_none_iff]

Expand All @@ -237,11 +228,20 @@ theorem some_eq_getElem?_iff {l : List α} : some a = l[n]? ↔ ∃ h : n < l.le

theorem getElem?_eq_none (h : length l ≤ n) : l[n]? = none := getElem?_eq_none_iff.mpr h

@[simp] theorem some_getElem_eq_getElem?_iff {α} (xs : List α) (i : Nat) (h : i < xs.length) :
@[simp] theorem getElem?_eq_getElem {l : List α} {n} (h : n < l.length) : l[n]? = some l[n] :=
getElem?_pos ..

theorem getElem?_eq_some_iff {l : List α} : l[n]? = some a ↔ ∃ h : n < l.length, l[n] = a := by
simp only [← get?_eq_getElem?, get?_eq_some_iff, get_eq_getElem]

theorem some_eq_getElem?_iff {l : List α} : some a = l[n]? ↔ ∃ h : n < l.length, l[n] = a := by
rw [eq_comm, getElem?_eq_some_iff]

@[simp] theorem some_getElem_eq_getElem?_iff (xs : List α) (i : Nat) (h : i < xs.length) :
(some xs[i] = xs[i]?) ↔ True := by
simp [h]

@[simp] theorem getElem?_eq_some_getElem_iff {α} (xs : List α) (i : Nat) (h : i < xs.length) :
@[simp] theorem getElem?_eq_some_getElem_iff (xs : List α) (i : Nat) (h : i < xs.length) :
(xs[i]? = some xs[i]) ↔ True := by
simp [h]

Expand All @@ -253,6 +253,12 @@ theorem getElem_eq_getElem?_get (l : List α) (i : Nat) (h : i < l.length) :
l[i] = l[i]?.get (by simp [getElem?_eq_getElem, h]) := by
simp [getElem_eq_iff]

theorem isSome_getElem? {l : List α} {n : Nat} : l[n]?.isSome ↔ n < l.length := by
simp

theorem isNone_getElem? {l : List α} {n : Nat} : l[n]?.isNone ↔ l.length ≤ n := by
simp

@[simp] theorem getElem?_nil {n : Nat} : ([] : List α)[n]? = none := rfl

theorem getElem?_cons_zero {l : List α} : (a::l)[0]? = some a := by simp
Expand All @@ -264,6 +270,13 @@ theorem getElem?_cons_zero {l : List α} : (a::l)[0]? = some a := by simp
theorem getElem?_cons : (a :: l)[i]? = if i = 0 then some a else l[i-1]? := by
cases i <;> simp

@[simp] theorem getElem_singleton (a : α) (h : i < 1) : [a][i] = a :=
match i, h with
| 0, _ => rfl

theorem getElem?_singleton (a : α) (i : Nat) : [a][i]? = if i = 0 then some a else none := by
simp [getElem?_cons]

/--
If one has `l[i]` in an expression and `h : l = l'`,
`rw [h]` will give a "motive it not type correct" error, as it cannot rewrite the
Expand All @@ -273,10 +286,6 @@ such a rewrite, with `rw [getElem_of_eq h]`.
theorem getElem_of_eq {l l' : List α} (h : l = l') {i : Nat} (w : i < l.length) :
l[i] = l'[i]'(h ▸ w) := by cases h; rfl

@[simp] theorem getElem_singleton (a : α) (h : i < 1) : [a][i] = a :=
match i, h with
| 0, _ => rfl

theorem getElem_zero {l : List α} (h : 0 < l.length) : l[0] = l.head (length_pos.mp h) :=
match l, h with
| _ :: _, _ => rfl
Expand All @@ -300,12 +309,6 @@ theorem ext_getElem {l₁ l₂ : List α} (hl : length l₁ = length l₂)
theorem getElem?_concat_length (l : List α) (a : α) : (l ++ [a])[l.length]? = some a := by
simp

theorem isSome_getElem? {l : List α} {n : Nat} : l[n]?.isSome ↔ n < l.length := by
simp

theorem isNone_getElem? {l : List α} {n : Nat} : l[n]?.isNone ↔ l.length ≤ n := by
simp

/-! ### mem -/

@[simp] theorem not_mem_nil (a : α) : ¬ a ∈ [] := nofun
Expand Down
6 changes: 3 additions & 3 deletions src/Init/Data/List/MapIdx.lean
Original file line number Diff line number Diff line change
Expand Up @@ -237,15 +237,15 @@ theorem getElem?_mapIdx_go : ∀ {l : List α} {arr : Array β} {i : Nat},
if h : i < arr.size then some arr[i] else Option.map (f i) l[i - arr.size]?
| [], arr, i => by
simp only [mapIdx.go, Array.toListImpl_eq, getElem?_def, Array.length_toList,
Array.getElem_eq_getElem_toList, length_nil, Nat.not_lt_zero, ↓reduceDIte, Option.map_none']
Array.getElem_toList, length_nil, Nat.not_lt_zero, ↓reduceDIte, Option.map_none']
| a :: l, arr, i => by
rw [mapIdx.go, getElem?_mapIdx_go]
simp only [Array.size_push]
split <;> split
· simp only [Option.some.injEq]
rw [Array.getElem_eq_getElem_toList]
rw [Array.getElem_toList]
simp only [Array.push_toList]
rw [getElem_append_left, Array.getElem_eq_getElem_toList]
rw [getElem_append_left, Array.getElem_toList]
· have : i = arr.size := by omega
simp_all
· omega
Expand Down
18 changes: 9 additions & 9 deletions src/Init/GetElem.lean
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,16 @@ instance (priority := low) [GetElem coll idx elem valid] [∀ xs i, Decidable (v
GetElem? coll idx elem valid where
getElem? xs i := decidableGetElem? xs i

theorem getElem_congr_coll [GetElem coll idx elem valid] {c d : coll} {i : idx} {h : valid c i}
(h' : c = d) : c[i] = d[i]'(h' ▸ h) := by
cases h'; rfl
theorem getElem_congr [GetElem coll idx elem valid] {c d : coll} (h : c = d)
{i j : idx} (h' : i = j) (w : valid c i) : c[i] = d[j]'(h' ▸ h ▸ w) := by
cases h; cases h'; rfl

theorem getElem_congr_coll [GetElem coll idx elem valid] {c d : coll} {i : idx} {w : valid c i}
(h : c = d) : c[i] = d[i]'(h ▸ w) := by
cases h; rfl

theorem getElem_congr [GetElem coll idx elem valid] {c : coll} {i j : idx} {h : valid c i}
(h' : i = j) : c[i] = c[j]'(h' ▸ h) := by
theorem getElem_congr_idx [GetElem coll idx elem valid] {c : coll} {i j : idx} {w : valid c i}
(h' : i = j) : c[i] = c[j]'(h' ▸ w) := by
cases h'; rfl

class LawfulGetElem (cont : Type u) (idx : Type v) (elem : outParam (Type w))
Expand Down Expand Up @@ -216,13 +220,9 @@ instance : GetElem (List α) Nat α fun as i => i < as.length where
@[simp] theorem getElem_cons_zero (a : α) (as : List α) (h : 0 < (a :: as).length) : getElem (a :: as) 0 h = a := by
rfl

@[deprecated getElem_cons_zero (since := "2024-06-12")] abbrev cons_getElem_zero := @getElem_cons_zero

@[simp] theorem getElem_cons_succ (a : α) (as : List α) (i : Nat) (h : i + 1 < (a :: as).length) : getElem (a :: as) (i+1) h = getElem as i (Nat.lt_of_succ_lt_succ h) := by
rfl

@[deprecated getElem_cons_succ (since := "2024-06-12")] abbrev cons_getElem_succ := @getElem_cons_succ

@[simp] theorem getElem_mem : ∀ {l : List α} {n} (h : n < l.length), l[n]'h ∈ l
| _ :: _, 0, _ => .head ..
| _ :: l, _+1, _ => .tail _ (getElem_mem (l := l) ..)
Expand Down
2 changes: 1 addition & 1 deletion src/Std/Data/DHashMap/Internal/WF.lean
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ theorem expand.go_eq [BEq α] [Hashable α] [PartialEquivBEq α] (source : Array
refine ih.trans ?_
simp only [Array.get_eq_getElem, AssocList.foldl_eq, Array.toList_set]
rw [List.drop_eq_getElem_cons hi, List.flatMap_cons, List.foldl_append,
List.drop_set_of_lt _ _ (by omega), Array.getElem_eq_getElem_toList]
List.drop_set_of_lt _ _ (by omega), Array.getElem_toList]
· next i source target hi =>
rw [expand.go_neg hi, List.drop_eq_nil_of_le, flatMap_nil, foldl_nil]
rwa [Array.size_eq_length_toList, Nat.not_lt] at hi
Expand Down
2 changes: 1 addition & 1 deletion src/Std/Tactic/BVDecide/LRAT/Internal/Clause.lean
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ theorem ofArray_eq (arr : Array (Literal (PosFin n)))
dsimp; omega
rw [List.getElem?_eq_getElem i_in_bounds, List.getElem?_eq_getElem i_in_bounds']
simp only [List.get_eq_getElem, Nat.zero_add] at h
rw [Array.getElem_eq_getElem_toList]
rw [Array.getElem_toList]
simp [h]
· have arr_data_length_le_i : arr.toList.length ≤ i := by
dsimp; omega
Expand Down
6 changes: 3 additions & 3 deletions src/Std/Tactic/BVDecide/LRAT/Internal/Formula/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ theorem deleteOne_preserves_strongAssignmentsInvariant {n : Nat} (f : DefaultFor
conv => rhs; rw [Array.size_mk]
exact hbound
simp only [getElem!, id_eq_idx, Array.length_toList, idx_in_bounds2, ↓reduceDIte,
Fin.eta, Array.get_eq_getElem, Array.getElem_eq_getElem_toList, decidableGetElem?] at heq
Fin.eta, Array.get_eq_getElem, Array.getElem_toList, decidableGetElem?] at heq
rw [hidx, hl] at heq
simp only [unit, Option.some.injEq, DefaultClause.mk.injEq, List.cons.injEq, and_true] at heq
simp only [← heq] at l_ne_b
Expand Down Expand Up @@ -530,7 +530,7 @@ theorem deleteOne_preserves_strongAssignmentsInvariant {n : Nat} (f : DefaultFor
conv => rhs; rw [Array.size_mk]
exact hbound
simp only [getElem!, id_eq_idx, Array.length_toList, idx_in_bounds2, ↓reduceDIte,
Fin.eta, Array.get_eq_getElem, Array.getElem_eq_getElem_toList, decidableGetElem?] at heq
Fin.eta, Array.get_eq_getElem, Array.getElem_toList, decidableGetElem?] at heq
rw [hidx, hl] at heq
simp only [unit, Option.some.injEq, DefaultClause.mk.injEq, List.cons.injEq, and_true] at heq
have i_eq_l : i = l.1 := by rw [← heq]
Expand Down Expand Up @@ -590,7 +590,7 @@ theorem deleteOne_preserves_strongAssignmentsInvariant {n : Nat} (f : DefaultFor
conv => rhs; rw [Array.size_mk]
exact hbound
simp only [getElem!, id_eq_idx, Array.length_toList, idx_in_bounds2, ↓reduceDIte,
Fin.eta, Array.get_eq_getElem, Array.getElem_eq_getElem_toList, decidableGetElem?] at heq
Fin.eta, Array.get_eq_getElem, Array.getElem_toList, decidableGetElem?] at heq
rw [hidx] at heq
simp only [Option.some.injEq] at heq
rw [← heq] at hl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ theorem existsRatHint_of_ratHintsExhaustive {n : Nat} (f : DefaultFormula n)
constructor
· rw [← Array.mem_toList]
apply Array.getElem_mem_toList
· rw [Array.getElem_eq_getElem_toList] at c'_in_f
· rw [Array.getElem_toList] at c'_in_f
simp only [getElem!, Array.getElem_range, i_lt_f_clauses_size, dite_true,
c'_in_f, DefaultClause.contains_iff, Array.get_eq_getElem, decidableGetElem?]
simpa [Clause.toList] using negPivot_in_c'
Expand All @@ -472,8 +472,8 @@ theorem existsRatHint_of_ratHintsExhaustive {n : Nat} (f : DefaultFormula n)
dsimp at *
omega
simp only [List.get_eq_getElem, Array.toList_map, Array.length_toList, List.getElem_map] at h'
rw [Array.getElem_eq_getElem_toList] at h'
rw [Array.getElem_eq_getElem_toList] at c'_in_f
rw [Array.getElem_toList] at h'
rw [Array.getElem_toList] at c'_in_f
exists ⟨j.1, j_in_bounds⟩
simp [getElem!, h', i_lt_f_clauses_size, dite_true, c'_in_f, decidableGetElem?]

Expand Down
36 changes: 17 additions & 19 deletions src/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean
Original file line number Diff line number Diff line change
Expand Up @@ -1133,25 +1133,24 @@ theorem nodup_derivedLits {n : Nat} (f : DefaultFormula n)
specialize h3 ⟨j.1, j_in_bounds⟩ j_ne_k
simp only [derivedLits_arr_def, Fin.getElem_fin] at li_eq_lj
simp only [Fin.getElem_fin, derivedLits_arr_def, ne_eq, li, li_eq_lj] at h3
simp only [List.get_eq_getElem, Array.getElem_eq_getElem_toList, not_true_eq_false] at h3
simp only [List.get_eq_getElem, Array.getElem_toList, not_true_eq_false] at h3
· next k_ne_i =>
have i_ne_k : ⟨i.1, i_in_bounds⟩ ≠ k := by intro i_eq_k; simp only [← i_eq_k, not_true] at k_ne_i
specialize h3 ⟨i.1, i_in_bounds⟩ i_ne_k
simp +decide [Fin.getElem_fin, derivedLits_arr_def, ne_eq,
Array.getElem_eq_getElem_toList, li] at h3
simp +decide [Fin.getElem_fin, derivedLits_arr_def, ne_eq, li] at h3
· by_cases li.2 = true
· next li_eq_true =>
have i_ne_k2 : ⟨i.1, i_in_bounds⟩ ≠ k2 := by
intro i_eq_k2
rw [← i_eq_k2] at k2_eq_false
simp only [List.get_eq_getElem] at k2_eq_false
simp [derivedLits_arr_def, Array.getElem_eq_getElem_toList, k2_eq_false, li] at li_eq_true
simp [derivedLits_arr_def, k2_eq_false, li] at li_eq_true
have j_ne_k2 : ⟨j.1, j_in_bounds⟩ ≠ k2 := by
intro j_eq_k2
rw [← j_eq_k2] at k2_eq_false
simp only [List.get_eq_getElem] at k2_eq_false
simp only [derivedLits_arr_def, Fin.getElem_fin, Array.getElem_eq_getElem_toList] at li_eq_lj
simp [derivedLits_arr_def, Array.getElem_eq_getElem_toList, k2_eq_false, li_eq_lj, li] at li_eq_true
simp only [derivedLits_arr_def, Fin.getElem_fin] at li_eq_lj
simp [derivedLits_arr_def, k2_eq_false, li_eq_lj, li] at li_eq_true
by_cases ⟨i.1, i_in_bounds⟩ = k1
· next i_eq_k1 =>
have j_ne_k1 : ⟨j.1, j_in_bounds⟩ ≠ k1 := by
Expand All @@ -1160,26 +1159,25 @@ theorem nodup_derivedLits {n : Nat} (f : DefaultFormula n)
simp only [Fin.mk.injEq] at i_eq_k1
exact i_ne_j (Fin.eq_of_val_eq i_eq_k1)
specialize h3 ⟨j.1, j_in_bounds⟩ j_ne_k1 j_ne_k2
simp [li, li_eq_lj, derivedLits_arr_def, Array.getElem_eq_getElem_toList] at h3
simp [li, li_eq_lj, derivedLits_arr_def] at h3
· next i_ne_k1 =>
specialize h3 ⟨i.1, i_in_bounds⟩ i_ne_k1 i_ne_k2
apply h3
simp +decide only [Fin.getElem_fin, Array.getElem_eq_getElem_toList,
ne_eq, derivedLits_arr_def, li]
simp +decide only [Fin.getElem_fin, ne_eq, derivedLits_arr_def, li]
rfl
· next li_eq_false =>
simp only [Bool.not_eq_true] at li_eq_false
have i_ne_k1 : ⟨i.1, i_in_bounds⟩ ≠ k1 := by
intro i_eq_k1
rw [← i_eq_k1] at k1_eq_true
simp only [List.get_eq_getElem] at k1_eq_true
simp [derivedLits_arr_def, Array.getElem_eq_getElem_toList, k1_eq_true, li] at li_eq_false
simp [derivedLits_arr_def, k1_eq_true, li] at li_eq_false
have j_ne_k1 : ⟨j.1, j_in_bounds⟩ ≠ k1 := by
intro j_eq_k1
rw [← j_eq_k1] at k1_eq_true
simp only [List.get_eq_getElem] at k1_eq_true
simp only [derivedLits_arr_def, Fin.getElem_fin, Array.getElem_eq_getElem_toList] at li_eq_lj
simp [derivedLits_arr_def, Array.getElem_eq_getElem_toList, k1_eq_true, li_eq_lj, li] at li_eq_false
simp only [derivedLits_arr_def, Fin.getElem_fin] at li_eq_lj
simp [derivedLits_arr_def, k1_eq_true, li_eq_lj, li] at li_eq_false
by_cases ⟨i.1, i_in_bounds⟩ = k2
· next i_eq_k2 =>
have j_ne_k2 : ⟨j.1, j_in_bounds⟩ ≠ k2 := by
Expand All @@ -1188,10 +1186,10 @@ theorem nodup_derivedLits {n : Nat} (f : DefaultFormula n)
simp only [Fin.mk.injEq] at i_eq_k2
exact i_ne_j (Fin.eq_of_val_eq i_eq_k2)
specialize h3 ⟨j.1, j_in_bounds⟩ j_ne_k1 j_ne_k2
simp [li, li_eq_lj, derivedLits_arr_def, Array.getElem_eq_getElem_toList] at h3
simp [li, li_eq_lj, derivedLits_arr_def] at h3
· next i_ne_k2 =>
specialize h3 ⟨i.1, i_in_bounds⟩ i_ne_k1 i_ne_k2
simp +decide [Array.getElem_eq_getElem_toList, derivedLits_arr_def, li] at h3
simp +decide [derivedLits_arr_def, li] at h3

theorem restoreAssignments_performRupCheck_base_case {n : Nat} (f : DefaultFormula n)
(f_assignments_size : f.assignments.size = n)
Expand Down Expand Up @@ -1225,7 +1223,7 @@ theorem restoreAssignments_performRupCheck_base_case {n : Nat} (f : DefaultFormu
constructor
· apply Nat.zero_le
· constructor
· simp only [derivedLits_arr_def, Fin.getElem_fin, Array.getElem_eq_getElem_toList, ← j_eq_i]
· simp only [derivedLits_arr_def, Fin.getElem_fin, ← j_eq_i]
rfl
· apply And.intro h1 ∘ And.intro h2
intro k _ k_ne_j
Expand All @@ -1237,7 +1235,7 @@ theorem restoreAssignments_performRupCheck_base_case {n : Nat} (f : DefaultFormu
apply Fin.ne_of_val_ne
simp only
exact Fin.val_ne_of_ne k_ne_j
simp only [Fin.getElem_fin, Array.getElem_eq_getElem_toList, ne_eq, derivedLits_arr_def]
simp only [Fin.getElem_fin, ne_eq, derivedLits_arr_def]
exact h3 ⟨k.1, k_in_bounds⟩ k_ne_j
· apply Or.inr ∘ Or.inr
have j1_lt_derivedLits_arr_size : j1.1 < derivedLits_arr.size := by
Expand All @@ -1251,11 +1249,11 @@ theorem restoreAssignments_performRupCheck_base_case {n : Nat} (f : DefaultFormu
⟨j2.1, j2_lt_derivedLits_arr_size⟩,
i_gt_zero, Nat.zero_le j1.1, Nat.zero_le j2.1, ?_⟩
constructor
· simp only [derivedLits_arr_def, Fin.getElem_fin, Array.getElem_eq_getElem_toList, ← j1_eq_i]
· simp only [derivedLits_arr_def, Fin.getElem_fin, ← j1_eq_i]
rw [← j1_eq_true]
rfl
· constructor
· simp only [derivedLits_arr_def, Fin.getElem_fin, Array.getElem_eq_getElem_toList, ← j2_eq_i]
· simp only [derivedLits_arr_def, Fin.getElem_fin, ← j2_eq_i]
rw [← j2_eq_false]
rfl
· apply And.intro h1 ∘ And.intro h2
Expand All @@ -1272,7 +1270,7 @@ theorem restoreAssignments_performRupCheck_base_case {n : Nat} (f : DefaultFormu
apply Fin.ne_of_val_ne
simp only
exact Fin.val_ne_of_ne k_ne_j2
simp only [Fin.getElem_fin, Array.getElem_eq_getElem_toList, ne_eq, derivedLits_arr_def]
simp only [Fin.getElem_fin, ne_eq, derivedLits_arr_def]
exact h3 ⟨k.1, k_in_bounds⟩ k_ne_j1 k_ne_j2

theorem restoreAssignments_performRupCheck {n : Nat} (f : DefaultFormula n) (f_assignments_size : f.assignments.size = n)
Expand Down

0 comments on commit 6abb8aa

Please sign in to comment.