Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 2541387

Browse files
committed
refactor(data/list/big_operators): review API (#12782)
* merge `prod_monoid` into `big_operators`; * review typeclass assumptions in some lemmas; * use `to_additive` in more lemmas.
1 parent 241d63d commit 2541387

File tree

4 files changed

+120
-125
lines changed

4 files changed

+120
-125
lines changed

src/algebra/big_operators/multiset.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Mario Carneiro
55
-/
66
import algebra.group_with_zero.power
7-
import data.list.prod_monoid
7+
import data.list.big_operators
88
import data.multiset.basic
99

1010
/-!

src/algebra/graded_monoid.lean

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ Authors: Eric Wieser
55
-/
66
import algebra.group.inj_surj
77
import data.list.big_operators
8-
import data.list.prod_monoid
98
import data.list.range
109
import group_theory.group_action.defs
1110
import group_theory.submonoid.basic

src/data/list/big_operators.lean

Lines changed: 119 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/-
22
Copyright (c) 2017 Johannes Hölzl. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
4-
Authors: Johannes Hölzl, Floris van Doorn, Sébastien Gouëzel
4+
Authors: Johannes Hölzl, Floris van Doorn, Sébastien Gouëzel, Alex J. Best
55
-/
66
import data.list.basic
77

@@ -41,10 +41,24 @@ by rw [concat_eq_append, prod_append, prod_singleton]
4141
@[simp, to_additive]
4242
lemma prod_join {l : list (list M)} : l.join.prod = (l.map list.prod).prod :=
4343
by induction l; [refl, simp only [*, list.join, map, prod_append, prod_cons]]
44+
4445
@[to_additive]
4546
lemma prod_eq_foldr : l.prod = foldr (*) 1 l :=
4647
list.rec_on l rfl $ λ a l ihl, by rw [prod_cons, foldr_cons, ihl]
4748

49+
@[simp, priority 500, to_additive]
50+
theorem prod_repeat (a : M) (n : ℕ) : (repeat a n).prod = a ^ n :=
51+
begin
52+
induction n with n ih,
53+
{ rw pow_zero, refl },
54+
{ rw [list.repeat_succ, list.prod_cons, ih, pow_succ] }
55+
end
56+
57+
@[to_additive sum_eq_card_nsmul]
58+
lemma prod_eq_pow_card (l : list M) (m : M) (h : ∀ (x ∈ l), x = m) :
59+
l.prod = m ^ l.length :=
60+
by rw [← prod_repeat, ← list.eq_repeat.mpr ⟨rfl, h⟩]
61+
4862
@[to_additive]
4963
lemma prod_hom_rel (l : list ι) {r : M → N → Prop} {f : ι → M} {g : ι → N} (h₁ : r 1 1)
5064
(h₂ : ∀ ⦃i a b⦄, r a b → r (f i * a) (g i * b)) :
@@ -102,7 +116,7 @@ lemma prod_take_succ :
102116
| (h :: t) (n+1) _ := by { dsimp, rw [prod_cons, prod_cons, prod_take_succ, mul_assoc] }
103117

104118
/-- A list with product not one must have positive length. -/
105-
@[to_additive]
119+
@[to_additive "A list with sum not zero must have positive length."]
106120
lemma length_pos_of_prod_ne_one (L : list M) (h : L.prod ≠ 1) : 0 < L.length :=
107121
by { cases L, { simp at h, cases h }, { simp } }
108122

@@ -120,17 +134,100 @@ open mul_opposite
120134
inhabited instance to return a garbage value on the empty list, this is not possible.
121135
Instead, we write the statement in terms of `(L.nth 0).get_or_else 1`.
122136
-/
123-
@[to_additive]
137+
@[to_additive "We'd like to state this as `L.head + L.tail.sum = L.sum`, but because `L.head`
138+
relies on an inhabited instance to return a garbage value on the empty list, this is not possible.
139+
Instead, we write the statement in terms of `(L.nth 0).get_or_else 0`."]
124140
lemma nth_zero_mul_tail_prod (l : list M) : (l.nth 0).get_or_else 1 * l.tail.prod = l.prod :=
125141
by cases l; simp
126142

127143
/-- Same as `nth_zero_mul_tail_prod`, but avoiding the `list.head` garbage complication by requiring
128144
the list to be nonempty. -/
129-
@[to_additive]
145+
@[to_additive "Same as `nth_zero_add_tail_sum`, but avoiding the `list.head` garbage complication
146+
by requiring the list to be nonempty."]
130147
lemma head_mul_tail_prod_of_ne_nil [inhabited M] (l : list M) (h : l ≠ []) :
131148
l.head * l.tail.prod = l.prod :=
132149
by cases l; [contradiction, simp]
133150

151+
@[to_additive]
152+
lemma prod_commute (l : list M) (y : M) (h : ∀ (x ∈ l), commute y x) : commute y l.prod :=
153+
begin
154+
induction l with z l IH,
155+
{ simp },
156+
{ rw list.ball_cons at h,
157+
rw list.prod_cons,
158+
exact commute.mul_right h.1 (IH h.2), }
159+
end
160+
161+
@[to_additive sum_le_sum] lemma prod_le_prod' [preorder M]
162+
[covariant_class M M (function.swap (*)) (≤)] [covariant_class M M (*) (≤)]
163+
{l : list ι} {f g : ι → M} (h : ∀ i ∈ l, f i ≤ g i) :
164+
(l.map f).prod ≤ (l.map g).prod :=
165+
begin
166+
induction l with i l ihl, { refl },
167+
rw forall_mem_cons at h,
168+
simpa using mul_le_mul' h.1 (ihl h.2)
169+
end
170+
171+
@[to_additive sum_lt_sum] lemma prod_lt_prod'
172+
[preorder M] [covariant_class M M (*) (<)] [covariant_class M M (*) (≤)]
173+
[covariant_class M M (function.swap (*)) (<)] [covariant_class M M (function.swap (*)) (≤)]
174+
{l : list ι} (f g : ι → M) (h₁ : ∀ i ∈ l, f i ≤ g i) (h₂ : ∃ i ∈ l, f i < g i) :
175+
(l.map f).prod < (l.map g).prod :=
176+
begin
177+
induction l with i l ihl, { rcases h₂ with ⟨_, ⟨⟩, _⟩ },
178+
simp only [ball_cons, bex_cons, map_cons, prod_cons] at h₁ h₂ ⊢,
179+
cases h₂,
180+
exacts [mul_lt_mul_of_lt_of_le h₂ (prod_le_prod' h₁.2),
181+
mul_lt_mul_of_le_of_lt h₁.1 $ ihl h₁.2 h₂]
182+
end
183+
184+
@[to_additive] lemma prod_lt_prod_of_ne_nil
185+
[preorder M] [covariant_class M M (*) (<)] [covariant_class M M (*) (≤)]
186+
[covariant_class M M (function.swap (*)) (<)] [covariant_class M M (function.swap (*)) (≤)]
187+
{l : list ι} (hl : l ≠ []) (f g : ι → M) (hlt : ∀ i ∈ l, f i < g i) :
188+
(l.map f).prod < (l.map g).prod :=
189+
prod_lt_prod' f g (λ i hi, (hlt i hi).le) $ (exists_mem_of_ne_nil l hl).imp $ λ i hi, ⟨hi, hlt i hi⟩
190+
191+
@[to_additive sum_le_card_nsmul]
192+
lemma prod_le_pow_card [preorder M]
193+
[covariant_class M M (function.swap (*)) (≤)] [covariant_class M M (*) (≤)]
194+
(l : list M) (n : M) (h : ∀ (x ∈ l), x ≤ n) :
195+
l.prod ≤ n ^ l.length :=
196+
by simpa only [map_id'', map_const, prod_repeat] using prod_le_prod' h
197+
198+
@[to_additive card_nsmul_le_sum]
199+
lemma pow_card_le_prod [preorder M]
200+
[covariant_class M M (function.swap (*)) (≤)] [covariant_class M M (*) (≤)]
201+
(l : list M) (n : M) (h : ∀ (x ∈ l), n ≤ x) :
202+
n ^ l.length ≤ l.prod :=
203+
@prod_le_pow_card (order_dual M) _ _ _ _ l n h
204+
205+
@[to_additive exists_lt_of_sum_lt] lemma exists_lt_of_prod_lt' [linear_order M]
206+
[covariant_class M M (function.swap (*)) (≤)] [covariant_class M M (*) (≤)] {l : list ι}
207+
(f g : ι → M) (h : (l.map f).prod < (l.map g).prod) :
208+
∃ i ∈ l, f i < g i :=
209+
by { contrapose! h, exact prod_le_prod' h }
210+
211+
@[to_additive exists_le_of_sum_le]
212+
lemma exists_le_of_prod_le' [linear_order M] [covariant_class M M (*) (<)]
213+
[covariant_class M M (*) (≤)] [covariant_class M M (function.swap (*)) (<)]
214+
[covariant_class M M (function.swap (*)) (≤)] {l : list ι} (hl : l ≠ [])
215+
(f g : ι → M) (h : (l.map f).prod ≤ (l.map g).prod) :
216+
∃ x ∈ l, f x ≤ g x :=
217+
by { contrapose! h, exact prod_lt_prod_of_ne_nil hl _ _ h }
218+
219+
@[to_additive sum_nonneg]
220+
lemma one_le_prod_of_one_le [preorder M] [covariant_class M M (*) (≤)] {l : list M}
221+
(hl₁ : ∀ x ∈ l, (1 : M) ≤ x) :
222+
1 ≤ l.prod :=
223+
begin
224+
-- We don't use `pow_card_le_prod` to avoid assumption
225+
-- [covariant_class M M (function.swap (*)) (≤)]
226+
induction l with hd tl ih, { refl },
227+
rw prod_cons,
228+
exact one_le_mul (hl₁ hd (mem_cons_self hd tl)) (ih (λ x h, hl₁ x (mem_cons_of_mem hd h)))
229+
end
230+
134231
end monoid
135232

136233
section monoid_with_zero
@@ -214,34 +311,25 @@ end
214311

215312
end comm_group
216313

217-
lemma eq_of_sum_take_eq [add_left_cancel_monoid M] {L L' : list M} (h : L.length = L'.length)
218-
(h' : ∀ i ≤ L.length, (L.take i).sum = (L'.take i).sum) : L = L' :=
314+
@[to_additive]
315+
lemma eq_of_prod_take_eq [left_cancel_monoid M] {L L' : list M} (h : L.length = L'.length)
316+
(h' : ∀ i ≤ L.length, (L.take i).prod = (L'.take i).prod) : L = L' :=
219317
begin
220318
apply ext_le h (λ i h₁ h₂, _),
221-
have : (L.take (i + 1)).sum = (L'.take (i + 1)).sum := h' _ (nat.succ_le_of_lt h₁),
222-
rw [sum_take_succ L i h₁, sum_take_succ L' i h₂, h' i (le_of_lt h₁)] at this,
223-
exact add_left_cancel this
319+
have : (L.take (i + 1)).prod = (L'.take (i + 1)).prod := h' _ (nat.succ_le_of_lt h₁),
320+
rw [prod_take_succ L i h₁, prod_take_succ L' i h₂, h' i (le_of_lt h₁)] at this,
321+
convert mul_left_cancel this
224322
end
225323

226-
lemma monotone_sum_take [canonically_ordered_add_monoid M] (L : list M) :
227-
monotone (λ i, (L.take i).sum) :=
324+
@[to_additive]
325+
lemma monotone_prod_take [canonically_ordered_monoid M] (L : list M) :
326+
monotone (λ i, (L.take i).prod) :=
228327
begin
229328
apply monotone_nat_of_le_succ (λ n, _),
230-
by_cases h : n < L.length,
231-
{ rw sum_take_succ _ _ h,
232-
exact le_self_add },
233-
{ push_neg at h,
234-
simp [take_all_of_le h, take_all_of_le (le_trans h (nat.le_succ _))] }
235-
end
236-
237-
@[to_additive sum_nonneg]
238-
lemma one_le_prod_of_one_le [ordered_comm_monoid M] {l : list M} (hl₁ : ∀ x ∈ l, (1 : M) ≤ x) :
239-
1 ≤ l.prod :=
240-
begin
241-
induction l with hd tl ih,
242-
{ simp },
243-
rw prod_cons,
244-
exact one_le_mul (hl₁ hd (mem_cons_self hd tl)) (ih (λ x h, hl₁ x (mem_cons_of_mem hd h))),
329+
cases lt_or_le n L.length with h h,
330+
{ rw prod_take_succ _ _ h,
331+
exact le_self_mul },
332+
{ simp [take_all_of_le h, take_all_of_le (le_trans h (nat.le_succ _))] }
245333
end
246334

247335
@[to_additive sum_pos]
@@ -275,8 +363,7 @@ lemma all_one_of_le_one_le_of_prod_eq_one [ordered_comm_monoid M]
275363
x = 1 :=
276364
le_antisymm (hl₂ ▸ single_le_prod hl₁ _ hx) (hl₁ x hx)
277365

278-
@[to_additive]
279-
lemma prod_eq_one_iff [canonically_ordered_monoid M] (l : list M) :
366+
@[to_additive] lemma prod_eq_one_iff [canonically_ordered_monoid M] (l : list M) :
280367
l.prod = 1 ↔ ∀ x ∈ l, x = (1 : M) :=
281368
⟨all_one_of_le_one_le_of_prod_eq_one (λ _ _, one_le _),
282369
begin
@@ -310,14 +397,8 @@ lemma sum_le_foldr_max [add_monoid M] [add_monoid N] [linear_order N] (f : M →
310397
begin
311398
induction l with hd tl IH,
312399
{ simpa using h0 },
313-
simp only [list.sum_cons, list.foldr_map, le_max_iff, list.foldr] at IH ⊢,
314-
cases le_or_lt (f tl.sum) (f hd),
315-
{ left,
316-
refine (hadd _ _).trans _,
317-
simpa using h },
318-
{ right,
319-
refine (hadd _ _).trans _,
320-
simp only [IH, max_le_iff, and_true, h.le.trans IH] }
400+
simp only [list.sum_cons, list.foldr_map, list.foldr] at IH ⊢,
401+
exact (hadd _ _).trans (max_le_max le_rfl IH)
321402
end
322403

323404
@[simp, to_additive]
@@ -345,32 +426,6 @@ begin
345426
exact dvd_add (h _ (mem_cons_self _ _)) (ih (λ x hx, h x (mem_cons_of_mem _ hx))) }
346427
end
347428

348-
lemma exists_lt_of_sum_lt [linear_ordered_cancel_add_comm_monoid M] {l : list ι} (f g : ι → M)
349-
(h : (l.map f).sum < (l.map g).sum) :
350-
∃ x ∈ l, f x < g x :=
351-
begin
352-
induction l with x l,
353-
{ exact (lt_irrefl _ h).elim },
354-
obtain h' | h' := lt_or_le (f x) (g x),
355-
{ exact ⟨x, mem_cons_self _ _, h'⟩ },
356-
simp at h,
357-
obtain ⟨y, h1y, h2y⟩ := l_ih (lt_of_add_lt_add_left (h.trans_le $ add_le_add_right h' _)),
358-
exact ⟨y, mem_cons_of_mem x h1y, h2y⟩,
359-
end
360-
361-
lemma exists_le_of_sum_le [linear_ordered_cancel_add_comm_monoid M] {l : list ι} (hl : l ≠ [])
362-
(f g : ι → M) (h : (l.map f).sum ≤ (l.map g).sum) :
363-
∃ x ∈ l, f x ≤ g x :=
364-
begin
365-
cases l with x l,
366-
{ contradiction },
367-
obtain h' | h' := le_or_lt (f x) (g x),
368-
{ exact ⟨x, mem_cons_self _ _, h'⟩ },
369-
obtain ⟨y, h1y, h2y⟩ := exists_lt_of_sum_lt f g _,
370-
exact ⟨y, mem_cons_of_mem x h1y, le_of_lt h2y⟩, simp at h,
371-
exact lt_of_add_lt_add_left (h.trans_lt $ add_lt_add_right h' _),
372-
end
373-
374429
/-- The product of a list of positive natural numbers is positive,
375430
and likewise for any nontrivial ordered semiring. -/
376431
lemma prod_pos [ordered_semiring R] [nontrivial R] (l : list R) (h : ∀ a ∈ l, (0 : R) < a) :
@@ -416,11 +471,11 @@ by rw [sub_eq_add_neg, alternating_sum]
416471

417472
end alternating
418473

419-
lemma sum_map_mul_left [semiring R] (L : list ι) (f : ι → R) (r : R) :
474+
lemma sum_map_mul_left [non_unital_non_assoc_semiring R] (L : list ι) (f : ι → R) (r : R) :
420475
(L.map (λ b, r * f b)).sum = r * (L.map f).sum :=
421476
sum_map_hom L f $ add_monoid_hom.mul_left r
422477

423-
lemma sum_map_mul_right [semiring R] (L : list ι) (f : ι → R) (r : R) :
478+
lemma sum_map_mul_right [non_unital_non_assoc_semiring R] (L : list ι) (f : ι → R) (r : R) :
424479
(L.map (λ b, f b * r)).sum = (L.map f).sum * r :=
425480
sum_map_hom L f $ add_monoid_hom.mul_right r
426481

src/data/list/prod_monoid.lean

Lines changed: 0 additions & 59 deletions
This file was deleted.

0 commit comments

Comments
 (0)