Definition key := Key.A.Definition data := Val.data.Module M := More_Dec_Orders Key.(* search trees definitions and properties *)

 (* the underlying data structure : binary trees labeled 
    with keys and associated values *)

 Inductive btree : Set :=
   | leaf : btree
   | bnode : key -> data -> btree -> btree -> btree.(* search trees definitions and properties *)

 (* the underlying data structure : binary trees labeled 
    with keys and associated values *)

 Inductive btree : Set :=
   | leaf : btree
   | bnode : key -> data -> btree -> btree -> btree.(* search trees definitions and properties *)

 (* the underlying data structure : binary trees labeled 
    with keys and associated values *)

 Inductive btree : Set :=
   | leaf : btree
   | bnode : key -> data -> btree -> btree -> btree.(* The entry with key k and value v occurs in the binary tree t *)

 Inductive occ (v : data) (k : key) : btree -> Prop :=
   | occ_root : forall t1 t2 : btree, occ v k (bnode k v t1 t2)
   | occ_l :
       forall (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t1 -> occ v k (bnode k' v' t1 t2)
   | occ_r :
       forall (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t2 -> occ v k (bnode k' v' t1 t2).(* The entry with key k and value v occurs in the binary tree t *)

 Inductive occ (v : data) (k : key) : btree -> Prop :=
   | occ_root : forall t1 t2 : btree, occ v k (bnode k v t1 t2)
   | occ_l :
       forall (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t1 -> occ v k (bnode k' v' t1 t2)
   | occ_r :
       forall (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t2 -> occ v k (bnode k' v' t1 t2).(* The entry with key k and value v occurs in the binary tree t *)

 Inductive occ (v : data) (k : key) : btree -> Prop :=
   | occ_root : forall t1 t2 : btree, occ v k (bnode k v t1 t2)
   | occ_l :
       forall (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t1 -> occ v k (bnode k' v' t1 t2)
   | occ_r :
       forall (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t2 -> occ v k (bnode k' v' t1 t2).(* The entry with key k and value v occurs in the binary tree t *)

 Inductive occ (v : data) (k : key) : btree -> Prop :=
   | occ_root : forall t1 t2 : btree, occ v k (bnode k v t1 t2)
   | occ_l :
       forall (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t1 -> occ v k (bnode k' v' t1 t2)
   | occ_r :
       forall (k' : key) (v' : data) (t1 t2 : btree),
       occ v k t2 -> occ v k (bnode k' v' t1 t2).(*  key k is less than every key in t  *)
 Inductive min (k : key) (t : btree) : Prop :=
     min_intro :
       (forall (k' : key) (v : data), occ v k' t -> Key.lt k k') -> min k t.(*  key k is less than every key in t  *)
 Inductive min (k : key) (t : btree) : Prop :=
     min_intro :
       (forall (k' : key) (v : data), occ v k' t -> Key.lt k k') -> min k t.(*  key k is gretaer than every key in t  *)
 Inductive maj (k : key) (t : btree) : Prop :=
     maj_intro :
       (forall (k' : key) (v : data), occ v k' t -> Key.lt k' k) -> maj k t.(*  key k is gretaer than every key in t  *)
 Inductive maj (k : key) (t : btree) : Prop :=
     maj_intro :
       (forall (k' : key) (v : data), occ v k' t -> Key.lt k' k) -> maj k t.(* searchness predicate on binary trees *)
 Inductive search_tree : btree -> Prop :=
   | leaf_search_tree : search_tree leaf
   | bnode_search_tree :
       forall (k : key) (v : data) (t1 t2 : btree),
       search_tree t1 ->
       search_tree t2 ->
       maj k t1 -> min k t2 -> search_tree (bnode k v t1 t2).(* searchness predicate on binary trees *)
 Inductive search_tree : btree -> Prop :=
   | leaf_search_tree : search_tree leaf
   | bnode_search_tree :
       forall (k : key) (v : data) (t1 t2 : btree),
       search_tree t1 ->
       search_tree t2 ->
       maj k t1 -> min k t2 -> search_tree (bnode k v t1 t2).(* searchness predicate on binary trees *)
 Inductive search_tree : btree -> Prop :=
   | leaf_search_tree : search_tree leaf
   | bnode_search_tree :
       forall (k : key) (v : data) (t1 t2 : btree),
       search_tree t1 ->
       search_tree t2 ->
       maj k t1 -> min k t2 -> search_tree (bnode k v t1 t2).Inductive is_bnode : btree -> Prop :=
     is_bnode_intro :
       forall (k : key) (v : data) (t1 t2 : btree),
       is_bnode (bnode k v t1 t2).Inductive is_bnode : btree -> Prop :=
     is_bnode_intro :
       forall (k : key) (v : data) (t1 t2 : btree),
       is_bnode (bnode k v t1 t2).Derive Inversion_clear OCC_INV with
  (forall (k k' : key) (v v' : data) (t1 t2 : btree),
   occ v' k' (bnode k v t1 t2)).

(* Specifications: *)
Lemma occ_inv : forall (k k' : key) (v v' : data) (t1 t2 : btree), occ v' k' (bnode k v t1 t2) -> k = k' /\ v = v' \/ occ v' k' t1 \/ occ v' k' t2.
Lemma not_occ_Leaf : forall (k : key) (v : data), ~ occ v k leaf.
Lemma min_leaf : forall k : key, min k leaf.
Lemma maj_leaf : forall k : key, maj k leaf.
Lemma maj_not_occ : forall (k : key) (v : data) (t : btree), maj k t -> ~ occ v k t.
Lemma min_not_occ : forall (k : key) (v : data) (t : btree), min k t -> ~ occ v k t.
Lemma search_tree_l : search_tree t1.
Lemma search_tree_r : search_tree t2.
Lemma maj_l : maj n t1.
Lemma min_r : min n t2.
Lemma not_right : forall (p : key) (v' : data), Key.le p n -> ~ occ v' p t2.
Lemma not_left : forall (p : key) (v' : data), Key.le n p -> ~ occ v' p t1.
Lemma go_left : forall (p : key) (v' : data), occ v' p (bnode n v t1 t2) -> Key.lt p n -> occ v' p t1.
Lemma go_right : forall (p : key) (v' : data), occ v' p (bnode n v t1 t2) -> Key.lt n p -> occ v' p t2.
Lemma occ_unicity : forall t : btree, search_tree t -> forall (k : key) (v v' : data), occ v k t -> occ v' k t -> v = v'.