Module infotheo.lib.bigop_ext
From mathcomp Require Import all_ssreflect ssralg ssrnum matrix lra.From mathcomp Require Import unstable.
From mathcomp Require boolp.
Require Import ssr_ext ssralg_ext.
# Additional lemmas about bigops
Set Implicit Arguments.
Set SsrOldRewriteGoalsOrder.
Unset Strict Implicit.
Import Prenex Implicits.
Lemma morph_oppr {R : zmodType} : {morph @GRing.opp R : x y / (x + y)%R : R}.
#[deprecated(since="infotheo 0.9", note="use `big_distrr` instead of `big_morph` + `morph_mulRdr`")]
Lemma morph_mulRDr {R : pzRingType} a :
{morph (GRing.mul a) : x y / (x + y)%R : R}.
Definition
big_morph_oppr
{R : zmodType} :=big_morph_oppr not a defined object.
big_morph _ morph_oppr (@GRing.oppr0 R).
Section bigop_no_law.
Variables (R : Type) (idx : R) (op : R -> R -> R).
Lemma big_tcast n m (n_m : n = m) (A : finType) F (P : pred {: n.-tuple A}) :
\big[op/idx]_(p in {: n.-tuple A} | P p) F p =
\big[op/idx]_(p in {: m.-tuple A} | P (tcast (esym n_m) p)) F (tcast (esym n_m) p).
Lemma big_cast_rV n m (n_m : n = m) (A : finType) F (P : pred {: 'rV[A]_n}) :
\big[op/idx]_(p in {: 'rV_n} | P p) F p =
\big[op/idx]_(p in {: 'rV_m} | P (castmx (erefl, esym n_m) p)) F (castmx (erefl, esym n_m) p).
End bigop_no_law.
Arguments big_tcast {R} {idx} {op} {n} {m} _ {A} _ _.
Arguments big_cast_rV {R} {idx} {op} {n} {m} _ {A} _ _.
Section bigop_add_law.
Variables (R : Type) (idx : R) (op : R -> R -> R) (M : Monoid.add_law idx op).
Lemma Set2sumE (A : finType) (f : A -> R) (card_A : #|A| = 2%nat) :
\big[M/idx]_(i in A) (f i) = M (f (Set2.a card_A)) (f (Set2.b card_A)).
Lemma big_bool (f : bool -> R) : \big[M/idx]_(i in {:bool}) f i = M (f false) (f true).
Proof.
set h : 'I_2 -> bool := [eta (fun=>false) with ord0 |-> false, lift ord0 ord0 |-> true].
set h' : bool -> 'I_2 := fun x => match x with false => ord0 | true => lift ord0 ord0 end.
rewrite (reindex_onto h h') /=; last by move=> i _; rewrite /h /h'; case: ifP.
rewrite (eq_bigl xpredT); last first.
move=> i; move: (ord2 i) => /orP[|] /eqP -> /=; first by rewrite eqxx.
exact/eqP/val_inj.
by rewrite big_ord_recl /= big_ord_recl big_ord0 Monoid.addm0.
Qed.
set h' : bool -> 'I_2 := fun x => match x with false => ord0 | true => lift ord0 ord0 end.
rewrite (reindex_onto h h') /=; last by move=> i _; rewrite /h /h'; case: ifP.
rewrite (eq_bigl xpredT); last first.
move=> i; move: (ord2 i) => /orP[|] /eqP -> /=; first by rewrite eqxx.
exact/eqP/val_inj.
by rewrite big_ord_recl /= big_ord_recl big_ord0 Monoid.addm0.
Qed.
Variable (A : finType).
Local Open Scope ring_scope.
Lemma big_rV0_row_of_tuple f (P : pred _) :
\big[M/idx]_(v in 'rV[A]_0 | P v) f v =
if P (row_of_tuple [tuple]) then f (row_of_tuple [tuple]) else idx.
Proof.
rewrite -big_map /= /index_enum -enumT /=.
set e := enum _.
rewrite (_ : e = [:: row_of_tuple [tuple]]).
by rewrite /= big_cons big_nil Monoid.addm0.
rewrite /e.
apply: (@eq_from_nth _ (row_of_tuple [tuple])).
by rewrite -cardE card_mx muln0 expn0.
move=> i.
rewrite -cardE card_mx muln0 expn0 ltnS leqn0 => /eqP ->{i}.
rewrite -/e.
destruct e => //.
apply: val_inj => /=.
by apply/ffunP => /= -[? []].
Qed.
set e := enum _.
rewrite (_ : e = [:: row_of_tuple [tuple]]).
by rewrite /= big_cons big_nil Monoid.addm0.
rewrite /e.
apply: (@eq_from_nth _ (row_of_tuple [tuple])).
by rewrite -cardE card_mx muln0 expn0.
move=> i.
rewrite -cardE card_mx muln0 expn0 ltnS leqn0 => /eqP ->{i}.
rewrite -/e.
destruct e => //.
apply: val_inj => /=.
by apply/ffunP => /= -[? []].
Qed.
End bigop_add_law.
Section bigop_algebraic_misc.
bigA_distr is a specialization of bigA_distr_bigA and at the same
time a generalized version of GRing.exprDn for iterated prod. (plus : Monoid.add_law zero times)
(I : finType)
(F1 F2 : I -> R) :
\big[times/one]_(i in I) plus (F1 i) (F2 i) =
\big[plus/zero]_(0 <= k < #|I|.+1)
\big[plus/zero]_(J in {set I} | #|J| == k)
\big[times/one]_(j in I) (if j \notin J then F1 j else F2 j).
Proof.
pose F12 i (j : bool) := if ~~ j then F1 i else F2 i.
under eq_bigr=> i.
rewrite (_: plus (F1 i) (F2 i) = \big[plus/zero]_j F12 i j); last first.
rewrite (bigID (fun i => i == false)) big_pred1_eq (big_pred1 true) //.
by case.
over.
rewrite bigA_distr_bigA big_mkord (partition_big
(fun i : {ffun I -> bool} => inord #|[set x | i x]|)
(fun j : 'I_#|I|.+1 => true)) //=.
apply/eq_big =>// i _.
rewrite (reindex (fun s : {set I} => [ffun x => x \in s])); last first.
apply: onW_bij.
exists (fun f : {ffun I -> bool} => [set x | f x]).
by move=> s; apply/setP => v; rewrite inE ffunE.
by move=> f; apply/ffunP => v; rewrite ffunE inE.
apply/eq_big.
move=> s; apply/eqP/eqP.
move<-; rewrite -[#|s|](@inordK #|I|) ?ltnS ?max_card //.
by congr inord; apply: eq_card => v; rewrite inE ffunE.
move=> Hi; rewrite -[RHS]inord_val -{}Hi.
by congr inord; apply: eq_card => v; rewrite inE ffunE.
by move=> j Hj; apply: eq_bigr => k Hk; rewrite /F12 ffunE.
Qed.
under eq_bigr=> i.
rewrite (_: plus (F1 i) (F2 i) = \big[plus/zero]_j F12 i j); last first.
rewrite (bigID (fun i => i == false)) big_pred1_eq (big_pred1 true) //.
by case.
over.
rewrite bigA_distr_bigA big_mkord (partition_big
(fun i : {ffun I -> bool} => inord #|[set x | i x]|)
(fun j : 'I_#|I|.+1 => true)) //=.
apply/eq_big =>// i _.
rewrite (reindex (fun s : {set I} => [ffun x => x \in s])); last first.
apply: onW_bij.
exists (fun f : {ffun I -> bool} => [set x | f x]).
by move=> s; apply/setP => v; rewrite inE ffunE.
by move=> f; apply/ffunP => v; rewrite ffunE inE.
apply/eq_big.
move=> s; apply/eqP/eqP.
move<-; rewrite -[#|s|](@inordK #|I|) ?ltnS ?max_card //.
by congr inord; apply: eq_card => v; rewrite inE ffunE.
move=> Hi; rewrite -[RHS]inord_val -{}Hi.
by congr inord; apply: eq_card => v; rewrite inE ffunE.
by move=> j Hj; apply: eq_bigr => k Hk; rewrite /F12 ffunE.
Qed.
Lemma bigID2 (R : Type) (I : finType) (J : {set I}) (F1 F2 : I -> R)
(idx : R) (op : Monoid.com_law idx) :
\big[op/idx]_(j in I) (if j \notin J then F1 j else F2 j) =
op (\big[op/idx]_(j in ~: J) F1 j) (\big[op/idx]_(j in J) F2 j).
Proof.
Switching from a sum on the domain to a sum on the image of function
Section partition_big_finType_eqType.Variables (A : finType) (B : eqType).
Variables (R : Type) (idx : R) (op : Monoid.com_law idx).
Lemma partition_big_undup_map (p : seq A) (f : A -> B) : forall g, uniq p ->
\big[op/idx]_(i <- p) g i =
\big[op/idx]_(r <- undup (map f p)) \big[op/idx]_(i <- p | f i == r) (g i).
Proof.
move Hn : (undup (map f (p))) => n.
elim: n p f Hn => [p f H F ? | b bs IH p f H F ?].
rewrite big_nil.
suff -> : p = [::] by rewrite big_nil.
move/undup_nil : H => /(congr1 size) /=; rewrite size_map.
by move/eqP; rewrite size_eq0 => /eqP.
rewrite big_cons.
have [h [t [H1 [H2 H3]]]] : exists h t,
perm_eq p (h ++ t) /\ undup (map f h) = [:: b] /\ undup (map f t) = bs.
exact: undup_perm.
transitivity (\big[op/idx]_(i <- h ++ t) F i); first exact: perm_big.
transitivity (op
(\big[op/idx]_(i <- h ++ t | f i == b) F i)
(\big[op/idx]_(j <- bs) \big[op/idx]_(i <- h ++ t | f i == j) F i)); last first.
congr (op _ _).
by apply: perm_big; rewrite perm_sym.
by apply: eq_bigr => b0 _ /=; apply: perm_big; rewrite perm_sym.
have -> : \big[op/idx]_(j <- bs) \big[op/idx]_(i <- h ++ t | f i == j) F i =
\big[op/idx]_(j <- bs) \big[op/idx]_(i <- t | f i == j) F i.
rewrite [in LHS]big_seq [in RHS]big_seq /=.
apply/esym/eq_bigr => b0 b0bs.
rewrite big_cat /=.
rewrite (_ : \big[op/idx]_(i0 <- h | f i0 == b0) F i0 = idx) ?Monoid.simpm//.
transitivity (\big[op/idx]_(i0 <- h | false) F i0); last by rewrite big_pred0.
rewrite big_seq_cond; apply: eq_bigl => /= a.
apply/negP => /andP[ah /eqP fai]; subst b0.
have fab : f a \in [:: b].
have H' : f a \in map f h by apply/mapP; exists a.
have : f a \in undup (map f h) by rewrite mem_undup.
by rewrite H2.
have : uniq (b :: bs) by rewrite -H undup_uniq.
move: fab; rewrite /= in_cons in_nil orbC /= => /eqP ?; subst b.
by rewrite b0bs.
rewrite -IH //; last first.
have : uniq (h ++ t) by rewrite -(perm_uniq H1).
by rewrite cat_uniq => /and3P[].
suff -> : \big[op/idx]_(i <- h ++ t | f i == b) F i = \big[op/idx]_(i <- h) F i.
by rewrite big_cat.
rewrite big_cat /=.
have -> : \big[op/idx]_(i <- t | f i == b) F i = idx.
transitivity (\big[op/idx]_(i0 <- t | false) F i0); last by rewrite big_pred0.
rewrite big_seq_cond; apply: eq_bigl => /= a.
apply/negP => /andP[ta /eqP fab]; subst b.
have fabs : f a \in bs.
have : f a \in undup (map f t) by rewrite mem_undup; apply/mapP; exists a.
by rewrite H3.
have : uniq (f a :: bs) by rewrite -H undup_uniq.
by rewrite /= fabs.
rewrite Monoid.simpm big_seq_cond /=.
apply/esym.
rewrite big_seq /=; apply: congr_big => //= a.
case/boolP : (a \in h) => ah //=; apply/esym.
have : f a \in [:: b] by rewrite -H2 mem_undup; apply/mapP; exists a.
by rewrite in_cons /= in_nil orbC.
Qed.
elim: n p f Hn => [p f H F ? | b bs IH p f H F ?].
rewrite big_nil.
suff -> : p = [::] by rewrite big_nil.
move/undup_nil : H => /(congr1 size) /=; rewrite size_map.
by move/eqP; rewrite size_eq0 => /eqP.
rewrite big_cons.
have [h [t [H1 [H2 H3]]]] : exists h t,
perm_eq p (h ++ t) /\ undup (map f h) = [:: b] /\ undup (map f t) = bs.
exact: undup_perm.
transitivity (\big[op/idx]_(i <- h ++ t) F i); first exact: perm_big.
transitivity (op
(\big[op/idx]_(i <- h ++ t | f i == b) F i)
(\big[op/idx]_(j <- bs) \big[op/idx]_(i <- h ++ t | f i == j) F i)); last first.
congr (op _ _).
by apply: perm_big; rewrite perm_sym.
by apply: eq_bigr => b0 _ /=; apply: perm_big; rewrite perm_sym.
have -> : \big[op/idx]_(j <- bs) \big[op/idx]_(i <- h ++ t | f i == j) F i =
\big[op/idx]_(j <- bs) \big[op/idx]_(i <- t | f i == j) F i.
rewrite [in LHS]big_seq [in RHS]big_seq /=.
apply/esym/eq_bigr => b0 b0bs.
rewrite big_cat /=.
rewrite (_ : \big[op/idx]_(i0 <- h | f i0 == b0) F i0 = idx) ?Monoid.simpm//.
transitivity (\big[op/idx]_(i0 <- h | false) F i0); last by rewrite big_pred0.
rewrite big_seq_cond; apply: eq_bigl => /= a.
apply/negP => /andP[ah /eqP fai]; subst b0.
have fab : f a \in [:: b].
have H' : f a \in map f h by apply/mapP; exists a.
have : f a \in undup (map f h) by rewrite mem_undup.
by rewrite H2.
have : uniq (b :: bs) by rewrite -H undup_uniq.
move: fab; rewrite /= in_cons in_nil orbC /= => /eqP ?; subst b.
by rewrite b0bs.
rewrite -IH //; last first.
have : uniq (h ++ t) by rewrite -(perm_uniq H1).
by rewrite cat_uniq => /and3P[].
suff -> : \big[op/idx]_(i <- h ++ t | f i == b) F i = \big[op/idx]_(i <- h) F i.
by rewrite big_cat.
rewrite big_cat /=.
have -> : \big[op/idx]_(i <- t | f i == b) F i = idx.
transitivity (\big[op/idx]_(i0 <- t | false) F i0); last by rewrite big_pred0.
rewrite big_seq_cond; apply: eq_bigl => /= a.
apply/negP => /andP[ta /eqP fab]; subst b.
have fabs : f a \in bs.
have : f a \in undup (map f t) by rewrite mem_undup; apply/mapP; exists a.
by rewrite H3.
have : uniq (f a :: bs) by rewrite -H undup_uniq.
by rewrite /= fabs.
rewrite Monoid.simpm big_seq_cond /=.
apply/esym.
rewrite big_seq /=; apply: congr_big => //= a.
case/boolP : (a \in h) => ah //=; apply/esym.
have : f a \in [:: b] by rewrite -H2 mem_undup; apply/mapP; exists a.
by rewrite in_cons /= in_nil orbC.
Qed.
Lemma partition_big_fin_img (f : A -> B) g :
\big[op/idx]_(i in A) (g i) =
\big[op/idx]_(r <- fin_img f) \big[op/idx]_(i in A | f i == r) (g i).
Proof.
Lemma partition_big_fin_img_set (F : {set A}) (f : A -> B) g :
\big[op/idx]_(i in F) (g i) =
\big[op/idx]_(r <- fin_img f) \big[op/idx]_(i in F | f i == r) (g i).
Proof.
have /= := @partition_big_undup_map (enum A) f (fun i => if i \notin F then idx else g i).
rewrite enum_uniq => /(_ isT) H.
transitivity (\big[op/idx]_(i in A) (if i \notin F then idx else g i)).
rewrite bigID2.
rewrite [X in op X _]big1_idem// ?Monoid.op1m//; first exact/Monoid.op1m.
rewrite -big_enum.
rewrite H.
apply: eq_bigr => i _.
rewrite big_mkcond.
under [LHS]eq_bigr => j _ do rewrite if_neg -if_and.
rewrite -big_mkcond big_enum_cond.
apply: eq_big => //.
move => j.
congr (_ && _) => //.
by rewrite andbC.
Qed.
rewrite enum_uniq => /(_ isT) H.
transitivity (\big[op/idx]_(i in A) (if i \notin F then idx else g i)).
rewrite bigID2.
rewrite [X in op X _]big1_idem// ?Monoid.op1m//; first exact/Monoid.op1m.
rewrite -big_enum.
rewrite H.
apply: eq_bigr => i _.
rewrite big_mkcond.
under [LHS]eq_bigr => j _ do rewrite if_neg -if_and.
rewrite -big_mkcond big_enum_cond.
apply: eq_big => //.
move => j.
congr (_ && _) => //.
by rewrite andbC.
Qed.
End partition_big_finType_eqType.
Section BigOps.
Variables (R : Type) (idx : R).
Variables (op : Monoid.law idx) (aop : Monoid.com_law idx).
Variables I J : finType.
Implicit Type A B : {set I}.
Implicit Type h : I -> J.
Implicit Type P : pred I.
Implicit Type F : I -> R.
Lemma partition_big_preimset h (B : {set J}) F :
\big[aop/idx]_(i in h @^-1: B) F i =
\big[aop/idx]_(j in B) \big[aop/idx]_(i in I | h i == j) F i.
Proof.
have HA : [disjoint B :&: [set h x | x in I] & B :\: [set h x | x in I]]
by rewrite -setI_eq0 -setIA setIDA [in _ :&: B]setIC -setIDA setDv !setI0.
have Hha : [disjoint h @^-1: (B :&: [set h x | x in I])
& h @^-1: (B :\: [set h x | x in I])].
rewrite -setI_eq0 -preimsetI.
suff : [disjoint B :&: [set h x | x in I] & B :\: [set h x | x in I]].
by rewrite -setI_eq0; move/eqP => ->; rewrite preimset0.
by [].
rewrite -(setID B (h @: I)) /= preimsetU.
under eq_bigl do rewrite in_setU.
rewrite bigU //.
under [in RHS]eq_bigl do rewrite in_setU.
rewrite bigU //.
have -> : h @^-1: (B :\: [set h x | x in I]) = set0.
apply/setP/subset_eqP/andP; rewrite sub0set; split => //.
apply/subsetP=> i; rewrite !inE; case/andP.
move/imsetP=> H _; rewrite boolp.falseE; apply: H.
by exists i; rewrite ?inE.
rewrite big_set0 Monoid.mulm1.
have -> : \big[aop/idx]_(x in B :\: [set h x | x in I]) \big[aop/idx]_(i | h i == x) F i =
\big[aop/idx]_(x in B :\: [set h x | x in I]) idx.
apply: eq_bigr => j.
rewrite inE; case/andP => Hj Hj'.
apply: big_pred0 => i.
apply/negP => /eqP hij.
move: Hj; rewrite -hij.
move/imsetP; apply.
by exists i.
rewrite big1_eq Monoid.mulm1.
set B' := B :&: [set h x | x in I].
set A := h @^-1: B'.
have -> : B' = h @: A by rewrite imset_preimset //; apply: subsetIr.
have Hright j : j \in h @: A -> \big[aop/idx]_(i in I | h i == j) F i =
\big[aop/idx]_(i in A | h i == j) F i.
move=> Hj; apply: eq_bigl => i; apply: andb_id2r; move/eqP => hij.
move: Hj; rewrite -hij !inE.
case/imsetP => x; rewrite /A /B' !inE => /andP [H H0] ->.
by rewrite H H0.
rewrite [in RHS](eq_bigr _ Hright).
exact: partition_big_imset.
Qed.
by rewrite -setI_eq0 -setIA setIDA [in _ :&: B]setIC -setIDA setDv !setI0.
have Hha : [disjoint h @^-1: (B :&: [set h x | x in I])
& h @^-1: (B :\: [set h x | x in I])].
rewrite -setI_eq0 -preimsetI.
suff : [disjoint B :&: [set h x | x in I] & B :\: [set h x | x in I]].
by rewrite -setI_eq0; move/eqP => ->; rewrite preimset0.
by [].
rewrite -(setID B (h @: I)) /= preimsetU.
under eq_bigl do rewrite in_setU.
rewrite bigU //.
under [in RHS]eq_bigl do rewrite in_setU.
rewrite bigU //.
have -> : h @^-1: (B :\: [set h x | x in I]) = set0.
apply/setP/subset_eqP/andP; rewrite sub0set; split => //.
apply/subsetP=> i; rewrite !inE; case/andP.
move/imsetP=> H _; rewrite boolp.falseE; apply: H.
by exists i; rewrite ?inE.
rewrite big_set0 Monoid.mulm1.
have -> : \big[aop/idx]_(x in B :\: [set h x | x in I]) \big[aop/idx]_(i | h i == x) F i =
\big[aop/idx]_(x in B :\: [set h x | x in I]) idx.
apply: eq_bigr => j.
rewrite inE; case/andP => Hj Hj'.
apply: big_pred0 => i.
apply/negP => /eqP hij.
move: Hj; rewrite -hij.
move/imsetP; apply.
by exists i.
rewrite big1_eq Monoid.mulm1.
set B' := B :&: [set h x | x in I].
set A := h @^-1: B'.
have -> : B' = h @: A by rewrite imset_preimset //; apply: subsetIr.
have Hright j : j \in h @: A -> \big[aop/idx]_(i in I | h i == j) F i =
\big[aop/idx]_(i in A | h i == j) F i.
move=> Hj; apply: eq_bigl => i; apply: andb_id2r; move/eqP => hij.
move: Hj; rewrite -hij !inE.
case/imsetP => x; rewrite /A /B' !inE => /andP [H H0] ->.
by rewrite H H0.
rewrite [in RHS](eq_bigr _ Hright).
exact: partition_big_imset.
Qed.
End BigOps.
Section big_pred1_inj.
Variables (R : Type) (idx : R) (op : Monoid.law idx).
Lemma big_pred1_inj (A C : finType) h i (k : A -> C) : injective k ->
\big[op/idx]_(a | k a == k i) h a = h i.
End big_pred1_inj.
Arguments big_pred1_inj [R] [idx] [op] [A] [C] [h] [i] [k] _.
Section bigop_com_law.
Variables (R : Type) (idx : R) (M : Monoid.com_law idx).
Variable A : finType.
Lemma big_union (X1 X2 : {set A}) f :
[disjoint X2 & X1] ->
\big[M/idx]_(a | a \in X1 :|: X2) f a =
M (\big[M/idx]_(a | a \in X1) f a) (\big[M/idx]_(a | a \in X2) f a).
Proof.
Variable B : finType.
Big sums lemmas for cartesian products
Lemma pair_big_fst (F : {: A * B} -> R) P Q :
P =1 Q \o fst ->
\big[M/idx]_(i in A | Q i) \big[M/idx]_(j in B) F (i, j) =
\big[M/idx]_(i in {: A * B} | P i) F i.
Proof.
Lemma pair_big_snd (F : {: A * B} -> R) P Q :
P =1 Q \o snd ->
\big[M/idx]_(i in A) \big[M/idx]_(j in B | Q j) F (i, j) =
\big[M/idx]_(i in {: A * B} | P i) F i.
Proof.
Lemma big_setX (a : {set A}) (b : {set B}) f :
\big[M/idx]_(x in a `* b) f x = \big[M/idx]_(x in a) \big[M/idx]_(y in b) f (x, y).
Proof.
Lemma big_rV_prod n f (X : {set 'rV[A * B]_n}) :
\big[M/idx]_(a in 'rV[A * B]_n | a \in X) f a =
\big[M/idx]_(a in {: 'rV[A]_n * 'rV[B]_n} | (prod_rV a) \in X) f (prod_rV a).
Proof.
Local Open Scope vec_ext_scope.
Local Open Scope ring_scope.
Lemma big_rV_1 f g (P : pred _) (Q : pred _):
(forall i : 'rV[A]_1, f i = g (i ``_ ord0)) ->
(forall i : 'rV[A]_1, P i = Q (i ``_ ord0)) ->
\big[M/idx]_(i in 'rV[A]_1 | P i) f i = \big[M/idx]_(i in A | Q i) g i.
Proof.
Lemma big_rV1_ord0 (f : A -> R) k :
\big[M/idx]_(i in A) f i = k -> \big[M/idx]_(i in 'rV[A]_1) f (i ``_ ord0) = k.
Proof.
Local Open Scope vec_ext_scope.
Local Open Scope ring_scope.
Lemma big_rV_cons n (F : 'rV[A]_n.+1 -> R) (a : A) (i0 : 'I_n.+1) : i0 = ord0 ->
\big[M/idx]_(v in 'rV[A]_n) (F (row_mx (\row_(k < 1) a) v)) =
\big[M/idx]_(v in 'rV[A]_n.+1 | v ``_ i0 == a) (F v).
Proof.
move=> i00.
rewrite [in RHS](reindex_onto (row_mx (\row_(k < 1) a)) rbehead) /=; last first.
move=> m /eqP <-; by rewrite i00 row_mx_rbehead.
apply: eq_bigl => ?; by rewrite i00 rbehead_row_mx eqxx andbT row_mx_row_ord0 eqxx.
Qed.
rewrite [in RHS](reindex_onto (row_mx (\row_(k < 1) a)) rbehead) /=; last first.
move=> m /eqP <-; by rewrite i00 row_mx_rbehead.
apply: eq_bigl => ?; by rewrite i00 rbehead_row_mx eqxx andbT row_mx_row_ord0 eqxx.
Qed.
Lemma big_rV_behead n (F : 'rV[A]_n.+1 -> R) (w : 'rV[A]_n) :
\big[M/idx]_(a in A) (F (row_mx (\row_(k < 1) a) w)) =
\big[M/idx]_(v in 'rV[A]_n.+1 | rbehead v == w) (F v).
Proof.
rewrite [in RHS](reindex_onto
(fun p => row_mx (\row_(k < 1) p) w) (fun p => p ``_ ord0) ) /=; last first.
move=> i /eqP <-; by rewrite row_mx_rbehead.
apply: eq_bigl => ?; by rewrite rbehead_row_mx eqxx /= row_mx_row_ord0 eqxx.
Qed.
(fun p => row_mx (\row_(k < 1) p) w) (fun p => p ``_ ord0) ) /=; last first.
move=> i /eqP <-; by rewrite row_mx_rbehead.
apply: eq_bigl => ?; by rewrite rbehead_row_mx eqxx /= row_mx_row_ord0 eqxx.
Qed.
Lemma big_rV_cons_behead_support n (F : 'rV[A]_n.+1 -> R)
(X1 : {set A}) (X2 : {set {: 'rV[A]_n}}) :
\big[M/idx]_(a in X1) \big[M/idx]_(v in X2) (F (row_mx (\row_(k < 1) a) v)) =
\big[M/idx]_(w in 'rV[A]_n.+1 | (w ``_ ord0 \in X1) && (rbehead w \in X2)) (F w).
Proof.
rewrite [in RHS](partition_big (fun x : 'rV_n.+1 => x ``_ ord0) (mem X1)) /=; last first.
by move=> i /andP[].
apply: eq_bigr => i Hi.
rewrite (reindex_onto (fun j => row_mx (\row_(k < 1) i) j) rbehead) /=; last first.
move=> j /andP[] => _ /eqP => <-; by rewrite row_mx_rbehead.
apply: eq_big => //= x; by rewrite row_mx_row_ord0 rbehead_row_mx !eqxx Hi !andbT.
Qed.
by move=> i /andP[].
apply: eq_bigr => i Hi.
rewrite (reindex_onto (fun j => row_mx (\row_(k < 1) i) j) rbehead) /=; last first.
move=> j /andP[] => _ /eqP => <-; by rewrite row_mx_rbehead.
apply: eq_big => //= x; by rewrite row_mx_row_ord0 rbehead_row_mx !eqxx Hi !andbT.
Qed.
Lemma big_rV_cons_behead n (F : 'rV[A]_n.+1 -> R)
(P1 : pred A) (P2 : pred 'rV[A]_n) :
\big[M/idx]_(i in A | P1 i)
\big[M/idx]_(j in 'rV[A]_n | P2 j) (F (row_mx (\row_(k < 1) i) j)) =
\big[M/idx]_(p in 'rV[A]_n.+1 | (P1 (p ``_ ord0)) && (P2 (rbehead p)) ) (F p).
Proof.
rewrite [in RHS](partition_big (fun x : 'rV_n.+1 => x ``_ ord0) P1) /=; last first.
by move=> i /andP[].
apply: eq_bigr => i Hi.
rewrite (reindex_onto (fun j => row_mx (\row_(k < 1) i) j) rbehead) /=; last first.
move=> j /andP[] Hj1 /eqP => <-; by rewrite row_mx_rbehead.
apply: eq_big => //= x; by rewrite row_mx_row_ord0 rbehead_row_mx 2!eqxx Hi !andbT.
Qed.
by move=> i /andP[].
apply: eq_bigr => i Hi.
rewrite (reindex_onto (fun j => row_mx (\row_(k < 1) i) j) rbehead) /=; last first.
move=> j /andP[] Hj1 /eqP => <-; by rewrite row_mx_rbehead.
apply: eq_big => //= x; by rewrite row_mx_row_ord0 rbehead_row_mx 2!eqxx Hi !andbT.
Qed.
Lemma big_rV_belast_last n (F : 'rV[A]_n.+1 -> R)
(P1 : pred 'rV[A]_n) (P2 : pred A) :
\big[M/idx]_(i in 'rV[A]_n | P1 i)
\big[M/idx]_(j in A | P2 j) (F (castmx (erefl, addn1 n) (row_mx i (\row_(k < 1) j)))) =
\big[M/idx]_(p in 'rV[A]_n.+1 | (P1 (rbelast p)) && (P2 (rlast p)) ) (F p).
Proof.
rewrite [in RHS](partition_big (fun x : 'rV_n.+1 => rlast x) P2) /=; last first.
by move=> i /andP[].
rewrite exchange_big.
apply: eq_bigr => i Hi.
rewrite (reindex_onto (fun j => (castmx (erefl 1%nat, addn1 n) (row_mx j (\row_(k < 1) i)))) rbelast) /=; last first.
move=> j /andP[] Hj1 /eqP => <-; by rewrite row_mx_rbelast.
apply: eq_big => //= x.
by rewrite row_mx_row_ord_max rbelast_row_mx 2!eqxx !andbT Hi andbT.
Qed.
by move=> i /andP[].
rewrite exchange_big.
apply: eq_bigr => i Hi.
rewrite (reindex_onto (fun j => (castmx (erefl 1%nat, addn1 n) (row_mx j (\row_(k < 1) i)))) rbelast) /=; last first.
move=> j /andP[] Hj1 /eqP => <-; by rewrite row_mx_rbelast.
apply: eq_big => //= x.
by rewrite row_mx_row_ord_max rbelast_row_mx 2!eqxx !andbT Hi andbT.
Qed.
End bigop_com_law.
Arguments pair_big_fst {R} {idx} {M} {A} {B} _.
Arguments pair_big_snd {R} {idx} {M} {A} {B} _.
Arguments big_rV_belast_last {R} {idx} {M} {A} {n} _ _ _.
Arguments big_rV_cons_behead {R} {idx} {M} {A} {n} _ _ _.
Section bigcup_ext.
Variables I A B : finType.
Lemma bigcup_set0 i (D : I -> {set B}) (F : B -> I -> {set A}) b :
b \in D i -> F b i != set0 ->
\bigcup_(b' in D i) F b' i == set0 -> D i == set0.
Proof.
Lemma bigcup_setX (E : I -> {set A}) (F : {set B}) :
\bigcup_(i in I) (F `* E i) = F `* (\bigcup_(i in I) (E i)).
Proof.
Lemma bigcup_preimset (P : pred I) (F : A -> B) (E : I -> {set B}) :
\bigcup_(i | P i) F @^-1: E i = F @^-1: \bigcup_(i | P i) E i.
Proof.
Lemma bigcup_set1 (E : {set A}) : E = \bigcup_(a in E) [set a].
Proof.
End bigcup_ext.
Section MyPartitions.
Variables (R : Type) (idx : R) (op : Monoid.com_law idx).
Variables T I : finType.
Lemma big_bigcup_partition (F : I -> {set T}) E (V : {set I}):
(forall i j, i != j -> [disjoint F i & F j]) ->
\big[op/idx]_(x in \bigcup_(i in V) F i) E x =
\big[op/idx]_(i in V) \big[op/idx]_(x in F i) E x.
Proof.
move=> disjF; pose Q := [set F i | i in V & F i != set0].
have trivP: trivIset Q.
apply/trivIsetP=> _ _ /imsetP[i _ ->] /imsetP[j _ ->] neqFij.
by apply: disjF; apply: contraNneq neqFij => ->.
have ->: \bigcup_(i in V) F i = cover Q.
apply/esym.
rewrite cover_imset big_mkcond /=.
apply/esym.
rewrite big_mkcond /=.
apply: eq_bigr => i _.
case: ifP.
rewrite inE => -> /=.
by case: ifP => // /eqP.
by rewrite inE => ->.
rewrite big_trivIset // big_imset => [|i j _ /setIdP[_ notFj0] eqFij].
rewrite big_mkcond [in X in _ = X]big_mkcond.
apply: eq_bigr => i _.
rewrite inE.
case: ifP.
by case/andP=> ->.
move/negbT.
rewrite negb_and.
case/orP.
by move/negbTE => ->.
rewrite negbK => /eqP Fi.
case: ifP => //.
by rewrite Fi big_set0.
by apply: contraNeq (disjF _ _) _; rewrite -setI_eq0 eqFij setIid.
Qed.
have trivP: trivIset Q.
apply/trivIsetP=> _ _ /imsetP[i _ ->] /imsetP[j _ ->] neqFij.
by apply: disjF; apply: contraNneq neqFij => ->.
have ->: \bigcup_(i in V) F i = cover Q.
apply/esym.
rewrite cover_imset big_mkcond /=.
apply/esym.
rewrite big_mkcond /=.
apply: eq_bigr => i _.
case: ifP.
rewrite inE => -> /=.
by case: ifP => // /eqP.
by rewrite inE => ->.
rewrite big_trivIset // big_imset => [|i j _ /setIdP[_ notFj0] eqFij].
rewrite big_mkcond [in X in _ = X]big_mkcond.
apply: eq_bigr => i _.
rewrite inE.
case: ifP.
by case/andP=> ->.
move/negbT.
rewrite negb_and.
case/orP.
by move/negbTE => ->.
rewrite negbK => /eqP Fi.
case: ifP => //.
by rewrite Fi big_set0.
by apply: contraNeq (disjF _ _) _; rewrite -setI_eq0 eqFij setIid.
Qed.
End MyPartitions.
Section big_tuple_ffun.
Import Monoid.Theory.
Variable R : Type.
Variable V : zmodType.
Variable times : Monoid.mul_law (@GRing.zero V).
Local Notation "*%M" := times (at level 0).
Variable plus : Monoid.add_law (@GRing.zero V) *%M.
Local Notation "+%M" := plus (at level 0).
Lemma big_tuple_ffun (I J : finType) (F : {ffun I -> J} -> R)
(G : R -> J -> V) (jdef : J) (idef : I) :
\big[+%M/@GRing.zero V]_(j : #|I|.-tuple J) G (F [ffun x => tnth j (enum_rank x)]) (nth jdef j 0)
= \big[+%M/@GRing.zero V]_(f : {ffun I -> J}) G (F f) (f (nth idef (enum I) 0)).
Proof.
rewrite (reindex_onto (fun y => fgraph y) (fun p => [ffun x => tnth p (enum_rank x)])); last first.
move=> t _; by apply/eq_from_tnth => i; rewrite tnth_fgraph ffunE enum_valK.
apply: eq_big.
move=> f /=; apply/eqP/ffunP => i; by rewrite ffunE tnth_fgraph enum_rankK.
move=> f _.
congr (G (F _) _).
apply/ffunP => i; by rewrite ffunE tnth_fgraph enum_rankK.
have @zero : 'I_#|I| by exists O; apply/card_gt0P; exists idef.
transitivity (tnth (fgraph f) zero).
by rewrite (tnth_nth jdef).
rewrite tnth_fgraph; congr (f _).
by apply: enum_val_nth.
Qed.
move=> t _; by apply/eq_from_tnth => i; rewrite tnth_fgraph ffunE enum_valK.
apply: eq_big.
move=> f /=; apply/eqP/ffunP => i; by rewrite ffunE tnth_fgraph enum_rankK.
move=> f _.
congr (G (F _) _).
apply/ffunP => i; by rewrite ffunE tnth_fgraph enum_rankK.
have @zero : 'I_#|I| by exists O; apply/card_gt0P; exists idef.
transitivity (tnth (fgraph f) zero).
by rewrite (tnth_nth jdef).
rewrite tnth_fgraph; congr (f _).
by apply: enum_val_nth.
Qed.
End big_tuple_ffun.
Import Order.POrderTheory Order.TotalTheory GRing.Theory Num.Theory.
Section prod_gt0_inv.
Local Open Scope ring_scope.
Lemma prod_gt0_inv (R : realFieldType) n (F : _ -> R)
(HF: forall a, (0 <= F a)) :
(0 < \prod_(i < n.+1) F i -> forall i, 0 < F i).
Proof.
End prod_gt0_inv.
Section classify_big.
Local Open Scope ring_scope.
Variable R : pzRingType.
Lemma classify_big (A : finType) n (f : A -> 'I_n) (F : 'I_n -> R) :
\sum_a F (f a) =
\sum_(i < n) (#|f @^-1: [set i]|%:R * F i).
Proof.
transitivity (\sum_(i < n) \sum_(a | true && (f a == i)) F (f a)).
by apply: partition_big.
apply: eq_bigr => i _ /=.
transitivity (\sum_(a | f a == i) F i); first by apply: eq_bigr => s /eqP ->.
rewrite big_const iter_addr addr0 mulr_natl; congr GRing.natmul.
apply: eq_card => j /=; by rewrite !inE.
Qed.
by apply: partition_big.
apply: eq_bigr => i _ /=.
transitivity (\sum_(a | f a == i) F i); first by apply: eq_bigr => s /eqP ->.
rewrite big_const iter_addr addr0 mulr_natl; congr GRing.natmul.
apply: eq_card => j /=; by rewrite !inE.
Qed.
End classify_big.
Section num.
Local Open Scope ring_scope.
Variables (R : numDomainType) (I : Type) (r : seq I).
Lemma ler_suml [P Q : pred I] [F G : I -> R] :
(forall i : I, P i -> F i <= G i) ->
(forall i : I, Q i -> ~~ P i -> 0 <= G i) ->
(forall i : I, P i -> Q i) ->
\sum_(i <- r | P i) F i <= \sum_(i <- r | Q i) G i.
Proof.
Lemma ler_sum_predU [P Q : pred I] (F : I -> R) :
(forall i : I, P i -> Q i -> 0 <= F i) ->
\sum_(i <- r | (predU P Q) i) F i <=
\sum_(i <- r | P i) F i + \sum_(i <- r | Q i) F i.
Proof.
move=> F0.
under eq_bigr => i _.
rewrite (_ : F i = if Q i then F i else F i); last by case: ifP.
over.
rewrite big_if /=.
under eq_bigl do rewrite orbC orbK.
rewrite addrC; apply: lerD => //.
apply: ler_suml=> // i; rewrite andb_orl andbN orbF; last by case/andP.
by move=> /[dup] /F0 /[swap] -> /[!andTb] /[!negbK].
Qed.
under eq_bigr => i _.
rewrite (_ : F i = if Q i then F i else F i); last by case: ifP.
over.
rewrite big_if /=.
under eq_bigl do rewrite orbC orbK.
rewrite addrC; apply: lerD => //.
apply: ler_suml=> // i; rewrite andb_orl andbN orbF; last by case/andP.
by move=> /[dup] /F0 /[swap] -> /[!andTb] /[!negbK].
Qed.
Section real.
Local Open Scope ring_scope.
Variables (R : realDomainType) (I : Type) (r : seq I).
Lemma fsumr_gt0 (U : eqType) (F : U -> R) (s : seq U) :
0 < \sum_(i <- s) F i -> exists2 i, i \in s & 0 < F i.
Proof.
End real.
Declare Scope min_scope.
Reserved Notation "\min^ b '_(' a 'in' A ) F" (at level 41,
F at level 41, a, A at level 50,
format "'[' \min^ b '_(' a 'in' A ) '/ ' F ']'").
Notation "\min^ b '_(' a 'in' A ) F" :=
((fun a => F) (arg_min b (fun x => x \in A) (fun a => F))) : min_scope.
Notation "\rmax_ ( i 'in' A ) F" := (\big[Order.max/GRing.zero]_(i in A) F)
(at level 41, F at level 41, i, A at level 50,
format "'[' \rmax_ ( i 'in' A ) '/ ' F ']'").
Notation "\rmax_ ( i <- r ) F" := (\big[Order.max/GRing.zero]_(i <- r) F)
(at level 41, F at level 41, i, r at level 50,
format "'[' \rmax_ ( i <- r ) '/ ' F ']'").
Section order.
Import classical.mathcomp_extra Order.Theory.
Local Open Scope ring_scope.
Local Open Scope order_scope.
Lemma bigmax_le_seq disp (T : porderType disp) (I : eqType) (r : seq I) (f : I -> T)
(x0 x : T) (PP : pred I) :
(x0 <= x)%O ->
(forall i : I, i \in r -> PP i -> (f i <= x)%O) ->
(\big[Order.max/x0]_(i <- r | PP i) f i <= x)%O.
Proof.
Lemma bigmax_leP_seq disp (T : orderType disp) (I : eqType) (r : seq I) (F : I -> T)
(x m : T) (PP : pred I) :
reflect ((x <= m)%O /\ (forall i : I, i \in r -> PP i -> (F i <= m)%O))
(\big[Order.max/x]_(i <- r | PP i) F i <= m)%O.
Proof.
apply:(iffP idP); last by case; exact:bigmax_le_seq.
move=> bm; split; first by exact/(le_trans _ bm)/bigmax_ge_id.
by move=> *; exact/(le_trans _ bm)/le_bigmax_seq.
Qed.
move=> bm; split; first by exact/(le_trans _ bm)/bigmax_ge_id.
by move=> *; exact/(le_trans _ bm)/le_bigmax_seq.
Qed.
Section classical.
Import boolp.
Lemma bigmax_gt0P_seq (T : realDomainType) (A : eqType) (F : A -> T)
(s : seq A) (PP : pred A) :
reflect (exists i : A, [/\ i \in s, PP i & (0 < F i)%O]) (0 < \big[Num.max/0]_(m <- s | PP m) F m).
Proof.
rewrite ltNge.
apply:(iffP idP).
move=> /bigmax_leP_seq /not_andP []; first by rewrite lexx.
move=> /existsNP [] x /not_implyP [] xs /not_implyP [] PPx /negP.
rewrite -ltNge=> Fx0.
by exists x; repeat (split=> //).
case=> x [] ? ? ?; apply/bigmax_leP_seq/not_andP; right.
apply/existsNP; exists x; do 2 (apply/not_implyP; split=> //).
by apply/negP; rewrite -ltNge.
Qed.
apply:(iffP idP).
move=> /bigmax_leP_seq /not_andP []; first by rewrite lexx.
move=> /existsNP [] x /not_implyP [] xs /not_implyP [] PPx /negP.
rewrite -ltNge=> Fx0.
by exists x; repeat (split=> //).
case=> x [] ? ? ?; apply/bigmax_leP_seq/not_andP; right.
apply/existsNP; exists x; do 2 (apply/not_implyP; split=> //).
by apply/negP; rewrite -ltNge.
Qed.
End classical.
End order.
Section big_union.
Definition
big_union_disj
:= big_union.big_union_disj not a defined object.
Lemma big_union_nondisj (R : Type) (idx : R) (M : Monoid.com_law idx)
(A : finType) (X1 X2 : {set A}) (f : A -> R) :
\big[M/idx]_(a in (X1 :&: X2)) f a = idx ->
\big[M/idx]_(a in (X1 :|: X2)) f a =
M (\big[M/idx]_(a in X1) f a) (\big[M/idx]_(a in X2) f a).
Proof.
move=> I0.
rewrite -setIUY big_union_disj 1?disjoint_sym ?setIYI_disj //.
rewrite I0 Monoid.opm1 big_union_disj; last first.
by rewrite -setI_eq0 setIDA setIC Order.SetSubsetOrder.setIDv // set0D.
(* Order.SetSubsetOrder.setIDv is B :&: (A :\: B) = set0 *)
set lhs := LHS.
rewrite -(setID X1 X2) big_union_disj; last first.
by rewrite -setI_eq0 setIC -setIA Order.SetSubsetOrder.setIDv // setI0.
rewrite I0 Monoid.op1m.
rewrite -[in X in M _ X](setID X2 X1) big_union_disj; last first.
by rewrite -setI_eq0 setIC -setIA Order.SetSubsetOrder.setIDv // setI0.
by rewrite setIC I0 Monoid.op1m.
Qed.
rewrite -setIUY big_union_disj 1?disjoint_sym ?setIYI_disj //.
rewrite I0 Monoid.opm1 big_union_disj; last first.
by rewrite -setI_eq0 setIDA setIC Order.SetSubsetOrder.setIDv // set0D.
(* Order.SetSubsetOrder.setIDv is B :&: (A :\: B) = set0 *)
set lhs := LHS.
rewrite -(setID X1 X2) big_union_disj; last first.
by rewrite -setI_eq0 setIC -setIA Order.SetSubsetOrder.setIDv // setI0.
rewrite I0 Monoid.op1m.
rewrite -[in X in M _ X](setID X2 X1) big_union_disj; last first.
by rewrite -setI_eq0 setIC -setIA Order.SetSubsetOrder.setIDv // setI0.
by rewrite setIC I0 Monoid.op1m.
Qed.
End big_union.
Section bigID_setC.
Context {X : finType} {R : pzRingType}.
Variable f0 : X -> R.
Variable S : {set X}.
Local Open Scope ring_scope.
Lemma bigID_setC :
\sum_(x| x \in X) f0 x = \sum_(x| x \in S) f0 x + \sum_(x| x \in ~: S) f0 x.
Proof.
End bigID_setC.