From c98440cad6b7a9c793aded892ec61a8ed50cac28 Mon Sep 17 00:00:00 2001 From: xleroy Date: Fri, 2 Mar 2007 15:43:35 +0000 Subject: Suppression de lib/Sets.v, utilisation de FSet a la place. Generalisation de Lattice pour utiliser une notion d'egalite possiblement differente de =. Adaptation de Kildall et de ses utilisateurs en consequence. git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@182 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e --- lib/union_find.v | 484 ------------------------------------------------------- 1 file changed, 484 deletions(-) delete mode 100644 lib/union_find.v (limited to 'lib/union_find.v') diff --git a/lib/union_find.v b/lib/union_find.v deleted file mode 100644 index 452459fa..00000000 --- a/lib/union_find.v +++ /dev/null @@ -1,484 +0,0 @@ -(** A purely functional union-find algorithm *) - -Require Import Wf. -Require Recdef. - -(** The ``union-find'' algorithm is used to represent equivalence classes - over a given type. It maintains a data structure representing a partition - of the type into equivalence classes. Three operations are provided: -- [empty], which returns the finest partition: each element of the type - is equivalent to itself only. -- [repr part x] returns a canonical representative for the equivalence - class of element [x] in partition [part]. Two elements [x] and [y] - are in the same equivalence class if and only if - [repr part x = repr part y]. -- [identify part x y] returns a new partition where the equivalence - classes of [x] and [y] are merged, and all equivalences valid in [part] - are still valid. - - The partitions are represented by partial mappings from elements - to elements. If [part] maps [x] to [y], this means that [x] and [y] - are in the same equivalence class. The canonical representative - of the class of [x] is obtained by iteratively following these mappings - until an element not mapped to anything is reached; this element is the - canonical representative, as returned by [repr]. - - In algorithm textbooks, the mapping is maintained imperatively by - storing pointers within elements. Here, we give a purely functional - presentation where the mapping is a separate functional data structure. -*) - -(** The elements of equivalence classes are represented by the following - signature: a type with a decidable equality. *) - -Module Type ELEMENT. - Variable T: Set. - Variable eq: forall (a b: T), {a = b} + {a <> b}. -End ELEMENT. - -(** The mapping structure over elements is represented by the following - signature. *) - -Module Type MAP. - Variable elt: Set. - Variable T: Set. - Variable empty: T. - Variable get: elt -> T -> option elt. - Variable add: elt -> elt -> T -> T. - - Hypothesis get_empty: forall (x: elt), get x empty = None. - Hypothesis get_add_1: - forall (x y: elt) (m: T), get x (add x y m) = Some y. - Hypothesis get_add_2: - forall (x y z: elt) (m: T), z <> x -> get z (add x y m) = get z m. -End MAP. - -(** Our implementation of union-find is a functor, parameterized by - a structure for elements and a structure for maps. It returns a - module with the following structure. *) - -Module Type UNIONFIND. - Variable elt: Set. - (** The type of partitions. *) - Variable T: Set. - - (** The operations over partitions. *) - Variable empty: T. - Variable repr: T -> elt -> elt. - Variable identify: T -> elt -> elt -> T. - - (** The relation implied by the partition [m]. *) - Definition sameclass (m: T) (x y: elt) : Prop := repr m x = repr m y. - - (* [sameclass] is an equivalence relation *) - Hypothesis sameclass_refl: - forall (m: T) (x: elt), sameclass m x x. - Hypothesis sameclass_sym: - forall (m: T) (x y: elt), sameclass m x y -> sameclass m y x. - Hypothesis sameclass_trans: - forall (m: T) (x y z: elt), - sameclass m x y -> sameclass m y z -> sameclass m x z. - - (* [repr m x] is a canonical representative of the equivalence class - of [x] in partition [m]. *) - Hypothesis repr_repr: - forall (m: T) (x: elt), repr m (repr m x) = repr m x. - Hypothesis sameclass_repr: - forall (m: T) (x: elt), sameclass m x (repr m x). - - (* [empty] is the finest partition *) - Hypothesis repr_empty: - forall (x: elt), repr empty x = x. - Hypothesis sameclass_empty: - forall (x y: elt), sameclass empty x y -> x = y. - - (* [identify] preserves existing equivalences and adds an equivalence - between the two elements provided. *) - Hypothesis sameclass_identify_1: - forall (m: T) (x y: elt), sameclass (identify m x y) x y. - Hypothesis sameclass_identify_2: - forall (m: T) (x y u v: elt), - sameclass m u v -> sameclass (identify m x y) u v. - -End UNIONFIND. - -(** Implementation of the union-find algorithm. *) - -Module Unionfind (E: ELEMENT) (M: MAP with Definition elt := E.T) - <: UNIONFIND with Definition elt := E.T. - -Definition elt := E.T. - -(* A set of equivalence classes over [elt] is represented by a map [m]. -- [M.get a m = Some a'] means that [a] is in the same class as [a']. -- [M.get a m = None] means that [a] is the canonical representative - for its equivalence class. -*) - -(** Such a map induces an ordering over type [elt]: - [repr_order m a a'] if and only if [M.get a' m = Some a]. - This ordering must be well founded (no cycles). *) - -Definition repr_order (m: M.T) (a a': elt) : Prop := - M.get a' m = Some a. - -(** The canonical representative of an element. - Needs Noetherian recursion. *) - -Section REPR. - -Variable m: M.T. -Variable wf: well_founded (repr_order m). - -Function repr_aux (a: elt) {wf (repr_order m) a} : elt := - match M.get a m with - | Some a' => repr_aux a' - | None => a - end. -Proof. - intros. assumption. - assumption. -Qed. - -Lemma repr_aux_none: - forall (a: elt), - M.get a m = None -> - repr_aux a = a. -Proof. - intros. rewrite repr_aux_equation. rewrite H. auto. -Qed. - -Lemma repr_aux_some: - forall (a a': elt), - M.get a m = Some a' -> - repr_aux a = repr_aux a'. -Proof. - intros. rewrite repr_aux_equation. rewrite H. auto. -Qed. - -Lemma repr_aux_canon: - forall (a: elt), M.get (repr_aux a) m = None. -Proof. - intros a0. - apply (repr_aux_ind (fun a a' => M.get a' m = None)). - auto. auto. -Qed. - -End REPR. - -(** The empty partition (each element in its own class) is well founded. *) - -Lemma wf_empty: - well_founded (repr_order M.empty). -Proof. - red. intro. apply Acc_intro. - intros b RO. - red in RO. - rewrite M.get_empty in RO. - discriminate. -Qed. - -(** Merging two equivalence classes. *) - -Section IDENTIFY. - -Variable m: M.T. -Hypothesis mwf: well_founded (repr_order m). -Variable a b: elt. -Hypothesis a_diff_b: a <> b. -Hypothesis a_canon: M.get a m = None. -Hypothesis b_canon: M.get b m = None. - -(** Identifying two distinct canonical representatives [a] and [b] - is achieved by mapping one to the other. *) - -Definition identify_base: M.T := M.add a b m. - -Lemma identify_base_b_canon: - M.get b identify_base = None. -Proof. - unfold identify_base. - rewrite M.get_add_2. - auto. - apply sym_not_eq. auto. -Qed. - -Lemma identify_base_a_maps_to_b: - M.get a identify_base = Some b. -Proof. - unfold identify_base. rewrite M.get_add_1. auto. -Qed. - -Lemma identify_base_repr_order: - forall (x y: elt), - repr_order identify_base x y -> - repr_order m x y \/ (y = a /\ x = b). -Proof. - intros x y. unfold identify_base. - unfold repr_order. - case (E.eq a y); intro. - rewrite e. rewrite M.get_add_1. - intro. injection H. intro. rewrite H0. tauto. - rewrite M.get_add_2; auto. -Qed. - -(** [identify_base] preserves well foundation. *) - -Lemma identify_base_order_wf: - well_founded (repr_order identify_base). -Proof. - red. - cut (forall (x: elt), Acc (repr_order m) x -> Acc (repr_order identify_base) x). - intro CUT. intro x. apply CUT. apply mwf. - - induction 1. - apply Acc_intro. intros. - destruct (identify_base_repr_order y x H1) as [A | [A B]]. - apply H0; auto. - subst x y. apply Acc_intro. intros z H4. - red in H4. rewrite identify_base_b_canon in H4. discriminate. -Qed. - -Lemma identify_aux_decomp: - forall (x: elt), - (M.get x m = None /\ M.get x identify_base = None) - \/ (x = a /\ M.get x m = None /\ M.get x identify_base = Some b) - \/ (exists y, M.get x m = Some y /\ M.get x identify_base = Some y). -Proof. - intro x. - unfold identify_base. - case (E.eq a x); intro. - rewrite <- e. rewrite M.get_add_1. - tauto. - rewrite M.get_add_2; auto. - case (M.get x m); intros. - right; right; exists e; tauto. - tauto. -Qed. - -Lemma identify_base_repr: - forall (x: elt), - repr_aux identify_base identify_base_order_wf x = - (if E.eq (repr_aux m mwf x) a then b else repr_aux m mwf x). -Proof. - apply (well_founded_ind mwf - (fun (x: elt) => - repr_aux identify_base identify_base_order_wf x = - (if E.eq (repr_aux m mwf x) a then b else repr_aux m mwf x))); - intros. - destruct (identify_aux_decomp x) as [[A B] | [[A [B C]] | [y [A B]]]]. - - rewrite (repr_aux_none identify_base); auto. - rewrite (repr_aux_none m mwf x); auto. - case (E.eq x a); intro. - subst x. - rewrite identify_base_a_maps_to_b in B. discriminate. - auto. - - subst x. rewrite (repr_aux_none m mwf a); auto. - case (E.eq a a); intro. - rewrite (repr_aux_some identify_base identify_base_order_wf a b); auto. - rewrite (repr_aux_none identify_base identify_base_order_wf b); auto. - apply identify_base_b_canon. - tauto. - - rewrite (repr_aux_some identify_base identify_base_order_wf x y); auto. - rewrite (repr_aux_some m mwf x y); auto. -Qed. - -Lemma identify_base_sameclass_1: - forall (x y: elt), - repr_aux m mwf x = repr_aux m mwf y -> - repr_aux identify_base identify_base_order_wf x = - repr_aux identify_base identify_base_order_wf y. -Proof. - intros. - rewrite identify_base_repr. - rewrite identify_base_repr. - rewrite H. - auto. -Qed. - -Lemma identify_base_sameclass_2: - forall (x y: elt), - repr_aux m mwf x = a -> - repr_aux m mwf y = b -> - repr_aux identify_base identify_base_order_wf x = - repr_aux identify_base identify_base_order_wf y. -Proof. - intros. - rewrite identify_base_repr. - rewrite identify_base_repr. - rewrite H. - case (E.eq a a); intro. - case (E.eq (repr_aux m mwf y) a); auto. - tauto. -Qed. - -End IDENTIFY. - -(** The union-find data structure is a record encapsulating a mapping - and a proof of well foundation. *) - -Record unionfind : Set := mkunionfind - { map: M.T; wf: well_founded (repr_order map) }. - -Definition T := unionfind. - -Definition repr (uf: unionfind) (a: elt) : elt := - repr_aux (map uf) (wf uf) a. - -Lemma repr_repr: - forall (uf: unionfind) (a: elt), repr uf (repr uf a) = repr uf a. -Proof. - intros. - unfold repr. - rewrite (repr_aux_none (map uf) (wf uf) (repr_aux (map uf) (wf uf) a)). - auto. - apply repr_aux_canon. -Qed. - -Definition empty := mkunionfind M.empty wf_empty. - -(** [identify] computes canonical representatives for the two elements - and adds a mapping from one to the other, unless they are already - equal. *) - -Definition identify (uf: unionfind) (a b: elt) : unionfind := - match E.eq (repr uf a) (repr uf b) with - | left EQ => - uf - | right NOTEQ => - mkunionfind - (identify_base (map uf) (repr uf a) (repr uf b)) - (identify_base_order_wf (map uf) (wf uf) - (repr uf a) (repr uf b) - NOTEQ - (repr_aux_canon (map uf) (wf uf) b)) - end. - -Definition sameclass (uf: unionfind) (a b: elt) : Prop := - repr uf a = repr uf b. - -Lemma sameclass_refl: - forall (uf: unionfind) (a: elt), sameclass uf a a. -Proof. - intros. red. auto. -Qed. - -Lemma sameclass_sym: - forall (uf: unionfind) (a b: elt), sameclass uf a b -> sameclass uf b a. -Proof. - intros. red. symmetry. exact H. -Qed. - -Lemma sameclass_trans: - forall (uf: unionfind) (a b c: elt), - sameclass uf a b -> sameclass uf b c -> sameclass uf a c. -Proof. - intros. red. transitivity (repr uf b). exact H. exact H0. -Qed. - -Lemma sameclass_repr: - forall (uf: unionfind) (a: elt), sameclass uf a (repr uf a). -Proof. - intros. red. symmetry. rewrite repr_repr. auto. -Qed. - -Lemma repr_empty: - forall (a: elt), repr empty a = a. -Proof. - intro a. unfold repr; unfold empty. - simpl. - apply repr_aux_none. - apply M.get_empty. -Qed. - -Lemma sameclass_empty: - forall (a b: elt), sameclass empty a b -> a = b. -Proof. - intros. red in H. rewrite repr_empty in H. - rewrite repr_empty in H. auto. -Qed. - -Lemma sameclass_identify_2: - forall (uf: unionfind) (a b x y: elt), - sameclass uf x y -> sameclass (identify uf a b) x y. -Proof. - intros. - unfold identify. - case (E.eq (repr uf a) (repr uf b)). - intro. auto. - intros; red; unfold repr; simpl. - apply identify_base_sameclass_1. - apply repr_aux_canon. - exact H. -Qed. - -Lemma sameclass_identify_1: - forall (uf: unionfind) (a b: elt), - sameclass (identify uf a b) a b. -Proof. - intros. - unfold identify. - case (E.eq (repr uf a) (repr uf b)). - intro. auto. - intros. - red; unfold repr; simpl. - apply identify_base_sameclass_2. - apply repr_aux_canon. - auto. - auto. -Qed. - -End Unionfind. - -(* Example of use 1: with association lists *) - -(* - -Require Import List. - -Module AListMap(E: ELEMENT) : MAP. - -Definition elt := E.T. -Definition T := list (elt * elt). -Definition empty : T := nil. -Fixpoint get (x: elt) (m: T) {struct m} : option elt := - match m with - | nil => None - | (a,b) :: t => - match E.eq x a with - | left _ => Some b - | right _ => get x t - end - end. -Definition add (x y: elt) (m: T) := (x,y) :: m. - -Lemma get_empty: forall (x: elt), get x empty = None. -Proof. - intro. unfold empty. simpl. auto. -Qed. - -Lemma get_add_1: - forall (x y: elt) (m: T), get x (add x y m) = Some y. -Proof. - intros. unfold add. simpl. - case (E.eq x x); intro. - auto. - tauto. -Qed. - -Lemma get_add_2: - forall (x y z: elt) (m: T), z <> x -> get z (add x y m) = get z m. -Proof. - intros. unfold add. simpl. - case (E.eq z x); intro. - subst z; tauto. - auto. -Qed. - -End AListMap. - -*) - -- cgit