Section RandomPerm.
Variable D R : Set.
Hypothesis D_EqDec : EqDec D.
Hypothesis R_EqDec : EqDec R.
Variable RndR : Comp R.
Hypothesis RndR_wf : well_formed_comp RndR.
Fixpoint inRange(f : list (D * R))(r : R) :=
match f with
| nil => false
| (d', r') :: f' =>
if (eqb r r') then true
else (inRange f' r)
end.
Definition getUnusedR(f : list (D * R)) :=
Repeat (RndR) (fun r => negb (inRange f r)).
intuition.
destruct (in_dec (EqDec_dec _) x (getSupport (getUnusedR ls1))).
unfold getUnusedR in *.
simpl in i.
apply filter_In in i; intuition.
eapply evalDist_Repeat_eq.
intuition.
rewrite H.
trivial.
eapply filter_In; intuition.
eapply sumList_permutation.
eapply NoDup_Permutation.
eapply filter_NoDup.
eapply getSupport_NoDup.
eapply filter_NoDup.
eapply getSupport_NoDup.
intuition.
apply filter_In in H2; intuition.
eapply filter_In; intuition.
rewrite <- H.
trivial.
apply filter_In in H2; intuition.
eapply filter_In; intuition.
rewrite H.
trivial.
unfold getUnusedR in *.
simpl in n.
apply filter_not_In in n.
intuition.
simpl.
rewrite getSupport_not_In_evalDist_h; intuition.
repeat rewrite ratMult_0_r.
intuition.
simpl.
unfold indicator.
rewrite <- H.
rewrite H0.
repeat rewrite ratMult_0_l.
intuition.
Qed.
induction ls; intuition; simpl in *.
discriminate.
case_eq (eqb x b); intuition.
rewrite eqb_leibniz in H0.
subst.
intuition.
right.
eapply IHls.
rewrite H0 in H.
trivial.
Qed.
intuition.
unfold getUnusedR.
eapply (well_formed_Repeat _ _ r).
wftac.
eapply filter_In.
intuition.
rewrite H.
simpl.
trivial.
Grab Existential Variables.
unfold eq_dec; intuition.
eapply (EqDec_dec _).
Qed.
Hint Resolve getUnusedR_wf : wftac.
(* A random permutation *)
Definition randomPerm(p : (list (D * R) *  D)) : Comp (list (D * R) * R) :=
let (f, d) := p in
match (f#d) with
| None => (r <-$ getUnusedR f ; ret ((d, r) :: f, r))
| Some r => ret (f, r)
end.

Lemma randomPerm_wf : forall ls b0,
(forall x, ls#x = None -> exists r, inRange ls r = false /\ In r (getSupport RndR)) ->
well_formed_comp (randomPerm (ls, b0)).