Compare commits

...

6 Commits

Author SHA1 Message Date
Kim Morrison
3ef63b219c fix test 2024-09-23 15:04:39 +10:00
Kim Morrison
1769ea4264 fix proof 2024-09-23 14:33:10 +10:00
Kim Morrison
8a4193e0c4 merge master 2024-09-23 14:08:46 +10:00
Kim Morrison
49c1c5ad2f much simpler proof 2024-09-20 16:56:17 +10:00
Kim Morrison
eb4668122f feat: theorems about List.toArray 2024-09-20 16:03:36 +10:00
Kim Morrison
3541cb783f chore: reorganization in Array/Basic (#5400)
Getting started on `Array`.
2024-09-20 16:03:36 +10:00
12 changed files with 108 additions and 60 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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))

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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