Section RndListElem.
Variable A : Set.
Hypothesis eqd : EqDec A.
Local Open Scope list_scope.
Definition rndListElem(ls : list A) : Comp (option A) :=
match (length ls) with
| O => ret None
| S _ =>
i <-$ [0 .. (length ls));
ret (nth_option ls i)
end.
intuition.
unfold rndListElem.
case_eq (length ls); intuition; wftac.
Qed.
End RndListElem.
Local Open Scope list_scope.
induction ls; intuition; simpl in *.
discriminate.
destruct i.
inversion H; clear H; subst.
intuition.
right.
eapply IHls.
eauto.
Qed.
Fixpoint firstIndexOf(A : Set)(eqd : eq_dec A)(ls : list A)(a : A)(def : nat) :=
match ls with
| nil => def
| a' :: ls' =>
if (eqd a a') then O else (S (firstIndexOf eqd ls' a def))
end.
induction ls; intuition; simpl in *;
intuition.
subst.
destruct (eqd a0 a0); subst.
omega.
intuition.
destruct (eqd a0 a); subst.
omega.
eapply lt_n_S.
eauto.
Qed.
induction ls; intuition; simpl in *.
intuition.
intuition.
subst.
destruct (eqd a0 a0); subst; intuition.
destruct (eqd a0 a); subst; intuition.
Qed.
intuition.
unfold rndListElem.
case_eq (length ls); intuition.
exfalso.
destruct ls; simpl in *; intuition.
eapply getSupport_In_Seq.
eapply in_getSupport_RndNat.
rewrite <- H0.
eapply firstIndexOf_in_lt; eauto.
simpl.
left.
eapply nth_firstIndexOf; trivial.
unfold rndListElem in *.
repeat simp_in_support.
discriminate.
eapply nth_option_In; eauto.
Grab Existential Variables.
apply O.
unfold eq_dec.
eapply (EqDec_dec eqd).
Qed.
induction ls; intuition; simpl in *.
discriminate.
inversion H0; clear H0; subst.
destruct n.
inversion H; clear H; subst.
destruct (eqd a0 a0); subst; intuition.
destruct (eqd a0 a); subst; intuition.
exfalso.
eapply H3.
eapply nth_option_In.
eauto.
Qed.
induction ls; intuition; simpl in *.
omega.
destruct n.
econstructor; eauto.
destruct (IHls n).
omega.
econstructor; eauto.
Qed.
intuition.
unfold rndListElem in *.
case_eq (length ls); intuition.
destruct ls; simpl in *; trivial; discriminate.
rewrite H0 in H.
repeat simp_in_support.
apply RndNat_support_lt in H1.
edestruct (nth_option_some ls); eauto.
rewrite H0.
eauto.
congruence.
subst.
simpl.
intuition.
Qed.
intuition.
destruct a1.
destruct a2.
rewrite <- rndListElem_support in *.
unfold rndListElem.
case_eq (length ls); intuition.
destruct ls; simpl in *. intuition. omega.
eapply comp_spec_impl_eq.
eapply comp_spec_seq.
apply (Some a).
apply (Some a).
eapply eq_impl_comp_spec.
eapply well_formed_RndNat.
omega.
eapply well_formed_RndNat.
omega.
eapply RndNat_uniform.
3:{
intros.
simpl in H5.
eapply comp_spec_ret.
assert (a1 = (firstIndexOf (EqDec_dec _) ls a 0) <->
b = (firstIndexOf (EqDec_dec _) ls a0 0)).
eapply H5.
clear H5.
intuition; subst.
rewrite H5.
eapply nth_firstIndexOf; trivial.
symmetry.
eapply nth_firstIndexOf_if; intuition.
rewrite H7.
eapply nth_firstIndexOf; trivial.
symmetry.
eapply nth_firstIndexOf_if; intuition.
}
rewrite <- H2.
apply firstIndexOf_in_lt; trivial.
rewrite <- H2.
apply firstIndexOf_in_lt; trivial.
apply rndListElem_support in H0.
apply rndListElem_support_None in H1.
subst.
simpl in *.
intuition.
destruct a2.
apply rndListElem_support in H1.
apply rndListElem_support_None in H0.
subst.
simpl in *.
intuition.
intuition.
Qed.
induction ls; intuition; simpl in *.
discriminate.
destruct i.
inversion H0; clear H0; subst.
intuition.
eapply IHls; eauto.
Qed.
induction 1; intuition; simpl in *.
intuition; subst.
destruct (eqd a' a'); subst; intuition.
destruct i; intuition.
eapply not_in_nth_option; eauto.
destruct i; intuition.
inversion H3; clear H3; subst.
destruct (eqd a' a'); subst; intuition.
destruct (eqd a' x); subst; intuition.
eapply IHNoDup; eauto.
Qed.
induction ls; intuition; simpl in *.
omega.
destruct i.
discriminate.
assert (i < length ls).
omega.
eauto.
Qed.

Theorem rndListElem_uniform_gen :
forall (A B : Set)(eqda : EqDec A)(eqdb : EqDec B)(ls1 : list A)(ls2 : list B)(a1 :  A)(a2 : B),
NoDup ls1 ->
NoDup ls2 ->
length ls1 = length ls2 ->
In a1 ls1 ->
In a2 ls2 ->
comp_spec
(fun x y => x = Some a1 <-> y = Some a2)
(rndListElem _ ls1) (rndListElem _ ls2).