Module infotheo.information_theory.source_coding_vl_direct
Require realType_ext.From mathcomp Require Import all_ssreflect ssralg ssrnum ssrint matrix.
From mathcomp Require Import archimedean lra ring.
From mathcomp Require Import reals exp.
Require Import ssr_ext ssralg_ext bigop_ext realType_ext realType_ln.
Require Import fdist proba entropy aep typ_seq natbin source_code.
# Source coding theorem (variable length, direct part)
Formalization documented in:
- Ryosuke Obi, Manabu Hagiwara, and Reynald Affeldt. Formalization of
variable-length source coding theorem: Direct part. International
Symposium on Information Theory and Its Applications (ISITA 2014),
Melbourne, Australia, October 26--29, 2014, pages 201--205. IEICE. IEEE
Xplore, Oct 2014
Original source file by R. Obi, quickly patched to compile with InfoTheo
[2019-08-19] and simplified afterwards.
Set Implicit Arguments.
Set SsrOldRewriteGoalsOrder.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Local Open Scope reals_ext_scope.
Local Open Scope fdist_scope.
Local Open Scope entropy_scope.
Local Open Scope typ_seq_scope.
Local Open Scope ring_scope.
Import Order.POrderTheory GRing.Theory Num.Theory Order.TotalTheory.
Section Length.
Variable R : realType.
Variable (X : finType) (n' : nat).
Let n := n'.+1.
Variable P : R.-fdist X.
Variable epsilon : R.
Hypothesis eps_pos : 0 < epsilon.
Lemma fdist_support_LB : 1 <= #|X|%:R :> R.
Proof.
Lemma fdist_supp_lg_add_1_neq_0 : 1 + log (#|X|%:R) != 0 :> R.
Proof.
rewrite gt_eqF// ltr_pwDl//.
rewrite -log1 ler_log ?posrE// ?fdist_support_LB//.
by rewrite (lt_le_trans _ fdist_support_LB)//.
Qed.
rewrite -log1 ler_log ?posrE// ?fdist_support_LB//.
by rewrite (lt_le_trans _ fdist_support_LB)//.
Qed.
Definition
L_typ
:= Num.ceil (n%:R * (`H P + epsilon)).L_typ not a defined object.
Definition
L_not_typ
:= Num.ceil (log (#| [set : n.-tuple X]|%:R) : R).L_not_typ not a defined object.
Lemma Lt_pos : 0 < L_typ%:~R :> R.
Proof.
Lemma Lnt_nonneg : 0 <= L_not_typ%:~R :> R.
Proof.
apply: (@le_trans _ _ (log (#|[set: n.-tuple X]|%:R))); last first.
by rewrite ceil_ge.
rewrite -log1 ler_log ?posrE// cardsT card_tuple.
by rewrite natrX exprn_ege1// fdist_support_LB.
rewrite natrX exprn_gt0//.
by rewrite (lt_le_trans _ fdist_support_LB).
Qed.
by rewrite ceil_ge.
rewrite -log1 ler_log ?posrE// cardsT card_tuple.
by rewrite natrX exprn_ege1// fdist_support_LB.
rewrite natrX exprn_gt0//.
by rewrite (lt_le_trans _ fdist_support_LB).
Qed.
Lemma card_le_TS_Lt : #| `TS P n epsilon |%:R <= #|[ set : `|L_typ|%N.-tuple bool]|%:R :> R.
Proof.
Lemma card_le_Xn_Lnt' : #| [set: n.-tuple X]|%:R <= #| [set: `|L_not_typ|%N.-tuple bool]|%:R :> R.
Proof.
rewrite /L_not_typ cardsT card_tuple.
rewrite {1}(_ : (expn #|X| n)%:R = 2 `^ (log ((expn #|X| n)%:R))).
- rewrite cardsT card_tuple card_bool.
rewrite [in leRHS]natrX.
rewrite -powR_mulrn//.
rewrite ler_powR ?ler1n//.
rewrite (le_trans (ceil_ge _))//.
rewrite natr_absz ler_int.
by rewrite (le_trans (ler_norm _)).
- rewrite LogK// natrX exprn_gt0//.
by rewrite (lt_le_trans _ fdist_support_LB).
Qed.
rewrite {1}(_ : (expn #|X| n)%:R = 2 `^ (log ((expn #|X| n)%:R))).
- rewrite cardsT card_tuple card_bool.
rewrite [in leRHS]natrX.
rewrite -powR_mulrn//.
rewrite ler_powR ?ler1n//.
rewrite (le_trans (ceil_ge _))//.
rewrite natr_absz ler_int.
by rewrite (le_trans (ler_norm _)).
- rewrite LogK// natrX exprn_gt0//.
by rewrite (lt_le_trans _ fdist_support_LB).
Qed.
End Length.
Section Enc_Dec.
Variable R : realType.
Variable (X : finType) (n' : nat).
Let n := n'.+1.
Variable P : R.-fdist X.
Variable epsilon : R.
Hypothesis eps_pos : 0 < epsilon.
Local Notation "'L_typ'" := (L_typ n' P epsilon).
Local Notation "'L_not_typ'" := (L_not_typ R X n').
Definition
enc_typ
x :=enc_typ not a defined object.
let i := seq.index x (enum (`TS P n epsilon))
in Tuple (size_bitseq_of_nat i (`|L_typ|%N)).
Lemma card_le_Xn_Lnt :
(#| n.-tuple X : finType | <= #|`|L_not_typ|.-tuple bool : finType|)%N.
Definition
enc_not_typ
x := enum_val (widen_ord card_le_Xn_Lnt (enum_rank x)).enc_not_typ not a defined object.
Lemma inj_enc_not_typ : injective enc_not_typ.
Proof.
Definition
f
: encT X (seq bool) n := fun x =>f not a defined object.
if x \in `TS P n epsilon then
true :: enc_typ x
else
false :: enc_not_typ (tuple_of_row x).
Lemma f_inj : injective f.
Proof.
have card_TS_Lt : (#|`TS P n epsilon| <= 2 ^ `|L_typ|)%N.
rewrite -(ler_nat R).
by move: (card_le_TS_Lt n' P epsilon);
rewrite {1}cardsT card_tuple /= card_bool.
move=> t1 t2; rewrite /f.
case/boolP : (t1 == t2) ; first by move /eqP.
move=> mainCase.
case: ifP=>?; case: ifP=>? //; case=> H; last by apply/tuple_of_row_inj/inj_enc_not_typ/val_inj.
- have {}H : index t1 (enum (`TS P n epsilon)) = index t2 (enum (`TS P n epsilon))
by apply: (@bitseq_of_nat_inj (`|L_typ|%N)) => //; apply: (leq_trans _ card_TS_Lt);
apply: seq_index_enum_card => //; apply: enum_uniq.
rewrite -(@nth_index _ t1 t1 (enum (`TS P n epsilon))); last by rewrite mem_enum.
rewrite -(@nth_index _ t1 t2 (enum (`TS P n epsilon))); last by rewrite mem_enum.
by rewrite H.
Qed.
rewrite -(ler_nat R).
by move: (card_le_TS_Lt n' P epsilon);
rewrite {1}cardsT card_tuple /= card_bool.
move=> t1 t2; rewrite /f.
case/boolP : (t1 == t2) ; first by move /eqP.
move=> mainCase.
case: ifP=>?; case: ifP=>? //; case=> H; last by apply/tuple_of_row_inj/inj_enc_not_typ/val_inj.
- have {}H : index t1 (enum (`TS P n epsilon)) = index t2 (enum (`TS P n epsilon))
by apply: (@bitseq_of_nat_inj (`|L_typ|%N)) => //; apply: (leq_trans _ card_TS_Lt);
apply: seq_index_enum_card => //; apply: enum_uniq.
rewrite -(@nth_index _ t1 t1 (enum (`TS P n epsilon))); last by rewrite mem_enum.
rewrite -(@nth_index _ t1 t2 (enum (`TS P n epsilon))); last by rewrite mem_enum.
by rewrite H.
Qed.
Definition
phi_def
: n.-tuple X.phi_def not a defined object.
move Hpick : [pick x | x \in [set: X] ] => p;
move: Hpick; case: (pickP _)=>[x _ _ | abs]; first apply: [tuple of nseq n x].
exfalso.
move: (fdist_card_neq0 P).
rewrite -cardsT card_gt0; case/set0Pn => ?.
by rewrite abs.
Definition
phi
: decT X (seq bool) n := fun y =>phi not a defined object.
if [ pick x | f x == y ] is Some x then x else row_of_tuple phi_def.
Lemma phi_f x : phi (f x) = x.
Proof.
Lemma uniq_decodable_f : uniquely_decodable f.
Proof.
elim => [ | a la H ]; case => [|b lb]; rewrite /extension /= /f //=;
[by case : ifP |by case : ifP | ].
case: ifP => aT; case: ifP=> bT //; move /eqP; rewrite -/f eqseq_cat.
+ by case/andP=>[/eqP eq_ab ] /eqP /H ->; congr (_ :: _); apply: f_inj; rewrite /f aT bT.
+ by rewrite /= !/bitseq_of_nat !size_pad_seqL.
+ by case/andP=>[/eqP eq_ab ] /eqP /H ->; congr (_ :: _); apply: f_inj; rewrite /f aT bT.
+ by rewrite !size_tuple.
Qed.
[by case : ifP |by case : ifP | ].
case: ifP => aT; case: ifP=> bT //; move /eqP; rewrite -/f eqseq_cat.
+ by case/andP=>[/eqP eq_ab ] /eqP /H ->; congr (_ :: _); apply: f_inj; rewrite /f aT bT.
+ by rewrite /= !/bitseq_of_nat !size_pad_seqL.
+ by case/andP=>[/eqP eq_ab ] /eqP /H ->; congr (_ :: _); apply: f_inj; rewrite /f aT bT.
+ by rewrite !size_tuple.
Qed.
End Enc_Dec.
Section E_Leng_Cw_Lemma.
Variable R : realType.
Variables (X : finType).
Variable (n' : nat).
Let n := n'.+1.
Variable P : R.-fdist X.
Variable epsilon : R.
Hypothesis eps_pos : 0 < epsilon.
Hypothesis aepbound_UB : aep_bound P epsilon <= n%:R.
Local Notation "'L_typ'" := (L_typ n' P epsilon).
Local Notation "'L_not_typ'" := (L_not_typ R X n').
Lemma eq_sizef_Lt :
\sum_(x| x \in `TS P n epsilon) (P `^ n)%fdist (x) * (size (f P epsilon x))%:R =
\sum_(x| x \in `TS P n epsilon) (P `^ n)%fdist (x) * (L_typ%:~R + 1).
Proof.
Lemma eq_sizef_Lnt:
\sum_(x| x \in ~:(`TS P n epsilon)) (P `^ n)%fdist x * (size (f P epsilon x))%:R
= \sum_(x| x \in ~:(`TS P n epsilon)) (P `^ n)%fdist x * (L_not_typ%:~R + 1) .
Proof.
Lemma E_leng_cw_le_Length : E_leng_cw P (f (n':=n') P epsilon) <=
(L_typ%:~R + 1) + epsilon * (L_not_typ%:~R + 1) .
Proof.
rewrite /E_leng_cw /Ex /=.
rewrite (bigID_setC _ (`TS P n'.+1 epsilon)).
rewrite eq_sizef_Lnt eq_sizef_Lt.
rewrite -!big_distrl/= mulrC.
rewrite (_ : \sum_(i | i \in ~: `TS P n epsilon)
(P `^ n)%fdist i = 1 - \sum_(i | i \in `TS P n epsilon) (P `^ n)%fdist i); last first.
- rewrite -(FDist.f1 (P `^ n)%fdist) (bigID_setC _ (`TS P n epsilon)).
by rewrite addrAC subrr add0r.
- apply: lerD => //.
+ rewrite -[X in _ <= X]mulr1; apply: ler_wpM2l => //.
* by apply: addr_ge0 => //; exact/ltW/Lt_pos.
* by rewrite -(FDist.f1 (P `^ n)%fdist); apply: leR_sumRl => // *.
+ apply: ler_wpM2r => //.
* by apply: addr_ge0 => //; exact: (Lnt_nonneg _ P).
* by rewrite lerBlDr addrC -lerBlDr; exact: Pr_TS_1.
Qed.
rewrite (bigID_setC _ (`TS P n'.+1 epsilon)).
rewrite eq_sizef_Lnt eq_sizef_Lt.
rewrite -!big_distrl/= mulrC.
rewrite (_ : \sum_(i | i \in ~: `TS P n epsilon)
(P `^ n)%fdist i = 1 - \sum_(i | i \in `TS P n epsilon) (P `^ n)%fdist i); last first.
- rewrite -(FDist.f1 (P `^ n)%fdist) (bigID_setC _ (`TS P n epsilon)).
by rewrite addrAC subrr add0r.
- apply: lerD => //.
+ rewrite -[X in _ <= X]mulr1; apply: ler_wpM2l => //.
* by apply: addr_ge0 => //; exact/ltW/Lt_pos.
* by rewrite -(FDist.f1 (P `^ n)%fdist); apply: leR_sumRl => // *.
+ apply: ler_wpM2r => //.
* by apply: addr_ge0 => //; exact: (Lnt_nonneg _ P).
* by rewrite lerBlDr addrC -lerBlDr; exact: Pr_TS_1.
Qed.
End E_Leng_Cw_Lemma.
Section v_scode.
Variable R : realType.
Variable (X : finType) (n' : nat).
Let n := n'.+1.
Variable P : R.-fdist X.
Variable epsilon : R.
Hypothesis eps_pos : 0 < epsilon .
Definition
epsilon'
:= epsilon / (3 + (3 * log (#|X|)%:R)).epsilon' not a defined object.
Definition
n0
:= maxn (`|Num.ceil (2 / (1 + @log R (#|X|%:R)))|%N)n0 not a defined object.
(maxn (`|Num.ceil (8 / epsilon)|%N)
(`|Num.ceil (aep_sigma2 P/ epsilon' ^ 3)|%N)).
Hypothesis n0_Le_n : (n0 < n)%N.
Lemma n0_eps3 : 2 * (epsilon / (3 * (1 + log (#|X|%:R)))) / n%:R < epsilon / 3.
Proof.
move: (fdist_supp_lg_add_1_neq_0 P) => ?.
rewrite (mulrC 2) -!mulrA.
rewrite ltr_pM2l//.
rewrite invfM.
rewrite -mulrA.
rewrite gtr_pMr ?invr_gt0//.
rewrite !mulrA.
rewrite ltr_pdivrMr// mul1r.
rewrite mulrC .
move: n0_Le_n.
rewrite -(ltr_nat R).
apply: le_lt_trans.
rewrite /n0.
rewrite (le_trans (ceil_ge _))//.
rewrite (le_trans (ler_norm _))//.
rewrite -intr_norm.
rewrite -natr_absz ler_nat.
by rewrite leq_max leqnn.
Qed.
rewrite (mulrC 2) -!mulrA.
rewrite ltr_pM2l//.
rewrite invfM.
rewrite -mulrA.
rewrite gtr_pMr ?invr_gt0//.
rewrite !mulrA.
rewrite ltr_pdivrMr// mul1r.
rewrite mulrC .
move: n0_Le_n.
rewrite -(ltr_nat R).
apply: le_lt_trans.
rewrite /n0.
rewrite (le_trans (ceil_ge _))//.
rewrite (le_trans (ler_norm _))//.
rewrite -intr_norm.
rewrite -natr_absz ler_nat.
by rewrite leq_max leqnn.
Qed.
Lemma n0_eps4 : 2 / n%:R < epsilon / 4.
Proof.
move: n0_Le_n; rewrite /n0 !gtn_max; case/andP=> _; case/andP=> Hyp _.
rewrite ltr_pdivrMr//.
rewrite -ltr_pdivrMl ?divr_gt0//.
rewrite -(ltr_nat R) in Hyp.
rewrite (le_lt_trans _ Hyp)//.
rewrite invfM -mulrA invrK -natrM/= mulrC.
rewrite (le_trans (ceil_ge _))//.
rewrite (le_trans (ler_norm _))//.
rewrite -intr_norm.
by rewrite natr_absz.
Qed.
rewrite ltr_pdivrMr//.
rewrite -ltr_pdivrMl ?divr_gt0//.
rewrite -(ltr_nat R) in Hyp.
rewrite (le_lt_trans _ Hyp)//.
rewrite invfM -mulrA invrK -natrM/= mulrC.
rewrite (le_trans (ceil_ge _))//.
rewrite (le_trans (ler_norm _))//.
rewrite -intr_norm.
by rewrite natr_absz.
Qed.
Lemma eps'_pos : 0 < epsilon'.
Proof.
rewrite /epsilon'.
rewrite divr_gt0//.
rewrite ltr_wpDr// mulr_ge0// -log1 ler_log ?posrE//.
exact: fdist_support_LB.
by rewrite (lt_le_trans _ (fdist_support_LB P)).
Qed.
rewrite divr_gt0//.
rewrite ltr_wpDr// mulr_ge0// -log1 ler_log ?posrE//.
exact: fdist_support_LB.
by rewrite (lt_le_trans _ (fdist_support_LB P)).
Qed.
Lemma le_aepbound_n : aep_bound P epsilon' <= n%:R.
Proof.
Lemma lb_entro_plus_eps :
(L_typ n' P epsilon')%:~R + 1 + epsilon' * ((L_not_typ R X n')%:~R + 1) <
(`H P + epsilon) * n%:R.
Proof.
move : (fdist_supp_lg_add_1_neq_0 P) => ?.
rewrite /L_typ /L_not_typ.
apply: (@le_lt_trans _ _ (n'.+1%:R * (`H P + epsilon') + 1 + 1 +
epsilon' * (log (#|[set: (n'.+1).-tuple X]|%:R) + 1 + 1))).
- rewrite lerD//.
+ rewrite lerD//.
rewrite -lerBlDr ltW//.
rewrite [X in _ - X](_ : 1 = 1%:~R)//.
by rewrite -intrB ceilB1_lt.
+ rewrite ler_wpM2l//.
by rewrite ltW// eps'_pos.
rewrite lerD2r.
rewrite -lerBlDr ltW//.
rewrite [X in _ - X](_ : 1 = 1%:~R)//.
by rewrite -intrB ceilB1_lt.
- rewrite cardsT card_tuple log_pow_natmul; last by apply: fdist_card_neq0; exact: P.
rewrite -![_ + 1 + 1]addrA.
have ->: 1 + 1 = (1 + 1) * n%:R * n%:R^-1 :> R by rewrite mulfK// pnatr_eq0.
rewrite (mulrC 2 _).
rewrite -mulrA -!mulrDr.
rewrite (mulrC epsilon' _) -mulrA.
rewrite -mulrDr.
rewrite [ltRHS]mulrC.
rewrite ltr_pM2l//.
rewrite -addrA -addrA ltrD2l.
apply: (@le_lt_trans _ _ (epsilon / 4 + epsilon / 3 + epsilon / 3)); last first.
rewrite -!mulrDr gtr_pMr//.
lra.
rewrite addrCA -addrA.
rewrite lerD//.
by rewrite ltW// n0_eps4.
rewrite {2}/epsilon'.
rewrite mulrDl addrA lerD//; last first.
rewrite -mulrA.
rewrite (mulrC _^-1).
rewrite ltW//.
rewrite (le_lt_trans _ n0_eps3)//.
by rewrite mulrDr mulr1 -mulrA.
rewrite -/epsilon'.
rewrite /epsilon'.
rewrite (mulrCA _ epsilon).
rewrite -mulrDr ler_pM2l//.
rewrite -[X in X + _ <= _]mul1r.
rewrite -mulrDl.
rewrite -{1}(mulr1 3) -mulrDr mulrC.
rewrite invfM -mulrA.
by rewrite mulVf// mulr1.
Qed.
rewrite /L_typ /L_not_typ.
apply: (@le_lt_trans _ _ (n'.+1%:R * (`H P + epsilon') + 1 + 1 +
epsilon' * (log (#|[set: (n'.+1).-tuple X]|%:R) + 1 + 1))).
- rewrite lerD//.
+ rewrite lerD//.
rewrite -lerBlDr ltW//.
rewrite [X in _ - X](_ : 1 = 1%:~R)//.
by rewrite -intrB ceilB1_lt.
+ rewrite ler_wpM2l//.
by rewrite ltW// eps'_pos.
rewrite lerD2r.
rewrite -lerBlDr ltW//.
rewrite [X in _ - X](_ : 1 = 1%:~R)//.
by rewrite -intrB ceilB1_lt.
- rewrite cardsT card_tuple log_pow_natmul; last by apply: fdist_card_neq0; exact: P.
rewrite -![_ + 1 + 1]addrA.
have ->: 1 + 1 = (1 + 1) * n%:R * n%:R^-1 :> R by rewrite mulfK// pnatr_eq0.
rewrite (mulrC 2 _).
rewrite -mulrA -!mulrDr.
rewrite (mulrC epsilon' _) -mulrA.
rewrite -mulrDr.
rewrite [ltRHS]mulrC.
rewrite ltr_pM2l//.
rewrite -addrA -addrA ltrD2l.
apply: (@le_lt_trans _ _ (epsilon / 4 + epsilon / 3 + epsilon / 3)); last first.
rewrite -!mulrDr gtr_pMr//.
lra.
rewrite addrCA -addrA.
rewrite lerD//.
by rewrite ltW// n0_eps4.
rewrite {2}/epsilon'.
rewrite mulrDl addrA lerD//; last first.
rewrite -mulrA.
rewrite (mulrC _^-1).
rewrite ltW//.
rewrite (le_lt_trans _ n0_eps3)//.
by rewrite mulrDr mulr1 -mulrA.
rewrite -/epsilon'.
rewrite /epsilon'.
rewrite (mulrCA _ epsilon).
rewrite -mulrDr ler_pM2l//.
rewrite -[X in X + _ <= _]mul1r.
rewrite -mulrDl.
rewrite -{1}(mulr1 3) -mulrDr mulrC.
rewrite invfM -mulrA.
by rewrite mulVf// mulr1.
Qed.
Lemma v_scode' : exists2 sc : scode_vl _ n,
cancel (enc sc) (dec sc) & E_leng_cw P (enc sc) / n%:R < `H P + epsilon.
Proof.
move : (fdist_supp_lg_add_1_neq_0 P) => ?.
exists (mkScode (f P epsilon') (phi n' P epsilon')).
by move=> x/=; rewrite phi_f.
rewrite ltr_pdivrMr// (le_lt_trans (E_leng_cw_le_Length eps'_pos le_aepbound_n))//.
by rewrite lb_entro_plus_eps.
Qed.
exists (mkScode (f P epsilon') (phi n' P epsilon')).
by move=> x/=; rewrite phi_f.
rewrite ltr_pdivrMr// (le_lt_trans (E_leng_cw_le_Length eps'_pos le_aepbound_n))//.
by rewrite lb_entro_plus_eps.
Qed.
End v_scode.
Section variable_length_source_coding.
Context {R : realType} {X : finType}.
Variables (P : R.-fdist X) (epsilon : R).
Hypothesis eps_pos : 0 < epsilon.
Local Notation "'n0'" := (n0 P epsilon).
Theorem v_scode_direct : exists n, exists2 f : encT X (seq bool) n,
injective f & E_leng_cw P f / n%:R < `H P + epsilon.
Proof.
End variable_length_source_coding.