Skip to content

Commit 969fb38

Browse files
Update lean-toolchain for leanprover/lean4#10524
2 parents ade3a03 + 8a9e7f9 commit 969fb38

File tree

8 files changed

+252
-134
lines changed

8 files changed

+252
-134
lines changed

Batteries/Data/Fin/Lemmas.lean

Lines changed: 121 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,26 @@ Authors: Mario Carneiro
55
-/
66
import Batteries.Data.Fin.Basic
77
import Batteries.Util.ProofWanted
8+
import Batteries.Tactic.Alias
89

910
namespace Fin
1011

1112
attribute [norm_cast] val_last
1213

14+
/-! ### foldl/foldr -/
15+
16+
theorem foldl_assoc {op : α → α → α} [ha : Std.Associative op] {f : Fin n → α} {a₁ a₂} :
17+
foldl n (fun x i => op x (f i)) (op a₁ a₂) = op a₁ (foldl n (fun x i => op x (f i)) a₂) := by
18+
induction n generalizing a₂ with
19+
| zero => rfl
20+
| succ n ih => simp only [foldl_succ, ha.assoc, ih]
21+
22+
theorem foldr_assoc {op : α → α → α} [ha : Std.Associative op] {f : Fin n → α} {a₁ a₂} :
23+
foldr n (fun i x => op (f i) x) (op a₁ a₂) = op (foldr n (fun i x => op (f i) x) a₁) a₂ := by
24+
induction n generalizing a₂ with
25+
| zero => rfl
26+
| succ n ih => simp only [foldr_succ, ha.assoc, ih]
27+
1328
/-! ### clamp -/
1429

1530
@[simp] theorem coe_clamp (n m : Nat) : (clamp n m : Nat) = min n m := rfl
@@ -21,14 +36,9 @@ attribute [norm_cast] val_last
2136
@[simp] theorem findSome?_one {f : Fin 1 → Option α} : findSome? f = f 0 := rfl
2237

2338
theorem findSome?_succ {f : Fin (n+1) → Option α} :
24-
findSome? f = (f 0 <|> findSome? fun i => f i.succ) := by
25-
simp only [findSome?, foldl_succ]
26-
cases f 0
27-
· rw [Option.orElse_eq_orElse, Option.orElse_none, Option.orElse_none]
28-
· simp only [Option.orElse_some, Option.orElse_eq_orElse, Option.orElse_none]
29-
induction n with
30-
| zero => rfl
31-
| succ n ih => rw [foldl_succ, Option.orElse_some, ih (f := fun i => f i.succ)]
39+
findSome? f = (f 0).or (findSome? fun i => f i.succ) := by
40+
simp only [findSome?, foldl_succ, Option.orElse_eq_orElse, Option.orElse_eq_or]
41+
exact Eq.trans (by cases (f 0) <;> rfl) foldl_assoc
3242

3343
theorem findSome?_succ_of_some {f : Fin (n+1) → Option α} (h : f 0 = some x) :
3444
findSome? f = some x := by simp [findSome?_succ, h]
@@ -42,68 +52,67 @@ theorem findSome?_succ_of_none {f : Fin (n+1) → Option α} (h : f 0 = none) :
4252
theorem findSome?_succ_of_isNone {f : Fin (n+1) → Option α} (h : (f 0).isNone) :
4353
findSome? f = findSome? fun i => f i.succ := by simp_all [findSome?_succ_of_none]
4454

45-
theorem exists_of_findSome?_eq_some {f : Fin n → Option α} (h : findSome? f = some x) :
46-
∃ i, f i = some x := by
55+
@[simp, grind =]
56+
theorem findSome?_eq_some_iff {f : Fin n → Option α} :
57+
findSome? f = some a ↔ ∃ i, f i = some a ∧ ∀ j < i, f j = none := by
4758
induction n with
48-
| zero => rw [findSome?_zero] at h; contradiction
59+
| zero =>
60+
simp only [findSome?_zero, (Option.some_ne_none _).symm, false_iff]
61+
exact fun ⟨i, _⟩ => i.elim0
4962
| succ n ih =>
50-
rw [findSome?_succ] at h
51-
match heq : f 0 with
52-
| some x =>
53-
rw [heq, Option.orElse_eq_orElse, Option.orElse_some] at h
54-
exists 0
55-
rw [heq, h]
56-
| none =>
57-
rw [heq, Option.orElse_eq_orElse, Option.orElse_none] at h
58-
match ih h with | ⟨i, _⟩ => exists i.succ
63+
simp only [findSome?_succ, Option.or_eq_some_iff, Fin.exists_fin_succ, Fin.forall_fin_succ,
64+
not_lt_zero, false_implies, implies_true, and_true, succ_lt_succ_iff, succ_pos,
65+
forall_const, ih, and_left_comm (b := f 0 = none), exists_and_left]
5966

60-
theorem eq_none_of_findSome?_eq_none {f : Fin n → Option α} (h : findSome? f = none) (i) :
61-
f i = none := by
67+
@[simp, grind =] theorem findSome?_eq_none_iff {f : Fin n → Option α} :
68+
findSome? f = none ↔ ∀ i, f i = none := by
6269
induction n with
63-
| zero => cases i; contradiction
70+
| zero =>
71+
simp only [findSome?_zero, true_iff]
72+
exact fun i => i.elim0
6473
| succ n ih =>
65-
rw [findSome?_succ] at h
66-
match heq : f 0 with
67-
| some x =>
68-
rw [heq, Option.orElse_eq_orElse, Option.orElse_some] at h
69-
contradiction
70-
| none =>
71-
rw [heq, Option.orElse_eq_orElse, Option.orElse_none] at h
72-
cases i using Fin.cases with
73-
| zero => exact heq
74-
| succ i => exact ih h i
75-
76-
@[simp] theorem findSome?_isSome_iff {f : Fin n → Option α} :
77-
(findSome? f).isSome ↔ ∃ i, (f i).isSome := by
78-
simp only [Option.isSome_iff_exists]
79-
constructor
80-
· intro ⟨x, hx⟩
81-
match exists_of_findSome?_eq_some hx with
82-
| ⟨i, hi⟩ => exists i, x
83-
· intro ⟨i, x, hix⟩
84-
match h : findSome? f with
85-
| some x => exists x
86-
| none => rw [eq_none_of_findSome?_eq_none h i] at hix; contradiction
87-
88-
@[simp] theorem findSome?_eq_none_iff {f : Fin n → Option α} :
89-
findSome? f = none ↔ ∀ i, f i = none := by
90-
constructor
91-
· exact eq_none_of_findSome?_eq_none
92-
· intro hf
93-
match h : findSome? f with
94-
| none => rfl
95-
| some x =>
96-
match exists_of_findSome?_eq_some h with
97-
| ⟨i, h⟩ => rw [hf] at h; contradiction
98-
99-
theorem findSome?_isNone_iff {f : Fin n → Option α} :
74+
simp only [findSome?_succ, Option.or_eq_none_iff, ih, forall_fin_succ]
75+
76+
theorem isNone_findSome?_iff {f : Fin n → Option α} :
10077
(findSome? f).isNone ↔ ∀ i, (f i).isNone := by simp
10178

79+
@[deprecated (since := "2025-09-28")]
80+
alias findSome?_isNone_iff := isNone_findSome?_iff
81+
82+
@[simp] theorem isSome_findSome?_iff {f : Fin n → Option α} :
83+
(findSome? f).isSome ↔ ∃ i, (f i).isSome := by
84+
cases h : findSome? f with (simp only [findSome?_eq_none_iff, findSome?_eq_some_iff] at h; grind)
85+
86+
@[deprecated (since := "2025-09-28")]
87+
alias findSome?_isSome_iff := isSome_findSome?_iff
88+
89+
theorem exists_minimal_of_findSome?_eq_some {f : Fin n → Option α}
90+
(h : findSome? f = some x) : ∃ i, f i = some x ∧ ∀ j < i, f j = none :=
91+
findSome?_eq_some_iff.1 h
92+
93+
theorem exists_eq_some_of_findSome?_eq_some {f : Fin n → Option α}
94+
(h : findSome? f = some x) : ∃ i, f i = some x := by grind
95+
96+
@[deprecated (since := "2025-09-28")]
97+
alias exists_of_findSome?_eq_some := exists_eq_some_of_findSome?_eq_some
98+
99+
theorem eq_none_of_findSome?_eq_none {f : Fin n → Option α} (h : findSome? f = none) (i) :
100+
f i = none := findSome?_eq_none_iff.1 h i
101+
102+
theorem exists_isSome_of_isSome_findSome? {f : Fin n → Option α} (h : (findSome? f).isSome) :
103+
∃ i, (f i).isSome := isSome_findSome?_iff.1 h
104+
105+
theorem isNone_of_isNone_findSome? {f : Fin n → Option α} (h : (findSome? f).isNone) :
106+
(f i).isNone := isNone_findSome?_iff.1 h i
107+
108+
theorem isSome_findSome?_of_isSome {f : Fin n → Option α} (h : (f i).isSome) :
109+
(findSome? f).isSome := isSome_findSome?_iff.2 ⟨_, h⟩
110+
102111
theorem map_findSome? (f : Fin n → Option α) (g : α → β) :
103-
(findSome? f).map g = findSome? (Option.map g ∘ f) := by
112+
(findSome? f).map g = findSome? (Option.map g <| f ·) := by
104113
induction n with
105114
| zero => rfl
106-
| succ n ih => simp [findSome?_succ, Function.comp_def, Option.map_or, ih]
115+
| succ n ih => simp [findSome?_succ, Option.map_or, ih]
107116

108117
theorem findSome?_guard {p : Fin n → Bool} : findSome? (Option.guard p) = find? p := rfl
109118

@@ -123,38 +132,62 @@ theorem findSome?_eq_findSome?_finRange (f : Fin n → Option α) :
123132

124133
theorem find?_succ {p : Fin (n+1) → Bool} :
125134
find? p = if p 0 then some 0 else (find? fun i => p i.succ).map Fin.succ := by
126-
simp only [find?, findSome?_succ, Option.guard]
127-
split <;> simp [map_findSome?, Function.comp_def, Option.guard]
135+
simp only [find?, findSome?_succ, Option.guard, fun a => apply_ite (Option.or · a),
136+
Option.some_or, Option.none_or, map_findSome?, Option.map_if]
128137

129-
theorem eq_true_of_find?_eq_some {p : Fin n → Bool} (h : find? p = some i) : p i = true := by
130-
match exists_of_findSome?_eq_some h with
131-
| ⟨i, hi⟩ =>
132-
simp only [Option.guard] at hi
133-
split at hi
134-
· cases hi; assumption
135-
· contradiction
138+
@[simp, grind =]
139+
theorem find?_eq_some_iff {p : Fin n → Bool} :
140+
find? p = some i ↔ p i ∧ ∀ j, j < i → p j = false := by simp [find?, and_assoc]
136141

137-
theorem eq_false_of_find?_eq_none {p : Fin n → Bool} (h : find? p = none) (i) : p i = false := by
138-
have hi := eq_none_of_findSome?_eq_none h i
139-
simp only [Option.guard] at hi
140-
split at hi
141-
· contradiction
142-
· simp [*]
142+
theorem isSome_find?_iff {p : Fin n → Bool} :
143+
(find? p).isSome ↔ ∃ i, p i := by simp [find?]
143144

144-
theorem find?_isSome_iff {p : Fin n → Bool} : (find? p).isSome ↔ ∃ i, p i := by
145-
simp [find?]
145+
@[deprecated (since := "2025-09-28")]
146+
alias find?_isSome_iff := isSome_find?_iff
146147

147-
theorem find?_isNone_iff {p : Fin n → Bool} : (find? p).isNone ↔ ∀ i, ¬ p i := by
148-
simp [find?]
148+
@[simp, grind =]
149+
theorem find?_eq_none_iff {p : Fin n → Bool} : find? p = none ↔ ∀ i, p i = false := by simp [find?]
149150

150-
proof_wanted find?_eq_some_iff {p : Fin n → Bool} : find? p = some i ↔ p i ∧ ∀ j, j < i → ¬ p j
151+
theorem isNone_find?_iff {p : Fin n → Bool} : (find? p).isNone ↔ ∀ i, p i = false := by simp [find?]
151152

152-
theorem find?_eq_none_iff {p : Fin n → Bool} : find? p = none ↔ ∀ i, ¬ p i := by
153-
rw [← find?_isNone_iff, Option.isNone_iff_eq_none]
153+
@[deprecated (since := "2025-09-28")]
154+
alias find?_isNone_iff := isNone_find?_iff
154155

155-
theorem find?_eq_find?_finRange {p : Fin n → Bool} : find? p = (List.finRange n).find? p := by
156-
induction n with
157-
| zero => rfl
158-
| succ n ih =>
159-
rw [find?_succ, List.finRange_succ, List.find?_cons]
160-
split <;> simp [Function.comp_def, *]
156+
theorem eq_true_of_find?_eq_some {p : Fin n → Bool} (h : find? p = some i) : p i :=
157+
(find?_eq_some_iff.mp h).1
158+
159+
theorem eq_false_of_find?_eq_some_of_lt {p : Fin n → Bool} (h : find? p = some i) :
160+
∀ j < i, p j = false := (find?_eq_some_iff.mp h).2
161+
162+
theorem eq_false_of_find?_eq_none {p : Fin n → Bool} (h : find? p = none) (i) :
163+
p i = false := find?_eq_none_iff.1 h i
164+
165+
theorem exists_eq_true_of_isSome_find? {p : Fin n → Bool} (h : (find? p).isSome) :
166+
∃ i, p i := isSome_find?_iff.1 h
167+
168+
theorem eq_false_of_isNone_find? {p : Fin n → Bool} (h : (find? p).isNone) : p i = false :=
169+
isNone_find?_iff.1 h i
170+
171+
theorem isSome_find?_of_eq_true {p : Fin n → Bool} (h : p i) :
172+
(find? p).isSome := isSome_find?_iff.2 ⟨_, h⟩
173+
174+
theorem get_find?_eq_true {p : Fin n → Bool} (h : (find? p).isSome) : p ((find? p).get h) :=
175+
eq_true_of_find?_eq_some (Option.some_get _).symm
176+
177+
theorem get_find?_minimal {p : Fin n → Bool} (h : (find? p).isSome) :
178+
∀ j, j < (find? p).get h → p j = false :=
179+
eq_false_of_find?_eq_some_of_lt (Option.some_get _).symm
180+
181+
theorem find?_eq_find?_finRange {p : Fin n → Bool} : find? p = (List.finRange n).find? p :=
182+
(findSome?_eq_findSome?_finRange _).trans (List.findSome?_guard)
183+
184+
/-! ### exists -/
185+
186+
theorem exists_eq_true_iff_exists_minimal_eq_true (p : Fin n → Bool):
187+
(∃ i, p i) ↔ ∃ i, p i ∧ ∀ j < i, p j = false := by
188+
cases h : find? p <;> grind
189+
190+
theorem exists_iff_exists_minimal (p : Fin n → Prop) [DecidablePred p] :
191+
(∃ i, p i) ↔ ∃ i, p i ∧ ∀ j < i, ¬ p j := by
192+
simpa only [decide_eq_true_iff, decide_eq_false_iff_not] using
193+
exists_eq_true_iff_exists_minimal_eq_true (p ·)

Batteries/Data/List/Basic.lean

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -555,29 +555,55 @@ pwFilter (·<·) [0, 1, 5, 2, 6, 3, 4] = [0, 1, 2, 3, 4]
555555
def pwFilter (R : α → α → Prop) [DecidableRel R] (l : List α) : List α :=
556556
l.foldr (fun x IH => if ∀ y ∈ IH, R x y then x :: IH else IH) []
557557

558-
section Chain
558+
/-- `IsChain R l` means that `R` holds between adjacent elements of `l`.
559+
```
560+
IsChain R [a, b, c, d] ↔ R a b ∧ R b c ∧ R c d
561+
``` -/
562+
inductive IsChain (R : α → α → Prop) : List α → Prop where
563+
/-- A list of length 0 is a chain. -/
564+
| nil : IsChain R []
565+
/-- A list of length 1 is a chain. -/
566+
| singleton (a : α) : IsChain R [a]
567+
/-- If `a` relates to `b` and `b::l` is a chain, then `a :: b :: l` is also a chain. -/
568+
| cons_cons (hr : R a b) (h : IsChain R (b :: l)) : IsChain R (a :: b :: l)
569+
570+
attribute [simp, grind ←] IsChain.nil
571+
attribute [simp, grind ←] IsChain.singleton
572+
573+
@[simp, grind =] theorem isChain_cons_cons : IsChain R (a :: b :: l) ↔ R a b ∧ IsChain R (b :: l) :=
574+
fun | .cons_cons hr h => ⟨hr, h⟩, fun ⟨hr, h⟩ => .cons_cons hr h⟩
559575

560-
variable (R : α → α → Prop)
576+
instance instDecidableIsChain {R : α → α → Prop} [h : DecidableRel R] (l : List α) :
577+
Decidable (l.IsChain R) := match l with | [] => isTrue .nil | a :: l => go a l
578+
where
579+
go (a : α) (l : List α) : Decidable ((a :: l).IsChain R) :=
580+
match l with
581+
| [] => isTrue <| .singleton a
582+
| b :: l => haveI := (go b l); decidable_of_iff' _ isChain_cons_cons
561583

562584
/-- `Chain R a l` means that `R` holds between adjacent elements of `a::l`.
563585
```
564586
Chain R a [b, c, d] ↔ R a b ∧ R b c ∧ R c d
565587
``` -/
566-
inductive Chain : α → List α → Prop
567-
/-- A chain of length 1 is trivially a chain. -/
568-
| nil {a : α} : Chain a []
569-
/-- If `a` relates to `b` and `b::l` is a chain, then `a :: b :: l` is also a chain. -/
570-
| cons : ∀ {a b : α} {l : List α}, R a b → Chain b l → Chain a (b :: l)
588+
@[deprecated IsChain (since := "2025-09-19")]
589+
def Chain : (α → α → Prop) → α → List α → Prop := (IsChain · <| · :: ·)
590+
591+
set_option linter.deprecated false in
592+
/-- A list of length 1 is a chain. -/
593+
@[deprecated IsChain.singleton (since := "2025-09-19")]
594+
theorem Chain.nil {a : α} : Chain R a [] := IsChain.singleton a
595+
596+
set_option linter.deprecated false in
597+
/-- If `a` relates to `b` and `b::l` is a chain, then `a :: b :: l` is also a chain. -/
598+
@[deprecated IsChain.cons_cons (since := "2025-09-19")]
599+
theorem Chain.cons : R a b → Chain R b l → Chain R a (b :: l) := IsChain.cons_cons
571600

572601
/-- `Chain' R l` means that `R` holds between adjacent elements of `l`.
573602
```
574603
Chain' R [a, b, c, d] ↔ R a b ∧ R b c ∧ R c d
575604
``` -/
576-
def Chain' : List α → Prop
577-
| [] => True
578-
| a :: l => Chain R a l
579-
580-
end Chain
605+
@[deprecated IsChain (since := "2025-09-19")]
606+
def Chain' : (α → α → Prop) → List α → Prop := (IsChain · ·)
581607

582608
/-- `eraseDup l` removes duplicates from `l` (taking only the first occurrence).
583609
Defined as `pwFilter (≠)`.

0 commit comments

Comments
 (0)