2015-05-16 08:42:13 +00:00
|
|
|
|
/-
|
|
|
|
|
Copyright (c) 2015 Jeremy Avigad. All rights reserved.
|
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
Authors: Leonardo de Moura, Jeremy Avigad
|
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
Finite products on a monoid, and finite sums on an additive monoid.
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
|
|
|
|
We have to be careful with dependencies. This theory imports files from finset and list, which
|
|
|
|
|
import basic files from nat. Then nat imports this file to instantiate finite products and sums.
|
2015-08-08 00:53:30 +00:00
|
|
|
|
|
|
|
|
|
Bigops based on finsets go in the namespace algebra.finset. There are also versions based on sets,
|
|
|
|
|
defined in group_set_bigops.lean.
|
2015-05-16 08:42:13 +00:00
|
|
|
|
-/
|
2015-07-15 02:17:40 +00:00
|
|
|
|
import .group .group_power data.list.basic data.list.perm data.finset.basic
|
2015-12-06 07:27:46 +00:00
|
|
|
|
open function binary quot subtype list finset
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
variables {A B : Type}
|
|
|
|
|
variable [deceqA : decidable_eq A]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
/- Prodl: product indexed by a list -/
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
section monoid
|
|
|
|
|
variable [mB : monoid B]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
include mB
|
|
|
|
|
|
|
|
|
|
definition mulf (f : A → B) : B → A → B :=
|
|
|
|
|
λ b a, b * f a
|
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
definition Prodl (l : list A) (f : A → B) : B :=
|
2015-05-16 08:42:13 +00:00
|
|
|
|
list.foldl (mulf f) 1 l
|
|
|
|
|
|
|
|
|
|
-- ∏ x ← l, f x
|
2015-05-17 05:24:37 +00:00
|
|
|
|
notation `∏` binders `←` l, r:(scoped f, Prodl l f) := r
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
|
|
|
|
private theorem foldl_const (f : A → B) :
|
|
|
|
|
∀ (l : list A) (b : B), foldl (mulf f) b l = b * foldl (mulf f) 1 l
|
|
|
|
|
| [] b := by rewrite [*foldl_nil, mul_one]
|
|
|
|
|
| (a::l) b := by rewrite [*foldl_cons, foldl_const, {foldl _ (mulf f 1 a) _}foldl_const, ↑mulf,
|
|
|
|
|
one_mul, mul.assoc]
|
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prodl_nil (f : A → B) : Prodl [] f = 1 := rfl
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prodl_cons (f : A → B) (a : A) (l : list A) : Prodl (a::l) f = f a * Prodl l f :=
|
|
|
|
|
by rewrite [↑Prodl, foldl_cons, foldl_const, ↑mulf, one_mul]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prodl_append :
|
|
|
|
|
∀ (l₁ l₂ : list A) (f : A → B), Prodl (l₁++l₂) f = Prodl l₁ f * Prodl l₂ f
|
|
|
|
|
| [] l₂ f := by rewrite [append_nil_left, Prodl_nil, one_mul]
|
|
|
|
|
| (a::l) l₂ f := by rewrite [append_cons, *Prodl_cons, Prodl_append, mul.assoc]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
section deceqA
|
|
|
|
|
include deceqA
|
|
|
|
|
|
|
|
|
|
theorem Prodl_insert_of_mem (f : A → B) {a : A} {l : list A} : a ∈ l →
|
|
|
|
|
Prodl (insert a l) f = Prodl l f :=
|
2015-05-16 12:26:59 +00:00
|
|
|
|
assume ainl, by rewrite [insert_eq_of_mem ainl]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prodl_insert_of_not_mem (f : A → B) {a : A} {l : list A} :
|
|
|
|
|
a ∉ l → Prodl (insert a l) f = f a * Prodl l f :=
|
|
|
|
|
assume nainl, by rewrite [insert_eq_of_not_mem nainl, Prodl_cons]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prodl_union {l₁ l₂ : list A} (f : A → B) (d : disjoint l₁ l₂) :
|
|
|
|
|
Prodl (union l₁ l₂) f = Prodl l₁ f * Prodl l₂ f :=
|
|
|
|
|
by rewrite [union_eq_append d, Prodl_append]
|
|
|
|
|
end deceqA
|
2015-05-17 07:50:32 +00:00
|
|
|
|
|
2015-05-18 22:45:23 +00:00
|
|
|
|
theorem Prodl_one : ∀(l : list A), Prodl l (λ x, 1) = (1:B)
|
2015-05-17 07:50:32 +00:00
|
|
|
|
| [] := rfl
|
|
|
|
|
| (a::l) := by rewrite [Prodl_cons, Prodl_one, mul_one]
|
2015-07-15 02:17:40 +00:00
|
|
|
|
|
|
|
|
|
lemma Prodl_singleton {a : A} {f : A → B} : Prodl [a] f = f a :=
|
|
|
|
|
!one_mul
|
|
|
|
|
|
|
|
|
|
lemma Prodl_map {f : A → B} :
|
|
|
|
|
∀ {l : list A}, Prodl l f = Prodl (map f l) id
|
|
|
|
|
| nil := by rewrite [map_nil]
|
|
|
|
|
| (a::l) := begin rewrite [map_cons, Prodl_cons f, Prodl_cons id (f a), Prodl_map] end
|
|
|
|
|
|
|
|
|
|
open nat
|
|
|
|
|
lemma Prodl_eq_pow_of_const {f : A → B} :
|
|
|
|
|
∀ {l : list A} b, (∀ a, a ∈ l → f a = b) → Prodl l f = b ^ length l
|
2015-12-06 07:27:46 +00:00
|
|
|
|
| nil := take b, assume Pconst, by rewrite [length_nil, {b^0}pow_zero]
|
2015-07-15 02:17:40 +00:00
|
|
|
|
| (a::l) := take b, assume Pconst,
|
|
|
|
|
assert Pconstl : ∀ a', a' ∈ l → f a' = b,
|
|
|
|
|
from take a' Pa'in, Pconst a' (mem_cons_of_mem a Pa'in),
|
2015-08-14 15:00:16 +00:00
|
|
|
|
by rewrite [Prodl_cons f, Pconst a !mem_cons, Prodl_eq_pow_of_const b Pconstl, length_cons, add_one, pow_succ b]
|
2015-07-15 02:17:40 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
end monoid
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
section comm_monoid
|
|
|
|
|
variable [cmB : comm_monoid B]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
include cmB
|
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prodl_mul (l : list A) (f g : A → B) : Prodl l (λx, f x * g x) = Prodl l f * Prodl l g :=
|
2015-05-16 08:42:13 +00:00
|
|
|
|
list.induction_on l
|
2015-05-17 05:24:37 +00:00
|
|
|
|
(by rewrite [*Prodl_nil, mul_one])
|
2015-05-16 08:42:13 +00:00
|
|
|
|
(take a l,
|
|
|
|
|
assume IH,
|
2015-05-17 05:24:37 +00:00
|
|
|
|
by rewrite [*Prodl_cons, IH, *mul.assoc, mul.left_comm (Prodl l f)])
|
|
|
|
|
end comm_monoid
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
/- Prod: product indexed by a finset -/
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-08-08 00:53:30 +00:00
|
|
|
|
namespace finset
|
2015-05-16 08:42:13 +00:00
|
|
|
|
variable [cmB : comm_monoid B]
|
|
|
|
|
include cmB
|
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem mulf_rcomm (f : A → B) : right_commutative (mulf f) :=
|
2015-11-11 19:32:05 +00:00
|
|
|
|
right_commutative_compose_right (@has_mul.mul B _) f (@mul.right_comm B _)
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prodl_eq_Prodl_of_perm (f : A → B) {l₁ l₂ : list A} :
|
|
|
|
|
perm l₁ l₂ → Prodl l₁ f = Prodl l₂ f :=
|
|
|
|
|
λ p, perm.foldl_eq_of_perm (mulf_rcomm f) p 1
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
definition Prod (s : finset A) (f : A → B) : B :=
|
2015-05-16 08:42:13 +00:00
|
|
|
|
quot.lift_on s
|
2015-05-17 05:24:37 +00:00
|
|
|
|
(λ l, Prodl (elt_of l) f)
|
|
|
|
|
(λ l₁ l₂ p, Prodl_eq_Prodl_of_perm f p)
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
|
|
|
|
-- ∏ x ∈ s, f x
|
2015-12-06 07:27:46 +00:00
|
|
|
|
notation `∏` binders `∈` s, r:(scoped f, Prod s f) := r
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prod_empty (f : A → B) : Prod ∅ f = 1 :=
|
|
|
|
|
Prodl_nil f
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 06:00:38 +00:00
|
|
|
|
theorem Prod_mul (s : finset A) (f g : A → B) : Prod s (λx, f x * g x) = Prod s f * Prod s g :=
|
|
|
|
|
quot.induction_on s (take u, !Prodl_mul)
|
|
|
|
|
|
|
|
|
|
section deceqA
|
|
|
|
|
include deceqA
|
2015-05-16 12:26:59 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prod_insert_of_mem (f : A → B) {a : A} {s : finset A} :
|
|
|
|
|
a ∈ s → Prod (insert a s) f = Prod s f :=
|
2015-05-16 12:26:59 +00:00
|
|
|
|
quot.induction_on s
|
2015-05-17 05:24:37 +00:00
|
|
|
|
(λ l ainl, Prodl_insert_of_mem f ainl)
|
2015-05-16 12:26:59 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prod_insert_of_not_mem (f : A → B) {a : A} {s : finset A} :
|
|
|
|
|
a ∉ s → Prod (insert a s) f = f a * Prod s f :=
|
2015-05-16 12:26:59 +00:00
|
|
|
|
quot.induction_on s
|
2015-05-17 05:24:37 +00:00
|
|
|
|
(λ l nainl, Prodl_insert_of_not_mem f nainl)
|
2015-05-16 12:26:59 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Prod_union (f : A → B) {s₁ s₂ : finset A} (disj : s₁ ∩ s₂ = ∅) :
|
|
|
|
|
Prod (s₁ ∪ s₂) f = Prod s₁ f * Prod s₂ f :=
|
|
|
|
|
have H1 : disjoint s₁ s₂ → Prod (s₁ ∪ s₂) f = Prod s₁ f * Prod s₂ f, from
|
2015-05-16 12:26:59 +00:00
|
|
|
|
quot.induction_on₂ s₁ s₂
|
2015-05-17 05:24:37 +00:00
|
|
|
|
(λ l₁ l₂ d, Prodl_union f d),
|
2015-05-17 09:06:10 +00:00
|
|
|
|
H1 (disjoint_of_inter_eq_empty disj)
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 06:00:38 +00:00
|
|
|
|
theorem Prod_ext {s : finset A} {f g : A → B} :
|
|
|
|
|
(∀{x}, x ∈ s → f x = g x) → Prod s f = Prod s g :=
|
|
|
|
|
finset.induction_on s
|
|
|
|
|
(assume H, rfl)
|
2015-05-25 08:37:07 +00:00
|
|
|
|
(take x s', assume H1 : x ∉ s',
|
2015-05-17 06:00:38 +00:00
|
|
|
|
assume IH : (∀ {x : A}, x ∈ s' → f x = g x) → Prod s' f = Prod s' g,
|
|
|
|
|
assume H2 : ∀{y}, y ∈ insert x s' → f y = g y,
|
|
|
|
|
assert H3 : ∀y, y ∈ s' → f y = g y, from
|
|
|
|
|
take y, assume H', H2 (mem_insert_of_mem _ H'),
|
|
|
|
|
assert H4 : f x = g x, from H2 !mem_insert,
|
|
|
|
|
by rewrite [Prod_insert_of_not_mem f H1, Prod_insert_of_not_mem g H1, IH H3, H4])
|
|
|
|
|
end deceqA
|
2015-05-17 07:50:32 +00:00
|
|
|
|
|
2015-05-18 22:45:23 +00:00
|
|
|
|
theorem Prod_one (s : finset A) : Prod s (λ x, 1) = (1:B) :=
|
2015-05-17 07:50:32 +00:00
|
|
|
|
quot.induction_on s (take u, !Prodl_one)
|
2015-08-08 00:53:30 +00:00
|
|
|
|
end finset
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
section add_monoid
|
|
|
|
|
variable [amB : add_monoid B]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
include amB
|
2015-10-09 20:21:03 +00:00
|
|
|
|
local attribute add_monoid.to_monoid [trans_instance]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
definition Suml (l : list A) (f : A → B) : B := Prodl l f
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
|
|
|
|
-- ∑ x ← l, f x
|
2015-05-17 05:24:37 +00:00
|
|
|
|
notation `∑` binders `←` l, r:(scoped f, Suml l f) := r
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Suml_nil (f : A → B) : Suml [] f = 0 := Prodl_nil f
|
|
|
|
|
theorem Suml_cons (f : A → B) (a : A) (l : list A) : Suml (a::l) f = f a + Suml l f :=
|
|
|
|
|
Prodl_cons f a l
|
|
|
|
|
theorem Suml_append (l₁ l₂ : list A) (f : A → B) : Suml (l₁++l₂) f = Suml l₁ f + Suml l₂ f :=
|
|
|
|
|
Prodl_append l₁ l₂ f
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 06:00:38 +00:00
|
|
|
|
section deceqA
|
|
|
|
|
include deceqA
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Suml_insert_of_mem (f : A → B) {a : A} {l : list A} (H : a ∈ l) :
|
|
|
|
|
Suml (insert a l) f = Suml l f := Prodl_insert_of_mem f H
|
|
|
|
|
theorem Suml_insert_of_not_mem (f : A → B) {a : A} {l : list A} (H : a ∉ l) :
|
|
|
|
|
Suml (insert a l) f = f a + Suml l f := Prodl_insert_of_not_mem f H
|
|
|
|
|
theorem Suml_union {l₁ l₂ : list A} (f : A → B) (d : disjoint l₁ l₂) :
|
|
|
|
|
Suml (union l₁ l₂) f = Suml l₁ f + Suml l₂ f := Prodl_union f d
|
2015-05-17 06:00:38 +00:00
|
|
|
|
end deceqA
|
2015-05-17 07:50:32 +00:00
|
|
|
|
|
2015-05-18 22:45:23 +00:00
|
|
|
|
theorem Suml_zero (l : list A) : Suml l (λ x, 0) = (0:B) := Prodl_one l
|
2015-05-17 05:24:37 +00:00
|
|
|
|
end add_monoid
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
section add_comm_monoid
|
|
|
|
|
variable [acmB : add_comm_monoid B]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
include acmB
|
2015-10-09 20:21:03 +00:00
|
|
|
|
local attribute add_comm_monoid.to_comm_monoid [trans_instance]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Suml_add (l : list A) (f g : A → B) : Suml l (λx, f x + g x) = Suml l f + Suml l g :=
|
|
|
|
|
Prodl_mul l f g
|
|
|
|
|
end add_comm_monoid
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
/- Sum -/
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-08-08 00:53:30 +00:00
|
|
|
|
namespace finset
|
2015-05-17 05:24:37 +00:00
|
|
|
|
variable [acmB : add_comm_monoid B]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
include acmB
|
2015-10-09 20:21:03 +00:00
|
|
|
|
local attribute add_comm_monoid.to_comm_monoid [trans_instance]
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
definition Sum (s : finset A) (f : A → B) : B := Prod s f
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
|
|
|
|
-- ∑ x ∈ s, f x
|
2015-05-17 05:24:37 +00:00
|
|
|
|
notation `∑` binders `∈` s, r:(scoped f, Sum s f) := r
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Sum_empty (f : A → B) : Sum ∅ f = 0 := Prod_empty f
|
2015-05-17 06:00:38 +00:00
|
|
|
|
theorem Sum_add (s : finset A) (f g : A → B) :
|
|
|
|
|
Sum s (λx, f x + g x) = Sum s f + Sum s g := Prod_mul s f g
|
2015-05-16 08:42:13 +00:00
|
|
|
|
|
2015-05-17 06:00:38 +00:00
|
|
|
|
section deceqA
|
|
|
|
|
include deceqA
|
2015-05-17 05:24:37 +00:00
|
|
|
|
theorem Sum_insert_of_mem (f : A → B) {a : A} {s : finset A} (H : a ∈ s) :
|
|
|
|
|
Sum (insert a s) f = Sum s f := Prod_insert_of_mem f H
|
|
|
|
|
theorem Sum_insert_of_not_mem (f : A → B) {a : A} {s : finset A} (H : a ∉ s) :
|
|
|
|
|
Sum (insert a s) f = f a + Sum s f := Prod_insert_of_not_mem f H
|
|
|
|
|
theorem Sum_union (f : A → B) {s₁ s₂ : finset A} (disj : s₁ ∩ s₂ = ∅) :
|
|
|
|
|
Sum (s₁ ∪ s₂) f = Sum s₁ f + Sum s₂ f := Prod_union f disj
|
2015-05-17 06:00:38 +00:00
|
|
|
|
theorem Sum_ext {s : finset A} {f g : A → B} (H : ∀x, x ∈ s → f x = g x) :
|
|
|
|
|
Sum s f = Sum s g := Prod_ext H
|
|
|
|
|
end deceqA
|
2015-05-17 07:50:32 +00:00
|
|
|
|
|
2015-05-18 22:45:23 +00:00
|
|
|
|
theorem Sum_zero (s : finset A) : Sum s (λ x, 0) = (0:B) := Prod_one s
|
2015-08-08 00:53:30 +00:00
|
|
|
|
end finset
|