feat: theorems about List.toArray (#5403)
This commit is contained in:
parent
f4afbc2f8b
commit
e551a366a0
12 changed files with 108 additions and 60 deletions
|
|
@ -1382,6 +1382,11 @@ gen_injective_theorems% EStateM.Result
|
|||
gen_injective_theorems% Lean.Name
|
||||
gen_injective_theorems% Lean.Syntax
|
||||
|
||||
/-- Replacement for `Array.mk.injEq`; we avoid mentioning the constructor and prefer `List.toArray`. -/
|
||||
abbrev List.toArray_inj := @Array.mk.injEq
|
||||
|
||||
attribute [deprecated List.toArray_inj (since := "2024-09-09")] Array.mk.injEq
|
||||
|
||||
theorem Nat.succ.inj {m n : Nat} : m.succ = n.succ → m = n :=
|
||||
fun x => Nat.noConfusion x id
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import Init.Data.Nat.Linear
|
|||
import Init.NotationExtra
|
||||
|
||||
theorem Array.of_push_eq_push {as bs : Array α} (h : as.push a = bs.push b) : as = bs ∧ a = b := by
|
||||
simp only [push, mk.injEq] at h
|
||||
simp only [push, List.toArray_inj] at h
|
||||
have ⟨h₁, h₂⟩ := List.of_concat_eq_concat h
|
||||
cases as; cases bs
|
||||
simp_all
|
||||
|
|
|
|||
|
|
@ -19,24 +19,14 @@ This file contains some theorems about `Array` and `List` needed for `Init.Data.
|
|||
|
||||
namespace Array
|
||||
|
||||
attribute [simp] uset
|
||||
/-- We avoid mentioning the constructor `Array.mk` directly, preferring `List.toArray`. -/
|
||||
@[simp] theorem mk_eq_toArray (as : List α) : Array.mk as = as.toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem singleton_def (v : α) : singleton v = #[v] := rfl
|
||||
@[simp] theorem getElem_toList {a : Array α} {i : Nat} (h : i < a.size) : a.toList[i] = a[i] := rfl
|
||||
|
||||
@[simp] theorem toArray_toList : (a : Array α) → a.toList.toArray = a
|
||||
| ⟨l⟩ => ext' (toList_toArray l)
|
||||
|
||||
@[deprecated toArray_toList (since := "2024-09-09")]
|
||||
abbrev toArray_data := @toArray_toList
|
||||
|
||||
@[simp] theorem toList_length {l : Array α} : l.toList.length = l.size := rfl
|
||||
|
||||
@[deprecated toList_length (since := "2024-09-09")]
|
||||
abbrev data_length := @toList_length
|
||||
|
||||
@[simp] theorem mkEmpty_eq (α n) : @mkEmpty α n = #[] := rfl
|
||||
|
||||
@[simp] theorem size_mk (as : List α) : (Array.mk as).size = as.length := by simp [size]
|
||||
@[simp] theorem getElem_mk {xs : List α} {i : Nat} (h : i < xs.length) : (Array.mk xs)[i] = xs[i] := rfl
|
||||
|
||||
theorem getElem_eq_toList_getElem (a : Array α) (h : i < a.size) : a[i] = a.toList[i] := by
|
||||
by_cases i < a.size <;> (try simp [*]) <;> rfl
|
||||
|
|
@ -46,27 +36,7 @@ abbrev getElem_eq_data_getElem := @getElem_eq_toList_getElem
|
|||
|
||||
@[deprecated getElem_eq_toList_getElem (since := "2024-06-12")]
|
||||
theorem getElem_eq_toList_get (a : Array α) (h : i < a.size) : a[i] = a.toList.get ⟨i, h⟩ := by
|
||||
simp [getElem_eq_toList_getElem]
|
||||
|
||||
theorem foldrM_push [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) :
|
||||
(arr.push a).foldrM f init = f a init >>= arr.foldrM f := by
|
||||
simp [foldrM_eq_reverse_foldlM_toList, -size_push]
|
||||
|
||||
@[simp] theorem foldrM_push' [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) :
|
||||
(arr.push a).foldrM f init (start := arr.size + 1) = f a init >>= arr.foldrM f := by
|
||||
simp [← foldrM_push]
|
||||
|
||||
theorem foldr_push (f : α → β → β) (init : β) (arr : Array α) (a : α) :
|
||||
(arr.push a).foldr f init = arr.foldr f (f a init) := foldrM_push ..
|
||||
|
||||
@[simp] theorem foldr_push' (f : α → β → β) (init : β) (arr : Array α) (a : α) :
|
||||
(arr.push a).foldr f init (start := arr.size + 1) = arr.foldr f (f a init) := foldrM_push' ..
|
||||
|
||||
/-- A more efficient version of `arr.toList.reverse`. -/
|
||||
@[inline] def toListRev (arr : Array α) : List α := arr.foldl (fun l t => t :: l) []
|
||||
|
||||
@[simp] theorem toListRev_eq (arr : Array α) : arr.toListRev = arr.toList.reverse := by
|
||||
rw [toListRev, foldl_eq_foldl_toList, ← List.foldr_reverse, List.foldr_cons_nil]
|
||||
simp
|
||||
|
||||
theorem get_push_lt (a : Array α) (x : α) (i : Nat) (h : i < a.size) :
|
||||
have : i < (a.push x).size := by simp [*, Nat.lt_succ_of_le, Nat.le_of_lt]
|
||||
|
|
@ -84,6 +54,78 @@ theorem get_push (a : Array α) (x : α) (i : Nat) (h : i < (a.push x).size) :
|
|||
· simp at h
|
||||
simp [get_push_lt, Nat.le_antisymm (Nat.le_of_lt_succ h) (Nat.ge_of_not_lt h')]
|
||||
|
||||
end Array
|
||||
|
||||
namespace List
|
||||
|
||||
open Array
|
||||
|
||||
/-! ### Lemmas about `List.toArray`. -/
|
||||
|
||||
@[simp] theorem toArray_size (as : List α) : as.toArray.size = as.length := by simp [size]
|
||||
|
||||
@[simp] theorem toArrayAux_size {a : List α} {b : Array α} :
|
||||
(a.toArrayAux b).size = b.size + a.length := by
|
||||
simp [size]
|
||||
|
||||
@[simp] theorem toArray_toList : (a : Array α) → a.toList.toArray = a
|
||||
| ⟨l⟩ => ext' (toList_toArray l)
|
||||
|
||||
@[simp] theorem getElem_toArray {a : List α} {i : Nat} (h : i < a.toArray.size) :
|
||||
a.toArray[i] = a[i]'(by simpa using h) := by
|
||||
have h₁ := mk_eq_toArray a
|
||||
have h₂ := getElem_mk (by simpa using h)
|
||||
simpa [h₁] using h₂
|
||||
|
||||
@[simp] theorem toArray_concat {as : List α} {x : α} :
|
||||
(as ++ [x]).toArray = as.toArray.push x := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
end List
|
||||
|
||||
namespace Array
|
||||
|
||||
attribute [simp] uset
|
||||
|
||||
@[simp] theorem singleton_def (v : α) : singleton v = #[v] := rfl
|
||||
|
||||
@[deprecated List.toArray_toList (since := "2024-09-09")]
|
||||
abbrev toArray_data := @List.toArray_toList
|
||||
@[deprecated List.toArray_toList (since := "2024-09-09")]
|
||||
abbrev toArray_toList := @List.toArray_toList
|
||||
|
||||
@[simp] theorem toList_length {l : Array α} : l.toList.length = l.size := rfl
|
||||
|
||||
@[deprecated toList_length (since := "2024-09-09")]
|
||||
abbrev data_length := @toList_length
|
||||
|
||||
@[simp] theorem mkEmpty_eq (α n) : @mkEmpty α n = #[] := rfl
|
||||
|
||||
@[simp] theorem size_mk (as : List α) : (Array.mk as).size = as.length := by simp [size]
|
||||
|
||||
theorem foldrM_push [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) :
|
||||
(arr.push a).foldrM f init = f a init >>= arr.foldrM f := by
|
||||
simp [foldrM_eq_reverse_foldlM_toList, -size_push]
|
||||
|
||||
/-- Variant of `foldrM_push` with the `start := arr.size + 1` rather than `(arr.push a).size`. -/
|
||||
@[simp] theorem foldrM_push' [Monad m] (f : α → β → m β) (init : β) (arr : Array α) (a : α) :
|
||||
(arr.push a).foldrM f init (start := arr.size + 1) = f a init >>= arr.foldrM f := by
|
||||
simp [← foldrM_push]
|
||||
|
||||
theorem foldr_push (f : α → β → β) (init : β) (arr : Array α) (a : α) :
|
||||
(arr.push a).foldr f init = arr.foldr f (f a init) := foldrM_push ..
|
||||
|
||||
/-- Variant of `foldr_push` with the `start := arr.size + 1` rather than `(arr.push a).size`. -/
|
||||
@[simp] theorem foldr_push' (f : α → β → β) (init : β) (arr : Array α) (a : α) :
|
||||
(arr.push a).foldr f init (start := arr.size + 1) = arr.foldr f (f a init) := foldrM_push' ..
|
||||
|
||||
/-- A more efficient version of `arr.toList.reverse`. -/
|
||||
@[inline] def toListRev (arr : Array α) : List α := arr.foldl (fun l t => t :: l) []
|
||||
|
||||
@[simp] theorem toListRev_eq (arr : Array α) : arr.toListRev = arr.toList.reverse := by
|
||||
rw [toListRev, foldl_eq_foldl_toList, ← List.foldr_reverse, List.foldr_cons_nil]
|
||||
|
||||
theorem mapM_eq_foldlM [Monad m] [LawfulMonad m] (f : α → m β) (arr : Array α) :
|
||||
arr.mapM f = arr.foldlM (fun bs a => bs.push <$> f a) #[] := by
|
||||
rw [mapM, aux, foldlM_eq_foldlM_toList]; rfl
|
||||
|
|
@ -345,7 +387,7 @@ theorem getElem_mem_toList (a : Array α) (h : i < a.size) : a[i] ∈ a.toList :
|
|||
abbrev getElem_mem_data := @getElem_mem_toList
|
||||
|
||||
theorem getElem?_eq_toList_get? (a : Array α) (i : Nat) : a[i]? = a.toList.get? i := by
|
||||
by_cases i < a.size <;> simp_all [getElem?_pos, getElem?_neg, List.get?_eq_get, eq_comm]; rfl
|
||||
by_cases i < a.size <;> simp_all [getElem?_pos, getElem?_neg, List.get?_eq_get, eq_comm]
|
||||
|
||||
@[deprecated getElem?_eq_toList_get? (since := "2024-09-09")]
|
||||
abbrev getElem?_eq_data_get? := @getElem?_eq_toList_get?
|
||||
|
|
@ -605,12 +647,12 @@ theorem foldr_induction
|
|||
simp only [mem_def, map_toList, List.mem_map]
|
||||
|
||||
theorem mapM_eq_mapM_toList [Monad m] [LawfulMonad m] (f : α → m β) (arr : Array α) :
|
||||
arr.mapM f = return mk (← arr.toList.mapM f) := by
|
||||
arr.mapM f = return (← arr.toList.mapM f).toArray := by
|
||||
rw [mapM_eq_foldlM, foldlM_eq_foldlM_toList, ← List.foldrM_reverse]
|
||||
conv => rhs; rw [← List.reverse_reverse arr.toList]
|
||||
induction arr.toList.reverse with
|
||||
| nil => simp; rfl
|
||||
| cons a l ih => simp [ih]; simp [map_eq_pure_bind, push]
|
||||
| nil => simp
|
||||
| cons a l ih => simp [ih]; simp [map_eq_pure_bind]
|
||||
|
||||
@[deprecated mapM_eq_mapM_toList (since := "2024-09-09")]
|
||||
abbrev mapM_eq_mapM_data := @mapM_eq_mapM_toList
|
||||
|
|
|
|||
|
|
@ -12,6 +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 [Array.getElem_eq_toList_getElem] using List.exists_of_set _
|
||||
simpa only [ugetElem_eq_getElem, getElem_eq_toList_getElem, uset, toList_set] using
|
||||
List.exists_of_set _
|
||||
|
||||
end Array
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ protected def _root_.USize.repr (n : @& USize) : String :=
|
|||
|
||||
/-- We statically allocate and memoize reprs for small natural numbers. -/
|
||||
private def reprArray : Array String := Id.run do
|
||||
List.range 128 |>.map (·.toUSize.repr) |> Array.mk
|
||||
List.range 128 |>.map (·.toUSize.repr) |> List.toArray
|
||||
|
||||
private def reprFast (n : Nat) : String :=
|
||||
if h : n < 128 then Nat.reprArray.get ⟨n, h⟩ else
|
||||
|
|
|
|||
|
|
@ -2709,7 +2709,10 @@ def Array.extract (as : Array α) (start stop : Nat) : Array α :=
|
|||
let sz' := Nat.sub (min stop as.size) start
|
||||
loop sz' start (mkEmpty sz')
|
||||
|
||||
/-- Auxiliary definition for `List.toArray`. -/
|
||||
/--
|
||||
Auxiliary definition for `List.toArray`.
|
||||
`List.toArrayAux as r = r ++ as.toArray`
|
||||
-/
|
||||
@[inline_if_reduce]
|
||||
def List.toArrayAux : List α → Array α → Array α
|
||||
| nil, r => r
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ let _x.26 := @Array.push _ _x.24 z
|
|||
def foldArrayLiteral : Folder := fun args => do
|
||||
let #[_, .fvar fvarId] := args | return none
|
||||
let some (list, typ, level) ← getPseudoListLiteral fvarId | return none
|
||||
let arr := Array.mk list
|
||||
let arr := list.toArray
|
||||
let lit ← mkPseudoArrayLiteral arr typ level
|
||||
return some lit
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ theorem CNF.Clause.mem_lrat_of_mem (clause : CNF.Clause (PosFin n)) (h1 : l ∈
|
|||
| nil => cases h1
|
||||
| cons hd tl ih =>
|
||||
unfold DefaultClause.ofArray at h2
|
||||
rw [Array.foldr_eq_foldr_toList, Array.toArray_toList] at h2
|
||||
rw [Array.foldr_eq_foldr_toList, List.toArray_toList] at h2
|
||||
dsimp only [List.foldr] at h2
|
||||
split at h2
|
||||
· cases h2
|
||||
|
|
@ -77,7 +77,7 @@ theorem CNF.Clause.mem_lrat_of_mem (clause : CNF.Clause (PosFin n)) (h1 : l ∈
|
|||
· assumption
|
||||
· next heq _ _ =>
|
||||
unfold DefaultClause.ofArray
|
||||
rw [Array.foldr_eq_foldr_toList, Array.toArray_toList]
|
||||
rw [Array.foldr_eq_foldr_toList, List.toArray_toList]
|
||||
exact heq
|
||||
· cases h1
|
||||
· simp only [← Option.some.inj h2]
|
||||
|
|
@ -89,7 +89,7 @@ theorem CNF.Clause.mem_lrat_of_mem (clause : CNF.Clause (PosFin n)) (h1 : l ∈
|
|||
apply ih
|
||||
assumption
|
||||
unfold DefaultClause.ofArray
|
||||
rw [Array.foldr_eq_foldr_toList, Array.toArray_toList]
|
||||
rw [Array.foldr_eq_foldr_toList, List.toArray_toList]
|
||||
exact heq
|
||||
|
||||
theorem CNF.Clause.convertLRAT_sat_of_sat (clause : CNF.Clause (PosFin n))
|
||||
|
|
|
|||
|
|
@ -500,8 +500,7 @@ theorem deleteOne_preserves_strongAssignmentsInvariant {n : Nat} (f : DefaultFor
|
|||
· next id_eq_idx =>
|
||||
exfalso
|
||||
have idx_in_bounds2 : idx < f.clauses.size := by
|
||||
have f_clauses_rw : f.clauses = { toList := f.clauses.toList } := rfl
|
||||
conv => rhs; rw [f_clauses_rw, Array.size_mk]
|
||||
conv => rhs; rw [Array.size_mk]
|
||||
exact hbound
|
||||
simp only [getElem!, id_eq_idx, Array.toList_length, idx_in_bounds2, ↓reduceDIte,
|
||||
Fin.eta, Array.get_eq_getElem, Array.getElem_eq_toList_getElem, decidableGetElem?] at heq
|
||||
|
|
@ -534,8 +533,7 @@ theorem deleteOne_preserves_strongAssignmentsInvariant {n : Nat} (f : DefaultFor
|
|||
· next id_eq_idx =>
|
||||
exfalso
|
||||
have idx_in_bounds2 : idx < f.clauses.size := by
|
||||
have f_clauses_rw : f.clauses = { toList := f.clauses.toList } := rfl
|
||||
conv => rhs; rw [f_clauses_rw, Array.size_mk]
|
||||
conv => rhs; rw [Array.size_mk]
|
||||
exact hbound
|
||||
simp only [getElem!, id_eq_idx, Array.toList_length, idx_in_bounds2, ↓reduceDIte,
|
||||
Fin.eta, Array.get_eq_getElem, Array.getElem_eq_toList_getElem, decidableGetElem?] at heq
|
||||
|
|
@ -595,8 +593,7 @@ theorem deleteOne_preserves_strongAssignmentsInvariant {n : Nat} (f : DefaultFor
|
|||
· next id_eq_idx =>
|
||||
exfalso
|
||||
have idx_in_bounds2 : idx < f.clauses.size := by
|
||||
have f_clauses_rw : f.clauses = { toList := f.clauses.toList } := rfl
|
||||
conv => rhs; rw [f_clauses_rw, Array.size_mk]
|
||||
conv => rhs; rw [Array.size_mk]
|
||||
exact hbound
|
||||
simp only [getElem!, id_eq_idx, Array.toList_length, idx_in_bounds2, ↓reduceDIte,
|
||||
Fin.eta, Array.get_eq_getElem, Array.getElem_eq_toList_getElem, decidableGetElem?] at heq
|
||||
|
|
|
|||
|
|
@ -1112,7 +1112,7 @@ theorem nodup_derivedLits {n : Nat} (f : DefaultFormula n)
|
|||
(derivedLits : CNF.Clause (PosFin n))
|
||||
(derivedLits_satisfies_invariant:
|
||||
DerivedLitsInvariant f f_assignments_size (performRupCheck f rupHints).fst.assignments f'_assignments_size derivedLits)
|
||||
(derivedLits_arr : Array (Literal (PosFin n))) (derivedLits_arr_def: derivedLits_arr = { toList := derivedLits })
|
||||
(derivedLits_arr : Array (Literal (PosFin n))) (derivedLits_arr_def : derivedLits_arr = { toList := derivedLits })
|
||||
(i j : Fin (Array.size derivedLits_arr)) (i_ne_j : i ≠ j) :
|
||||
derivedLits_arr[i] ≠ derivedLits_arr[j] := by
|
||||
intro li_eq_lj
|
||||
|
|
|
|||
|
|
@ -543,8 +543,8 @@ theorem reduce_fold_fn_preserves_induction_motive {c_arr : Array (Literal (PosFi
|
|||
theorem reduce_postcondition {n : Nat} (c : DefaultClause n) (assignment : Array Assignment) :
|
||||
(reduce c assignment = reducedToEmpty → Incompatible (PosFin n) c assignment) ∧
|
||||
(∀ l : Literal (PosFin n), reduce c assignment = reducedToUnit l → ∀ (p : (PosFin n) → Bool), p ⊨ assignment → p ⊨ c → p ⊨ l) := by
|
||||
let c_arr := Array.mk c.clause
|
||||
have c_clause_rw : c.clause = c_arr.toList := rfl
|
||||
let c_arr := c.clause.toArray
|
||||
have c_clause_rw : c.clause = c_arr.toList := by simp [c_arr]
|
||||
rw [reduce, c_clause_rw, ← Array.foldl_eq_foldl_toList]
|
||||
let motive := ReducePostconditionInductionMotive c_arr assignment
|
||||
have h_base : motive 0 reducedToEmpty := by
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ def enumFromTR' (n : Nat) (l : List α) : List (Nat × α) :=
|
|||
|
||||
open List in
|
||||
theorem enumFrom_eq_enumFromTR' : @enumFrom = @enumFromTR' := by
|
||||
funext α n l; simp [enumFromTR', -Array.size_toArray]
|
||||
funext α n l; simp only [enumFromTR']
|
||||
let f := fun (a : α) (n, acc) => (n-1, (n-1, a) :: acc)
|
||||
let rec go : ∀ l n, l.foldr f (n + l.length, []) = (n, enumFrom n l)
|
||||
| [], n => rfl
|
||||
| a::as, n => by
|
||||
rw [← show _ + as.length = n + (a::as).length from Nat.succ_add .., List.foldr, go as]
|
||||
simp [enumFrom, f]
|
||||
rw [Array.foldr_eq_foldr_data]
|
||||
rw [Array.foldr_eq_foldr_toList]
|
||||
simp [go] -- Should close the goal
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue