Section OracleMapHybrid.
Variable A B C State S_A : Set.
Variable b : B.
Hypothesis eqdA : EqDec A.
Hypothesis eqdB : EqDec B.
Hypothesis eqdState : EqDec State.
Hypothesis eqdS_A : EqDec S_A.
Variable A1 : Comp (State * (list A * S_A)).
Variable A2 : S_A -> list B -> Comp bool.
Hypothesis A1_wf : well_formed_comp A1.
Hypothesis A2_wf :
forall s_A lsb, well_formed_comp (A2 s_A lsb).
Variable q : nat.
Variable k : Rat.
Hypothesis max_queries :
forall ls s s_A,
In (s, (ls, s_A)) (getSupport A1) ->
(length ls <= q)%nat.
Variable O1 O2 : State -> A -> Comp (B * State).
Hypothesis O1_wf :
forall s a,
well_formed_comp (O1 s a).
Hypothesis O2_wf :
forall s a,
well_formed_comp (O2 s a).
Definition OMH_G O :=
[s, p] <-$2 A1;
[lsa, s_A] <-2 p;
[lsb, _] <-$2 oracleMap _ _ O s lsa;
A2 s_A lsb.
Definition OMH_G_i i :=
[s, p] <-$2 A1;
[lsa, s_A] <-2 p;
[lsb1, s'] <-$2 oracleMap _ _ O1 s (firstn i lsa);
[lsb2, _] <-$2 oracleMap _ _ O2 s' (skipn i lsa);
A2 s_A (lsb1 ++ lsb2).
Hypothesis adjacent_close :
forall i,
| Pr[OMH_G_i i] - Pr[OMH_G_i (S i)] | <= k.
Definition OMH_G_oc (p : list A * S_A) :=
[lsa, s_A] <-2 p;
lsb <--$ oc_compMap _ (fun a => OC_Query _ a) lsa;
$ A2 s_A lsb.
intuition.
econstructor.
apply oc_compMap_wf.
intuition.
econstructor.
intuition.
econstructor.
auto.
Qed.
intuition.
unfold OMH_G, OMH_G_oc.
fcf_skip.
fcf_simp.
fcf_to_prhl_eq.
simpl.
fcf_inline_first.
fcf_skip.
apply compFold_oc_equiv.
subst.
fcf_inline_first.
fcf_ident_expand_l.
fcf_skip.
fcf_simp.
fcf_spec_ret.
Qed.
Definition OMH_G1 := OMH_G O1.
Definition OMH_G2 := OMH_G O2.
unfold OMH_G1.
rewrite OMH_G_oc_equiv.
unfold G1, OMH_G_oc.
reflexivity.
Qed.
unfold OMH_G2.
rewrite OMH_G_oc_equiv.
unfold G2, OMH_G_oc.
reflexivity.
Qed.
intuition.
unfold OMH_G_oc.
econstructor.
econstructor.
eapply oc_compMap_qam.
intuition.
econstructor.
intuition.
econstructor.
rewrite mult_1_r.
rewrite plus_0_r.
eapply max_queries.
eauto.
Qed.
Definition Gi_oracleMap i :=
[s, p] <-$2 A1;
[lsa, s_A] <-2 p;
p <-$ oracleMap _ _ (Oi _ _ O1 O2 i) (s, 0)%nat lsa;
A2 s_A (fst p).
Definition Gi_oracleMap' i :=
[s, p] <-$2 A1;
[lsa, s_A] <-2 p;
p <-$ (
[lsb1, s'] <-$2 oracleMap _ _ (Oi _ _ O1 O2 i) (s, 0)%nat (firstn i lsa);
[lsb2, s''] <-$2 oracleMap _ _ (Oi _ _ O1 O2 i) s'%nat (skipn i lsa);
ret (lsb1 ++ lsb2, s'')
);
A2 s_A (fst p).

Theorem Gi_oracleMap_equiv :
forall i,
Pr[Gi _ _ O1 O2 A1 OMH_G_oc i] == Pr[Gi_oracleMap i].