induction n; destruct i; intuition; try omega.
unfold computeHybrid.
unfold minus.
unfold forNats.
fold forNats.
unfold compMap.
fold compMap.
comp_simp.
inline_first.
comp_skip.
inline_first.
comp_irr_l.
inline_first.
comp_skip.
comp_simp.
simpl.
intuition.
unfold computeHybrid.
unfold minus.
fold minus.
unfold forNats.
fold forNats.
unfold compMap.
fold compMap.
inline_first.
do 2 comp_at comp_inline leftc 1%nat.
comp_swap_l.
comp_skip.
assert (evalDist
(a1 <-$
(lsb' <-$ compMap B_EqDec (fun _ : nat => (c1 a)) (forNats i);
ret x0 :: lsb');
a2 <-$ compMap B_EqDec (fun _ : nat => (c2 a)) (forNats (n0 - i));
ret a1 ++ a2) x ==
evalDist
(ls <-$
(a1 <-$ compMap B_EqDec (fun _ : nat => (c1 a)) (forNats i);
a2 <-$ compMap B_EqDec (fun _ : nat => (c2 a)) (forNats (n0 - i));
ret a1 ++ a2);
ret (x0 :: ls)) x).
inline_first.
comp_skip.
inline_first.
comp_skip.
comp_simp.
rewrite app_comm_cons.
intuition.
rewrite H1.
clear H1.
eapply eqRat_trans.
2:{
comp_skip.
eapply IHn0.
omega.
omega.
eapply eqRat_refl.
}
unfold computeHybrid.
inline_first.
comp_skip.
inline_first.
comp_skip.
inline_first.
comp_skip.
comp_simp.
simpl.
intuition.
Qed.
Definition B1 : Comp (A * (A * A_State)) :=
[a, s_A] <-$2 A1;
ret (a, (a, s_A)).
Definition B2(s : A * A_State)(b : B) : Comp bool :=
[a, s_A] <-2 s;
i <-$ [0 .. n);
rndHybrid <-$ computeHybrid n i a;
distHybrid <- listReplace rndHybrid i b b;
A2 s_A distHybrid.
Definition DistSingle_G1(c : A -> Comp B) :=
[a, s_A] <-$2 B1;
b <-$ (c a);
B2 s_A b.

Theorem DistSingle_G1_equiv :
DistSingle_Adv c1 c2 B1 B2 ==
(| Pr[DistSingle_G1 c1] - Pr[DistSingle_G1 c2] |).