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).
intuition.
unfold Gi, OMH_G_oc, Gi_oracleMap.
fcf_skip.
fcf_simp.
fcf_to_prhl_eq.
simpl.
fcf_inline_first.
eapply comp_spec_eq_symm.
fcf_skip.
eapply compFold_oc_equiv.
subst.
simpl.
fcf_ident_expand_l.
fcf_inline_first.
fcf_skip.
fcf_simp.
fcf_spec_ret.
Qed.
intuition.
unfold Gi_oracleMap, Gi_oracleMap'.
fcf_skip.
fcf_simp.
fcf_skip.
cutrewrite (l = (firstn i l ++ skipn i l)).
eapply eqRat_trans.
eapply compFold_app.
fcf_skip.
rewrite firstn_skipn.
reflexivity.
fcf_simp.
fcf_ident_expand_l.
fcf_to_prhl_eq.
rewrite firstn_skipn.
fcf_skip.
eapply (compFold_spec' (fun a b c d => a = b /\ snd c = snd d /\ l0++ (fst d) = (fst c)));
intuition.
simpl.
eapply app_nil_r.
simpl in *.
subst.
destruct d.
simpl in *.
subst.
unfold Oi.
inversion H2; clear H2; subst.
fcf_inline_first.
fcf_skip.
fcf_simp.
fcf_spec_ret.
simpl.
rewrite app_assoc.
trivial.
fcf_simp.
simpl in H3.
intuition.
subst.
fcf_spec_ret.
rewrite firstn_skipn.
trivial.
Qed.
intuition.
unfold Gi_oracleMap', OMH_G_i.
fcf_skip.
fcf_simp.
fcf_inline_first.
fcf_to_prhl_eq.
fcf_skip.
eapply (compFold_spec' (fun a b c d => a = b /\ fst c = fst d /\ fst (snd c) = snd d /\ (snd (snd c) + length a = min i (length l))%nat)); intuition.
simpl.
apply firstn_length.
fcf_simp.
simpl in *.
subst.
inversion H1; clear H1; subst.
fcf_inline_first.
destruct (ge_dec b2 i).
exfalso.
destruct (le_dec i (length l)).
rewrite min_l in H4.
omega.
trivial.
rewrite min_r in H4.
omega.
omega.
comp_skip.
fcf_spec_ret.
simpl.
omega.
simpl in H2.
intuition.
subst.
fcf_inline_first.
fcf_simp.
rewrite plus_0_r in H6.
destruct (ge_dec i (length l)).
rewrite skipn_ge_nil; trivial.
unfold oracleMap.
simpl.
fcf_simp.
simpl.
eapply comp_spec_eq_refl.
fcf_skip.
eapply (compFold_spec' (fun a b c d => a = b /\ fst c = fst d /\ fst (snd c) = snd d /\ (snd (snd c) >= i)%nat)); intuition.
simpl.
rewrite min_l; omega.
simpl in *.
subst.
destruct (ge_dec b2 i); try omega.
inversion H4; clear H4; subst.
fcf_inline_first.
fcf_simp.
fcf_skip.
simpl.
fcf_spec_ret.
simpl.
omega.
simpl in H5.
intuition; subst.
fcf_simp.
simpl.
eapply comp_spec_eq_refl.
Qed.

Theorem OMH_G1_G2_close :
| Pr[OMH_G1] - Pr[OMH_G2] | <= (q / 1) * k.