End COMPRESS.
(* Find with path compression *)
Section FIND.
Variable uf: t.
Program Fixpoint find_x (a: elt) {wf (order uf.(m)) a} :
{ r: elt * t | fst r = repr uf a /\ forall x, repr (snd r) x = repr uf x } :=
match M.get a uf.(m) with
| Some a' =>
match find_x a' with
| pair b uf' => (b, compress uf' a b _ _)
end
| None => (a, uf)
end.
Next Obligation.
red. auto.
Qed.
Next Obligation.
(* a <> b*)
destruct (find_x a')
as [[b' uf''] [A B]]. simpl in *. inv Heq_anonymous.
apply repr_some_diff. auto.
Qed.
Next Obligation.
destruct (find_x a') as [[b' uf''] [A B]]. simpl in *. inv Heq_anonymous.
rewrite B. apply repr_some. auto.
Qed.
Next Obligation.
split.
destruct (find_x a')
as [[b' uf''] [A B]]. simpl in *. inv Heq_anonymous.
symmetry. apply repr_some. auto.
intros. rewrite repr_compress.
destruct (find_x a')
as [[b' uf''] [A B]]. simpl in *. inv Heq_anonymous. auto.
Qed.
Next Obligation.
split; auto. symmetry. apply repr_none. auto.
Qed.
Next Obligation.
apply mwf.
Defined.
Definition find (a: elt) : elt * t := proj1_sig (find_x a).

(* Specifications: *)
Lemma find_repr:
forall a, fst (find a) = repr uf a.
Lemma find_unchanged:
forall a x, repr (snd (find a)) x = repr uf x.
Lemma sameclass_find_1:
forall a x y, sameclass (snd (find a)) x y <-> sameclass uf x y.
Lemma sameclass_find_2:
forall a, sameclass uf a (fst (find a)).
Lemma sameclass_find_3:
forall a, sameclass (snd (find a)) a (fst (find a)).