intros key update init k0 d0 l0 r0 b0 r b avl_t0 less equiv_r0.
inversion_clear equiv_r0.
apply equiv_ins_intro.
intros k data equal lookup_t0.
apply Lookup_Right.
apply H.
assumption.
apply (lookup_avl_inv_greater k k0 d0 l0 r0 b0 data); try assumption.
apply (less_equal_less k0 key k).
assumption.
apply equal_sym; assumption.
intros k equal not_lookup_t0.
apply Lookup_Right.
apply H0.
assumption.
intros data lookup_l0.
apply (not_lookup_t0 data).
apply Lookup_Right; assumption.
intros k data notequal lookup_t0.
inversion_clear lookup_t0.
apply Lookup_Equal.
apply Lookup_Left; assumption.
apply Lookup_Right.
apply H1; assumption.
intros k data notequal lookup_t.
inversion_clear lookup_t.
apply Lookup_Equal.
apply Lookup_Left; assumption.
apply Lookup_Right.
apply H2; assumption.
Qed.
(***************************************************************************)
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.
(***************************************************************************)
(***************************************************************************)

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