Library FSets.FSetAVL0
FSetAVL : Implementation of FSetInterface via AVL trees
Notations and helper lemma about pairs
Notation "s #1" := (fst s) (at level 9, format "s '#1'") : pair_scope.
Notation "s #2" := (snd s) (at level 9, format "s '#2'") : pair_scope.
Module Raw (Import I:Int)(X:OrderedType).
Open Local Scope pair_scope.
Open Local Scope lazy_bool_scope.
Open Local Scope Int_scope.
Local Notation int := I.t.
Definition elt := X.t.
Definition height (s : tree) : int :=
match s with
| Leaf ⇒ 0
| Node _ _ _ h ⇒ h
end.
Fixpoint cardinal (s : tree) : nat :=
match s with
| Leaf ⇒ 0%nat
| Node l _ r _ ⇒ S (cardinal l + cardinal r)
end.
Appartness
Fixpoint mem x s :=
match s with
| Leaf ⇒ false
| Node l y r _ ⇒ match X.compare x y with
| LT _ ⇒ mem x l
| EQ _ ⇒ true
| GT _ ⇒ mem x r
end
end.
Helper functions
bal l x r acts as create, but performs one step of
rebalancing if necessary, i.e. assumes |height l - height r| ≤ 3.
Definition assert_false := create.
Definition bal l x r :=
let hl := height l in
let hr := height r in
if gt_le_dec hl (hr+2) then
match l with
| Leaf ⇒ assert_false l x r
| Node ll lx lr _ ⇒
if ge_lt_dec (height ll) (height lr) then
create ll lx (create lr x r)
else
match lr with
| Leaf ⇒ assert_false l x r
| Node lrl lrx lrr _ ⇒
create (create ll lx lrl) lrx (create lrr x r)
end
end
else
if gt_le_dec hr (hl+2) then
match r with
| Leaf ⇒ assert_false l x r
| Node rl rx rr _ ⇒
if ge_lt_dec (height rr) (height rl) then
create (create l x rl) rx rr
else
match rl with
| Leaf ⇒ assert_false l x r
| Node rll rlx rlr _ ⇒
create (create l x rll) rlx (create rlr rx rr)
end
end
else
create l x r.
Fixpoint add x s := match s with
| Leaf ⇒ Node Leaf x Leaf 1
| Node l y r h ⇒
match X.compare x y with
| LT _ ⇒ bal (add x l) y r
| EQ _ ⇒ Node l y r h
| GT _ ⇒ bal l y (add x r)
end
end.
Fixpoint join l : elt → t → t :=
match l with
| Leaf ⇒ add
| Node ll lx lr lh ⇒ fun x ⇒
fix join_aux (r:t) : t := match r with
| Leaf ⇒ add x l
| Node rl rx rr rh ⇒
if gt_le_dec lh (rh+2) then bal ll lx (join lr x r)
else if gt_le_dec rh (lh+2) then bal (join_aux rl) rx rr
else create l x r
end
end.
Extraction of minimum element
Fixpoint remove_min l x r : t×elt :=
match l with
| Leaf ⇒ (r,x)
| Node ll lx lr lh ⇒
let (l',m) := remove_min ll lx lr in (bal l' x r, m)
end.
Merging two trees
Definition merge s1 s2 := match s1,s2 with
| Leaf, _ ⇒ s2
| _, Leaf ⇒ s1
| _, Node l2 x2 r2 h2 ⇒
let (s2',m) := remove_min l2 x2 r2 in bal s1 m s2'
end.
Fixpoint remove x s := match s with
| Leaf ⇒ Leaf
| Node l y r h ⇒
match X.compare x y with
| LT _ ⇒ bal (remove x l) y r
| EQ _ ⇒ merge l r
| GT _ ⇒ bal l y (remove x r)
end
end.
Fixpoint min_elt s := match s with
| Leaf ⇒ None
| Node Leaf y _ _ ⇒ Some y
| Node l _ _ _ ⇒ min_elt l
end.
Fixpoint max_elt s := match s with
| Leaf ⇒ None
| Node _ y Leaf _ ⇒ Some y
| Node _ _ r _ ⇒ max_elt r
end.
Definition concat s1 s2 :=
match s1, s2 with
| Leaf, _ ⇒ s2
| _, Leaf ⇒ s1
| _, Node l2 x2 r2 _ ⇒
let (s2',m) := remove_min l2 x2 r2 in
join s1 m s2'
end.
Record triple := mktriple { t_left:t; t_in:bool; t_right:t }.
Notation "<< l , b , r >>" := (mktriple l b r) (at level 9).
Notation "t #l" := (t_left t) (at level 9, format "t '#l'").
Notation "t #b" := (t_in t) (at level 9, format "t '#b'").
Notation "t #r" := (t_right t) (at level 9, format "t '#r'").
Fixpoint split x s : triple := match s with
| Leaf ⇒ << Leaf, false, Leaf >>
| Node l y r h ⇒
match X.compare x y with
| LT _ ⇒ let (ll,b,rl) := split x l in << ll, b, join rl y r >>
| EQ _ ⇒ << l, true, r >>
| GT _ ⇒ let (rl,b,rr) := split x r in << join l y rl, b, rr >>
end
end.
Fixpoint inter s1 s2 := match s1, s2 with
| Leaf, _ ⇒ Leaf
| _, Leaf ⇒ Leaf
| Node l1 x1 r1 h1, _ ⇒
let (l2',pres,r2') := split x1 s2 in
if pres then join (inter l1 l2') x1 (inter r1 r2')
else concat (inter l1 l2') (inter r1 r2')
end.
Fixpoint diff s1 s2 := match s1, s2 with
| Leaf, _ ⇒ Leaf
| _, Leaf ⇒ s1
| Node l1 x1 r1 h1, _ ⇒
let (l2',pres,r2') := split x1 s2 in
if pres then concat (diff l1 l2') (diff r1 r2')
else join (diff l1 l2') x1 (diff r1 r2')
end.
Union
Fixpoint union s1 s2 :=
match s1, s2 with
| Leaf, _ ⇒ s2
| _, Leaf ⇒ s1
| Node l1 x1 r1 h1, _ ⇒
let (l2',_,r2') := split x1 s2 in
join (union l1 l2') x1 (union r1 r2')
end.
Fixpoint elements_aux (acc : list X.t) (t : tree) : list X.t :=
match t with
| Leaf ⇒ acc
| Node l x r _ ⇒ elements_aux (x :: elements_aux acc r) l
end.
Fixpoint filter_acc (f:elt→bool) acc s := match s with
| Leaf ⇒ acc
| Node l x r h ⇒
filter_acc f (filter_acc f (if f x then add x acc else acc) l) r
end.
Definition filter f := filter_acc f Leaf.
Fixpoint partition_acc (f:elt→bool)(acc : t×t)(s : t) : t×t :=
match s with
| Leaf ⇒ acc
| Node l x r _ ⇒
let (acct,accf) := acc in
partition_acc f
(partition_acc f
(if f x then (add x acct, accf) else (acct, add x accf)) l) r
end.
Definition partition f := partition_acc f (Leaf,Leaf).
for_all and ∃
Fixpoint for_all (f:elt→bool) s := match s with
| Leaf ⇒ true
| Node l x r _ ⇒ f x &&& for_all f l &&& for_all f r
end.
Fixpoint exists_ (f:elt→bool) s := match s with
| Leaf ⇒ false
| Node l x r _ ⇒ f x ||| exists_ f l ||| exists_ f r
end.
Fixpoint fold (A : Type) (f : elt → A → A)(s : tree) : A → A :=
fun a ⇒ match s with
| Leaf ⇒ a
| Node l x r _ ⇒ fold f r (f x (fold f l a))
end.
Implicit Arguments fold [A].
Subset
Fixpoint subsetl (subset_l1:t→bool) x1 s2 : bool :=
match s2 with
| Leaf ⇒ false
| Node l2 x2 r2 h2 ⇒
match X.compare x1 x2 with
| EQ _ ⇒ subset_l1 l2
| LT _ ⇒ subsetl subset_l1 x1 l2
| GT _ ⇒ mem x1 r2 &&& subset_l1 s2
end
end.
Fixpoint subsetr (subset_r1:t→bool) x1 s2 : bool :=
match s2 with
| Leaf ⇒ false
| Node l2 x2 r2 h2 ⇒
match X.compare x1 x2 with
| EQ _ ⇒ subset_r1 r2
| LT _ ⇒ mem x1 l2 &&& subset_r1 s2
| GT _ ⇒ subsetr subset_r1 x1 r2
end
end.
Fixpoint subset s1 s2 : bool := match s1, s2 with
| Leaf, _ ⇒ true
| Node _ _ _ _, Leaf ⇒ false
| Node l1 x1 r1 h1, Node l2 x2 r2 h2 ⇒
match X.compare x1 x2 with
| EQ _ ⇒ subset l1 l2 &&& subset r1 r2
| LT _ ⇒ subsetl (subset l1) x1 l2 &&& subset r1 s2
| GT _ ⇒ subsetr (subset r1) x1 r2 &&& subset l1 s2
end
end.
A new comparison algorithm suggested by Xavier Leroy
Fixpoint cons s e : enumeration :=
match s with
| Leaf ⇒ e
| Node l x r h ⇒ cons l (More x r e)
end.
One step of comparison of elements
Definition compare_more x1 (cont:enumeration→comparison) e2 :=
match e2 with
| End ⇒ Gt
| More x2 r2 e2 ⇒
match X.compare x1 x2 with
| EQ _ ⇒ cont (cons r2 e2)
| LT _ ⇒ Lt
| GT _ ⇒ Gt
end
end.
Comparison of left tree, middle element, then right tree
Fixpoint compare_cont s1 (cont:enumeration→comparison) e2 :=
match s1 with
| Leaf ⇒ cont e2
| Node l1 x1 r1 _ ⇒
compare_cont l1 (compare_more x1 (compare_cont r1 cont)) e2
end.
Initial continuation
The complete comparison
Inductive In (x : elt) : tree → Prop :=
| IsRoot : ∀ l r h y, X.eq x y → In x (Node l y r h)
| InLeft : ∀ l r h y, In x l → In x (Node l y r h)
| InRight : ∀ l r h y, In x r → In x (Node l y r h).
Inductive bst : tree → Prop :=
| BSLeaf : bst Leaf
| BSNode : ∀ x l r h, bst l → bst r →
lt_tree x l → gt_tree x r → bst (Node l x r h).
Definition Equal s s' := ∀ a : elt, In a s ↔ In a s'.
Definition Subset s s' := ∀ a : elt, In a s → In a s'.
Definition Empty s := ∀ a : elt, ¬ In a s.
Definition For_all (P : elt → Prop) s := ∀ x, In x s → P x.
Definition Exists (P : elt → Prop) s := ∃ x, In x s ∧ P x.
Hint Constructors In bst.
Hint Unfold lt_tree gt_tree.
Tactic Notation "factornode" ident(l) ident(x) ident(r) ident(h)
"as" ident(s) :=
set (s:=Node l x r h) in *; clearbody s; clear l x r h.
Ltac inv f :=
match goal with
| H:f Leaf |- _ ⇒ inversion_clear H; inv f
| H:f _ Leaf |- _ ⇒ inversion_clear H; inv f
| H:f (Node _ _ _ _) |- _ ⇒ inversion_clear H; inv f
| H:f _ (Node _ _ _ _) |- _ ⇒ inversion_clear H; inv f
| _ ⇒ idtac
end.
Ltac intuition_in := repeat progress (intuition; inv In).
Helper tactic concerning order of elements.
Ltac order := match goal with
| U: lt_tree _ ?s, V: In _ ?s |- _ ⇒ generalize (U _ V); clear U; order
| U: gt_tree _ ?s, V: In _ ?s |- _ ⇒ generalize (U _ V); clear U; order
| _ ⇒ MX.order
end.
Lemma In_1 :
∀ s x y, X.eq x y → In x s → In y s.
Proof.
induction s; simpl; intuition_in; eauto.
Qed.
Hint Immediate In_1.
Lemma In_node_iff :
∀ l x r h y,
In y (Node l x r h) ↔ In y l ∨ X.eq y x ∨ In y r.
Proof.
intuition_in.
Qed.
Lemma lt_leaf : ∀ x : elt, lt_tree x Leaf.
Proof.
red; inversion 1.
Qed.
Lemma gt_leaf : ∀ x : elt, gt_tree x Leaf.
Proof.
red; inversion 1.
Qed.
Lemma lt_tree_node :
∀ (x y : elt) (l r : tree) (h : int),
lt_tree x l → lt_tree x r → X.lt y x → lt_tree x (Node l y r h).
Proof.
unfold lt_tree; intuition_in; order.
Qed.
Lemma gt_tree_node :
∀ (x y : elt) (l r : tree) (h : int),
gt_tree x l → gt_tree x r → X.lt x y → gt_tree x (Node l y r h).
Proof.
unfold gt_tree; intuition_in; order.
Qed.
Hint Resolve lt_leaf gt_leaf lt_tree_node gt_tree_node.
Lemma lt_tree_not_in :
∀ (x : elt) (t : tree), lt_tree x t → ¬ In x t.
Proof.
intros; intro; order.
Qed.
Lemma lt_tree_trans :
∀ x y, X.lt x y → ∀ t, lt_tree x t → lt_tree y t.
Proof.
eauto.
Qed.
Lemma gt_tree_not_in :
∀ (x : elt) (t : tree), gt_tree x t → ¬ In x t.
Proof.
intros; intro; order.
Qed.
Lemma gt_tree_trans :
∀ x y, X.lt y x → ∀ t, gt_tree x t → gt_tree y t.
Proof.
eauto.
Qed.
Hint Resolve lt_tree_not_in lt_tree_trans gt_tree_not_in gt_tree_trans.
Functional Scheme mem_ind := Induction for mem Sort Prop.
Functional Scheme bal_ind := Induction for bal Sort Prop.
Functional Scheme add_ind := Induction for add Sort Prop.
Functional Scheme remove_min_ind := Induction for remove_min Sort Prop.
Functional Scheme merge_ind := Induction for merge Sort Prop.
Functional Scheme remove_ind := Induction for remove Sort Prop.
Functional Scheme min_elt_ind := Induction for min_elt Sort Prop.
Functional Scheme max_elt_ind := Induction for max_elt Sort Prop.
Functional Scheme concat_ind := Induction for concat Sort Prop.
Functional Scheme split_ind := Induction for split Sort Prop.
Functional Scheme inter_ind := Induction for inter Sort Prop.
Functional Scheme diff_ind := Induction for diff Sort Prop.
Functional Scheme union_ind := Induction for union Sort Prop.
Lemma empty_1 : Empty empty.
Proof.
intro; intro.
inversion H.
Qed.
Lemma empty_bst : bst empty.
Proof.
auto.
Qed.
Lemma is_empty_1 : ∀ s, Empty s → is_empty s = true.
Proof.
destruct s as [|r x l h]; simpl; auto.
intro H; elim (H x); auto.
Qed.
Lemma is_empty_2 : ∀ s, is_empty s = true → Empty s.
Proof.
destruct s; simpl; intros; try discriminate; red; auto.
Qed.
Lemma mem_1 : ∀ s x, bst s → In x s → mem x s = true.
Proof.
intros s x; functional induction mem x s; auto; intros; try clear e0;
inv bst; intuition_in; order.
Qed.
Lemma mem_2 : ∀ s x, mem x s = true → In x s.
Proof.
intros s x; functional induction mem x s; auto; intros; discriminate.
Qed.
Lemma singleton_1 : ∀ x y, In y (singleton x) → X.eq x y.
Proof.
unfold singleton; intros; inv In; order.
Qed.
Lemma singleton_2 : ∀ x y, X.eq x y → In y (singleton x).
Proof.
unfold singleton; auto.
Qed.
Lemma singleton_bst : ∀ x : elt, bst (singleton x).
Proof.
unfold singleton; auto.
Qed.
Lemma create_in :
∀ l x r y, In y (create l x r) ↔ X.eq y x ∨ In y l ∨ In y r.
Proof.
unfold create; split; [ inversion_clear 1 | ]; intuition.
Qed.
Lemma create_bst :
∀ l x r, bst l → bst r → lt_tree x l → gt_tree x r →
bst (create l x r).
Proof.
unfold create; auto.
Qed.
Hint Resolve create_bst.
Lemma bal_in : ∀ l x r y,
In y (bal l x r) ↔ X.eq y x ∨ In y l ∨ In y r.
Proof.
intros l x r; functional induction bal l x r; intros; try clear e0;
rewrite !create_in; intuition_in.
Qed.
Lemma bal_bst : ∀ l x r, bst l → bst r →
lt_tree x l → gt_tree x r → bst (bal l x r).
Proof.
intros l x r; functional induction bal l x r; intros;
inv bst; repeat apply create_bst; auto; unfold create;
(apply lt_tree_node || apply gt_tree_node); auto;
(eapply lt_tree_trans || eapply gt_tree_trans); eauto.
Qed.
Hint Resolve bal_bst.
Lemma add_in : ∀ s x y,
In y (add x s) ↔ X.eq y x ∨ In y s.
Proof.
intros s x; functional induction (add x s); auto; intros;
try rewrite bal_in, IHt; intuition_in.
eapply In_1; eauto.
Qed.
Lemma add_bst : ∀ s x, bst s → bst (add x s).
Proof.
intros s x; functional induction (add x s); auto; intros;
inv bst; apply bal_bst; auto.
red; red in H3.
intros.
rewrite add_in in H.
intuition.
eauto.
inv bst; auto using bal_bst.
red; red in H3.
intros.
rewrite add_in in H.
intuition.
apply MX.lt_eq with x; auto.
Qed.
Hint Resolve add_bst.
Ltac join_tac :=
intro l; induction l as [| ll _ lx lr Hlr lh];
[ | intros x r; induction r as [| rl Hrl rx rr _ rh]; unfold join;
[ | destruct (gt_le_dec lh (rh+2));
[ match goal with |- context b [ bal ?a ?b ?c] ⇒
replace (bal a b c)
with (bal ll lx (join lr x (Node rl rx rr rh))); [ | auto]
end
| destruct (gt_le_dec rh (lh+2));
[ match goal with |- context b [ bal ?a ?b ?c] ⇒
replace (bal a b c)
with (bal (join (Node ll lx lr lh) x rl) rx rr); [ | auto]
end
| ] ] ] ]; intros.
Lemma join_in : ∀ l x r y,
In y (join l x r) ↔ X.eq y x ∨ In y l ∨ In y r.
Proof.
join_tac.
simpl.
rewrite add_in; intuition_in.
rewrite add_in; intuition_in.
rewrite bal_in, Hlr; clear Hlr Hrl; intuition_in.
rewrite bal_in, Hrl; clear Hlr Hrl; intuition_in.
apply create_in.
Qed.
Lemma join_bst : ∀ l x r, bst l → bst r →
lt_tree x l → gt_tree x r → bst (join l x r).
Proof.
join_tac; auto; inv bst; apply bal_bst; auto;
clear Hrl Hlr; intro; intros; rewrite join_in in ×.
intuition; [ apply MX.lt_eq with x | ]; eauto.
intuition; [ apply MX.eq_lt with x | ]; eauto.
Qed.
Hint Resolve join_bst.
Lemma remove_min_in : ∀ l x r h y,
In y (Node l x r h) ↔
X.eq y (remove_min l x r)#2 ∨ In y (remove_min l x r)#1.
Proof.
intros l x r; functional induction (remove_min l x r); simpl in *; intros.
intuition_in.
rewrite bal_in, In_node_iff, IHp, e0; simpl; intuition.
Qed.
Lemma remove_min_bst : ∀ l x r h,
bst (Node l x r h) → bst (remove_min l x r)#1.
Proof.
intros l x r; functional induction (remove_min l x r); simpl; intros.
inv bst; auto.
inversion_clear H.
specialize IHp with (1:=H0); rewrite e0 in IHp; auto.
apply bal_bst; auto.
intro y; specialize (H2 y).
rewrite remove_min_in, e0 in H2; simpl in H2; intuition.
Qed.
Lemma remove_min_gt_tree : ∀ l x r h,
bst (Node l x r h) →
gt_tree (remove_min l x r)#2 (remove_min l x r)#1.
Proof.
intros l x r; functional induction (remove_min l x r); simpl; intros.
inv bst; auto.
inversion_clear H.
specialize IHp with (1:=H0); rewrite e0 in IHp; simpl in IHp.
intro y; rewrite bal_in; intuition;
specialize (H2 m); rewrite remove_min_in, e0 in H2; simpl in H2;
[ apply MX.lt_eq with x | ]; eauto.
Qed.
Hint Resolve remove_min_bst remove_min_gt_tree.
Lemma merge_in : ∀ s1 s2 y,
In y (merge s1 s2) ↔ In y s1 ∨ In y s2.
Proof.
intros s1 s2; functional induction (merge s1 s2); intros;
try factornode _x _x0 _x1 _x2 as s1.
intuition_in.
intuition_in.
rewrite bal_in, remove_min_in, e1; simpl; intuition.
Qed.
Lemma merge_bst : ∀ s1 s2, bst s1 → bst s2 →
(∀ y1 y2 : elt, In y1 s1 → In y2 s2 → X.lt y1 y2) →
bst (merge s1 s2).
Proof.
intros s1 s2; functional induction (merge s1 s2); intros; auto;
try factornode _x _x0 _x1 _x2 as s1.
apply bal_bst; auto.
change s2' with ((s2',m)#1); rewrite <-e1; eauto.
intros y Hy.
apply H1; auto.
rewrite remove_min_in, e1; simpl; auto.
change (gt_tree (s2',m)#2 (s2',m)#1); rewrite <-e1; eauto.
Qed.
Hint Resolve merge_bst.
Lemma remove_in : ∀ s x y, bst s →
(In y (remove x s) ↔ ¬ X.eq y x ∧ In y s).
Proof.
intros s x; functional induction (remove x s); intros; inv bst.
intuition_in.
rewrite bal_in, IHt; clear e0 IHt; intuition; [order|order|intuition_in].
rewrite merge_in; clear e0; intuition; [order|order|intuition_in].
elim H4; eauto.
rewrite bal_in, IHt; clear e0 IHt; intuition; [order|order|intuition_in].
Qed.
Lemma remove_bst : ∀ s x, bst s → bst (remove x s).
Proof.
intros s x; functional induction (remove x s); intros; inv bst.
auto.
apply bal_bst; auto.
intro z; rewrite remove_in; auto; destruct 1; eauto.
eauto.
apply bal_bst; auto.
intro z; rewrite remove_in; auto; destruct 1; eauto.
Qed.
Hint Resolve remove_bst.
Lemma min_elt_1 : ∀ s x, min_elt s = Some x → In x s.
Proof.
intro s; functional induction (min_elt s); auto; inversion 1; auto.
Qed.
Lemma min_elt_2 : ∀ s x y, bst s →
min_elt s = Some x → In y s → ¬ X.lt y x.
Proof.
intro s; functional induction (min_elt s);
try rename _x1 into l1, _x2 into x1, _x3 into r1, _x4 into h1.
inversion_clear 2.
inversion_clear 1.
inversion 1; subst.
inversion_clear 1; auto.
inversion_clear H5.
inversion_clear 1.
simpl.
destruct l1.
inversion 1; subst.
assert (X.lt x y) by (apply H2; auto).
inversion_clear 1; auto; order.
assert (X.lt x1 y) by auto.
inversion_clear 2; auto;
(assert (~ X.lt x1 x) by auto); order.
Qed.
Lemma min_elt_3 : ∀ s, min_elt s = None → Empty s.
Proof.
intro s; functional induction (min_elt s).
red; red; inversion 2.
inversion 1.
intro H0.
destruct (IHo H0 _x2); auto.
Qed.
Lemma max_elt_1 : ∀ s x, max_elt s = Some x → In x s.
Proof.
intro s; functional induction (max_elt s); auto; inversion 1; auto.
Qed.
Lemma max_elt_2 : ∀ s x y, bst s →
max_elt s = Some x → In y s → ¬ X.lt x y.
Proof.
intro s; functional induction (max_elt s);
try rename _x1 into l1, _x2 into x1, _x3 into r1, _x4 into h1.
inversion_clear 2.
inversion_clear 1.
inversion 1; subst.
inversion_clear 1; auto.
inversion_clear H5.
inversion_clear 1.
assert (X.lt y x1) by auto.
inversion_clear 2; auto;
(assert (~ X.lt x x1) by auto); order.
Qed.
Lemma max_elt_3 : ∀ s, max_elt s = None → Empty s.
Proof.
intro s; functional induction (max_elt s).
red; auto.
inversion 1.
intros H0; destruct (IHo H0 _x2); auto.
Qed.
Lemma choose_1 : ∀ s x, choose s = Some x → In x s.
Proof.
exact min_elt_1.
Qed.
Lemma choose_2 : ∀ s, choose s = None → Empty s.
Proof.
exact min_elt_3.
Qed.
Lemma choose_3 : ∀ s s', bst s → bst s' →
∀ x x', choose s = Some x → choose s' = Some x' →
Equal s s' → X.eq x x'.
Proof.
unfold choose, Equal; intros s s' Hb Hb' x x' Hx Hx' H.
assert (~X.lt x x').
apply min_elt_2 with s'; auto.
rewrite <-H; auto using min_elt_1.
assert (~X.lt x' x).
apply min_elt_2 with s; auto.
rewrite H; auto using min_elt_1.
destruct (X.compare x x'); intuition.
Qed.
Lemma concat_in : ∀ s1 s2 y,
In y (concat s1 s2) ↔ In y s1 ∨ In y s2.
Proof.
intros s1 s2; functional induction (concat s1 s2); intros;
try factornode _x _x0 _x1 _x2 as s1.
intuition_in.
intuition_in.
rewrite join_in, remove_min_in, e1; simpl; intuition.
Qed.
Lemma concat_bst : ∀ s1 s2, bst s1 → bst s2 →
(∀ y1 y2 : elt, In y1 s1 → In y2 s2 → X.lt y1 y2) →
bst (concat s1 s2).
Proof.
intros s1 s2; functional induction (concat s1 s2); intros; auto;
try factornode _x _x0 _x1 _x2 as s1.
apply join_bst; auto.
change (bst (s2',m)#1); rewrite <-e1; eauto.
intros y Hy.
apply H1; auto.
rewrite remove_min_in, e1; simpl; auto.
change (gt_tree (s2',m)#2 (s2',m)#1); rewrite <-e1; eauto.
Qed.
Hint Resolve concat_bst.
Lemma split_in_1 : ∀ s x y, bst s →
(In y (split x s)#l ↔ In y s ∧ X.lt y x).
Proof.
intros s x; functional induction (split x s); simpl; intros;
inv bst; try clear e0.
intuition_in.
rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order.
intuition_in; order.
rewrite join_in.
rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order.
Qed.
Lemma split_in_2 : ∀ s x y, bst s →
(In y (split x s)#r ↔ In y s ∧ X.lt x y).
Proof.
intros s x; functional induction (split x s); subst; simpl; intros;
inv bst; try clear e0.
intuition_in.
rewrite join_in.
rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order.
intuition_in; order.
rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order.
Qed.
Lemma split_in_3 : ∀ s x, bst s →
((split x s)#b = true ↔ In x s).
Proof.
intros s x; functional induction (split x s); subst; simpl; intros;
inv bst; try clear e0.
intuition_in; try discriminate.
rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order.
intuition.
rewrite e1 in IHt; simpl in IHt; rewrite IHt; intuition_in; order.
Qed.
Lemma split_bst : ∀ s x, bst s →
bst (split x s)#l ∧ bst (split x s)#r.
Proof.
intros s x; functional induction (split x s); subst; simpl; intros;
inv bst; try clear e0; try rewrite e1 in *; simpl in *; intuition;
apply join_bst; auto.
intros y0.
generalize (split_in_2 x y0 H0); rewrite e1; simpl; intuition.
intros y0.
generalize (split_in_1 x y0 H1); rewrite e1; simpl; intuition.
Qed.
Lemma inter_bst_in : ∀ s1 s2, bst s1 → bst s2 →
bst (inter s1 s2) ∧ (∀ y, In y (inter s1 s2) ↔ In y s1 ∧ In y s2).
Proof.
intros s1 s2; functional induction inter s1 s2; intros B1 B2;
[intuition_in|intuition_in | | ];
factornode _x0 _x1 _x2 _x3 as s2;
generalize (split_bst x1 B2);
rewrite e1; simpl; destruct 1; inv bst;
destruct IHt as (IHb1,IHi1); auto;
destruct IHt0 as (IHb2,IHi2); auto;
generalize (@split_in_1 s2 x1)(@split_in_2 s2 x1)
(split_in_3 x1 B2)(split_bst x1 B2);
rewrite e1; simpl; split; intros.
apply join_bst; auto; intro y; [rewrite IHi1|rewrite IHi2]; intuition. rewrite join_in, IHi1, IHi2, H5, H6; intuition_in.
apply In_1 with x1; auto.
apply concat_bst; auto; intros y1 y2; rewrite IHi1, IHi2; intuition; order.
rewrite concat_in, IHi1, IHi2, H5, H6; auto.
assert (~In x1 s2) by (rewrite <- H7; auto).
intuition_in.
elim H9.
apply In_1 with y; auto.
Qed.
Lemma inter_in : ∀ s1 s2 y, bst s1 → bst s2 →
(In y (inter s1 s2) ↔ In y s1 ∧ In y s2).
Proof.
intros s1 s2 y B1 B2; destruct (inter_bst_in B1 B2); auto.
Qed.
Lemma inter_bst : ∀ s1 s2, bst s1 → bst s2 → bst (inter s1 s2).
Proof.
intros s1 s2 B1 B2; destruct (inter_bst_in B1 B2); auto.
Qed.
Lemma diff_bst_in : ∀ s1 s2, bst s1 → bst s2 →
bst (diff s1 s2) ∧ (∀ y, In y (diff s1 s2) ↔ In y s1 ∧ ¬In y s2).
Proof.
intros s1 s2; functional induction diff s1 s2; intros B1 B2;
[intuition_in|intuition_in | | ];
factornode _x0 _x1 _x2 _x3 as s2;
generalize (split_bst x1 B2);
rewrite e1; simpl; destruct 1;
inv avl; inv bst;
destruct IHt as (IHb1,IHi1); auto;
destruct IHt0 as (IHb2,IHi2); auto;
generalize (@split_in_1 s2 x1)(@split_in_2 s2 x1)
(split_in_3 x1 B2)(split_bst x1 B2);
rewrite e1; simpl; split; intros.
apply concat_bst; auto; intros y1 y2; rewrite IHi1, IHi2; intuition; order.
rewrite concat_in, IHi1, IHi2, H5, H6; intuition_in.
elim H13.
apply In_1 with x1; auto.
apply join_bst; auto; intro y; [rewrite IHi1|rewrite IHi2]; intuition. rewrite join_in, IHi1, IHi2, H5, H6; auto.
assert (~In x1 s2) by (rewrite <- H7; auto).
intuition_in.
elim H9.
apply In_1 with y; auto.
Qed.
Lemma diff_in : ∀ s1 s2 y, bst s1 → bst s2 →
(In y (diff s1 s2) ↔ In y s1 ∧ ¬In y s2).
Proof.
intros s1 s2 y B1 B2; destruct (diff_bst_in B1 B2); auto.
Qed.
Lemma diff_bst : ∀ s1 s2, bst s1 → bst s2 → bst (diff s1 s2).
Proof.
intros s1 s2 B1 B2; destruct (diff_bst_in B1 B2); auto.
Qed.
Lemma union_in : ∀ s1 s2 y, bst s1 → bst s2 →
(In y (union s1 s2) ↔ In y s1 ∨ In y s2).
Proof.
intros s1 s2; functional induction union s1 s2; intros y B1 B2.
intuition_in.
intuition_in.
factornode _x0 _x1 _x2 _x3 as s2.
generalize (split_in_1 x1 y B2)(split_in_2 x1 y B2)(split_bst x1 B2).
rewrite e1; simpl.
destruct 3; inv bst.
rewrite join_in, IHt, IHt0, H, H0; auto.
case (X.compare y x1); intuition_in.
Qed.
Lemma union_bst : ∀ s1 s2, bst s1 → bst s2 →
bst (union s1 s2).
Proof.
intros s1 s2; functional induction union s1 s2; intros B1 B2; auto.
factornode _x0 _x1 _x2 _x3 as s2.
generalize (@split_in_1 s2 x1)(@split_in_2 s2 x1)(split_bst x1 B2).
rewrite e1; simpl; destruct 3.
inv bst.
apply join_bst; auto.
intro y; rewrite union_in, H; intuition_in.
intro y; rewrite union_in, H0; intuition_in.
Qed.
Lemma elements_aux_in : ∀ s acc x,
InA X.eq x (elements_aux acc s) ↔ In x s ∨ InA X.eq x acc.
Proof.
induction s as [ | l Hl x r Hr h ]; simpl; auto.
intuition.
inversion H0.
intros.
rewrite Hl.
destruct (Hr acc x0); clear Hl Hr.
intuition; inversion_clear H3; intuition.
Qed.
Lemma elements_in : ∀ s x, InA X.eq x (elements s) ↔ In x s.
Proof.
intros; generalize (elements_aux_in s nil x); intuition.
inversion_clear H0.
Qed.
Lemma elements_aux_sort : ∀ s acc, bst s → sort X.lt acc →
(∀ x y : elt, InA X.eq x acc → In y s → X.lt y x) →
sort X.lt (elements_aux acc s).
Proof.
induction s as [ | l Hl y r Hr h]; simpl; intuition.
inv bst.
apply Hl; auto.
constructor.
apply Hr; auto.
apply MX.In_Inf; intros.
destruct (elements_aux_in r acc y0); intuition.
intros.
inversion_clear H.
order.
destruct (elements_aux_in r acc x); intuition eauto.
Qed.
Lemma elements_sort : ∀ s : tree, bst s → sort X.lt (elements s).
Proof.
intros; unfold elements; apply elements_aux_sort; auto.
intros; inversion H0.
Qed.
Hint Resolve elements_sort.
Lemma elements_nodup : ∀ s : tree, bst s → NoDupA X.eq (elements s).
Proof.
auto.
Qed.
Lemma elements_aux_cardinal :
∀ s acc, (length acc + cardinal s)%nat = length (elements_aux acc s).
Proof.
simple induction s; simpl in |- *; intuition.
rewrite <- H.
simpl in |- ×.
rewrite <- H0; omega.
Qed.
Lemma elements_cardinal : ∀ s : tree, cardinal s = length (elements s).
Proof.
exact (fun s ⇒ elements_aux_cardinal s nil).
Qed.
Lemma elements_app :
∀ s acc, elements_aux acc s = elements s ++ acc.
Proof.
induction s; simpl; intros; auto.
rewrite IHs1, IHs2.
unfold elements; simpl.
rewrite 2 IHs1, IHs2, <- !app_nil_end, !app_ass; auto.
Qed.
Lemma elements_node :
∀ l x r h acc,
elements l ++ x :: elements r ++ acc =
elements (Node l x r h) ++ acc.
Proof.
unfold elements; simpl; intros; auto.
rewrite !elements_app, <- !app_nil_end, !app_ass; auto.
Qed.
Section F.
Variable f : elt → bool.
Lemma filter_acc_in : ∀ s acc,
compat_bool X.eq f → ∀ x : elt,
In x (filter_acc f acc s) ↔ In x acc ∨ In x s ∧ f x = true.
Proof.
induction s; simpl; intros.
intuition_in.
rewrite IHs2, IHs1 by (destruct (f t); auto).
case_eq (f t); intros.
rewrite (add_in); auto.
intuition_in.
rewrite (H _ _ H2).
intuition.
intuition_in.
rewrite (H _ _ H2) in H3.
rewrite H0 in H3; discriminate.
Qed.
Lemma filter_acc_bst : ∀ s acc, bst s → bst acc →
bst (filter_acc f acc s).
Proof.
induction s; simpl; auto.
intros.
inv bst.
destruct (f t); auto.
Qed.
Lemma filter_in : ∀ s,
compat_bool X.eq f → ∀ x : elt,
In x (filter f s) ↔ In x s ∧ f x = true.
Proof.
unfold filter; intros; rewrite filter_acc_in; intuition_in.
Qed.
Lemma filter_bst : ∀ s, bst s → bst (filter f s).
Proof.
unfold filter; intros; apply filter_acc_bst; auto.
Qed.
Lemma partition_acc_in_1 : ∀ s acc,
compat_bool X.eq f → ∀ x : elt,
In x (partition_acc f acc s)#1 ↔
In x acc#1 ∨ In x s ∧ f x = true.
Proof.
induction s; simpl; intros.
intuition_in.
destruct acc as [acct accf]; simpl in ×.
rewrite IHs2 by
(destruct (f t); auto; apply partition_acc_avl_1; simpl; auto).
rewrite IHs1 by (destruct (f t); simpl; auto).
case_eq (f t); simpl; intros.
rewrite (add_in); auto.
intuition_in.
rewrite (H _ _ H2).
intuition.
intuition_in.
rewrite (H _ _ H2) in H3.
rewrite H0 in H3; discriminate.
Qed.
Lemma partition_acc_in_2 : ∀ s acc,
compat_bool X.eq f → ∀ x : elt,
In x (partition_acc f acc s)#2 ↔
In x acc#2 ∨ In x s ∧ f x = false.
Proof.
induction s; simpl; intros.
intuition_in.
destruct acc as [acct accf]; simpl in ×.
rewrite IHs2 by
(destruct (f t); auto; apply partition_acc_avl_2; simpl; auto).
rewrite IHs1 by (destruct (f t); simpl; auto).
case_eq (f t); simpl; intros.
intuition.
intuition_in.
rewrite (H _ _ H2) in H3.
rewrite H0 in H3; discriminate.
rewrite (add_in); auto.
intuition_in.
rewrite (H _ _ H2).
intuition.
Qed.
Lemma partition_in_1 : ∀ s,
compat_bool X.eq f → ∀ x : elt,
In x (partition f s)#1 ↔ In x s ∧ f x = true.
Proof.
unfold partition; intros; rewrite partition_acc_in_1;
simpl in *; intuition_in.
Qed.
Lemma partition_in_2 : ∀ s,
compat_bool X.eq f → ∀ x : elt,
In x (partition f s)#2 ↔ In x s ∧ f x = false.
Proof.
unfold partition; intros; rewrite partition_acc_in_2;
simpl in *; intuition_in.
Qed.
Lemma partition_acc_bst_1 : ∀ s acc, bst s → bst acc#1 →
bst (partition_acc f acc s)#1.
Proof.
induction s; simpl; auto.
destruct acc as [acct accf]; simpl in ×.
intros.
inv bst.
destruct (f t); auto.
apply IHs2; simpl; auto.
apply IHs1; simpl; auto.
Qed.
Lemma partition_acc_bst_2 : ∀ s acc, bst s → bst acc#2 →
bst (partition_acc f acc s)#2.
Proof.
induction s; simpl; auto.
destruct acc as [acct accf]; simpl in ×.
intros.
inv bst.
destruct (f t); auto.
apply IHs2; simpl; auto.
apply IHs1; simpl; auto.
Qed.
Lemma partition_bst_1 : ∀ s, bst s → bst (partition f s)#1.
Proof.
unfold partition; intros; apply partition_acc_bst_1; auto.
Qed.
Lemma partition_bst_2 : ∀ s, bst s → bst (partition f s)#2.
Proof.
unfold partition; intros; apply partition_acc_bst_2; auto.
Qed.
for_all and ∃
Lemma for_all_1 : ∀ s, compat_bool X.eq f →
For_all (fun x ⇒ f x = true) s → for_all f s = true.
Proof.
induction s; simpl; auto.
intros.
rewrite IHs1; try red; auto.
rewrite IHs2; try red; auto.
generalize (H0 t).
destruct (f t); simpl; auto.
Qed.
Lemma for_all_2 : ∀ s, compat_bool X.eq f →
for_all f s = true → For_all (fun x ⇒ f x = true) s.
Proof.
induction s; simpl; auto; intros; red; intros; inv In.
destruct (andb_prop _ _ H0); auto.
destruct (andb_prop _ _ H1); eauto.
apply IHs1; auto.
destruct (andb_prop _ _ H0); auto.
destruct (andb_prop _ _ H1); auto.
apply IHs2; auto.
destruct (andb_prop _ _ H0); auto.
Qed.
Lemma exists_1 : ∀ s, compat_bool X.eq f →
Exists (fun x ⇒ f x = true) s → exists_ f s = true.
Proof.
induction s; simpl; destruct 2 as (x,(U,V)); inv In; rewrite <- ?orb_lazy_alt.
rewrite (H _ _ (X.eq_sym H0)); rewrite V; auto.
apply orb_true_intro; left.
apply orb_true_intro; right; apply IHs1; auto; ∃ x; auto.
apply orb_true_intro; right; apply IHs2; auto; ∃ x; auto.
Qed.
Lemma exists_2 : ∀ s, compat_bool X.eq f →
exists_ f s = true → Exists (fun x ⇒ f x = true) s.
Proof.
induction s; simpl; intros; rewrite <- ?orb_lazy_alt in ×.
discriminate.
destruct (orb_true_elim _ _ H0) as [H1|H1].
destruct (orb_true_elim _ _ H1) as [H2|H2].
∃ t; auto.
destruct (IHs1 H H2); auto; ∃ x; intuition.
destruct (IHs2 H H1); auto; ∃ x; intuition.
Qed.
End F.
Definition fold' (A : Type) (f : elt → A → A)(s : tree) :=
L.fold f (elements s).
Implicit Arguments fold' [A].
Lemma fold_equiv_aux :
∀ (A : Type) (s : tree) (f : elt → A → A) (a : A) (acc : list elt),
L.fold f (elements_aux acc s) a = L.fold f acc (fold f s a).
Proof.
simple induction s.
simpl in |- *; intuition.
simpl in |- *; intros.
rewrite H.
simpl.
apply H0.
Qed.
Lemma fold_equiv :
∀ (A : Type) (s : tree) (f : elt → A → A) (a : A),
fold f s a = fold' f s a.
Proof.
unfold fold', elements in |- ×.
simple induction s; simpl in |- *; auto; intros.
rewrite fold_equiv_aux.
rewrite H0.
simpl in |- *; auto.
Qed.
Lemma fold_1 :
∀ (s:t)(Hs:bst s)(A : Type)(f : elt → A → A)(i : A),
fold f s i = fold_left (fun a e ⇒ f e a) (elements s) i.
Proof.
intros.
rewrite fold_equiv.
unfold fold'.
rewrite L.fold_1.
unfold L.elements; auto.
apply elements_sort; auto.
Qed.
Lemma subsetl_12 : ∀ subset_l1 l1 x1 h1 s2,
bst (Node l1 x1 Leaf h1) → bst s2 →
(∀ s, bst s → (subset_l1 s = true ↔ Subset l1 s)) →
(subsetl subset_l1 x1 s2 = true ↔ Subset (Node l1 x1 Leaf h1) s2 ).
Proof.
induction s2 as [|l2 IHl2 x2 r2 IHr2 h2]; simpl; intros.
unfold Subset; intuition; try discriminate.
assert (H': In x1 Leaf) by auto; inversion H'.
inversion_clear H0.
specialize (IHl2 H H2 H1).
specialize (IHr2 H H3 H1).
inv bst. clear H8.
destruct X.compare.
rewrite IHl2; clear H1 IHl2 IHr2.
unfold Subset. intuition_in.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
rewrite H1 by auto; clear H1 IHl2 IHr2.
unfold Subset. intuition_in.
assert (X.eq a x2) by order; intuition_in.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
rewrite <-andb_lazy_alt, andb_true_iff, H1 by auto; clear H1 IHl2 IHr2.
unfold Subset. intuition_in.
assert (H':=mem_2 H6); apply In_1 with x1; auto.
apply mem_1; auto.
assert (In x1 (Node l2 x2 r2 h2)) by auto; intuition_in; order.
Qed.
Lemma subsetr_12 : ∀ subset_r1 r1 x1 h1 s2,
bst (Node Leaf x1 r1 h1) → bst s2 →
(∀ s, bst s → (subset_r1 s = true ↔ Subset r1 s)) →
(subsetr subset_r1 x1 s2 = true ↔ Subset (Node Leaf x1 r1 h1) s2).
Proof.
induction s2 as [|l2 IHl2 x2 r2 IHr2 h2]; simpl; intros.
unfold Subset; intuition; try discriminate.
assert (H': In x1 Leaf) by auto; inversion H'.
inversion_clear H0.
specialize (IHl2 H H2 H1).
specialize (IHr2 H H3 H1).
inv bst. clear H7.
destruct X.compare.
rewrite <-andb_lazy_alt, andb_true_iff, H1 by auto; clear H1 IHl2 IHr2.
unfold Subset. intuition_in.
assert (H':=mem_2 H1); apply In_1 with x1; auto.
apply mem_1; auto.
assert (In x1 (Node l2 x2 r2 h2)) by auto; intuition_in; order.
rewrite H1 by auto; clear H1 IHl2 IHr2.
unfold Subset. intuition_in.
assert (X.eq a x2) by order; intuition_in.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
rewrite IHr2; clear H1 IHl2 IHr2.
unfold Subset. intuition_in.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
Qed.
Lemma subset_12 : ∀ s1 s2, bst s1 → bst s2 →
(subset s1 s2 = true ↔ Subset s1 s2).
Proof.
induction s1 as [|l1 IHl1 x1 r1 IHr1 h1]; simpl; intros.
unfold Subset; intuition_in.
destruct s2 as [|l2 x2 r2 h2]; simpl; intros.
unfold Subset; intuition_in; try discriminate.
assert (H': In x1 Leaf) by auto; inversion H'.
inv bst.
destruct X.compare.
rewrite <-andb_lazy_alt, andb_true_iff, IHr1 by auto.
rewrite (@subsetl_12 (subset l1) l1 x1 h1) by auto.
clear IHl1 IHr1.
unfold Subset; intuition_in.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
rewrite <-andb_lazy_alt, andb_true_iff, IHl1, IHr1 by auto.
clear IHl1 IHr1.
unfold Subset; intuition_in.
assert (X.eq a x2) by order; intuition_in.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
rewrite <-andb_lazy_alt, andb_true_iff, IHl1 by auto.
rewrite (@subsetr_12 (subset r1) r1 x1 h1) by auto.
clear IHl1 IHr1.
unfold Subset; intuition_in.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
assert (In a (Node l2 x2 r2 h2)) by auto; intuition_in; order.
Qed.
Definition eq := Equal.
Definition lt (s1 s2 : t) : Prop := L.lt (elements s1) (elements s2).
Lemma eq_refl : ∀ s : t, Equal s s.
Proof.
unfold Equal; intuition.
Qed.
Lemma eq_sym : ∀ s s' : t, Equal s s' → Equal s' s.
Proof.
unfold Equal; intros s s' H x; destruct (H x); split; auto.
Qed.
Lemma eq_trans : ∀ s s' s'' : t,
Equal s s' → Equal s' s'' → Equal s s''.
Proof.
unfold Equal; intros s s' s'' H1 H2 x;
destruct (H1 x); destruct (H2 x); split; auto.
Qed.
Lemma eq_L_eq :
∀ s s' : t, Equal s s' → L.eq (elements s) (elements s').
Proof.
unfold Equal, L.eq, L.Equal; intros; do 2 rewrite elements_in; auto.
Qed.
Lemma L_eq_eq :
∀ s s' : t, L.eq (elements s) (elements s') → Equal s s'.
Proof.
unfold Equal, L.eq, L.Equal; intros; do 2 rewrite <-elements_in; auto.
Qed.
Hint Resolve eq_L_eq L_eq_eq.
Definition lt_trans (s s' s'' : t) (h : lt s s')
(h' : lt s' s'') : lt s s'' := L.lt_trans h h'.
Lemma lt_not_eq : ∀ s s' : t,
bst s → bst s' → lt s s' → ¬ Equal s s'.
Proof.
unfold lt in |- *; intros; intro.
apply L.lt_not_eq with (s := elements s) (s' := elements s'); auto.
Qed.
Lemma L_eq_cons :
∀ (l1 l2 : list elt) (x y : elt),
X.eq x y → L.eq l1 l2 → L.eq (x :: l1) (y :: l2).
Proof.
unfold L.eq, L.Equal in |- *; intuition.
inversion_clear H1; generalize (H0 a); clear H0; intuition.
apply InA_eqA with x; eauto with ×.
inversion_clear H1; generalize (H0 a); clear H0; intuition.
apply InA_eqA with y; eauto with ×.
Qed.
Hint Resolve L_eq_cons.
A new comparison algorithm suggested by Xavier Leroy
Fixpoint flatten_e (e : enumeration) : list elt := match e with
| End ⇒ nil
| More x t r ⇒ x :: elements t ++ flatten_e r
end.
Lemma flatten_e_elements :
∀ l x r h e,
elements l ++ flatten_e (More x r e) = elements (Node l x r h) ++ flatten_e e.
Proof.
intros; simpl; apply elements_node.
Qed.
Lemma cons_1 : ∀ s e,
flatten_e (cons s e) = elements s ++ flatten_e e.
Proof.
induction s; simpl; auto; intros.
rewrite IHs1; apply flatten_e_elements.
Qed.
Correctness of this comparison
Definition Cmp c :=
match c with
| Eq ⇒ L.eq
| Lt ⇒ L.lt
| Gt ⇒ (fun l1 l2 ⇒ L.lt l2 l1)
end.
Lemma cons_Cmp : ∀ c x1 x2 l1 l2, X.eq x1 x2 →
Cmp c l1 l2 → Cmp c (x1::l1) (x2::l2).
Proof.
destruct c; simpl; auto.
Qed.
Hint Resolve cons_Cmp.
Lemma compare_end_Cmp :
∀ e2, Cmp (compare_end e2) nil (flatten_e e2).
Proof.
destruct e2; simpl; auto.
apply L.eq_refl.
Qed.
Lemma compare_more_Cmp : ∀ x1 cont x2 r2 e2 l,
Cmp (cont (cons r2 e2)) l (elements r2 ++ flatten_e e2) →
Cmp (compare_more x1 cont (More x2 r2 e2)) (x1::l)
(flatten_e (More x2 r2 e2)).
Proof.
simpl; intros; destruct X.compare; simpl; auto.
Qed.
Lemma compare_cont_Cmp : ∀ s1 cont e2 l,
(∀ e, Cmp (cont e) l (flatten_e e)) →
Cmp (compare_cont s1 cont e2) (elements s1 ++ l) (flatten_e e2).
Proof.
induction s1 as [|l1 Hl1 x1 r1 Hr1 h1]; simpl; intros; auto.
rewrite <- elements_node; simpl.
apply Hl1; auto. clear e2. intros [|x2 r2 e2].
simpl; auto.
apply compare_more_Cmp.
rewrite <- cons_1; auto.
Qed.
Lemma compare_Cmp : ∀ s1 s2,
Cmp (compare s1 s2) (elements s1) (elements s2).
Proof.
intros; unfold compare.
rewrite (app_nil_end (elements s1)).
replace (elements s2) with (flatten_e (cons s2 End)) by
(rewrite cons_1; simpl; rewrite <- app_nil_end; auto).
apply compare_cont_Cmp; auto.
intros.
apply compare_end_Cmp; auto.
Qed.
Lemma equal_1 : ∀ s1 s2, bst s1 → bst s2 →
Equal s1 s2 → equal s1 s2 = true.
Proof.
unfold equal; intros s1 s2 B1 B2 E.
generalize (compare_Cmp s1 s2).
destruct (compare s1 s2); simpl in *; auto; intros.
elim (lt_not_eq B1 B2 H E); auto.
elim (lt_not_eq B2 B1 H (eq_sym E)); auto.
Qed.
Lemma equal_2 : ∀ s1 s2,
equal s1 s2 = true → Equal s1 s2.
Proof.
unfold equal; intros s1 s2 E.
generalize (compare_Cmp s1 s2);
destruct compare; auto; discriminate.
Qed.
End Proofs.
End Raw.
Encapsulation
Module IntMake (I:Int)(X: OrderedType) <: S with Module E := X.
Module E := X.
Module Raw := Raw I X.
Import Raw.Proofs.
Record bst := Bst {this :> Raw.t; is_bst : Raw.bst this}.
Definition t := bst.
Definition elt := E.t.
Definition In (x : elt) (s : t) := Raw.In x s.
Definition Equal (s s':t) := ∀ a : elt, In a s ↔ In a s'.
Definition Subset (s s':t) := ∀ a : elt, In a s → In a s'.
Definition Empty (s:t) := ∀ a : elt, ¬ In a s.
Definition For_all (P : elt → Prop) (s:t) := ∀ x, In x s → P x.
Definition Exists (P : elt → Prop) (s:t) := ∃ x, In x s ∧ P x.
Lemma In_1 : ∀ (s:t)(x y:elt), E.eq x y → In x s → In y s.
Proof. intro s; exact (@In_1 s). Qed.
Definition mem (x:elt)(s:t) : bool := Raw.mem x s.
Definition empty : t := Bst empty_bst.
Definition is_empty (s:t) : bool := Raw.is_empty s.
Definition singleton (x:elt) : t := Bst (singleton_bst x).
Definition add (x:elt)(s:t) : t := Bst (add_bst x (is_bst s)).
Definition remove (x:elt)(s:t) : t := Bst (remove_bst x (is_bst s)).
Definition inter (s s':t) : t := Bst (inter_bst (is_bst s) (is_bst s')).
Definition union (s s':t) : t := Bst (union_bst (is_bst s) (is_bst s')).
Definition diff (s s':t) : t := Bst (diff_bst (is_bst s) (is_bst s')).
Definition elements (s:t) : list elt := Raw.elements s.
Definition min_elt (s:t) : option elt := Raw.min_elt s.
Definition max_elt (s:t) : option elt := Raw.max_elt s.
Definition choose (s:t) : option elt := Raw.choose s.
Definition fold (B : Type) (f : elt → B → B) (s:t) : B → B := Raw.fold f s.
Definition cardinal (s:t) : nat := Raw.cardinal s.
Definition filter (f : elt → bool) (s:t) : t :=
Bst (filter_bst f (is_bst s)).
Definition for_all (f : elt → bool) (s:t) : bool := Raw.for_all f s.
Definition exists_ (f : elt → bool) (s:t) : bool := Raw.exists_ f s.
Definition partition (f : elt → bool) (s:t) : t × t :=
let p := Raw.partition f s in
(@Bst (fst p) (partition_bst_1 f (is_bst s)),
@Bst (snd p) (partition_bst_2 f (is_bst s))).
Definition equal (s s':t) : bool := Raw.equal s s'.
Definition subset (s s':t) : bool := Raw.subset s s'.
Definition eq (s s':t) : Prop := Raw.Equal s s'.
Definition lt (s s':t) : Prop := Raw.Proofs.lt s s'.
Definition compare (s s':t) : Compare lt eq s s'.
Proof.
destruct s as (s,b), s' as (s',b').
generalize (compare_Cmp s s').
destruct Raw.compare; intros; [apply EQ|apply LT|apply GT]; red; auto.
Defined.
Definition eq_dec (s s':t) : { eq s s' } + { ¬ eq s s' }.
Proof.
destruct s as (s,b), s' as (s',b'); unfold eq; simpl.
case_eq (Raw.equal s s'); intro H; [left|right].
apply equal_2; auto.
intro H'; rewrite equal_1 in H; auto; discriminate.
Defined.
Section Specs.
Variable s s' s'': t.
Variable x y : elt.
Hint Resolve is_bst.
Lemma mem_1 : In x s → mem x s = true.
Proof. exact (mem_1 (is_bst s)). Qed.
Lemma mem_2 : mem x s = true → In x s.
Proof. exact (@mem_2 s x). Qed.
Lemma equal_1 : Equal s s' → equal s s' = true.
Proof. exact (equal_1 (is_bst s) (is_bst s')). Qed.
Lemma equal_2 : equal s s' = true → Equal s s'.
Proof. exact (@equal_2 s s'). Qed.
Ltac wrap t H := unfold t, In; simpl; rewrite H; auto; intuition.
Lemma subset_1 : Subset s s' → subset s s' = true.
Proof. wrap subset subset_12. Qed.
Lemma subset_2 : subset s s' = true → Subset s s'.
Proof. wrap subset subset_12. Qed.
Lemma empty_1 : Empty empty.
Proof. exact empty_1. Qed.
Lemma is_empty_1 : Empty s → is_empty s = true.
Proof. exact (@is_empty_1 s). Qed.
Lemma is_empty_2 : is_empty s = true → Empty s.
Proof. exact (@is_empty_2 s). Qed.
Lemma add_1 : E.eq x y → In y (add x s).
Proof. wrap add add_in. Qed.
Lemma add_2 : In y s → In y (add x s).
Proof. wrap add add_in. Qed.
Lemma add_3 : ¬ E.eq x y → In y (add x s) → In y s.
Proof. wrap add add_in. elim H; auto. Qed.
Lemma remove_1 : E.eq x y → ¬ In y (remove x s).
Proof. wrap remove remove_in. Qed.
Lemma remove_2 : ¬ E.eq x y → In y s → In y (remove x s).
Proof. wrap remove remove_in. Qed.
Lemma remove_3 : In y (remove x s) → In y s.
Proof. wrap remove remove_in. Qed.
Lemma singleton_1 : In y (singleton x) → E.eq x y.
Proof. exact (@singleton_1 x y). Qed.
Lemma singleton_2 : E.eq x y → In y (singleton x).
Proof. exact (@singleton_2 x y). Qed.
Lemma union_1 : In x (union s s') → In x s ∨ In x s'.
Proof. wrap union union_in. Qed.
Lemma union_2 : In x s → In x (union s s').
Proof. wrap union union_in. Qed.
Lemma union_3 : In x s' → In x (union s s').
Proof. wrap union union_in. Qed.
Lemma inter_1 : In x (inter s s') → In x s.
Proof. wrap inter inter_in. Qed.
Lemma inter_2 : In x (inter s s') → In x s'.
Proof. wrap inter inter_in. Qed.
Lemma inter_3 : In x s → In x s' → In x (inter s s').
Proof. wrap inter inter_in. Qed.
Lemma diff_1 : In x (diff s s') → In x s.
Proof. wrap diff diff_in. Qed.
Lemma diff_2 : In x (diff s s') → ¬ In x s'.
Proof. wrap diff diff_in. Qed.
Lemma diff_3 : In x s → ¬ In x s' → In x (diff s s').
Proof. wrap diff diff_in. Qed.
Lemma fold_1 : ∀ (A : Type) (i : A) (f : elt → A → A),
fold f s i = fold_left (fun a e ⇒ f e a) (elements s) i.
Proof. unfold fold, elements; intros; apply fold_1; auto. Qed.
Lemma cardinal_1 : cardinal s = length (elements s).
Proof.
unfold cardinal, elements; intros; apply elements_cardinal; auto.
Qed.
Section Filter.
Variable f : elt → bool.
Lemma filter_1 : compat_bool E.eq f → In x (filter f s) → In x s.
Proof. intro. wrap filter filter_in. Qed.
Lemma filter_2 : compat_bool E.eq f → In x (filter f s) → f x = true.
Proof. intro. wrap filter filter_in. Qed.
Lemma filter_3 : compat_bool E.eq f → In x s → f x = true → In x (filter f s).
Proof. intro. wrap filter filter_in. Qed.
Lemma for_all_1 : compat_bool E.eq f → For_all (fun x ⇒ f x = true) s → for_all f s = true.
Proof. exact (@for_all_1 f s). Qed.
Lemma for_all_2 : compat_bool E.eq f → for_all f s = true → For_all (fun x ⇒ f x = true) s.
Proof. exact (@for_all_2 f s). Qed.
Lemma exists_1 : compat_bool E.eq f → Exists (fun x ⇒ f x = true) s → exists_ f s = true.
Proof. exact (@exists_1 f s). Qed.
Lemma exists_2 : compat_bool E.eq f → exists_ f s = true → Exists (fun x ⇒ f x = true) s.
Proof. exact (@exists_2 f s). Qed.
Lemma partition_1 : compat_bool E.eq f →
Equal (fst (partition f s)) (filter f s).
Proof.
unfold partition, filter, Equal, In; simpl ;intros H a.
rewrite partition_in_1, filter_in; intuition.
Qed.
Lemma partition_2 : compat_bool E.eq f →
Equal (snd (partition f s)) (filter (fun x ⇒ negb (f x)) s).
Proof.
unfold partition, filter, Equal, In; simpl ;intros H a.
rewrite partition_in_2, filter_in; intuition.
rewrite H2; auto.
destruct (f a); auto.
repeat red; intros; f_equal.
rewrite (H _ _ H0); auto.
Qed.
End Filter.
Lemma elements_1 : In x s → InA E.eq x (elements s).
Proof. wrap elements elements_in. Qed.
Lemma elements_2 : InA E.eq x (elements s) → In x s.
Proof. wrap elements elements_in. Qed.
Lemma elements_3 : sort E.lt (elements s).
Proof. exact (elements_sort (is_bst s)). Qed.
Lemma elements_3w : NoDupA E.eq (elements s).
Proof. exact (elements_nodup (is_bst s)). Qed.
Lemma min_elt_1 : min_elt s = Some x → In x s.
Proof. exact (@min_elt_1 s x). Qed.
Lemma min_elt_2 : min_elt s = Some x → In y s → ¬ E.lt y x.
Proof. exact (@min_elt_2 s x y (is_bst s)). Qed.
Lemma min_elt_3 : min_elt s = None → Empty s.
Proof. exact (@min_elt_3 s). Qed.
Lemma max_elt_1 : max_elt s = Some x → In x s.
Proof. exact (@max_elt_1 s x). Qed.
Lemma max_elt_2 : max_elt s = Some x → In y s → ¬ E.lt x y.
Proof. exact (@max_elt_2 s x y (is_bst s)). Qed.
Lemma max_elt_3 : max_elt s = None → Empty s.
Proof. exact (@max_elt_3 s). Qed.
Lemma choose_1 : choose s = Some x → In x s.
Proof. exact (@choose_1 s x). Qed.
Lemma choose_2 : choose s = None → Empty s.
Proof. exact (@choose_2 s). Qed.
Lemma choose_3 : choose s = Some x → choose s' = Some y →
Equal s s' → E.eq x y.
Proof. exact (@choose_3 _ _ (is_bst s) (is_bst s') x y). Qed.
Lemma eq_refl : eq s s.
Proof. exact (eq_refl s). Qed.
Lemma eq_sym : eq s s' → eq s' s.
Proof. exact (@eq_sym s s'). Qed.
Lemma eq_trans : eq s s' → eq s' s'' → eq s s''.
Proof. exact (@eq_trans s s' s''). Qed.
Lemma lt_trans : lt s s' → lt s' s'' → lt s s''.
Proof. exact (@lt_trans s s' s''). Qed.
Lemma lt_not_eq : lt s s' → ¬eq s s'.
Proof. exact (@lt_not_eq _ _ (is_bst s) (is_bst s')). Qed.
End Specs.
End IntMake.
Module Make (X: OrderedType) <: S with Module E := X
:=IntMake(Z_as_Int)(X).
