feat: upstream List/Array/Vector lemmas from human-eval-lean (#12405)
This PR adds several useful lemmas for `List`, `Array` and `Vector` whenever they were missing, improving API coverage and consistency among these types. - `size_singleton`/`sum_singleton`/`sum_push` - `foldlM_toArray`/`foldlM_toList`/`foldl_toArray`/`foldl_toList`/`foldrM_toArray`/`foldrM_toList`/`foldr_toList` - `toArray_toList` - `foldl_eq_apply_foldr`/`foldr_eq_apply_foldl`, `foldr_eq_foldl`: relates `foldl` and `foldr` for associative operations with identity - `sum_eq_foldl`: relates sum to `foldl` for associative operations with identity - `Perm.pairwise_iff`/`Perm.pairwise`: pairwise properties are preserved under permutations of arrays
This commit is contained in:
parent
b548cf38b6
commit
c86f82161a
5 changed files with 145 additions and 7 deletions
|
|
@ -72,6 +72,9 @@ theorem toArray_eq : List.toArray as = xs ↔ as = xs.toList := by
|
|||
|
||||
/-! ### size -/
|
||||
|
||||
theorem size_singleton {x : α} : #[x].size = 1 := by
|
||||
simp
|
||||
|
||||
theorem eq_empty_of_size_eq_zero (h : xs.size = 0) : xs = #[] := by
|
||||
cases xs
|
||||
simp_all
|
||||
|
|
@ -3483,6 +3486,21 @@ theorem foldl_eq_foldr_reverse {xs : Array α} {f : β → α → β} {b} :
|
|||
theorem foldr_eq_foldl_reverse {xs : Array α} {f : α → β → β} {b} :
|
||||
xs.foldr f b = xs.reverse.foldl (fun x y => f y x) b := by simp
|
||||
|
||||
theorem foldl_eq_apply_foldr {xs : Array α} {f : α → α → α}
|
||||
[Std.Associative f] [Std.LawfulRightIdentity f init] :
|
||||
xs.foldl f x = f x (xs.foldr f init) := by
|
||||
simp [← foldl_toList, ← foldr_toList, List.foldl_eq_apply_foldr]
|
||||
|
||||
theorem foldr_eq_apply_foldl {xs : Array α} {f : α → α → α}
|
||||
[Std.Associative f] [Std.LawfulLeftIdentity f init] :
|
||||
xs.foldr f x = f (xs.foldl f init) x := by
|
||||
simp [← foldl_toList, ← foldr_toList, List.foldr_eq_apply_foldl]
|
||||
|
||||
theorem foldr_eq_foldl {xs : Array α} {f : α → α → α}
|
||||
[Std.Associative f] [Std.LawfulIdentity f init] :
|
||||
xs.foldr f init = xs.foldl f init := by
|
||||
simp [foldl_eq_apply_foldr, Std.LawfulLeftIdentity.left_id]
|
||||
|
||||
@[simp] theorem foldr_push_eq_append {as : Array α} {bs : Array β} {f : α → β} (w : start = as.size) :
|
||||
as.foldr (fun a xs => Array.push xs (f a)) bs start 0 = bs ++ (as.map f).reverse := by
|
||||
subst w
|
||||
|
|
@ -4335,16 +4353,33 @@ def sum_eq_sum_toList := @sum_toList
|
|||
|
||||
@[simp, grind =]
|
||||
theorem sum_append [Zero α] [Add α] [Std.Associative (α := α) (· + ·)]
|
||||
[Std.LeftIdentity (α := α) (· + ·) 0] [Std.LawfulLeftIdentity (α := α) (· + ·) 0]
|
||||
[Std.LawfulLeftIdentity (α := α) (· + ·) 0]
|
||||
{as₁ as₂ : Array α} : (as₁ ++ as₂).sum = as₁.sum + as₂.sum := by
|
||||
simp [← sum_toList, List.sum_append]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_singleton [Add α] [Zero α] [Std.LawfulRightIdentity (· + ·) (0 : α)] {x : α} :
|
||||
#[x].sum = x := by
|
||||
simp [Array.sum_eq_foldr, Std.LawfulRightIdentity.right_id x]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_push [Add α] [Zero α] [Std.Associative (α := α) (· + ·)]
|
||||
[Std.LawfulIdentity (· + ·) (0 : α)] {xs : Array α} {x : α} :
|
||||
(xs.push x).sum = xs.sum + x := by
|
||||
simp [Array.sum_eq_foldr, Std.LawfulRightIdentity.right_id, Std.LawfulLeftIdentity.left_id,
|
||||
← Array.foldr_assoc]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_reverse [Zero α] [Add α] [Std.Associative (α := α) (· + ·)]
|
||||
[Std.Commutative (α := α) (· + ·)]
|
||||
[Std.LawfulLeftIdentity (α := α) (· + ·) 0] (xs : Array α) : xs.reverse.sum = xs.sum := by
|
||||
simp [← sum_toList, List.sum_reverse]
|
||||
|
||||
theorem sum_eq_foldl [Zero α] [Add α] [Std.Associative (α := α) (· + ·)]
|
||||
[Std.LawfulIdentity (· + ·) (0 : α)] {xs : Array α} :
|
||||
xs.sum = xs.foldl (init := 0) (· + ·) := by
|
||||
simp [← sum_toList, List.sum_eq_foldl]
|
||||
|
||||
theorem foldl_toList_eq_flatMap {l : List α} {acc : Array β}
|
||||
{F : Array β → α → Array β} {G : α → List β}
|
||||
(H : ∀ acc a, (F acc a).toList = acc.toList ++ G a) :
|
||||
|
|
|
|||
|
|
@ -126,6 +126,14 @@ theorem swap_perm {xs : Array α} {i j : Nat} (h₁ : i < xs.size) (h₂ : j < x
|
|||
simp only [swap, perm_iff_toList_perm, toList_set]
|
||||
apply set_set_perm
|
||||
|
||||
theorem Perm.pairwise_iff {R : α → α → Prop} (S : ∀ {x y}, R x y → R y x) {xs ys : Array α}
|
||||
: ∀ _p : xs.Perm ys, xs.toList.Pairwise R ↔ ys.toList.Pairwise R := by
|
||||
simpa only [perm_iff_toList_perm] using List.Perm.pairwise_iff S
|
||||
|
||||
theorem Perm.pairwise {R : α → α → Prop} {xs ys : Array α} (hp : xs ~ ys)
|
||||
(hR : xs.toList.Pairwise R) (hsymm : ∀ {x y}, R x y → R y x) :
|
||||
ys.toList.Pairwise R := (hp.pairwise_iff hsymm).mp hR
|
||||
|
||||
namespace Perm
|
||||
|
||||
set_option linter.indexVariables false in
|
||||
|
|
|
|||
|
|
@ -1838,6 +1838,11 @@ theorem sum_append [Add α] [Zero α] [Std.LawfulLeftIdentity (α := α) (· +
|
|||
[Std.Associative (α := α) (· + ·)] {l₁ l₂ : List α} : (l₁ ++ l₂).sum = l₁.sum + l₂.sum := by
|
||||
induction l₁ generalizing l₂ <;> simp_all [Std.Associative.assoc, Std.LawfulLeftIdentity.left_id]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_singleton [Add α] [Zero α] [Std.LawfulRightIdentity (· + ·) (0 : α)] {x : α} :
|
||||
[x].sum = x := by
|
||||
simp [List.sum_eq_foldr, Std.LawfulRightIdentity.right_id x]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_reverse [Zero α] [Add α] [Std.Associative (α := α) (· + ·)]
|
||||
[Std.Commutative (α := α) (· + ·)]
|
||||
|
|
@ -2727,6 +2732,31 @@ theorem foldr_assoc {op : α → α → α} [ha : Std.Associative op] :
|
|||
simp only [foldr_cons, ha.assoc]
|
||||
rw [foldr_assoc]
|
||||
|
||||
theorem foldl_eq_apply_foldr {xs : List α} {f : α → α → α}
|
||||
[Std.Associative f] [Std.LawfulRightIdentity f init] :
|
||||
xs.foldl f x = f x (xs.foldr f init) := by
|
||||
induction xs generalizing x
|
||||
· simp [Std.LawfulRightIdentity.right_id]
|
||||
· simp [foldl_assoc, *]
|
||||
|
||||
theorem foldr_eq_apply_foldl {xs : List α} {f : α → α → α}
|
||||
[Std.Associative f] [Std.LawfulLeftIdentity f init] :
|
||||
xs.foldr f x = f (xs.foldl f init) x := by
|
||||
have : Std.Associative (fun x y => f y x) := ⟨by simp [Std.Associative.assoc]⟩
|
||||
have : Std.RightIdentity (fun x y => f y x) init := ⟨⟩
|
||||
have : Std.LawfulRightIdentity (fun x y => f y x) init := ⟨by simp [Std.LawfulLeftIdentity.left_id]⟩
|
||||
rw [← List.reverse_reverse (as := xs), foldr_reverse, foldl_eq_apply_foldr, foldl_reverse]
|
||||
|
||||
theorem foldr_eq_foldl {xs : List α} {f : α → α → α}
|
||||
[Std.Associative f] [Std.LawfulIdentity f init] :
|
||||
xs.foldr f init = xs.foldl f init := by
|
||||
simp [foldl_eq_apply_foldr, Std.LawfulLeftIdentity.left_id]
|
||||
|
||||
theorem sum_eq_foldl [Zero α] [Add α] [Std.Associative (α := α) (· + ·)]
|
||||
[Std.LawfulIdentity (· + ·) (0 : α)] {xs : List α} :
|
||||
xs.sum = xs.foldl (init := 0) (· + ·) := by
|
||||
simp [sum_eq_foldr, foldl_eq_apply_foldr, Std.LawfulLeftIdentity.left_id]
|
||||
|
||||
-- The argument `f : α₁ → α₂` is intentionally explicit, as it is sometimes not found by unification.
|
||||
theorem foldl_hom (f : α₁ → α₂) {g₁ : α₁ → β → α₁} {g₂ : α₂ → β → α₂} {l : List β} {init : α₁}
|
||||
(H : ∀ x y, g₂ (f x) y = f (g₁ x y)) : l.foldl g₂ (f init) = f (l.foldl g₁ init) := by
|
||||
|
|
|
|||
|
|
@ -101,6 +101,17 @@ theorem toArray_mk {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).toArray
|
|||
@[simp] theorem foldr_mk {f : α → β → β} {b : β} {xs : Array α} (h : xs.size = n) :
|
||||
(Vector.mk xs h).foldr f b = xs.foldr f b := rfl
|
||||
|
||||
@[simp, grind =] theorem foldlM_toArray [Monad m]
|
||||
{f : β → α → m β} {init : β} {xs : Vector α n} :
|
||||
xs.toArray.foldlM f init = xs.foldlM f init := rfl
|
||||
|
||||
@[simp, grind =] theorem foldrM_toArray [Monad m]
|
||||
{f : α → β → m β} {init : β} {xs : Vector α n} :
|
||||
xs.toArray.foldrM f init = xs.foldrM f init := rfl
|
||||
|
||||
@[simp, grind =] theorem foldl_toArray (f : β → α → β) {init : β} {xs : Vector α n} :
|
||||
xs.toArray.foldl f init = xs.foldl f init := rfl
|
||||
|
||||
@[simp] theorem drop_mk {xs : Array α} {h : xs.size = n} {i} :
|
||||
(Vector.mk xs h).drop i = Vector.mk (xs.extract i xs.size) (by simp [h]) := rfl
|
||||
|
||||
|
|
@ -514,17 +525,32 @@ protected theorem ext {xs ys : Vector α n} (h : (i : Nat) → (_ : i < n) → x
|
|||
|
||||
@[grind =_] theorem toList_toArray {xs : Vector α n} : xs.toArray.toList = xs.toList := rfl
|
||||
|
||||
theorem toArray_toList {xs : Vector α n} : xs.toList.toArray = xs.toArray := rfl
|
||||
|
||||
@[simp, grind =] theorem foldlM_toList [Monad m]
|
||||
{f : β → α → m β} {init : β} {xs : Vector α n} :
|
||||
xs.toList.foldlM f init = xs.foldlM f init := by
|
||||
rw [← foldlM_toArray, ← toArray_toList, List.foldlM_toArray]
|
||||
|
||||
@[simp, grind =] theorem foldl_toList (f : β → α → β) {init : β} {xs : Vector α n} :
|
||||
xs.toList.foldl f init = xs.foldl f init :=
|
||||
List.foldl_eq_foldlM .. ▸ foldlM_toList ..
|
||||
|
||||
@[simp, grind =] theorem foldrM_toList [Monad m]
|
||||
{f : α → β → m β} {init : β} {xs : Vector α n} :
|
||||
xs.toList.foldrM f init = xs.foldrM f init := by
|
||||
rw [← foldrM_toArray, ← toArray_toList, List.foldrM_toArray]
|
||||
|
||||
@[simp, grind =] theorem foldr_toList (f : α → β → β) {init : β} {xs : Vector α n} :
|
||||
xs.toList.foldr f init = xs.foldr f init :=
|
||||
List.foldr_eq_foldrM .. ▸ foldrM_toList ..
|
||||
|
||||
@[simp, grind =] theorem toList_mk : (Vector.mk xs h).toList = xs.toList := rfl
|
||||
|
||||
@[simp, grind =] theorem sum_toList [Add α] [Zero α] {xs : Vector α n} :
|
||||
xs.toList.sum = xs.sum := by
|
||||
rw [← toList_toArray, Array.sum_toList, sum_toArray]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem toList_zip {as : Vector α n} {bs : Vector β n} :
|
||||
(Vector.zip as bs).toList = List.zip as.toList bs.toList := by
|
||||
rw [mk_zip_mk, toList_mk, Array.toList_zip, toList_toArray, toList_toArray]
|
||||
|
||||
@[simp] theorem getElem_toList {xs : Vector α n} {i : Nat} (h : i < xs.toList.length) :
|
||||
xs.toList[i] = xs[i]'(by simpa using h) := by
|
||||
cases xs
|
||||
|
|
@ -609,6 +635,11 @@ theorem toList_swap {xs : Vector α n} {i j} (hi hj) :
|
|||
@[simp] theorem toList_take {xs : Vector α n} {i} : (xs.take i).toList = xs.toList.take i := by
|
||||
simp [toList]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem toList_zip {as : Vector α n} {bs : Vector β n} :
|
||||
(Vector.zip as bs).toList = List.zip as.toList bs.toList := by
|
||||
rw [mk_zip_mk, toList_mk, Array.toList_zip, toList_toArray, toList_toArray]
|
||||
|
||||
@[simp] theorem toList_zipWith {f : α → β → γ} {as : Vector α n} {bs : Vector β n} :
|
||||
(Vector.zipWith f as bs).toList = List.zipWith f as.toList bs.toList := by
|
||||
rcases as with ⟨as, rfl⟩
|
||||
|
|
@ -703,6 +734,9 @@ protected theorem eq_empty {xs : Vector α 0} : xs = #v[] := by
|
|||
|
||||
/-! ### size -/
|
||||
|
||||
theorem size_singleton {x : α} : #v[x].size = 1 := by
|
||||
simp
|
||||
|
||||
theorem eq_empty_of_size_eq_zero {xs : Vector α n} (h : n = 0) : xs = #v[].cast h.symm := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
apply toArray_inj.1
|
||||
|
|
@ -2448,6 +2482,21 @@ theorem foldl_eq_foldr_reverse {xs : Vector α n} {f : β → α → β} {b} :
|
|||
theorem foldr_eq_foldl_reverse {xs : Vector α n} {f : α → β → β} {b} :
|
||||
xs.foldr f b = xs.reverse.foldl (fun x y => f y x) b := by simp
|
||||
|
||||
theorem foldl_eq_apply_foldr {xs : Vector α n} {f : α → α → α}
|
||||
[Std.Associative f] [Std.LawfulRightIdentity f init] :
|
||||
xs.foldl f x = f x (xs.foldr f init) := by
|
||||
simp [← foldl_toList, ← foldr_toList, List.foldl_eq_apply_foldr]
|
||||
|
||||
theorem foldr_eq_apply_foldl {xs : Vector α n} {f : α → α → α}
|
||||
[Std.Associative f] [Std.LawfulLeftIdentity f init] :
|
||||
xs.foldr f x = f (xs.foldl f init) x := by
|
||||
simp [← foldl_toList, ← foldr_toList, List.foldr_eq_apply_foldl]
|
||||
|
||||
theorem foldr_eq_foldl {xs : Vector α n} {f : α → α → α}
|
||||
[Std.Associative f] [Std.LawfulIdentity f init] :
|
||||
xs.foldr f init = xs.foldl f init := by
|
||||
simp [foldl_eq_apply_foldr, Std.LawfulLeftIdentity.left_id]
|
||||
|
||||
theorem foldl_assoc {op : α → α → α} [ha : Std.Associative op] {xs : Vector α n} {a₁ a₂} :
|
||||
xs.foldl op (op a₁ a₂) = op a₁ (xs.foldl op a₂) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
|
|
@ -3064,8 +3113,25 @@ theorem sum_append [Zero α] [Add α] [Std.Associative (α := α) (· + ·)]
|
|||
{as₁ as₂ : Vector α n} : (as₁ ++ as₂).sum = as₁.sum + as₂.sum := by
|
||||
simp [← sum_toList, List.sum_append]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_singleton [Add α] [Zero α] [Std.LawfulRightIdentity (· + ·) (0 : α)] {x : α} :
|
||||
#v[x].sum = x := by
|
||||
simp [← sum_toList, Std.LawfulRightIdentity.right_id x]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_push [Add α] [Zero α] [Std.Associative (α := α) (· + ·)]
|
||||
[Std.LawfulIdentity (· + ·) (0 : α)] {xs : Vector α n} {x : α} :
|
||||
(xs.push x).sum = xs.sum + x := by
|
||||
simp [← sum_toArray]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem sum_reverse [Zero α] [Add α] [Std.Associative (α := α) (· + ·)]
|
||||
[Std.Commutative (α := α) (· + ·)]
|
||||
[Std.LawfulLeftIdentity (α := α) (· + ·) 0] (xs : Vector α n) : xs.reverse.sum = xs.sum := by
|
||||
simp [← sum_toList, List.sum_reverse]
|
||||
|
||||
theorem sum_eq_foldl [Zero α] [Add α]
|
||||
[Std.Associative (α := α) (· + ·)] [Std.LawfulIdentity (· + ·) (0 : α)]
|
||||
{xs : Vector α n} :
|
||||
xs.sum = xs.foldl (b := 0) (· + ·) := by
|
||||
simp [← sum_toList, List.sum_eq_foldl]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
@[simp] theorem Array.size_singleton : #[a].size = 1 := rfl
|
||||
@[simp] theorem USize.not_size_le_one : ¬ USize.size ≤ 1 := by cases USize.size_eq <;> simp (config := { decide := true }) [*]
|
||||
|
||||
def f := #[true].any id 0 USize.size
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue