Skip to content

Commit

Permalink
feat: When the sum of a nonneg function is zero (#7372)
Browse files Browse the repository at this point in the history
Also fix implicitness of arguments to `Finset.sum_singleton`.
  • Loading branch information
YaelDillies committed Sep 27, 2023
1 parent fad287b commit c8320ac
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 20 deletions.
17 changes: 12 additions & 5 deletions Mathlib/Algebra/BigOperators/Basic.lean
Expand Up @@ -8,9 +8,10 @@ import Mathlib.Algebra.Group.Pi
import Mathlib.Algebra.GroupPower.Lemmas
import Mathlib.Algebra.Hom.Equiv.Basic
import Mathlib.Algebra.Ring.Opposite
import Mathlib.Data.Finset.Powerset
import Mathlib.Data.Finset.Sigma
import Mathlib.Data.Finset.Sum
import Mathlib.Data.Fintype.Basic
import Mathlib.Data.Finset.Sigma
import Mathlib.Data.Multiset.Powerset
import Mathlib.Data.Set.Pairwise.Basic

Expand Down Expand Up @@ -340,7 +341,7 @@ theorem prod_insert_one [DecidableEq α] (h : f a = 1) : ∏ x in insert a s, f
#align finset.sum_insert_zero Finset.sum_insert_zero

@[to_additive (attr := simp)]
theorem prod_singleton : ∏ x in singleton a, f x = f a :=
theorem prod_singleton (f : α → β) (a : α) : ∏ x in singleton a, f x = f a :=
Eq.trans fold_singleton <| mul_one _
#align finset.prod_singleton Finset.prod_singleton
#align finset.sum_singleton Finset.sum_singleton
Expand Down Expand Up @@ -790,7 +791,7 @@ theorem prod_eq_single_of_mem {s : Finset α} {f : α → β} (a : α) (h : a
· intro _ H
rwa [mem_singleton.1 H]
· simpa only [mem_singleton] }
_ = f a := prod_singleton
_ = f a := prod_singleton _ _
#align finset.prod_eq_single_of_mem Finset.prod_eq_single_of_mem
#align finset.sum_eq_single_of_mem Finset.sum_eq_single_of_mem

Expand Down Expand Up @@ -1265,8 +1266,7 @@ theorem prod_range_zero (f : ℕ → β) : ∏ k in range 0, f k = 1 := by rw [r

@[to_additive sum_range_one]
theorem prod_range_one (f : ℕ → β) : ∏ k in range 1, f k = f 0 := by
rw [range_one]
apply @prod_singleton β ℕ 0 f
rw [range_one, prod_singleton]
#align finset.prod_range_one Finset.prod_range_one
#align finset.sum_range_one Finset.sum_range_one

Expand Down Expand Up @@ -1460,6 +1460,13 @@ theorem prod_pow (s : Finset α) (n : ℕ) (f : α → β) : ∏ x in s, f x ^ n
#align finset.prod_pow Finset.prod_pow
#align finset.sum_nsmul Finset.sum_nsmul

/-- A product over `Finset.powersetLen` which only depends on the size of the sets is constant. -/
@[to_additive
"A sum over `Finset.powersetLen` which only depends on the size of the sets is constant."]
lemma prod_powersetLen (n : ℕ) (s : Finset α) (f : ℕ → β) :
∏ t in powersetLen n s, f t.card = f n ^ s.card.choose n := by
rw [prod_eq_pow_card, card_powersetLen]; rintro a ha; rw [(mem_powersetLen.1 ha).2]

@[to_additive]
theorem prod_flip {n : ℕ} (f : ℕ → β) :
(∏ r in range (n + 1), f (n - r)) = ∏ k in range (n + 1), f k := by
Expand Down
49 changes: 43 additions & 6 deletions Mathlib/Algebra/BigOperators/Order.lean
Expand Up @@ -202,7 +202,7 @@ theorem prod_eq_one_iff_of_le_one' :
@[to_additive single_le_sum]
theorem single_le_prod' (hf : ∀ i ∈ s, 1 ≤ f i) {a} (h : a ∈ s) : f a ≤ ∏ x in s, f x :=
calc
f a = ∏ i in {a}, f i := prod_singleton.symm
f a = ∏ i in {a}, f i := (prod_singleton _ _).symm
_ ≤ ∏ i in s, f i :=
prod_le_prod_of_subset_of_one_le' (singleton_subset_iff.2 h) fun i hi _ ↦ hf i hi
#align finset.single_le_prod' Finset.single_le_prod'
Expand Down Expand Up @@ -494,7 +494,7 @@ theorem prod_lt_prod_of_subset' (h : s ⊆ t) {i : ι} (ht : i ∈ t) (hs : i
theorem single_lt_prod' {i j : ι} (hij : j ≠ i) (hi : i ∈ s) (hj : j ∈ s) (hlt : 1 < f j)
(hle : ∀ k ∈ s, k ≠ i → 1 ≤ f k) : f i < ∏ k in s, f k :=
calc
f i = ∏ k in {i}, f k := prod_singleton.symm
f i = ∏ k in {i}, f k := by rw [prod_singleton]
_ < ∏ k in s, f k :=
prod_lt_prod_of_subset' (singleton_subset_iff.2 hi) hj (mt mem_singleton.1 hij) hlt
fun k hks hki ↦ hle k hks (mt mem_singleton.2 hki)
Expand Down Expand Up @@ -682,23 +682,60 @@ end CanonicallyOrderedCommSemiring
end Finset

namespace Fintype

variable [Fintype ι]
section OrderedCommMonoid
variable [Fintype ι] [OrderedCommMonoid M] {f : ι → M}

@[to_additive (attr := mono) sum_mono]
theorem prod_mono' [OrderedCommMonoid M] : Monotone fun f : ι → M ↦ ∏ i, f i := fun _ _ hfg ↦
theorem prod_mono' : Monotone fun f : ι → M ↦ ∏ i, f i := fun _ _ hfg ↦
Finset.prod_le_prod' fun x _ ↦ hfg x
#align fintype.prod_mono' Fintype.prod_mono'
#align fintype.sum_mono Fintype.sum_mono

@[to_additive sum_nonneg]
lemma one_le_prod (hf : 1 ≤ f) : 1 ≤ ∏ i, f i := Finset.one_le_prod' λ _ _ ↦ hf _

@[to_additive] lemma prod_le_one (hf : f ≤ 1) : ∏ i, f i ≤ 1 := Finset.prod_le_one' λ _ _ ↦ hf _

end OrderedCommMonoid

section OrderedCancelCommMonoid
variable [Fintype ι] [OrderedCancelCommMonoid M] {f : ι → M}

@[to_additive sum_strictMono]
theorem prod_strictMono' [OrderedCancelCommMonoid M] : StrictMono fun f : ι → M ↦ ∏ x, f x :=
theorem prod_strictMono' : StrictMono fun f : ι → M ↦ ∏ x, f x :=
fun _ _ hfg ↦
let ⟨hle, i, hlt⟩ := Pi.lt_def.mp hfg
Finset.prod_lt_prod' (fun i _ ↦ hle i) ⟨i, Finset.mem_univ i, hlt⟩
#align fintype.prod_strict_mono' Fintype.prod_strictMono'
#align fintype.sum_strict_mono Fintype.sum_strictMono

@[to_additive sum_pos]
lemma one_lt_prod (hf : 1 < f) : 1 < ∏ i, f i :=
Finset.one_lt_prod' (λ _ _ ↦ hf.le _) $ by simpa using (Pi.lt_def.1 hf).2

@[to_additive]
lemma prod_lt_one (hf : f < 1) : ∏ i, f i < 1 :=
Finset.prod_lt_one' (λ _ _ ↦ hf.le _) $ by simpa using (Pi.lt_def.1 hf).2

@[to_additive sum_pos_iff_of_nonneg]
lemma one_lt_prod_iff_of_one_le (hf : 1 ≤ f) : 1 < ∏ i, f i ↔ 1 < f := by
obtain rfl | hf := hf.eq_or_lt <;> simp [*, one_lt_prod]

@[to_additive]
lemma prod_lt_one_iff_of_le_one (hf : f ≤ 1) : ∏ i, f i < 1 ↔ f < 1 := by
obtain rfl | hf := hf.eq_or_lt <;> simp [*, prod_lt_one]

@[to_additive]
lemma prod_eq_one_iff_of_one_le (hf : 1 ≤ f) : ∏ i, f i = 1 ↔ f = 1 := by
simpa only [(one_le_prod hf).not_gt_iff_eq, hf.not_gt_iff_eq]
using (one_lt_prod_iff_of_one_le hf).not

@[to_additive]
lemma prod_eq_one_iff_of_le_one (hf : f ≤ 1) : ∏ i, f i = 1 ↔ f = 1 := by
simpa only [(prod_le_one hf).not_gt_iff_eq, hf.not_gt_iff_eq, eq_comm]
using (prod_lt_one_iff_of_le_one hf).not

end OrderedCancelCommMonoid
end Fintype

namespace WithTop
Expand Down
2 changes: 1 addition & 1 deletion Mathlib/Analysis/Convex/Combination.lean
Expand Up @@ -330,7 +330,7 @@ theorem convexHull_eq (s : Set E) : convexHull R s =
(_ : ∑ i in t, w i = 1) (_ : ∀ i ∈ t, z i ∈ s), t.centerMass w z = x } := by
refine' Subset.antisymm (convexHull_min _ _) _
· intro x hx
use PUnit, {PUnit.unit}, fun _ => 1, fun _ => x, fun _ _ => zero_le_one, Finset.sum_singleton,
use PUnit, {PUnit.unit}, fun _ => 1, fun _ => x, fun _ _ => zero_le_one, sum_singleton _ _,
fun _ _ => hx
simp only [Finset.centerMass, Finset.sum_singleton, inv_one, one_smul]
· rintro x ⟨ι, sx, wx, zx, hwx₀, hwx₁, hzx, rfl⟩ y ⟨ι', sy, wy, zy, hwy₀, hwy₁, hzy, rfl⟩ a b ha
Expand Down
2 changes: 1 addition & 1 deletion Mathlib/Data/Nat/Digits.lean
Expand Up @@ -552,7 +552,7 @@ theorem sub_one_mul_sum_div_pow_eq_sub_sum_digits
have ih := ih (w₂' h') w₁'
simp only [self_div_pow_eq_ofDigits_drop _ _ h, digits_ofDigits p h tl w₁' w₂',
succ_eq_one_add] at ih
have := @sum_singleton _ _ tl.length (fun x => ofDigits p <| tl.drop x) _
have := sum_singleton (fun x ofDigits p <| tl.drop x) tl.length
rw [← Ico_succ_singleton, List.drop_length, ofDigits] at this
have h₁ : 1 ≤ tl.length := List.length_pos.mpr h'
rw [← sum_range_add_sum_Ico _ <| h₁, ← add_zero (∑ x in Ico _ _, ofDigits p (tl.drop x)),
Expand Down
10 changes: 4 additions & 6 deletions Mathlib/NumberTheory/Divisors.lean
Expand Up @@ -373,10 +373,8 @@ theorem sum_properDivisors_dvd (h : (∑ x in n.properDivisors, x) ∣ n) :
have hlt : ∑ x in n.succ.succ.properDivisors, x < n.succ.succ :=
lt_of_le_of_ne (Nat.le_of_dvd (Nat.succ_pos _) h) ne_n
symm
rw [← mem_singleton,
eq_properDivisors_of_subset_of_sum_eq_sum
(singleton_subset_iff.2 (mem_properDivisors.2 ⟨h, hlt⟩)) sum_singleton,
mem_properDivisors]
rw [← mem_singleton, eq_properDivisors_of_subset_of_sum_eq_sum (singleton_subset_iff.2
(mem_properDivisors.2 ⟨h, hlt⟩)) (sum_singleton _ _), mem_properDivisors]
refine' ⟨one_dvd _, Nat.succ_lt_succ (Nat.succ_pos _)⟩
#align nat.sum_proper_divisors_dvd Nat.sum_properDivisors_dvd

Expand Down Expand Up @@ -416,13 +414,13 @@ theorem sum_properDivisors_eq_one_iff_prime : ∑ x in n.properDivisors, x = 1
· cases n
· simp [Nat.not_prime_one]
· rw [← properDivisors_eq_singleton_one_iff_prime]
refine' ⟨fun h => _, fun h => h.symm ▸ sum_singleton⟩
refine' ⟨fun h => _, fun h => h.symm ▸ sum_singleton _ _
rw [@eq_comm (Finset ℕ) _ _]
apply
eq_properDivisors_of_subset_of_sum_eq_sum
(singleton_subset_iff.2
(one_mem_properDivisors_iff_one_lt.2 (succ_lt_succ (Nat.succ_pos _))))
(Eq.trans sum_singleton h.symm)
((sum_singleton _ _).trans h.symm)
#align nat.sum_proper_divisors_eq_one_iff_prime Nat.sum_properDivisors_eq_one_iff_prime

theorem mem_properDivisors_prime_pow {p : ℕ} (pp : p.Prime) (k : ℕ) {x : ℕ} :
Expand Down
2 changes: 1 addition & 1 deletion Mathlib/Topology/Algebra/InfiniteSum/Order.lean
Expand Up @@ -88,7 +88,7 @@ theorem isLUB_hasSum (h : ∀ i, 0 ≤ f i) (hf : HasSum f a) :

theorem le_hasSum (hf : HasSum f a) (i : ι) (hb : ∀ j, j ≠ i → 0 ≤ f j) : f i ≤ a :=
calc
f i = ∑ i in {i}, f i := Finset.sum_singleton.symm
f i = ∑ i in {i}, f i := by rw [sum_singleton]
_ ≤ a := sum_le_hasSum _ (by simpa) hf
#align le_has_sum le_hasSum

Expand Down

0 comments on commit c8320ac

Please sign in to comment.