Section TrueMult_impl_Repeat.
Variable A B : Set.
Hypothesis eqdb : EqDec B.
Variable A1 : Comp A.
Hypothesis A1_wf :
well_formed_comp A1.
Variable c : A -> Comp B.
Variable f P : B -> bool.
Hypothesis c_wf :
forall x, In x (getSupport A1) -> well_formed_comp (c x).
Hypothesis Repeat_c_terminating :
forall x, In x (getSupport A1) ->
exists x1 : B, In x1 (filter P (getSupport (c x))).
Definition TrueRepeat_G :=
a <-$ A1;
b <-$ Repeat (c a) P;
ret (f b).
Variable n : nat.
Variable failProb : Rat.
Hypothesis failProb_correct :
forall (a : A),
In a (getSupport A1) ->
Pr[x <-$ c a; ret negb (P x)] <= failProb.
Definition TrueRepeat_G1 :=
a <-$ A1;
bs <-$ compMap _ (fun _ => c a) (forNats n);
b_opt <- hd_error (filter P bs);
b' <-$ Repeat (c a) P;
b <- match b_opt with
| None => b'
| Some x => x
end;
ret (f b).
unfold TrueRepeat_G, TrueRepeat_G1.
inline_first.
comp_skip.
assert (Pr  [b <-$ Repeat (c x) P; ret f b ] ==
Pr  [b <-$ (y <-$ compMap _ (fun _ => (c x)) (forNats n);
match (hd_error (filter P y)) with
| None => Repeat (c x) P
| Some z => ret z
end); ret f b ]).
comp_skip.
eapply Repeat_unroll_n.
eauto.
eauto.
rewrite H0.
clear H0.
inline_first.
comp_skip.
case_eq (hd_error (filter P x0)); intuition.
comp_irr_r.
edestruct Repeat_c_terminating; eauto.
eapply well_formed_Repeat.
unfold eq_dec.
intuition.
eapply (EqDec_dec _).
eauto.
eauto.
reflexivity.
Qed.
Definition TrueRepeat_G2 :=
a <-$ A1;
bs <-$ compMap _ (fun _ => c a) (forNats n);
b_opt <- hd_error (filter P bs);
b' <-$ Repeat (c a) P;
b <- match b_opt with
| None => b'
| Some x => x
end;
ret (f b, if b_opt then false else true).
unfold TrueRepeat_G1, TrueRepeat_G2.
repeat (inline_first; comp_skip).
destruct (hd_error (filter P x0)).
comp_simp.
dist_compute.
rewrite e in n0.
simpl in *.
intuition.
eapply rat0_le_all.
comp_simp.
dist_compute.
rewrite e in n0.
simpl in *.
intuition.
eapply rat0_le_all.
Qed.
Definition TrueRepeat_G3 :=
a <-$ A1;
bs <-$ compMap _ (fun _ => c a) (forNats n);
b_opt <- hd_error (filter P bs);
b' <-$ Repeat (c a) P;
b <- match b_opt with
| None => b'
| Some x => x
end;
ret (fold_left (fun b x => b || (f x)) bs false, if b_opt then false else true).
unfold TrueRepeat_G2, TrueRepeat_G3.
repeat (inline_first; comp_skip).
comp_simp.
eapply comp_spec_impl_le.
eapply
comp_spec_ret.
simpl.
case_eq ( hd_error (filter P x0)); intuition.
rewrite orb_false_r in *.
eapply fold_left_orb_true_in.
eapply filter_In.
eapply hd_error_Some_In.
eauto.
trivial.
Qed.
Definition TrueRepeat_G3_bad :=
a <-$ A1;
compFold _ (fun b _ => x <-$ c a; ret b && negb (P x)) true (forNats n).
unfold TrueRepeat_G3, TrueMult_G.
inline_first.
comp_skip.
inline_first.
comp_skip.
inline_first.
comp_irr_l.
edestruct Repeat_c_terminating; eauto.
eapply well_formed_Repeat.
unfold eq_dec; intuition.
eapply (EqDec_dec _).
eauto.
eauto.
simpl.
intuition.
Qed.
unfold TrueRepeat_G3, TrueRepeat_G3_bad.
inline_first.
comp_skip.
assert(
Pr
[x0 <-$
(bs <-$ compMap eqdb (fun _ : nat => c x) (forNats n);
_ <-$ Repeat (c x) P;
ret (fold_left (fun (b : bool) (x0 : B) => b || f x0) bs false,
if hd_error (filter P bs) then false else true));
ret snd x0 ]
==
Pr
[x0 <-$
(_ <-$ Repeat (c x) P;
bs <-$ compMap eqdb (fun _ : nat => c x) (forNats n);
ret (fold_left (fun (b : bool) (x0 : B) => b || f x0) bs false,
if hd_error (filter P bs) then false else true));
ret snd x0 ]
).
comp_skip.
comp_swap_r.
comp_skip.
rewrite H0.
clear H0.
inline_first.
comp_irr_l.
edestruct Repeat_c_terminating.
eauto.
eapply well_formed_Repeat.
unfold eq_dec; intuition.
eapply (EqDec_dec _).
eauto.
eauto.
assert (
Pr
[x1 <-$
(bs <-$ compMap eqdb (fun _ : nat => c x) (forNats n);
ret (fold_left (fun (b : bool) (x1 : B) => b || f x1) bs false,
if hd_error (filter P bs) then false else true));
ret snd x1 ]
==
Pr
[bs <-$ compMap eqdb (fun _ : nat => c x) (forNats n);
ret (fold_left (fun b z => b && negb (P z)) bs true)]
).
inline_first.
comp_skip.
eapply comp_spec_eq_impl_eq.
simpl.
eapply comp_spec_ret.
eapply hd_filter_false_eq_and_false.
rewrite H1.
clear H1.
symmetry.
eapply comp_spec_eq_impl_eq.
eapply comp_spec_eq_trans.
eapply fold_map_fission_spec_eq.
intros.
eapply comp_spec_eq_refl.
comp_skip.
eapply compFold_ret_eq.
Qed.
unfold TrueRepeat_G3_bad.
comp_irr_l.
rewrite prob_fold_and_eq_exp.
eapply expRat_leRat_compat.
intuition.
Qed.
rewrite  evalDist_orb_le.
rewrite G3_TrueMult_equiv.
rewrite TrueRepeat_G1_bad_equiv .
rewrite TrueRepeat_G2_bad_small.
intuition.
Qed.

Theorem TrueMult_impl_Repeat :
Pr[TrueRepeat_G] <=
Pr[TrueMult_G _ c A1 f n] + (expRat failProb n).