Top source

Module mathcomp.experimental_reals.distr


From mathcomp Require Import boot order algebra.
From mathcomp.classical Require Import boolp classical_sets mathcomp_extra.
From mathcomp Require Import xfinmap constructive_ereal reals discrete.
From mathcomp Require Import realseq realsum.

Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Unset SsrOldRewriteGoalsOrder.

Import Order.TTheory GRing.Theory Num.Theory.

Local Open Scope ring_scope.

Local Notation := Monoid.simpm.

Reserved Notation "\dlet_ ( i <- d ) E"
  (at level 36, E at level 36, i, d at level 50,
     format "'[' \dlet_ ( i <- d ) '/ ' E ']'").

Reserved Notation "\dlim_ ( n ) E"
  (at level 36, E at level 36, n at level 50,
     format "'[' \dlim_ ( n ) '/ ' E ']'").

Reserved Notation "\P_[ mu ] E" (at level 2, format "\P_[ mu ] E").
Reserved Notation "\P_[ mu , A ] E" (at level 2, format "\P_[ mu , A ] E").
Reserved Notation "\E?_[ mu ] f" (at level 2, format "\E?_[ mu ] f").
Reserved Notation "\E_[ mu ] f" (at level 2, format "\E_[ mu ] f").
Reserved Notation "\E_[ mu , A ] f" (at level 2, format "\E_[ mu , A ] f").

Local Notation
"\`| f |"
Source code
:= (fun => `|f x|) (at level 2).

Section Distribution.
Variables ( : realType) ( : choiceType).

Structure := Distr {
   :> T -> R;
  _ : forall , 0 <= mu x;
  _ : summable mu;
  _ : PosSum.psum mu <= 1
}.

Definition
distr_of

distr_of : forall [R : realType] [T : choiceType], phant R -> phant T -> Type distr_of is not universe polymorphic Arguments distr_of [R T] _ _ distr_of is transparent Expands to: Constant mathcomp.experimental_reals.distr.distr_of Declared in library mathcomp.experimental_reals.distr, line 52, characters 11-19


Source code
& phant R & phant T := distr.
End Distribution.

Notation
"{ 'distr' T / R }"
Source code
:= (distr_of (Phant R) (Phant T))
  (at level 0, T at level 2, format "{ 'distr' T / R }")
  : type_scope.

Section DistrCoreTh.
Context { : realType} ( : choiceType) ( : {distr T / R}).

Lemma : forall , 0 <= mu x.
Proof.
by case: mu. Qed.

Lemma : PosSum.psum mu <= 1.
Proof.
by case: mu. Qed.

Lemma
summable_mu
Source code
: summable mu.
Proof.
by case: mu. Qed.
End DistrCoreTh.

#[global] Hint Extern 0 (is_true (0 <= _)) => solve [apply: ge0_mu] : core.
#[global] Hint Resolve le1_mu summable_mu : core.

Section Clamp.
Context { : realType}.

Definition
clamp

clamp : forall {R : realType}, R -> R clamp is not universe polymorphic Arguments clamp {R} x%_ring_scope clamp is transparent Expands to: Constant mathcomp.experimental_reals.distr.clamp Declared in library mathcomp.experimental_reals.distr, line 80, characters 11-16


Source code
( : R) :=
  Num.max (Num.min x 1) 0.

Lemma
ge0_clamp
Source code
: 0 <= clamp x.
Proof.
by rewrite le_max lexx orbT. Qed.

Lemma
le1_clamp
Source code
: clamp x <= 1.
Proof.
by rewrite ge_max ge_min lexx ler01 orbT. Qed.

Definition
cp01_clamp

cp01_clamp : forall {R : realType}, (forall x : R, (0 <= clamp x)%R) * (forall x : R, (clamp x <= 1)%R) cp01_clamp is not universe polymorphic Arguments cp01_clamp {R} cp01_clamp is transparent Expands to: Constant mathcomp.experimental_reals.distr.cp01_clamp Declared in library mathcomp.experimental_reals.distr, line 89, characters 11-21


Source code
:= (ge0_clamp, le1_clamp).

Lemma
clamp_in01
Source code
: 0 <= x <= 1 -> clamp x = x.
Proof.
by case/andP=> ge0_x le1_x; rewrite /clamp min_l ?max_l. Qed.

Lemma
clamp_id
Source code
: clamp (clamp x) = clamp x.
Proof.
by rewrite clamp_in01 // !cp01_clamp. Qed.

Lemma : clamp 0 = 0.
Proof.
by rewrite clamp_in01 // lexx ler01. Qed.

Lemma : clamp 1 = 1.
Proof.
by rewrite clamp_in01 // lexx ler01. Qed.
End Clamp.

Section StdDefs.
Context { : realType} ( : choiceType).

Implicit Types (mu : {distr T / R}) (A B E : pred T) (f : T -> R).

Definition
dinsupp

dinsupp : forall {R : realType} [T : choiceType], {distr T / R} -> T -> bool dinsupp is not universe polymorphic Arguments dinsupp {R} [T] mu x dinsupp is transparent Expands to: Constant mathcomp.experimental_reals.distr.dinsupp Declared in library mathcomp.experimental_reals.distr, line 110, characters 11-18


Source code
:= fun => mu x != 0 :> R.

Lemma
in_dinsupp
Source code
( : {distr T / R}) :
  (x \in dinsupp mu) = (mu x != 0).
Proof.
by []. Qed.

Lemma
dinsuppP
Source code
: reflect (mu x <> 0) (x \in dinsupp mu).
Proof.
by apply: (iffP idP) => /eqP. Qed.

Lemma
dinsuppPn
Source code
: reflect (mu x = 0) (x \notin dinsupp mu).
Proof.
by rewrite -topredE /dinsupp /= negbK; apply/eqP. Qed.

Definition
pr

pr : forall {R : realType} [T : choiceType], {distr T / R} -> pred T -> R pr is not universe polymorphic Arguments pr {R} [T] mu E pr is transparent Expands to: Constant mathcomp.experimental_reals.distr.pr Declared in library mathcomp.experimental_reals.distr, line 122, characters 11-13


Source code
:= PosSum.psum (fun => (E x)%:R * mu x).
Definition
prc

prc : forall {R : realType} [T : choiceType], {distr T / R} -> pred T -> pred T -> R prc is not universe polymorphic Arguments prc {R} [T] mu E A prc is transparent Expands to: Constant mathcomp.experimental_reals.distr.prc Declared in library mathcomp.experimental_reals.distr, line 123, characters 11-14


Source code
:= pr mu [predI E & A] / pr mu A.
Definition
esp

esp : forall {R : realType} [T : choiceType], {distr T / R} -> (T -> R) -> R esp is not universe polymorphic Arguments esp {R} [T] mu f%_function_scope esp is transparent Expands to: Constant mathcomp.experimental_reals.distr.esp Declared in library mathcomp.experimental_reals.distr, line 124, characters 11-14


Source code
:= sum (fun => f x * mu x).
Definition
espc

espc : forall {R : realType} [T : choiceType], {distr T / R} -> (T -> R) -> pred T -> R espc is not universe polymorphic Arguments espc {R} [T] mu f%_function_scope A espc is transparent Expands to: Constant mathcomp.experimental_reals.distr.espc Declared in library mathcomp.experimental_reals.distr, line 125, characters 11-15


Source code
:= sum (fun => f x * prc mu (pred1 x) A).

Definition
has_esp

has_esp : forall {R : realType} [T : choiceType], {distr T / R} -> (T -> R) -> Prop has_esp is not universe polymorphic Arguments has_esp {R} [T] mu f%_function_scope has_esp is transparent Expands to: Constant mathcomp.experimental_reals.distr.has_esp Declared in library mathcomp.experimental_reals.distr, line 127, characters 11-18


Source code
:= summable (fun => f x * mu x).
End StdDefs.

Notation
"\P_[ mu ] E"
Source code
:= (pr mu E).
Notation
"\P_[ mu , A ] E"
Source code
:= (prc mu E A).
Notation
"\E_[ mu ] f"
Source code
:= (esp mu f).
Notation
"\E_[ mu , A ] f"
Source code
:= (espc mu f A).
Notation
"\E?_[ mu ] f"
Source code
:= (has_esp mu f).
Notation mu := (\P_[mu] predT).

Section DistrTheory.
Context { : realType} { : choiceType} ( : T -> R).

Definition
isdistr

isdistr : forall {R : realType} {T : choiceType}, (T -> R) -> Prop isdistr is not universe polymorphic Arguments isdistr {R T} mu%_function_scope isdistr is transparent Expands to: Constant mathcomp.experimental_reals.distr.isdistr Declared in library mathcomp.experimental_reals.distr, line 141, characters 11-18


Source code
:=
  (forall , 0 <= mu x) /\ (forall , uniq J -> \sum_( <- J) mu j <= 1).

Hypothesis : isdistr.

Local Lemma : forall , 0 <= mu x.
Proof.
by case: isd. Qed.

Local Lemma : summable mu.
Proof.
case: isd=> _ h; apply/summable_seqP; exists 1=> //.
move=> s /h /(le_trans _); apply; rewrite le_eqVlt; apply/orP.
by left; apply/eqP/eq_bigr=> i _; rewrite ger0_norm ?isd1.
Qed.

Local Lemma : PosSum.psum mu <= 1.
Proof.
rewrite psumE; [apply/isd1 | apply/isd2 | apply: ge_sup].
  by exists 0, fset0; rewrite big_fset0.
apply/ubP=> y [x ->]; rewrite big_fset_seq /=.
by case: isd => _; apply; case: x => x /= /canonical_uniq.
Qed.

Definition
mkdistr

mkdistr : forall {R : realType} {T : choiceType} [mu : T -> R], isdistr mu -> distr R T mkdistr is not universe polymorphic Arguments mkdistr {R T} [mu]%_function_scope isd mkdistr is transparent Expands to: Constant mathcomp.experimental_reals.distr.mkdistr Declared in library mathcomp.experimental_reals.distr, line 164, characters 11-18


Source code
:= @Distr R T mu isd1 isd2 isd3.

Lemma
mkdistrE
Source code
: mkdistr =1 mu.
Proof.
by []. Qed.

Definition
ispredistr

ispredistr : forall {R : realType} {T : choiceType}, (T -> R) -> Prop ispredistr is not universe polymorphic Arguments ispredistr {R T} mu%_function_scope ispredistr is transparent Expands to: Constant mathcomp.experimental_reals.distr.ispredistr Declared in library mathcomp.experimental_reals.distr, line 169, characters 11-21


Source code
{ : choiceType} ( : T -> R) :=
  [/\ forall , 0 <= mu x & summable mu].
End DistrTheory.

Lemma
isdistr_finP
Source code
{ : realType} { : finType} ( : I -> R) :
  (isdistr mu) <-> (forall , 0 <= mu x) /\ (\sum_ mu j <= 1).
Proof.
split=> -[ ge0_mu le1]; split=> //.
+ by apply/le1; rewrite /index_enum -enumT enum_uniq.
+ move=> J uqJ; rewrite big_uniq 1?(le_trans _ le1) //=.
  by rewrite [X in _<=X](bigID (mem J)) /= lerDl sumr_ge0.
Qed.

Lemma
  { : realType} { : choiceType} ( : {distr T / R}) : mu x <= 1.
Proof.
apply/(@le_trans _ _ (PosSum.psum mu)) => //; rewrite -[mu x]ger0_norm//.
by apply/ger1_psum.
Qed.

Section DistrD.
Context { : realType} { : choiceType} ( : T -> R).

Definition
mnull

mnull : forall {R : realType} {T : choiceType}, T -> R mnull is not universe polymorphic Arguments mnull {R T} x mnull is transparent Expands to: Constant mathcomp.experimental_reals.distr.mnull Declared in library mathcomp.experimental_reals.distr, line 192, characters 11-16


Source code
:= fun : T => (0 : R).

Lemma
isd_mnull
Source code
: isdistr mnull.
Proof.
by split=> // J _; rewrite big1 ?ler01. Qed.

Definition
dnull

dnull : forall {R : realType} {T : choiceType}, distr R T dnull is not universe polymorphic Arguments dnull {R T} dnull is transparent Expands to: Constant mathcomp.experimental_reals.distr.dnull Declared in library mathcomp.experimental_reals.distr, line 197, characters 11-16


Source code
:= locked (mkdistr isd_mnull).

Lemma : dnull x = 0.
Proof.
by unlock dnull. Qed.

Definition
mkdistrd

mkdistrd : forall {R : realType} {T : choiceType}, (T -> R) -> {distr T / R} mkdistrd is not universe polymorphic Arguments mkdistrd {R T} mu%_function_scope mkdistrd is transparent Expands to: Constant mathcomp.experimental_reals.distr.mkdistrd Declared in library mathcomp.experimental_reals.distr, line 202, characters 11-19


Source code
: {distr T / R} :=
  if @idP `[< isdistr mu >] is ReflectT Px then
    mkdistr (asboolW Px)
  else dnull.
End DistrD.

Lemma
lef_dnull
Source code
{ : realType} { : choiceType} ( : {distr T / R}) :
  dnull <=1 mu.
Proof.
by move=> x; rewrite dnullE ge0_mu. Qed.

Section Restr.
Context { : realType} { : choiceType} ( : pred T).

Definition
mrestr

mrestr : forall {R : realType} {T : choiceType}, pred T -> {distr T / R} -> T -> R mrestr is not universe polymorphic Arguments mrestr {R T} p mu x mrestr is transparent Expands to: Constant mathcomp.experimental_reals.distr.mrestr Declared in library mathcomp.experimental_reals.distr, line 217, characters 11-17


Source code
( : {distr T / R}) :=
  fun => if p x then mu x else 0.

Lemma
isd_mrestr
Source code
( : {distr T / R}) : isdistr (mrestr mu).
Proof.
split=> [x|J]; first by rewrite /mrestr; case: ifP.
move=> eqJ; apply/(@le_trans _ _ (\sum_( <- J) `|mu j|)).
+ apply/ler_sum=> i _; rewrite /mrestr; case: ifPn=> _.
  by apply/ler_norm. by apply/normr_ge0.
+ by apply/(le_trans _ (le1_mu mu))/gerfinseq_psum.
Qed.

Definition
drestr

drestr : forall {R : realType} {T : choiceType}, pred T -> {distr T / R} -> distr R T drestr is not universe polymorphic Arguments drestr {R T} p mu drestr is transparent Expands to: Constant mathcomp.experimental_reals.distr.drestr Declared in library mathcomp.experimental_reals.distr, line 229, characters 11-17


Source code
( : {distr T / R}) := locked (mkdistr (isd_mrestr mu)).

Lemma ( : {distr T / R}) :
  drestr mu x = if p x then mu x else 0.
Proof.
by unlock drestr. Qed.
End Restr.

Section RestrTheory.
Context { : realType} { : choiceType}.

Lemma ( : {distr T / R}) ( : pred T) :
  mu x = drestr p mu x + drestr (predC p) mu x.
Proof.
by rewrite !drestrE !inE; case: ifPn; rewrite /= (addr0, add0r). Qed.

Lemma
dinsupp_restr
Source code
( : {distr T / R}) ( : pred T) :
  (x \in dinsupp (drestr p mu)) = (x \in dinsupp mu) && p x.
Proof.
apply/dinsuppP/idP.
- by rewrite drestrE; case: ifP=> // _ /dinsuppP ->.
- by case/andP; rewrite drestrE => /dinsuppP ? ->.
Qed.
End RestrTheory.

Section DRat.
Context { : realType} ( : choiceType).

Local Notation := {distr T / R}.

Implicit Types (s : seq T).

Definition
mrat

mrat : forall {R : realType} [T : choiceType], seq T -> T -> R mrat is not universe polymorphic Arguments mrat {R} [T] s%_seq_scope _ mrat is transparent Expands to: Constant mathcomp.experimental_reals.distr.mrat Declared in library mathcomp.experimental_reals.distr, line 261, characters 11-15


Source code
( : seq T) : T -> R :=
  fun : T => (count (pred1 x) s)%:R / (size s)%:R.

Lemma
ge0_mrat
Source code
: forall , 0 <= mrat s x.
Proof.
by move=> x; rewrite mulr_ge0 ?invr_ge0 // ler0n. Qed.

Local Lemma
has_sup_mrat
Source code
: uniq J -> \sum_( <- J) mrat s i <= 1.
Proof.
move=> uqJ; rewrite -mulr_suml /= -natr_sum; case: (size s =P 0%N).
  by move=> ->; rewrite invr0 mulr0 ler01.
move=> /eqP nz_s; rewrite ler_pdivrMr ?ltr0n ?lt0n // mul1r.
rewrite ler_nat (bigID (mem s)) /= [X in (_+X)%N]big1 ?addn0.
   by move=> i /count_memPn.
have ->: (size s = \sum_( <- undup s) count_mem i s)%N.
  rewrite -sum1_size -big_undup_iterop_count; apply: eq_bigr => i _.
  by rewrite Monoid.iteropE iter_addn addn0 mul1n.
rewrite [X in (_<=X)%N](bigID (mem J)) /= -ltnS -addSn.
rewrite ltn_addr //= ltnS -big_filter -[X in (_<=X)%N]big_filter.
rewrite leq_eqVlt; apply/orP; left; apply/eqP/perm_big.
apply/uniq_perm; rewrite ?filter_uniq ?undup_uniq //.
by move=> x; rewrite !mem_filter mem_undup andbC.
Qed.

Local Lemma
mrat_sup
Source code
: (0 < size s)%N ->
  \sum_( <- undup s) mrat s i = 1.
Proof.
move=> gt0_s; rewrite -mulr_suml -natr_sum.
apply/(mulIf (x := (size s)%:R)); first by rewrite pnatr_eq0 -lt0n.
rewrite mul1r divfK ?pnatr_eq0 -?lt0n//; congr (_%:R).
rewrite -sum1_size -[in RHS]big_undup_iterop_count/=; apply: eq_bigr => i _.
by rewrite Monoid.iteropE iter_addn addn0 mul1n.
Qed.

Local Lemma
summable_mrat
Source code
: summable (mrat s).
Proof.
apply/summable_seqP; exists 1=> // J uqJ; rewrite (eq_bigr (mrat s)).
  by move=> j _; rewrite ger0_norm ?ge0_mrat.
by apply/has_sup_mrat.
Qed.

Lemma
isd_mrat
Source code
: isdistr (mrat s).
Proof.
by split; [apply/ge0_mrat | apply/has_sup_mrat]. Qed.

Definition
drat

drat : forall {R : realType} [T : choiceType], seq T -> distr R T drat is not universe polymorphic Arguments drat {R} [T] s%_seq_scope drat is transparent Expands to: Constant mathcomp.experimental_reals.distr.drat Declared in library mathcomp.experimental_reals.distr, line 304, characters 11-15


Source code
:= locked (mkdistr (isd_mrat s)).

Lemma :
  drat s x = (count_mem x s)%:R / (size s)%:R.
Proof.
by unlock drat; rewrite mkdistrE. Qed.

Definition
dunit

dunit : forall {R : realType} [T : choiceType], T -> distr R T dunit is not universe polymorphic Arguments dunit {R} [T] x dunit is transparent Expands to: Constant mathcomp.experimental_reals.distr.dunit Declared in library mathcomp.experimental_reals.distr, line 310, characters 11-16


Source code
:= locked (drat [:: x]).
Definition
duni

duni : forall {R : realType} [T : choiceType], seq T -> distr R T duni is not universe polymorphic Arguments duni {R} [T] s%_seq_scope duni is transparent Expands to: Constant mathcomp.experimental_reals.distr.duni Declared in library mathcomp.experimental_reals.distr, line 311, characters 11-15


Source code
:= locked (drat (undup s)).

Lemma : (dunit x) y = (x == y)%:R.
Proof.
by unlock dunit; rewrite drat1E /= !(simpm, invr1). Qed.

Lemma : (duni s) x = (x \in s)%:R / (size (undup s))%:R.
Proof.
by unlock duni; rewrite drat1E count_uniq_mem ?(mem_undup, undup_uniq).
Qed.

Lemma
in_dunit
Source code
:
  t' \in dinsupp (dunit t) -> t' = t :> T.
Proof.
by rewrite in_dinsupp dunit1E pnatr_eq0 eqb0 negbK => /eqP.
Qed.
End DRat.

Section Flip.
Context { : realType}.

Definition
mflip

mflip : forall {R : realType}, R -> bool -> R mflip is not universe polymorphic Arguments mflip {R} xt%_ring_scope b%_bool_scope mflip is transparent Expands to: Constant mathcomp.experimental_reals.distr.mflip Declared in library mathcomp.experimental_reals.distr, line 332, characters 11-16


Source code
( : R) :=
  fun => if b then clamp xt else 1 - clamp xt.

Lemma
isd_mflip
Source code
: isdistr (mflip xt).
Proof.
apply/isdistr_finP; split=> [b|].
+ by case: b; rewrite ?subr_ge0 cp01_clamp.
+ by rewrite /index_enum !unlock /= addr0 addrC subrK.
Qed.

Definition
dflip

dflip : forall {R : realType}, R -> distr R Datatypes_bool__canonical__choice_Choice dflip is not universe polymorphic Arguments dflip {R} xt%_ring_scope dflip is transparent Expands to: Constant mathcomp.experimental_reals.distr.dflip Declared in library mathcomp.experimental_reals.distr, line 341, characters 11-16


Source code
( : R) := locked (mkdistr (isd_mflip xt)).

Lemma : dflip xt =1 mflip xt.
Proof.
by unlock dflip; apply/mkdistrE. Qed.
End Flip.

Section Std.
Context { : realType}.

Local Notation T := {distr T / R}.

Implicit Types (T U : choiceType).

Section Bind.
Context { : choiceType} ( : T -> distr U) ( : distr T).

Definition
mlet

mlet : forall {R : realType} {T U : choiceType}, (T -> {distr U / R}) -> {distr T / R} -> U -> R mlet is not universe polymorphic Arguments mlet {R T U} f%_function_scope mu y mlet is transparent Expands to: Constant mathcomp.experimental_reals.distr.mlet Declared in library mathcomp.experimental_reals.distr, line 359, characters 11-15


Source code
:= fun : U => PosSum.psum (fun => mu x * f x y).

Lemma
isd_mlet
Source code
: isdistr mlet.
Proof.
split=> [x|J uqJ]; first by apply/ge0_psum.
rewrite /mlet psum_bigop; first by move=> y x; rewrite mulr_ge0.
  move=> u; apply/(le_summable (F2 := mu)) => //.
  by move=> x; rewrite mulr_ge0 //= ler_piMr ?le1_mu1.
apply/(le_trans _ (le1_mu mu))/le_psum => //.
move=> x; rewrite sumr_ge0 /= => [y _|]; first by rewrite mulr_ge0.
rewrite -mulr_sumr ler_piMr //; apply/(le_trans _ (le1_mu (f x))).
have := summable_mu (f x) => /gerfinseq_psum => /(_ _ uqJ).
by apply/(le_trans _)/ler_sum=> y _; apply/ler_norm.
Qed.

Definition
dlet

dlet : forall {R : realType} {T U : choiceType}, (T -> {distr U / R}) -> {distr T / R} -> distr R U dlet is not universe polymorphic Arguments dlet {R T U} f%_function_scope mu dlet is transparent Expands to: Constant mathcomp.experimental_reals.distr.dlet Declared in library mathcomp.experimental_reals.distr, line 374, characters 11-15


Source code
:= locked (mkdistr isd_mlet).

Lemma : dlet y = PosSum.psum (fun => mu x * f x y).
Proof.
by unlock dlet. Qed.
End Bind.

Notation
"\dlet_ ( i <- d ) E"
Source code
:= (dlet (fun => E) d).

Definition
dlift

dlift : forall {R : realType} {A : choiceType}, (A -> {distr A / R}) -> {distr A / R} -> distr R A dlift is not universe polymorphic Arguments dlift {R A} f%_function_scope d dlift is transparent Expands to: Constant mathcomp.experimental_reals.distr.dlift Declared in library mathcomp.experimental_reals.distr, line 382, characters 11-16


Source code
{ : choiceType} ( : A -> {distr A / R}) :=
  fun => \dlet_( <- d) f x.

Definition
diter

diter : forall {R : realType} {A : choiceType}, nat -> (A -> {distr A / R}) -> A -> {distr A / R} diter is not universe polymorphic Arguments diter {R A} n%_nat_scope f%_function_scope a diter is transparent Expands to: Constant mathcomp.experimental_reals.distr.diter Declared in library mathcomp.experimental_reals.distr, line 385, characters 11-16


Source code
{ : choiceType} ( : A -> {distr A / R}) :=
  fun => (iter n (dlift f) (dunit a)).

Section BindTheory.
Variables ( : choiceType).

Implicit Types (f g : T -> distr U) (mu nu : distr T).

Lemma
dlet_null
Source code
: dlet f dnull =1 dnull.
Proof.
move=> x; rewrite dletE dnullE /= /mlet psum_eq0 //.
by move=> y; rewrite dnullE mul0r.
Qed.

Lemma
dlet_unit
Source code
: \dlet_( <- dunit v) f y =1 f v.
Proof.
move=> y; rewrite dletE (psum_finseq (r := [:: v])) //.
  move=> x; rewrite !inE dunit1E mulf_eq0 => /norP[].
  by rewrite pnatr_eq0 eqb0 negbK => /eqP->.
by rewrite big_seq1 dunit1E eqxx mul1r ger0_norm.
Qed.

Lemma
dlet_dunit_id
Source code
: \dlet_( <- mu) (dunit t) =1 mu.
Proof.
move=> x; rewrite dletE (psum_finseq (r := [:: x])) //.
  move=> y; rewrite !inE dunit1E mulf_eq0 pnatr_eq0.
  by case/norP; rewrite eqb0 negbK.
by rewrite big_seq1 dunit1E eqxx mulr1 ger0_norm.
Qed.

Lemma
eq_in_dlet
Source code
: {in dinsupp mu, f =2 g} -> mu =1 nu ->
  dlet f mu =1 dlet g nu.
Proof.
move=> eq_f eq_mu; unlock dlet=> y /=; apply/eq_psum=> x.
rewrite -eq_mu; case/boolP: (x \in dinsupp mu) => [/eq_f ->//|].
by move/dinsuppPn=> ->; rewrite !mul0r.
Qed.

Lemma
summable_mu_wgtd
Source code
( : T -> R) :
  (forall , 0 <= f x <= 1) -> summable (fun => mu x * f x).
Proof.
move=> in01_f; apply/summableMr=> //.
exists 1 => x; case/andP: (in01_f x) => ge0_fx le1_fx.
by rewrite ger0_norm.
Qed.

Lemma
summable_mlet
Source code
: summable (fun : T => mu x * (f x) y).
Proof.
by apply/summable_mu_wgtd=> x; rewrite ge0_mu le1_mu1. Qed.

Lemma
le_in_dlet
Source code
: {in dinsupp mu, f <=2 g} ->
  dlet f mu <=1 dlet g mu.
Proof.
(* summable -> refactor *)
move=> le_f; unlock dlet=> y /=; apply/le_psum/summable_mlet.
move=> x; rewrite mulr_ge0 //=; case: (mu x =P 0).
  by move=> ->; rewrite !mul0r.
by move/dinsuppPn/le_f/(_ y) => h; rewrite ler_pM.
Qed.

Lemma
le_mu_dlet
Source code
: mu <=1 nu -> dlet f mu <=1 dlet f nu.
Proof.
move=> le_mu x; unlock dlet; rewrite /= /mlet.
apply/le_psum/summable_mlet => y; rewrite mulr_ge0 //=.
case: (mu y =P 0) => [->|]; first by rewrite mul0r mulr_ge0.
by move=>/dinsuppPn=> h; rewrite ler_pM.
Qed.

Lemma :
    mu <=1 nu
  -> {in dinsupp mu, forall , f x <=1 g x}
  -> \dlet_( <- mu) f x <=1 \dlet_( <- nu) g x.
Proof.
move=> le_mu le_fg x.
by apply/(le_trans (le_in_dlet le_fg _))/le_mu_dlet.
Qed.

Lemma ( : {distr T / R}) ( : {distr U / R}) :
  (\dlet_(_ <- mu) nu) y = (dweight mu) * (nu y).
Proof.
rewrite dletE /pr [_ * nu y]mulrC -psumZ //=; apply/eq_psum.
by move=> /= x; rewrite mul1r mulrC.
Qed.

Lemma
dinsupp_dlet
Source code
:
  y \in dinsupp (\dlet_( <- mu) f x) ->
    exists2 , x \in dinsupp mu & f x y != 0.
Proof.
move/dinsuppP; rewrite dletE => /neq0_psum [x /eqP]; rewrite mulf_eq0.
by case/norP=> /eqP/dinsuppPn mux nz_fxy; exists x.
Qed.

Lemma
dlet_dinsupp
Source code
:
  x \in dinsupp mu -> f x y != 0 -> y \in dinsupp (dlet f mu).
Proof.
move=> /dinsuppP /eqP mux nz_fxy; apply/dinsuppP; rewrite dletE.
move/eq0_psum => /(_ (summable_mlet _ _ _) x) => /eqP.
by rewrite mulf_eq0 (negbTE mux) (negbTE nz_fxy).
Qed.

Lemma
dlet_eq0
Source code
( : T -> U) :
  {in dinsupp mu, forall , f x != y} -> (\dlet_( <- mu) dunit (f x)) y = 0.
Proof.
move=> h; unlock dlet => /=; apply/psum_eq0 => x.
case/boolP: (x \in dinsupp mu) => [|/dinsuppPn->];
  last by rewrite mul0r.
by move/h; rewrite dunit1E => /negbTE ->; rewrite mulr0.
Qed.

Lemma
eq0_dlet
Source code
( : {distr T / R}) ( : T -> {distr U / R}) :
  (\dlet_( <- mu) F x) y = 0 -> forall , x \in dinsupp mu -> F x y = 0.
Proof.
unlock dlet; rewrite /= /mlet => /eq0_psum h x /dinsuppP /eqP mu_x.
have {}/h: summable (fun => mu x * F x y).
  apply/(le_summable (F2 := mu)) => // z.
  by rewrite mulr_ge0 //= ler_piMr // le1_mu1.
by move/(_ x)/eqP; rewrite mulf_eq0 (negbTE mu_x) /= => /eqP.
Qed.
End BindTheory.

Section DLetDLet.
Context { : choiceType} ( : T -> distr U) ( : U -> distr V).

Lemma
dlet_dlet
Source code
( : {distr T / R}) :
     \dlet_( <- \dlet_( <- mu) f1 y) f2 x
  =1 \dlet_( <- mu) (\dlet_( <- f1 y) f2 x).
Proof.
move=> z; unlock dlet => /=; rewrite /mlet /=.
pose S := mu x * (f1 x y * f2 y z).
rewrite (eq_psum (F2 := fun => PosSum.psum (S^~ y))) => [x|].
  by rewrite -psumZ //; apply/eq_psum => y /=.
rewrite interchange_psum.
+ by move=> x; apply/summableZ/summable_mlet.
+ rewrite {}/S; apply/(le_summable (F2 := mu)) => //.
  move=> x; rewrite ge0_psum /= psumZ ?ler_piMr //.
  apply/(le_trans _ (le1_mu (f1 x)))/le_psum => //.
  by move=> y; rewrite mulr_ge0 //= ler_piMr ?le1_mu1.
apply/eq_psum=> y /=; rewrite -psumZr //.
by apply/eq_psum=> x /=; rewrite {}/S mulrA.
Qed.

End DLetDLet.

Section DLetAlg.
Context { : choiceType} ( : {distr T / R}).

Lemma
dlet_additive
Source code
( : T -> {distr U / R}) :
  (forall , mu x = mu1 x + mu2 x) -> (\dlet_( <- mu) f x) z =
    (\dlet_( <- mu1) f x) z + (\dlet_( <- mu2) f x) z.
Proof.
move=> muD; rewrite !dletE -psumD /=.
  by move=> x; rewrite mulr_ge0. by move=> x; rewrite mulr_ge0.
  by apply/summable_mlet. by apply/summable_mlet.
by apply/eq_psum=> x /=; rewrite -mulrDl -muD.
Qed.
End DLetAlg.

Definition
mlim

mlim : forall {R : realType} [T : choiceType], (nat -> {distr T / R}) -> T -> R mlim is not universe polymorphic Arguments mlim {R} [T] f%_function_scope _ mlim is transparent Expands to: Constant mathcomp.experimental_reals.distr.mlim Declared in library mathcomp.experimental_reals.distr, line 544, characters 11-15


Source code
( : nat -> distr T) : T -> R :=
  fun => fine (nlim (fun => f n x)).

Lemma
isd_mlim
Source code
( : nat -> distr T) : isdistr (mlim f).
Proof.
split=> [x|J]; rewrite /mlim.
  case: nlimP=> // l cvSl; apply/fine_ge0/(ncvg_geC _ cvSl).
  by move=> n; apply/ge0_mu.
move=> uqJ; pose F :=
  if `[< iscvg (fun => f n j) >] then fun => f n j else 0%:S.
apply/(@le_trans _ _ (\sum_( <- J) (fine (nlim (F j) (*: R*))))).
  apply/ler_sum=> j _; rewrite /F; case/boolP: `[< _ >] => //.
  move/asboolPn=> h; rewrite nlimC; case: nlimP=> //.
  by case=> // l cf; case: h; exists l.
rewrite -lee_fin -nlim_sumR => [i _|].
  rewrite /F; case/boolP: `[< _ >] => [/asboolP //|].
  by move=> _; apply/iscvgC.
rewrite leNgt; apply/negP; pose s := \sum_( <- J) F j n.
move/ncvg_gt=> -/(_ s (nlim_ncvg _)) [].
  suff: iscvg s by case=> l cs; exists l%:E.
  apply/iscvg_sum=> j _; rewrite /F; case/boolP: `[< _ >].
    by move/asboolP. by move=> _; apply/iscvgC.
move=> K /(_ _ (leqnn K)) /=; apply/negP; rewrite -leNgt.
apply/(@le_trans _ _ (\sum_( <- J) f K j)); last first.
  have /(gerfinseq_psum uqJ) := summable_mu (f K).
  move/le_trans=> -/(_ _ (le1_mu (f K)))=> h.
  by apply/(le_trans _ h)/ler_sum=> i _; apply/ler_norm.
by apply/ler_sum=> j _; rewrite /F; case/boolP: `[< _ >].
Qed.

Definition
dlim

dlim : forall {R : realType} [T : choiceType], (nat -> {distr T / R}) -> distr R T dlim is not universe polymorphic Arguments dlim {R} [T] f%_function_scope dlim is transparent Expands to: Constant mathcomp.experimental_reals.distr.dlim Declared in library mathcomp.experimental_reals.distr, line 574, characters 11-15


Source code
( : nat -> distr T) :=
  locked (mkdistr (isd_mlim f)).

Notation
"\dlim_ ( n ) E"
Source code
:= (dlim (fun => E)).

Lemma ( : nat -> distr T) :
  (\dlim_() f n) x = fine (nlim (fun => f n x)).
Proof.
by unlock dlim. Qed.

Section DLimTheory.
Variables ( : choiceType).

Implicit Types (f g : nat -> distr T) (h : T -> {distr U / R}).
Implicit Types (mu : {distr T / R}).

Lemma : \dlim_() mu =1 mu.
Proof.
by move=> x; rewrite !dlimE; rewrite nlimC. Qed.

Lemma : f =2 g -> dlim f =1 dlim g.
Proof.
move=> eq_f; unlock dlim=> x /=; rewrite /mlim; congr (_ _).
by apply/eq_nlim => n; rewrite eq_f.
Qed.

Lemma
eq_from_dlim
Source code
:
  (forall , (K <= n)%N -> f n =1 g n) -> dlim f =1 dlim g.
Proof.
move=> eq_fg x; rewrite !dlimE; congr (_ _).
by apply/(eq_from_nlim (K := K)); move=> n /eq_fg /(_ x).
Qed.

Definition
dlim_bump

dlim_bump : forall {R : realType} [T : choiceType] (mu0 : nat -> {distr T / R}), \dlim_(n) mu0 n.+1 =1 \dlim_(n) mu0 n dlim_bump is not universe polymorphic Arguments dlim_bump {R} [T] mu%_function_scope x dlim_bump is opaque Expands to: Constant mathcomp.experimental_reals.distr.dlim_bump Declared in library mathcomp.experimental_reals.distr, line 606, characters 11-20


Source code
( : nat -> {distr T / R}) :
  dlim (fun => mu n.+1) =1 dlim mu.
Proof.
by move=> x; rewrite !dlimE -[in RHS]nlim_bump. Qed.

Definition
dlim_lift

dlim_lift : forall {R : realType} [T : choiceType] (mu0 : nat -> {distr T / R}) (p : nat), \dlim_(n) mu0 (n + p) =1 \dlim_(n) mu0 n dlim_lift is not universe polymorphic Arguments dlim_lift {R} [T] mu%_function_scope p%_nat_scope x dlim_lift is opaque Expands to: Constant mathcomp.experimental_reals.distr.dlim_lift Declared in library mathcomp.experimental_reals.distr, line 610, characters 11-20


Source code
( : nat -> {distr T / R}) :
  dlim (fun => mu (n + p)%N) =1 dlim mu.
Proof.
by move=> x; rewrite !dlimE (nlim_lift (fun => (mu n) x)). Qed.

Definition
dcvg

dcvg : forall {R : realType} {T : choiceType}, (nat -> {distr T / R}) -> Prop dcvg is not universe polymorphic Arguments dcvg {R T} f%_function_scope dcvg is transparent Expands to: Constant mathcomp.experimental_reals.distr.dcvg Declared in library mathcomp.experimental_reals.distr, line 614, characters 11-15


Source code
{ : choiceType} ( : nat -> {distr T / R}) :=
  forall , exists , ncvg (fun => f n x) l.

Definition
ducvg

ducvg : forall {R : realType} {T : choiceType}, (nat -> {distr T / R}) -> Prop ducvg is not universe polymorphic Arguments ducvg {R T} f%_function_scope ducvg is transparent Expands to: Constant mathcomp.experimental_reals.distr.ducvg Declared in library mathcomp.experimental_reals.distr, line 617, characters 11-16


Source code
{ : choiceType} ( : nat -> {distr T / R}) :=
  exists , forall , ncvg (fun => f n x) l.

CoInductive
dlim_spec
Source code
( : T) : R -> Type :=
| : forall : R, 0 <= l -> l <= 1 ->
    ncvg (fun => f n x) l%:E -> dlim_spec f x l

| : ~ (exists : \bar R, ncvg (fun => f n x) l) ->
    dlim_spec f x 0.

Lemma : dlim_spec f x (dlim f x).
Proof.
rewrite dlimE; case: nlimP => [l h|?] /=; last by apply/DLimOut.
have: (0%:E <= l)%E by apply/ncvg_geC: h => n; apply/ge0_mu.
have: (l <= 1%:E)%E by apply/ncvg_leC: h => n; apply/le1_mu1.
by case: l h => // l h /= ge0_l ge1_; apply/DLimCvg.
Qed.

Lemma : dcvg f -> forall ,
  exists2 , (0 <= l <= 1) & ncvg (f^~ x) l%:E.
Proof.
move=> cv_f x; case: (dlimP f x) => [l ge0_l le1_l cv|].
  by exists l => //; apply/andP; split.
by case; case: (cv_f x).
Qed.

Lemma
dcvg_homo
Source code
:
  (forall , (n <= m)%N -> f n <=1 f m) -> dcvg f.
Proof.
move=> mn_f x; have: forall , (n <= m)%N -> f n x <= f m x.
  by move=> n m /mn_f; apply.
case/ncvg_mono_bnd => {mn_f}; first apply/asboolP/nboundedP.
  exists 2%:R => // n; apply/(@le_lt_trans _ _ 1%:R)/ltr_nat.
  by rewrite ger0_norm // le1_mu1.
by move=> y h; exists y%:E.
Qed.

Lemma
ge0_dlim
Source code
: forall , 0 <= dlim f x.
Proof.
by move=> x; case: dlimP. Qed.

Lemma
le1_dlim
Source code
: forall , dlim f x <= 1.
Proof.
by move=> x; case: dlimP => // _; apply/ler01. Qed.

Lemma :
  (forall , f n <=1 g n) -> dcvg g -> dlim f <=1 dlim g.
Proof.
move=> le dcvg_g x; case: dlimP => [|_]; last by apply/ge0_dlim.
move=> l _ _ h; case: dlimP => [l' _ _ h'|]; last by case.
by rewrite -lee_fin; apply/(ncvg_le _ h' h).
Qed.

Lemma
leub_dlim
Source code
: (forall , f n <=1 mu) -> dlim f <=1 mu.
Proof.
move=> le x; apply/(@le_trans _ _ ((\dlim_() mu) x)).
  by apply/le_dlim => // y; exists (mu y)%:E; apply/ncvgC.
by rewrite dlimE nlimC.
Qed.

Lemma :
  (forall , (n <= m)%N -> f n <=1 f m) -> f k <=1 dlim f.
Proof.
move=> mn_f x; rewrite dlimE -lee_fin; pose u := f n x.
apply/(ncvg_homo_le (u := u))=> [m n /mn_f|]; first by apply.
move/dcvg_homo: mn_f => /dcvgP /(_ x) [l _].
by move=> cv; rewrite (nlimE cv).
Qed.

Lemma
__admitted__dlet_lim
Source code
: (forall , (n <= m)%N -> f n <=1 f m) ->
  \dlet_( <- dlim f) h x =1 \dlim_() \dlet_( <- f n) h x.
Proof.
Admitted.

Lemma
__admitted__dlim_let
Source code
( : nat -> T -> {distr U / R}) ( : {distr T / R}) :
  (forall , (n <= m)%N -> f n x <=1 f m x) ->
  \dlim_() \dlet_( <- mu) (f n x) =1
    \dlet_( <- mu) \dlim_() (f n x).
Proof using Type. End DLimTheory.

#[deprecated(since="mathcomp-analysis 0.6.2",
  note="lacks proof, use __admitted__dlet_lim explicitly if you really want to use this lemma")]
Notation
dlet_lim
Source code
:= __admitted__dlet_lim.
#[deprecated(since="mathcomp-analysis 0.6.2",
  note="lacks proof, use __admitted__dlim_let explicitly if you really want to use this lemma")]
Notation
dlim_let
Source code
:= __admitted__dlim_let.

Section Marginals.
Variable ( : choiceType) ( : T -> U) ( : distr T).

Definition
dmargin

dmargin : forall {R : realType} [T U : choiceType], (T -> U) -> {distr T / R} -> distr R U dmargin is not universe polymorphic Arguments dmargin {R} [T U] h%_function_scope mu dmargin is transparent Expands to: Constant mathcomp.experimental_reals.distr.dmargin Declared in library mathcomp.experimental_reals.distr, line 706, characters 11-18


Source code
:= \dlet_( <- mu) (dunit (h x)).

Lemma
dmarginE
Source code
: dmargin = \dlet_( <- mu) (dunit (h y)).
Proof.
by []. Qed.
End Marginals.

Section MarginalsTh.
Variable ( : choiceType).

Lemma
dmargin_psumE
Source code
( : {distr T / R}) ( : T -> U) :
  (dmargin f mu) y = PosSum.psum (fun => (f x == y)%:R * mu x).
Proof.
rewrite dmarginE dletE; apply/eq_psum => x //=.
by rewrite mulrC dunit1E.
Qed.

Lemma
dlet_dmargin
Source code
( : {distr T / R}) ( : T -> U) ( : U -> {distr V / R}):
  \dlet_( <- dmargin f mu) g u =1 \dlet_( <- mu) (g (f t)).
Proof.
move=> x; rewrite dlet_dlet; apply: eq_in_dlet=> //.
by move=> y _ z; rewrite dlet_unit.
Qed.

Lemma
dmargin_dlet
Source code
( : {distr T / R}) ( : U -> V) ( : T -> {distr U / R}):
  dmargin f (\dlet_( <- mu) g t) =1 \dlet_( <- mu) (dmargin f (g t)).
Proof.
by apply/dlet_dlet. Qed.

Lemma
dmargin_dunit
Source code
( : T) ( : T -> U):
  dmargin f (dunit t) =1 dunit (f t) :> {distr U / R}.
Proof.
by apply/dlet_unit. Qed.
End MarginalsTh.
End Std.

#[deprecated(since="1.17.0", note="use `dmargin_dlet` instead")]
Notation
__deprecated__dmargin_dlet
Source code
:= dmargin_dlet (only parsing).
#[deprecated(since="1.17.0", note="use `dlet_dmargin` instead")]
Notation
__deprecated__dlet_dmargin
Source code
:= dlet_dmargin (only parsing).
#[deprecated(since="1.17.0", note="use `dlet_dlet` instead")]
Notation
__deprecated__dlet_dlet
Source code
:= dlet_dlet (only parsing).

Notation mu := (dmargin fst mu).
Notation mu := (dmargin snd mu).

Notation
"\dlet_ ( i <- d ) E"
Source code
:= (dlet (fun => E) d).
Notation
"\dlim_ ( n ) E"
Source code
:= (dlim (fun => E)).

Section DSwap.
Context { : realType} { : choiceType} ( : {distr (A * B) / R}).

Definition
dswap

dswap : forall {R : realType} {A B : choiceType}, {distr (A * B) / R} -> {distr (B * A) / R} dswap is not universe polymorphic Arguments dswap {R A B} mu dswap is transparent Expands to: Constant mathcomp.experimental_reals.distr.dswap Declared in library mathcomp.experimental_reals.distr, line 758, characters 11-16


Source code
: {distr (B * A) / R} :=
  dmargin (fun => (xy.2, xy.1)) mu.
End DSwap.

Section DSwapCoreTheory.
Context { : realType} { : choiceType} ( : {distr (A * B) / R}).

Lemma : dswap mu xy = mu (xy.2, xy.1).
Proof.
rewrite dletE /= (psum_finseq (r := [:: (xy.2, xy.1)])) //.
  case=> a b; rewrite !inE dunit1E /= mulf_eq0.
  by case/norP=> _; rewrite pnatr_eq0 eqb0 negbK=> /eqP <-.
by case: xy=> x y; rewrite big_seq1 dunit1E /= eqxx mulr1 ger0_norm.
Qed.
End DSwapCoreTheory.

Section DSwapTheory.
Context { : realType} { : choiceType} ( : {distr (A * B) / R}).

Lemma : dswap (dswap mu) =1 mu.
Proof.
by case=> x y; rewrite !dswapE. Qed.

Lemma
dinsupp_swap
Source code
: (xy.2, xy.1) \in dinsupp mu ->
  xy \in dinsupp (dswap mu).
Proof.
by move=> h; apply/dinsuppP; rewrite dswapE; apply/dinsuppPn.
Qed.

Lemma
dfst_dswap
Source code
: dfst (dswap mu) =1 dsnd mu.
Proof.
move=> z; rewrite dlet_dlet; apply/eq_in_dlet => // -[x y].
by move=> _ t /=; rewrite dlet_unit /=.
Qed.

Lemma
dsnd_dswap
Source code
: dsnd (dswap mu) =1 dfst mu.
Proof.
move=> z; rewrite dlet_dlet; apply/eq_in_dlet => // -[x y].
by move=> _ t /=; rewrite dlet_unit /=.
Qed.
End DSwapTheory.

#[deprecated(since="1.17.0", note="use `dfst_dswap` instead")]
Notation
__deprecated__dfst_dswap
Source code
:= dfst_dswap (only parsing).
#[deprecated(since="1.17.0", note="use `dsnd_dswap` instead")]
Notation
__deprecated__dsnd_dswap
Source code
:= dsnd_dswap (only parsing).

Section DFst.
Context { : realType} { : choiceType}.

Lemma ( : {distr (T * U) / R}) :
  dfst mu x = PosSum.psum (fun => mu (x, y)).
Proof.
rewrite dmargin_psumE /=; pose h : T * U := (x, y).
rewrite (reindex_psum (P := [pred | z.1 == x]) (h := h)) /=.
+ case=> a b; rewrite !inE/= mulf_eq0 => /norP[].
  by rewrite pnatr_eq0 eqb0 negbK.
+ by exists snd => [z|[z1 z2]]; rewrite !inE //= => /eqP ->.
by apply/eq_psum => y; rewrite eqxx mul1r.
Qed.

Lemma
summable_fst
Source code
( : {distr (T * U) / R}) :
  summable (fun => mu (x, y)).
Proof.
have /summable_seqP /= := summable_mu mu => -[M ge0_M h].
apply/summable_seqP; exists M => // J uqJ; pose X := [seq (x, y) | <- J].
apply/(le_trans _ (h X _)); last by rewrite map_inj_uniq // => y1 y2 [].
by rewrite le_eqVlt big_map eqxx.
Qed.
End DFst.

Section DSnd.
Context { : realType} { : choiceType}.

Lemma ( : {distr (T * U) / R}) :
  dsnd mu y = PosSum.psum (fun => mu (x, y)).
Proof.
by rewrite -dfst_dswap dfstE; apply/eq_psum=> x; rewrite dswapE. Qed.

Lemma
summable_snd
Source code
( : {distr (T * U) / R}) :
  summable (fun => mu (x, y)).
Proof.
have := summable_fst (dswap mu) y; apply/eq_summable.
by move=> x /=; rewrite dswapE.
Qed.
End DSnd.

#[deprecated(since="1.17.0", note="use `dsndE` instead")]
Notation
__deprecated__dsndE
Source code
:= dsndE (only parsing).

Section PrCoreTheory.
Context { : realType} { : choiceType}.

Implicit Types (mu : {distr T / R}) (A B E : pred T).

Lemma
summable_pr
Source code
: summable (fun => (E x)%:R * mu x).
Proof.
apply/(le_summable (F2 := mu)) => [x|]; last by apply/summable_mu.
  by rewrite mulr_ge0 ?ler0n //= ler_piMl // lern1 leq_b1.
Qed.

Lemma
pr_pred0
Source code
: \P_[mu] pred0 = 0.
Proof.
by rewrite /pr psum_eq0 // => x /=; rewrite mul0r. Qed.

Lemma
pr_pred1
Source code
: mu x = \P_[mu] (pred1 x).
Proof.
rewrite /pr (psum_finseq (r := [:: x])) // => [y|].
  by rewrite !inE; case: (y =P x); rewrite ?(mul0r, eqxx).
by rewrite big_seq1 /= eqxx mul1r ger0_norm.
Qed.

Lemma ( : pred T) : \P_[mu] E = \E_[mu] (fun => (E m)%:R).
Proof.
by rewrite /pr psum_sum // => x; rewrite mulr_ge0 // ler0n. Qed.

Lemma
pr_predT
Source code
: \P_[mu] predT = PosSum.psum mu.
Proof.
by apply/eq_psum=> x; rewrite mul1r. Qed.

Lemma
pr_dunit
Source code
: \P_[dunit x] E = (E x)%:R :> R.
Proof.
rewrite /pr (psum_finseq (r := [:: x])) //.
  move=> y; rewrite !inE dunit1E [x==_]eq_sym.
  by case: (y =P x) => //; rewrite mulr0 eqxx.
by rewrite big_seq1 dunit1E eqxx mulr1 ger0_norm ?ler0n.
Qed.

Lemma
exp_dunit
Source code
( : T -> R) ( : T) : \E_[dunit x] f = f x.
Proof.
rewrite /esp (sum_seq1 x) => [y|]; rewrite dunit1E.
  by case: (x == y) => //; rewrite mulr0 eqxx.
by rewrite eqxx mulr1.
Qed.

Lemma : \E_[mu] (fun _ => r) = \P_[mu] predT * r.
Proof.
by rewrite pr_predT psum_sum // [RHS]mulrC -sumZ; apply/eq_sum.
Qed.

Lemma : \E_[mu] (fun _ => 0) = 0.
Proof.
by rewrite exp_cst mulr0. Qed.

Lemma
has_expC
Source code
: \E?_[mu] (fun _ => c).
Proof.
by apply/summableMl => //; exists `|c|. Qed.

Lemma
has_exp0
Source code
: \E?_[mu] (fun _ => 0).
Proof.
by apply/(has_expC mu 0). Qed.

Lemma
has_exp1
Source code
: \E?_[mu] (fun _ => 1).
Proof.
by apply/(has_expC mu 1). Qed.

Lemma
has_expZ
Source code
: \E?_[mu] F -> \E?_[mu] (c \*o F).
Proof.
move=> heF; have: summable (c \*o (F \* mu)) by apply/summableZ.
by apply/eq_summable => x /=; rewrite mulrA.
Qed.

Lemma : \E_[mu] (c \*o F) = c * \E_[mu] F.
Proof.
by rewrite -sumZ; apply/eq_sum=> x /=; rewrite mulrA. Qed.

Lemma : 0 <= \P_[mu] A.
Proof.
by apply/ge0_psum. Qed.

Lemma : 0 <= \P_[mu, B] A.
Proof.
by rewrite /prc mulr_ge0 ?invr_ge0 // ge0_pr. Qed.

Lemma
eq_in_pr
Source code
:
  {in dinsupp mu, A =i B} -> \P_[mu] A = \P_[mu] B.
Proof.
move=> eq_AB; apply/eq_psum => x; case/boolP: (x \in dinsupp mu).
  by move/eq_AB; rewrite -!topredE => /= ->.
by move/dinsuppPn=> ->; rewrite !mulr0.
Qed.

Lemma : A =i B -> \P_[mu] A = \P_[mu] B.
Proof.
by move=> eq_AB; apply/eq_in_pr=> x _; apply/eq_AB. Qed.

Lemma ( : T -> R):
   {in dinsupp mu, f1 =1 f2} -> \E_[mu] f1 = \E_[mu] f2.
Proof.
move=> eq_f; apply/eq_sum => x; case/boolP: (x \in dinsupp mu).
  by move/eq_f=> ->. by move/dinsuppPn=> ->; rewrite !mulr0.
Qed.

Lemma
pr_pred0_eq
Source code
( : {distr T / R}) ( : pred T) :
  E =1 pred0 -> \P_[mu] E = 0.
Proof.
by move=> eq; rewrite -(pr_pred0 mu); apply/eq_pr. Qed.
End PrCoreTheory.

Section PrTheory.
Context { : realType} { : choiceType} { : eqType}.

Implicit Types (mu : {distr T / R}) (A B E : pred T).

Lemma ( : {distr U / R}) :
  \P_[dlet f mu] E = \E_[mu] (fun => \P_[f x] E).
Proof.
rewrite /esp -psum_sum => [x|]; first by rewrite mulr_ge0 ?ge0_pr.
rewrite /pr; unlock dlet => /=; rewrite /mlet /=.
pose F := (E x)%:R * (mu y * f y x).
transitivity (PosSum.psum (fun => PosSum.psum (fun => F x y))); rewrite {}/F.
  by apply/eq_psum => x; rewrite -psumZ ?ler0n.
rewrite interchange_psum /=; last first.
  apply/eq_psum=> y /=; rewrite mulrC -psumZ //.
  by apply/eq_psum=> x /=; rewrite mulrCA.
+ have := summable_pr E (dlet f mu); apply/eq_summable.
  by move=> x; rewrite /= dletE psumZ ?ler0n.
+ by move=> t; exact/summable_condl/summable_mlet.
Qed.

Lemma
pr_dmargin
Source code
( : {distr U / R}) :
  \P_[dmargin f mu] E = \P_[mu] [pred | f x \in E].
Proof.
by rewrite /dmargin pr_dlet pr_exp; apply/eq_exp=> x _; rewrite pr_dunit.
Qed.

Lemma :
  (forall , x \in dinsupp mu -> x \notin A) -> \P_[mu] A = 0.
Proof.
move=> h; apply/psum_eq0=> x; apply/eqP.
rewrite mulf_eq0 orbC; case/boolP: (mu x == 0) => //=.
by move/h; rewrite -topredE /= => /negbTE->.
Qed.

Lemma :
    (forall , x \in dinsupp mu -> x \in B -> x \notin A)
  -> \P_[mu, B] A = 0.
Proof.
move=> h; rewrite /prc eq0_pr ?mul0r // => x /h {h} /orb_idl.
by rewrite negb_and /= => <-; rewrite orbAC orbN.
Qed.

Lemma
subset_pr
Source code
: {subset B <= A} -> \P_[mu] B <= \P_[mu] A.
Proof.
move=> le_BA; apply/le_psum; last first.
  apply/summableMl => //; exists 1=> // x.
  by rewrite ger0_norm ?(ler0n, lern1) ?leq_b1.
move=> x; rewrite mulr_ge0 ?ler0n ?ler_wpM2r //.
rewrite ler_nat; have := le_BA x; rewrite -!topredE /=.
by case: (B x) => // ->.
Qed.

Lemma : \P_[mu] A <= 1.
Proof.
apply/(@le_trans _ _ \P_[mu] predT).
  by apply/subset_pr. by rewrite pr_predT le1_mu.
Qed.

Lemma : \E?_[mu] f1 -> \E?_[mu] f2 ->
  f1 <=1 f2 -> \E_[mu] f1 <= \E_[mu] f2.
Proof.
move=> sm1 sm2 le_f; apply/le_sum => //.
by move=> x; rewrite ler_wpM2r.
Qed.

Lemma
le_in_pr
Source code
:
  (forall , x \in dinsupp mu -> x \in E1 -> x \in E2) ->
    \P_[mu] E1 <= \P_[mu] E2.
Proof.
move=> le; rewrite /pr; apply/le_psum; last by apply/summable_pr.
move=> x; rewrite mulr_ge0 ?ler0n //=; case/boolP: (x \in dinsupp mu).
  move/le; rewrite -!topredE /= => E12; rewrite ler_wpM2r //.
  by rewrite ler_nat; case: (E1 x) E12 => // ->.
by move/dinsuppPn=> ->; rewrite !mulr0.
Qed.

Lemma
le_mu_pr
Source code
:
    (forall , x \in dinsupp nu -> x \in A -> nu x <= mu x)
  -> \P_[nu] A <= \P_[mu] A.
Proof.
move=> h; apply/le_psum; last by apply/summable_pr.
move=> x; rewrite mulr_ge0 ?ler0n //=.
case/boolP: (x \in dinsupp nu) => [/h {}h|]; last first.
  by move/dinsuppPn=> ->; rewrite mulr0 mulr_ge0 ?ler0n.
by case/boolP: (A x) => [/h|]; rewrite ?(mul0r, mul1r).
Qed.

Lemma : \P_[mu, B] A <= 1.
Proof.
have := ge0_pr B mu; rewrite /prc le_eqVlt.
case/orP=> [/eqP<-|]; first by rewrite invr0 mulr0 ler01.
by move/ler_pdivrMr=> ->; rewrite mul1r le_in_pr // => x _ /andP[].
Qed.

Lemma : 0 < \P_[mu] A ->
  PosSum.psum (fun => \P_[mu, A] (pred1 x)) = 1.
Proof.
move=> gt0_pE; rewrite psumZr ?(invr_ge0, ge0_pr) //.
rewrite (eq_psum (F2 := (fun => (A x)%:R * mu x))); last first.
  by rewrite divff // gt_eqF.
move=> x /=; rewrite /pr (psum_finseq (r := [:: x])) ?big_seq1 //=.
  move=> y; rewrite !inE; case: (y == x) => //=.
  by rewrite mul0r eqxx.
by rewrite !inE eqxx -topredE ger0_norm ?mulr_ge0 ?ler0n.
Qed.

Lemma : \P_[mu] E = 0 -> forall , x \in E -> mu x = 0.
Proof.
move/eq0_psum=> /(_ (summable_pr _ _)) => h x xE; move/(_ x): h.
by move: xE; rewrite -topredE /= => ->; rewrite mul1r.
Qed.

Lemma :
  \P_[mu] A = \P_[mu] [predI A & B] + \P_[mu] [predI A & predC B].
Proof.
rewrite {1}/pr (psumID B); first by apply/summable_pr.
congr (_ + _); apply/eq_psum => x; rewrite !inE -!topredE /=;
  by rewrite mulrA -natrM mulnb andbC.
Qed.

Lemma
pr_or_indep
Source code
( : pred T) ( : {distr T / R}) :
  (forall , x \in A -> x \notin B) ->
    \P_[mu] [predU A & B] = \P_[mu] A + \P_[mu] B.
Proof.
move=> dsj; rewrite /pr -psumD; try solve [
  by apply/summable_pr | by move=> x; rewrite mulr_ge0 ?ler0n
].
apply/eq_psum=> x /=; rewrite -mulrDl -!topredE /= -natrD.
case/boolP: (A x) => Ax; case/boolP: (B x) => Bx //=.
by move/dsj: Ax; rewrite -topredE /= Bx.
Qed.

Lemma
pr_mem_map
Source code
( : seq U) : uniq r ->
    \P_[mu] [pred | f x \in r]
  = \sum_( <- r) \P_[mu] [pred | f x == y].
Proof.
elim: r => [_|y r ih]; first by rewrite big_nil pr_pred0_eq //.
case/andP=> yNr /ih {ih}h; rewrite big_cons -h -pr_or_indep.
  by move=> x; rewrite !inE => /eqP->. by apply/eq_pr.
Qed.

Lemma ( : seq T) : uniq r ->
  \P_[mu] [pred | x \in r] = \sum_( <- r) mu x.
Proof.
elim: r => [_|y r ih]; first by rewrite big_nil pr_pred0_eq //.
case/andP=> yNr /ih {ih}h; rewrite big_cons /= pr_pred1.
by rewrite -h -pr_or_indep // => x /eqP ->.
Qed.

Lemma
pr_bigor_indep
Source code
( : I -> pred T) ( : seq I) :
    uniq r
  -> (forall , p1 != p2 -> p1 \in r -> p2 \in r -> x \in P p1 -> x \notin P p2)
  -> \P_[mu] [pred | has [pred | x \in P p] r]
  = \sum_( <- r) \P_[mu] (P p).
Proof.
move=> uq_r dj; pose S := \big[orb/false]_( <- r) (x \in P p).
rewrite (eq_pr (B := S)) => [x|]; first by rewrite !inE -big_has.
rewrite {}/S; elim: r uq_r dj => [_|p r ih /andP[pNr /ih {ih}h]] dj.
  by rewrite big_nil pr_pred0_eq // => x; rewrite big_nil.
rewrite big_cons -h => [p1 p2 x ne_p p1r p2r|].
  by apply/dj=> //; rewrite in_cons (p1r, p2r) orbT.
rewrite -pr_or_indep => [x xNPp|].
  rewrite -topredE /= big_has; apply/hasPn => y y_in_r.
  apply/(dj p); rewrite ?in_cons ?(eqxx, y_in_r, orbT) //.
  by apply/contra: pNr=> /eqP->.
by apply/eq_pr=> x; rewrite -!topredE /= big_cons.
Qed.

Lemma : \P_[mu] [predU A & B] =
  \P_[mu] A + \P_[mu] B - \P_[mu] [predI A & B].
Proof.
apply/eqP; rewrite eq_sym subr_eq [in X in _==X]addrC; apply/eqP.
rewrite (prID _ B) -addrA -pr_or_indep => [x|].
  by rewrite !inE => /andP[].
congr (_ + _); apply/eq_pr => x; rewrite !inE -!topredE /=.
by apply/orb_id2r => /negbTE ->; rewrite andbT.
Qed.

Lemma : \P_[mu] [predI A & B] =
  \P_[mu] A + \P_[mu] B - \P_[mu] [predU A & B].
Proof.
by rewrite pr_or subKr. Qed.

Lemma
ler_pr_or
Source code
:
  \P_[mu] [predU A & B] <= \P_[mu] A + \P_[mu] B.
Proof.
by rewrite pr_or lerBlDr lerDl ge0_pr. Qed.

Lemma
ler_pr_and
Source code
:
  \P_[mu] [predI A & B] <= \P_[mu] A + \P_[mu] B.
Proof.
by rewrite pr_and lerBlDr lerDl ge0_pr. Qed.

Lemma
pr_predC
Source code
: \P_[mu](predC E) = \P_[mu] predT - \P_[mu] E.
Proof.
apply/esym/eqP; rewrite subr_eq -pr_or_indep //.
by apply/eqP/eq_pr=> x; rewrite !inE orNb.
Qed.

Lemma
pr_split
Source code
: \P_[mu] A =
    \P_[mu] B * \P_[mu, B] A
  + \P_[mu] (predC B) * \P_[mu, predC B] A.
Proof.
suff h A' B': \P_[mu] [predI A' & B'] = \P_[mu] B' * \P_[mu, B'] A'.
  by rewrite (prID _ B); congr (_ + _); apply/h.
rewrite /prc mulrCA; have [] := eqVneq (\P_[mu] B') 0; last first.
  by move=> nzPB'; rewrite divff // mulr1.
move=> zPB'; rewrite zPB' invr0 !mulr0; apply/eq0_pr.
move=> x mux; move/pr_eq0: zPB' => /(_ x) h; rewrite !inE.
by apply/negP=> /andP[_ /h] /dinsuppP.
Qed.

Lemma
__admitted__exp_split
Source code
: \E?_[mu] f -> \E_[mu] f =
    \P_[mu] A * \E_[mu, A] f
  + \P_[mu] (predC A) * \E_[mu, predC A] f.
Proof using Type.
Lemma
has_esp_bounded
Source code
:
  (exists , forall , `|f x| < M) -> \E?_[mu] f.
Proof.
(* TO BE REMOVED *)
case=> M ltM; rewrite /has_esp; apply/summable_seqP.
exists (Num.max M 0); first by rewrite le_max lexx orbT.
move=> J uqJ; apply/(@le_trans _ _ (\sum_( <- J) M * mu j)).
  apply/ler_sum=> j _; rewrite normrM [X in _*X]ger0_norm //.
  by apply/ler_wpM2r=> //; apply/ltW.
case: (ltrP M 0) => [lt0_M|ge0_M].
  rewrite ?(ltW lt0_M) // -mulr_sumr.
  by rewrite nmulr_rle0 //; apply/sumr_ge0.
by rewrite -mulr_sumr ler_piMr // -pr_mem ?le1_pr.
Qed.

Lemma
bounded_has_exp
Source code
:
  (exists , forall , `|F x| <= M) -> \E?_[mu] F.
Proof.
by move=> leM; apply/summableMl. Qed.

Lemma
summable_has_exp
Source code
: summable F -> \E?_[mu] F.
Proof.
move=> smF; apply/summableMr => //; exists 1.
by move=> x; rewrite ger0_norm // le1_mu1.
Qed.

Lemma
exp_le_bd
Source code
( : R) :
  0 <= M -> (forall , `|F x| <= M) -> \E_[mu] F <= M.
Proof.
move=> ge0M bd; apply/(@le_trans _ _ (\E_[mu] (fun _ => M))).
+ apply/le_exp.
  + by apply/bounded_has_exp; exists M.
  + by apply/has_expC.
  + by move=> x; apply/(le_trans _ (bd x))/ler_norm.
by rewrite exp_cst ler_piMl // le1_pr.
Qed.

Lemma
__admitted__exp_dlet
Source code
( : T -> {distr U / R}) :
  (forall , \E?_[eta] F) ->
    \E_[dlet nu mu] F = \E_[mu] (fun => \E_[nu x] F).
Proof using Type*. End PrTheory.

#[deprecated(since="1.17.0", note="use `pr_dlet` instead")]
Notation
__deprecated__pr_dlet
Source code
:= pr_dlet (only parsing).

#[deprecated(since="mathcomp-analysis 0.6.2",
  note="lacks proof, use __admitted__exp_split explicitly if you really want to use this lemma")]
Notation
exp_split
Source code
:= __admitted__exp_split.
#[deprecated(since="mathcomp-analysis 0.6.2",
  note="lacks proof, use __admitted__exp_dlet explicitly is you really want to use this lemma")]
Notation
exp_dlet
Source code
:= __admitted__exp_dlet.

Section Jensen.
Context { : realType} { : finType}.

Definition
convexon

convexon : forall {R : realType}, \bar R -> \bar R -> (R -> R) -> Prop convexon is not universe polymorphic Arguments convexon {R} (a b)%_ereal_scope f%_function_scope convexon is transparent Expands to: Constant mathcomp.experimental_reals.distr.convexon Declared in library mathcomp.experimental_reals.distr, line 1220, characters 11-19


Source code
( : \bar R) ( : R -> R) :=
  forall , (a <= x%:E <= b)%E -> (a <= y%:E <= b)%E ->
    forall , 0 <= t <= 1 ->
      f (t * x + (1 - t) * y) <= t * (f x) + (1 - t) * (f y).

Notation f := (convexon -oo +oo f).

Section Jensen.
Context ( : R -> R) ( : I -> R).

Hypothesis : convex f.
Hypothesis : forall , 0 <= l x.
Hypothesis : \sum_ (l i) = 1.

Lemma : f (\sum_ (l i * x i)) <= \sum_ (l i * f (x i)).
Proof.
case: (index_enum I) eq1_l => [|i s]; rewrite ?(big_nil, big_cons).
  by move/esym/eqP; rewrite oner_eq0.
elim: {i} s (l i) (ge0_l i) (x i) => [|j s ih] li ge0_li xi.
  by rewrite !big_nil !addr0 => ->; rewrite !mul1r.
rewrite !big_cons; have := ge0_l j; rewrite le_eqVlt.
case/orP => [/eqP<-|gt0_lj].
  by rewrite !Monoid.simpm /= !Monoid.simpm; apply/ih.
rewrite !addrA => eq1; pose z := (li * xi + l j * x j) / (li + l j).
have nz_lij: li + l j != 0 by rewrite gt_eqF ?ltr_wpDl.
have/ih := eq1 => -/(_ _ z); rewrite [_ * (_ / _)]mulrC.
rewrite mulfVK // => {}ih; apply/(le_trans (ih _)).
  by rewrite addr_ge0 ?ge0_l.
rewrite lerD2r {ih}/z [_ / _]mulrDl ![_*_/_]mulrAC.
set c1 : R := _ / _; set c2 : R := _ / _; have eqc2: c2 = 1 - c1.
  apply/(mulfI nz_lij); rewrite mulrBr mulr1 ![(li + l j)*_]mulrC.
  by apply/eqP; rewrite !mulfVK // eq_sym subr_eq addrC.
set c := (li + l j); pose z := (c * c1 * f xi + c * c2 * f (x j)).
apply/(@le_trans _ _ z); last by rewrite /z ![_*(_/_)]mulrC !mulfVK.
rewrite {}/z -![c * _ * _]mulrA -mulrDr ler_wpM2l ?addr_ge0 //.
rewrite eqc2 cvx_f // ?leNye ?leey // divr_ge0 ?addr_ge0 //=.
by rewrite ler_pdivrMr ?mul1r ?lerDl ?ltr_wpDl.
Qed.
End Jensen.
End Jensen.

Notation f := (convexon \-inf \+inf f).