unfold G2_1, G2_2.
comp_skip.
eapply comp_spec_eq_impl_eq.
comp_skip.
eapply (@oc_comp_spec_eq _ _ _ _ _ _ _ _ _ _ _ _ _ _ (fun a b => list_pred (fun c d =>  fst c = (snd (fst d)) /\ snd c = snd d) a b)).
econstructor.
intuition.
unfold randomFunc_mem, F_randomFunc.
erewrite arrayLookup_f_equiv ; eauto.
destruct (arrayLookup_f (Bvector_EqDec b) x2 (F x a) ); intuition.
eapply comp_spec_ret; intuition.
simpl.
econstructor.
simpl.
intuition.
trivial.
comp_skip.
apply (oneVector c).
apply (oneVector c).
eapply comp_spec_ret; intuition.
simpl.
econstructor.
intuition.
eauto.
comp_simp.
simpl in *; intuition.
subst.
eapply comp_spec_eq_refl.
Qed.
Fixpoint findCollision_1 (A B : Set)(eqda : EqDec A)(eqdb : EqDec B)(ls : list (A * B))(a : A)(b : B) :=
match ls with
| nil => None
| (a', b') :: ls' => if
(eqb b b' && (negb (eqb a a')))
then (Some a') else (findCollision_1 _ _ ls' a b)
end.
Definition collidesWith (A B : Set)(eqda : EqDec A)(eqdb : EqDec B)(ls : list (A * B))(a : A) b :=
if (findCollision_1 _ _ ls a b) then true else false.
Fixpoint findCollision(A B : Set)(eqda : EqDec A)(eqdb : EqDec B)(ls : list (A * B)) : option (A * A * B) :=
match ls with
| nil => None
| (a, b) :: ls' => let a' := (findCollision_1 _ _ ls' a b) in
match a' with
| None =>  (findCollision _ _ ls')
| Some p' => Some (a, p', b)
end
end.
Definition funcCollision (A B : Set)(eqda : EqDec A)(eqdb : EqDec B)(ls : list (A * B)) :=
if (findCollision _ _ ls) then true else false.
Definition G2_3 :=
k_in <-$ {0, 1}^k;
[b, f] <-$2 A _ _ (F_randomFunc k_in) nil;
ret (b, funcCollision _ _ (fst (split f))).

Theorem G2_2_3_equiv :
Pr[G2_2] == Pr[x <-$ G2_3; ret fst x].