intros k d l r b avl_l below_avl_l avl_r above_avl_r bal_or_shift.
elim bal_or_shift; clear bal_or_shift.
(* l and r is Balanced with respect to b *)
intro Balanced_l.
apply Balance_Grow_Right_Spec_Intro with (Avl_Node k d l r b).
apply Node_Is_Avl; assumption.
trivial.
apply equiv_refl.
left.
apply Hasnot_Grown_Right_Bal.
assumption.
trivial.
(* l and r is'nt Balanced with respect to b *)
elim b; clear b; intros Balanced_shift_l.
(* b=Left_Balanced *)
apply Balance_Grow_Right_Spec_Intro with (Avl_Node k d l r Balanced).
apply Node_Is_Avl; try assumption.
apply Is_Fully_Balanced_Avl.
inversion_clear Balanced_shift_l; assumption.
trivial.
apply equiv_refl.
left.
simpl in |- *.
apply Hasnot_Grown_Right_Shift_Left.
assumption.
simpl in |- *.
inversion_clear Balanced_shift_l.
rewrite H; trivial.
(* b=Balanced *)
apply Balance_Grow_Right_Spec_Intro with (Avl_Node k d l r Right_Balanced).
apply Node_Is_Avl; try assumption.
apply Is_Right_Balanced_Avl.
inversion_clear Balanced_shift_l; assumption.
trivial.
apply equiv_refl.
right.
apply Has_Grown_Right_Shift_Balanced.
assumption.
trivial.
(* b=Right_Balanced *)
elim (rebalance_right k d l r Right_Balanced); try assumption.
intros t (avl_t,(lin,(equiv_t,height_t))).
apply Balance_Grow_Right_Spec_Intro with t.
assumption.
assumption.
assumption.
clear lin equiv_t avl_l below_avl_l avl_r above_avl_r.
generalize height_t; clear height_t.
generalize Balanced_shift_l; clear Balanced_shift_l.
case r; clear r.
intro u0.
elimtype False.
inversion_clear u0.
discriminate H.
intros kr dr lr rr br.
elim br; clear br; simpl in |- *; intros Balanced_shift_l height_t.
(* br=Left_Balanced *)
left.
apply Hasnot_Grown_Right_Shift_Right; assumption.
(* br=Balanced *)
right.
apply Has_Grown_Right_Shift_Right; assumption.
(* br=Right_Balanced *)
left.
apply Hasnot_Grown_Right_Shift_Right; assumption.
(* side premisses of (Elim (rebalance ... )) *)
inversion_clear Balanced_shift_l; assumption.
Qed.
(*********************************************************************)
(*  equiv_ins                                                        *)
Inductive equiv_ins (key : Int) (update : B -> B) (init : B)
(t0 t : avl_tree) : Prop :=
equiv_ins_intro :
(forall (k : Int) (data : B),
Equal k key -> lookup k t0 data -> lookup k t (update data)) ->
(forall k : Int,
Equal k key ->
(forall data : B, lookup k t0 data -> False) ->
lookup k t (update init)) ->
(forall (k : Int) (data : B),
~ Equal k key -> lookup k t0 data -> lookup k t data) ->
(forall (k : Int) (data : B),
~ Equal k key -> lookup k t data -> lookup k t0 data) ->
equiv_ins key update init t0 t.

(* Specifications: *)
Lemma inv_equiv_ins_equal0 :
forall (key : Int) (update : B -> B) (init : B) (t0 t : avl_tree)
(k : Int) (data : B),
equiv_ins key update init t0 t ->
Equal k key -> lookup k t0 data -> lookup k t (update data).