mathlib documentation

data.list.big_operators

Sums and products from lists #

This file provides basic results about list.prod and list.sum, which calculate the product and sum of elements of a list. These are defined in data.list.defs.

@[simp]
theorem list.sum_nil {M : Type u_2} [add_monoid M] :
@[simp]
theorem list.prod_nil {M : Type u_2} [monoid M] :
theorem list.sum_singleton {M : Type u_2} [add_monoid M] {a : M} :
[a].sum = a
theorem list.prod_singleton {M : Type u_2} [monoid M] {a : M} :
[a].prod = a
@[simp]
theorem list.sum_cons {M : Type u_2} [add_monoid M] {l : list M} {a : M} :
(a :: l).sum = a + l.sum
@[simp]
theorem list.prod_cons {M : Type u_2} [monoid M] {l : list M} {a : M} :
(a :: l).prod = a * l.prod
@[simp]
theorem list.prod_append {M : Type u_2} [monoid M] {l₁ l₂ : list M} :
(l₁ ++ l₂).prod = (l₁.prod) * l₂.prod
@[simp]
theorem list.sum_append {M : Type u_2} [add_monoid M] {l₁ l₂ : list M} :
(l₁ ++ l₂).sum = l₁.sum + l₂.sum
theorem list.sum_concat {M : Type u_2} [add_monoid M] {l : list M} {a : M} :
(l.concat a).sum = l.sum + a
theorem list.prod_concat {M : Type u_2} [monoid M] {l : list M} {a : M} :
(l.concat a).prod = (l.prod) * a
@[simp]
theorem list.sum_join {M : Type u_2} [add_monoid M] {l : list (list M)} :
@[simp]
theorem list.prod_join {M : Type u_2} [monoid M] {l : list (list M)} :
theorem list.sum_eq_foldr {M : Type u_2} [add_monoid M] {l : list M} :
theorem list.prod_eq_foldr {M : Type u_2} [monoid M] {l : list M} :
theorem list.prod_hom_rel {ι : Type u_1} {M : Type u_2} {N : Type u_3} [monoid M] [monoid N] (l : list ι) {r : M → N → Prop} {f : ι → M} {g : ι → N} (h₁ : r 1 1) (h₂ : ∀ ⦃i : ι⦄ ⦃a : M⦄ ⦃b : N⦄, r a br ((f i) * a) ((g i) * b)) :
r (list.map f l).prod (list.map g l).prod
theorem list.sum_hom_rel {ι : Type u_1} {M : Type u_2} {N : Type u_3} [add_monoid M] [add_monoid N] (l : list ι) {r : M → N → Prop} {f : ι → M} {g : ι → N} (h₁ : r 0 0) (h₂ : ∀ ⦃i : ι⦄ ⦃a : M⦄ ⦃b : N⦄, r a br (f i + a) (g i + b)) :
r (list.map f l).sum (list.map g l).sum
theorem list.sum_hom {M : Type u_2} {N : Type u_3} [add_monoid M] [add_monoid N] (l : list M) (f : M →+ N) :
theorem list.prod_hom {M : Type u_2} {N : Type u_3} [monoid M] [monoid N] (l : list M) (f : M →* N) :
theorem list.prod_hom₂ {ι : Type u_1} {M : Type u_2} {N : Type u_3} {P : Type u_4} [monoid M] [monoid N] [monoid P] (l : list ι) (f : M → N → P) (hf : ∀ (a b : M) (c d : N), f (a * b) (c * d) = (f a c) * f b d) (hf' : f 1 1 = 1) (f₁ : ι → M) (f₂ : ι → N) :
(list.map (λ (i : ι), f (f₁ i) (f₂ i)) l).prod = f (list.map f₁ l).prod (list.map f₂ l).prod
theorem list.sum_hom₂ {ι : Type u_1} {M : Type u_2} {N : Type u_3} {P : Type u_4} [add_monoid M] [add_monoid N] [add_monoid P] (l : list ι) (f : M → N → P) (hf : ∀ (a b : M) (c d : N), f (a + b) (c + d) = f a c + f b d) (hf' : f 0 0 = 0) (f₁ : ι → M) (f₂ : ι → N) :
(list.map (λ (i : ι), f (f₁ i) (f₂ i)) l).sum = f (list.map f₁ l).sum (list.map f₂ l).sum
theorem list.prod_map_hom {ι : Type u_1} {M : Type u_2} {N : Type u_3} [monoid M] [monoid N] (L : list ι) (f : ι → M) (g : M →* N) :
(list.map (g f) L).prod = g (list.map f L).prod
theorem list.sum_map_hom {ι : Type u_1} {M : Type u_2} {N : Type u_3} [add_monoid M] [add_monoid N] (L : list ι) (f : ι → M) (g : M →+ N) :
(list.map (g f) L).sum = g (list.map f L).sum
theorem list.sum_is_unit {M : Type u_2} [add_monoid M] {L : list M} (u : ∀ (m : M), m Lis_add_unit m) :
theorem list.prod_is_unit {M : Type u_2} [monoid M] {L : list M} (u : ∀ (m : M), m Lis_unit m) :
@[simp]
theorem list.sum_take_add_sum_drop {M : Type u_2} [add_monoid M] (L : list M) (i : ) :
(list.take i L).sum + (list.drop i L).sum = L.sum
@[simp]
theorem list.prod_take_mul_prod_drop {M : Type u_2} [monoid M] (L : list M) (i : ) :
((list.take i L).prod) * (list.drop i L).prod = L.prod
@[simp]
theorem list.sum_take_succ {M : Type u_2} [add_monoid M] (L : list M) (i : ) (p : i < L.length) :
(list.take (i + 1) L).sum = (list.take i L).sum + L.nth_le i p
@[simp]
theorem list.prod_take_succ {M : Type u_2} [monoid M] (L : list M) (i : ) (p : i < L.length) :
(list.take (i + 1) L).prod = ((list.take i L).prod) * L.nth_le i p
theorem list.length_pos_of_prod_ne_one {M : Type u_2} [monoid M] (L : list M) (h : L.prod 1) :
0 < L.length

A list with product not one must have positive length.

theorem list.length_pos_of_sum_ne_zero {M : Type u_2} [add_monoid M] (L : list M) (h : L.sum 0) :
0 < L.length
theorem list.prod_update_nth {M : Type u_2} [monoid M] (L : list M) (n : ) (a : M) :
(L.update_nth n a).prod = (((list.take n L).prod) * ite (n < L.length) a 1) * (list.drop (n + 1) L).prod
theorem list.sum_update_nth {M : Type u_2} [add_monoid M] (L : list M) (n : ) (a : M) :
(L.update_nth n a).sum = (list.take n L).sum + ite (n < L.length) a 0 + (list.drop (n + 1) L).sum
theorem list.nth_zero_add_tail_sum {M : Type u_2} [add_monoid M] (l : list M) :
(l.nth 0).get_or_else 0 + l.tail.sum = l.sum
theorem list.nth_zero_mul_tail_prod {M : Type u_2} [monoid M] (l : list M) :
((l.nth 0).get_or_else 1) * l.tail.prod = l.prod

We'd like to state this as L.head * L.tail.prod = L.prod, but because L.head relies on an inhabited instance to return a garbage value on the empty list, this is not possible. Instead, we write the statement in terms of (L.nth 0).get_or_else 1.

theorem list.head_add_tail_sum_of_ne_nil {M : Type u_2} [add_monoid M] [inhabited M] (l : list M) (h : l list.nil) :
l.head + l.tail.sum = l.sum
theorem list.head_mul_tail_prod_of_ne_nil {M : Type u_2} [monoid M] [inhabited M] (l : list M) (h : l list.nil) :
(l.head) * l.tail.prod = l.prod

Same as nth_zero_mul_tail_prod, but avoiding the list.head garbage complication by requiring the list to be nonempty.

theorem list.prod_eq_zero {M₀ : Type u_5} [monoid_with_zero M₀] {L : list M₀} (h : 0 L) :
L.prod = 0

If zero is an element of a list L, then list.prod L = 0. If the domain is a nontrivial monoid with zero with no divisors, then this implication becomes an iff, see list.prod_eq_zero_iff.

@[simp]
theorem list.prod_eq_zero_iff {M₀ : Type u_5} [monoid_with_zero M₀] [nontrivial M₀] [no_zero_divisors M₀] {L : list M₀} :
L.prod = 0 0 L

Product of elements of a list L equals zero if and only if 0 ∈ L. See also list.prod_eq_zero for an implication that needs weaker typeclass assumptions.

theorem list.prod_ne_zero {M₀ : Type u_5} [monoid_with_zero M₀] [nontrivial M₀] [no_zero_divisors M₀] {L : list M₀} (hL : 0 L) :
L.prod 0
theorem list.prod_inv_reverse {G : Type u_6} [group G] (L : list G) :
(L.prod)⁻¹ = (list.map (λ (x : G), x⁻¹) L).reverse.prod

This is the list.prod version of mul_inv_rev

theorem list.sum_neg_reverse {G : Type u_6} [add_group G] (L : list G) :
-L.sum = (list.map (λ (x : G), -x) L).reverse.sum

This is the list.sum version of add_neg_rev

theorem list.prod_reverse_noncomm {G : Type u_6} [group G] (L : list G) :
L.reverse.prod = ((list.map (λ (x : G), x⁻¹) L).prod)⁻¹

A non-commutative variant of list.prod_reverse

theorem list.sum_reverse_noncomm {G : Type u_6} [add_group G] (L : list G) :
L.reverse.sum = -(list.map (λ (x : G), -x) L).sum

A non-commutative variant of list.sum_reverse

@[simp]
theorem list.sum_drop_succ {G : Type u_6} [add_group G] (L : list G) (i : ) (p : i < L.length) :
(list.drop (i + 1) L).sum = -L.nth_le i p + (list.drop i L).sum

Counterpart to list.sum_take_succ when we have an negation operation

@[simp]
theorem list.prod_drop_succ {G : Type u_6} [group G] (L : list G) (i : ) (p : i < L.length) :
(list.drop (i + 1) L).prod = (L.nth_le i p)⁻¹ * (list.drop i L).prod

Counterpart to list.prod_take_succ when we have an inverse operation

theorem list.sum_neg {G : Type u_6} [add_comm_group G] (L : list G) :
-L.sum = (list.map (λ (x : G), -x) L).sum

This is the list.sum version of add_neg

theorem list.prod_inv {G : Type u_6} [comm_group G] (L : list G) :
(L.prod)⁻¹ = (list.map (λ (x : G), x⁻¹) L).prod

This is the list.prod version of mul_inv

theorem list.prod_update_nth' {G : Type u_6} [comm_group G] (L : list G) (n : ) (a : G) :
(L.update_nth n a).prod = (L.prod) * dite (n < L.length) (λ (hn : n < L.length), (L.nth_le n hn)⁻¹ * a) (λ (hn : ¬n < L.length), 1)

Alternative version of list.prod_update_nth when the list is over a group

theorem list.sum_update_nth' {G : Type u_6} [add_comm_group G] (L : list G) (n : ) (a : G) :
(L.update_nth n a).sum = L.sum + dite (n < L.length) (λ (hn : n < L.length), -L.nth_le n hn + a) (λ (hn : ¬n < L.length), 0)

Alternative version of list.sum_update_nth when the list is over a group

theorem list.eq_of_sum_take_eq {M : Type u_2} [add_left_cancel_monoid M] {L L' : list M} (h : L.length = L'.length) (h' : ∀ (i : ), i L.length(list.take i L).sum = (list.take i L').sum) :
L = L'
theorem list.monotone_sum_take {M : Type u_2} [canonically_ordered_add_monoid M] (L : list M) :
monotone (λ (i : ), (list.take i L).sum)
theorem list.sum_nonneg {M : Type u_2} [ordered_add_comm_monoid M] {l : list M} (hl₁ : ∀ (x : M), x l0 x) :
0 l.sum
theorem list.one_le_prod_of_one_le {M : Type u_2} [ordered_comm_monoid M] {l : list M} (hl₁ : ∀ (x : M), x l1 x) :
1 l.prod
theorem list.one_lt_prod_of_one_lt {M : Type u_2} [ordered_comm_monoid M] (l : list M) (hl : ∀ (x : M), x l1 < x) (hl₂ : l list.nil) :
1 < l.prod
theorem list.sum_pos {M : Type u_2} [ordered_add_comm_monoid M] (l : list M) (hl : ∀ (x : M), x l0 < x) (hl₂ : l list.nil) :
0 < l.sum
theorem list.single_le_sum {M : Type u_2} [ordered_add_comm_monoid M] {l : list M} (hl₁ : ∀ (x : M), x l0 x) (x : M) (H : x l) :
x l.sum
theorem list.single_le_prod {M : Type u_2} [ordered_comm_monoid M] {l : list M} (hl₁ : ∀ (x : M), x l1 x) (x : M) (H : x l) :
x l.prod
theorem list.all_zero_of_le_zero_le_of_sum_eq_zero {M : Type u_2} [ordered_add_comm_monoid M] {l : list M} (hl₁ : ∀ (x : M), x l0 x) (hl₂ : l.sum = 0) {x : M} (hx : x l) :
x = 0
theorem list.all_one_of_le_one_le_of_prod_eq_one {M : Type u_2} [ordered_comm_monoid M] {l : list M} (hl₁ : ∀ (x : M), x l1 x) (hl₂ : l.prod = 1) {x : M} (hx : x l) :
x = 1
theorem list.sum_eq_zero_iff {M : Type u_2} [canonically_ordered_add_monoid M] (l : list M) :
l.sum = 0 ∀ (x : M), x lx = 0
theorem list.prod_eq_one_iff {M : Type u_2} [canonically_ordered_monoid M] (l : list M) :
l.prod = 1 ∀ (x : M), x lx = 1
theorem list.length_le_sum_of_one_le (L : list ) (h : ∀ (i : ), i L1 i) :

If all elements in a list are bounded below by 1, then the length of the list is bounded by the sum of the elements.

theorem list.length_pos_of_sum_pos {M : Type u_2} [ordered_cancel_add_comm_monoid M] (L : list M) (h : 0 < L.sum) :
0 < L.length

A list with positive sum must have positive length.

theorem list.sum_le_foldr_max {M : Type u_2} {N : Type u_3} [add_monoid M] [add_monoid N] [linear_order N] (f : M → N) (h0 : f 0 0) (hadd : ∀ (x y : M), f (x + y) max (f x) (f y)) (l : list M) :
@[simp]
theorem list.sum_erase {M : Type u_2} [decidable_eq M] [add_comm_monoid M] {a : M} {l : list M} :
a la + (l.erase a).sum = l.sum
@[simp]
theorem list.prod_erase {M : Type u_2} [decidable_eq M] [comm_monoid M] {a : M} {l : list M} :
a la * (l.erase a).prod = l.prod
theorem list.dvd_prod {M : Type u_2} [comm_monoid M] {a : M} {l : list M} (ha : a l) :
a l.prod
@[simp]
theorem list.sum_const_nat (m n : ) :
(list.repeat m n).sum = m * n
theorem list.dvd_sum {R : Type u_7} [semiring R] {a : R} {l : list R} (h : ∀ (x : R), x la x) :
a l.sum
theorem list.exists_lt_of_sum_lt {ι : Type u_1} {M : Type u_2} [linear_ordered_cancel_add_comm_monoid M] {l : list ι} (f g : ι → M) (h : (list.map f l).sum < (list.map g l).sum) :
∃ (x : ι) (H : x l), f x < g x
theorem list.exists_le_of_sum_le {ι : Type u_1} {M : Type u_2} [linear_ordered_cancel_add_comm_monoid M] {l : list ι} (hl : l list.nil) (f g : ι → M) (h : (list.map f l).sum (list.map g l).sum) :
∃ (x : ι) (H : x l), f x g x
theorem list.prod_pos {R : Type u_7} [ordered_semiring R] [nontrivial R] (l : list R) (h : ∀ (a : R), a l0 < a) :
0 < l.prod

The product of a list of positive natural numbers is positive, and likewise for any nontrivial ordered semiring.

Several lemmas about sum/head/tail for list. These are hard to generalize well, as they rely on the fact that default ℕ = 0. If desired, we could add a class stating that default = 0.

theorem list.head_add_tail_sum (L : list ) :
L.head + L.tail.sum = L.sum

This relies on default ℕ = 0.

theorem list.head_le_sum (L : list ) :

This relies on default ℕ = 0.

theorem list.tail_sum (L : list ) :
L.tail.sum = L.sum - L.head

This relies on default ℕ = 0.

@[simp]
@[simp]
@[simp]
theorem list.alternating_prod_singleton {G : Type u_6} [comm_group G] (g : G) :
@[simp]
theorem list.alternating_sum_singleton {G : Type u_6} [add_comm_group G] (g : G) :
@[simp]
theorem list.alternating_sum_cons_cons' {G : Type u_6} [add_comm_group G] (g h : G) (l : list G) :
@[simp]
theorem list.alternating_prod_cons_cons {G : Type u_6} [comm_group G] (g h : G) (l : list G) :
theorem list.alternating_sum_cons_cons {G : Type u_1} [add_comm_group G] (g h : G) (l : list G) :
theorem list.sum_map_mul_left {ι : Type u_1} {R : Type u_7} [semiring R] (L : list ι) (f : ι → R) (r : R) :
(list.map (λ (b : ι), r * f b) L).sum = r * (list.map f L).sum
theorem list.sum_map_mul_right {ι : Type u_1} {R : Type u_7} [semiring R] (L : list ι) (f : ι → R) (r : R) :
(list.map (λ (b : ι), (f b) * r) L).sum = ((list.map f L).sum) * r
theorem monoid_hom.map_list_prod {M : Type u_2} {N : Type u_3} [monoid M] [monoid N] (f : M →* N) (l : list M) :
theorem add_monoid_hom.map_list_sum {M : Type u_2} {N : Type u_3} [add_monoid M] [add_monoid N] (f : M →+ N) (l : list M) :
theorem monoid_hom.unop_map_list_prod {M : Type u_2} {N : Type u_3} [monoid M] [monoid N] (f : M →* Nᵐᵒᵖ) (l : list M) :

A morphism into the opposite monoid acts on the product by acting on the reversed elements