Skip to content

Commit a42f76e

Browse files
kim-emluisacicolini
authored andcommitted
feat: lemmas about Vector.any/all/set (leanprover#6369)
This PR adds lemmas about `Vector.set`, `anyM`, `any`, `allM`, and `all`. With these additions, `Vector` is now as in-sync with the `List` API as `Array` is, and in future I'll be updating both simultaneously.
1 parent f3732e7 commit a42f76e

File tree

3 files changed

+375
-73
lines changed

3 files changed

+375
-73
lines changed

src/Init/Data/Array/Basic.lean

+6
Original file line numberDiff line numberDiff line change
@@ -662,9 +662,15 @@ def any (as : Array α) (p : α → Bool) (start := 0) (stop := as.size) : Bool
662662
def all (as : Array α) (p : α → Bool) (start := 0) (stop := as.size) : Bool :=
663663
Id.run <| as.allM p start stop
664664

665+
/-- `as.contains a` is true if there is some element `b` in `as` such that `a == b`. -/
665666
def contains [BEq α] (as : Array α) (a : α) : Bool :=
666667
as.any (a == ·)
667668

669+
/--
670+
Variant of `Array.contains` with arguments reversed.
671+
672+
For verification purposes, we simplify this to `contains`.
673+
-/
668674
def elem [BEq α] (a : α) (as : Array α) : Bool :=
669675
as.contains a
670676

src/Init/Data/Array/Lemmas.lean

+60-47
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,7 @@ theorem any_iff_exists {p : α → Bool} {as : Array α} {start stop} :
483483
rw [Bool.eq_false_iff, Ne, any_eq_true]
484484
simp
485485

486-
theorem any_toList {p : α → Bool} (as : Array α) : as.toList.any p = as.any p := by
486+
@[simp] theorem any_toList {p : α → Bool} (as : Array α) : as.toList.any p = as.any p := by
487487
rw [Bool.eq_iff_iff, any_eq_true, List.any_eq_true]
488488
simp only [List.mem_iff_getElem, getElem_toList]
489489
exact ⟨fun ⟨_, ⟨i, w, rfl⟩, h⟩ => ⟨i, w, h⟩, fun ⟨i, w, h⟩ => ⟨_, ⟨i, w, rfl⟩, h⟩⟩
@@ -522,7 +522,7 @@ theorem all_iff_forall {p : α → Bool} {as : Array α} {start stop} :
522522
rw [Bool.eq_false_iff, Ne, all_eq_true]
523523
simp
524524

525-
theorem all_toList {p : α → Bool} (as : Array α) : as.toList.all p = as.all p := by
525+
@[simp] theorem all_toList {p : α → Bool} (as : Array α) : as.toList.all p = as.all p := by
526526
rw [Bool.eq_iff_iff, all_eq_true, List.all_eq_true]
527527
simp only [List.mem_iff_getElem, getElem_toList]
528528
constructor
@@ -534,20 +534,6 @@ theorem all_toList {p : α → Bool} (as : Array α) : as.toList.all p = as.all
534534
theorem all_eq_true_iff_forall_mem {l : Array α} : l.all p ↔ ∀ x, x ∈ l → p x := by
535535
simp only [← all_toList, List.all_eq_true, mem_def]
536536

537-
theorem _root_.List.anyM_toArray [Monad m] [LawfulMonad m] (p : α → m Bool) (l : List α) :
538-
l.toArray.anyM p = l.anyM p := by
539-
rw [← anyM_toList]
540-
541-
theorem _root_.List.any_toArray (p : α → Bool) (l : List α) : l.toArray.any p = l.any p := by
542-
rw [any_toList]
543-
544-
theorem _root_.List.allM_toArray [Monad m] [LawfulMonad m] (p : α → m Bool) (l : List α) :
545-
l.toArray.allM p = l.allM p := by
546-
rw [← allM_toList]
547-
548-
theorem _root_.List.all_toArray (p : α → Bool) (l : List α) : l.toArray.all p = l.all p := by
549-
rw [all_toList]
550-
551537
/-- Variant of `anyM_toArray` with a side condition on `stop`. -/
552538
@[simp] theorem _root_.List.anyM_toArray' [Monad m] [LawfulMonad m] (p : α → m Bool) (l : List α)
553539
(h : stop = l.toArray.size) :
@@ -574,6 +560,20 @@ theorem _root_.List.all_toArray (p : α → Bool) (l : List α) : l.toArray.all
574560
subst h
575561
rw [all_toList]
576562

563+
theorem _root_.List.anyM_toArray [Monad m] [LawfulMonad m] (p : α → m Bool) (l : List α) :
564+
l.toArray.anyM p = l.anyM p := by
565+
rw [← anyM_toList]
566+
567+
theorem _root_.List.any_toArray (p : α → Bool) (l : List α) : l.toArray.any p = l.any p := by
568+
rw [any_toList]
569+
570+
theorem _root_.List.allM_toArray [Monad m] [LawfulMonad m] (p : α → m Bool) (l : List α) :
571+
l.toArray.allM p = l.allM p := by
572+
rw [← allM_toList]
573+
574+
theorem _root_.List.all_toArray (p : α → Bool) (l : List α) : l.toArray.all p = l.all p := by
575+
rw [all_toList]
576+
577577
/-- Variant of `any_eq_true` in terms of membership rather than an array index. -/
578578
theorem any_eq_true' {p : α → Bool} {as : Array α} :
579579
as.any p = true ↔ (∃ x, x ∈ as ∧ p x) := by
@@ -641,7 +641,7 @@ theorem decide_forall_mem {xs : Array α} {p : α → Prop} [DecidablePred p] :
641641
l.toArray.contains a = l.contains a := by
642642
simp [Array.contains, List.any_beq]
643643

644-
@[simp] theorem _root_.List.elem_toArray [BEq α] {l : List α} {a : α} :
644+
theorem _root_.List.elem_toArray [BEq α] {l : List α} {a : α} :
645645
Array.elem a l.toArray = List.elem a l := by
646646
simp [Array.elem]
647647

@@ -663,26 +663,32 @@ theorem all_bne' [BEq α] [PartialEquivBEq α] {xs : Array α} :
663663
(xs.all fun x => x != a) = !xs.contains a := by
664664
simp only [bne_comm, all_bne]
665665

666-
theorem mem_of_elem_eq_true [BEq α] [LawfulBEq α] {a : α} {as : Array α} : elem a as = true → a ∈ as := by
666+
theorem mem_of_contains_eq_true [BEq α] [LawfulBEq α] {a : α} {as : Array α} : as.contains a = true → a ∈ as := by
667667
cases as
668668
simp
669669

670-
theorem elem_eq_true_of_mem [BEq α] [LawfulBEq α] {a : α} {as : Array α} (h : a ∈ as) : elem a as = true := by
670+
@[deprecated mem_of_contains_eq_true (since := "2024-12-12")]
671+
abbrev mem_of_elem_eq_true := @mem_of_contains_eq_true
672+
673+
theorem contains_eq_true_of_mem [BEq α] [LawfulBEq α] {a : α} {as : Array α} (h : a ∈ as) : as.contains a = true := by
671674
cases as
672675
simpa using h
673676

677+
@[deprecated contains_eq_true_of_mem (since := "2024-12-12")]
678+
abbrev elem_eq_true_of_mem := @contains_eq_true_of_mem
679+
674680
instance [BEq α] [LawfulBEq α] (a : α) (as : Array α) : Decidable (a ∈ as) :=
675-
decidable_of_decidable_of_iff (Iff.intro mem_of_elem_eq_true elem_eq_true_of_mem)
681+
decidable_of_decidable_of_iff (Iff.intro mem_of_contains_eq_true contains_eq_true_of_mem)
676682

677683
@[simp] theorem elem_eq_contains [BEq α] {a : α} {l : Array α} :
678684
elem a l = l.contains a := by
679685
simp [elem]
680686

681687
theorem elem_iff [BEq α] [LawfulBEq α] {a : α} {as : Array α} :
682-
elem a as = true ↔ a ∈ as := ⟨mem_of_elem_eq_true, elem_eq_true_of_mem
688+
elem a as = true ↔ a ∈ as := ⟨mem_of_contains_eq_true, contains_eq_true_of_mem
683689

684690
theorem contains_iff [BEq α] [LawfulBEq α] {a : α} {as : Array α} :
685-
as.contains a = true ↔ a ∈ as := ⟨mem_of_elem_eq_true, elem_eq_true_of_mem
691+
as.contains a = true ↔ a ∈ as := ⟨mem_of_contains_eq_true, contains_eq_true_of_mem
686692

687693
theorem elem_eq_mem [BEq α] [LawfulBEq α] (a : α) (as : Array α) :
688694
elem a as = decide (a ∈ as) := by rw [Bool.eq_iff_iff, elem_iff, decide_eq_true_iff]
@@ -762,24 +768,24 @@ theorem getElem?_set (a : Array α) (i : Nat) (h : i < a.size) (v : α) (j : Nat
762768
cases as <;> cases n <;> simp [set]
763769

764770
theorem set_comm (a b : α)
765-
{n m : Nat} (as : Array α) {hn : n < as.size} {hm : m < (as.set n a).size} (h : nm) :
766-
(as.set n a).set m b = (as.set m b (by simpa using hm)).set n a (by simpa using hn) := by
771+
{i j : Nat} (as : Array α) {hi : i < as.size} {hj : j < (as.set i a).size} (h : ij) :
772+
(as.set i a).set j b = (as.set j b (by simpa using hj)).set i a (by simpa using hi) := by
767773
cases as
768774
simp [List.set_comm _ _ _ h]
769775

770776
@[simp]
771-
theorem set_set (a b : α) (as : Array α) (n : Nat) (h : n < as.size) :
772-
(as.set n a).set n b (by simpa using h) = as.set n b := by
777+
theorem set_set (a b : α) (as : Array α) (i : Nat) (h : i < as.size) :
778+
(as.set i a).set i b (by simpa using h) = as.set i b := by
773779
cases as
774780
simp
775781

776-
theorem mem_set (as : Array α) (n : Nat) (h : n < as.size) (a : α) :
777-
a ∈ as.set n a := by
782+
theorem mem_set (as : Array α) (i : Nat) (h : i < as.size) (a : α) :
783+
a ∈ as.set i a := by
778784
simp [mem_iff_getElem]
779-
exact ⟨n, (by simpa using h), by simp⟩
785+
exact ⟨i, (by simpa using h), by simp⟩
780786

781787
theorem mem_or_eq_of_mem_set
782-
{as : Array α} {n : Nat} {a b : α} {w : n < as.size} (h : a ∈ as.set n b) : a ∈ as ∨ a = b := by
788+
{as : Array α} {i : Nat} {a b : α} {w : i < as.size} (h : a ∈ as.set i b) : a ∈ as ∨ a = b := by
783789
cases as
784790
simpa using List.mem_or_eq_of_mem_set (by simpa using h)
785791

@@ -788,7 +794,10 @@ theorem mem_or_eq_of_mem_set
788794

789795
/-! ### setIfInBounds -/
790796

791-
@[simp] theorem set!_is_setIfInBounds : @set! = @setIfInBounds := rfl
797+
@[simp] theorem set!_eq_setIfInBounds : @set! = @setIfInBounds := rfl
798+
799+
@[deprecated set!_eq_setIfInBounds (since := "2024-12-12")]
800+
abbrev set!_is_setIfInBounds := @set!_eq_setIfInBounds
792801

793802
@[simp] theorem size_setIfInBounds (as : Array α) (index : Nat) (val : α) :
794803
(as.setIfInBounds index val).size = as.size := by
@@ -820,19 +829,23 @@ abbrev getElem_setIfInBounds_eq := @getElem_setIfInBounds_self
820829
(as.setIfInBounds i v)[j]'hj = as[j]'(by simpa using hj) := by
821830
simp [getElem_setIfInBounds, h]
822831

832+
theorem getElem?_setIfInBounds {as : Array α} {i j : Nat} {a : α} :
833+
(as.setIfInBounds i a)[j]? = if i = j then if i < as.size then some a else none else as[j]? := by
834+
cases as
835+
simp [List.getElem?_set]
836+
837+
theorem getElem?_setIfInBounds_self (as : Array α) {i : Nat} (v : α) :
838+
(as.setIfInBounds i v)[i]? = if i < as.size then some v else none := by
839+
simp [getElem?_setIfInBounds]
840+
823841
@[simp]
824-
theorem getElem?_setIfInBounds_self (as : Array α) {i : Nat} (p : i < as.size) (v : α) :
842+
theorem getElem?_setIfInBounds_self_of_lt (as : Array α) {i : Nat} (v : α) (h : i < as.size) :
825843
(as.setIfInBounds i v)[i]? = some v := by
826-
simp [getElem?_eq_getElem, p]
844+
simp [getElem?_setIfInBounds, h]
827845

828846
@[deprecated getElem?_setIfInBounds_self (since := "2024-12-11")]
829847
abbrev getElem?_setIfInBounds_eq := @getElem?_setIfInBounds_self
830848

831-
theorem getElem?_setIfInBounds {as : Array α} {i j : Nat} {a : α} :
832-
(as.setIfInBounds i a)[j]? = if i = j then if i < as.size then some a else none else as[j]? := by
833-
cases as
834-
simp [List.getElem?_set]
835-
836849
@[simp] theorem getElem?_setIfInBounds_ne {as : Array α} {i j : Nat} (h : i ≠ j) {a : α} :
837850
(as.setIfInBounds i a)[j]? = as[j]? := by
838851
simp [getElem?_setIfInBounds, h]
@@ -847,24 +860,24 @@ theorem setIfInBounds_eq_of_size_le {l : Array α} {n : Nat} (h : l.size ≤ n)
847860
cases as <;> cases n <;> simp
848861

849862
theorem setIfInBounds_comm (a b : α)
850-
{n m : Nat} (as : Array α) (h : nm) :
851-
(as.setIfInBounds n a).setIfInBounds m b = (as.setIfInBounds m b).setIfInBounds n a := by
863+
{i j : Nat} (as : Array α) (h : ij) :
864+
(as.setIfInBounds i a).setIfInBounds j b = (as.setIfInBounds j b).setIfInBounds i a := by
852865
cases as
853866
simp [List.set_comm _ _ _ h]
854867

855868
@[simp]
856-
theorem setIfInBounds_setIfInBounds (a b : α) (as : Array α) (n : Nat) :
857-
(as.setIfInBounds n a).setIfInBounds n b = as.setIfInBounds n b := by
869+
theorem setIfInBounds_setIfInBounds (a b : α) (as : Array α) (i : Nat) :
870+
(as.setIfInBounds i a).setIfInBounds i b = as.setIfInBounds i b := by
858871
cases as
859872
simp
860873

861-
theorem mem_setIfInBounds (as : Array α) (n : Nat) (h : n < as.size) (a : α) :
862-
a ∈ as.setIfInBounds n a := by
874+
theorem mem_setIfInBounds (as : Array α) (i : Nat) (h : i < as.size) (a : α) :
875+
a ∈ as.setIfInBounds i a := by
863876
simp [mem_iff_getElem]
864-
exact ⟨n, (by simpa using h), by simp⟩
877+
exact ⟨i, (by simpa using h), by simp⟩
865878

866879
theorem mem_or_eq_of_mem_setIfInBounds
867-
{as : Array α} {n : Nat} {a b : α} (h : a ∈ as.setIfInBounds n b) : a ∈ as ∨ a = b := by
880+
{as : Array α} {i : Nat} {a b : α} (h : a ∈ as.setIfInBounds i b) : a ∈ as ∨ a = b := by
868881
cases as
869882
simpa using List.mem_or_eq_of_mem_set (by simpa using h)
870883

@@ -2395,7 +2408,7 @@ abbrev get?_eq_toList_get? := @get?_eq_get?_toList
23952408
@[deprecated eq_push_pop_back!_of_size_ne_zero (since := "2024-10-31")]
23962409
abbrev eq_push_pop_back_of_size_ne_zero := @eq_push_pop_back!_of_size_ne_zero
23972410

2398-
@[deprecated set!_is_setIfInBounds (since := "2024-11-24")] abbrev set_is_setIfInBounds := @set!_is_setIfInBounds
2411+
@[deprecated set!_is_setIfInBounds (since := "2024-11-24")] abbrev set_is_setIfInBounds := @set!_eq_setIfInBounds
23992412
@[deprecated size_setIfInBounds (since := "2024-11-24")] abbrev size_setD := @size_setIfInBounds
24002413
@[deprecated getElem_setIfInBounds_eq (since := "2024-11-24")] abbrev getElem_setD_eq := @getElem_setIfInBounds_self
24012414
@[deprecated getElem?_setIfInBounds_eq (since := "2024-11-24")] abbrev get?_setD_eq := @getElem?_setIfInBounds_self

0 commit comments

Comments
 (0)