(** * Empty map *)

Definition Empty m := forall (a:key)(e:elt) , ~ MapsTo a e m.

(* Specifications: *)
Lemma empty_bst : bst (empty elt).
Lemma empty_1 : Empty (empty elt).
Lemma is_empty_1 : forall m, Empty m -> is_empty m = true.
Lemma is_empty_2 : forall m, is_empty m = true -> Empty m.
Lemma mem_1 : forall m x, bst m -> In x m -> mem x m = true.
Lemma mem_2 : forall m x, mem x m = true -> In x m.
Lemma find_1 : forall m x e, bst m -> MapsTo x e m -> find x m = Some e.
Lemma find_2 : forall m x e, find x m = Some e -> MapsTo x e m.
Lemma find_iff : forall m x e, bst m -> (find x m = Some e <-> MapsTo x e m).
Lemma find_in : forall m x, find x m <> None -> In x m.
Lemma in_find : forall m x, bst m -> In x m -> find x m <> None.
Lemma find_in_iff : forall m x, bst m -> (find x m <> None <-> In x m).
Lemma not_find_iff : forall m x, bst m -> (find x m = None <-> ~In x m).
Lemma find_find : forall m m' x, find x m = find x m' <-> (forall d, find x m = Some d <-> find x m' = Some d).
Lemma find_mapsto_equiv : forall m m' x, bst m -> bst m' -> (find x m = find x m' <-> (forall d, MapsTo x d m <-> MapsTo x d m')).
Lemma find_in_equiv : forall m m' x, bst m -> bst m' -> find x m = find x m' -> (In x m <-> In x m').
Lemma create_bst : forall l x e r, bst l -> bst r -> lt_tree x l -> gt_tree x r -> bst (create l x e r).
Lemma create_in : forall l x e r y, In y (create l x e r) <-> X.eq y x \/ In y l \/ In y r.
Lemma bal_bst : forall l x e r, bst l -> bst r -> lt_tree x l -> gt_tree x r -> bst (bal l x e r).
Lemma bal_in : forall l x e r y, In y (bal l x e r) <-> X.eq y x \/ In y l \/ In y r.
Lemma bal_mapsto : forall l x e r y e', MapsTo y e' (bal l x e r) <-> MapsTo y e' (create l x e r).
Lemma bal_find : forall l x e r y, bst l -> bst r -> lt_tree x l -> gt_tree x r -> find y (bal l x e r) = find y (create l x e r).
Lemma add_in : forall m x y e, In y (add x e m) <-> X.eq y x \/ In y m.
Lemma add_bst : forall m x e, bst m -> bst (add x e m).
Lemma add_1 : forall m x y e, X.eq x y -> MapsTo y e (add x e m).
Lemma add_2 : forall m x y e e', ~X.eq x y -> MapsTo y e m -> MapsTo y e (add x e' m).
Lemma add_3 : forall m x y e e', ~X.eq x y -> MapsTo y e (add x e' m) -> MapsTo y e m.
Lemma add_find : forall m x y e, bst m -> find y (add x e m) = match X.compare y x with EQ _ => Some e | _ => find y m end.
Lemma remove_min_in : forall l x e r h y, In y (Node l x e r h) <-> X.eq y (remove_min l x e r)#2#1 \/ In y (remove_min l x e r)#1.
Lemma remove_min_mapsto : forall l x e r h y e', MapsTo y e' (Node l x e r h) <-> ((X.eq y (remove_min l x e r)#2#1) /\ e' = (remove_min l x e r)#2#2) \/ MapsTo y e' (remove_min l x e r)#1.
Lemma remove_min_bst : forall l x e r h, bst (Node l x e r h) -> bst (remove_min l x e r)#1.
Lemma remove_min_gt_tree : forall l x e r h, bst (Node l x e r h) -> gt_tree (remove_min l x e r)#2#1 (remove_min l x e r)#1.
Lemma remove_min_find : forall l x e r h y, bst (Node l x e r h) -> find y (Node l x e r h) = match X.compare y (remove_min l x e r)#2#1 with | LT _ => None | EQ _ => Some (remove_min l x e r)#2#2 | GT _ => find y (remove_min l x e r)#1 end.
Lemma merge_in : forall m1 m2 y, bst m1 -> bst m2 -> (In y (merge m1 m2) <-> In y m1 \/ In y m2).
Lemma merge_mapsto : forall m1 m2 y e, bst m1 -> bst m2 -> (MapsTo y e (merge m1 m2) <-> MapsTo y e m1 \/ MapsTo y e m2).
Lemma merge_bst : forall m1 m2, bst m1 -> bst m2 -> (forall y1 y2 : key, In y1 m1 -> In y2 m2 -> X.lt y1 y2) -> bst (merge m1 m2).
Lemma remove_in : forall m x y, bst m -> (In y (remove x m) <-> ~ X.eq y x /\ In y m).
Lemma remove_bst : forall m x, bst m -> bst (remove x m).
Lemma remove_1 : forall m x y, bst m -> X.eq x y -> ~ In y (remove x m).
Lemma remove_2 : forall m x y e, bst m -> ~X.eq x y -> MapsTo y e m -> MapsTo y e (remove x m).
Lemma remove_3 : forall m x y e, bst m -> MapsTo y e (remove x m) -> MapsTo y e m.
Lemma join_in : forall l x d r y, In y (join l x d r) <-> X.eq y x \/ In y l \/ In y r.
Lemma join_bst : forall l x d r, bst l -> bst r -> lt_tree x l -> gt_tree x r -> bst (join l x d r).
Lemma join_find : forall l x d r y, bst l -> bst r -> lt_tree x l -> gt_tree x r -> find y (join l x d r) = find y (create l x d r).
Lemma split_in_1 : forall m x, bst m -> forall y, (In y (split x m)#l <-> In y m /\ X.lt y x).
Lemma split_in_2 : forall m x, bst m -> forall y, (In y (split x m)#r <-> In y m /\ X.lt x y).
Lemma split_in_3 : forall m x, bst m -> (split x m)#o = find x m.
Lemma split_bst : forall m x, bst m -> bst (split x m)#l /\ bst (split x m)#r.
Lemma split_lt_tree : forall m x, bst m -> lt_tree x (split x m)#l.
Lemma split_gt_tree : forall m x, bst m -> gt_tree x (split x m)#r.
Lemma split_find : forall m x y, bst m -> find y m = match X.compare y x with | LT _ => find y (split x m)#l | EQ _ => (split x m)#o | GT _ => find y (split x m)#r end.
Lemma concat_in : forall m1 m2 y, In y (concat m1 m2) <-> In y m1 \/ In y m2.
Lemma concat_bst : forall m1 m2, bst m1 -> bst m2 -> (forall y1 y2, In y1 m1 -> In y2 m2 -> X.lt y1 y2) -> bst (concat m1 m2).
Lemma concat_find : forall m1 m2 y, bst m1 -> bst m2 -> (forall y1 y2, In y1 m1 -> In y2 m2 -> X.lt y1 y2) -> find y (concat m1 m2) = match find y m2 with Some d => Some d | None => find y m1 end.