Module mathcomp.boot.bigop
From HB Require Import structures.From mathcomp Require Import ssreflect ssrbool ssrfun eqtype ssrnat seq path.
From mathcomp Require Import div fintype tuple finfun.
Finitely iterated operators
NB: See CONTRIBUTING.md for an introduction to HB concepts and commands.
This file provides a generic definition for iterating an operator over a
set of indices (bigop); this big operator is parameterized by the return
type (R), the type of indices (I), the operator (op), the default value on
empty lists (idx), the range of indices (r), the filter applied on this
range (P) and the expression we are iterating (F). The definition is not
to be used directly, but via the wide range of notations provided and
which support a natural use of big operators.
To improve performance of the Coq typechecker on large expressions, the
bigop constant is OPAQUE. It can however be unlocked to reveal the
transparent constant reducebig, to let Coq expand summation on an explicit
sequence with an explicit test.
The lemmas can be classified according to the operator being iterated:
1. Results independent of the operator: extensionality with respect to
the range of indices, to the filtering predicate or to the expression
being iterated; reindexing, widening or narrowing of the range of
indices; we provide lemmas for the special cases where indices are
natural numbers or bounded natural numbers ("ordinals"). We supply
several "functional" induction principles that can be used with the
ssreflect 1.3 "elim" tactic to do induction over the index range for
up to 3 bigops simultaneously.
2. Results depending on the properties of the operator:
We distinguish:
- semigroup laws (op is associative)
- commutative semigroup laws (semigroup laws, op is commutative)
- monoid laws (semigroup laws, idx is an identity element)
- abelian monoid laws (op is also commutative)
- laws with a distributive operation (semirings)
Examples of such results are splitting, permuting, and exchanging
bigops.
A special section is dedicated to big operators on natural numbers.
Notations:
The general form for iterated operators is
<bigop>_<range> <general_term>
- <bigop> is one of \big[op/idx], \sum, \prod, or \max (see below).
- <general_term> can be any expression.
- <range> binds an index variable in <general_term>; <range> is one of
(i <- s) i ranges over the sequence s.
(m <= i < n) i ranges over the nat interval m, m+1, ..., n-1.
(i < n) i ranges over the (finite) type 'I_n (i.e., ordinal n).
(i : T) i ranges over the finite type T.
i or (i) i ranges over its (inferred) finite type.
(i in A) i ranges over the elements that satisfy the collective
predicate A (the domain of A must be a finite type).
(i <- s | <condition>) limits the range to the i for which <condition>
holds. <condition> can be any expression that coerces to
bool, and may mention the bound index i. All six kinds of
ranges above can have a <condition> part.
- One can use the "\big[op/idx]" notations for any operator.
- BIG_F and BIG_P are pattern abbreviations for the <general_term> and
<condition> part of a \big ... expression; for (i in A) and (i in A | C)
ranges the term matched by BIG_P will include the i \in A condition.
- The (locked) head constant of a \big notation is bigop.
- The "\sum", "\prod" and "\max" notations in the %N scope are used for
natural numbers with addition, multiplication and maximum (and their
corresponding neutral elements), respectively.
- The "\sum" and "\prod" reserved notations are overloaded in ssralg in
the %R scope; in mxalgebra, vector & falgebra in the %MS and %VS scopes;
"\prod" is also overloaded in fingroup, in the %g and %G scopes.
- We reserve "\bigcup" and "\bigcap" notations for iterated union and
intersection (of sets, groups, vector spaces, etc.).
Tips for using lemmas in this file:
To apply a lemma for a specific operator: if no special property is
required for the operator, simply apply the lemma; if the lemma needs
certain properties for the operator, make sure the appropriate instances
are declared using, e.g., Check addn : Monoid.law _. to check that addn
is equipped with the monoid laws.
Interfaces for operator properties are packaged in the SemiGroup and
Monoid submodules:
SemiGroup.law == interface (keyed on the operator) for associative
operators
The HB class is SemiGroup.
SemiGroup.com_law == interface for associative and commutative operators
The HB class is SemiGroup.ComLaw.
Monoid.law idx == interface for associative operators with identity
element idx
The HB class is Monoid.Law.
Monoid.com_law idx == extension of Monoid.law for operators that are also
commutative
The HB class is Monoid.ComLaw.
Monoid.mul_law abz == interface for operators with absorbing (zero)
element abz
The HB class is Monoid.MulLaw.
Monoid.add_law idx mop == extension of Monoid.com_law for operators over
which operation mop distributes (mop will often also
have a Monoid.mul_law idx structure)
The HB class is Monoid.AddLaw.
SemiGroup.Theory == submodule containing basic generic algebra lemmas
for operators satisfying the SemiGroup interfaces
Monoid.Theory == submodule containing basic generic algebra lemmas
for operators satisfying the Monoid interfaces,
exports SemiGroup.Theory
Monoid.simpm == generic monoid simplification rewrite multirule
olaw op == extends a law on T to a law on option T, it is
canonically a Monoid.law when op is a SemiGroup.law,
and a Monoid.com_law when op is a SemiGroup.com_law
Monoid structures are predeclared for many basic operators: (_ && _)%B,
(_ || _)%B, (_ (+) _)%B (exclusive or), (_ + _)%N, (_ * _)%N, maxn,
gcdn, lcmn and (_ ++ _)%SEQ (list concatenation)
Reference: Y. Bertot, G. Gonthier, S. Ould Biha, I. Pasca, Canonical Big
Operators, TPHOLs 2008, LNCS vol. 5170, Springer, available at:
http://hal.inria.fr/docs/00/33/11/93/PDF/main.pdf
Examples of use in: poly.v, matrix.v
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Declare Scope big_scope.
Reserved Notation "\big [ op / idx ]_ i F"
(at level 36, F at level 36, op, idx at level 10, i at level 0,
right associativity,
format "'[' \big [ op / idx ]_ i '/ ' F ']'").
Reserved Notation "\big [ op / idx ]_ ( i <- r | P ) F"
(F at level 36, i, r at level 60,
format "'[' \big [ op / idx ]_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\big [ op / idx ]_ ( i <- r ) F"
(F at level 36,
format "'[' \big [ op / idx ]_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\big [ op / idx ]_ ( m <= i < n | P ) F"
(F at level 36, i, n at level 60,
format "'[' \big [ op / idx ]_ ( m <= i < n | P ) F ']'").
Reserved Notation "\big [ op / idx ]_ ( m <= i < n ) F"
(at level 36, F at level 36,
format "'[' \big [ op / idx ]_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\big [ op / idx ]_ ( i | P ) F"
(F at level 36,
format "'[' \big [ op / idx ]_ ( i | P ) '/ ' F ']'").
Reserved Notation "\big [ op / idx ]_ ( i : t | P ) F"
(F at level 36,
format "'[' \big [ op / idx ]_ ( i : t | P ) '/ ' F ']'").
Reserved Notation "\big [ op / idx ]_ ( i : t ) F"
(F at level 36,
format "'[' \big [ op / idx ]_ ( i : t ) '/ ' F ']'").
Reserved Notation "\big [ op / idx ]_ ( i < n | P ) F"
(F at level 36, n at level 60,
format "'[' \big [ op / idx ]_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\big [ op / idx ]_ ( i < n ) F"
(F at level 36,
format "'[' \big [ op / idx ]_ ( i < n ) F ']'").
Reserved Notation "\big [ op / idx ]_ ( i 'in' A | P ) F"
(F at level 36, A at level 60,
format "'[' \big [ op / idx ]_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\big [ op / idx ]_ ( i 'in' A ) F"
(F at level 36,
format "'[' \big [ op / idx ]_ ( i 'in' A ) '/ ' F ']'").
Reserved Notation "\sum_ i F"
(at level 34, F at level 41, i at level 0,
right associativity,
format "'[' \sum_ i '/ ' F ']'").
Reserved Notation "\sum_ ( i <- r | P ) F"
(at level 34, F at level 41, i, r at level 60,
format "'[' \sum_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\sum_ ( i <- r ) F"
(F at level 41,
format "'[' \sum_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\sum_ ( m <= i < n | P ) F"
(F at level 41, i, n at level 60,
format "'[' \sum_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\sum_ ( m <= i < n ) F"
(F at level 41,
format "'[' \sum_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\sum_ ( i | P ) F"
(F at level 41,
format "'[' \sum_ ( i | P ) '/ ' F ']'").
Reserved Notation "\sum_ ( i : t | P ) F" (F at level 41).
Reserved Notation "\sum_ ( i : t ) F" (F at level 41).
Reserved Notation "\sum_ ( i < n | P ) F"
(F at level 41, n at level 60,
format "'[' \sum_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\sum_ ( i < n ) F"
(F at level 41,
format "'[' \sum_ ( i < n ) '/ ' F ']'").
Reserved Notation "\sum_ ( i 'in' A | P ) F"
(F at level 41, A at level 60,
format "'[' \sum_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\sum_ ( i 'in' A ) F"
(F at level 41,
format "'[' \sum_ ( i 'in' A ) '/ ' F ']'").
Reserved Notation "\max_ i F"
(at level 34, F at level 41, i at level 0,
format "'[' \max_ i '/ ' F ']'").
Reserved Notation "\max_ ( i <- r | P ) F"
(at level 34, F at level 41, i, r at level 60,
format "'[' \max_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\max_ ( i <- r ) F"
(F at level 41,
format "'[' \max_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\max_ ( m <= i < n | P ) F"
(F at level 41, i, n at level 60,
format "'[' \max_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\max_ ( m <= i < n ) F"
(F at level 41,
format "'[' \max_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\max_ ( i | P ) F"
(F at level 41,
format "'[' \max_ ( i | P ) '/ ' F ']'").
Reserved Notation "\max_ ( i : t | P ) F" (F at level 41).
Reserved Notation "\max_ ( i : t ) F" (F at level 41).
Reserved Notation "\max_ ( i < n | P ) F"
(F at level 41, n at level 60,
format "'[' \max_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\max_ ( i < n ) F"
(F at level 41, n at level 60,
format "'[' \max_ ( i < n ) F ']'").
Reserved Notation "\max_ ( i 'in' A | P ) F"
(F at level 41, A at level 60,
format "'[' \max_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\max_ ( i 'in' A ) F"
(F at level 41,
format "'[' \max_ ( i 'in' A ) '/ ' F ']'").
Reserved Notation "\prod_ i F"
(at level 34, F at level 36, i at level 0,
format "'[' \prod_ i '/ ' F ']'").
Reserved Notation "\prod_ ( i <- r | P ) F"
(at level 34, F at level 36, i, r at level 60,
format "'[' \prod_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\prod_ ( i <- r ) F"
(F at level 36,
format "'[' \prod_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\prod_ ( m <= i < n | P ) F"
(F at level 36, i, n at level 60,
format "'[' \prod_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\prod_ ( m <= i < n ) F"
(F at level 36,
format "'[' \prod_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\prod_ ( i | P ) F"
(F at level 36,
format "'[' \prod_ ( i | P ) '/ ' F ']'").
Reserved Notation "\prod_ ( i : t | P ) F" (F at level 36).
Reserved Notation "\prod_ ( i : t ) F" (F at level 36).
Reserved Notation "\prod_ ( i < n | P ) F"
(F at level 36, n at level 60,
format "'[' \prod_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\prod_ ( i < n ) F"
(F at level 36,
format "'[' \prod_ ( i < n ) '/ ' F ']'").
Reserved Notation "\prod_ ( i 'in' A | P ) F"
(F at level 36, A at level 60,
format "'[' \prod_ ( i 'in' A | P ) F ']'").
Reserved Notation "\prod_ ( i 'in' A ) F"
(F at level 36,
format "'[' \prod_ ( i 'in' A ) '/ ' F ']'").
Reserved Notation "\bigcup_ i F"
(at level 41, F at level 41, i at level 0,
format "'[' \bigcup_ i '/ ' F ']'").
Reserved Notation "\bigcup_ ( i <- r | P ) F"
(at level 41, F at level 41, i, r at level 60,
format "'[' \bigcup_ ( i <- r | P ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( i <- r ) F"
(F at level 41,
format "'[' \bigcup_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( m <= i < n | P ) F"
(F at level 41, i, n at level 60,
format "'[' \bigcup_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( m <= i < n ) F"
(F at level 41,
format "'[' \bigcup_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( i | P ) F"
(F at level 41,
format "'[' \bigcup_ ( i | P ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( i : t | P ) F"
(F at level 41,
format "'[' \bigcup_ ( i : t | P ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( i : t ) F"
(F at level 41,
format "'[' \bigcup_ ( i : t ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( i < n | P ) F"
(F at level 41, n at level 60,
format "'[' \bigcup_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( i < n ) F"
(F at level 41,
format "'[' \bigcup_ ( i < n ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( i 'in' A | P ) F"
(F at level 41, A at level 60,
format "'[' \bigcup_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\bigcup_ ( i 'in' A ) F"
(F at level 41,
format "'[' \bigcup_ ( i 'in' A ) '/ ' F ']'").
Reserved Notation "\bigcap_ i F"
(at level 41, F at level 41, i at level 0,
format "'[' \bigcap_ i '/ ' F ']'").
Reserved Notation "\bigcap_ ( i <- r | P ) F"
(at level 41, F at level 41, i, r at level 60,
format "'[' \bigcap_ ( i <- r | P ) F ']'").
Reserved Notation "\bigcap_ ( i <- r ) F"
(F at level 41,
format "'[' \bigcap_ ( i <- r ) '/ ' F ']'").
Reserved Notation "\bigcap_ ( m <= i < n | P ) F"
(F at level 41, i, n at level 60,
format "'[' \bigcap_ ( m <= i < n | P ) '/ ' F ']'").
Reserved Notation "\bigcap_ ( m <= i < n ) F"
(F at level 41,
format "'[' \bigcap_ ( m <= i < n ) '/ ' F ']'").
Reserved Notation "\bigcap_ ( i | P ) F"
(F at level 41,
format "'[' \bigcap_ ( i | P ) '/ ' F ']'").
Reserved Notation "\bigcap_ ( i : t | P ) F"
(F at level 41,
format "'[' \bigcap_ ( i : t | P ) '/ ' F ']'").
Reserved Notation "\bigcap_ ( i : t ) F"
(F at level 41,
format "'[' \bigcap_ ( i : t ) '/ ' F ']'").
Reserved Notation "\bigcap_ ( i < n | P ) F"
(F at level 41, n at level 60,
format "'[' \bigcap_ ( i < n | P ) '/ ' F ']'").
Reserved Notation "\bigcap_ ( i < n ) F"
(F at level 41,
format "'[' \bigcap_ ( i < n ) '/ ' F ']'").
Reserved Notation "\bigcap_ ( i 'in' A | P ) F"
(F at level 41, A at level 60,
format "'[' \bigcap_ ( i 'in' A | P ) '/ ' F ']'").
Reserved Notation "\bigcap_ ( i 'in' A ) F"
(F at level 41,
format "'[' \bigcap_ ( i 'in' A ) '/ ' F ']'").
Module SemiGroup.
HB.mixin Record isLaw T (op : T -> T -> T) := {
opA : associative op;
}.
#[export]
HB.structure Definition Law T := {op of isLaw T op}.
Notation law := Law.type.
HB.mixin Record isCommutativeLaw T (op : T -> T -> T) := {
opC : commutative op;
}.
#[export]
HB.structure Definition ComLaw T := {op of Law T op & isCommutativeLaw T op}.
Notation com_law := ComLaw.type.
HB.factory Record isComLaw T (op : T -> T -> T) := {
opA : associative op;
opC : commutative op;
}.
HB.builders Context T op & isComLaw T op.
HB.instance Definition _ := isLaw.Build T op opA.
HB.instance Definition _ := isCommutativeLaw.Build T op opC.
HB.end.
Module Import Exports. HB.reexport. End Exports.
Module Theory.
Section Theory.
Variables (T : Type).
Section Plain.
Variable mul : law T.
Lemma mulmA : associative mul
Proof.
Section Commutative.
Variable mul : com_law T.
Lemma mulmC : commutative mul
Proof.
Lemma mulmAC : right_commutative mul.
Lemma mulmACA : interchange mul mul.
End Commutative.
End Theory.
End Theory.
Include Theory.
End SemiGroup.
Export SemiGroup.Exports.
Module Monoid.
Export SemiGroup.
HB.mixin Record isMonoidLaw T (idm : T) (op : T -> T -> T) := {
op1m : left_id idm op;
opm1 : right_id idm op;
}.
#[export]
HB.structure Definition Law T idm :=
{op of SemiGroup.Law T op & isMonoidLaw T idm op}.
Notation law := Law.type.
HB.factory Record isLaw T (idm : T) (op : T -> T -> T) := {
opA : associative op;
op1m : left_id idm op;
opm1 : right_id idm op;
}.
HB.builders Context T idm op & isLaw T idm op.
HB.instance Definition _ := SemiGroup.isLaw.Build T op opA.
HB.instance Definition _ := isMonoidLaw.Build T idm op op1m opm1.
HB.end.
#[export]
HB.structure Definition ComLaw T idm :=
{op of Law T idm op & isCommutativeLaw T op}.
Notation com_law := ComLaw.type.
HB.factory Record isComLaw T (idm : T) (op : T -> T -> T) := {
opA : associative op;
opC : commutative op;
op1m : left_id idm op;
}.
HB.builders Context T idm op & isComLaw T idm op.
Lemma opm1 : right_id idm op
HB.instance Definition _ := isLaw.Build T idm op opA op1m opm1.
HB.instance Definition _ := isCommutativeLaw.Build T op opC.
HB.end.
HB.mixin Record isMulLaw T (zero : T) (mul : T -> T -> T) := {
mul_zerol : left_zero zero mul;
mul_zeror : right_zero zero mul;
}.
#[export]
HB.structure Definition MulLaw T zero := {mul & isMulLaw T zero mul}.
Notation mul_law := MulLaw.type.
HB.mixin Record isAddLaw T (mul : T -> T -> T) (op : T -> T -> T) := {
mul_op_Dl : left_distributive mul op;
mul_op_Dr : right_distributive mul op;
}.
#[export]
HB.structure Definition AddLaw T zero mul :=
{add of ComLaw T zero add & isAddLaw T mul add}.
Notation add_law := AddLaw.type.
Module Import Exports. HB.reexport. End Exports.
Section CommutativeAxioms.
Variable (T : Type) (zero one : T) (mul add : T -> T -> T).
Hypothesis mulC : commutative mul.
Lemma mulC_id : left_id one mul -> right_id one mul.
Proof.
Lemma mulC_zero : left_zero zero mul -> right_zero zero mul.
Proof.
Lemma mulC_dist : left_distributive mul add -> right_distributive mul add.
Proof.
End CommutativeAxioms.
Module Theory.
Export SemiGroup.Theory.
Section Theory.
Variables (T : Type) (idm : T).
Section Plain.
Variable mul : law idm.
Lemma mul1m : left_id idm mul
Proof.
Proof.
End Plain.
Section Mul.
Variable mul : mul_law idm.
Lemma mul0m : left_zero idm mul
Proof.
Proof.
Section Add.
Variables (mul : T -> T -> T) (add : add_law idm mul).
Lemma addmA : associative add
Proof.
Proof.
Proof.
Proof.
Proof.
Proof.
Proof.
Proof.
Definition simpm := (mulm1, mulm0, mul1m, mul0m, mulmA).
End Theory.
End Theory.
Include SemiGroup.Theory.
Include Theory.
End Monoid.
Export Monoid.Exports.
Section PervasiveMonoids.
Import Monoid.
HB.instance Definition _ := isComLaw.Build bool true andb andbA andbC andTb.
HB.instance Definition _ := isMulLaw.Build bool false andb andFb andbF.
HB.instance Definition _ := isComLaw.Build bool false orb orbA orbC orFb.
HB.instance Definition _ := isMulLaw.Build bool true orb orTb orbT.
HB.instance Definition _ := isComLaw.Build bool false addb addbA addbC addFb.
HB.instance Definition _ := isAddLaw.Build bool andb orb andb_orl andb_orr.
HB.instance Definition _ := isAddLaw.Build bool orb andb orb_andl orb_andr.
HB.instance Definition _ := isAddLaw.Build bool andb addb andb_addl andb_addr.
HB.instance Definition _ := isComLaw.Build nat 0 addn addnA addnC add0n.
HB.instance Definition _ := isComLaw.Build nat 1 muln mulnA mulnC mul1n.
HB.instance Definition _ := isMulLaw.Build nat 0 muln mul0n muln0.
HB.instance Definition _ := isAddLaw.Build nat muln addn mulnDl mulnDr.
HB.instance Definition _ := isComLaw.Build nat 0 maxn maxnA maxnC max0n.
HB.instance Definition _ := isAddLaw.Build nat muln maxn maxnMl maxnMr.
HB.instance Definition _ := isComLaw.Build nat 0 gcdn gcdnA gcdnC gcd0n.
HB.instance Definition _ := isAddLaw.Build nat muln gcdn muln_gcdl muln_gcdr.
HB.instance Definition _ := isComLaw.Build nat 1 lcmn lcmnA lcmnC lcm1n.
HB.instance Definition _ := isAddLaw.Build nat muln lcmn muln_lcml muln_lcmr.
HB.instance Definition _ T := isLaw.Build (seq T) nil cat
(@catA T) (@cat0s T) (@cats0 T).
End PervasiveMonoids.
Delimit Scope big_scope with BIG.
Open Scope big_scope.
Variant bigbody R I := BigBody of I & (R -> R -> R) & bool & R.
Definition applybig {R I} (body : bigbody R I) x :=
let: BigBody _ op b v := body in if b then op v x else x.
Definition reducebig R I idx r (body : I -> bigbody R I) :=
foldr (applybig \o body) idx r.
HB.lock Definition bigop := reducebig.
Canonical bigop_unlock := Unlockable bigop.unlock.
Definition index_iota m n := iota m (n - m).
Lemma mem_index_iota m n i : (i \in index_iota m n) = (m <= i < n).
Proof.
Fact index_enum_key : unit
Proof.
split. Defined.
Definition index_enum (T : finType) :=
locked_with index_enum_key (Finite.enum T).
Lemma deprecated_filter_index_enum T P : filter P (index_enum T) = enum P.
Proof.
Lemma mem_index_enum T i : i \in index_enum T.
Proof.
Lemma index_enum_uniq T : uniq (index_enum T).
Proof.
Notation "\big [ op / idx ]_ ( i <- r | P ) F" :=
(bigop idx r (fun i => BigBody i op P%B F)) : big_scope.
Notation "\big [ op / idx ]_ ( i <- r ) F" :=
(bigop idx r (fun i => BigBody i op true F)) : big_scope.
Notation "\big [ op / idx ]_ ( m <= i < n | P ) F" :=
(bigop idx (index_iota m n) (fun i : nat => BigBody i op P%B F))
: big_scope.
Notation "\big [ op / idx ]_ ( m <= i < n ) F" :=
(bigop idx (index_iota m n) (fun i : nat => BigBody i op true F))
: big_scope.
Notation "\big [ op / idx ]_ ( i | P ) F" :=
(bigop idx (index_enum _) (fun i => BigBody i op P%B F)) : big_scope.
Notation "\big [ op / idx ]_ i F" :=
(bigop idx (index_enum _) (fun i => BigBody i op true F)) : big_scope.
Notation "\big [ op / idx ]_ ( i : t | P ) F" :=
(bigop idx (index_enum _) (fun i : t => BigBody i op P%B F))
(only parsing) : big_scope.
Notation "\big [ op / idx ]_ ( i : t ) F" :=
(bigop idx (index_enum _) (fun i : t => BigBody i op true F))
(only parsing) : big_scope.
Notation "\big [ op / idx ]_ ( i < n | P ) F" :=
(\big[op/idx]_(i : ordinal n | P%B) F) : big_scope.
Notation "\big [ op / idx ]_ ( i < n ) F" :=
(\big[op/idx]_(i : ordinal n) F) : big_scope.
Notation "\big [ op / idx ]_ ( i 'in' A | P ) F" :=
(\big[op/idx]_(i | (i \in A) && P) F) : big_scope.
Notation "\big [ op / idx ]_ ( i 'in' A ) F" :=
(\big[op/idx]_(i | i \in A) F) : big_scope.
Notation BIG_F := (F in \big[_/_]_(i <- _ | _) F i)%pattern.
Notation BIG_P := (P in \big[_/_]_(i <- _ | P i) _)%pattern.
Local Notation "+%N" := addn (only parsing).
Notation "\sum_ ( i <- r | P ) F" :=
(\big[+%N/0%N]_(i <- r | P%B) F%N) : nat_scope.
Notation "\sum_ ( i <- r ) F" :=
(\big[+%N/0%N]_(i <- r) F%N) : nat_scope.
Notation "\sum_ ( m <= i < n | P ) F" :=
(\big[+%N/0%N]_(m <= i < n | P%B) F%N) : nat_scope.
Notation "\sum_ ( m <= i < n ) F" :=
(\big[+%N/0%N]_(m <= i < n) F%N) : nat_scope.
Notation "\sum_ ( i | P ) F" :=
(\big[+%N/0%N]_(i | P%B) F%N) : nat_scope.
Notation "\sum_ i F" :=
(\big[+%N/0%N]_i F%N) : nat_scope.
Notation "\sum_ ( i : t | P ) F" :=
(\big[+%N/0%N]_(i : t | P%B) F%N) (only parsing) : nat_scope.
Notation "\sum_ ( i : t ) F" :=
(\big[+%N/0%N]_(i : t) F%N) (only parsing) : nat_scope.
Notation "\sum_ ( i < n | P ) F" :=
(\big[+%N/0%N]_(i < n | P%B) F%N) : nat_scope.
Notation "\sum_ ( i < n ) F" :=
(\big[+%N/0%N]_(i < n) F%N) : nat_scope.
Notation "\sum_ ( i 'in' A | P ) F" :=
(\big[+%N/0%N]_(i in A | P%B) F%N) : nat_scope.
Notation "\sum_ ( i 'in' A ) F" :=
(\big[+%N/0%N]_(i in A) F%N) : nat_scope.
Local Notation "*%N" := muln (only parsing).
Notation "\prod_ ( i <- r | P ) F" :=
(\big[*%N/1%N]_(i <- r | P%B) F%N) : nat_scope.
Notation "\prod_ ( i <- r ) F" :=
(\big[*%N/1%N]_(i <- r) F%N) : nat_scope.
Notation "\prod_ ( m <= i < n | P ) F" :=
(\big[*%N/1%N]_(m <= i < n | P%B) F%N) : nat_scope.
Notation "\prod_ ( m <= i < n ) F" :=
(\big[*%N/1%N]_(m <= i < n) F%N) : nat_scope.
Notation "\prod_ ( i | P ) F" :=
(\big[*%N/1%N]_(i | P%B) F%N) : nat_scope.
Notation "\prod_ i F" :=
(\big[*%N/1%N]_i F%N) : nat_scope.
Notation "\prod_ ( i : t | P ) F" :=
(\big[*%N/1%N]_(i : t | P%B) F%N) (only parsing) : nat_scope.
Notation "\prod_ ( i : t ) F" :=
(\big[*%N/1%N]_(i : t) F%N) (only parsing) : nat_scope.
Notation "\prod_ ( i < n | P ) F" :=
(\big[*%N/1%N]_(i < n | P%B) F%N) : nat_scope.
Notation "\prod_ ( i < n ) F" :=
(\big[*%N/1%N]_(i < n) F%N) : nat_scope.
Notation "\prod_ ( i 'in' A | P ) F" :=
(\big[*%N/1%N]_(i in A | P%B) F%N) : nat_scope.
Notation "\prod_ ( i 'in' A ) F" :=
(\big[*%N/1%N]_(i in A) F%N) : nat_scope.
Notation "\max_ ( i <- r | P ) F" :=
(\big[maxn/0%N]_(i <- r | P%B) F%N) : nat_scope.
Notation "\max_ ( i <- r ) F" :=
(\big[maxn/0%N]_(i <- r) F%N) : nat_scope.
Notation "\max_ ( i | P ) F" :=
(\big[maxn/0%N]_(i | P%B) F%N) : nat_scope.
Notation "\max_ i F" :=
(\big[maxn/0%N]_i F%N) : nat_scope.
Notation "\max_ ( i : I | P ) F" :=
(\big[maxn/0%N]_(i : I | P%B) F%N) (only parsing) : nat_scope.
Notation "\max_ ( i : I ) F" :=
(\big[maxn/0%N]_(i : I) F%N) (only parsing) : nat_scope.
Notation "\max_ ( m <= i < n | P ) F" :=
(\big[maxn/0%N]_(m <= i < n | P%B) F%N) : nat_scope.
Notation "\max_ ( m <= i < n ) F" :=
(\big[maxn/0%N]_(m <= i < n) F%N) : nat_scope.
Notation "\max_ ( i < n | P ) F" :=
(\big[maxn/0%N]_(i < n | P%B) F%N) : nat_scope.
Notation "\max_ ( i < n ) F" :=
(\big[maxn/0%N]_(i < n) F%N) : nat_scope.
Notation "\max_ ( i 'in' A | P ) F" :=
(\big[maxn/0%N]_(i in A | P%B) F%N) : nat_scope.
Notation "\max_ ( i 'in' A ) F" :=
(\big[maxn/0%N]_(i in A) F%N) : nat_scope.
Lemma big_load R (K K' : R -> Type) idx op I r (P : pred I) F :
K (\big[op/idx]_(i <- r | P i) F i) * K' (\big[op/idx]_(i <- r | P i) F i)
-> K' (\big[op/idx]_(i <- r | P i) F i).
Proof.
by case. Qed.
Arguments big_load [R] K [K'] idx op [I].
Section Elim3.
Variables (R1 R2 R3 : Type) (K : R1 -> R2 -> R3 -> Type).
Variables (id1 : R1) (op1 : R1 -> R1 -> R1).
Variables (id2 : R2) (op2 : R2 -> R2 -> R2).
Variables (id3 : R3) (op3 : R3 -> R3 -> R3).
Hypothesis Kid : K id1 id2 id3.
Lemma big_rec3 I r (P : pred I) F1 F2 F3
(K_F : forall i y1 y2 y3, P i -> K y1 y2 y3 ->
K (op1 (F1 i) y1) (op2 (F2 i) y2) (op3 (F3 i) y3)) :
K (\big[op1/id1]_(i <- r | P i) F1 i)
(\big[op2/id2]_(i <- r | P i) F2 i)
(\big[op3/id3]_(i <- r | P i) F3 i).
Hypothesis Kop : forall x1 x2 x3 y1 y2 y3,
K x1 x2 x3 -> K y1 y2 y3-> K (op1 x1 y1) (op2 x2 y2) (op3 x3 y3).
Lemma big_ind3 I r (P : pred I) F1 F2 F3
(K_F : forall i, P i -> K (F1 i) (F2 i) (F3 i)) :
K (\big[op1/id1]_(i <- r | P i) F1 i)
(\big[op2/id2]_(i <- r | P i) F2 i)
(\big[op3/id3]_(i <- r | P i) F3 i).
End Elim3.
Arguments big_rec3 [R1 R2 R3] K [id1 op1 id2 op2 id3 op3] _ [I r P F1 F2 F3].
Arguments big_ind3 [R1 R2 R3] K [id1 op1 id2 op2 id3 op3] _ _ [I r P F1 F2 F3].
Section Elim2.
Variables (R1 R2 : Type) (K : R1 -> R2 -> Type) (f : R2 -> R1).
Variables (id1 : R1) (op1 : R1 -> R1 -> R1).
Variables (id2 : R2) (op2 : R2 -> R2 -> R2).
Hypothesis Kid : K id1 id2.
Lemma big_rec2 I r (P : pred I) F1 F2
(K_F : forall i y1 y2, P i -> K y1 y2 ->
K (op1 (F1 i) y1) (op2 (F2 i) y2)) :
K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i).
Hypothesis Kop : forall x1 x2 y1 y2,
K x1 x2 -> K y1 y2 -> K (op1 x1 y1) (op2 x2 y2).
Lemma big_ind2 I r (P : pred I) F1 F2 (K_F : forall i, P i -> K (F1 i) (F2 i)) :
K (\big[op1/id1]_(i <- r | P i) F1 i) (\big[op2/id2]_(i <- r | P i) F2 i).
Hypotheses (f_op : {morph f : x y / op2 x y >-> op1 x y}) (f_id : f id2 = id1).
Lemma big_morph I r (P : pred I) F :
f (\big[op2/id2]_(i <- r | P i) F i) = \big[op1/id1]_(i <- r | P i) f (F i).
End Elim2.
Arguments big_rec2 [R1 R2] K [id1 op1 id2 op2] _ [I r P F1 F2].
Arguments big_ind2 [R1 R2] K [id1 op1 id2 op2] _ _ [I r P F1 F2].
Arguments big_morph [R1 R2] f [id1 op1 id2 op2] _ _ [I].
Section Elim1.
Variables (R : Type) (K : R -> Type) (f : R -> R).
Variables (idx : R) (op op' : R -> R -> R).
Hypothesis Kid : K idx.
Lemma big_rec I r (P : pred I) F
(Kop : forall i x, P i -> K x -> K (op (F i) x)) :
K (\big[op/idx]_(i <- r | P i) F i).
Hypothesis Kop : forall x y, K x -> K y -> K (op x y).
Lemma big_ind I r (P : pred I) F (K_F : forall i, P i -> K (F i)) :
K (\big[op/idx]_(i <- r | P i) F i).
Hypothesis Kop' : forall x y, K x -> K y -> op x y = op' x y.
Lemma eq_big_op I r (P : pred I) F (K_F : forall i, P i -> K (F i)) :
\big[op/idx]_(i <- r | P i) F i = \big[op'/idx]_(i <- r | P i) F i.
Hypotheses (fM : {morph f : x y / op x y}) (f_id : f idx = idx).
Lemma big_endo I r (P : pred I) F :
f (\big[op/idx]_(i <- r | P i) F i) = \big[op/idx]_(i <- r | P i) f (F i).
Proof.
End Elim1.
Arguments big_rec [R] K [idx op] _ [I r P F].
Arguments big_ind [R] K [idx op] _ _ [I r P F].
Arguments eq_big_op [R] K [idx op] op' _ _ _ [I].
Arguments big_endo [R] f [idx op] _ _ [I].
Lemma big_morph_in (R1 R2 : Type) (Q : {pred R2}) (f : R2 -> R1)
(id1 : R1) (op1 : R1 -> R1 -> R1)
(id2 : R2) (op2 : R2 -> R2 -> R2) :
{in Q &, forall x y, op2 x y \in Q} ->
id2 \in Q ->
{in Q &, {morph f : x y / op2 x y >-> op1 x y}} ->
f id2 = id1 ->
forall [I : Type] (r : seq I) (P : pred I) (F : I -> R2),
(forall i, P i -> F i \in Q) ->
f (\big[op2/id2]_(i <- r | P i) F i) = \big[op1/id1]_(i <- r | P i) f (F i).
Proof.
Section OptionLaw.
Context {T : Type} (op : T -> T -> T).
Definition olaw x := oapp (fun y => Some (oapp (op^~ y) y x)) x.
Lemma olawss x y : olaw (Some x) (Some y) = some (op x y)
Proof.
by []. Qed.
Proof.
by case. Qed.
Proof.
by []. Qed.
End OptionLaw.
Arguments olaw : simpl never.
Section OptionSemiGroupLaw.
Import Monoid.
Variables (T : Type) (op : SemiGroup.law T).
Let olawA_subdef : associative (olaw op).
HB.instance Definition _ := Monoid.isLaw.Build (option T) None (olaw op)
olawA_subdef (olawx1 _) (olaw1x _).
Context [x : T].
Lemma some_big_mk_monoid [I : Type] r P (F : I -> T) :
Some (\big[op/x]_(i <- r | P i) F i) =
olaw op (\big[olaw op/None]_(i <- r | P i) Some (F i)) (Some x).
Lemma big_mk_option_monoid [I : Type] r P (F : I -> T) :
\big[op/x]_(i <- r | P i) F i =
odflt x (olaw op (\big[olaw op/None]_(i <- r | P i) Some (F i)) (Some x)).
Proof.
End OptionSemiGroupLaw.
Section OptionComLaw.
Import Monoid.
Variables (T : Type) (op : SemiGroup.com_law T).
Let oopC_subdef : commutative (olaw op).
HB.instance Definition _ := isCommutativeLaw.Build
(option T) (olaw op) oopC_subdef.
End OptionComLaw.
Section oAC.
Variables (T : Type) (op : T -> T -> T).
#[deprecated(since="math-comp 2.6", use=olaw)]
Definition oAC & associative op & commutative op :=
fun x => oapp (fun y => Some (oapp (op^~ y) y x)) x.
Hypothesis (opA : associative op) (opC : commutative op).
#[warning="-deprecated"]
Local Notation oop := (oAC opA opC).
Lemma oACE x y : oop (Some x) (Some y) = some (op x y)
Proof.
by []. Qed.
Let oopAC_subdef : associative oop.
Let oopx1_subdef : left_id None oop
Proof.
by case. Qed.
Proof.
by []. Qed.
Let oopC_subdef : commutative oop.
HB.instance Definition _ := Monoid.isComLaw.Build (option T) None oop
oopAC_subdef oopC_subdef oopx1_subdef.
Context [x : T].
#[deprecated(since="math-comp 2.6", use=some_big_mk_monoid)]
Lemma some_big_AC_mk_monoid [I : Type] r P (F : I -> T) :
Some (\big[op/x]_(i <- r | P i) F i) =
oop (\big[oop/None]_(i <- r | P i) Some (F i)) (Some x).
#[deprecated(since="math-comp 2.6", use=big_mk_option_monoid)]
Lemma big_AC_mk_monoid [I : Type] r P (F : I -> T) :
\big[op/x]_(i <- r | P i) F i =
odflt x (oop (\big[oop/None]_(i <- r | P i) Some (F i)) (Some x)).
Proof.
End oAC.
#[warning="-deprecated"]
Arguments oAC : simpl never.
Section Extensionality.
Variables (R : Type) (idx : R) (op : R -> R -> R).
Section SeqExtension.
Variable I : Type.
Lemma foldrE r : foldr op idx r = \big[op/idx]_(x <- r) x.
Proof.
Lemma big_filter r (P : pred I) F :
\big[op/idx]_(i <- filter P r) F i = \big[op/idx]_(i <- r | P i) F i.
Proof.
Lemma big_filter_cond r (P1 P2 : pred I) F :
\big[op/idx]_(i <- filter P1 r | P2 i) F i
= \big[op/idx]_(i <- r | P1 i && P2 i) F i.
Proof.
rewrite -big_filter -(big_filter r); congr bigop.
by rewrite -filter_predI; apply: eq_filter => i; apply: andbC.
Qed.
by rewrite -filter_predI; apply: eq_filter => i; apply: andbC.
Qed.
Lemma eq_bigl r (P1 P2 : pred I) F :
P1 =1 P2 ->
\big[op/idx]_(i <- r | P1 i) F i = \big[op/idx]_(i <- r | P2 i) F i.
Proof.
Lemma big_andbC r (P Q : pred I) F :
\big[op/idx]_(i <- r | P i && Q i) F i
= \big[op/idx]_(i <- r | Q i && P i) F i.
Lemma eq_bigr r (P : pred I) F1 F2 : (forall i, P i -> F1 i = F2 i) ->
\big[op/idx]_(i <- r | P i) F1 i = \big[op/idx]_(i <- r | P i) F2 i.
Proof.
Lemma eq_big r (P1 P2 : pred I) F1 F2 :
P1 =1 P2 -> (forall i, P1 i -> F1 i = F2 i) ->
\big[op/idx]_(i <- r | P1 i) F1 i = \big[op/idx]_(i <- r | P2 i) F2 i.
Lemma congr_big r1 r2 (P1 P2 : pred I) F1 F2 :
r1 = r2 -> P1 =1 P2 -> (forall i, P1 i -> F1 i = F2 i) ->
\big[op/idx]_(i <- r1 | P1 i) F1 i = \big[op/idx]_(i <- r2 | P2 i) F2 i.
Proof.
Lemma big_nil (P : pred I) F : \big[op/idx]_(i <- [::] | P i) F i = idx.
Proof.
Lemma big_cons i r (P : pred I) F :
let x := \big[op/idx]_(j <- r | P j) F j in
\big[op/idx]_(j <- i :: r | P j) F j = if P i then op (F i) x else x.
Proof.
Lemma big_rcons_op i r (P : pred I) F :
let idx' := if P i then op (F i) idx else idx in
\big[op/idx]_(j <- rcons r i | P j) F j = \big[op/idx']_(j <- r | P j) F j.
Lemma big_map J (h : J -> I) r (P : pred I) F :
\big[op/idx]_(i <- map h r | P i) F i
= \big[op/idx]_(j <- r | P (h j)) F (h j).
Proof.
Lemma big_nth x0 r (P : pred I) F :
\big[op/idx]_(i <- r | P i) F i
= \big[op/idx]_(0 <= i < size r | P (nth x0 r i)) (F (nth x0 r i)).
Proof.
Lemma big_hasC r (P : pred I) F :
~~ has P r -> \big[op/idx]_(i <- r | P i) F i = idx.
Proof.
Lemma big_pred0_eq (r : seq I) F : \big[op/idx]_(i <- r | false) F i = idx.
Lemma big_pred0 r (P : pred I) F :
P =1 xpred0 -> \big[op/idx]_(i <- r | P i) F i = idx.
Proof.
Lemma big_cat_nested r1 r2 (P : pred I) F :
let x := \big[op/idx]_(i <- r2 | P i) F i in
\big[op/idx]_(i <- r1 ++ r2 | P i) F i = \big[op/x]_(i <- r1 | P i) F i.
Lemma big_catl r1 r2 (P : pred I) F :
~~ has P r2 ->
\big[op/idx]_(i <- r1 ++ r2 | P i) F i = \big[op/idx]_(i <- r1 | P i) F i.
Proof.
Lemma big_catr r1 r2 (P : pred I) F :
~~ has P r1 ->
\big[op/idx]_(i <- r1 ++ r2 | P i) F i = \big[op/idx]_(i <- r2 | P i) F i.
Proof.
rewrite -big_filter -(big_filter r2) filter_cat.
by rewrite has_count -size_filter; case: filter.
Qed.
by rewrite has_count -size_filter; case: filter.
Qed.
End SeqExtension.
Lemma big_map_id J (h : J -> R) r (P : pred R) :
\big[op/idx]_(i <- map h r | P i) i
= \big[op/idx]_(j <- r | P (h j)) h j.
Proof.
Lemma big_condT (J : finType) (A : {pred J}) F :
\big[op/idx]_(i in A | true) F i = \big[op/idx]_(i in A) F i.
Lemma big_seq_cond (I : eqType) r (P : pred I) F :
\big[op/idx]_(i <- r | P i) F i
= \big[op/idx]_(i <- r | (i \in r) && P i) F i.
Proof.
Lemma big_seq (I : eqType) (r : seq I) F :
\big[op/idx]_(i <- r) F i = \big[op/idx]_(i <- r | i \in r) F i.
Proof.
Lemma eq_big_seq (I : eqType) (r : seq I) F1 F2 :
{in r, F1 =1 F2} -> \big[op/idx]_(i <- r) F1 i = \big[op/idx]_(i <- r) F2 i.
Lemma big_nat_cond m n (P : pred nat) F :
\big[op/idx]_(m <= i < n | P i) F i
= \big[op/idx]_(m <= i < n | (m <= i < n) && P i) F i.
Proof.
Lemma big_nat m n F :
\big[op/idx]_(m <= i < n) F i = \big[op/idx]_(m <= i < n | m <= i < n) F i.
Proof.
Lemma congr_big_nat m1 n1 m2 n2 P1 P2 F1 F2 :
m1 = m2 -> n1 = n2 ->
(forall i, m1 <= i < n2 -> P1 i = P2 i) ->
(forall i, P1 i && (m1 <= i < n2) -> F1 i = F2 i) ->
\big[op/idx]_(m1 <= i < n1 | P1 i) F1 i
= \big[op/idx]_(m2 <= i < n2 | P2 i) F2 i.
Proof.
move=> <- <- eqP12 eqF12; rewrite big_seq_cond (big_seq_cond _ P2).
apply: eq_big => i; rewrite ?inE /= !mem_index_iota.
by apply: andb_id2l; apply: eqP12.
by rewrite andbC; apply: eqF12.
Qed.
apply: eq_big => i; rewrite ?inE /= !mem_index_iota.
by apply: andb_id2l; apply: eqP12.
by rewrite andbC; apply: eqF12.
Qed.
Lemma eq_big_nat m n F1 F2 :
(forall i, m <= i < n -> F1 i = F2 i) ->
\big[op/idx]_(m <= i < n) F1 i = \big[op/idx]_(m <= i < n) F2 i.
Proof.
Lemma big_geq m n (P : pred nat) F :
m >= n -> \big[op/idx]_(m <= i < n | P i) F i = idx.
Proof.
Lemma big_ltn_cond m n (P : pred nat) F :
m < n -> let x := \big[op/idx]_(m.+1 <= i < n | P i) F i in
\big[op/idx]_(m <= i < n | P i) F i = if P m then op (F m) x else x.
Proof.
Lemma big_ltn m n F :
m < n ->
\big[op/idx]_(m <= i < n) F i = op (F m) (\big[op/idx]_(m.+1 <= i < n) F i).
Proof.
Lemma big_addn m n a (P : pred nat) F :
\big[op/idx]_(m + a <= i < n | P i) F i =
\big[op/idx]_(m <= i < n - a | P (i + a)) F (i + a).
Proof.
Lemma big_add1 m n (P : pred nat) F :
\big[op/idx]_(m.+1 <= i < n | P i) F i =
\big[op/idx]_(m <= i < n.-1 | P (i.+1)) F (i.+1).
Lemma big_nat_recl n m F : m <= n ->
\big[op/idx]_(m <= i < n.+1) F i =
op (F m) (\big[op/idx]_(m <= i < n) F i.+1).
Lemma big_mkord n (P : pred nat) F :
\big[op/idx]_(0 <= i < n | P i) F i = \big[op/idx]_(i < n | P i) F i.
Proof.
rewrite /index_iota subn0 -(big_map (@nat_of_ord n)).
by congr bigop; rewrite /index_enum 2!unlock val_ord_enum.
Qed.
by congr bigop; rewrite /index_enum 2!unlock val_ord_enum.
Qed.
Lemma big_mknat n (P : pred 'I_n.+1) F :
\big[op/idx]_(i < n.+1 | P i) F i
= \big[op/idx]_(0 <= i < n.+1 | P (inord i)) F (inord i).
Lemma big_nat_widen m n1 n2 (P : pred nat) F :
n1 <= n2 ->
\big[op/idx]_(m <= i < n1 | P i) F i
= \big[op/idx]_(m <= i < n2 | P i && (i < n1)) F i.
Proof.
move=> len12; symmetry; rewrite -big_filter filter_predI big_filter.
have [ltn_trans eq_by_mem] := (ltn_trans, irr_sorted_eq ltn_trans ltnn).
congr bigop; apply: eq_by_mem; rewrite ?sorted_filter ?iota_ltn_sorted // => i.
rewrite mem_filter !mem_index_iota andbCA andbA andb_idr => // /andP[_].
by move/leq_trans->.
Qed.
have [ltn_trans eq_by_mem] := (ltn_trans, irr_sorted_eq ltn_trans ltnn).
congr bigop; apply: eq_by_mem; rewrite ?sorted_filter ?iota_ltn_sorted // => i.
rewrite mem_filter !mem_index_iota andbCA andbA andb_idr => // /andP[_].
by move/leq_trans->.
Qed.
Lemma big_ord_widen_cond n1 n2 (P : pred nat) (F : nat -> R) :
n1 <= n2 ->
\big[op/idx]_(i < n1 | P i) F i
= \big[op/idx]_(i < n2 | P i && (i < n1)) F i.
Proof.
Lemma big_ord_widen n1 n2 (F : nat -> R) :
n1 <= n2 ->
\big[op/idx]_(i < n1) F i = \big[op/idx]_(i < n2 | i < n1) F i.
Proof.
Lemma big_ord_widen_leq n1 n2 (P : pred 'I_(n1.+1)) F :
n1 < n2 ->
\big[op/idx]_(i < n1.+1 | P i) F i
= \big[op/idx]_(i < n2 | P (inord i) && (i <= n1)) F (inord i).
Proof.
Lemma big_ord0 P F : \big[op/idx]_(i < 0 | P i) F i = idx.
Proof.
Lemma big_mask_tuple I n m (t : n.-tuple I) (P : pred I) F :
\big[op/idx]_(i <- mask m t | P i) F i
= \big[op/idx]_(i < n | nth false m i && P (tnth t i)) F (tnth t i).
Proof.
rewrite [t in LHS]tuple_map_ord/= -map_mask big_map.
by rewrite mask_enum_ord big_filter_cond/= enumT.
Qed.
by rewrite mask_enum_ord big_filter_cond/= enumT.
Qed.
Lemma big_mask I r m (P : pred I) (F : I -> R) (r_ := tnth (in_tuple r)) :
\big[op/idx]_(i <- mask m r | P i) F i
= \big[op/idx]_(i < size r | nth false m i && P (r_ i)) F (r_ i).
Proof.
Lemma big_tnth I r (P : pred I) F (r_ := tnth (in_tuple r)) :
\big[op/idx]_(i <- r | P i) F i
= \big[op/idx]_(i < size r | P (r_ i)) (F (r_ i)).
Proof.
Lemma big_index_uniq (I : eqType) (r : seq I) (E : 'I_(size r) -> R) :
uniq r ->
\big[op/idx]_i E i = \big[op/idx]_(x <- r) oapp E idx (insub (index x r)).
Proof.
Lemma big_tuple I n (t : n.-tuple I) (P : pred I) F :
\big[op/idx]_(i <- t | P i) F i
= \big[op/idx]_(i < n | P (tnth t i)) F (tnth t i).
Lemma big_ord_narrow_cond n1 n2 (P : pred 'I_n2) F (le_n12 : n1 <= n2) :
let w := widen_ord le_n12 in
\big[op/idx]_(i < n2 | P i && (i < n1)) F i
= \big[op/idx]_(i < n1 | P (w i)) F (w i).
Proof.
Lemma big_ord_narrow_cond_leq n1 n2 (P : pred _) F (le_n12 : n1 <= n2) :
let w := @widen_ord n1.+1 n2.+1 le_n12 in
\big[op/idx]_(i < n2.+1 | P i && (i <= n1)) F i
= \big[op/idx]_(i < n1.+1 | P (w i)) F (w i).
Proof.
Lemma big_ord_narrow n1 n2 F (le_n12 : n1 <= n2) :
let w := widen_ord le_n12 in
\big[op/idx]_(i < n2 | i < n1) F i = \big[op/idx]_(i < n1) F (w i).
Proof.
Lemma big_ord_narrow_leq n1 n2 F (le_n12 : n1 <= n2) :
let w := @widen_ord n1.+1 n2.+1 le_n12 in
\big[op/idx]_(i < n2.+1 | i <= n1) F i = \big[op/idx]_(i < n1.+1) F (w i).
Proof.
Lemma big_ord_recl n F :
\big[op/idx]_(i < n.+1) F i =
op (F ord0) (\big[op/idx]_(i < n) F (@lift n.+1 ord0 i)).
Proof.
Lemma big_nseq_cond I n a (P : pred I) F :
\big[op/idx]_(i <- nseq n a | P i) F i
= if P a then iter n (op (F a)) idx else idx.
Proof.
Lemma big_nseq I n a (F : I -> R):
\big[op/idx]_(i <- nseq n a) F i = iter n (op (F a)) idx.
Proof.
End Extensionality.
Variant big_enum_spec (I : finType) (P : pred I) : seq I -> Type :=
BigEnumSpec e of
forall R idx op (F : I -> R),
\big[op/idx]_(i <- e) F i = \big[op/idx]_(i | P i) F i
& uniq e /\ (forall i, (i \in e) = P i)
& (let cP := [pred i | P i] in perm_eq e (enum cP) /\ size e = #|cP|)
: big_enum_spec P e.
Lemma big_enumP I P : big_enum_spec P (filter P (index_enum I)).
Proof.
set e := filter P _; have Ue: uniq e by apply/filter_uniq/index_enum_uniq.
have mem_e i: (i \in e) = P i by rewrite mem_filter mem_index_enum andbT.
split=> // [R idx op F | cP]; first by rewrite big_filter.
suffices De: perm_eq e (enum cP) by rewrite (perm_size De) cardE.
by apply/uniq_perm=> // [|i]; rewrite ?enum_uniq ?mem_enum ?mem_e.
Qed.
have mem_e i: (i \in e) = P i by rewrite mem_filter mem_index_enum andbT.
split=> // [R idx op F | cP]; first by rewrite big_filter.
suffices De: perm_eq e (enum cP) by rewrite (perm_size De) cardE.
by apply/uniq_perm=> // [|i]; rewrite ?enum_uniq ?mem_enum ?mem_e.
Qed.
Section BigConst.
Variables (R : Type) (idx : R) (op : R -> R -> R).
Lemma big_const_seq I r (P : pred I) x :
\big[op/idx]_(i <- r | P i) x = iter (count P r) (op x) idx.
Proof.
Lemma big_const (I : finType) (A : {pred I}) x :
\big[op/idx]_(i in A) x = iter #|A| (op x) idx.
Proof.
Lemma big_const_nat m n x :
\big[op/idx]_(m <= i < n) x = iter (n - m) (op x) idx.
Proof.
Lemma big_const_ord n x :
\big[op/idx]_(i < n) x = iter n (op x) idx.
End BigConst.
Section Plain.
Variable R : Type.
Variable op : R -> R -> R.
Variable x : R.
Lemma big_seq1_id I (i : I) (F : I -> R) :
\big[op/x]_(j <- [:: i]) F j = op (F i) x.
Lemma big_nat1_id n F : \big[op/x]_(n <= i < n.+1) F i = op (F n) x.
Lemma big_pred1_eq_id (I : finType) (i : I) F :
\big[op/x]_(j | j == i) F j = op (F i) x.
Proof.
have [e1 <- _ [e_enum _]] := big_enumP (pred1 i).
by rewrite (perm_small_eq _ e_enum) enum1 ?big_seq1_id.
Qed.
by rewrite (perm_small_eq _ e_enum) enum1 ?big_seq1_id.
Qed.
Lemma big_pred1_id (I : finType) i (P : pred I) F :
P =1 pred1 i -> \big[op/x]_(j | P j) F j = op (F i) x.
Proof.
End Plain.
Section SemiGroupProperties.
Variable R : Type.
#[local] Notation opA := SemiGroup.opA.
#[local] Notation opC := SemiGroup.opC.
Section Id.
Variable op : SemiGroup.law R.
Variable x : R.
Hypothesis opxx : op x x = x.
Lemma big_const_idem I (r : seq I) P : \big[op/x]_(i <- r | P i) x = x.
Proof.
Lemma big1_idem I r (P : pred I) F :
(forall i, P i -> F i = x) -> \big[op/x]_(i <- r | P i) F i = x.
Proof.
Lemma big_id_idem I (r : seq I) P F :
op (\big[op/x]_(i <- r | P i) F i) x = \big[op/x]_(i <- r | P i) F i.
End Id.
Section Abelian.
Variable op : SemiGroup.com_law R.
Let opCA : left_commutative op.
Variable x : R.
Lemma big_rem_AC (I : eqType) (r : seq I) z (P : pred I) F : z \in r ->
\big[op/x]_(y <- r | P y) F y
= if P z then op (F z) (\big[op/x]_(y <- rem z r | P y) F y)
else \big[op/x]_(y <- rem z r | P y) F y.
Proof.
Lemma big_undup (I : eqType) (r : seq I) (P : pred I) F :
idempotent_op op ->
\big[op/x]_(i <- undup r | P i) F i = \big[op/x]_(i <- r | P i) F i.
Proof.
move=> opxx; rewrite -!(big_filter _ _ _ P) filter_undup.
elim: {P r}(filter P r) => //= i r IHr.
case: ifP => [r_i | _]; rewrite !big_cons {}IHr //.
by rewrite (big_rem_AC _ _ r_i) opA /= opxx.
Qed.
elim: {P r}(filter P r) => //= i r IHr.
case: ifP => [r_i | _]; rewrite !big_cons {}IHr //.
by rewrite (big_rem_AC _ _ r_i) opA /= opxx.
Qed.
Lemma perm_big (I : eqType) r1 r2 (P : pred I) F :
perm_eq r1 r2 ->
\big[op/x]_(i <- r1 | P i) F i = \big[op/x]_(i <- r2 | P i) F i.
Proof.
elim: r1 r2 => [|i r1 IHr1] r2 eq_r12.
by case: r2 eq_r12 => [//|i r2] /[1!perm_sym] /perm_nilP.
have r2i: i \in r2 by rewrite -has_pred1 has_count -(permP eq_r12) /= eqxx.
rewrite big_cons (IHr1 (rem i r2)) -?big_rem_AC// -(perm_cons i).
exact: perm_trans (perm_to_rem _).
Qed.
by case: r2 eq_r12 => [//|i r2] /[1!perm_sym] /perm_nilP.
have r2i: i \in r2 by rewrite -has_pred1 has_count -(permP eq_r12) /= eqxx.
rewrite big_cons (IHr1 (rem i r2)) -?big_rem_AC// -(perm_cons i).
exact: perm_trans (perm_to_rem _).
Qed.
Lemma big_enum_cond (I : finType) (A : {pred I}) (P : pred I) F :
\big[op/x]_(i <- enum A | P i) F i = \big[op/x]_(i in A | P i) F i.
Proof.
Lemma big_enum (I : finType) (A : {pred I}) F :
\big[op/x]_(i <- enum A) F i = \big[op/x]_(i in A) F i.
Proof.
Lemma big_uniq (I : finType) (r : seq I) F :
uniq r -> \big[op/x]_(i <- r) F i = \big[op/x]_(i in r) F i.
Proof.
Lemma bigD1 (I : finType) j (P : pred I) F :
P j -> \big[op/x]_(i | P i) F i
= op (F j) (\big[op/x]_(i | P i && (i != j)) F i).
Proof.
rewrite (big_rem_AC _ _ (mem_index_enum j)) => ->.
by rewrite rem_filter ?index_enum_uniq// big_filter_cond big_andbC.
Qed.
by rewrite rem_filter ?index_enum_uniq// big_filter_cond big_andbC.
Qed.
Lemma bigD1_seq (I : eqType) (r : seq I) j F :
j \in r -> uniq r ->
\big[op/x]_(i <- r) F i = op (F j) (\big[op/x]_(i <- r | i != j) F i).
Proof.
Lemma big_image_cond I (J : finType) (h : J -> I) (A : pred J) (P : pred I) F :
\big[op/x]_(i <- [seq h j | j in A] | P i) F i
= \big[op/x]_(j in A | P (h j)) F (h j).
Proof.
Lemma big_image I (J : finType) (h : J -> I) (A : pred J) F :
\big[op/x]_(i <- [seq h j | j in A]) F i = \big[op/x]_(j in A) F (h j).
Lemma cardD1x (I : finType) (A : pred I) j :
A j -> #|SimplPred A| = 1 + #|[pred i | A i & i != j]|.
Proof.
Lemma reindex_omap (I J : finType) (h : J -> I) h' (P : pred I) F :
(forall i, P i -> omap h (h' i) = some i) ->
\big[op/x]_(i | P i) F i =
\big[op/x]_(j | P (h j) && (h' (h j) == some j)) F (h j).
Proof.
move=> h'K; have [n lePn] := ubnP #|P|; elim: n => // n IHn in P h'K lePn *.
case: (pickP P) => [i Pi | P0]; last first.
by rewrite !big_pred0 // => j; rewrite P0.
have := h'K i Pi; case h'i_eq : (h' i) => [/= j|//] [hj_eq].
rewrite (bigD1 i Pi) (bigD1 j) hj_eq ?Pi ?h'i_eq ?eqxx //=; congr (op : _ -> _).
rewrite {}IHn => [k /andP[]||]; [by auto | by rewrite (cardD1x i) in lePn|].
apply: eq_bigl => k; rewrite andbC -andbA (andbCA (P _)); case: eqP => //= hK.
congr (_ && ~~ _); apply/eqP/eqP => [|->//].
by move=> /(congr1 h'); rewrite h'i_eq hK => -[].
Qed.
case: (pickP P) => [i Pi | P0]; last first.
by rewrite !big_pred0 // => j; rewrite P0.
have := h'K i Pi; case h'i_eq : (h' i) => [/= j|//] [hj_eq].
rewrite (bigD1 i Pi) (bigD1 j) hj_eq ?Pi ?h'i_eq ?eqxx //=; congr (op : _ -> _).
rewrite {}IHn => [k /andP[]||]; [by auto | by rewrite (cardD1x i) in lePn|].
apply: eq_bigl => k; rewrite andbC -andbA (andbCA (P _)); case: eqP => //= hK.
congr (_ && ~~ _); apply/eqP/eqP => [|->//].
by move=> /(congr1 h'); rewrite h'i_eq hK => -[].
Qed.
Lemma reindex_onto (I J : finType) (h : J -> I) h' (P : pred I) F :
(forall i, P i -> h (h' i) = i) ->
\big[op/x]_(i | P i) F i =
\big[op/x]_(j | P (h j) && (h' (h j) == j)) F (h j).
Proof.
Lemma reindex (I J : finType) (h : J -> I) (P : pred I) F :
{on [pred i | P i], bijective h} ->
\big[op/x]_(i | P i) F i = \big[op/x]_(j | P (h j)) F (h j).
Proof.
Lemma reindex_inj (I : finType) (h : I -> I) (P : pred I) F :
injective h -> \big[op/x]_(i | P i) F i = \big[op/x]_(j | P (h j)) F (h j).
Arguments reindex_inj [I h P F].
Lemma bigD1_ord n j (P : pred 'I_n) F :
P j -> \big[op/x]_(i < n | P i) F i
= op (F j) (\big[op/x]_(i < n.-1 | P (lift j i)) F (lift j i)).
Proof.
Lemma big_enum_val_cond (I : finType) (A : pred I) (P : pred I) F :
\big[op/x]_(x in A | P x) F x =
\big[op/x]_(i < #|A| | P (enum_val i)) F (enum_val i).
Proof.
have [A_eq0|/card_gt0P[x0 x0A]] := posnP #|A|.
rewrite !big_pred0 // => i; first by rewrite card0_eq.
by have: false by move: i => []; rewrite A_eq0.
rewrite (reindex (enum_val : 'I_#|A| -> I)).
by apply: subon_bij (enum_val_bij_in x0A) => y /andP[].
by apply: eq_big => [y|y Py]; rewrite ?enum_valP.
Qed.
rewrite !big_pred0 // => i; first by rewrite card0_eq.
by have: false by move: i => []; rewrite A_eq0.
rewrite (reindex (enum_val : 'I_#|A| -> I)).
by apply: subon_bij (enum_val_bij_in x0A) => y /andP[].
by apply: eq_big => [y|y Py]; rewrite ?enum_valP.
Qed.
Lemma big_enum_rank_cond (I : finType) (A : pred I) z (zA : z \in A) P F
(h := enum_rank_in zA) :
\big[op/x]_(i < #|A| | P i) F i = \big[op/x]_(s in A | P (h s)) F (h s).
Proof.
Lemma big_nat_rev m n P F :
\big[op/x]_(m <= i < n | P i) F i
= \big[op/x]_(m <= i < n | P (m + n - i.+1)) F (m + n - i.+1).
Proof.
Lemma big_rev_mkord m n P F :
\big[op/x]_(m <= k < n | P k) F k
= \big[op/x]_(k < n - m | P (n - k.+1)) F (n - k.+1).
Proof.
Section Id.
Hypothesis opxx : op x x = x.
Lemma big_mkcond_idem I r (P : pred I) F :
\big[op/x]_(i <- r | P i) F i = \big[op/x]_(i <- r) (if P i then F i else x).
Proof.
Lemma big_mkcondr_idem I r (P Q : pred I) F :
\big[op/x]_(i <- r | P i && Q i) F i =
\big[op/x]_(i <- r | P i) (if Q i then F i else x).
Proof.
Lemma big_mkcondl_idem I r (P Q : pred I) F :
\big[op/x]_(i <- r | P i && Q i) F i =
\big[op/x]_(i <- r | Q i) (if P i then F i else x).
Proof.
Lemma big_rmcond_idem I (r : seq I) (P : pred I) F :
(forall i, ~~ P i -> F i = x) ->
\big[op/x]_(i <- r | P i) F i = \big[op/x]_(i <- r) F i.
Proof.
Lemma big_rmcond_in_idem (I : eqType) (r : seq I) (P : pred I) F :
(forall i, i \in r -> ~~ P i -> F i = x) ->
\big[op/x]_(i <- r | P i) F i = \big[op/x]_(i <- r) F i.
Proof.
move=> F_eq1; rewrite big_seq_cond [RHS]big_seq_cond !big_mkcondl_idem.
by rewrite big_rmcond_idem => // i /F_eq1; case: ifP => // _ ->.
Qed.
by rewrite big_rmcond_idem => // i /F_eq1; case: ifP => // _ ->.
Qed.
Lemma big_cat_idem I r1 r2 (P : pred I) F :
\big[op/x]_(i <- r1 ++ r2 | P i) F i =
op (\big[op/x]_(i <- r1 | P i) F i) (\big[op/x]_(i <- r2 | P i) F i).
Proof.
Lemma big_allpairs_dep_idem I1 (I2 : I1 -> Type) J (h : forall i1, I2 i1 -> J)
(r1 : seq I1) (r2 : forall i1, seq (I2 i1)) (F : J -> R) :
\big[op/x]_(i <- [seq h i1 i2 | i1 <- r1, i2 <- r2 i1]) F i =
\big[op/x]_(i1 <- r1) \big[op/x]_(i2 <- r2 i1) F (h i1 i2).
Proof.
elim: r1 => [|i1 r1 IHr1]; first by rewrite !big_nil.
by rewrite big_cat_idem IHr1 big_cons big_map.
Qed.
by rewrite big_cat_idem IHr1 big_cons big_map.
Qed.
Lemma big_allpairs_idem I1 I2 (r1 : seq I1) (r2 : seq I2) F :
\big[op/x]_(i <- [seq (i1, i2) | i1 <- r1, i2 <- r2]) F i =
\big[op/x]_(i1 <- r1) \big[op/x]_(i2 <- r2) F (i1, i2).
Proof.
Lemma big_cat_nat_idem n m p (P : pred nat) F : m <= n -> n <= p ->
\big[op/x]_(m <= i < p | P i) F i =
op (\big[op/x]_(m <= i < n | P i) F i) (\big[op/x]_(n <= i < p | P i) F i).
Proof.
Lemma big_split_idem I r (P : pred I) F1 F2 :
\big[op/x]_(i <- r | P i) op (F1 i) (F2 i) =
op (\big[op/x]_(i <- r | P i) F1 i) (\big[op/x]_(i <- r | P i) F2 i).
Lemma big_id_idem_AC I (r : seq I) P F :
\big[op/x]_(i <- r | P i) op (F i) x = \big[op/x]_(i <- r | P i) F i.
Proof.
Lemma bigID_idem I r (a P : pred I) F :
\big[op/x]_(i <- r | P i) F i =
op (\big[op/x]_(i <- r | P i && a i) F i)
(\big[op/x]_(i <- r | P i && ~~ a i) F i).
Proof.
rewrite -big_id_idem_AC big_mkcond_idem !(big_mkcond_idem _ _ F) -big_split_idem.
by apply: eq_bigr => i; case: ifPn => //=; case: ifPn; rewrite // opC.
Qed.
by apply: eq_bigr => i; case: ifPn => //=; case: ifPn; rewrite // opC.
Qed.
Lemma bigU_idem (I : finType) (A B : pred I) F :
[disjoint A & B] ->
\big[op/x]_(i in [predU A & B]) F i =
op (\big[op/x]_(i in A) F i) (\big[op/x]_(i in B) F i).
Proof.
Lemma partition_big_idem I (s : seq I)
(J : finType) (P : pred I) (p : I -> J) (Q : pred J) F :
(forall i, P i -> Q (p i)) ->
\big[op/x]_(i <- s | P i) F i =
\big[op/x]_(j : J | Q j) \big[op/x]_(i <- s | (P i) && (p i == j)) F i.
Proof.
move=> Qp; transitivity (\big[op/x]_(i <- s | P i && Q (p i)) F i).
by apply: eq_bigl => i; case Pi: (P i); rewrite // Qp.
have [n leQn] := ubnP #|Q|; elim: n => // n IHn in Q {Qp} leQn *.
case: (pickP Q) => [j Qj | Q0]; last first.
by rewrite !big_pred0 // => i; rewrite Q0 andbF.
rewrite (bigD1 j) // -IHn; first by rewrite ltnS (cardD1x j Qj) in leQn.
rewrite (bigID_idem (fun i => p i == j)).
congr (op : _ -> _); apply: eq_bigl => i; last by rewrite andbA.
by case: eqP => [->|_]; rewrite !(Qj, andbT, andbF).
Qed.
by apply: eq_bigl => i; case Pi: (P i); rewrite // Qp.
have [n leQn] := ubnP #|Q|; elim: n => // n IHn in Q {Qp} leQn *.
case: (pickP Q) => [j Qj | Q0]; last first.
by rewrite !big_pred0 // => i; rewrite Q0 andbF.
rewrite (bigD1 j) // -IHn; first by rewrite ltnS (cardD1x j Qj) in leQn.
rewrite (bigID_idem (fun i => p i == j)).
congr (op : _ -> _); apply: eq_bigl => i; last by rewrite andbA.
by case: eqP => [->|_]; rewrite !(Qj, andbT, andbF).
Qed.
Arguments partition_big_idem [I s J P] p Q [F].
Lemma sig_big_dep_idem (I : finType) (J : I -> finType)
(P : pred I) (Q : forall {i}, pred (J i)) (F : forall {i}, J i -> R) :
\big[op/x]_(i | P i) \big[op/x]_(j : J i | Q j) F j =
\big[op/x]_(p : {i : I & J i} | P (tag p) && Q (tagged p)) F (tagged p).
Proof.
pose s := [seq Tagged J j | i <- index_enum I, j <- index_enum (J i)].
rewrite [LHS]big_mkcond_idem big_mkcondl_idem.
rewrite [RHS]big_mkcond_idem -[RHS](@perm_big _ s); last first.
rewrite big_allpairs_dep_idem/=; apply: eq_bigr => i _.
by rewrite -big_mkcond_idem/=; case: P; rewrite // big1_idem.
rewrite uniq_perm ?index_enum_uniq//.
by rewrite allpairs_uniq_dep// => [|i|[i j] []]; rewrite ?index_enum_uniq.
by move=> [i j]; rewrite ?mem_index_enum; apply/allpairsPdep; exists i, j.
Qed.
rewrite [LHS]big_mkcond_idem big_mkcondl_idem.
rewrite [RHS]big_mkcond_idem -[RHS](@perm_big _ s); last first.
rewrite big_allpairs_dep_idem/=; apply: eq_bigr => i _.
by rewrite -big_mkcond_idem/=; case: P; rewrite // big1_idem.
rewrite uniq_perm ?index_enum_uniq//.
by rewrite allpairs_uniq_dep// => [|i|[i j] []]; rewrite ?index_enum_uniq.
by move=> [i j]; rewrite ?mem_index_enum; apply/allpairsPdep; exists i, j.
Qed.
Lemma pair_big_dep_idem (I J : finType) (P : pred I) (Q : I -> pred J) F :
\big[op/x]_(i | P i) \big[op/x]_(j | Q i j) F i j =
\big[op/x]_(p | P p.1 && Q p.1 p.2) F p.1 p.2.
Proof.
Lemma pair_big_idem (I J : finType) (P : pred I) (Q : pred J) F :
\big[op/x]_(i | P i) \big[op/x]_(j | Q j) F i j =
\big[op/x]_(p | P p.1 && Q p.2) F p.1 p.2.
Proof.
Lemma pair_bigA_idem (I J : finType) (F : I -> J -> R) :
\big[op/x]_i \big[op/x]_j F i j = \big[op/x]_p F p.1 p.2.
Proof.
Lemma exchange_big_dep_idem I J rI rJ (P : pred I) (Q : I -> pred J)
(xQ : pred J) F :
(forall i j, P i -> Q i j -> xQ j) ->
\big[op/x]_(i <- rI | P i) \big[op/x]_(j <- rJ | Q i j) F i j =
\big[op/x]_(j <- rJ | xQ j) \big[op/x]_(i <- rI | P i && Q i j) F i j.
Proof.
move=> PQxQ; pose p u := (u.2, u.1).
under [LHS]eq_bigr do rewrite big_tnth; rewrite [LHS]big_tnth.
under [RHS]eq_bigr do rewrite big_tnth; rewrite [RHS]big_tnth.
rewrite !pair_big_dep_idem (reindex_onto (p _ _) (p _ _)) => [[]|] //=.
apply: eq_big => [] [j i] //=; symmetry; rewrite eqxx andbT andb_idl //.
by case/andP; apply: PQxQ.
Qed.
under [LHS]eq_bigr do rewrite big_tnth; rewrite [LHS]big_tnth.
under [RHS]eq_bigr do rewrite big_tnth; rewrite [RHS]big_tnth.
rewrite !pair_big_dep_idem (reindex_onto (p _ _) (p _ _)) => [[]|] //=.
apply: eq_big => [] [j i] //=; symmetry; rewrite eqxx andbT andb_idl //.
by case/andP; apply: PQxQ.
Qed.
Lemma exchange_big_idem I J rI rJ (P : pred I) (Q : pred J) F :
\big[op/x]_(i <- rI | P i) \big[op/x]_(j <- rJ | Q j) F i j =
\big[op/x]_(j <- rJ | Q j) \big[op/x]_(i <- rI | P i) F i j.
Proof.
rewrite (exchange_big_dep_idem Q) //.
by under eq_bigr => i Qi do under eq_bigl do rewrite Qi andbT.
Qed.
by under eq_bigr => i Qi do under eq_bigl do rewrite Qi andbT.
Qed.
Lemma exchange_big_dep_nat_idem m1 n1 m2 n2 (P : pred nat) (Q : rel nat)
(xQ : pred nat) F :
(forall i j, m1 <= i < n1 -> m2 <= j < n2 -> P i -> Q i j -> xQ j) ->
\big[op/x]_(m1 <= i < n1 | P i) \big[op/x]_(m2 <= j < n2 | Q i j) F i j =
\big[op/x]_(m2 <= j < n2 | xQ j)
\big[op/x]_(m1 <= i < n1 | P i && Q i j) F i j.
Proof.
move=> PQxQ; under eq_bigr do rewrite big_seq_cond.
rewrite big_seq_cond /= (exchange_big_dep_idem xQ) => [i j|].
by rewrite !mem_index_iota => /andP[mn_i Pi] /andP[mn_j /PQxQ->].
rewrite 2!(big_seq_cond _ _ _ xQ); apply: eq_bigr => j /andP[-> _] /=.
by rewrite [rhs in _ = rhs]big_seq_cond; apply: eq_bigl => i; rewrite -andbA.
Qed.
rewrite big_seq_cond /= (exchange_big_dep_idem xQ) => [i j|].
by rewrite !mem_index_iota => /andP[mn_i Pi] /andP[mn_j /PQxQ->].
rewrite 2!(big_seq_cond _ _ _ xQ); apply: eq_bigr => j /andP[-> _] /=.
by rewrite [rhs in _ = rhs]big_seq_cond; apply: eq_bigl => i; rewrite -andbA.
Qed.
Lemma exchange_big_nat_idem m1 n1 m2 n2 (P Q : pred nat) F :
\big[op/x]_(m1 <= i < n1 | P i) \big[op/x]_(m2 <= j < n2 | Q j) F i j =
\big[op/x]_(m2 <= j < n2 | Q j) \big[op/x]_(m1 <= i < n1 | P i) F i j.
Proof.
rewrite (exchange_big_dep_nat_idem Q) //.
by under eq_bigr => i Qi do under eq_bigl do rewrite Qi andbT.
Qed.
by under eq_bigr => i Qi do under eq_bigl do rewrite Qi andbT.
Qed.
End Id.
End Abelian.
End SemiGroupProperties.
Arguments big_undup [R op x I].
Arguments perm_big [R op x I r1 r2].
Arguments bigD1 [R op x I] j [P F].
Arguments reindex_omap [R op x I J] h h' [P F].
Arguments reindex_onto [R op x I J] h h' [P F].
Arguments reindex [R op x I J] h [P F].
Arguments reindex_inj [R op x I h P F].
Arguments big_enum_val_cond [R op x I A] P F.
Arguments big_enum_rank_cond [R op x I A z] zA P F.
Section MonoidProperties.
Import Monoid.Theory.
Variable R : Type.
Variable idx : R.
Local Notation "1" := idx.
Section Plain.
Variable op : Monoid.law 1.
Local Notation "*%M" := op.
Local Notation "x * y" := (op x y).
Lemma foldlE x r : foldl *%M x r = \big[*%M/1]_(y <- x :: r) y.
Lemma foldl_idx r : foldl *%M 1 r = \big[*%M/1]_(x <- r) x.
Lemma eq_big_idx_seq idx' I r (P : pred I) F :
right_id idx' *%M -> has P r ->
\big[*%M/idx']_(i <- r | P i) F i = \big[*%M/1]_(i <- r | P i) F i.
Proof.
move=> op_idx'; rewrite -!(big_filter _ _ r) has_count -size_filter.
case/lastP: (filter P r) => {r}// r i _.
by rewrite -cats1 !(big_cat_nested, big_cons, big_nil) op_idx' mulm1.
Qed.
case/lastP: (filter P r) => {r}// r i _.
by rewrite -cats1 !(big_cat_nested, big_cons, big_nil) op_idx' mulm1.
Qed.
Lemma eq_big_idx idx' (I : finType) i0 (P : pred I) F :
P i0 -> right_id idx' *%M ->
\big[*%M/idx']_(i | P i) F i = \big[*%M/1]_(i | P i) F i.
Proof.
Lemma big_change_idx I x r (P : pred I) F :
\big[*%M/x]_(j <- r | P j) F j = (\big[*%M/1]_(j <- r | P j) F j) * x.
Proof.
Lemma big1_eq I r (P : pred I) : \big[*%M/1]_(i <- r | P i) 1 = 1.
Lemma big1 I r (P : pred I) F :
(forall i, P i -> F i = 1) -> \big[*%M/1]_(i <- r | P i) F i = 1.
Lemma big1_seq (I : eqType) r (P : pred I) F :
(forall i, P i && (i \in r) -> F i = 1) ->
\big[*%M/1]_(i <- r | P i) F i = 1.
Proof.
Lemma big_seq1 I (i : I) F : \big[*%M/1]_(j <- [:: i]) F j = F i.
Proof.
Lemma big_rcons I i r (P : pred I) F :
\big[*%M/1]_(j <- rcons r i | P j) F j =
(\big[*%M/1]_(j <- r | P j) F j) * (if P i then F i else idx).
Proof.
Lemma big_mkcond I r (P : pred I) F :
\big[*%M/1]_(i <- r | P i) F i =
\big[*%M/1]_(i <- r) (if P i then F i else 1).
Lemma big_mkcondr I r (P Q : pred I) F :
\big[*%M/1]_(i <- r | P i && Q i) F i =
\big[*%M/1]_(i <- r | P i) (if Q i then F i else 1).
Proof.
Lemma big_mkcondl I r (P Q : pred I) F :
\big[*%M/1]_(i <- r | P i && Q i) F i =
\big[*%M/1]_(i <- r | Q i) (if P i then F i else 1).
Proof.
Lemma big_rmcond I (r : seq I) (P : pred I) F :
(forall i, ~~ P i -> F i = 1) ->
\big[*%M/1]_(i <- r | P i) F i = \big[*%M/1]_(i <- r) F i.
Proof.
Lemma big_rmcond_in (I : eqType) (r : seq I) (P : pred I) F :
(forall i, i \in r -> ~~ P i -> F i = 1) ->
\big[*%M/1]_(i <- r | P i) F i = \big[*%M/1]_(i <- r) F i.
Proof.
move=> F_eq1; rewrite big_seq_cond [RHS]big_seq_cond !big_mkcondl big_rmcond//.
by move=> i /F_eq1; case: ifP => // _ ->.
Qed.
by move=> i /F_eq1; case: ifP => // _ ->.
Qed.
Lemma big_cat I r1 r2 (P : pred I) F :
\big[*%M/1]_(i <- r1 ++ r2 | P i) F i =
\big[*%M/1]_(i <- r1 | P i) F i * \big[*%M/1]_(i <- r2 | P i) F i.
Proof.
Lemma big_allpairs_dep I1 (I2 : I1 -> Type) J (h : forall i1, I2 i1 -> J)
(r1 : seq I1) (r2 : forall i1, seq (I2 i1)) (F : J -> R) :
\big[*%M/1]_(i <- [seq h i1 i2 | i1 <- r1, i2 <- r2 i1]) F i =
\big[*%M/1]_(i1 <- r1) \big[*%M/1]_(i2 <- r2 i1) F (h i1 i2).
Proof.
Lemma big_allpairs I1 I2 (r1 : seq I1) (r2 : seq I2) F :
\big[*%M/1]_(i <- [seq (i1, i2) | i1 <- r1, i2 <- r2]) F i =
\big[*%M/1]_(i1 <- r1) \big[op/idx]_(i2 <- r2) F (i1, i2).
Proof.
Lemma rev_big_rev I (r : seq I) P F :
\big[*%M/1]_(i <- rev r | P i) F i =
\big[(fun x y => y * x)/1]_(i <- r | P i) F i.
Proof.
Lemma big_only1 (I : finType) (i : I) (P : pred I) (F : I -> R) : P i ->
(forall j, j != i -> P j -> F j = idx) ->
\big[op/idx]_(j | P j) F j = F i.
Proof.
move=> Pi Fisx; have := index_enum_uniq I.
have : i \in index_enum I by rewrite mem_index_enum.
elim: index_enum => //= j r IHr /[!inE]; case: eqVneq => [<-|nij]//=.
move=> _ /andP[iNr runiq]; rewrite big_cons/= Pi big1_seq ?Monoid.mulm1//.
by move=> {}j /andP[/Fisx + jr] => ->//; apply: contraNneq iNr => <-.
move=> ir /andP[jNr runiq]; rewrite big_cons IHr//.
by case: ifPn => // /Fisx->; rewrite 1?eq_sym// Monoid.mul1m.
Qed.
have : i \in index_enum I by rewrite mem_index_enum.
elim: index_enum => //= j r IHr /[!inE]; case: eqVneq => [<-|nij]//=.
move=> _ /andP[iNr runiq]; rewrite big_cons/= Pi big1_seq ?Monoid.mulm1//.
by move=> {}j /andP[/Fisx + jr] => ->//; apply: contraNneq iNr => <-.
move=> ir /andP[jNr runiq]; rewrite big_cons IHr//.
by case: ifPn => // /Fisx->; rewrite 1?eq_sym// Monoid.mul1m.
Qed.
Lemma big_pred1_eq (I : finType) (i : I) F : \big[*%M/1]_(j | j == i) F j = F i.
Lemma big_pred1 (I : finType) i (P : pred I) F :
P =1 pred1 i -> \big[*%M/1]_(j | P j) F j = F i.
Proof.
Lemma big_ord1 F : \big[op/idx]_(i < 1) F i = F ord0.
Proof.
Lemma big_ord1_cond P F :
\big[op/idx]_(i < 1 | P i) F i = if P ord0 then F ord0 else idx.
Proof.
Lemma big_ord1_eq (F : nat -> R) i n :
\big[op/idx]_(j < n | j == i :> nat) F j = if i < n then F i else idx.
Proof.
case: ltnP => [i_lt|i_ge]; first by rewrite (big_pred1_eq (Ordinal _)).
by rewrite big_pred0// => j; apply: contra_leqF i_ge => /eqP <-.
Qed.
by rewrite big_pred0// => j; apply: contra_leqF i_ge => /eqP <-.
Qed.
Lemma big_ord1_cond_eq (F : nat -> R) (P : pred nat) i n :
\big[op/idx]_(j < n | P j && (j == i :> nat)) F j =
if (i < n) && P i then F i else idx.
Proof.
Lemma big_cat_nat n m p (P : pred nat) F : m <= n -> n <= p ->
\big[*%M/1]_(m <= i < p | P i) F i =
(\big[*%M/1]_(m <= i < n | P i) F i) * (\big[*%M/1]_(n <= i < p | P i) F i).
Proof.
Lemma big_nat_widenl (m1 m2 n : nat) (P : pred nat) F :
m2 <= m1 ->
\big[op/idx]_(m1 <= i < n | P i) F i =
\big[op/idx]_(m2 <= i < n | P i && (m1 <= i)) F i.
Proof.
move=> le_m21; have [le_nm1|lt_m1n] := leqP n m1.
rewrite big_geq// big_nat_cond big1//.
by move=> i /and3P[/andP[_ /leq_trans/(_ le_nm1)/ltn_geF->]].
rewrite big_mkcond big_mkcondl (big_cat_nat _ _ le_m21) 1?ltnW//.
rewrite [X in op X]big_nat_cond [X in op X]big_pred0.
by move=> k; case: ltnP; rewrite andbF.
by rewrite Monoid.mul1m; apply: congr_big_nat => // k /andP[].
Qed.
rewrite big_geq// big_nat_cond big1//.
by move=> i /and3P[/andP[_ /leq_trans/(_ le_nm1)/ltn_geF->]].
rewrite big_mkcond big_mkcondl (big_cat_nat _ _ le_m21) 1?ltnW//.
rewrite [X in op X]big_nat_cond [X in op X]big_pred0.
by move=> k; case: ltnP; rewrite andbF.
by rewrite Monoid.mul1m; apply: congr_big_nat => // k /andP[].
Qed.
Lemma big_geq_mkord (m n : nat) (P : pred nat) F :
\big[op/idx]_(m <= i < n | P i) F i =
\big[op/idx]_(i < n | P i && (m <= i)) F i.
Proof.
Lemma big_nat1_eq (F : nat -> R) i m n :
\big[op/idx]_(m <= j < n | j == i) F j = if m <= i < n then F i else idx.
Proof.
Lemma big_nat1_cond_eq (F : nat -> R) (P : pred nat) i m n :
\big[op/idx]_(m <= j < n | P j && (j == i)) F j =
if (m <= i < n) && P i then F i else idx.
Proof.
Lemma big_nat1 n F : \big[*%M/1]_(n <= i < n.+1) F i = F n.
Lemma big_nat_recr n m F : m <= n ->
\big[*%M/1]_(m <= i < n.+1) F i = (\big[*%M/1]_(m <= i < n) F i) * F n.
Proof.
Lemma big_nat_mul n k F :
\big[*%M/1]_(0 <= i < n * k) F i =
\big[*%M/1]_(0 <= i < n) \big[*%M/1]_(i * k <= j < i.+1 * k) F j.
Proof.
elim: n => [|n ih]; first by rewrite mul0n 2!big_nil.
rewrite [in RHS]big_nat_recr//= -ih mulSn addnC [in LHS]/index_iota subn0 iotaD.
rewrite big_cat /= [in X in _ = X * _]/index_iota subn0; congr (_ * _).
by rewrite add0n /index_iota (addnC _ k) addnK.
Qed.
rewrite [in RHS]big_nat_recr//= -ih mulSn addnC [in LHS]/index_iota subn0 iotaD.
rewrite big_cat /= [in X in _ = X * _]/index_iota subn0; congr (_ * _).
by rewrite add0n /index_iota (addnC _ k) addnK.
Qed.
Lemma big_ord_recr n F :
\big[*%M/1]_(i < n.+1) F i =
(\big[*%M/1]_(i < n) F (widen_ord (leqnSn n) i)) * F ord_max.
Proof.
transitivity (\big[*%M/1]_(0 <= i < n.+1) F (inord i)).
by rewrite big_mkord; apply: eq_bigr=> i _; rewrite inord_val.
rewrite big_nat_recr // big_mkord; congr (_ * F _); last first.
by apply: val_inj; rewrite /= inordK.
by apply: eq_bigr => [] i _; congr F; apply: ord_inj; rewrite inordK //= leqW.
Qed.
by rewrite big_mkord; apply: eq_bigr=> i _; rewrite inord_val.
rewrite big_nat_recr // big_mkord; congr (_ * F _); last first.
by apply: val_inj; rewrite /= inordK.
by apply: eq_bigr => [] i _; congr F; apply: ord_inj; rewrite inordK //= leqW.
Qed.
Lemma big_sumType (I1 I2 : finType) (P : pred (I1 + I2)) F :
\big[*%M/1]_(i | P i) F i =
(\big[*%M/1]_(i | P (inl _ i)) F (inl _ i))
* (\big[*%M/1]_(i | P (inr _ i)) F (inr _ i)).
Lemma big_split_ord m n (P : pred 'I_(m + n)) F :
\big[*%M/1]_(i | P i) F i =
(\big[*%M/1]_(i | P (lshift n i)) F (lshift n i))
* (\big[*%M/1]_(i | P (rshift m i)) F (rshift m i)).
Proof.
Lemma big_cat_ordfun m n (F : R ^ m) (G : R ^ n) :
\big[*%M/1]_i cat_ordfun F G i = (\big[*%M/1]_i F i) * (\big[*%M/1]_i G i).
Proof.
Lemma big_flatten I rr (P : pred I) F :
\big[*%M/1]_(i <- flatten rr | P i) F i
= \big[*%M/1]_(r <- rr) \big[*%M/1]_(i <- r | P i) F i.
Lemma big_pmap J I (h : J -> option I) (r : seq J) F :
\big[op/idx]_(i <- pmap h r) F i = \big[op/idx]_(j <- r) oapp F idx (h j).
Proof.
Lemma telescope_big (f : nat -> nat -> R) (n m : nat) :
(forall k, n < k < m -> op (f n k) (f k k.+1) = f n k.+1) ->
\big[op/idx]_(n <= i < m) f i i.+1 = if n < m then f n m else idx.
Proof.
End Plain.
Section Abelian.
Variable op : Monoid.com_law 1.
Local Notation "'*%M'" := op.
Local Notation "x * y" := (op x y).
Lemma big_rem (I : eqType) r x (P : pred I) F :
x \in r ->
\big[*%M/1]_(y <- r | P y) F y
= (if P x then F x else 1) * \big[*%M/1]_(y <- rem x r | P y) F y.
Proof.
Lemma big_rev I (r : seq I) P F :
\big[*%M/1]_(i <- rev r | P i) F i = \big[*%M/1]_(i <- r | P i) F i.
Proof.
Lemma eq_big_idem (I : eqType) (r1 r2 : seq I) (P : pred I) F :
idempotent_op *%M -> r1 =i r2 ->
\big[*%M/1]_(i <- r1 | P i) F i = \big[*%M/1]_(i <- r2 | P i) F i.
Proof.
Lemma big_undup_iterop_count (I : eqType) (r : seq I) (P : pred I) F :
\big[*%M/1]_(i <- undup r | P i) iterop (count_mem i r) *%M (F i) 1
= \big[*%M/1]_(i <- r | P i) F i.
Proof.
rewrite -[RHS](perm_big _ F (perm_count_undup _)) big_flatten big_map.
by rewrite [LHS]big_mkcond; apply: eq_bigr=> i _; rewrite big_nseq_cond iteropE.
Qed.
by rewrite [LHS]big_mkcond; apply: eq_bigr=> i _; rewrite big_nseq_cond iteropE.
Qed.
Lemma big_split I r (P : pred I) F1 F2 :
\big[*%M/1]_(i <- r | P i) (F1 i * F2 i) =
\big[*%M/1]_(i <- r | P i) F1 i * \big[*%M/1]_(i <- r | P i) F2 i.
Proof.
Lemma bigID I r (a P : pred I) F :
\big[*%M/1]_(i <- r | P i) F i =
\big[*%M/1]_(i <- r | P i && a i) F i *
\big[*%M/1]_(i <- r | P i && ~~ a i) F i.
Proof.
Lemma big_if I r (P Q : pred I) F G :
\big[*%M/1]_(i <- r | P i) (if Q i then F i else G i) =
\big[*%M/1]_(i <- r | P i && Q i) F i *
\big[*%M/1]_(i <- r | P i && ~~ Q i) G i.
Proof.
Lemma bigU (I : finType) (A B : pred I) F :
[disjoint A & B] ->
\big[*%M/1]_(i in [predU A & B]) F i =
(\big[*%M/1]_(i in A) F i) * (\big[*%M/1]_(i in B) F i).
Lemma partition_big I (s : seq I)
(J : finType) (P : pred I) (p : I -> J) (Q : pred J) F :
(forall i, P i -> Q (p i)) ->
\big[*%M/1]_(i <- s | P i) F i =
\big[*%M/1]_(j : J | Q j) \big[*%M/1]_(i <- s | (P i) && (p i == j)) F i.
Proof.
move=> Qp; transitivity (\big[*%M/1]_(i <- s | P i && Q (p i)) F i).
by apply: eq_bigl => i; case Pi: (P i); rewrite // Qp.
have [n leQn] := ubnP #|Q|; elim: n => // n IHn in Q {Qp} leQn *.
case: (pickP Q) => [j Qj | Q0]; last first.
by rewrite !big_pred0 // => i; rewrite Q0 andbF.
rewrite (bigD1 j) // -IHn; first by rewrite ltnS (cardD1x Qj) in leQn.
rewrite (bigID (fun i => p i == j)); congr (_ * _); apply: eq_bigl => i.
by case: eqP => [-> | _]; rewrite !(Qj, simpm).
by rewrite andbA.
Qed.
by apply: eq_bigl => i; case Pi: (P i); rewrite // Qp.
have [n leQn] := ubnP #|Q|; elim: n => // n IHn in Q {Qp} leQn *.
case: (pickP Q) => [j Qj | Q0]; last first.
by rewrite !big_pred0 // => i; rewrite Q0 andbF.
rewrite (bigD1 j) // -IHn; first by rewrite ltnS (cardD1x Qj) in leQn.
rewrite (bigID (fun i => p i == j)); congr (_ * _); apply: eq_bigl => i.
by case: eqP => [-> | _]; rewrite !(Qj, simpm).
by rewrite andbA.
Qed.
Arguments partition_big [I s J P] p Q [F].
Lemma big_enum_val (I : finType) (A : pred I) F :
\big[op/idx]_(x in A) F x = \big[op/idx]_(i < #|A|) F (enum_val i).
Proof.
Lemma big_enum_rank (I : finType) (A : pred I) x (xA : x \in A) F
(h := enum_rank_in xA) :
\big[op/idx]_(i < #|A|) F i = \big[op/idx]_(s in A) F (h s).
Proof.
Lemma big_sub_cond (I : finType) (A P : {pred I}) (F : I -> R) :
\big[*%M/1]_(i in A | P i) F i =
\big[*%M/1]_(x : {x in A} | P (val x)) F (val x).
Proof.
Lemma big_sub (I : finType) (A : {pred I}) (F : I -> R) :
\big[*%M/1]_(i in A) F i = \big[*%M/1]_(x : {x in A}) F (val x).
Proof.
Lemma sig_big_dep (I : finType) (J : I -> finType)
(P : pred I) (Q : forall {i}, pred (J i)) (F : forall {i}, J i -> R) :
\big[op/idx]_(i | P i) \big[op/idx]_(j : J i | Q j) F j =
\big[op/idx]_(p : {i : I & J i} | P (tag p) && Q (tagged p)) F (tagged p).
Proof.
Lemma pair_big_dep (I J : finType) (P : pred I) (Q : I -> pred J) F :
\big[*%M/1]_(i | P i) \big[*%M/1]_(j | Q i j) F i j =
\big[*%M/1]_(p | P p.1 && Q p.1 p.2) F p.1 p.2.
Proof.
Lemma pair_big (I J : finType) (P : pred I) (Q : pred J) F :
\big[*%M/1]_(i | P i) \big[*%M/1]_(j | Q j) F i j =
\big[*%M/1]_(p | P p.1 && Q p.2) F p.1 p.2.
Proof.
Lemma pair_bigA (I J : finType) (F : I -> J -> R) :
\big[*%M/1]_i \big[*%M/1]_j F i j = \big[*%M/1]_p F p.1 p.2.
Proof.
Lemma exchange_big_dep I J rI rJ (P : pred I) (Q : I -> pred J)
(xQ : pred J) F :
(forall i j, P i -> Q i j -> xQ j) ->
\big[*%M/1]_(i <- rI | P i) \big[*%M/1]_(j <- rJ | Q i j) F i j =
\big[*%M/1]_(j <- rJ | xQ j) \big[*%M/1]_(i <- rI | P i && Q i j) F i j.
Proof.
Lemma exchange_big I J rI rJ (P : pred I) (Q : pred J) F :
\big[*%M/1]_(i <- rI | P i) \big[*%M/1]_(j <- rJ | Q j) F i j =
\big[*%M/1]_(j <- rJ | Q j) \big[*%M/1]_(i <- rI | P i) F i j.
Proof.
Lemma exchange_big_dep_nat m1 n1 m2 n2 (P : pred nat) (Q : rel nat)
(xQ : pred nat) F :
(forall i j, m1 <= i < n1 -> m2 <= j < n2 -> P i -> Q i j -> xQ j) ->
\big[*%M/1]_(m1 <= i < n1 | P i) \big[*%M/1]_(m2 <= j < n2 | Q i j) F i j =
\big[*%M/1]_(m2 <= j < n2 | xQ j)
\big[*%M/1]_(m1 <= i < n1 | P i && Q i j) F i j.
Proof.
Lemma exchange_big_nat m1 n1 m2 n2 (P Q : pred nat) F :
\big[*%M/1]_(m1 <= i < n1 | P i) \big[*%M/1]_(m2 <= j < n2 | Q j) F i j =
\big[*%M/1]_(m2 <= j < n2 | Q j) \big[*%M/1]_(m1 <= i < n1 | P i) F i j.
Proof.
End Abelian.
End MonoidProperties.
Arguments big_filter [R idx op I].
Arguments big_filter_cond [R idx op I].
Arguments congr_big [R idx op I r1] r2 [P1] P2 [F1] F2.
Arguments eq_big [R idx op I r P1] P2 [F1] F2.
Arguments eq_bigl [R idx op I r P1] P2.
Arguments eq_bigr [R idx op I r P F1] F2.
Arguments eq_big_idx [R idx op idx' I] i0 [P F].
Arguments big_seq_cond [R idx op I r].
Arguments eq_big_seq [R idx op I r F1] F2.
Arguments congr_big_nat [R idx op m1 n1] m2 n2 [P1] P2 [F1] F2.
Arguments big_map [R idx op I J] h [r].
Arguments big_nth [R idx op I] x0 [r].
Arguments big_catl [R idx op I r1 r2 P F].
Arguments big_catr [R idx op I r1 r2 P F].
Arguments big_geq [R idx op m n P F].
Arguments big_ltn_cond [R idx op m n P F].
Arguments big_ltn [R idx op m n F].
Arguments big_addn [R idx op].
Arguments big_mkord [R idx op n].
Arguments big_nat_widen [R idx op].
Arguments big_nat_widenl [R idx op].
Arguments big_geq_mkord [R idx op].
Arguments big_ord_widen_cond [R idx op n1].
Arguments big_ord_widen [R idx op n1].
Arguments big_ord_widen_leq [R idx op n1].
Arguments big_ord_narrow_cond [R idx op n1 n2 P F].
Arguments big_ord_narrow_cond_leq [R idx op n1 n2 P F].
Arguments big_ord_narrow [R idx op n1 n2 F].
Arguments big_ord_narrow_leq [R idx op n1 n2 F].
Arguments big_mkcond [R idx op I r].
Arguments big1_eq [R idx op I].
Arguments big1_seq [R idx op I].
Arguments big1 [R idx op I].
Arguments big_only1 {R idx op I} i [P F].
Arguments big_pred1 [R idx op I] i [P F].
Arguments perm_big [R op x I r1] r2 [P F].
Arguments big_uniq [R op x I] r [F].
Arguments big_rem [R idx op I r] x [P F].
Arguments bigID [R idx op I r].
Arguments bigU [R idx op I].
Arguments bigD1 [R op x I] j [P F].
Arguments bigD1_seq [R op x I r] j [F].
Arguments bigD1_ord [R op x n] j [P F].
Arguments partition_big [R idx op I s J P] p Q [F].
Arguments reindex_omap [R op x I J] h h' [P F].
Arguments reindex_onto [R op x I J] h h' [P F].
Arguments reindex [R op x I J] h [P F].
Arguments reindex_inj [R op x I h P F].
Arguments big_enum_val_cond [R op x I A] P F.
Arguments big_enum_rank_cond [R op x I A z] zA P F.
Arguments big_enum_val [R idx op I A] F.
Arguments big_enum_rank [R idx op I A x] xA F.
Arguments big_sub_cond [R idx op I].
Arguments big_sub [R idx op I].
Arguments sig_big_dep [R idx op I J].
Arguments pair_big_dep [R idx op I J].
Arguments pair_big [R idx op I J].
Arguments big_allpairs_dep {R idx op I1 I2 J h r1 r2 F}.
Arguments big_allpairs {R idx op I1 I2 r1 r2 F}.
Arguments exchange_big_dep [R idx op I J rI rJ P Q] xQ [F].
Arguments exchange_big_dep_nat [R idx op m1 n1 m2 n2 P Q] xQ [F].
Arguments big_ord_recl [R idx op].
Arguments big_ord_recr [R idx op].
Arguments big_nat_recl [R idx op].
Arguments big_nat_recr [R idx op].
Arguments big_cat_nat_idem [R op x] opxx [n m p P F].
Arguments big_cat_nat [R idx op n m p P F].
Arguments big_pmap [R idx op J I] h [r].
Arguments telescope_big [R idx op] f [n m].
Section SemiGroupWithOneCommutativeAndIdempotent.
Import Monoid.
Variables (R : Type) (op : SemiGroup.law R).
Context [x : R].
Hypothesis opxx : op x x = x.
Hypothesis opxC : forall a, op x a = op a x.
Lemma big_split_ord_idem m n (P : pred 'I_(m + n)) F :
\big[op/x]_(i | P i) F i =
op (\big[op/x]_(i | P (lshift n i)) F (lshift n i))
(\big[op/x]_(i | P (rshift m i)) F (rshift m i)).
Proof.
End SemiGroupWithOneCommutativeAndIdempotent.
Section IncreasingSemiGroup.
Import Monoid.
Variables (R : Type) (op : SemiGroup.com_law R).
Variable le : rel R.
Hypothesis le_refl : reflexive le.
Hypothesis op_incr : forall x y, le x (op x y).
Context [x : R].
Local Notation mk := (big_mk_option_monoid op).
Lemma sub_le_big I [s] (P P' : {pred I}) (F : I -> R) :
(forall i, P i -> P' i) ->
le (\big[op/x]_(i <- s | P i) F i) (\big[op/x]_(i <- s | P' i) F i).
Proof.
Lemma sub_le_big_seq (I : eqType) s s' P (F : I -> R) :
(forall i, count_mem i s <= count_mem i s')%N ->
le (\big[op/x]_(i <- s | P i) F i) (\big[op/x]_(i <- s' | P i) F i).
Proof.
rewrite mk => /count_subseqP[_ /subseqP[m sm ->]].
move/(perm_big _)->; rewrite big_mask [X in le _ X]big_tnth.
by rewrite -!mk sub_le_big // => j /andP[].
Qed.
move/(perm_big _)->; rewrite big_mask [X in le _ X]big_tnth.
by rewrite -!mk sub_le_big // => j /andP[].
Qed.
Lemma sub_le_big_seq_cond (I : eqType) s s' P P' (F : I -> R) :
(forall i, count_mem i (filter P s) <= count_mem i (filter P' s'))%N ->
le (\big[op/x]_(i <- s | P i) F i) (\big[op/x]_(i <- s' | P' i) F i).
Proof.
Lemma uniq_sub_le_big (I : eqType) s s' P (F : I -> R) : uniq s -> uniq s' ->
{subset s <= s'} ->
le (\big[op/x]_(i <- s | P i) F i) (\big[op/x]_(i <- s' | P i) F i).
Proof.
move=> us us' ss'; rewrite sub_le_big_seq => // i; rewrite !count_uniq_mem//.
by have /implyP := ss' i; case: (_ \in s) (_ \in s') => [] [].
Qed.
by have /implyP := ss' i; case: (_ \in s) (_ \in s') => [] [].
Qed.
Lemma uniq_sub_le_big_cond (I : eqType) s s' P P' (F : I -> R) :
uniq (filter P s) -> uniq (filter P' s') ->
{subset [seq i <- s | P i] <= [seq i <- s' | P' i]} ->
le (\big[op/x]_(i <- s | P i) F i) (\big[op/x]_(i <- s' | P' i) F i).
Proof.
Section Id.
Hypothesis opK : idempotent_op op.
Lemma idem_sub_le_big (I : eqType) s s' P (F : I -> R) :
{subset s <= s'} ->
le (\big[op/x]_(i <- s | P i) F i) (\big[op/x]_(i <- s' | P i) F i).
Proof.
move=> ss'; rewrite -big_undup// -[X in le _ X]big_undup//.
by rewrite uniq_sub_le_big ?undup_uniq// => i; rewrite !mem_undup; apply: ss'.
Qed.
by rewrite uniq_sub_le_big ?undup_uniq// => i; rewrite !mem_undup; apply: ss'.
Qed.
Lemma idem_sub_le_big_cond (I : eqType) s s' P P' (F : I -> R) :
{subset [seq i <- s | P i] <= [seq i <- s' | P' i]} ->
le (\big[op/x]_(i <- s | P i) F i) (\big[op/x]_(i <- s' | P' i) F i).
Proof.
End Id.
Lemma sub_in_le_big [I : eqType] (s : seq I) (P P' : {pred I}) (F : I -> R) :
{in s, forall i, P i -> P' i} ->
le (\big[op/x]_(i <- s | P i) F i) (\big[op/x]_(i <- s | P' i) F i).
Proof.
move=> PP'; apply: sub_le_big_seq_cond => i; rewrite leq_count_subseq//.
rewrite subseq_filter filter_subseq andbT; apply/allP => j.
by rewrite !mem_filter => /andP[/PP'/[apply]->].
Qed.
rewrite subseq_filter filter_subseq andbT; apply/allP => j.
by rewrite !mem_filter => /andP[/PP'/[apply]->].
Qed.
Lemma le_big_ord n m [P : {pred nat}] [F : nat -> R] : (n <= m)%N ->
le (\big[op/x]_(i < n | P i) F i) (\big[op/x]_(i < m | P i) F i).
Proof.
Lemma subset_le_big [I : finType] [A A' P : {pred I}] (F : I -> R) :
A \subset A' ->
le (\big[op/x]_(i in A | P i) F i) (\big[op/x]_(i in A' | P i) F i).
Proof.
Lemma le_big_nat_cond n m n' m' (P P' : {pred nat}) (F : nat -> R) :
(n' <= n)%N -> (m <= m')%N -> (forall i, (n <= i < m)%N -> P i -> P' i) ->
le (\big[op/x]_(n <= i < m | P i) F i) (\big[op/x]_(n' <= i < m' | P' i) F i).
Proof.
move=> len'n lemm' PP'i; rewrite uniq_sub_le_big_cond ?filter_uniq ?iota_uniq//.
move=> i; rewrite !mem_filter !mem_index_iota => /and3P[Pi ni im].
by rewrite PP'i ?ni//= (leq_trans _ ni)// (leq_trans im).
Qed.
move=> i; rewrite !mem_filter !mem_index_iota => /and3P[Pi ni im].
by rewrite PP'i ?ni//= (leq_trans _ ni)// (leq_trans im).
Qed.
Lemma le_big_nat n m n' m' [P] [F : nat -> R] : (n' <= n)%N -> (m <= m')%N ->
le (\big[op/x]_(n <= i < m | P i) F i) (\big[op/x]_(n' <= i < m' | P i) F i).
Proof.
Lemma le_big_ord_cond n m (P P' : {pred nat}) (F : nat -> R) :
(n <= m)%N -> (forall i : 'I_n, P i -> P' i) ->
le (\big[op/x]_(i < n | P i) F i) (\big[op/x]_(i < m | P' i) F i).
Proof.
End IncreasingSemiGroup.
Section EqSupport.
Variables (R : eqType) (idx : R).
Section MonoidSupport.
Variables (op : Monoid.law idx) (I : Type).
Lemma eq_bigl_supp (r : seq I) (P1 : pred I) (P2 : pred I) (F : I -> R) :
{in [pred x | F x != idx], P1 =1 P2} ->
\big[op/idx]_(i <- r | P1 i) F i = \big[op/idx]_(i <- r | P2 i) F i.
Proof.
move=> P12; rewrite big_mkcond [RHS]big_mkcond; apply: eq_bigr => i _.
by case: (eqVneq (F i) idx) => [->|/P12->]; rewrite ?if_same.
Qed.
by case: (eqVneq (F i) idx) => [->|/P12->]; rewrite ?if_same.
Qed.
End MonoidSupport.
Section ComoidSupport.
Variables (op : Monoid.com_law idx) (I : eqType).
Lemma perm_big_supp_cond [r s : seq I] [P : pred I] (F : I -> R) :
perm_eq
[seq i <- r | P i && (F i != idx)]
[seq i <- s | P i && (F i != idx)] ->
\big[op/idx]_(i <- r | P i) F i = \big[op/idx]_(i <- s | P i) F i.
Proof.
Lemma perm_big_supp [r s : seq I] [P : pred I] (F : I -> R) :
perm_eq [seq i <- r | F i != idx] [seq i <- s | F i != idx] ->
\big[op/idx]_(i <- r | P i) F i = \big[op/idx]_(i <- s | P i) F i.
Proof.
End ComoidSupport.
End EqSupport.
Arguments eq_bigl_supp [R idx op I r P1].
Arguments perm_big_supp_cond [R idx op I r s P].
Arguments perm_big_supp [R idx op I r s P].
Section Distributivity.
Import Monoid.Theory.
Variable R : Type.
Variables zero one : R.
Local Notation "0" := zero.
Local Notation "1" := one.
Variable times : Monoid.mul_law 0.
Local Notation "*%M" := times.
Local Notation "x * y" := (times x y).
Variable plus : Monoid.add_law 0 *%M.
Local Notation "+%M" := plus.
Local Notation "x + y" := (plus x y).
Lemma big_distrl I r a (P : pred I) F :
\big[+%M/0]_(i <- r | P i) F i * a = \big[+%M/0]_(i <- r | P i) (F i * a).
Lemma big_distrr I r a (P : pred I) F :
a * \big[+%M/0]_(i <- r | P i) F i = \big[+%M/0]_(i <- r | P i) (a * F i).
Lemma big_distrlr I J rI rJ (pI : pred I) (pJ : pred J) F G :
(\big[+%M/0]_(i <- rI | pI i) F i) * (\big[+%M/0]_(j <- rJ | pJ j) G j)
= \big[+%M/0]_(i <- rI | pI i) \big[+%M/0]_(j <- rJ | pJ j) (F i * G j).
Proof.
Lemma big_distr_big_dep (I J : finType) j0 (P : pred I) (Q : I -> pred J) F :
\big[*%M/1]_(i | P i) \big[+%M/0]_(j | Q i j) F i j =
\big[+%M/0]_(f in pfamily j0 P Q) \big[*%M/1]_(i | P i) F i (f i).
Proof.
pose fIJ := {ffun I -> J}; pose Pf := pfamily j0 (_ : seq I) Q.
have [r big_r [Ur mem_r] _] := big_enumP P.
symmetry; transitivity (\big[+%M/0]_(f in Pf r) \big[*%M/1]_(i <- r) F i (f i)).
by apply: eq_big => // f; apply: eq_forallb => i; rewrite /= mem_r.
rewrite -{P mem_r}big_r; elim: r Ur => /= [_ | i r IHr].
rewrite (big_pred1 [ffun=> j0]) ?big_nil //= => f.
apply/familyP/eqP=> /= [Df |->{f} i]; last by rewrite ffunE !inE.
by apply/ffunP=> i; rewrite ffunE; apply/eqP/Df.
case/andP=> /negbTE nri; rewrite big_cons big_distrl => {}/IHr<-.
rewrite (partition_big (fun f : fIJ => f i) (Q i)) => [f|].
by move/familyP/(_ i); rewrite /= inE /= eqxx.
pose seti j (f : fIJ) := [ffun k => if k == i then j else f k].
apply: eq_bigr => j Qij.
rewrite (reindex_onto (seti j) (seti j0)) => [f /andP[_ /eqP fi]|].
by apply/ffunP=> k; rewrite !ffunE; case: eqP => // ->.
rewrite big_distrr; apply: eq_big => [f | f eq_f]; last first.
rewrite big_cons ffunE eqxx !big_seq; congr (_ * _).
by apply: eq_bigr => k; rewrite ffunE; case: eqP nri => // -> ->.
rewrite !ffunE !eqxx andbT; apply/andP/familyP=> /= [[Pjf fij0] k | Pff].
have /[!(ffunE, inE)] := familyP Pjf k; case: eqP => // -> _.
by rewrite nri -(eqP fij0) !ffunE !inE !eqxx.
(split; [apply/familyP | apply/eqP/ffunP]) => k; have /[!(ffunE, inE)]:= Pff k.
by case: eqP => // ->.
by case: eqP => // ->; rewrite nri /= => /eqP.
Qed.
have [r big_r [Ur mem_r] _] := big_enumP P.
symmetry; transitivity (\big[+%M/0]_(f in Pf r) \big[*%M/1]_(i <- r) F i (f i)).
by apply: eq_big => // f; apply: eq_forallb => i; rewrite /= mem_r.
rewrite -{P mem_r}big_r; elim: r Ur => /= [_ | i r IHr].
rewrite (big_pred1 [ffun=> j0]) ?big_nil //= => f.
apply/familyP/eqP=> /= [Df |->{f} i]; last by rewrite ffunE !inE.
by apply/ffunP=> i; rewrite ffunE; apply/eqP/Df.
case/andP=> /negbTE nri; rewrite big_cons big_distrl => {}/IHr<-.
rewrite (partition_big (fun f : fIJ => f i) (Q i)) => [f|].
by move/familyP/(_ i); rewrite /= inE /= eqxx.
pose seti j (f : fIJ) := [ffun k => if k == i then j else f k].
apply: eq_bigr => j Qij.
rewrite (reindex_onto (seti j) (seti j0)) => [f /andP[_ /eqP fi]|].
by apply/ffunP=> k; rewrite !ffunE; case: eqP => // ->.
rewrite big_distrr; apply: eq_big => [f | f eq_f]; last first.
rewrite big_cons ffunE eqxx !big_seq; congr (_ * _).
by apply: eq_bigr => k; rewrite ffunE; case: eqP nri => // -> ->.
rewrite !ffunE !eqxx andbT; apply/andP/familyP=> /= [[Pjf fij0] k | Pff].
have /[!(ffunE, inE)] := familyP Pjf k; case: eqP => // -> _.
by rewrite nri -(eqP fij0) !ffunE !inE !eqxx.
(split; [apply/familyP | apply/eqP/ffunP]) => k; have /[!(ffunE, inE)]:= Pff k.
by case: eqP => // ->.
by case: eqP => // ->; rewrite nri /= => /eqP.
Qed.
Lemma big_distr_big (I J : finType) j0 (P : pred I) (Q : pred J) F :
\big[*%M/1]_(i | P i) \big[+%M/0]_(j | Q j) F i j =
\big[+%M/0]_(f in pffun_on j0 P Q) \big[*%M/1]_(i | P i) F i (f i).
Proof.
rewrite (big_distr_big_dep j0); apply: eq_bigl => f.
by apply/familyP/familyP=> Pf i; case: ifP (Pf i).
Qed.
by apply/familyP/familyP=> Pf i; case: ifP (Pf i).
Qed.
Lemma bigA_distr_big_dep (I J : finType) (Q : I -> pred J) F :
\big[*%M/1]_i \big[+%M/0]_(j | Q i j) F i j
= \big[+%M/0]_(f in family Q) \big[*%M/1]_i F i (f i).
Proof.
have [j _ | J0] := pickP J; first by rewrite (big_distr_big_dep j).
have Q0 i: Q i =i pred0 by move=> /J0/esym/notF[].
transitivity (iter #|I| ( *%M 0) 1).
by rewrite -big_const; apply/eq_bigr=> i; have /(big_pred0 _)-> := Q0 i.
have [i _ | I0] := pickP I.
rewrite (cardD1 i) //= mul0m big_pred0 // => f.
by apply/familyP=> /(_ i); rewrite Q0.
have f: I -> J by move=> /I0/esym/notF[].
rewrite eq_card0 // (big_pred1 (finfun f)) ?big_pred0 // => g.
by apply/familyP/eqP=> _; first apply/ffunP; move=> /I0/esym/notF[].
Qed.
have Q0 i: Q i =i pred0 by move=> /J0/esym/notF[].
transitivity (iter #|I| ( *%M 0) 1).
by rewrite -big_const; apply/eq_bigr=> i; have /(big_pred0 _)-> := Q0 i.
have [i _ | I0] := pickP I.
rewrite (cardD1 i) //= mul0m big_pred0 // => f.
by apply/familyP=> /(_ i); rewrite Q0.
have f: I -> J by move=> /I0/esym/notF[].
rewrite eq_card0 // (big_pred1 (finfun f)) ?big_pred0 // => g.
by apply/familyP/eqP=> _; first apply/ffunP; move=> /I0/esym/notF[].
Qed.
Lemma bigA_distr_big (I J : finType) (Q : pred J) (F : I -> J -> R) :
\big[*%M/1]_i \big[+%M/0]_(j | Q j) F i j
= \big[+%M/0]_(f in ffun_on Q) \big[*%M/1]_i F i (f i).
Proof.
Lemma bigA_distr_bigA (I J : finType) F :
\big[*%M/1]_(i : I) \big[+%M/0]_(j : J) F i j
= \big[+%M/0]_(f : {ffun I -> J}) \big[*%M/1]_i F i (f i).
Proof.
End Distributivity.
Arguments big_distrl [R zero times plus I r].
Arguments big_distrr [R zero times plus I r].
Arguments big_distr_big_dep [R zero one times plus I J].
Arguments big_distr_big [R zero one times plus I J].
Arguments bigA_distr_big_dep [R zero one times plus I J].
Arguments bigA_distr_big [R zero one times plus I J].
Arguments bigA_distr_bigA [R zero one times plus I J].
Section BigBool.
Section Seq.
Variables (I : Type) (r : seq I) (P B : pred I).
Lemma big_has : \big[orb/false]_(i <- r) B i = has B r.
Proof.
Lemma big_all : \big[andb/true]_(i <- r) B i = all B r.
Proof.
Lemma big_has_cond : \big[orb/false]_(i <- r | P i) B i = has (predI P B) r.
Proof.
Lemma big_all_cond :
\big[andb/true]_(i <- r | P i) B i = all [pred i | P i ==> B i] r.
Proof.
Lemma big_bool R (idx : R) (op : Monoid.com_law idx) (F : bool -> R):
\big[op/idx]_(i : bool) F i = op (F true) (F false).
Proof.
End Seq.
Section FinType.
Variables (I : finType) (P B : pred I).
Lemma big_orE : \big[orb/false]_(i | P i) B i = [exists (i | P i), B i].
Proof.
Lemma big_andE : \big[andb/true]_(i | P i) B i = [forall (i | P i), B i].
Proof.
End FinType.
End BigBool.
Section NatConst.
Variables (I : finType) (A : pred I).
Lemma sum_nat_const n : \sum_(i in A) n = #|A| * n.
Proof.
Lemma sum1_card : \sum_(i in A) 1 = #|A|.
Proof.
Lemma sum1_count J (r : seq J) (a : pred J) : \sum_(j <- r | a j) 1 = count a r.
Proof.
Lemma sum1_size J (r : seq J) : \sum_(j <- r) 1 = size r.
Proof.
Lemma prod_nat_const n : \prod_(i in A) n = n ^ #|A|.
Lemma sum_nat_const_nat n1 n2 n : \sum_(n1 <= i < n2) n = (n2 - n1) * n.
Proof.
Lemma prod_nat_const_nat n1 n2 n : \prod_(n1 <= i < n2) n = n ^ (n2 - n1).
Proof.
End NatConst.
Lemma telescope_sumn_in n m f : n <= m ->
(forall i, n <= i < m -> f i <= f i.+1) ->
\sum_(n <= k < m) (f k.+1 - f k) = f m - f n.
Proof.
move=> nm fle; rewrite (telescope_big (fun i j => f j - f i)); last first.
by case: ltngtP nm => // ->; rewrite subnn.
move=> k /andP[nk km]; rewrite /= addnBAC ?subnKC ?fle ?(ltnW nk)//.
elim: k nk km => [//| k IHk /[!ltnS]/[1!leq_eqVlt]+ km].
move=> /predU1P[/[dup]nk -> | nk]; first by rewrite fle ?nk ?leqnn 1?ltnW.
by rewrite (leq_trans (IHk _ _) (fle _ _))// ltnW// ltnW.
Qed.
by case: ltngtP nm => // ->; rewrite subnn.
move=> k /andP[nk km]; rewrite /= addnBAC ?subnKC ?fle ?(ltnW nk)//.
elim: k nk km => [//| k IHk /[!ltnS]/[1!leq_eqVlt]+ km].
move=> /predU1P[/[dup]nk -> | nk]; first by rewrite fle ?nk ?leqnn 1?ltnW.
by rewrite (leq_trans (IHk _ _) (fle _ _))// ltnW// ltnW.
Qed.
Lemma telescope_sumn n m f : {homo f : x y / x <= y} ->
\sum_(n <= k < m) (f k.+1 - f k) = f m - f n.
Proof.
Lemma sumnE r : sumn r = \sum_(i <- r) i
Proof.
Lemma card_bseq n (T : finType) : #|{bseq n of T}| = \sum_(i < n.+1) #|T| ^ i.
Proof.
rewrite (bij_eq_card bseq_tagged_tuple_bij) card_tagged sumnE big_map big_enum.
by under eq_bigr do rewrite card_tuple.
Qed.
by under eq_bigr do rewrite card_tuple.
Qed.
Lemma leqif_sum (I : finType) (P C : pred I) (E1 E2 : I -> nat) :
(forall i, P i -> E1 i <= E2 i ?= iff C i) ->
\sum_(i | P i) E1 i <= \sum_(i | P i) E2 i ?= iff [forall (i | P i), C i].
Proof.
Lemma leq_sum I r (P : pred I) (E1 E2 : I -> nat) :
(forall i, P i -> E1 i <= E2 i) ->
\sum_(i <- r | P i) E1 i <= \sum_(i <- r | P i) E2 i.
Lemma sumnB I r (P : pred I) (E1 E2 : I -> nat) :
(forall i, P i -> E1 i <= E2 i) ->
\sum_(i <- r | P i) (E2 i - E1 i) =
\sum_(i <- r | P i) E2 i - \sum_(i <- r | P i) E1 i.
Lemma sum_nat_eq0 (I : finType) (P : pred I) (E : I -> nat) :
(\sum_(i | P i) E i == 0)%N = [forall (i | P i), E i == 0%N].
Lemma sum_nat_seq_eq0 I r (P : pred I) F :
(\sum_(i <- r | P i) F i == 0)%N = all (fun i => P i ==> (F i == 0%N)) r.
Proof.
Lemma sum_nat_seq_neq0 I r (P : pred I) F :
(\sum_(i <- r | P i) F i != 0)%N = has (fun i => P i && (F i != 0)%N) r.
Proof.
Lemma sum_nat_eq1 (I : finType) (P : pred I) (F : I -> nat) :
reflect
(exists i : I, [/\ P i, F i = 1 & forall j, j != i -> P j -> F j = 0]%N)
(\sum_(i | P i) F i == 1)%N.
Proof.
apply/(iffP idP) => [sumF_eq1 | [i [Pi Fi1 zFj]]]; last first.
rewrite (bigD1 i)//= Fi1 addn_eq1//= orbF sum_nat_eq0.
by apply/forall_inP => j /andP[Pj ji]; apply/eqP/zFj.
have /forall_inPn [i Pi FiN0]: ~~ [forall i in P, F i == 0].
by apply: contraTN sumF_eq1 => /'forall_in_eqP F0; rewrite big1.
move: sumF_eq1; rewrite (bigD1 i)//= addn_eq1 (negPf FiN0)/= orbF.
move=> /andP[/eqP Fi1]; rewrite sum_nat_eq0 => /'forall_in_eqP FNi0.
by exists i; split; rewrite // => j /[swap] Nij /(conj Nij)/andP/FNi0.
Qed.
rewrite (bigD1 i)//= Fi1 addn_eq1//= orbF sum_nat_eq0.
by apply/forall_inP => j /andP[Pj ji]; apply/eqP/zFj.
have /forall_inPn [i Pi FiN0]: ~~ [forall i in P, F i == 0].
by apply: contraTN sumF_eq1 => /'forall_in_eqP F0; rewrite big1.
move: sumF_eq1; rewrite (bigD1 i)//= addn_eq1 (negPf FiN0)/= orbF.
move=> /andP[/eqP Fi1]; rewrite sum_nat_eq0 => /'forall_in_eqP FNi0.
by exists i; split; rewrite // => j /[swap] Nij /(conj Nij)/andP/FNi0.
Qed.
Lemma sum_nat_seq_eq1 (I : eqType) r (P : pred I) (F : I -> nat) :
(\sum_(i <- r | P i) F i = 1)%N ->
exists i, [/\ i \in r, P i, F i = 1
& forall j, j != i -> j \in r -> P j -> F j = 0]%N.
Proof.
rewrite big_tnth/= => /eqP/sum_nat_eq1[/= i [Pi Fi FNi]].
exists (tnth (in_tuple r) i); split; rewrite //= ?mem_tnth// => j.
move=> /[swap] /(tnthP (in_tuple r))[{} j -> Nij /FNi->//].
by apply: contra_neq Nij => ->.
Qed.
exists (tnth (in_tuple r) i); split; rewrite //= ?mem_tnth// => j.
move=> /[swap] /(tnthP (in_tuple r))[{} j -> Nij /FNi->//].
by apply: contra_neq Nij => ->.
Qed.
Lemma prod_nat_seq_eq0 I r (P : pred I) F :
(\prod_(i <- r | P i) F i == 0)%N = has (fun i => P i && (F i == 0%N)) r.
Proof.
Lemma prod_nat_seq_neq0 I r (P : pred I) F :
(\prod_(i <- r | P i) F i != 0)%N = all (fun i => P i ==> (F i != 0%N)) r.
Proof.
Lemma prod_nat_seq_eq1 I r (P : pred I) F :
(\prod_(i <- r | P i) F i == 1)%N = all (fun i => P i ==> (F i == 1%N)) r.
Proof.
Lemma prod_nat_seq_neq1 I r (P : pred I) F :
(\prod_(i <- r | P i) F i != 1)%N = has (fun i => P i && (F i != 1%N)) r.
Proof.
Lemma leq_prod I r (P : pred I) (E1 E2 : I -> nat) :
(forall i, P i -> E1 i <= E2 i) ->
\prod_(i <- r | P i) E1 i <= \prod_(i <- r | P i) E2 i.
Arguments leq_prod [I r P E1 E2].
Lemma prodn_cond_gt0 I r (P : pred I) F :
(forall i, P i -> 0 < F i) -> 0 < \prod_(i <- r | P i) F i.
Arguments prodn_cond_gt0 [I r P F].
Lemma prodn_gt0 I r (P : pred I) F :
(forall i, 0 < F i) -> 0 < \prod_(i <- r | P i) F i.
Proof.
Lemma gt0_prodn_seq (I : eqType) r (P : pred I) F :
0 < \prod_(i <- r | P i) F i -> forall i, i \in r -> P i -> 0 < F i.
Proof.
Lemma gt0_prodn (I : finType) (P : pred I) F :
0 < \prod_(i | P i) F i -> forall i, P i -> 0 < F i.
Proof.
Lemma leq_bigmax_seq (I : eqType) r (P : pred I) F i0 :
i0 \in r -> P i0 -> F i0 <= \max_(i <- r | P i) F i.
Proof.
Lemma leq_bigmax_cond (I : finType) (P : pred I) F i0 :
P i0 -> F i0 <= \max_(i | P i) F i.
Proof.
Lemma leq_bigmax (I : finType) F (i0 : I) : F i0 <= \max_i F i.
Proof.
Lemma bigmax_leqP (I : finType) (P : pred I) m F :
reflect (forall i, P i -> F i <= m) (\max_(i | P i) F i <= m).
Proof.
Lemma bigmax_leqP_seq (I : eqType) r (P : pred I) m F :
reflect (forall i, i \in r -> P i -> F i <= m) (\max_(i <- r | P i) F i <= m).
Proof.
apply: (iffP idP) => leFm => [i ri Pi|].
exact/(leq_trans _ leFm)/leq_bigmax_seq.
rewrite big_seq_cond; elim/big_ind: _ => // [m1 m2|i /andP[ri]].
by rewrite geq_max => ->.
exact: leFm.
Qed.
exact/(leq_trans _ leFm)/leq_bigmax_seq.
rewrite big_seq_cond; elim/big_ind: _ => // [m1 m2|i /andP[ri]].
by rewrite geq_max => ->.
exact: leFm.
Qed.
Lemma bigmax_sup (I : finType) i0 (P : pred I) m F :
P i0 -> m <= F i0 -> m <= \max_(i | P i) F i.
Proof.
Lemma bigmaxn_sup_seq (I : eqType) r i0 (P : pred I) m F :
i0 \in r -> P i0 -> m <= F i0 -> m <= \max_(i <- r | P i) F i.
Proof.
#[deprecated(since="mathcomp 2.5.0", use=bigmaxn_sup_seq)]
Notation bigmax_sup_seq := bigmaxn_sup_seq.
Lemma bigmax_eq_arg (I : finType) i0 (P : pred I) F :
P i0 -> \max_(i | P i) F i = F [arg max_(i > i0 | P i) F i].
Proof.
move=> Pi0; case: arg_maxnP => //= i Pi maxFi.
by apply/eqP; rewrite eqn_leq leq_bigmax_cond // andbT; apply/bigmax_leqP.
Qed.
by apply/eqP; rewrite eqn_leq leq_bigmax_cond // andbT; apply/bigmax_leqP.
Qed.
Lemma eq_bigmax_cond (I : finType) (A : pred I) F :
#|A| > 0 -> {i0 | i0 \in A & \max_(i in A) F i = F i0}.
Proof.
Lemma eq_bigmax (I : finType) F : #|I| > 0 -> {i0 : I | \max_i F i = F i0}.
Proof.
Lemma expn_sum m I r (P : pred I) F :
(m ^ (\sum_(i <- r | P i) F i) = \prod_(i <- r | P i) m ^ F i)%N.
Lemma dvdn_biglcmP (I : finType) (P : pred I) F m :
reflect (forall i, P i -> F i %| m) (\big[lcmn/1%N]_(i | P i) F i %| m).
Proof.
Lemma biglcmn_sup (I : finType) i0 (P : pred I) F m :
P i0 -> m %| F i0 -> m %| \big[lcmn/1%N]_(i | P i) F i.
Proof.
Lemma dvdn_biggcdP (I : finType) (P : pred I) F m :
reflect (forall i, P i -> m %| F i) (m %| \big[gcdn/0]_(i | P i) F i).
Proof.
Lemma biggcdn_inf (I : finType) i0 (P : pred I) F m :
P i0 -> F i0 %| m -> \big[gcdn/0]_(i | P i) F i %| m.