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).

Theorem TrueRepeat_G2_G3_equiv :
Pr[x <-$ TrueRepeat_G2; ret (fst x || snd x)] <=
Pr[x <-$ TrueRepeat_G3; ret (fst x || snd x)].