Section ShuffleList.
Variable A : Set.
Hypothesis A_EqDec : EqDec A.
Definition shuffle(ls : list A) :=
o <-$ rndListElem _ (getAllPermutations ls);
ret
match o with
| None => nil
| Some x => x
end.
intuition.
unfold shuffle in *.
repeat simp_in_support.
destruct x.
eapply Permutation_sym.
eapply getAllPermutations_perms.
apply rndListElem_support in H0.
trivial.
apply rndListElem_support_None in H0.
exfalso.
eapply getAllPermutations_not_nil.
eauto.
Qed.
Fixpoint permute(ls : list A)(sigma : list nat) : list A :=
match sigma with
| nil => nil
| n :: sigma' =>
match (nth_error ls n) with
| None => nil
| Some a => a :: (permute ls sigma')
end
end.
induction ls; destruct n; intuition; simpl in *.
omega.
omega.
inversion H0.
eapply IHls; eauto.
omega.
Qed.
induction sigma; intuition; simpl in *.
case_eq (nth_error ls a); intuition.
simpl.
f_equal.
eapply IHsigma; intuition.
exfalso.
eapply nth_error_not_None.
eapply H.
intuition.
trivial.
Qed.
intuition.
unfold shuffle in *.
repeat simp_in_support.
destruct x.
eapply rndListElem_support in H0.
eapply getAllPermutations_perms.
trivial.
eapply rndListElem_support_None in H0.
exfalso.
eapply getAllPermutations_not_nil.
eauto.
Qed.
intuition.
unfold shuffle.
wftac.
eapply rndListElem_wf.
Qed.
End ShuffleList.
Definition RndPerm(n : nat) :=
shuffle _ (allNatsLt n).
intuition.
eapply list_pred_impl.
eapply list_pred_map_both.
eauto.
intuition.
destruct H0.
destruct H0.
intuition; subst.
trivial.
Qed.
induction 1; intuition; simpl in *.
econstructor.
econstructor.
trivial.
econstructor.
econstructor.
econstructor.
repeat econstructor;assumption.
eapply list_pred_map_both'.
eapply list_pred_impl.
eauto.
intuition.
econstructor; assumption.
Qed.
induction 1; intuition; simpl in *.
econstructor.
econstructor.
econstructor.
eapply list_pred_flatten_both.
eapply list_pred_map_both'.
eapply list_pred_impl.
eauto.
intuition.
eapply addInAllLocations_pred; intuition.
Qed.
induction ls; destruct n; intuition; simpl in *.
inversion H.
inversion H.
eapply IHls.
trivial.
Qed.
induction ls; intuition; simpl in *.
Qed.
induction ls using rev_ind; intuition; simpl in *.
econstructor.
rewrite app_length.
simpl.
rewrite plus_comm.
simpl.
eapply list_pred_app_both.
eapply list_pred_impl.
eapply IHls.
intuition.
eapply nth_error_app_Some; intuition.
econstructor.
eapply  nth_error_app_length .
econstructor.
Qed.
induction a; inversion 1; intuition; simpl in *.
subst.
rewrite H2.
f_equal.
eapply IHa.
trivial.
Qed.
intuition.
generalize (@getAllPermutations_pred _ _ (fun a b => nth_error ls b = Some a) ls (allNatsLt (length ls))) ; intros.
eapply list_pred_impl.
eapply H.
eapply allNats_nth_pred.
intuition.
eapply permute_nth_equiv.
trivial.
Qed.
induction 1; intuition; simpl in *.
discriminate.
destruct n.
inversion H1; clear H1; subst.
econstructor; intuition.
edestruct IHlist_pred; eauto.
Qed.
intuition.
unfold rndListElem in *.
case_eq (length lsa); intuition.
erewrite <- list_pred_length_eq; eauto.
rewrite H0.
eapply comp_spec_ret; intuition.
erewrite <- list_pred_length_eq; eauto.
rewrite H0.
comp_skip.
apply None.
apply None.
eapply comp_spec_ret; intuition.
case_eq (nth_option lsa b); intuition.
edestruct list_pred_nth_exists; eauto.
exfalso.
eapply nth_option_not_None; eauto.
apply RndNat_support_lt in H1.
omega.
Qed.

Theorem shuffle_RndPerm_spec :
forall (A : Set)(eqd : EqDec A)(ls : list A),
comp_spec (fun a b => a = permute ls b)
(shuffle eqd ls)
(shuffle _ (allNatsLt (length ls))).