(***************************************************************************)

Inductive lin_ins_spec (key : Int) (update : B -> B) 
(init : B) (t0 t : avl_tree) : Prop :=
  | Lin_Ins_New :
      forall l0 l1 : list (Int * B),
      lin_avl t0 = l0 ++ l1 ->
      lin_avl t = l0 ++ (key, update init) :: l1 ->
      lin_ins_spec key update init t0 t
  | Lin_Ins_Update :
      forall (d : B) (l0 l1 : list (Int * B)),
      lin_avl t0 = l0 ++ (key, d) :: l1 ->
      lin_avl t = l0 ++ (key, update d) :: l1 ->
      lin_ins_spec key update init t0 t.(***************************************************************************)

Inductive lin_ins_spec (key : Int) (update : B -> B) 
(init : B) (t0 t : avl_tree) : Prop :=
  | Lin_Ins_New :
      forall l0 l1 : list (Int * B),
      lin_avl t0 = l0 ++ l1 ->
      lin_avl t = l0 ++ (key, update init) :: l1 ->
      lin_ins_spec key update init t0 t
  | Lin_Ins_Update :
      forall (d : B) (l0 l1 : list (Int * B)),
      lin_avl t0 = l0 ++ (key, d) :: l1 ->
      lin_avl t = l0 ++ (key, update d) :: l1 ->
      lin_ins_spec key update init t0 t.(***************************************************************************)

Inductive lin_ins_spec (key : Int) (update : B -> B) 
(init : B) (t0 t : avl_tree) : Prop :=
  | Lin_Ins_New :
      forall l0 l1 : list (Int * B),
      lin_avl t0 = l0 ++ l1 ->
      lin_avl t = l0 ++ (key, update init) :: l1 ->
      lin_ins_spec key update init t0 t
  | Lin_Ins_Update :
      forall (d : B) (l0 l1 : list (Int * B)),
      lin_avl t0 = l0 ++ (key, d) :: l1 ->
      lin_avl t = l0 ++ (key, update d) :: l1 ->
      lin_ins_spec key update init t0 t.Inductive avl_ins_spec (key : Int) (update : B -> B) 
(init : B) (t0 : avl_tree) : Set :=
    Avl_Ins_Spec_Intro :
      forall t : avl_tree,
      lookup_dec_spec key t0 ->
      is_avl t ->
      lin_ins_spec key update init t0 t ->
      equiv_ins key update init t0 t ->
      {height_avl t = height_avl t0} + {height_avl t = S (height_avl t0)} ->
      avl_ins_spec key update init t0.Inductive avl_ins_spec (key : Int) (update : B -> B) 
(init : B) (t0 : avl_tree) : Set :=
    Avl_Ins_Spec_Intro :
      forall t : avl_tree,
      lookup_dec_spec key t0 ->
      is_avl t ->
      lin_ins_spec key update init t0 t ->
      equiv_ins key update init t0 t ->
      {height_avl t = height_avl t0} + {height_avl t = S (height_avl t0)} ->
      avl_ins_spec key update init t0.

(* Specifications: *)
Lemma insert_avl : forall (key : Int) (update : B -> B) (init : B) (t0 : avl_tree), is_avl t0 -> avl_ins_spec key update init t0.