(* File: AvlTrees.v  (last edited on 25/10/2000) (c) Klaus Weich  *)

Require Import ML_Int.
Require Import My_Arith.
Require Import List.

Global Set Asymmetric Patterns.

Section avl_trees.

Variable B : Set.


(*********************************************************)
(*		Definition bal and avl_tree	  	 *)

Inductive bal : Set :=
  | Left_Balanced : bal
  | Balanced : bal
  | Right_Balanced : bal.

Inductive avl_tree : Set :=
  | Avl_Nil : avl_tree
  | Avl_Node : Int -> B -> avl_tree -> avl_tree -> bal -> avl_tree.



(*********************************************************)
(*		Definition is_below		  	 *)


Inductive is_below : avl_tree -> Int -> Prop :=
  | Below_Nil : forall k0 : Int, is_below Avl_Nil k0
  | Below_Node :
      forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
      Less k k0 ->
      is_below l k0 -> is_below r k0 -> is_below (Avl_Node k d l r b) k0.

Lemma inv_below_key :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_below (Avl_Node k d l r b) k0 -> Less k k0.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_below_left :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_below (Avl_Node k d l r b) k0 -> is_below l k0.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_below_right :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_below (Avl_Node k d l r b) k0 -> is_below r k0.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.


Lemma below_trans :
 forall (t : avl_tree) (k0 k1 : Int),
 is_below t k0 -> Less k0 k1 -> is_below t k1.
(* Goal: forall (t : avl_tree) (_ : @eq nat (height_avl t) O), @eq avl_tree t Avl_Nil *)
intros t; elim t; clear t.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_below Avl_Nil k0 *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a d), Less k k0), is_below a k0) (a0 : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a0 d), Less k k0), is_below a0 k0) (b0 : bal) (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k (Avl_Node i b a a0 b0) d), Less k k0), is_below (Avl_Node i b a a0 b0) k0 *)
apply Below_Nil.
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 k1 : Int) (_ : is_above_avl a k0) (_ : Less k1 k0), is_above_avl a k1) (a0 : avl_tree) (_ : forall (k0 k1 : Int) (_ : is_above_avl a0 k0) (_ : Less k1 k0), is_above_avl a0 k1) (b0 : bal) (k0 k1 : Int) (_ : is_above_avl (Avl_Node i b a a0 b0) k0) (_ : Less k1 k0), is_above_avl (Avl_Node i b a a0 b0) k1 *)
intros k d l ih_l r ih_r b k0 k1 H0 H1.
(* Goal: is_below (Avl_Node k0 d0 l0 r b0) k *)
(* Goal: Less k0 k *)
(* Goal: equiv t (Avl_Node k0 d0 l0 r b0) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (@app (prod Int B) (lin_avl t) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))) *)
(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply Below_Node.
(* Goal: Less k k1 *)
(* Goal: is_below_avl r k1 *)
apply (less_trans k k0 k1).
(* Goal: Less k k0 *)
(* Goal: Less k0 k1 *)
(* Goal: is_below l k1 *)
(* Goal: is_below r k1 *)
apply (inv_below_key k d l r b k0 H0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below l k1 *)
(* Goal: is_below r k1 *)
apply (ih_l k0 k1 (inv_below_left k d l r b k0 H0) H1).
(* Goal: is_below r k1 *)
apply (ih_r k0 k1 (inv_below_right k d l r b k0 H0) H1).
Qed.



(*********************************************************)
(*		Definition is_above		  	 *)

Inductive is_above : avl_tree -> Int -> Prop :=
  | Above_Nil : forall k0 : Int, is_above Avl_Nil k0
  | Above_Node :
      forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
      Less k0 k ->
      is_above l k0 -> is_above r k0 -> is_above (Avl_Node k d l r b) k0.

Lemma inv_above_key :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_above (Avl_Node k d l r b) k0 -> Less k0 k.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_above_left :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_above (Avl_Node k d l r b) k0 -> is_above l k0.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_above_right :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_above (Avl_Node k d l r b) k0 -> is_above r k0.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.


Lemma above_trans :
 forall (t : avl_tree) (k0 k1 : Int),
 is_above t k0 -> Less k1 k0 -> is_above t k1.
(* Goal: forall (t : avl_tree) (_ : @eq nat (height_avl t) O), @eq avl_tree t Avl_Nil *)
intros t; elim t; clear t.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above Avl_Nil k0 *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a d), Less k0 k), is_above a k0) (a0 : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a0 d), Less k0 k), is_above a0 k0) (b0 : bal) (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k (Avl_Node i b a a0 b0) d), Less k0 k), is_above (Avl_Node i b a a0 b0) k0 *)
apply Above_Nil.
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 k1 : Int) (_ : is_above_avl a k0) (_ : Less k1 k0), is_above_avl a k1) (a0 : avl_tree) (_ : forall (k0 k1 : Int) (_ : is_above_avl a0 k0) (_ : Less k1 k0), is_above_avl a0 k1) (b0 : bal) (k0 k1 : Int) (_ : is_above_avl (Avl_Node i b a a0 b0) k0) (_ : Less k1 k0), is_above_avl (Avl_Node i b a a0 b0) k1 *)
intros k d l ih_l r ih_r b k0 k1 H0 H1.
(* Goal: is_above (Avl_Node k d l r b) k0 *)
apply Above_Node.
(* Goal: Less k1 k *)
(* Goal: is_above_avl l k1 *)
apply (less_trans k1 k0 k H1).
(* Goal: Less k0 k *)
(* Goal: is_above l k1 *)
(* Goal: is_above r k1 *)
apply (inv_above_key k d l r b k0 H0).
(* Goal: is_above l k1 *)
(* Goal: is_above r k1 *)
apply (ih_l k0 k1 (inv_above_left k d l r b k0 H0) H1).
(* Goal: is_above r k1 *)
apply (ih_r k0 k1 (inv_above_right k d l r b k0 H0) H1).
Qed.



(*********************************************************)
(*		Definition height         	  	 *)

Fixpoint height (t : avl_tree) : nat :=
  match t with
  | Avl_Nil => 0
  | Avl_Node _ _ l r _ => S (max (height l) (height r))
  end.


Lemma height_O_nil : forall t : avl_tree, height t = 0 -> t = Avl_Nil.
(* Goal: forall (t : avl_tree) (_ : @eq nat (height_avl t) O), @eq avl_tree t Avl_Nil *)
intros t; elim t; clear t.
(* Goal: forall _ : @eq nat (height_avl Avl_Nil) O, @eq avl_tree Avl_Nil Avl_Nil *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : @eq nat (height_avl a) O, @eq avl_tree a Avl_Nil) (a0 : avl_tree) (_ : forall _ : @eq nat (height_avl a0) O, @eq avl_tree a0 Avl_Nil) (b0 : bal) (_ : @eq nat (height_avl (Avl_Node i b a a0 b0)) O), @eq avl_tree (Avl_Node i b a a0 b0) Avl_Nil *)
intros; trivial.
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : @eq nat (height_avl a) O, @eq avl_tree a Avl_Nil) (a0 : avl_tree) (_ : forall _ : @eq nat (height_avl a0) O, @eq avl_tree a0 Avl_Nil) (b0 : bal) (_ : @eq nat (height_avl (Avl_Node i b a a0 b0)) O), @eq avl_tree (Avl_Node i b a a0 b0) Avl_Nil *)
intros k d l ih_l r ih_r b.
simpl in |- *; intro u0;  discriminate u0.
Qed.


(*********************************************************)
(*		Definition is_balanced		  	 *)


Inductive is_balanced (l r : avl_tree) : bal -> Prop :=
  | Is_Left_Balanced :
      height l = S (height r) -> is_balanced l r Left_Balanced
  | Is_Fully_Balanced : height l = height r -> is_balanced l r Balanced
  | Is_Right_Balanced :
      S (height l) = height r -> is_balanced l r Right_Balanced.


Lemma inv_left_balanced :
 forall l r : avl_tree,
 is_balanced l r Left_Balanced -> height l = S (height r).
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_fully_balanced :
 forall l r : avl_tree, is_balanced l r Balanced -> height l = height r.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_right_balanced :
 forall l r : avl_tree,
 is_balanced l r Right_Balanced -> S (height l) = height r.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.


(************************************************************************)
(* lookup                                                               *)


Inductive lookup (key : Int) : avl_tree -> B -> Prop :=
  | Lookup_Equal :
      forall (d : B) (l r : avl_tree) (b : bal),
      lookup key (Avl_Node key d l r b) d
  | Lookup_Left :
      forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B),
      lookup key l data -> lookup key (Avl_Node k d l r b) data
  | Lookup_Right :
      forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B),
      lookup key r data -> lookup key (Avl_Node k d l r b) data.


Lemma inv_lookup_nil :
 forall (key : Int) (data : B), lookup key Avl_Nil data -> False.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: lookup k t0 d *)
inversion H.
Qed.

Lemma inv_lookup :
 forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B),
 lookup key (Avl_Node k d l r b) data ->
 k = key /\ d = data \/ lookup key l data \/ lookup key r data.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: or (and (@eq Int k k) (@eq B data data)) (or (lookup k l data) (lookup k r data)) *)
(* Goal: or (and (@eq Int k key) (@eq B d data)) (or (lookup key l data) (lookup key r data)) *)
(* Goal: or (and (@eq Int k key) (@eq B d data)) (or (lookup key l data) (lookup key r data)) *)
left; split; trivial.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
right; left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
right; right; assumption.
Qed.

(*******************************************************)
(* Lemmata about Lookup and below/above                *)

Lemma lookup_below_less :
 forall (key : Int) (t : avl_tree) (data : B) (k0 : Int),
 lookup key t data -> is_below t k0 -> Less key k0.
(* Goal: forall (key : Int) (t : avl_tree) (data : B) (k0 : Int) (_ : lookup key t data) (_ : is_above t k0), Less k0 key *)
intros key t; elim t; clear t.
(* Goal: forall (data : B) (k0 : Int) (_ : lookup key Avl_Nil data) (_ : is_below Avl_Nil k0), Less key k0 *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a data) (_ : is_below a k0), Less key k0) (a0 : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a0 data) (_ : is_below a0 k0), Less key k0) (b0 : bal) (data : B) (k0 : Int) (_ : lookup key (Avl_Node i b a a0 b0) data) (_ : is_below (Avl_Node i b a a0 b0) k0), Less key k0 *)
intros data k0 lookup_t below_t.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a data) (_ : is_above a k0), Less k0 key) (a0 : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a0 data) (_ : is_above a0 k0), Less k0 key) (b0 : bal) (data : B) (k0 : Int) (_ : lookup key (Avl_Node i b a a0 b0) data) (_ : is_above (Avl_Node i b a a0 b0) k0), Less k0 key *)
apply (inv_lookup_nil key data lookup_t).
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a data) (_ : is_below a k0), Less key k0) (a0 : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a0 data) (_ : is_below a0 k0), Less key k0) (b0 : bal) (data : B) (k0 : Int) (_ : lookup key (Avl_Node i b a a0 b0) data) (_ : is_below (Avl_Node i b a a0 b0) k0), Less key k0 *)
intros k d l ih_l r ih_r b data k0 lookup_t below_t.
(* Goal: lookup key r data *)
elim (inv_lookup key k d l r b data lookup_t); clear lookup_t; intro u0.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: Equal k0 key *)
(* Goal: lookup k0 (Avl_Node k d l0 r0 b) data *)
 rewrite <- u0.
(* Goal: Less k k0 *)
(* Goal: Less key k0 *)
apply (inv_below_key k d l r b k0 below_t).

(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.
(* Goal: Less k0 key *)
(* Goal: Less k0 key *)
apply (ih_l data).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below l k0 *)
(* Goal: Less key k0 *)
apply (inv_below_left k d l r b k0 below_t).

(* Goal: Less k0 key *)
apply (ih_r data).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below r k0 *)
apply (inv_below_right k d l r b k0 below_t).
Qed.


Lemma lookup_above_greater :
 forall (key : Int) (t : avl_tree) (data : B) (k0 : Int),
 lookup key t data -> is_above t k0 -> Less k0 key.
(* Goal: forall (key : Int) (t : avl_tree) (data : B) (k0 : Int) (_ : lookup key t data) (_ : is_above t k0), Less k0 key *)
intros key t; elim t; clear t.
(* Goal: forall (data : B) (k0 : Int) (_ : lookup key Avl_Nil data) (_ : is_above Avl_Nil k0), Less k0 key *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a data) (_ : is_above a k0), Less k0 key) (a0 : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a0 data) (_ : is_above a0 k0), Less k0 key) (b0 : bal) (data : B) (k0 : Int) (_ : lookup key (Avl_Node i b a a0 b0) data) (_ : is_above (Avl_Node i b a a0 b0) k0), Less k0 key *)
intros data k0 lookup_t above_t.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a data) (_ : is_above a k0), Less k0 key) (a0 : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a0 data) (_ : is_above a0 k0), Less k0 key) (b0 : bal) (data : B) (k0 : Int) (_ : lookup key (Avl_Node i b a a0 b0) data) (_ : is_above (Avl_Node i b a a0 b0) k0), Less k0 key *)
apply (inv_lookup_nil key data lookup_t).
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a data) (_ : is_above a k0), Less k0 key) (a0 : avl_tree) (_ : forall (data : B) (k0 : Int) (_ : lookup key a0 data) (_ : is_above a0 k0), Less k0 key) (b0 : bal) (data : B) (k0 : Int) (_ : lookup key (Avl_Node i b a a0 b0) data) (_ : is_above (Avl_Node i b a a0 b0) k0), Less k0 key *)
intros k d l ih_l r ih_r b data k0 lookup_t above_t.
(* Goal: lookup key r data *)
elim (inv_lookup key k d l r b data lookup_t); clear lookup_t; intro u0.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: Equal k0 key *)
(* Goal: lookup k0 (Avl_Node k d l0 r0 b) data *)
 rewrite <- u0.
(* Goal: Less k0 k *)
(* Goal: Less k0 key *)
apply (inv_above_key k d l r b k0 above_t).

(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.
(* Goal: Less k0 key *)
(* Goal: Less k0 key *)
apply (ih_l data).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_above l k0 *)
(* Goal: Less k0 key *)
apply (inv_above_left k d l r b k0 above_t).

(* Goal: Less k0 key *)
apply (ih_r data).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_above r k0 *)
apply (inv_above_right k d l r b k0 above_t).
Qed.


Lemma lookup_less_below :
 forall (t : avl_tree) (k0 : Int),
 (forall (k : Int) (d : B), lookup k t d -> Less k k0) -> is_below t k0.
(* Goal: forall (t : avl_tree) (_ : @eq nat (height_avl t) O), @eq avl_tree t Avl_Nil *)
intros t; elim t; clear t.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_below Avl_Nil k0 *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a d), Less k k0), is_below a k0) (a0 : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a0 d), Less k k0), is_below a0 k0) (b0 : bal) (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k (Avl_Node i b a a0 b0) d), Less k k0), is_below (Avl_Node i b a a0 b0) k0 *)
apply Below_Nil.
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a d), Less k0 k), is_above a k0) (a0 : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a0 d), Less k0 k), is_above a0 k0) (b0 : bal) (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k (Avl_Node i b a a0 b0) d), Less k0 k), is_above (Avl_Node i b a a0 b0) k0 *)
intros k d l ih_l r ih_r b k0 H.
(* Goal: is_below (Avl_Node k0 d0 l0 r b0) k *)
(* Goal: Less k0 k *)
(* Goal: equiv t (Avl_Node k0 d0 l0 r b0) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (@app (prod Int B) (lin_avl t) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))) *)
(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply Below_Node.
(* Goal: Less k0 k *)
(* Goal: is_above l k0 *)
(* Goal: is_above r k0 *)
apply (H k d).
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: is_below l k0 *)
(* Goal: is_below r k0 *)
apply ih_l.
(* Goal: forall (k : Int) (d : B) (_ : lookup k l d), Less k0 k *)
(* Goal: is_above r k0 *)
intros k1 d0 lookup_l.
(* Goal: Less k0 k1 *)
apply (H k1 d0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: is_above r k0 *)
apply ih_r.
(* Goal: forall (k : Int) (d : B) (_ : lookup k r d), Less k0 k *)
intros k1 d0 lookup_r.
(* Goal: Less k0 k1 *)
apply (H k1 d0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
Qed.


Lemma lookup_greater_above :
 forall (t : avl_tree) (k0 : Int),
 (forall (k : Int) (d : B), lookup k t d -> Less k0 k) -> is_above t k0.
(* Goal: forall (t : avl_tree) (_ : @eq nat (height_avl t) O), @eq avl_tree t Avl_Nil *)
intros t; elim t; clear t.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above Avl_Nil k0 *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a d), Less k0 k), is_above a k0) (a0 : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a0 d), Less k0 k), is_above a0 k0) (b0 : bal) (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k (Avl_Node i b a a0 b0) d), Less k0 k), is_above (Avl_Node i b a a0 b0) k0 *)
apply Above_Nil.
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a d), Less k0 k), is_above a k0) (a0 : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a0 d), Less k0 k), is_above a0 k0) (b0 : bal) (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k (Avl_Node i b a a0 b0) d), Less k0 k), is_above (Avl_Node i b a a0 b0) k0 *)
intros k d l ih_l r ih_r b k0 H.
(* Goal: is_above (Avl_Node k d l r b) k0 *)
apply Above_Node.
(* Goal: Less k0 k *)
(* Goal: is_above l k0 *)
(* Goal: is_above r k0 *)
apply (H k d).
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: is_below l k0 *)
(* Goal: is_below r k0 *)
apply ih_l.
(* Goal: forall (k : Int) (d : B) (_ : lookup k l d), Less k0 k *)
(* Goal: is_above r k0 *)
intros k1 d0 lookup_l.
(* Goal: Less k0 k1 *)
apply (H k1 d0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: is_above r k0 *)
apply ih_r.
(* Goal: forall (k : Int) (d : B) (_ : lookup k r d), Less k0 k *)
intros k1 d0 lookup_r.
(* Goal: Less k0 k1 *)
apply (H k1 d0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
Qed.



Lemma lookup_above_lookup :
 forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B),
 lookup key (Avl_Node k d l r b) data ->
 Less key k -> is_above r key -> lookup key l data.
(* Goal: forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B) (_ : lookup key (Avl_Node k d l r b) data) (_ : Less key k) (_ : is_above r key), lookup key l data *)
intros key k d l r b data lookup_t less above_r.
(* Goal: lookup key r data *)
elim (inv_lookup key k d l r b data lookup_t); clear lookup_t; intro u0.

(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: False *)
apply less_irrefl with key.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite u0 in less.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
apply less_irrefl with key.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply lookup_above_greater with r data; assumption.
Qed.




Lemma lookup_below_lookup :
 forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B),
 lookup key (Avl_Node k d l r b) data ->
 Less k key -> is_below l key -> lookup key r data.
(* Goal: forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B) (_ : lookup key (Avl_Node k d l r b) data) (_ : Less k key) (_ : is_below l key), lookup key r data *)
intros key k d l r b data lookup_t less below_l.
(* Goal: lookup key r data *)
elim (inv_lookup key k d l r b data lookup_t); clear lookup_t; intro u0.

(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: False *)
apply less_irrefl with key.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite u0 in less.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.

(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
apply less_irrefl with key.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply lookup_below_less with l data; assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.

Lemma lookup_below_false :
 forall (key : Int) (t : avl_tree) (data : B),
 lookup key t data -> is_below t key -> False.
(* Goal: forall (key : Int) (t : avl_tree) (data : B) (_ : lookup key t data) (_ : is_below t key), False *)
intros key t data lookup_t below_t.
(* Goal: False *)
apply less_irrefl with key.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply lookup_below_less with t data; assumption.
Qed.



Lemma lookup_above_false :
 forall (key : Int) (t : avl_tree) (data : B),
 lookup key t data -> is_above t key -> False.
(* Goal: forall (key : Int) (t : avl_tree) (data : B) (_ : lookup key t data) (_ : is_above t key), False *)
intros key t data lookup_t above_t.
(* Goal: False *)
apply less_irrefl with key.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply lookup_above_greater with t data; assumption.
Qed.




(*********************************************************)
(*		Definition is_below_avl		  	 *)


Inductive is_below_avl : avl_tree -> Int -> Prop :=
  | Below_Avl_Nil : forall k0 : Int, is_below_avl Avl_Nil k0
  | Below_Avl_Node :
      forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
      Less k k0 -> is_below_avl r k0 -> is_below_avl (Avl_Node k d l r b) k0.

Lemma inv_below_avl_key :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_below_avl (Avl_Node k d l r b) k0 -> Less k k0.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_below_avl_right :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_below_avl (Avl_Node k d l r b) k0 -> is_below_avl r k0.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.


Lemma below_avl_trans :
 forall (t : avl_tree) (k0 k1 : Int),
 is_below_avl t k0 -> Less k0 k1 -> is_below_avl t k1.
(* Goal: forall (t : avl_tree) (_ : @eq nat (height_avl t) O), @eq avl_tree t Avl_Nil *)
intros t; elim t; clear t.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_below_avl Avl_Nil k *)
(* Goal: is_above_avl Avl_Nil k *)
apply Below_Avl_Nil.
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 k1 : Int) (_ : is_above_avl a k0) (_ : Less k1 k0), is_above_avl a k1) (a0 : avl_tree) (_ : forall (k0 k1 : Int) (_ : is_above_avl a0 k0) (_ : Less k1 k0), is_above_avl a0 k1) (b0 : bal) (k0 k1 : Int) (_ : is_above_avl (Avl_Node i b a a0 b0) k0) (_ : Less k1 k0), is_above_avl (Avl_Node i b a a0 b0) k1 *)
intros k d l ih_l r ih_r b k0 k1 H0 H1.
(* Goal: is_below_avl (Avl_Node k d l r b) key *)
apply Below_Avl_Node.
(* Goal: Less k k1 *)
(* Goal: is_below_avl r k1 *)
apply (less_trans k k0 k1).
(* Goal: Less k k0 *)
(* Goal: Less k0 k1 *)
(* Goal: is_below_avl r k1 *)
apply (inv_below_avl_key k d l r b k0 H0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below_avl r k1 *)
apply (ih_r k0 k1 (inv_below_avl_right k d l r b k0 H0) H1).
Qed.


Lemma below_below_avl :
 forall (t : avl_tree) (key : Int), is_below t key -> is_below_avl t key.
(* Goal: forall (t : avl_tree) (key : Int) (_ : is_above t key), is_above_avl t key *)
intros t key; elim t; clear t.

(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_below_avl Avl_Nil k *)
(* Goal: is_above_avl Avl_Nil k *)
apply Below_Avl_Nil.

(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_below a key, is_below_avl a key) (a0 : avl_tree) (_ : forall _ : is_below a0 key, is_below_avl a0 key) (b0 : bal) (_ : is_below (Avl_Node i b a a0 b0) key), is_below_avl (Avl_Node i b a a0 b0) key *)
intros k d l ih_l r ih_r b below_t.
(* Goal: is_below_avl (Avl_Node k d l r b) key *)
apply Below_Avl_Node.
(* Goal: Less k key *)
(* Goal: is_below_avl r key *)
apply (inv_below_key k d l r b key below_t).
(* Goal: is_above r k0 *)
apply ih_r.
(* Goal: is_below r key *)
apply (inv_below_right k d l r b key below_t).
Qed.



(*********************************************************)
(*		Definition is_above_avl		  	 *)

Inductive is_above_avl : avl_tree -> Int -> Prop :=
  | Above_Avl_Nil : forall k0 : Int, is_above_avl Avl_Nil k0
  | Above_Avl_Node :
      forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
      Less k0 k -> is_above_avl l k0 -> is_above_avl (Avl_Node k d l r b) k0.

Lemma inv_above_avl_key :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_above_avl (Avl_Node k d l r b) k0 -> Less k0 k.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_above_avl_left :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (k0 : Int),
 is_above_avl (Avl_Node k d l r b) k0 -> is_above_avl l k0.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.


Lemma above_avl_trans :
 forall (t : avl_tree) (k0 k1 : Int),
 is_above_avl t k0 -> Less k1 k0 -> is_above_avl t k1.
(* Goal: forall (t : avl_tree) (_ : @eq nat (height_avl t) O), @eq avl_tree t Avl_Nil *)
intros t; elim t; clear t.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl Avl_Nil k *)
apply Above_Avl_Nil.
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 k1 : Int) (_ : is_above_avl a k0) (_ : Less k1 k0), is_above_avl a k1) (a0 : avl_tree) (_ : forall (k0 k1 : Int) (_ : is_above_avl a0 k0) (_ : Less k1 k0), is_above_avl a0 k1) (b0 : bal) (k0 k1 : Int) (_ : is_above_avl (Avl_Node i b a a0 b0) k0) (_ : Less k1 k0), is_above_avl (Avl_Node i b a a0 b0) k1 *)
intros k d l ih_l r ih_r b k0 k1 H0 H1.
(* Goal: is_above_avl (Avl_Node k d l r b) key *)
apply Above_Avl_Node.
(* Goal: Less k1 k *)
(* Goal: is_above_avl l k1 *)
apply (less_trans k1 k0 k H1).
(* Goal: Less k0 k *)
(* Goal: is_above_avl l k1 *)
apply (inv_above_avl_key k d l r b k0 H0).
(* Goal: is_above_avl l k1 *)
apply (ih_l k0 k1 (inv_above_avl_left k d l r b k0 H0) H1).
Qed.

Lemma above_above_avl :
 forall (t : avl_tree) (key : Int), is_above t key -> is_above_avl t key.
(* Goal: forall (t : avl_tree) (key : Int) (_ : is_above t key), is_above_avl t key *)
intros t key; elim t; clear t.

(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl Avl_Nil k *)
apply Above_Avl_Nil.

(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_above a key, is_above_avl a key) (a0 : avl_tree) (_ : forall _ : is_above a0 key, is_above_avl a0 key) (b0 : bal) (_ : is_above (Avl_Node i b a a0 b0) key), is_above_avl (Avl_Node i b a a0 b0) key *)
intros k d l ih_l r ih_r b above_t.
(* Goal: is_above_avl (Avl_Node k d l r b) key *)
apply Above_Avl_Node.
(* Goal: Less key k *)
(* Goal: is_above_avl l key *)
apply (inv_above_key k d l r b key above_t).
(* Goal: is_below l k0 *)
(* Goal: is_below r k0 *)
apply ih_l.
(* Goal: is_above l key *)
apply (inv_above_left k d l r b key above_t).
Qed.


(*****************************************************************)
(*           height_avl                                          *)

Fixpoint height_avl (t : avl_tree) : nat :=
  match t with
  | Avl_Nil => 0
  | Avl_Node _ _ l _ Left_Balanced => S (height_avl l)
  | Avl_Node _ _ l _ Balanced => S (height_avl l)
  | Avl_Node _ _ _ r Right_Balanced => S (height_avl r)
  end.


Lemma height_avl_O_nil : forall t : avl_tree, height_avl t = 0 -> t = Avl_Nil.
(* Goal: forall (t : avl_tree) (_ : @eq nat (height_avl t) O), @eq avl_tree t Avl_Nil *)
intros t; elim t; clear t.
(* Goal: forall _ : @eq nat (height_avl Avl_Nil) O, @eq avl_tree Avl_Nil Avl_Nil *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : @eq nat (height_avl a) O, @eq avl_tree a Avl_Nil) (a0 : avl_tree) (_ : forall _ : @eq nat (height_avl a0) O, @eq avl_tree a0 Avl_Nil) (b0 : bal) (_ : @eq nat (height_avl (Avl_Node i b a a0 b0)) O), @eq avl_tree (Avl_Node i b a a0 b0) Avl_Nil *)
intros; trivial.
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : @eq nat (height_avl a) O, @eq avl_tree a Avl_Nil) (a0 : avl_tree) (_ : forall _ : @eq nat (height_avl a0) O, @eq avl_tree a0 Avl_Nil) (b0 : bal) (_ : @eq nat (height_avl (Avl_Node i b a a0 b0)) O), @eq avl_tree (Avl_Node i b a a0 b0) Avl_Nil *)
intros k d l ih_l r ih_r b.
elim b; simpl in |- *; intro u0;  discriminate u0.
Qed.


(*********************************************************)
(*		Definition is_balanced		  	 *)


Inductive is_balanced_avl (l r : avl_tree) : bal -> Prop :=
  | Is_Left_Balanced_Avl :
      height_avl l = S (height_avl r) -> is_balanced_avl l r Left_Balanced
  | Is_Fully_Balanced_Avl :
      height_avl l = height_avl r -> is_balanced_avl l r Balanced
  | Is_Right_Balanced_Avl :
      S (height_avl l) = height_avl r -> is_balanced_avl l r Right_Balanced.


Lemma inv_left_balanced_avl :
 forall l r : avl_tree,
 is_balanced_avl l r Left_Balanced -> height_avl l = S (height_avl r).
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_fully_balanced_avl :
 forall l r : avl_tree,
 is_balanced_avl l r Balanced -> height_avl l = height_avl r.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.


Lemma inv_right_balanced_avl :
 forall l r : avl_tree,
 is_balanced_avl l r Right_Balanced -> S (height_avl l) = height_avl r.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.


Lemma hasnot_grown_left__preserves_is_balanced_avl :
 forall (l l0 r0 : avl_tree) (b0 : bal),
 is_balanced_avl l0 r0 b0 ->
 height_avl l = height_avl l0 -> is_balanced_avl l r0 b0.
(* Goal: forall (l l0 r0 : avl_tree) (b0 : bal) (_ : is_balanced_avl l0 r0 b0) (_ : @eq nat (height_avl l) (height_avl l0)), is_balanced_avl l r0 b0 *)
intros l l0 r0 b0 Balanced_l0 height_l.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
inversion_clear Balanced_l0.
(* Goal: is_balanced_avl l r Left_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Left_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Left_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) (has_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Is_Left_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite height_l; assumption.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite height_l; assumption.
(* Goal: is_balanced_avl l r Right_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Right_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Right_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite height_l; assumption.
Qed.


Lemma hasnot_grown_right__preserves_is_balanced_avl :
 forall (l0 r r0 : avl_tree) (b0 : bal),
 is_balanced_avl l0 r0 b0 ->
 height_avl r = height_avl r0 -> is_balanced_avl l0 r b0.
(* Goal: forall (l0 r r0 : avl_tree) (b0 : bal) (_ : is_balanced_avl l0 r0 b0) (_ : @eq nat (height_avl r0) (S (height_avl r))), is_balanced_avl_left_shift l0 r b0 *)
intros l0 r r0 b0 Balanced_l0 height_r.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
inversion_clear Balanced_l0.
(* Goal: is_balanced_avl l r Left_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Left_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Left_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) (has_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Is_Left_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite height_r; assumption.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite height_r; assumption.
(* Goal: is_balanced_avl l r Right_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Right_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Right_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite height_r; assumption.
Qed.


(*************************************************)
(*		Definition Avl		  	 *)
(*************************************************)

Inductive is_avl : avl_tree -> Prop :=
  | Nil_Is_Avl : is_avl Avl_Nil
  | Node_Is_Avl :
      forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
      is_avl l ->
      is_avl r ->
      is_balanced_avl l r b ->
      is_below_avl l k -> is_above_avl r k -> is_avl (Avl_Node k d l r b).


Lemma is_avl_rec :
 forall P : avl_tree -> Set,
 P Avl_Nil ->
 (forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
  is_avl l ->
  P l ->
  is_avl r ->
  P r ->
  is_balanced_avl l r b ->
  is_below_avl l k -> is_above_avl r k -> P (Avl_Node k d l r b)) ->
 forall t : avl_tree, is_avl t -> P t.
(* Goal: forall (P : forall _ : avl_tree, Set) (_ : P Avl_Nil) (_ : forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : P l) (_ : is_avl r) (_ : P r) (_ : is_balanced_avl l r b) (_ : is_below_avl l k) (_ : is_above_avl r k), P (Avl_Node k d l r b)) (t : avl_tree) (_ : is_avl t), P t *)
intros P base step t.
(* Goal: forall _ : is_avl t, P t *)
elim t; clear t.
(* Goal: forall _ : is_avl Avl_Nil, P Avl_Nil *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, P a) (a0 : avl_tree) (_ : forall _ : is_avl a0, P a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), P (Avl_Node i b a a0 b0) *)
intros; apply base.
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, P a) (a0 : avl_tree) (_ : forall _ : is_avl a0, P a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), P (Avl_Node i b a a0 b0) *)
intros k d l ih_l r ih_r b avl_t.
(* Goal: P (Avl_Node k d l r b) *)
apply step.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t; assumption.
(* Goal: is_below l k0 *)
(* Goal: is_below r k0 *)
apply ih_l.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t; assumption.
(* Goal: is_above r k0 *)
apply ih_r.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t; assumption.
Qed.



Lemma inv_is_avl_left :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl (Avl_Node k d l r b) -> is_avl l.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.


Lemma inv_is_avl_right :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl (Avl_Node k d l r b) -> is_avl r.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_is_avl_is_balanced_avl :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl (Avl_Node k d l r b) -> is_balanced_avl l r b.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_is_avl_is_is_below_avl :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl (Avl_Node k d l r b) -> is_below_avl l k.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.

Lemma inv_is_avl_is_is_above_avl :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl (Avl_Node k d l r b) -> is_above_avl r k.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_above_avl r k *)
inversion H; assumption.
Qed.


Lemma avl_height_avl_height :
 forall t : avl_tree, is_avl t -> height_avl t = height t.
(* Goal: forall (t : avl_tree) (_ : is_avl t) (k0 : Int) (_ : is_below_avl t k0), is_below t k0 *)
intros t avl_t.
(* Goal: @eq nat (height_avl t) (height t) *)
elim avl_t.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : lookup_dec_spec key l) (_ : is_avl r) (_ : lookup_dec_spec key r) (_ : is_balanced_avl l r b) (_ : is_below_avl l k) (_ : is_above_avl r k), lookup_dec_spec key (Avl_Node k d l r b) *)
intros k d l r b avl_l ih_l avl_r ih_r Balanced_t below_l above_r.
(* Goal: @eq nat (height_avl (Avl_Node k d l r b)) (height (Avl_Node k d l r b)) *)
clear avl_l avl_r below_l above_r. 
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq nat match b with | Left_Balanced => S (height_avl l) | Balanced => S (height_avl l) | Right_Balanced => S (height_avl r) end (S (max (height l) (height r))) *)
 rewrite <- ih_l.
(* Goal: @eq nat match b with | Left_Balanced => S (height_avl l) | Balanced => S (height_avl l) | Right_Balanced => S (height_avl r) end (S (max (height_avl l) (height r))) *)
 rewrite <- ih_r.
(* Goal: @eq nat match b with | Left_Balanced => S (height_avl l) | Balanced => S (height_avl l) | Right_Balanced => S (height_avl r) end (S (max (height_avl l) (height_avl r))) *)
clear ih_l ih_r.
(* Goal: @eq nat match b with | Left_Balanced => S (height_avl l) | Balanced => S (height_avl l) | Right_Balanced => S (height_avl r) end (S (max (height_avl l) (height_avl r))) *)
inversion_clear Balanced_t.
(* Goal: @eq nat (S match br0 with | Left_Balanced => S (height_avl lr0) | Balanced => S (height_avl lr0) | Right_Balanced => S (height_avl rr0) end) (S (S (height_avl l0))) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
 rewrite H.
(* Goal: @eq nat (S (S (height_avl r))) (S (max (S (height_avl r)) (height_avl r))) *)
(* Goal: @eq nat (S (height_avl l)) (S (max (height_avl l) (height_avl r))) *)
(* Goal: @eq nat (S (height_avl r)) (S (max (height_avl l) (height_avl r))) *)
 rewrite (max_Sn_n (height_avl r)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: @eq nat (S match br0 with | Left_Balanced => S (height_avl lr0) | Balanced => S (height_avl lr0) | Right_Balanced => S (height_avl rr0) end) (S (S (height_avl l0))) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
 rewrite H.
(* Goal: @eq nat (S (height_avl r)) (S (max (height_avl r) (height_avl r))) *)
(* Goal: @eq nat (S (height_avl r)) (S (max (height_avl l) (height_avl r))) *)
 rewrite (max_n_n (height_avl r)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: @eq nat (S (S (height_avl l))) (S (max (height_avl l) (S (height_avl l)))) *)
 rewrite (max_n_Sn (height_avl l)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
Qed.


Lemma is_balanced_avl_is_balanced :
 forall l r : avl_tree,
 is_avl l ->
 is_avl r -> forall b : bal, is_balanced_avl l r b -> is_balanced l r b.
(* Goal: forall (l r : avl_tree) (_ : is_avl l) (_ : is_avl r) (b : bal) (_ : is_balanced_avl l r b), is_balanced l r b *)
intros l r avl_l avl_r.
(* Goal: forall (b : bal) (_ : is_balanced_avl l r b), is_balanced l r b *)
intro b; elim b; clear b; intro bal0.
(* Goal: is_balanced l r Left_Balanced *)
(* Goal: is_balanced l r Balanced *)
(* Goal: is_balanced l r Right_Balanced *)
apply Is_Left_Balanced.
(* Goal: @eq nat (S (height l)) (height r) *)
 rewrite <- (avl_height_avl_height r avl_r).
(* Goal: @eq nat (S (height l)) (height_avl r) *)
 rewrite <- (avl_height_avl_height l avl_l).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply inv_left_balanced_avl; assumption.
(* Goal: is_balanced l r Balanced *)
(* Goal: is_balanced l r Right_Balanced *)
apply Is_Fully_Balanced.
(* Goal: @eq nat (S (height l)) (height r) *)
 rewrite <- (avl_height_avl_height r avl_r).
(* Goal: @eq nat (S (height l)) (height_avl r) *)
 rewrite <- (avl_height_avl_height l avl_l).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply inv_fully_balanced_avl; assumption.

(* Goal: is_balanced l r Right_Balanced *)
apply Is_Right_Balanced.
(* Goal: @eq nat (S (height l)) (height r) *)
 rewrite <- (avl_height_avl_height r avl_r).
(* Goal: @eq nat (S (height l)) (height_avl r) *)
 rewrite <- (avl_height_avl_height l avl_l).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply inv_right_balanced_avl; assumption.
Qed.



Lemma is_avl_is_balanced :
 forall (l r : avl_tree) (k : Int) (d : B) (b : bal),
 is_avl (Avl_Node k d l r b) -> is_balanced l r b.
(* Goal: forall (l r : avl_tree) (k : Int) (d : B) (b : bal) (_ : is_avl (Avl_Node k d l r b)), is_balanced l r b *)
intros l r k d b avl_t.
(* Goal: is_balanced l r b *)
apply is_balanced_avl_is_balanced.
(* Goal: is_avl l *)
(* Goal: is_avl r *)
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_left k d l r b avl_t).
(* Goal: is_avl r *)
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_right k d l r b avl_t).
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_is_balanced_avl k d l r b avl_t).
Qed.


Lemma is_below_avl_is_below :
 forall t : avl_tree,
 is_avl t -> forall k0 : Int, is_below_avl t k0 -> is_below t k0.
(* Goal: forall (t : avl_tree) (_ : is_avl t) (k0 : Int) (_ : is_below_avl t k0), is_below t k0 *)
intros t avl_t.
(* Goal: forall (k0 : Int) (_ : is_below_avl t k0), is_below t k0 *)
elim avl_t; clear avl_t t.
(* Goal: is_below Avl_Nil k0 *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a d), Less k k0), is_below a k0) (a0 : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a0 d), Less k k0), is_below a0 k0) (b0 : bal) (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k (Avl_Node i b a a0 b0) d), Less k k0), is_below (Avl_Node i b a a0 b0) k0 *)
intros; apply Below_Nil.
intros k d l r b avl_l ih_l avl_r ih_r Balanced_t below_l above_r k0
 below_avl.
(* Goal: is_below (Avl_Node k d l r b) k0 *)
inversion_clear below_avl.
(* Goal: is_below (Avl_Node k0 d0 l0 r b0) k *)
(* Goal: Less k0 k *)
(* Goal: equiv t (Avl_Node k0 d0 l0 r b0) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (@app (prod Int B) (lin_avl t) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))) *)
(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply Below_Node.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below l k0 *)
(* Goal: is_below r k0 *)
apply ih_l. 
(* Goal: is_below_avl l k0 *)
(* Goal: is_below r k0 *)
apply below_avl_trans with k.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply ih_r; assumption.
Qed.


Lemma is_above_avl_is_above :
 forall t : avl_tree,
 is_avl t -> forall k0 : Int, is_above_avl t k0 -> is_above t k0.
(* Goal: forall (k0 : Int) (_ : is_below_avl t k0), is_below t k0 *)
intros t avl_t; elim avl_t; clear avl_t t.
(* Goal: is_above Avl_Nil k0 *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a d), Less k0 k), is_above a k0) (a0 : avl_tree) (_ : forall (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k a0 d), Less k0 k), is_above a0 k0) (b0 : bal) (k0 : Int) (_ : forall (k : Int) (d : B) (_ : lookup k (Avl_Node i b a a0 b0) d), Less k0 k), is_above (Avl_Node i b a a0 b0) k0 *)
intros; apply Above_Nil.
intros k d l r b avl_l ih_l avl_r ih_r Balanced_t below_l above_r k0
 above_avl.
(* Goal: is_above (Avl_Node k d l r b) k0 *)
clear avl_l avl_r Balanced_t.
(* Goal: is_above (Avl_Node k d l r b) k0 *)
inversion_clear above_avl.
(* Goal: is_above (Avl_Node k d l r b) k0 *)
apply Above_Node.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply ih_l; assumption.
(* Goal: is_above r k0 *)
apply ih_r.
(* Goal: is_above_avl r k0 *)
apply above_avl_trans with k.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.






(***************************************************************)
(*  lookup_avl                                                 *)


Lemma lookup_avl_inv_equal :
 forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B),
 is_avl (Avl_Node k d l r b) ->
 Equal key k -> lookup key (Avl_Node k d l r b) data -> d = data.
(* Goal: forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B) (_ : is_avl (Avl_Node k d l r b)) (_ : Equal key k) (_ : lookup key (Avl_Node k d l r b) data), @eq B d data *)
intros key k d l r b data avl_t equal lookup_t.
(* Goal: lookup key r data *)
elim (inv_lookup key k d l r b data lookup_t); intro u0.

(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim u0; trivial.

(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.

(* Goal: False *)
(* Goal: lookup key r data *)
apply (lookup_below_false key l data u0).
(* Goal: is_below (Avl_Node kl0 dl0 ll0 rl0 bl0) k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply is_below_avl_is_below.
(* Goal: is_avl l *)
(* Goal: is_avl r *)
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_left k d l r b avl_t).
(* Goal: is_above_avl r key *)
 rewrite (equal_eq key k equal).
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_is_is_below_avl k d l r b avl_t).

(* Goal: False *)
apply (lookup_above_false key r data u0).
(* Goal: is_above r0 k0 *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: equiv (Avl_Node k d l r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply is_above_avl_is_above.
(* Goal: is_avl r *)
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_right k d l r b avl_t).
(* Goal: is_above_avl r key *)
 rewrite (equal_eq key k equal).
(* Goal: is_above_avl r k *)
apply (inv_is_avl_is_is_above_avl k d l r b avl_t).
Qed.


Lemma lookup_avl_inv_less :
 forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B),
 is_avl (Avl_Node k d l r b) ->
 Less key k -> lookup key (Avl_Node k d l r b) data -> lookup key l data.
(* Goal: forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B) (_ : is_avl (Avl_Node k d l r b)) (_ : Less k key) (_ : lookup key (Avl_Node k d l r b) data), lookup key r data *)
intros key k d l r b data avl_t less lookup_t.
(* Goal: lookup key r data *)
elim (inv_lookup key k d l r b data lookup_t); intro u0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup key r data *)
apply (less_irrefl key).
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite u0 in less.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
apply (lookup_above_false key r data u0).
(* Goal: is_above r0 k0 *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: equiv (Avl_Node k d l r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply is_above_avl_is_above.
(* Goal: is_avl r *)
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_right k d l r b avl_t).
(* Goal: is_above_avl r key *)
apply (above_avl_trans r k key).
(* Goal: is_above_avl r k *)
apply (inv_is_avl_is_is_above_avl k d l r b avl_t).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.


Lemma lookup_avl_inv_greater :
 forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B),
 is_avl (Avl_Node k d l r b) ->
 Less k key -> lookup key (Avl_Node k d l r b) data -> lookup key r data.
(* Goal: forall (key k : Int) (d : B) (l r : avl_tree) (b : bal) (data : B) (_ : is_avl (Avl_Node k d l r b)) (_ : Less k key) (_ : lookup key (Avl_Node k d l r b) data), lookup key r data *)
intros key k d l r b data avl_t less lookup_t.
(* Goal: lookup key r data *)
elim (inv_lookup key k d l r b data lookup_t); intro u0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup key r data *)
apply (less_irrefl key).
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite u0 in less.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.

(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup key r data *)
apply (lookup_below_false key l data u0).
(* Goal: is_below l key *)
(* Goal: lookup key r data *)
apply (below_trans l k key).
(* Goal: is_below (Avl_Node kl0 dl0 ll0 rl0 bl0) k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply is_below_avl_is_below.
(* Goal: is_avl l *)
(* Goal: is_avl r *)
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_left k d l r b avl_t).
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_is_is_below_avl k d l r b avl_t).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.



Lemma lookup_avl_equal :
 forall (k1 k : Int) (t : avl_tree) (d1 d : B),
 is_avl t -> lookup k1 t d1 -> lookup k t d -> Equal k1 k -> d1 = d.
(* Goal: forall (k1 k : Int) (t : avl_tree) (d1 d : B) (_ : is_avl t) (_ : lookup k1 t d1) (_ : lookup k t d) (_ : Equal k1 k), @eq B d1 d *)
intros k1 k t d1 d avl_t.
(* Goal: forall (_ : lookup k1 t d1) (_ : lookup k t d) (_ : Equal k1 k), @eq B d1 d *)
generalize d; clear d.
(* Goal: forall (d : B) (_ : lookup k1 t d1) (_ : lookup k t d) (_ : Equal k1 k), @eq B d1 d *)
generalize d1; clear d1.
(* Goal: forall (d1 d : B) (_ : lookup k1 t d1) (_ : lookup k t d) (_ : Equal k1 k), @eq B d1 d *)
generalize k; clear k.
(* Goal: forall (k : Int) (d1 d : B) (_ : lookup k1 t d1) (_ : lookup k t d) (_ : Equal k1 k), @eq B d1 d *)
generalize k1; clear k1.
(* Goal: forall (k1 k : Int) (d1 d : B) (_ : lookup k1 t d1) (_ : lookup k t d) (_ : Equal k1 k), @eq B d1 d *)
elim avl_t; clear avl_t.

(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.

intros k0 d0 l r b avl_l ih_l avl_r ih_r Balanced_l below_avl_r above_avl_r
 k1 k2 d1 d2 lookup_k1.
(* Goal: forall (_ : lookup k2 (Avl_Node k0 d0 l r b) d2) (_ : Equal k1 k2), @eq B d1 d2 *)
inversion_clear lookup_k1.
(* Goal: forall (_ : lookup k2 (Avl_Node k0 d1 l r b) d2) (_ : Equal k0 k2), @eq B d1 d2 *)
(* Goal: forall (_ : lookup k2 (Avl_Node k0 d0 l r b) d2) (_ : Equal k1 k2), @eq B d1 d2 *)
(* Goal: forall (_ : lookup k2 (Avl_Node k0 d0 l r b) d2) (_ : Equal k1 k2), @eq B d1 d2 *)
intros lookup_k0 equal_k1.
(* Goal: @eq B d1 d2 *)
(* Goal: forall (_ : lookup k2 (Avl_Node k0 d0 l r b) d2) (_ : Equal k1 k2), @eq B d1 d2 *)
(* Goal: forall (_ : lookup k2 (Avl_Node k0 d0 l r b) d2) (_ : Equal k1 k2), @eq B d1 d2 *)
apply lookup_avl_inv_equal with k2 k0 l r b.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equal_sym; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: forall (_ : lookup k2 (Avl_Node k0 d0 l r b) d2) (_ : Equal k1 k2), @eq B d1 d2 *)
intros lookup_k2 equal_k1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply ih_l with k1 k2; try assumption.
(* Goal: lookup k2 l d2 *)
(* Goal: forall (_ : lookup k2 (Avl_Node k0 d0 l r b) d2) (_ : Equal k1 k2), @eq B d1 d2 *)
apply lookup_avl_inv_less with k0 d0 r b.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; assumption.
(* Goal: Less k0 k2 *)
(* Goal: lookup k2 (Avl_Node k0 d0 l r b) d2 *)
 rewrite <- (equal_eq k1 k2 equal_k1).
(* Goal: Less k1 k0 *)
(* Goal: lookup k2 (Avl_Node k0 d0 l r b) d2 *)
(* Goal: forall (_ : lookup k2 (Avl_Node k0 d0 l r b) d2) (_ : Equal k1 k2), @eq B d1 d2 *)
apply lookup_below_less with l d1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_below_avl_is_below; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall (_ : lookup k2 (Avl_Node k0 d0 l r b) d2) (_ : Equal k1 k2), @eq B d1 d2 *)
intros lookup_k2 equal_k1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply ih_r with k1 k2; try assumption.
(* Goal: lookup k2 r d2 *)
apply lookup_avl_inv_greater with k0 d0 l b.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; assumption.
(* Goal: Less k0 k2 *)
(* Goal: lookup k2 (Avl_Node k0 d0 l r b) d2 *)
 rewrite <- (equal_eq k1 k2 equal_k1).
(* Goal: Less k0 k1 *)
(* Goal: lookup k2 (Avl_Node k0 d0 l r b) d2 *)
apply lookup_above_greater with r d1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_above_avl_is_above; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.


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

Inductive lookup_dec_spec (key : Int) (t : avl_tree) : Set :=
  | Lookup : forall d : B, lookup key t d -> lookup_dec_spec key t
  | Not_Lookup : (forall d : B, ~ lookup key t d) -> lookup_dec_spec key t.



Lemma lookup_dec :
 forall (key : Int) (t : avl_tree), is_avl t -> lookup_dec_spec key t.
(* Goal: forall (k0 : Int) (_ : is_below_avl t k0), is_below t k0 *)
intros key t avl_t; elim avl_t; clear avl_t t.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Not_Lookup.
(* Goal: forall d : B, not (lookup key Avl_Nil d) *)
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : lookup_dec_spec key l) (_ : is_avl r) (_ : lookup_dec_spec key r) (_ : is_balanced_avl l r b) (_ : is_below_avl l k) (_ : is_above_avl r k), lookup_dec_spec key (Avl_Node k d l r b) *)
unfold not in |- *; intros d lookup_nil.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (inv_lookup_nil key d); assumption.

(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : lookup_dec_spec key l) (_ : is_avl r) (_ : lookup_dec_spec key r) (_ : is_balanced_avl l r b) (_ : is_below_avl l k) (_ : is_above_avl r k), lookup_dec_spec key (Avl_Node k d l r b) *)
intros k d l r b avl_l ih_l avl_r ih_r Balanced_t below_l above_r.
(* Goal: lookup_dec_spec key (Avl_Node k d l r b) *)
elim (equal_dec key k).

(* Goal: forall _ : Equal key k, lookup_dec_spec key (Avl_Node k d l r b) *)
(* Goal: forall _ : not (Equal key k), lookup_dec_spec key (Avl_Node k d l r b) *)
intro equal_key_k.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Lookup with d.
(* Goal: lookup key (Avl_Node k d l r b) d *)
(* Goal: forall _ : not (Equal key k), lookup_dec_spec key (Avl_Node k d l r b) *)
 rewrite (equal_eq key k equal_key_k).
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.

(* Goal: forall _ : not (Equal key k), lookup_dec_spec key (Avl_Node k d l r b) *)
intros not_equal_key_k.
(* Goal: lookup_dec_spec key (Avl_Node k d l r b) *)
elim (less_dec key k).

(* Goal: forall _ : Less key k, lookup_dec_spec key (Avl_Node k d l r b) *)
(* Goal: forall _ : not (Less key k), lookup_dec_spec key (Avl_Node k d l r b) *)
intro less_key_k.
(* Goal: lookup_dec_spec key (Avl_Node k d l r b) *)
(* Goal: forall _ : not (Less key k), lookup_dec_spec key (Avl_Node k d l r b) *)
elim ih_l; clear ih_r ih_l.
(* Goal: forall (d0 : B) (_ : lookup key r d0), lookup_dec_spec key (Avl_Node k d l r b) *)
(* Goal: forall _ : forall d : B, not (lookup key r d), lookup_dec_spec key (Avl_Node k d l r b) *)
intros d0 lookup_d0.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl (Avl_Node k0 (update d0) l0 r0 b0) *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 (update d0) l0 r0 b0) *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 (update d0) l0 r0 b0) *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 (update d0) l0 r0 b0)) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl (Avl_Node k0 (update d0) l0 r0 b0)) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: forall _ : not (Equal key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup with d0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intros not_lookup_d0.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Not_Lookup.
(* Goal: forall (d0 : B) (_ : lookup key r d0), lookup_dec_spec key (Avl_Node k d l r b) *)
(* Goal: forall _ : forall d : B, not (lookup key r d), lookup_dec_spec key (Avl_Node k d l r b) *)
unfold not in |- *; intros d0 lookup_d0.
(* Goal: False *)
apply (not_lookup_d0 d0).
(* Goal: lookup key l d0 *)
(* Goal: forall _ : not (Less key k), lookup_dec_spec key (Avl_Node k d l r b) *)
apply (lookup_avl_inv_less key k d l r b). 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: forall _ : not (Less key k), lookup_dec_spec key (Avl_Node k d l r b) *)
intros not_less.
(* Goal: lookup_dec_spec key (Avl_Node k d l r b) *)
generalize (notequal_notless_greater key k not_equal_key_k not_less).
(* Goal: forall _ : Less k key, lookup_dec_spec key (Avl_Node k d l r b) *)
clear not_equal_key_k not_less.
(* Goal: forall _ : Less k key, lookup_dec_spec key (Avl_Node k d l r b) *)
intros less_k_key.
(* Goal: lookup_dec_spec key (Avl_Node k d l r b) *)
elim ih_r; clear ih_r ih_l.
(* Goal: forall (d0 : B) (_ : lookup key r d0), lookup_dec_spec key (Avl_Node k d l r b) *)
(* Goal: forall _ : forall d : B, not (lookup key r d), lookup_dec_spec key (Avl_Node k d l r b) *)
intros d0 lookup_d0.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl (Avl_Node k0 (update d0) l0 r0 b0) *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 (update d0) l0 r0 b0) *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 (update d0) l0 r0 b0) *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 (update d0) l0 r0 b0)) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl (Avl_Node k0 (update d0) l0 r0 b0)) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: forall _ : not (Equal key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup with d0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intros not_lookup_d0.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Not_Lookup.
(* Goal: forall (d0 : B) (_ : lookup key r d0), lookup_dec_spec key (Avl_Node k d l r b) *)
(* Goal: forall _ : forall d : B, not (lookup key r d), lookup_dec_spec key (Avl_Node k d l r b) *)
unfold not in |- *; intros d0 lookup_d0.
(* Goal: False *)
apply (not_lookup_d0 d0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_avl_inv_greater key k d l r b); try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; assumption.
Qed.


(***************************************************************************)
(*  equiv                                                                  *)


Fixpoint lin_avl (t : avl_tree) : list (Int * B) :=
  match t with
  | Avl_Nil => nil (A:=Int * B)
  | Avl_Node k d l r _ => lin_avl l ++ (k, d) :: lin_avl r
  end.

Inductive equiv : avl_tree -> avl_tree -> Prop :=
    equiv_intro :
      forall t0 t1 : avl_tree,
      (forall (key : Int) (data : B),
       lookup key t0 data -> lookup key t1 data) ->
      (forall (key : Int) (data : B),
       lookup key t1 data -> lookup key t0 data) -> 
      equiv t0 t1.

Lemma inv_equiv_t0_t1 :
 forall (t0 t1 : avl_tree) (key : Int) (data : B),
 equiv t0 t1 -> lookup key t0 data -> lookup key t1 data.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 l0 d1 *)
(* Goal: is_below l0 k0 *)
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply H1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.

Lemma inv_equiv_t1_t0 :
 forall (t0 t1 : avl_tree) (key : Int) (data : B),
 equiv t0 t1 -> lookup key t1 data -> lookup key t0 data.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
apply H2.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.


Lemma equiv_sym : forall t t0 : avl_tree, equiv t t0 -> equiv t0 t.
(* Goal: forall (t t0 : avl_tree) (_ : equiv t t0), equiv t0 t *)
intros t t0 equiv_t_t0.
(* Goal: equiv t0 t *)
inversion_clear equiv_t_t0.
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
apply equiv_intro.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.

Lemma equiv_refl :
 forall (k : Int) (d : B) (l r : avl_tree) (b b' : bal),
 equiv (Avl_Node k d l r b) (Avl_Node k d l r b').
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b b' : bal), equiv (Avl_Node k d l r b) (Avl_Node k d l r b') *)
intros k d l r b b'.
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
apply equiv_intro.
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data), lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data *)
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data), lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data *)
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
Qed.


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

Definition rebalance_left_spec (k : Int) (d : B) (l r : avl_tree) 
(b : bal) : Set :=
  { t : avl_tree | 
      is_avl t /\
      lin_avl t = lin_avl (Avl_Node k d l r b) /\
      equiv t (Avl_Node k d l r b) /\
      match l with
      | Avl_Nil => True
      | Avl_Node _ _ _ _ Left_Balanced => height_avl t = height_avl l
      | Avl_Node _ _ _ _ Balanced => height_avl t = S (height_avl l)
      | Avl_Node _ _ _ _ Right_Balanced => height_avl t = height_avl l
      end }.



Lemma rebalance_left :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl l ->
 is_below_avl l k ->
 is_avl r ->
 is_above_avl r k ->
 height_avl l = S (S (height_avl r)) -> rebalance_left_spec k d l r b.
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : is_below_avl l k) (_ : is_avl r) (_ : is_above_avl r k) (_ : @eq nat (height_avl l) (S (S (height_avl r)))), rebalance_left_spec k d l r b *)
intros k d l r b avl_l below_avl_l avl_r above_avl_r.
(* Goal: forall _ : @eq nat (height_avl l) (S (S (height_avl r))), rebalance_left_spec k d l r b *)
generalize below_avl_l; clear below_avl_l.
(* Goal: forall (_ : is_below_avl l k) (_ : @eq nat (height_avl l) (S (S (height_avl r)))), rebalance_left_spec k d l r b *)
elim avl_l; clear avl_l l.

(* l=Avl_Nil *)
(* Goal: forall (_ : is_below_avl Avl_Nil k) (_ : @eq nat (height_avl Avl_Nil) (S (S (height_avl r)))), rebalance_left_spec k d Avl_Nil r b *)
(* Goal: forall (k0 : Int) (d0 : B) (l r0 : avl_tree) (b0 : bal) (_ : is_avl l) (_ : forall (_ : is_below_avl l k) (_ : @eq nat (height_avl l) (S (S (height_avl r)))), rebalance_left_spec k d l r b) (_ : is_avl r0) (_ : forall (_ : is_below_avl r0 k) (_ : @eq nat (height_avl r0) (S (S (height_avl r)))), rebalance_left_spec k d r0 r b) (_ : is_balanced_avl l r0 b0) (_ : is_below_avl l k0) (_ : is_above_avl r0 k0) (_ : is_below_avl (Avl_Node k0 d0 l r0 b0) k) (_ : @eq nat (height_avl (Avl_Node k0 d0 l r0 b0)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node k0 d0 l r0 b0) r b *)
intros below_avl_l height_l.
(* Goal: rebalance_left_spec k d (Avl_Node kl dl ll Avl_Nil Right_Balanced) r b *)
(* Goal: forall (k0 : Int) (d0 : B) (l r0 : avl_tree) (b0 : bal) (_ : is_avl l) (_ : forall (_ : is_balanced_avl ll l Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl l kl) (_ : is_below_avl (Avl_Node kl dl ll l Right_Balanced) k) (_ : @eq nat (S (height_avl l)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll l Right_Balanced) r b) (_ : is_avl r0) (_ : forall (_ : is_balanced_avl ll r0 Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl r0 kl) (_ : is_below_avl (Avl_Node kl dl ll r0 Right_Balanced) k) (_ : @eq nat (S (height_avl r0)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll r0 Right_Balanced) r b) (_ : is_balanced_avl l r0 b0) (_ : is_below_avl l k0) (_ : is_above_avl r0 k0) (_ : is_balanced_avl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl (Avl_Node k0 d0 l r0 b0) kl) (_ : is_below_avl (Avl_Node kl dl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) k) (_ : @eq nat (S match b0 with | Left_Balanced => S (height_avl l) | Balanced => S (height_avl l) | Right_Balanced => S (height_avl r0) end) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) r b *)
 discriminate height_l.

(* l=(Avl_Node kl dl ll rl bl) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_left_shift (Avl_Node i b a a0 b0) r Left_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_left t k d (Avl_Node i b a a0 b0) r Left_Balanced) (has_shrunk_left t k d (Avl_Node i b a a0 b0) r Left_Balanced) *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
intros kl dl ll rl bl.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
case bl; clear bl; simpl in |- *.



(* bl=Left_Balanced => single LL-rotation *)
intros avl_ll ih_ll avl_rl ih_rl Balanced_l below_ll above_rl below_avl_l
 height_l;  injection height_l; clear height_l ih_ll ih_rl; 
 intros height_l.
(* Goal: rebalance_left_spec k d (Avl_Node kl dl ll rl Left_Balanced) r b *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Balanced) k) (_ : @eq nat (S (height_avl ll)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Balanced) r b *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Right_Balanced) k) (_ : @eq nat (S (height_avl rl)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Right_Balanced) r b *)
exists (Avl_Node kl dl ll (Avl_Node k d rl r Balanced) Balanced).
(* Goal: and (is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (and (@eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b))) (and (equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) (@eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced))))) *)
repeat apply conj.
(* Goal: is_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
inversion_clear below_avl_l.
(* Goal: forall _ : @eq nat match blr with | Left_Balanced => S (height_avl llr) | Balanced => S (height_avl llr) | Right_Balanced => S (height_avl rlr) end (S (height_avl r)), @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
inversion_clear Balanced_l.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl rl) (height_avl r) *)
(* Goal: is_balanced_avl ll (Avl_Node k d rl r Balanced) Balanced *)
(* Goal: is_above_avl (Avl_Node k d rl r Balanced) kl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node kl dl ll (Avl_Node k d rl r Balanced) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll rl Left_Balanced) r b)) *)
(* Goal: equiv (Avl_Node kl dl ll (Avl_Node k d rl r Balanced) Balanced) (Avl_Node k d (Avl_Node kl dl ll rl Left_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node kl dl ll (Avl_Node k d rl r Balanced) Balanced)) (height_avl (Avl_Node kl dl ll rl Left_Balanced)) *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Balanced) k) (_ : @eq nat (S (height_avl ll)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Balanced) r b *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Right_Balanced) k) (_ : @eq nat (S (height_avl rl)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Right_Balanced) r b *)
 rewrite height_l in H1.
symmetry  in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection H1; trivial.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Above_Avl_Node; assumption.

(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
 rewrite
 (app_ass (lin_avl ll) ((kl, dl) :: lin_avl rl) ((k, d) :: lin_avl r))
 .
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: equiv (Avl_Node kl dl ll (Avl_Node k d rl r Balanced) Balanced) (Avl_Node k d (Avl_Node kl dl ll rl Left_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node kl dl ll (Avl_Node k d rl r Balanced) Balanced)) (height_avl (Avl_Node kl dl ll rl Left_Balanced)) *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Balanced) k) (_ : @eq nat (S (height_avl ll)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Balanced) r b *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Right_Balanced) k) (_ : @eq nat (S (height_avl rl)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Right_Balanced) r b *)
apply equiv_intro; clear avl_ll avl_rl height_l Balanced_l.
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data), lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data *)
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Left; apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Left; assumption.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Right; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t0.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Right; apply Lookup_Equal.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Right; assumption.

(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial. 


(* bl=Balanced => single LL-rotation  *)
intros avl_ll ih_ll avl_rl ih_rl Balanced_l below_ll above_rl below_avl_l
 height_l;  injection height_l; clear height_l ih_ll ih_rl; 
 intros height_l.
(* Goal: rebalance_left_spec k d (Avl_Node kl dl ll rl Balanced) r b *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Right_Balanced) k) (_ : @eq nat (S (height_avl rl)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Right_Balanced) r b *)
exists (Avl_Node kl dl ll (Avl_Node k d rl r Left_Balanced) Right_Balanced).
(* Goal: and (is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (and (@eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b))) (and (equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) (@eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced))))) *)
repeat apply conj.
(* Goal: forall _ : @eq nat match blr with | Left_Balanced => S (height_avl llr) | Balanced => S (height_avl llr) | Right_Balanced => S (height_avl rlr) end (S (height_avl r)), @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
inversion_clear Balanced_l.
(* Goal: is_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
inversion_clear below_avl_l.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Left_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Left_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Left_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) (has_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Is_Left_Balanced_Avl.
(* Goal: @eq nat (height_avl rl) (S (height_avl r)) *)
(* Goal: is_balanced_avl ll (Avl_Node k d rl r Left_Balanced) Right_Balanced *)
(* Goal: is_above_avl (Avl_Node k d rl r Left_Balanced) kl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node kl dl ll (Avl_Node k d rl r Left_Balanced) Right_Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll rl Balanced) r b)) *)
(* Goal: equiv (Avl_Node kl dl ll (Avl_Node k d rl r Left_Balanced) Right_Balanced) (Avl_Node k d (Avl_Node kl dl ll rl Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node kl dl ll (Avl_Node k d rl r Left_Balanced) Right_Balanced)) (S (height_avl (Avl_Node kl dl ll rl Balanced))) *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Right_Balanced) k) (_ : @eq nat (S (height_avl rl)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Right_Balanced) r b *)
 rewrite <- height_l.
symmetry  in |- *.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_balanced_avl l r Right_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Right_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Right_Balanced_Avl.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Above_Avl_Node; assumption.

(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
 rewrite
 (app_ass (lin_avl ll) ((kl, dl) :: lin_avl rl) ((k, d) :: lin_avl r))
 .
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: equiv (Avl_Node kl dl ll (Avl_Node k d rl r Left_Balanced) Right_Balanced) (Avl_Node k d (Avl_Node kl dl ll rl Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node kl dl ll (Avl_Node k d rl r Left_Balanced) Right_Balanced)) (S (height_avl (Avl_Node kl dl ll rl Balanced))) *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Right_Balanced) k) (_ : @eq nat (S (height_avl rl)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Right_Balanced) r b *)
apply equiv_intro; clear avl_ll avl_rl below_avl_l height_l.
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data), lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data *)
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Left; apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Left; assumption.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Right; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t0.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Right; apply Lookup_Equal.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Right; assumption.

(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : @eq nat match blr with | Left_Balanced => S (height_avl llr) | Balanced => S (height_avl llr) | Right_Balanced => S (height_avl rlr) end (S (height_avl r)), @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
inversion_clear Balanced_l.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.


(* bl=Right_Balanced => double LR-rotation *)
(* Goal: forall (_ : is_avl ll) (_ : forall (_ : is_below_avl ll k) (_ : @eq nat (height_avl ll) (S (S (height_avl r)))), rebalance_left_spec k d ll r b) (_ : is_avl rl) (_ : forall (_ : is_below_avl rl k) (_ : @eq nat (height_avl rl) (S (S (height_avl r)))), rebalance_left_spec k d rl r b) (_ : is_balanced_avl ll rl Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl rl kl) (_ : is_below_avl (Avl_Node kl dl ll rl Right_Balanced) k) (_ : @eq nat (S (height_avl rl)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll rl Right_Balanced) r b *)
intros avl_ll ih_ll avl_rl ih_rl; clear ih_ll ih_rl.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim avl_rl; clear avl_rl rl; simpl in |- *.

(* Goal: forall (_ : is_balanced_avl ll Avl_Nil Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl Avl_Nil kl) (_ : is_below_avl (Avl_Node kl dl ll Avl_Nil Right_Balanced) k) (_ : @eq nat (S O) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll Avl_Nil Right_Balanced) r b *)
(* Goal: forall (k0 : Int) (d0 : B) (l r0 : avl_tree) (b0 : bal) (_ : is_avl l) (_ : forall (_ : is_balanced_avl ll l Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl l kl) (_ : is_below_avl (Avl_Node kl dl ll l Right_Balanced) k) (_ : @eq nat (S (height_avl l)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll l Right_Balanced) r b) (_ : is_avl r0) (_ : forall (_ : is_balanced_avl ll r0 Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl r0 kl) (_ : is_below_avl (Avl_Node kl dl ll r0 Right_Balanced) k) (_ : @eq nat (S (height_avl r0)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll r0 Right_Balanced) r b) (_ : is_balanced_avl l r0 b0) (_ : is_below_avl l k0) (_ : is_above_avl r0 k0) (_ : is_balanced_avl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl (Avl_Node k0 d0 l r0 b0) kl) (_ : is_below_avl (Avl_Node kl dl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) k) (_ : @eq nat (S match b0 with | Left_Balanced => S (height_avl l) | Balanced => S (height_avl l) | Right_Balanced => S (height_avl r0) end) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) r b *)
intros Balanced_l below_ll above_l below_avl_l height_l.
(* Goal: rebalance_left_spec k d (Avl_Node kl dl ll Avl_Nil Right_Balanced) r b *)
(* Goal: forall (k0 : Int) (d0 : B) (l r0 : avl_tree) (b0 : bal) (_ : is_avl l) (_ : forall (_ : is_balanced_avl ll l Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl l kl) (_ : is_below_avl (Avl_Node kl dl ll l Right_Balanced) k) (_ : @eq nat (S (height_avl l)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll l Right_Balanced) r b) (_ : is_avl r0) (_ : forall (_ : is_balanced_avl ll r0 Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl r0 kl) (_ : is_below_avl (Avl_Node kl dl ll r0 Right_Balanced) k) (_ : @eq nat (S (height_avl r0)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll r0 Right_Balanced) r b) (_ : is_balanced_avl l r0 b0) (_ : is_below_avl l k0) (_ : is_above_avl r0 k0) (_ : is_balanced_avl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl (Avl_Node k0 d0 l r0 b0) kl) (_ : is_below_avl (Avl_Node kl dl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) k) (_ : @eq nat (S match b0 with | Left_Balanced => S (height_avl l) | Balanced => S (height_avl l) | Right_Balanced => S (height_avl r0) end) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) r b *)
 discriminate height_l.
(* Goal: forall (k0 : Int) (d0 : B) (l r0 : avl_tree) (b0 : bal) (_ : is_avl l) (_ : forall (_ : is_balanced_avl ll l Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl l kl) (_ : is_below_avl (Avl_Node kl dl ll l Right_Balanced) k) (_ : @eq nat (S (height_avl l)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll l Right_Balanced) r b) (_ : is_avl r0) (_ : forall (_ : is_balanced_avl ll r0 Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl r0 kl) (_ : is_below_avl (Avl_Node kl dl ll r0 Right_Balanced) k) (_ : @eq nat (S (height_avl r0)) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll r0 Right_Balanced) r b) (_ : is_balanced_avl l r0 b0) (_ : is_below_avl l k0) (_ : is_above_avl r0 k0) (_ : is_balanced_avl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) (_ : is_below_avl ll kl) (_ : is_above_avl (Avl_Node k0 d0 l r0 b0) kl) (_ : is_below_avl (Avl_Node kl dl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) k) (_ : @eq nat (S match b0 with | Left_Balanced => S (height_avl l) | Balanced => S (height_avl l) | Right_Balanced => S (height_avl r0) end) (S (S (height_avl r)))), rebalance_left_spec k d (Avl_Node kl dl ll (Avl_Node k0 d0 l r0 b0) Right_Balanced) r b *)
intros klr dlr llr rlr blr avl_llr ih_llr avl_rlr ih_rlr; clear ih_llr ih_rlr.
intros Balanced_rl below_llr above_rlr Balanced_l below_ll above_lr
 below_avl_l height_l.
(* Goal: rebalance_left_spec k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b *)
 injection height_l; clear height_l; intros height_l.
exists 
    (Avl_Node klr dlr
       (Avl_Node kl dl ll llr
          match blr with
          | Left_Balanced => Balanced
          | Balanced => Balanced
          | Right_Balanced => Left_Balanced
          end)
       (Avl_Node k d rlr r
          match blr with
          | Left_Balanced => Right_Balanced
          | Balanced => Balanced
          | Right_Balanced => Balanced
          end) Balanced).
(* Goal: and (is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (and (@eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b))) (and (equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) (@eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced))))) *)
repeat apply conj.
(* Goal: forall _ : @eq nat match blr with | Left_Balanced => S (height_avl llr) | Balanced => S (height_avl llr) | Right_Balanced => S (height_avl rlr) end (S (height_avl r)), @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
inversion_clear Balanced_l.
(* Goal: is_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
inversion_clear above_lr.
(* Goal: is_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
inversion_clear below_avl_l.
(* Goal: is_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
inversion_clear H3.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
clear height_l.
(* Goal: forall _ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)), @eq nat (height_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end)) (height_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end)) *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
generalize H; clear H.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
inversion_clear Balanced_rl; simpl in |- *; intros.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection H3; trivial.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection H3; trivial.
(* Goal: is_balanced_avl l r Left_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Left_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Left_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) (has_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Is_Left_Balanced_Avl.
(* Goal: @eq nat (height_avl ll) (S (height_avl llr)) *)
(* Goal: is_avl (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) *)
(* Goal: is_balanced_avl (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced *)
(* Goal: is_below_avl (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) klr *)
(* Goal: is_above_avl (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) klr *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
 rewrite <- H in H3.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection H3; trivial.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
generalize height_l; clear height_l.
(* Goal: forall _ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)), @eq nat (height_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end)) (height_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end)) *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
generalize H; clear H.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
inversion_clear Balanced_rl; simpl in |- *; intros.
(* Goal: is_balanced_avl l r Right_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Right_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Right_Balanced_Avl.
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection height_l; trivial.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection height_l; trivial.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection height_l; trivial.

(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
generalize height_l; clear height_l.
(* Goal: forall _ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)), @eq nat (height_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end)) (height_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end)) *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
generalize H; clear H.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
inversion_clear Balanced_rl; clear blr; simpl in |- *; intros.
(* Goal: @eq nat (S (height_avl ll)) (S (height_avl r)) *)
(* Goal: @eq nat (S (height_avl ll)) (S (height_avl rlr)) *)
(* Goal: @eq nat (S (height_avl ll)) (S (height_avl rlr)) *)
(* Goal: is_below_avl (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) klr *)
(* Goal: is_above_avl (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) klr *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
 rewrite H3.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Below_Avl_Node; try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Above_Avl_Node; try assumption.

(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
clear height_l.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.

 rewrite
 (app_ass (lin_avl ll) ((kl, dl) :: lin_avl llr)
    ((klr, dlr) :: lin_avl rlr ++ (k, d) :: lin_avl r))
 .
 rewrite
 (app_ass (lin_avl ll) ((kl, dl) :: lin_avl llr ++ (klr, dlr) :: lin_avl rlr)
    ((k, d) :: lin_avl r)).
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
 rewrite
 (app_ass (lin_avl llr) ((klr, dlr) :: lin_avl rlr) ((k, d) :: lin_avl r))
 .
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
apply equiv_intro; clear avl_ll avl_llr avl_rlr below_avl_l height_l.
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data), lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data *)
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Left; apply Lookup_Right; apply Lookup_Equal.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
apply Lookup_Left.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Left; assumption.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Right; apply Lookup_Right; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t0.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Right; apply Lookup_Equal.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Left; apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Left; assumption.
(* Goal: lookup key (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) data *)
(* Goal: lookup key (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
inversion_clear H0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Right; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Right; assumption.

(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
clear below_avl_l above_lr below_ll above_rlr below_llr avl_rlr avl_llr.
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b)) *)
(* Goal: equiv (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced) r b) *)
(* Goal: @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
generalize height_l; clear height_l.
(* Goal: forall _ : @eq nat match blr with | Left_Balanced => S (height_avl llr) | Balanced => S (height_avl llr) | Right_Balanced => S (height_avl rlr) end (S (height_avl r)), @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
inversion_clear Balanced_l.
(* Goal: forall _ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)), @eq nat (height_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end)) (height_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end)) *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
generalize H; clear H.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
inversion_clear Balanced_rl; clear blr; simpl in |- *; intros.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; trivial.
Qed.


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



Definition rebalance_right_spec (k : Int) (d : B) (l r : avl_tree) 
(b : bal) : Set :=
  { t : avl_tree | 
      is_avl t /\
      lin_avl t = lin_avl (Avl_Node k d l r b) /\
      equiv t (Avl_Node k d l r b) /\
      match r with
      | Avl_Nil => True
      | Avl_Node _ _ _ _ Left_Balanced => height_avl t = height_avl r
      | Avl_Node _ _ _ _ Balanced => height_avl t = S (height_avl r)
      | Avl_Node _ _ _ _ Right_Balanced => height_avl t = height_avl r
      end }.


Lemma rebalance_right :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl l ->
 is_below_avl l k ->
 is_avl r ->
 is_above_avl r k ->
 S (S (height_avl l)) = height_avl r -> rebalance_right_spec k d l r b.
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : is_below_avl l k) (_ : is_avl r) (_ : is_above_avl r k) (_ : @eq nat (S (S (height_avl l))) (height_avl r)), rebalance_right_spec k d l r b *)
intros k d l r b avl_l below_avl_l avl_r.
(* Goal: forall (_ : is_above_avl r k) (_ : @eq nat (S (S (height_avl l))) (height_avl r)), rebalance_right_spec k d l r b *)
elim avl_r; clear avl_r.

(* r=Avl_Nil *)
(* Goal: forall (_ : is_above_avl Avl_Nil k) (_ : @eq nat (S (S (height_avl l))) (height_avl Avl_Nil)), rebalance_right_spec k d l Avl_Nil b *)
(* Goal: forall (k0 : Int) (d0 : B) (l0 r : avl_tree) (b0 : bal) (_ : is_avl l0) (_ : forall (_ : is_above_avl l0 k) (_ : @eq nat (S (S (height_avl l))) (height_avl l0)), rebalance_right_spec k d l l0 b) (_ : is_avl r) (_ : forall (_ : is_above_avl r k) (_ : @eq nat (S (S (height_avl l))) (height_avl r)), rebalance_right_spec k d l r b) (_ : is_balanced_avl l0 r b0) (_ : is_below_avl l0 k0) (_ : is_above_avl r k0) (_ : is_above_avl (Avl_Node k0 d0 l0 r b0) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node k0 d0 l0 r b0))), rebalance_right_spec k d l (Avl_Node k0 d0 l0 r b0) b *)
intros above_avl_r height_r.
(* Goal: rebalance_right_spec k d l (Avl_Node kr dr Avl_Nil rr Left_Balanced) b *)
(* Goal: forall (k0 : Int) (d0 : B) (l0 r : avl_tree) (b0 : bal) (_ : is_avl l0) (_ : forall (_ : is_balanced_avl l0 rr Left_Balanced) (_ : is_below_avl l0 kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr l0 rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr l0 rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr l0 rr Left_Balanced) b) (_ : is_avl r) (_ : forall (_ : is_balanced_avl r rr Left_Balanced) (_ : is_below_avl r kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr r rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr r rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr r rr Left_Balanced) b) (_ : is_balanced_avl l0 r b0) (_ : is_below_avl l0 k0) (_ : is_above_avl r k0) (_ : is_balanced_avl (Avl_Node k0 d0 l0 r b0) rr Left_Balanced) (_ : is_below_avl (Avl_Node k0 d0 l0 r b0) kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr (Avl_Node k0 d0 l0 r b0) rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node k0 d0 l0 r b0) rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr (Avl_Node k0 d0 l0 r b0) rr Left_Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
 discriminate height_r.

(* r=(Avl_Node kr dr lr rr br) *)
(* Goal: forall (k0 : Int) (d0 : B) (l0 r : avl_tree) (b0 : bal) (_ : is_avl l0) (_ : forall (_ : is_above_avl l0 k) (_ : @eq nat (S (S (height_avl l))) (height_avl l0)), rebalance_right_spec k d l l0 b) (_ : is_avl r) (_ : forall (_ : is_above_avl r k) (_ : @eq nat (S (S (height_avl l))) (height_avl r)), rebalance_right_spec k d l r b) (_ : is_balanced_avl l0 r b0) (_ : is_below_avl l0 k0) (_ : is_above_avl r k0) (_ : is_above_avl (Avl_Node k0 d0 l0 r b0) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node k0 d0 l0 r b0))), rebalance_right_spec k d l (Avl_Node k0 d0 l0 r b0) b *)
intros kr dr lr rr br avl_lr ih_lr avl_rr ih_rr.
(* Goal: forall (_ : is_balanced_avl lr rr br) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr br) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr br))), rebalance_right_spec k d l (Avl_Node kr dr lr rr br) b *)
clear ih_lr ih_rr.
(* Goal: forall (_ : is_balanced_avl lr rr br) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr br) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr br))), rebalance_right_spec k d l (Avl_Node kr dr lr rr br) b *)
case br; clear br.

(* br=Left_Balanced => double RL-rotation *)
(* Goal: forall (_ : is_balanced_avl lr rr Left_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Left_Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
elim avl_lr; clear avl_lr lr.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (S (height_avl rr))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
intros Balanced_r below_lr above_rr above_avl_r height_r.
(* Goal: rebalance_right_spec k d l (Avl_Node kr dr Avl_Nil rr Left_Balanced) b *)
(* Goal: forall (k0 : Int) (d0 : B) (l0 r : avl_tree) (b0 : bal) (_ : is_avl l0) (_ : forall (_ : is_balanced_avl l0 rr Left_Balanced) (_ : is_below_avl l0 kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr l0 rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr l0 rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr l0 rr Left_Balanced) b) (_ : is_avl r) (_ : forall (_ : is_balanced_avl r rr Left_Balanced) (_ : is_below_avl r kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr r rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr r rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr r rr Left_Balanced) b) (_ : is_balanced_avl l0 r b0) (_ : is_below_avl l0 k0) (_ : is_above_avl r k0) (_ : is_balanced_avl (Avl_Node k0 d0 l0 r b0) rr Left_Balanced) (_ : is_below_avl (Avl_Node k0 d0 l0 r b0) kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr (Avl_Node k0 d0 l0 r b0) rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node k0 d0 l0 r b0) rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr (Avl_Node k0 d0 l0 r b0) rr Left_Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
 discriminate height_r.
(* Goal: forall (k0 : Int) (d0 : B) (l0 r : avl_tree) (b0 : bal) (_ : is_avl l0) (_ : forall (_ : is_balanced_avl l0 rr Left_Balanced) (_ : is_below_avl l0 kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr l0 rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr l0 rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr l0 rr Left_Balanced) b) (_ : is_avl r) (_ : forall (_ : is_balanced_avl r rr Left_Balanced) (_ : is_below_avl r kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr r rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr r rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr r rr Left_Balanced) b) (_ : is_balanced_avl l0 r b0) (_ : is_below_avl l0 k0) (_ : is_above_avl r k0) (_ : is_balanced_avl (Avl_Node k0 d0 l0 r b0) rr Left_Balanced) (_ : is_below_avl (Avl_Node k0 d0 l0 r b0) kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr (Avl_Node k0 d0 l0 r b0) rr Left_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node k0 d0 l0 r b0) rr Left_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr (Avl_Node k0 d0 l0 r b0) rr Left_Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
intros krl drl lrl rrl brl avl_lrl ih_lrl avl_rrl ih_rrl; clear ih_lrl ih_rrl.
intros Balanced_lr below_lrl above_rrl Balanced_r below_lr above_rr
 above_avl_r height_r.
exists
    (Avl_Node krl drl
       (Avl_Node k d l lrl
          match brl with
          | Left_Balanced => Balanced
          | Balanced => Balanced
          | Right_Balanced => Left_Balanced
          end)
       (Avl_Node kr dr rrl rr
          match brl with
          | Left_Balanced => Right_Balanced
          | Balanced => Balanced
          | Right_Balanced => Balanced
          end) Balanced).
(* Goal: and (is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (and (@eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b))) (and (equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) (@eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced))))) *)
repeat apply conj.
(* Goal: is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) *)
(* Goal: equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
inversion_clear Balanced_r.
(* Goal: is_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
inversion_clear below_lr.
(* Goal: is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) *)
(* Goal: equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
inversion_clear above_avl_r.
(* Goal: is_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
inversion_clear H3.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
generalize height_r;
(* Goal: is_balanced_avl rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end *)
(* Goal: is_balanced_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
 clear height_r H5 H4 H2 H1 H0 above_rr above_rrl below_lrl.
(* Goal: forall _ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)), @eq nat (height_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end)) (height_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end)) *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
generalize H; clear H.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
inversion_clear Balanced_lr; clear brl; simpl in |- *; intros.
(* blr=Left_Balanced *)
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection height_r; trivial.
(* blr=Balanced *)
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection height_r; trivial.
(* blr=Right_Balanced *)
(* Goal: is_balanced_avl l r Left_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Left_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Left_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) (has_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Is_Left_Balanced_Avl.
(* Goal: @eq nat (S match br0 with | Left_Balanced => S (height_avl lr0) | Balanced => S (height_avl lr0) | Right_Balanced => S (height_avl rr0) end) (S (S (height_avl l0))) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
 rewrite H.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection height_r; trivial.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end *)
(* Goal: is_balanced_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
clear height_r H5 H4 H2 H1 H0 above_rr above_rrl below_lrl.
(* Goal: forall _ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)), @eq nat (height_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end)) (height_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end)) *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
generalize H; clear H.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
inversion_clear Balanced_lr; clear brl; simpl in |- *; intros.
(* brl=Left_Balanced *)
(* Goal: is_balanced_avl l r Right_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Right_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Right_Balanced_Avl.
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection H0; trivial.
(* brl=Balanced *)
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection H0; trivial.
(* brl=Right_Balanced *)
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection H0; trivial.

(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
generalize height_r;
(* Goal: is_balanced_avl rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end *)
(* Goal: is_balanced_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
 clear height_r H5 H4 H2 H1 H0 above_rr above_rrl below_lrl.
(* Goal: forall _ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)), @eq nat (height_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end)) (height_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end)) *)
(* Goal: is_below_avl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) krl *)
(* Goal: is_above_avl (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) krl *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b)) *)
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
generalize H; clear H.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
inversion_clear Balanced_lr; clear brl; simpl in |- *; intros.
(* brl=Left_Balanced *)
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Left_Balanced)) (S (S (height_avl r0))) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H0.
(* Goal: rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
 injection height_r; clear height_r; intro height_r.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite height_r; trivial.
(* brl=Balanced *)
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
 injection height_r; clear height_r; intro height_r.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite height_r; trivial.
(* brl=Right_Balanced *)
(* Goal: rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
 injection height_r; clear height_r; intro height_r.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite height_r; trivial.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Below_Avl_Node; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Above_Avl_Node; assumption.

clear height_r above_avl_r above_rr below_lr Balanced_r above_rrl below_lrl
 Balanced_lr.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
 rewrite
 (app_ass (lin_avl l) ((k, d) :: lin_avl lrl)
    ((krl, drl) :: lin_avl rrl ++ (kr, dr) :: lin_avl rr))
 .
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
 rewrite
 (app_ass (lin_avl lrl) ((krl, drl) :: lin_avl rrl) ((kr, dr) :: lin_avl rr))
 .
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

clear height_r above_avl_r above_rr below_lr Balanced_r above_rrl below_lrl
 Balanced_lr.
(* Goal: equiv (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) (Avl_Node k d l (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
apply equiv_intro.
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data), lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data *)
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Right; apply Lookup_Left; apply Lookup_Equal.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Left; apply Lookup_Left; assumption.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Right; apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Left; apply Lookup_Right; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Right; assumption.

(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t0.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Left; apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Left; assumption.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Right; apply Lookup_Equal.
(* Goal: lookup key (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) data *)
(* Goal: lookup key (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
inversion_clear H0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Right; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Right; assumption.

(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
clear above_avl_r above_rr below_lr above_rrl below_lrl.
(* Goal: @eq nat (height_avl (Avl_Node krl drl (Avl_Node k d l lrl match brl with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node kr dr rrl rr match brl with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kr dr (Avl_Node krl drl lrl rrl brl) rr Left_Balanced)) *)
(* Goal: forall (_ : is_balanced_avl lr rr Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
generalize height_r; clear height_r.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim brl; simpl in |- *; trivial.

(* br=Balanced *)
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (S (height_avl rr))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
intros Balanced_r below_lr above_rr above_avl_r height_r.
(* Goal: rebalance_right_spec k d l (Avl_Node kr dr lr rr Balanced) b *)
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (height_avl (Avl_Node kr dr lr rr Right_Balanced))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
exists (Avl_Node kr dr (Avl_Node k d l lr Right_Balanced) rr Left_Balanced).
(* Goal: and (is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (and (@eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b))) (and (equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) (@eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced))))) *)
repeat apply conj.
(* Goal: is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) *)
(* Goal: equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
inversion_clear above_avl_r.
(* Goal: rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
 injection height_r; clear height_r; intro height_r.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Right_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Right_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Right_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_balanced_avl l r Left_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Left_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Left_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) (has_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Is_Left_Balanced_Avl.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) *)
(* Goal: equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
inversion_clear Balanced_r.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H1; trivial.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Below_Avl_Node; assumption.

(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
 rewrite
 (app_ass (lin_avl l) ((k, d) :: lin_avl lr) ((kr, dr) :: lin_avl rr))
 .
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
apply equiv_intro; clear above_avl_r height_r.
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data), lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data *)
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Right; apply Lookup_Equal.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Right; assumption.

(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t0.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Left; apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Left; assumption.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Right; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* br=Right_Balanced *)
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall (_ : is_balanced_avl lr rr Right_Balanced) (_ : is_below_avl lr kr) (_ : is_above_avl rr kr) (_ : is_above_avl (Avl_Node kr dr lr rr Right_Balanced) k) (_ : @eq nat (S (S (height_avl l))) (S (height_avl rr))), rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
intros Balanced_r below_lr above_rr above_avl_r height_r.
(* Goal: rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
 injection height_r; clear height_r; intro height_r.
(* Goal: rebalance_right_spec k d l (Avl_Node kr dr lr rr Right_Balanced) b *)
exists (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced).
(* Goal: and (is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (and (@eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b))) (and (equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) (@eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced))))) *)
repeat apply conj.
(* Goal: is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) *)
(* Goal: equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
inversion_clear above_avl_r.
(* Goal: is_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) *)
(* Goal: equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
inversion_clear Balanced_r.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl l) (height_avl lr) *)
(* Goal: is_balanced_avl (Avl_Node k d l lr Balanced) rr Balanced *)
(* Goal: is_below_avl (Avl_Node k d l lr Balanced) kr *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (lin_avl (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b)) *)
(* Goal: equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
 rewrite <- height_r in H1.
symmetry  in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection H1; trivial.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Below_Avl_Node; assumption.

(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
 rewrite
 (app_ass (lin_avl l) ((k, d) :: lin_avl lr) ((kr, dr) :: lin_avl rr))
 .
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: equiv (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
apply equiv_intro; clear above_avl_r height_r.
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data), lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data *)
(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Right; apply Lookup_Equal.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; apply Lookup_Right; assumption.

(* Goal: forall (key : Int) (data : B) (_ : lookup key (Avl_Node k d l (Avl_Node kr dr lr rr Right_Balanced) b) data), lookup key (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced) data *)
(* Goal: @eq nat (height_avl (Avl_Node kr dr (Avl_Node k d l lr Balanced) rr Balanced)) (height_avl (Avl_Node kr dr lr rr Right_Balanced)) *)
intros key data lookup_t0.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Left; apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Left; assumption.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; apply Lookup_Right; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite height_r; trivial.
Qed.

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

Inductive is_balanced_avl_left_shift (l r : avl_tree) : bal -> Prop :=
  | Is_Left_Balanced_Avl_Left_Shift :
      height_avl l = S (S (height_avl r)) ->
      is_balanced_avl_left_shift l r Left_Balanced
  | Is_Fully_Balanced_Avl_Left_Shift :
      height_avl l = S (height_avl r) ->
      is_balanced_avl_left_shift l r Balanced
  | Is_Right_Balanced_Avl_Left_Shift :
      height_avl l = height_avl r ->
      is_balanced_avl_left_shift l r Right_Balanced.



Lemma is_left_balanced_is_left_balanced_left_shift :
 forall (l0 l r0 : avl_tree) (b0 : bal),
 is_balanced_avl l0 r0 b0 ->
 height_avl l = S (height_avl l0) -> is_balanced_avl_left_shift l r0 b0.
(* Goal: forall (l0 l r0 : avl_tree) (b0 : bal) (_ : is_balanced_avl l0 r0 b0) (_ : @eq nat (height_avl l) (S (height_avl l0))), is_balanced_avl_left_shift l r0 b0 *)
intros l0 l r0 b0 Balanced_l0 height_l.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
inversion_clear Balanced_l0.
(* Goal: is_balanced_avl_left_shift l0 r Left_Balanced *)
(* Goal: is_balanced_avl_left_shift l0 r Balanced *)
(* Goal: is_balanced_avl_left_shift l0 r Right_Balanced *)
apply Is_Left_Balanced_Avl_Left_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite <- H; assumption.
(* Goal: is_balanced_avl_left_shift l0 r Balanced *)
(* Goal: is_balanced_avl_left_shift l0 r Right_Balanced *)
apply Is_Fully_Balanced_Avl_Left_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite <- H; assumption.
(* Goal: is_balanced_avl_left_shift l0 r Right_Balanced *)
apply Is_Right_Balanced_Avl_Left_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite <- H; assumption.
Qed.


Lemma is_balanced_is_balanced_left_shift_false :
 forall (l r : avl_tree) (b : bal),
 is_balanced_avl l r b -> is_balanced_avl_left_shift l r b -> False.
(* Goal: forall (l r : avl_tree) (b : bal) (_ : is_balanced_avl l r b) (_ : is_balanced_avl_right_shift l r b), False *)
intros l r b Balanced_l.
inversion_clear Balanced_l; intros Balanced_shift_l;
(* Goal: @eq nat (S (height_avl l)) (S (height_avl r)) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
 inversion_clear Balanced_shift_l.
(* Goal: False *)
(* Goal: False *)
(* Goal: False *)
apply n_Sn_false with (S (height_avl r)).
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Left_Balanced)) (S (S (height_avl r0))) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
symmetry  in |- *; assumption.
(* Goal: False *)
(* Goal: False *)
(* Goal: False *)
apply n_Sn_false with (height_avl r).
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Left_Balanced)) (S (S (height_avl r0))) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
symmetry  in |- *; assumption.
(* Goal: False *)
(* Goal: False *)
apply n_Sn_false with (height_avl l).
(* Goal: @eq nat (S match br0 with | Left_Balanced => S (height_avl lr0) | Balanced => S (height_avl lr0) | Right_Balanced => S (height_avl rr0) end) (S (S (height_avl l0))) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
 rewrite H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.

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

Inductive is_balanced_avl_right_shift (l r : avl_tree) : bal -> Prop :=
  | Is_Left_Balanced_Avl_Right_Shift :
      height_avl l = height_avl r ->
      is_balanced_avl_right_shift l r Left_Balanced
  | Is_Fully_Balanced_Avl_Right_Shift :
      S (height_avl l) = height_avl r ->
      is_balanced_avl_right_shift l r Balanced
  | Is_Right_Balanced_Avl_Right_Shift :
      S (S (height_avl l)) = height_avl r ->
      is_balanced_avl_right_shift l r Right_Balanced.



Lemma is_balanced_avl_is_balanced_avl_right_shift :
 forall (l0 r r0 : avl_tree) (b0 : bal),
 is_balanced_avl l0 r0 b0 ->
 height_avl r = S (height_avl r0) -> is_balanced_avl_right_shift l0 r b0.
(* Goal: forall (l0 r r0 : avl_tree) (b0 : bal) (_ : is_balanced_avl l0 r0 b0) (_ : @eq nat (height_avl r) (S (height_avl r0))), is_balanced_avl_right_shift l0 r b0 *)
intros l0 r r0 b0 Balanced_r0 height_l.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
inversion_clear Balanced_r0.
(* Goal: is_balanced_avl_right_shift l r0 Left_Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
apply Is_Left_Balanced_Avl_Right_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite H; symmetry  in |- *; assumption.
(* Goal: is_balanced_avl_right_shift l r0 Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
apply Is_Fully_Balanced_Avl_Right_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite H; symmetry  in |- *; assumption.
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
apply Is_Right_Balanced_Avl_Right_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite H; symmetry  in |- *; assumption.
Qed.


Lemma is_balanced_avl_is_balanced_avl_right_shift_false :
 forall (l r : avl_tree) (b : bal),
 is_balanced_avl l r b -> is_balanced_avl_right_shift l r b -> False.
(* Goal: forall (l r : avl_tree) (b : bal) (_ : is_balanced_avl l r b) (_ : is_balanced_avl_right_shift l r b), False *)
intros l r b Balanced_l.
inversion_clear Balanced_l; intros Balanced_shift_l;
(* Goal: @eq nat (S (height_avl l)) (S (height_avl r)) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
 inversion_clear Balanced_shift_l.
(* Goal: False *)
(* Goal: False *)
(* Goal: False *)
apply n_Sn_false with (height_avl r).
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
symmetry  in |- *; assumption.
(* Goal: False *)
(* Goal: False *)
apply n_Sn_false with (height_avl l).
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl l)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite H0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: False *)
apply n_Sn_false with (S (height_avl l)).
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl l)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite H0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.

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


Inductive hasnot_grown_left (t : avl_tree) (k : Int) 
(d : B) (l r : avl_tree) : bal -> Prop :=
  | Hasnot_Grown_Left_Bal :
      forall b : bal,
      is_balanced_avl l r b ->
      height_avl t = height_avl (Avl_Node k d l r b) ->
      hasnot_grown_left t k d l r b
  | Hasnot_Grown_Left_Shift_Left :
      is_balanced_avl_left_shift l r Left_Balanced ->
      height_avl t = height_avl l ->
      hasnot_grown_left t k d l r Left_Balanced
  | Hasnot_Grown_Left_Shift_Right :
      is_balanced_avl_left_shift l r Right_Balanced ->
      height_avl t = S (height_avl l) ->
      hasnot_grown_left t k d l r Right_Balanced.


Inductive has_grown_left (t : avl_tree) (k : Int) (d : B) 
(l r : avl_tree) : bal -> Prop :=
  | Has_Grown_Left_Shift_Left :
      is_balanced_avl_left_shift l r Left_Balanced ->
      height_avl t = S (height_avl l) ->
      has_grown_left t k d l r Left_Balanced
  | Has_Grown_Left_Shift_Balanced :
      is_balanced_avl_left_shift l r Balanced ->
      height_avl t = S (height_avl l) -> has_grown_left t k d l r Balanced.


Inductive bal_grow_left_spec (k : Int) (d : B) (l r : avl_tree) 
(b : bal) : Set :=
    Balance_Grow_Left_Spec_Intro :
      forall t : avl_tree,
      is_avl t ->
      lin_avl t = lin_avl (Avl_Node k d l r b) ->
      equiv t (Avl_Node k d l r b) ->
      {hasnot_grown_left t k d l r b} + {has_grown_left t k d l r b} ->
      bal_grow_left_spec k d l r b.


Lemma balance_left :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl l ->
 is_below_avl l k ->
 is_avl r ->
 is_above_avl r k ->
 {is_balanced_avl l r b} + {is_balanced_avl_left_shift l r b} ->
 bal_grow_left_spec k d l r b.
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : is_below_avl l k) (_ : is_avl r) (_ : is_above_avl r k) (_ : sumbool (is_balanced_avl l r b) (is_balanced_avl_right_shift l r b)), bal_shrunk_right_spec k d l r b *)
intros k d l r b avl_l below_avl_l avl_r above_avl_r bal_or_shift.
(* Goal: bal_shrunk_right_spec k d l r b *)
elim bal_or_shift; clear bal_or_shift.
(* l and r is Balanced with respect to b *)
(* Goal: forall _ : is_balanced_avl l r b, bal_shrunk_right_spec k d l r b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
intro Balanced_l.
(* Goal: bal_grow_left_spec k d l r b *)
(* Goal: forall _ : is_balanced_avl_left_shift l r b, bal_grow_left_spec k d l r b *)
apply Balance_Grow_Left_Spec_Intro with (Avl_Node k d l r b). 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: hasnot_grown_left (Avl_Node k d l r b) k d l r b *)
(* Goal: forall _ : is_balanced_avl_left_shift l r b, bal_grow_left_spec k d l r b *)
apply Hasnot_Grown_Left_Bal. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* l and r is'nt Balanced with respect to b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
elim b; clear b; intros Balanced_shift_l.
(* b=Left_Balanced *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
elim (rebalance_left k d l r Left_Balanced); try assumption.
(* Goal: forall (x : avl_tree) (_ : and (is_avl x) (and (@eq (list (prod Int B)) (lin_avl x) (lin_avl (Avl_Node k d l r Right_Balanced))) (and (equiv x (Avl_Node k d l r Right_Balanced)) match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl x) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl x) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl x) (height_avl r) end))), bal_grow_right_spec k d l r Right_Balanced *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intros t (avl_t,(lin,(equiv_t,height_t))).
(* Goal: bal_grow_left_spec k d l r Left_Balanced *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_grow_left_spec k d l r Balanced *)
(* Goal: bal_grow_left_spec k d l r Right_Balanced *)
apply Balance_Grow_Left_Spec_Intro with t.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: sumbool (hasnot_grown_left t k d l r Left_Balanced) (has_grown_left t k d l r Left_Balanced) *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_grow_left_spec k d l r Balanced *)
(* Goal: bal_grow_left_spec k d l r Right_Balanced *)
clear lin equiv_t avl_l below_avl_l.
(* Goal: sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
generalize height_t; clear height_t.
(* Goal: forall _ : match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl t) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl t) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl t) (height_avl r) end, sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
generalize Balanced_shift_l; clear Balanced_shift_l.
(* Goal: forall (_ : is_balanced_avl_left_shift l r Left_Balanced) (_ : match l with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl t) (height_avl l) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl t) (S (height_avl l)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl t) (height_avl l) end), sumbool (hasnot_shrunk_left t k d l r Left_Balanced) (has_shrunk_left t k d l r Left_Balanced) *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
case l; clear l.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intro u0. 
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
inversion_clear u0.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
 discriminate H.
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_left_shift (Avl_Node i b a a0 b0) r Left_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_left t k d (Avl_Node i b a a0 b0) r Left_Balanced) (has_shrunk_left t k d (Avl_Node i b a a0 b0) r Left_Balanced) *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
intros kl dl ll rl bl.
(* Goal: forall (_ : is_balanced_avl_left_shift (Avl_Node kl dl ll rl bl) r Left_Balanced) (_ : match bl with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node kl dl ll rl bl)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node kl dl ll rl bl))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node kl dl ll rl bl)) end), sumbool (hasnot_shrunk_left t k d (Avl_Node kl dl ll rl bl) r Left_Balanced) (has_shrunk_left t k d (Avl_Node kl dl ll rl bl) r Left_Balanced) *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
elim bl; clear bl; simpl in |- *; intros Balanced_shift_l height_t.
(* bl=Left_Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Hasnot_Grown_Left_Shift_Left; assumption.
(* bl=Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Has_Grown_Left_Shift_Left; assumption.
(* bl=Right_Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Hasnot_Grown_Left_Shift_Left; assumption.
(* side premisses of (Elim (rebalance ... )) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.

(* b=Balanced *)
(* Goal: bal_grow_left_spec k d l r Balanced *)
(* Goal: bal_grow_left_spec k d l r Right_Balanced *)
apply Balance_Grow_Left_Spec_Intro with (Avl_Node k d l r Left_Balanced).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Left_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Left_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Left_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) (has_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Is_Left_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: has_grown_left (Avl_Node k d l r Left_Balanced) k d l r Balanced *)
(* Goal: bal_grow_left_spec k d l r Right_Balanced *)
apply Has_Grown_Left_Shift_Balanced. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* b=Right_Balanced *)
(* Goal: bal_grow_left_spec k d l r Right_Balanced *)
apply Balance_Grow_Left_Spec_Intro with (Avl_Node k d l r Balanced).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *. 
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: hasnot_grown_left (Avl_Node k d l r Balanced) k d l r Right_Balanced *)
apply Hasnot_Grown_Left_Shift_Right. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
Qed.



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


Inductive hasnot_grown_right (t : avl_tree) (k : Int) 
(d : B) (l r : avl_tree) : bal -> Prop :=
  | Hasnot_Grown_Right_Bal :
      forall b : bal,
      is_balanced_avl l r b ->
      height_avl t = height_avl (Avl_Node k d l r b) ->
      hasnot_grown_right t k d l r b
  | Hasnot_Grown_Right_Shift_Left :
      is_balanced_avl_right_shift l r Left_Balanced ->
      height_avl t = S (height_avl r) ->
      hasnot_grown_right t k d l r Left_Balanced
  | Hasnot_Grown_Right_Shift_Right :
      is_balanced_avl_right_shift l r Right_Balanced ->
      height_avl t = height_avl r ->
      hasnot_grown_right t k d l r Right_Balanced.


Inductive has_grown_right (t : avl_tree) (k : Int) 
(d : B) (l r : avl_tree) : bal -> Prop :=
  | Has_Grown_Right_Shift_Balanced :
      is_balanced_avl_right_shift l r Balanced ->
      height_avl t = S (height_avl r) -> has_grown_right t k d l r Balanced
  | Has_Grown_Right_Shift_Right :
      is_balanced_avl_right_shift l r Right_Balanced ->
      height_avl t = S (height_avl r) ->
      has_grown_right t k d l r Right_Balanced.



Inductive bal_grow_right_spec (k : Int) (d : B) (l r : avl_tree) 
(b : bal) : Set :=
    Balance_Grow_Right_Spec_Intro :
      forall t : avl_tree,
      is_avl t ->
      lin_avl t = lin_avl (Avl_Node k d l r b) ->
      equiv t (Avl_Node k d l r b) ->
      {hasnot_grown_right t k d l r b} + {has_grown_right t k d l r b} ->
      bal_grow_right_spec k d l r b.


Lemma balance_right :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl l ->
 is_below_avl l k ->
 is_avl r ->
 is_above_avl r k ->
 {is_balanced_avl l r b} + {is_balanced_avl_right_shift l r b} ->
 bal_grow_right_spec k d l r b.
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : is_below_avl l k) (_ : is_avl r) (_ : is_above_avl r k) (_ : sumbool (is_balanced_avl l r b) (is_balanced_avl_right_shift l r b)), bal_shrunk_right_spec k d l r b *)
intros k d l r b avl_l below_avl_l avl_r above_avl_r bal_or_shift.
(* Goal: bal_shrunk_right_spec k d l r b *)
elim bal_or_shift; clear bal_or_shift.
(* l and r is Balanced with respect to b *)
(* Goal: forall _ : is_balanced_avl l r b, bal_shrunk_right_spec k d l r b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
intro Balanced_l.
(* Goal: bal_grow_right_spec k d l r b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_grow_right_spec k d l r b *)
apply Balance_Grow_Right_Spec_Intro with (Avl_Node k d l r b). 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: hasnot_grown_right (Avl_Node k d l r b) k d l r b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_grow_right_spec k d l r b *)
apply Hasnot_Grown_Right_Bal. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* l and r is'nt Balanced with respect to b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
elim b; clear b; intros Balanced_shift_l.
(* b=Left_Balanced *)
(* Goal: bal_grow_right_spec k d l r Left_Balanced *)
(* Goal: bal_grow_right_spec k d l r Balanced *)
(* Goal: bal_grow_right_spec k d l r Right_Balanced *)
apply Balance_Grow_Right_Spec_Intro with (Avl_Node k d l r Balanced).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *. 
(* Goal: hasnot_grown_right (Avl_Node k d l r Balanced) k d l r Left_Balanced *)
(* Goal: bal_grow_right_spec k d l r Balanced *)
(* Goal: bal_grow_right_spec k d l r Right_Balanced *)
apply Hasnot_Grown_Right_Shift_Left. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq nat (S (height_avl l)) (S (height_avl r)) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
inversion_clear Balanced_shift_l.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.

(* b=Balanced *)
(* Goal: bal_grow_right_spec k d l r Balanced *)
(* Goal: bal_grow_right_spec k d l r Right_Balanced *)
apply Balance_Grow_Right_Spec_Intro with (Avl_Node k d l r Right_Balanced).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Right_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Right_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Right_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: has_grown_right (Avl_Node k d l r Right_Balanced) k d l r Balanced *)
(* Goal: bal_grow_right_spec k d l r Right_Balanced *)
apply Has_Grown_Right_Shift_Balanced. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* b=Right_Balanced *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
elim (rebalance_right k d l r Right_Balanced); try assumption.
(* Goal: forall (x : avl_tree) (_ : and (is_avl x) (and (@eq (list (prod Int B)) (lin_avl x) (lin_avl (Avl_Node k d l r Right_Balanced))) (and (equiv x (Avl_Node k d l r Right_Balanced)) match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl x) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl x) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl x) (height_avl r) end))), bal_grow_right_spec k d l r Right_Balanced *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intros t (avl_t,(lin,(equiv_t,height_t))).
(* Goal: bal_grow_right_spec k d l r Right_Balanced *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
apply Balance_Grow_Right_Spec_Intro with t.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: sumbool (hasnot_grown_right t k d l r Right_Balanced) (has_grown_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
clear lin equiv_t avl_l below_avl_l avl_r above_avl_r.
(* Goal: sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
generalize height_t; clear height_t.
(* Goal: forall _ : match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl t) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl t) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl t) (height_avl r) end, sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
generalize Balanced_shift_l; clear Balanced_shift_l.
(* Goal: forall (_ : is_balanced_avl_right_shift l r Right_Balanced) (_ : match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl t) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl t) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl t) (height_avl r) end), sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
case r; clear r.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intro u0. 
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
inversion_clear u0.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
 discriminate H.
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intros kr dr lr rr br.
(* Goal: forall (_ : is_balanced_avl_right_shift l (Avl_Node kr dr lr rr br) Right_Balanced) (_ : match br with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node kr dr lr rr br)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node kr dr lr rr br))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node kr dr lr rr br)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node kr dr lr rr br) Right_Balanced) (has_shrunk_right t k d l (Avl_Node kr dr lr rr br) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
elim br; clear br; simpl in |- *; intros Balanced_shift_l height_t.
(* br=Left_Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Hasnot_Grown_Right_Shift_Right; assumption.
(* br=Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Has_Grown_Right_Shift_Right; assumption.
(* br=Right_Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Hasnot_Grown_Right_Shift_Right; assumption.
(* side premisses of (Elim (rebalance ... )) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
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.

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).
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H2; assumption.
Qed.


Lemma inv_equiv_ins_equal1 :
 forall (key : Int) (update : B -> B) (init : B) (t0 t : avl_tree) (k : Int),
 equiv_ins key update init t0 t ->
 Equal k key ->
 (forall data : B, lookup k t0 data -> False) -> lookup k t (update init).
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H3; assumption.
Qed.


Lemma inv_equiv_ins_notequal0 :
 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 data.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H4; assumption.
Qed.

Lemma inv_equiv_ins_notequal1 :
 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 t data -> lookup k t0 data.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H5; assumption.
Qed.


Lemma equiv_ins_equiv_equiv_ins :
 forall (key : Int) (update : B -> B) (init : B) (t0 t1 t2 : avl_tree),
 equiv_ins key update init t0 t1 ->
 equiv t1 t2 -> equiv_ins key update init t0 t2.
(* Goal: forall (key : Int) (update : forall _ : B, B) (init : B) (t0 t1 t2 : avl_tree) (_ : equiv_ins key update init t0 t1) (_ : equiv t1 t2), equiv_ins key update init t0 t2 *)
intros key update init t0 t1 t2 equiv_ins0 equiv0.
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b) *)
apply equiv_ins_intro.

(* Goal: forall (k : Int) (data : B) (_ : Equal k key) (_ : lookup k t0 data), lookup k t2 (update data) *)
(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k t0 data), False), lookup k t2 (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t0 data), lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
intros k data equal Lookup_t0.
(* Goal: lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
apply (inv_equiv_t0_t1 t1 t2).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (inv_equiv_ins_equal0 key update init t0 t1 k data); assumption.

(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k t0 data), False), lookup k t2 (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t0 data), lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
intros k equal not_Lookup_t0.
(* Goal: lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
apply (inv_equiv_t0_t1 t1 t2).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (inv_equiv_ins_equal1 key update init t0 t1 k); assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t0 data), lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
intros k data notequal Lookup_t0.
(* Goal: lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
apply (inv_equiv_t0_t1 t1 t2).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (inv_equiv_ins_notequal0 key update init t0 t1 k data); assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
intros k data notequal Lookup_t2.
(* Goal: lookup k t0 data *)
apply (inv_equiv_ins_notequal1 key update init t0 t1 k data).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (inv_equiv_t1_t0 t1 t2); assumption.

Qed.




Lemma equiv_ins_below :
 forall (key : Int) (update : B -> B) (init : B) (t0 t : avl_tree) (k0 : Int),
 equiv_ins key update init t0 t ->
 Less key k0 -> is_below t0 k0 -> is_below t k0.
(* Goal: forall (key : Int) (update : forall _ : B, B) (init : B) (t0 t : avl_tree) (k0 : Int) (_ : equiv_ins key update init t0 t) (_ : Less key k0) (_ : is_below t0 k0), is_below t k0 *)
intros key update init t0 t k0 equiv_t0 less below_t0.
(* Goal: is_below t k *)
apply lookup_less_below.
(* Goal: forall (k : Int) (d : B) (_ : lookup k t d), Less k0 k *)
intros k d lookup_t.
(* Goal: Less k0 k *)
elim (equal_dec k key).

(* Goal: forall _ : Equal k key, Less k0 k *)
(* Goal: forall _ : not (Equal k key), Less k0 k *)
intro equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (equal_less_less k key k0); assumption.

(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro notequal.
generalize
 (inv_equiv_ins_notequal1 key update init t0 t k d equiv_t0 notequal lookup_t).
(* Goal: forall _ : lookup k (Avl_Node k0 d0 l0 r0 b0) data, lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro lookup_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_below_less k t0 d); assumption.
Qed.



Lemma equiv_ins_above :
 forall (key : Int) (update : B -> B) (init : B) (t0 t : avl_tree) (k0 : Int),
 equiv_ins key update init t0 t ->
 Less k0 key -> is_above t0 k0 -> is_above t k0.
(* Goal: forall (key : Int) (update : forall _ : B, B) (init : B) (t0 t : avl_tree) (k0 : Int) (_ : equiv_ins key update init t0 t) (_ : Less k0 key) (_ : is_above t0 k0), is_above t k0 *)
intros key update init t0 t k0 equiv_t0 greater below_t0.
(* Goal: is_above t k *)
apply lookup_greater_above.
(* Goal: forall (k : Int) (d : B) (_ : lookup k t d), Less k0 k *)
intros k d lookup_t.
(* Goal: Less k0 k *)
elim (equal_dec k key).

(* Goal: forall _ : Equal k key, Less k0 k *)
(* Goal: forall _ : not (Equal k key), Less k0 k *)
intro equal.
(* Goal: Less k0 k *)
(* Goal: forall _ : not (Equal k key), Less k0 k *)
apply (less_equal_less k0 key k).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equal_sym; assumption.

(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro notequal.
generalize
 (inv_equiv_ins_notequal1 key update init t0 t k d equiv_t0 notequal lookup_t).
(* Goal: forall _ : lookup k (Avl_Node k0 d0 l0 r0 b0) data, lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro lookup_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_above_greater k t0 d); assumption.
Qed.

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

Lemma leave_is_avl :
 forall (k : Int) (d : B), is_avl (Avl_Node k d Avl_Nil Avl_Nil Balanced).
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: is_avl (Avl_Node k d' l r b) *)
apply Node_Is_Avl.
(* Goal: is_avl Avl_Nil *)
(* Goal: is_balanced_avl Avl_Nil Avl_Nil Balanced *)
(* Goal: is_below_avl Avl_Nil k *)
(* Goal: is_above_avl Avl_Nil k *)
apply Nil_Is_Avl.
(* Goal: is_avl Avl_Nil *)
(* Goal: is_balanced_avl Avl_Nil Avl_Nil Balanced *)
(* Goal: is_below_avl Avl_Nil k *)
(* Goal: is_above_avl Avl_Nil k *)
apply Nil_Is_Avl.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply Is_Fully_Balanced_Avl; trivial.
(* Goal: is_below_avl Avl_Nil k *)
(* Goal: is_above_avl Avl_Nil k *)
apply Below_Avl_Nil.
(* Goal: is_above_avl Avl_Nil k *)
apply Above_Avl_Nil.
Qed.


Lemma equiv_ins_nil :
 forall (key : Int) (update : B -> B) (init : B),
 equiv_ins key update init Avl_Nil
   (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced).
(* Goal: forall (key : Int) (update : forall _ : B, B) (init : B), equiv_ins key update init Avl_Nil (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
intros key update init.
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b) *)
apply equiv_ins_intro.
(* Goal: forall (k : Int) (data : B) (_ : Equal k key) (_ : lookup k Avl_Nil data), lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) (update data) *)
(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k Avl_Nil data), False), lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k Avl_Nil data), lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data), lookup k Avl_Nil data *)
intros k data equal lookup_nil.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data), lookup k Avl_Nil data *)
apply (inv_lookup_nil k data lookup_nil).

(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k Avl_Nil data), False), lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k Avl_Nil data), lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data), lookup k Avl_Nil data *)
intros k equal notlookup_nil.
(* Goal: lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k Avl_Nil data), lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data), lookup k Avl_Nil data *)
 rewrite (equal_eq k key equal).
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data), lookup k Avl_Nil data *)
intros k data notequal lookup_nil.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data), lookup k Avl_Nil data *)
apply (inv_lookup_nil k data lookup_nil).

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) data), lookup k Avl_Nil data *)
intros k data notequal lookup_nil.
elim
 (inv_lookup k key (update init) Avl_Nil Avl_Nil Balanced data lookup_nil).
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intro u0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply notequal.
(* Goal: Equal k key *)
(* Goal: forall _ : or (lookup k Avl_Nil data) (lookup k Avl_Nil data), lookup k Avl_Nil data *)
elim u0; intros u00 u01.
(* Goal: Equal k key *)
(* Goal: forall _ : or (lookup k Avl_Nil data) (lookup k Avl_Nil data), lookup k Avl_Nil data *)
 rewrite u00.
(* Goal: Equal k0 k0 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply equal_refl.

(* Goal: forall _ : or (lookup k Avl_Nil data) (lookup k Avl_Nil data), lookup k Avl_Nil data *)
 tauto.
Qed.


Lemma avl_ins_eq :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (d' : B),
 is_avl (Avl_Node k d l r b) -> is_avl (Avl_Node k d' l r b).
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (d' : B) (_ : is_avl (Avl_Node k d l r b)), is_avl (Avl_Node k d' l r b) *)
intros k d l r b d' avl_t.
(* Goal: is_avl (Avl_Node k d' l r b) *)
apply Node_Is_Avl.
(* Goal: is_avl l *)
(* Goal: is_avl r *)
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_left k d l r b avl_t).
(* Goal: is_avl r *)
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_right k d l r b avl_t).
(* Goal: is_balanced_avl l r b *)
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_is_balanced_avl k d l r b avl_t).
(* Goal: is_below_avl l k *)
(* Goal: is_above_avl r k *)
apply (inv_is_avl_is_is_below_avl k d l r b avl_t).
(* Goal: is_above_avl r k *)
apply (inv_is_avl_is_is_above_avl k d l r b avl_t).
Qed.


Lemma equiv_ins_eq :
 forall (key : Int) (update : B -> B) (init : B) (k : Int) 
   (d : B) (l0 r0 : avl_tree) (b : bal),
 is_avl (Avl_Node k d l0 r0 b) ->
 Equal key k ->
 equiv_ins key update init (Avl_Node k d l0 r0 b)
   (Avl_Node k (update d) l0 r0 b).
(* Goal: forall (key : Int) (update : forall _ : B, B) (init : B) (k : Int) (d : B) (l0 r0 : avl_tree) (b : bal) (_ : is_avl (Avl_Node k d l0 r0 b)) (_ : Equal key k), equiv_ins key update init (Avl_Node k d l0 r0 b) (Avl_Node k (update d) l0 r0 b) *)
intros key update init k d l0 r0 b avl_t0 equal.
(* Goal: equiv_ins key update init (Avl_Node k d l0 r0 b) (Avl_Node k (update d) l0 r0 b) *)
generalize (avl_ins_eq k d l0 r0 b (update d) avl_t0).
(* Goal: forall _ : is_avl (Avl_Node k (update d) l0 r0 b), equiv_ins key update init (Avl_Node k d l0 r0 b) (Avl_Node k (update d) l0 r0 b) *)
intro avl_t.

(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b) *)
apply equiv_ins_intro.

(* Goal: forall (k0 : Int) (data : B) (_ : Equal k0 key) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) (update data) *)
(* Goal: forall (k0 : Int) (_ : Equal k0 key) (_ : forall (data : B) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), False), lookup k0 (Avl_Node k (update d) l0 r0 b) (update init) *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
intros k0 data equal1.
(* Goal: forall _ : forall (data : B) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), False, lookup k0 (Avl_Node k (update d) l0 r0 b) (update init) *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
generalize (equal_trans k0 key k equal1 equal).
(* Goal: forall (_ : Equal k0 k) (_ : forall (data : B) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), False), lookup k0 (Avl_Node k (update d) l0 r0 b) (update init) *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
intro equal2. 
(* Goal: forall _ : lookup k (Avl_Node k0 d0 l0 r0 b0) data, lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro lookup_t0.
(* Goal: lookup k0 (Avl_Node k (update d) l0 r0 b) (update data) *)
(* Goal: forall (k0 : Int) (_ : Equal k0 key) (_ : forall (data : B) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), False), lookup k0 (Avl_Node k (update d) l0 r0 b) (update init) *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
 rewrite (lookup_avl_inv_equal k0 k d l0 r0 b data avl_t0 equal2 lookup_t0).
(* Goal: lookup k0 (Avl_Node k d l0 r0 b) d *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
 rewrite (equal_eq k0 k equal2).
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal. 

(* Goal: forall (k0 : Int) (_ : Equal k0 key) (_ : forall (data : B) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), False), lookup k0 (Avl_Node k (update d) l0 r0 b) (update init) *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
intros k0 equal1.
(* Goal: forall _ : forall (data : B) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), False, lookup k0 (Avl_Node k (update d) l0 r0 b) (update init) *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
generalize (equal_trans k0 key k equal1 equal).
(* Goal: forall (_ : Equal k0 k) (_ : forall (data : B) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), False), lookup k0 (Avl_Node k (update d) l0 r0 b) (update init) *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
intro equal2. 
(* Goal: forall _ : forall (data : B) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), False, lookup k (Avl_Node k0 d0 l r0 b) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro not_lookup_t0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False. 
(* Goal: False *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
apply (not_lookup_t0 d). 
(* Goal: lookup k0 (Avl_Node k d l0 r0 b) d *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k d l0 r0 b) data), lookup k0 (Avl_Node k (update d) l0 r0 b) data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
 rewrite (equal_eq k0 k equal2).
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal. 

(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
intros k0 data notequal0.
(* Goal: forall _ : lookup k (Avl_Node k0 d0 l0 r0 b0) data, lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro lookup_t0.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
elim (inv_lookup k0 k d l0 r0 b data lookup_t0); intro u0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup k0 (Avl_Node k d l0 r0 b) data *)
apply notequal0.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: Equal k0 key *)
(* Goal: lookup k0 (Avl_Node k d l0 r0 b) data *)
 rewrite <- u0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equal_sym; assumption.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 key)) (_ : lookup k0 (Avl_Node k (update d) l0 r0 b) data), lookup k0 (Avl_Node k d l0 r0 b) data *)
intros k0 data notequal0.
(* Goal: forall _ : lookup k (Avl_Node k0 d0 l r0 b) data, lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro lookup_t.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
elim (inv_lookup k0 k (update d) l0 r0 b data lookup_t); intro u0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup k0 (Avl_Node k d l0 r0 b) data *)
apply notequal0.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: Equal k0 key *)
(* Goal: lookup k0 (Avl_Node k d l0 r0 b) data *)
 rewrite <- u0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equal_sym; assumption.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
Qed.


Lemma equiv_ins_left :
 forall (key : Int) (update : B -> B) (init : B) (k0 : Int) 
   (d0 : B) (l0 r0 : avl_tree) (b0 : bal) (l : avl_tree) 
   (b : bal),
 is_avl (Avl_Node k0 d0 l0 r0 b0) ->
 Less key k0 ->
 equiv_ins key update init l0 l ->
 equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l r0 b).
(* Goal: forall (key : Int) (update : forall _ : B, B) (init : B) (k0 : Int) (d0 : B) (l0 r0 : avl_tree) (b0 : bal) (l : avl_tree) (b : bal) (_ : is_avl (Avl_Node k0 d0 l0 r0 b0)) (_ : Less key k0) (_ : equiv_ins key update init l0 l), equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l r0 b) *)
intros key update init k0 d0 l0 r0 b0 l b avl_t0 less equiv_ins_l0.
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b) *)
apply equiv_ins_intro.

(* Goal: forall (k : Int) (data : B) (_ : Equal k key) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l r0 b) (update data) *)
(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), False), lookup k (Avl_Node k0 d0 l r0 b) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k data equal.
(* Goal: forall _ : lookup k (Avl_Node k0 d0 l0 r0 b0) data, lookup k (Avl_Node k0 d0 l r0 b) (update data) *)
(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), False), lookup k (Avl_Node k0 d0 l r0 b) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
generalize (equal_less_less k key k0 equal less); intro less1.
(* Goal: forall _ : lookup k (Avl_Node k0 d0 l0 r0 b0) data, lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro lookup_t0.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
apply Lookup_Left.
(* Goal: lookup k l (update data) *)
(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), False), lookup k (Avl_Node k0 d0 l r0 b) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
apply (inv_equiv_ins_equal0 key update init l0 l).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_avl_inv_less k k0 d0 l0 r0 b0 data); assumption.

(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), False), lookup k (Avl_Node k0 d0 l r0 b) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k equal.
(* Goal: forall _ : forall (data : B) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), False, lookup k (Avl_Node k0 d0 l r0 b) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro not_lookup_t0.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
apply Lookup_Left.
(* Goal: lookup k l (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
apply (inv_equiv_ins_equal1 key update init l0 l).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall (data : B) (_ : lookup k r0 data), False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros data lookup_l0.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
apply (not_lookup_t0 data).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k data notequal.
(* Goal: forall _ : lookup k (Avl_Node k0 d0 l0 r0 b0) data, lookup k (Avl_Node k0 d0 l r0 b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro lookup_t0.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
elim (inv_lookup k k0 d0 l0 r0 b0 data lookup_t0); intro u0.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite u0.
(* Goal: lookup k (Avl_Node k d0 l0 r0 b0) data *)
(* Goal: lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite u1.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.

(* Goal: lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
apply Lookup_Left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (inv_equiv_ins_notequal0 key update init l0 l); assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l r0 b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k data notequal.
(* Goal: forall _ : lookup k (Avl_Node k0 d0 l r0 b) data, lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intro lookup_t.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
elim (inv_lookup k k0 d0 l r0 b data lookup_t); intro u0.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite u0.
(* Goal: lookup k (Avl_Node k d0 l0 r0 b0) data *)
(* Goal: lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite u1.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.

(* Goal: lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
apply Lookup_Left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (inv_equiv_ins_notequal1 key update init l0 l); assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
Qed.




Lemma equiv_ins_right :
 forall (key : Int) (update : B -> B) (init : B) (k0 : Int) 
   (d0 : B) (l0 r0 : avl_tree) (b0 : bal) (r : avl_tree) 
   (b : bal),
 is_avl (Avl_Node k0 d0 l0 r0 b0) ->
 Less k0 key ->
 equiv_ins key update init r0 r ->
 equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b).
(* Goal: forall (key : Int) (update : forall _ : B, B) (init : B) (k0 : Int) (d0 : B) (l0 r0 : avl_tree) (b0 : bal) (r : avl_tree) (b : bal) (_ : is_avl (Avl_Node k0 d0 l0 r0 b0)) (_ : Less k0 key) (_ : equiv_ins key update init r0 r), equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b) *)
intros key update init k0 d0 l0 r0 b0 r b avl_t0 less equiv_r0.
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b) *)
inversion_clear equiv_r0.
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b) *)
apply equiv_ins_intro.

(* Goal: forall (k : Int) (data : B) (_ : Equal k key) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) (update data) *)
(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), False), lookup k (Avl_Node k0 d0 l0 r b) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k data equal lookup_t0.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
apply Lookup_Right.
(* Goal: lookup k r (update data) *)
(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), False), lookup k (Avl_Node k0 d0 l0 r b) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
apply H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_avl_inv_greater k k0 d0 l0 r0 b0 data); try assumption.
(* Goal: Less k0 k *)
(* Goal: forall _ : not (Equal k key), Less k0 k *)
apply (less_equal_less k0 key k).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equal_sym; assumption.

(* Goal: forall (k : Int) (_ : Equal k key) (_ : forall (data : B) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), False), lookup k (Avl_Node k0 d0 l0 r b) (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k equal not_lookup_t0.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
apply Lookup_Right.
(* Goal: lookup k r (update init) *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
apply H0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall (data : B) (_ : lookup k r0 data), False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros data lookup_l0.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
apply (not_lookup_t0 data).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k data notequal lookup_t0.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
apply Lookup_Right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H1; assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k data notequal lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
apply Lookup_Right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
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.
(* Goal: forall (key : Int) (update : forall _ : B, B) (init : B) (t0 : avl_tree) (_ : is_avl t0), avl_ins_spec key update init t0 *)
intros key update init t0.
(* Goal: forall _ : is_avl t0, avl_ins_spec key update init t0 *)
elim t0; clear t0.

(* t0=Avl_Nil *)
(* Goal: forall _ : is_avl Avl_Nil, delete_spec key Avl_Nil *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
intros avl_t0.
apply
 Avl_Ins_Spec_Intro
  with (t := Avl_Node key (update init) Avl_Nil Avl_Nil Balanced).

(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Not_Lookup.
(* Goal: forall d : B, not (lookup key Avl_Nil d) *)
(* Goal: is_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: lin_ins_spec key update init Avl_Nil (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: equiv_ins key update init Avl_Nil (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced)) (height_avl Avl_Nil)) (@eq nat (height_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced)) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, avl_ins_spec key update init a) (a0 : avl_tree) (_ : forall _ : is_avl a0, avl_ins_spec key update init a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), avl_ins_spec key update init (Avl_Node i b a a0 b0) *)
unfold not in |- *; intros d lookup0.
(* Goal: False *)
(* Goal: is_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: lin_ins_spec key update init Avl_Nil (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: equiv_ins key update init Avl_Nil (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced)) (height_avl Avl_Nil)) (@eq nat (height_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced)) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, avl_ins_spec key update init a) (a0 : avl_tree) (_ : forall _ : is_avl a0, avl_ins_spec key update init a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), avl_ins_spec key update init (Avl_Node i b a a0 b0) *)
apply (inv_lookup_nil key d lookup0).

(* Goal: is_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: lin_ins_spec key update init Avl_Nil (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: equiv_ins key update init Avl_Nil (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced)) (height_avl Avl_Nil)) (@eq nat (height_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced)) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, avl_ins_spec key update init a) (a0 : avl_tree) (_ : forall _ : is_avl a0, avl_ins_spec key update init a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), avl_ins_spec key update init (Avl_Node i b a a0 b0) *)
apply leave_is_avl.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply Lin_Ins_New with (nil (A:=Int * B)) (nil (A:=Int * B)); trivial.
(* Goal: equiv_ins key update init Avl_Nil (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced) *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced)) (height_avl Avl_Nil)) (@eq nat (height_avl (Avl_Node key (update init) Avl_Nil Avl_Nil Balanced)) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, avl_ins_spec key update init a) (a0 : avl_tree) (_ : forall _ : is_avl a0, avl_ins_spec key update init a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), avl_ins_spec key update init (Avl_Node i b a a0 b0) *)
apply equiv_ins_nil.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right; simpl in |- *; trivial.

(* t0=(Avl_Node k0 d0 l0 r0 b0)  *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
intros k0 d0 l0 ih_l0 r0 ih_r0 b0 avl_t0.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim (equal_dec key k0).

(* Goal: forall _ : Equal k key, Less k0 k *)
(* Goal: forall _ : not (Equal k key), Less k0 k *)
intro equal.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
clear ih_l0 ih_r0.
(* Goal: avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Equal key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
apply Avl_Ins_Spec_Intro with (t := Avl_Node k0 (update d0) l0 r0 b0).
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl (Avl_Node k0 (update d0) l0 r0 b0) *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 (update d0) l0 r0 b0) *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 (update d0) l0 r0 b0) *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 (update d0) l0 r0 b0)) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl (Avl_Node k0 (update d0) l0 r0 b0)) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: forall _ : not (Equal key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup with d0.
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (@cons (prod Int B) (@pair Int B key d1) (lin_avl r0))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (equal_eq key k0 equal).
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (avl_ins_eq k0 d0 l0 r0 b0); assumption.
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (@cons (prod Int B) (@pair Int B key d1) (lin_avl r0))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (equal_eq key k0 equal).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply Lin_Ins_Update with d0 (lin_avl l0) (lin_avl r0); trivial.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_ins_eq; assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim b0; simpl in |- *; trivial.

(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro notequal.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim (less_dec key k0).
(* Goal: forall _ : Less key k0, delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro less.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim (ih_l0 (inv_is_avl_left k0 d0 l0 r0 b0 avl_t0)); clear ih_l0 ih_r0.
(* Goal: forall (t : avl_tree) (_ : lookup_dec_spec key l0) (_ : is_avl t) (_ : lin_ins_spec key update init l0 t) (_ : equiv_ins key update init l0 t) (_ : sumbool (@eq nat (height_avl t) (height_avl l0)) (@eq nat (height_avl t) (S (height_avl l0)))), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
intros l lookup_dec_spec0 avl_l lin_ins_l equiv_ins_l bal_or_shift.
(* Goal: avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
elim (balance_left k0 d0 l r0 b0). 
(* Goal: forall (t : avl_tree) (_ : is_avl t) (_ : @eq (list (prod Int B)) (lin_avl t) (lin_avl (Avl_Node k0 d0 l0 r b0))) (_ : equiv t (Avl_Node k0 d0 l0 r b0)) (_ : sumbool (hasnot_grown_right t k0 d0 l0 r b0) (has_grown_right t k0 d0 l0 r b0)), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intros t avl_t lin_t equiv_t growth_dec.
(* Goal: avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Avl_Ins_Spec_Intro with t.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
elim lookup_dec_spec0; clear lookup_dec_spec0.
(* Goal: forall (d : B) (_ : lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros d lookup_d.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Lookup with d.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intros not_lookup_d0.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Not_Lookup.
(* Goal: forall d : B, not (lookup key (Avl_Node k0 d0 l0 r0 b0) d) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
unfold not in |- *; intros d lookup_d0.
(* Goal: False *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply (not_lookup_d0 d).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_avl_inv_less key k0 d0 l0 r0 b0); assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
elim lin_ins_l; clear lin_ins_l.
(* Goal: forall (l1 l2 : list (prod Int B)) (_ : @eq (list (prod Int B)) (lin_avl l0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) l2))) (_ : @eq (list (prod Int B)) (lin_avl l) (@app (prod Int B) l1 l2)), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intros l1 l2 lin_l0 lin_l.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply Lin_Ins_New with l1 (l2 ++ (k0, d0) :: lin_avl r0); simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) l1 (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0)))) *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite lin_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite (app_ass l1 l2 ((k0, d0) :: lin_avl r0)); trivial.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite lin_t; simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0)))) *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite lin_l.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update init)) l2)) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update init)) (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))))) *)
(* Goal: forall (d : B) (l1 l2 : list (prod Int B)) (_ : @eq (list (prod Int B)) (lin_avl l0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) l2))) (_ : @eq (list (prod Int B)) (lin_avl l) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update d)) l2))), lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (app_ass l1 ((key, update init) :: l2) ((k0, d0) :: lin_avl r0)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: forall (d : B) (l1 l2 : list (prod Int B)) (_ : @eq (list (prod Int B)) (lin_avl l0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) l2))) (_ : @eq (list (prod Int B)) (lin_avl l) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update d)) l2))), lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
intros d' l1 l2 lin_l0 lin_l.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply Lin_Ins_Update with d' l1 (l2 ++ (k0, d0) :: lin_avl r0); simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) l1 (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0)))) *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite lin_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite (app_ass l1 ((key, d') :: l2) ((k0, d0) :: lin_avl r0)); trivial.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite lin_t; simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0)))) *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite lin_l.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update d')) l2)) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update d')) (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))))) *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (app_ass l1 ((key, update d') :: l2) ((k0, d0) :: lin_avl r0)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_ins_equiv_equiv_ins with (Avl_Node k0 d0 l r0 b0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (equiv_ins_left key update init k0 d0 l0 r0 b0 l b0); assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_sym; assumption.
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
elim growth_dec; clear growth_dec.

(* Goal: forall _ : hasnot_grown_right t k0 d0 l0 r b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: forall _ : has_grown_right t k0 d0 l0 r b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intro has_not_grown.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0)) *)
(* Goal: forall _ : has_grown_left t k0 d0 l r0 b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
generalize H1; clear H1.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0)) *)
(* Goal: forall _ : has_grown_left t k0 d0 l r0 b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
clear equiv_t equiv_ins_l H3 H2 H0 H.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0)) *)
(* Goal: forall _ : has_grown_right t k0 d0 l0 r b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
inversion_clear has_not_grown.
(* (is_balanced_avl l r0 b0) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear H; simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intro Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* (is_balanced_avl_left_shift l r0 Left_Balanced) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.
(* (is_balanced_avl_left_shift l r0 Right_Balanced) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: forall _ : has_grown_right t k0 d0 l0 r b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intro has_grown.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: @eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
clear equiv_t equiv_ins_l.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
generalize H1; clear H H0 H1 H2 H3.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0))) *)
(* Goal: is_avl l *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
inversion_clear has_grown.
(*  (is_balanced_avl_left_shift l r0 Left_Balanced) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.
(* (is_balanced_avl_left_shift l r0 Balanced) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.

(* side premisses of Elim (balance...) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply below_below_avl.
(* Goal: is_below l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_ins_below with key update init l0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_below_avl_is_below; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_left_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
elim bal_or_shift; clear bal_or_shift; intro height_l.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_balanced_avl l r0 b0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply hasnot_grown_left__preserves_is_balanced_avl with l0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_balanced_avl_left_shift l r0 b0 *)
(* Goal: forall _ : not (Less key k0), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
apply is_left_balanced_is_left_balanced_left_shift with l0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(**********    greater   **********************************)

(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro notless.
(* Goal: avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
generalize (notequal_notless_greater key k0 notequal notless).
(* Goal: forall _ : Less k0 key, avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
intro greater; clear notless.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim (ih_r0 (inv_is_avl_right k0 d0 l0 r0 b0 avl_t0)); clear ih_l0 ih_r0.

(* Goal: forall (t : avl_tree) (_ : lookup_dec_spec key r0) (_ : is_avl t) (_ : lin_ins_spec key update init r0 t) (_ : equiv_ins key update init r0 t) (_ : sumbool (@eq nat (height_avl t) (height_avl r0)) (@eq nat (height_avl t) (S (height_avl r0)))), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
intros r lookup_dec_spec0 avl_r lin_ins_r equiv_ins_r bal_or_shift.
(* Goal: avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
elim (balance_right k0 d0 l0 r b0). 
(* Goal: forall (t : avl_tree) (_ : is_avl t) (_ : @eq (list (prod Int B)) (lin_avl t) (lin_avl (Avl_Node k0 d0 l0 r b0))) (_ : equiv t (Avl_Node k0 d0 l0 r b0)) (_ : sumbool (hasnot_grown_right t k0 d0 l0 r b0) (has_grown_right t k0 d0 l0 r b0)), avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intros t avl_t lin_t equiv_t growth_dec.
(* Goal: avl_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Avl_Ins_Spec_Intro with t.

(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
elim lookup_dec_spec0; clear lookup_dec_spec0.
(* Goal: forall (d : B) (_ : lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros d lookup_d.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Lookup with d.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intros not_lookup_d0.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply Not_Lookup.
(* Goal: forall (d : B) (_ : lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
unfold not in |- *; intros d lookup_d.
(* Goal: False *)
(* Goal: is_avl t *)
(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply (not_lookup_d0 d).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_avl_inv_greater key k0 d0 l0 r0 b0); assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
elim lin_ins_r; clear lin_ins_r.
(* Goal: forall (l1 l2 : list (prod Int B)) (_ : @eq (list (prod Int B)) (lin_avl r0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) l2))) (_ : @eq (list (prod Int B)) (lin_avl r) (@app (prod Int B) l1 l2)), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: lookup key r0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros l1 l2 lin_r0 lin_r.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply Lin_Ins_New with (lin_avl l0 ++ (k0, d0) :: l1) l2; simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) (@cons (prod Int B) (@pair Int B key d') l2)) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) (@cons (prod Int B) (@pair Int B key (update d')) l2)) *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
 rewrite lin_r0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite (app_ass (lin_avl l0) ((k0, d0) :: l1) l2); trivial.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite lin_t; simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r))) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) (@cons (prod Int B) (@pair Int B key (update d')) l2)) *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
 rewrite lin_r.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update init)) l2)))) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) (@cons (prod Int B) (@pair Int B key (update init)) l2)) *)
(* Goal: forall (d : B) (l1 l2 : list (prod Int B)) (_ : @eq (list (prod Int B)) (lin_avl r0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) l2))) (_ : @eq (list (prod Int B)) (lin_avl r) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update d)) l2))), lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
 rewrite (app_ass (lin_avl l0) ((k0, d0) :: l1) ((key, update init) :: l2)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: forall (d : B) (l1 l2 : list (prod Int B)) (_ : @eq (list (prod Int B)) (lin_avl r0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) l2))) (_ : @eq (list (prod Int B)) (lin_avl r) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update d)) l2))), lin_ins_spec key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intros d' l1 l2 lin_r0 lin_r.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply Lin_Ins_Update with d' (lin_avl l0 ++ (k0, d0) :: l1) l2; simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) (@cons (prod Int B) (@pair Int B key d') l2)) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) (@cons (prod Int B) (@pair Int B key (update d')) l2)) *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
 rewrite lin_r0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite (app_ass (lin_avl l0) ((k0, d0) :: l1) ((key, d') :: l2)); trivial.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite lin_t; simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r))) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) (@cons (prod Int B) (@pair Int B key (update d')) l2)) *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
 rewrite lin_r.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key (update d')) l2)))) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) (@cons (prod Int B) (@pair Int B key (update d')) l2)) *)
(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
 rewrite (app_ass (lin_avl l0) ((k0, d0) :: l1) ((key, update d') :: l2)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: equiv_ins key update init (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply equiv_ins_equiv_equiv_ins with (Avl_Node k0 d0 l0 r b0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (equiv_ins_right key update init k0 d0 l0 r0 b0 r b0); assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_sym; assumption.
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
clear equiv_t avl_t bal_or_shift equiv_ins_r.
(* Goal: sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
elim growth_dec; clear growth_dec.

(* Goal: forall _ : hasnot_grown_right t k0 d0 l0 r b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: forall _ : has_grown_right t k0 d0 l0 r b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intro has_not_grown.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
generalize H1; clear H H0 H1 H2 H3.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0)) *)
(* Goal: forall _ : has_grown_right t k0 d0 l0 r b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
inversion_clear has_not_grown.
(* (is_balanced_avl l0 r b0) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear H; simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite <- H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.
(* (is_balanced_avl_right_shift l0 r Left_Balanced) *)
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0; simpl in |- *.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; trivial.
(* (is_balanced_avl_left_shift l0 r Right_Balanced) *)
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0; simpl in |- *.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite <- H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intro Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.

(* Goal: forall _ : has_grown_right t k0 d0 l0 r b0, sumbool (@eq nat (height_avl t) (height_avl (Avl_Node k0 d0 l0 r0 b0))) (@eq nat (height_avl t) (S (height_avl (Avl_Node k0 d0 l0 r0 b0)))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
intro has_grown.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
generalize H1; clear H H0 H1 H2 H3.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear has_grown; simpl in |- *.
(*  (is_balanced_avl_right_shift l0 r Balanced) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; trivial.
(* (is_balanced_avl_right_shift l0 r Right_Balanced) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite <- H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.

(* side premisses of Elim (balance...) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply above_above_avl.
(* Goal: is_above r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
apply equiv_ins_above with key update init r0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_above_avl_is_above; assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_right_shift l0 r b0) *)
elim bal_or_shift; clear bal_or_shift; intro height_r.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_balanced_avl l0 r b0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply hasnot_grown_right__preserves_is_balanced_avl with r0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_balanced_avl_right_shift l0 r b0 *)
apply is_balanced_avl_is_balanced_avl_right_shift with r0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.


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


Inductive equiv_del (key : Int) (t0 t : avl_tree) : Prop :=
    equiv_del_intro :
      (forall k : Int, Equal k key -> forall d : B, lookup k t d -> False) ->
      (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_del key t0 t.


Lemma inv_equiv_del_equal :
 forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B),
 equiv_del key t0 t -> Equal k key -> lookup k t d -> False.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: lookup k t0 d *)
inversion H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H2 with (k := k) (d := d); assumption.
Qed.


Lemma inv_equiv_del_notequal0 :
 forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B),
 equiv_del key t0 t -> ~ Equal k key -> lookup k t0 d -> lookup k t d.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: lookup k t0 d *)
inversion H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H3; assumption.
Qed.

Lemma inv_equiv_del_notequal1 :
 forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B),
 equiv_del key t0 t -> ~ Equal k key -> lookup k t d -> lookup k t0 d.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k : Int) (d : B) (_ : equiv_del key t0 t) (_ : not (Equal k key)) (_ : lookup k t d), lookup k t0 d *)
intros.
(* Goal: lookup k t0 d *)
inversion H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H4; assumption.
Qed.



Lemma equiv_del_equiv_equiv_del :
 forall (key : Int) (t0 t1 t2 : avl_tree),
 equiv_del key t0 t1 -> equiv t1 t2 -> equiv_del key t0 t2.
(* Goal: forall (key : Int) (t0 t1 t2 : avl_tree) (_ : equiv_del key t0 t1) (_ : equiv t1 t2), equiv_del key t0 t2 *)
intros key t0 t1 t2 equiv_del0 equiv0.
(* Goal: equiv_del key t0 t2 *)
inversion_clear equiv_del0.
(* Goal: equiv_del key t0 t2 *)
inversion_clear equiv0.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 l b0) (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_del_intro.

(* Goal: forall (k : Int) (_ : Equal k key) (d : B) (_ : lookup k t2 d), False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t0 data), lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
intros k equal data lookup_t2.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t0 data), lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
apply H with k data.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H3; assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k data notequal lookup_t0.
(* Goal: lookup k t2 data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
apply H2.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H0; assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k t2 data), lookup k t0 data *)
intros k data notequal lookup_t2.
(* Goal: lookup k0 l0 d1 *)
(* Goal: is_below l0 k0 *)
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply H1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H3; assumption.
Qed.


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

Lemma equiv_del_semi_leave :
 forall (k : Int) (d : B) (l : avl_tree) (b : bal),
 is_avl (Avl_Node k d l Avl_Nil b) ->
 equiv_del k (Avl_Node k d l Avl_Nil b) l.
(* Goal: forall (k : Int) (d : B) (l : avl_tree) (b : bal) (_ : is_avl (Avl_Node k d l Avl_Nil b)), equiv_del k (Avl_Node k d l Avl_Nil b) l *)
intros k d l b avl_t.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 l b0) (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_del_intro.

(* Goal: forall (k0 : Int) (_ : Equal k0 k) (d : B) (_ : lookup k0 l d), False *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d l Avl_Nil b) data), lookup k0 l data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 l data), lookup k0 (Avl_Node k d l Avl_Nil b) data *)
intros k0 equal d0 lookup_l.
(* Goal: is_above r k *)
(* Goal: Equal k0 k *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d Avl_Nil r b) data), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear avl_t.
(* Goal: False *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d l Avl_Nil b) data), lookup k0 l data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 l data), lookup k0 (Avl_Node k d l Avl_Nil b) data *)
apply lookup_below_false with k0 l d0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below l k0 *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d l Avl_Nil b) data), lookup k0 l data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 l data), lookup k0 (Avl_Node k d l Avl_Nil b) data *)
 rewrite (equal_eq k0 k equal).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_below_avl_is_below; assumption.

(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d Avl_Nil r b) data), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
intros k0 data notequal lookup_t.
(* Goal: lookup k0 l data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 l data), lookup k0 (Avl_Node k d l Avl_Nil b) data *)
inversion lookup_t.
(* Goal: lookup k l data *)
(* Goal: lookup k0 l data *)
(* Goal: lookup k0 l data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 l data), lookup k0 (Avl_Node k d l Avl_Nil b) data *)
 rewrite H0 in notequal.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply notequal.
(* Goal: Equal k0 k0 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply equal_refl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: lookup k0 l data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 l data), lookup k0 (Avl_Node k d l Avl_Nil b) data *)
inversion_clear H5.

(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
intros k0 data notequal lookup_l.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
Qed.

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

Lemma equiv_del_above :
 forall (key : Int) (t0 t : avl_tree) (k0 : Int),
 equiv_del key t0 t -> Less k0 key -> is_above t0 k0 -> is_above t k0.
(* Goal: forall (key : Int) (t0 t : avl_tree) (k0 : Int) (_ : equiv_del key t0 t) (_ : Less k0 key) (_ : is_above t0 k0), is_above t k0 *)
intros key t0 t k0 equiv_t0 greater below_t0.
(* Goal: is_above t k *)
apply lookup_greater_above.
(* Goal: forall (k : Int) (d : B) (_ : lookup k t d), Less k0 k *)
intros k d lookup_t.
(* Goal: Less k0 k *)
elim (equal_dec k key).

(* Goal: forall _ : Equal k key, Less k0 k *)
(* Goal: forall _ : not (Equal k key), Less k0 k *)
intro equal.
(* Goal: Less k0 k *)
(* Goal: forall _ : not (Equal k key), Less k0 k *)
apply (less_equal_less k0 key k).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equal_sym; assumption.

(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro notequal.
(* Goal: Less k0 k *)
apply (lookup_above_greater k t0 d).
(* Goal: lookup k t0 d *)
(* Goal: is_above t0 k0 *)
inversion_clear equiv_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H1; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.


Lemma equiv_del_right :
 forall (key k0 : Int) (d0 : B) (l0 r0 : avl_tree) 
   (b0 : bal) (r : avl_tree) (b : bal),
 is_avl (Avl_Node k0 d0 l0 r0 b0) ->
 Less k0 key ->
 equiv_del key r0 r ->
 equiv_del key (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b).
(* Goal: forall (key k0 : Int) (d0 : B) (l0 r0 : avl_tree) (b0 : bal) (r : avl_tree) (b : bal) (_ : is_avl (Avl_Node k0 d0 l0 r0 b0)) (_ : Less k0 key) (_ : equiv_del key r0 r), equiv_del key (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b) *)
intros key k0 d0 l0 r0 b0 r b avl_t0 less equiv_r0.
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b) *)
inversion_clear equiv_r0.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 l b0) (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_del_intro.

(* Goal: forall (k : Int) (_ : Equal k key) (d : B) (_ : lookup k (Avl_Node k0 d0 l0 r b) d), False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k equal data lookup_t.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
elim (inv_lookup k k0 d0 l0 r b data lookup_t); intro u0.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intros u0 u1.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite u0 in less.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite (equal_eq k key equal) in less.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply less_irrefl with key; assumption.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
elim u0; clear u0; intro u0.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite (equal_eq k key equal) in u0.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
apply lookup_below_false with key l0 data.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below l0 k *)
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
apply below_trans with k0.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_below_avl_is_below; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H with k data; assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r0 b0) data), lookup k (Avl_Node k0 d0 l0 r b) data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k data notequal lookup_t0.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
apply Lookup_Right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H0; assumption.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k (Avl_Node k0 d0 l0 r b) data), lookup k (Avl_Node k0 d0 l0 r0 b0) data *)
intros k data notequal lookup_t.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
apply Lookup_Right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H1; assumption.
Qed.



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

Lemma below_equiv_below :
 forall (k : Int) (t0 t : avl_tree),
 is_below t0 k -> equiv t t0 -> is_below t k.
(* Goal: forall (k : Int) (t0 t : avl_tree) (_ : is_below t0 k) (_ : equiv t t0), is_below t k *)
intros k t0 t below_t0 equiv_t.
(* Goal: is_below t k *)
inversion_clear equiv_t.
(* Goal: is_below t k *)
apply lookup_less_below.
(* Goal: forall (k0 : Int) (d : B) (_ : lookup k0 t d), Less k k0 *)
intros k0 d0 lookup_k0.
(* Goal: Less k0 k *)
apply lookup_below_less with t0 d0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.

Lemma Balanced_shrunk_left_balanced_shift :
 forall (l0 r r0 : avl_tree) (b0 : bal),
 is_balanced_avl l0 r0 b0 ->
 height_avl r0 = S (height_avl r) -> is_balanced_avl_left_shift l0 r b0.
(* Goal: forall (l0 r r0 : avl_tree) (b0 : bal) (_ : is_balanced_avl l0 r0 b0) (_ : @eq nat (height_avl r0) (S (height_avl r))), is_balanced_avl_left_shift l0 r b0 *)
intros l0 r r0 b0 Balanced_l0 height_r.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
inversion_clear Balanced_l0.
(* Goal: is_balanced_avl_left_shift l0 r Left_Balanced *)
(* Goal: is_balanced_avl_left_shift l0 r Balanced *)
(* Goal: is_balanced_avl_left_shift l0 r Right_Balanced *)
apply Is_Left_Balanced_Avl_Left_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite <- height_r; assumption.
(* Goal: is_balanced_avl_left_shift l0 r Balanced *)
(* Goal: is_balanced_avl_left_shift l0 r Right_Balanced *)
apply Is_Fully_Balanced_Avl_Left_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite <- height_r; assumption.
(* Goal: is_balanced_avl_left_shift l0 r Right_Balanced *)
apply Is_Right_Balanced_Avl_Left_Shift.
(* Goal: @eq nat (height_avl l0) (height_avl r) *)
 rewrite <- H in height_r. 
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection height_r; trivial.
Qed.


Lemma below_equiv_del_below :
 forall (t0 t : avl_tree) (k key : Int),
 is_below t0 k -> equiv_del key t0 t -> is_below t k.
(* Goal: forall (t0 t : avl_tree) (k key : Int) (_ : is_below t0 k) (_ : equiv_del key t0 t), is_below t k *)
intros t0 t k key below_t0 equiv_del_t0.
(* Goal: is_above t k *)
inversion_clear equiv_del_t0.
(* Goal: is_below t k *)
apply lookup_less_below.
(* Goal: forall (k0 : Int) (d : B) (_ : lookup k0 t d), Less k k0 *)
intros k0 d0 lookup_k0.
(* Goal: Less k0 k *)
apply lookup_below_less with t0 d0.
(* Goal: lookup k0 t0 d0 *)
(* Goal: is_above t0 k *)
elim (equal_dec k0 key).
(* Goal: forall _ : Equal k0 key, lookup k0 t0 d0 *)
(* Goal: forall _ : not (Equal k0 key), lookup k0 t0 d0 *)
(* Goal: is_above t0 k *)
intros equal_k0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H with k0 d0; assumption.
(* Goal: forall _ : not (Equal k0 key), lookup k0 t0 d0 *)
(* Goal: is_above t0 k *)
intros not_equal_k0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H1; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.


Lemma above_equiv_del_above :
 forall (t0 t : avl_tree) (k key : Int),
 is_above t0 k -> equiv_del key t0 t -> is_above t k.
(* Goal: forall (t0 t : avl_tree) (k key : Int) (_ : is_above t0 k) (_ : equiv_del key t0 t), is_above t k *)
intros t0 t k key above_t0 equiv_del_t0.
(* Goal: is_above t k *)
inversion_clear equiv_del_t0.
(* Goal: is_above t k *)
apply lookup_greater_above.
(* Goal: forall (k0 : Int) (d : B) (_ : lookup k0 t d), Less k k0 *)
intros k0 d0 lookup_k0.
(* Goal: Less k k0 *)
apply lookup_above_greater with t0 d0.
(* Goal: lookup k0 t0 d0 *)
(* Goal: is_above t0 k *)
elim (equal_dec k0 key).
(* Goal: forall _ : Equal k0 key, lookup k0 t0 d0 *)
(* Goal: forall _ : not (Equal k0 key), lookup k0 t0 d0 *)
(* Goal: is_above t0 k *)
intros equal_k0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H with k0 d0; assumption.
(* Goal: forall _ : not (Equal k0 key), lookup k0 t0 d0 *)
(* Goal: is_above t0 k *)
intros not_equal_k0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H1; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.



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


Inductive hasnot_shrunk_left (t : avl_tree) (k : Int) 
(d : B) (l r : avl_tree) : bal -> Prop :=
  | Hasnot_Shrunk_Left_Bal :
      forall b : bal,
      is_balanced_avl l r b ->
      height_avl t = height_avl (Avl_Node k d l r b) ->
      hasnot_shrunk_left t k d l r b
  | Hasnot_Shrunk_Left_Shift_Left :
      is_balanced_avl_left_shift l r Left_Balanced ->
      height_avl t = S (height_avl l) ->
      hasnot_shrunk_left t k d l r Left_Balanced
  | Hasnot_Shrunk_Left_Shift_Balanced :
      is_balanced_avl_left_shift l r Balanced ->
      height_avl t = S (height_avl l) ->
      hasnot_shrunk_left t k d l r Balanced.


Inductive has_shrunk_left (t : avl_tree) (k : Int) 
(d : B) (l r : avl_tree) : bal -> Prop :=
  | Has_Shrunk_Left_Shift_Left :
      is_balanced_avl_left_shift l r Left_Balanced ->
      height_avl t = height_avl l -> has_shrunk_left t k d l r Left_Balanced
  | Has_Shrunk_Left_Shift_Right :
      is_balanced_avl_left_shift l r Right_Balanced ->
      height_avl t = S (height_avl l) ->
      has_shrunk_left t k d l r Right_Balanced.




Inductive bal_shrunk_left_spec (k : Int) (d : B) (l r : avl_tree) 
(b : bal) : Set :=
    Balance_Shrunk_Left_Spec_Intro :
      forall t : avl_tree,
      is_avl t ->
      lin_avl t = lin_avl (Avl_Node k d l r b) ->
      equiv t (Avl_Node k d l r b) ->
      {hasnot_shrunk_left t k d l r b} + {has_shrunk_left t k d l r b} ->
      bal_shrunk_left_spec k d l r b.


Lemma balance_shrunk_left :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl l ->
 is_below_avl l k ->
 is_avl r ->
 is_above_avl r k ->
 {is_balanced_avl l r b} + {is_balanced_avl_left_shift l r b} ->
 bal_shrunk_left_spec k d l r b.
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : is_below_avl l k) (_ : is_avl r) (_ : is_above_avl r k) (_ : sumbool (is_balanced_avl l r b) (is_balanced_avl_right_shift l r b)), bal_shrunk_right_spec k d l r b *)
intros k d l r b avl_l below_avl_l avl_r above_avl_r bal_or_shift.
(* Goal: bal_shrunk_right_spec k d l r b *)
elim bal_or_shift; clear bal_or_shift.
(* l and r is Balanced with respect to b *)
(* Goal: forall _ : is_balanced_avl l r b, bal_shrunk_right_spec k d l r b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
intro Balanced_l.
(* Goal: bal_shrunk_left_spec k d l r b *)
(* Goal: forall _ : is_balanced_avl_left_shift l r b, bal_shrunk_left_spec k d l r b *)
apply Balance_Shrunk_Left_Spec_Intro with (Avl_Node k d l r b). 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: hasnot_shrunk_left (Avl_Node k d l r b) k d l r b *)
(* Goal: forall _ : is_balanced_avl_left_shift l r b, bal_shrunk_left_spec k d l r b *)
apply Hasnot_Shrunk_Left_Bal. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* l and r is'nt Balanced with respect to b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
elim b; clear b; intros Balanced_shift_l.
(* b=Left_Balanced *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
elim (rebalance_left k d l r Left_Balanced); try assumption.
(* Goal: forall (x : avl_tree) (_ : and (is_avl x) (and (@eq (list (prod Int B)) (lin_avl x) (lin_avl (Avl_Node k d l r Right_Balanced))) (and (equiv x (Avl_Node k d l r Right_Balanced)) match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl x) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl x) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl x) (height_avl r) end))), bal_shrunk_right_spec k d l r Right_Balanced *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intros t (avl_t,(lin_t,(equiv_t,height_t))).
(* Goal: bal_shrunk_left_spec k d l r Left_Balanced *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Balance_Shrunk_Left_Spec_Intro with t.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: sumbool (hasnot_shrunk_left t k d l r Left_Balanced) (has_shrunk_left t k d l r Left_Balanced) *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
clear lin_t equiv_t avl_l below_avl_l.
(* Goal: sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
generalize height_t; clear height_t.
(* Goal: forall _ : match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl t) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl t) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl t) (height_avl r) end, sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
generalize Balanced_shift_l; clear Balanced_shift_l.
(* Goal: forall (_ : is_balanced_avl_left_shift l r Left_Balanced) (_ : match l with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl t) (height_avl l) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl t) (S (height_avl l)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl t) (height_avl l) end), sumbool (hasnot_shrunk_left t k d l r Left_Balanced) (has_shrunk_left t k d l r Left_Balanced) *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
case l; clear l.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intro u0. 
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
inversion_clear u0.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
 discriminate H.
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_left_shift (Avl_Node i b a a0 b0) r Left_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_left t k d (Avl_Node i b a a0 b0) r Left_Balanced) (has_shrunk_left t k d (Avl_Node i b a a0 b0) r Left_Balanced) *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
intros kl dl ll rl bl.
(* Goal: forall (_ : is_balanced_avl_left_shift (Avl_Node kl dl ll rl bl) r Left_Balanced) (_ : match bl with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node kl dl ll rl bl)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node kl dl ll rl bl))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node kl dl ll rl bl)) end), sumbool (hasnot_shrunk_left t k d (Avl_Node kl dl ll rl bl) r Left_Balanced) (has_shrunk_left t k d (Avl_Node kl dl ll rl bl) r Left_Balanced) *)
(* Goal: @eq nat (height_avl l) (S (S (height_avl r))) *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
elim bl; clear bl; simpl in |- *; intros Balanced_shift_l height_t.
(* bl=Left_Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Has_Shrunk_Left_Shift_Left; assumption.
(* bl=Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Hasnot_Shrunk_Left_Shift_Left; assumption.
(* bl=Right_Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Has_Shrunk_Left_Shift_Left; assumption.
(* side premisses of (Elim (rebalance ... )) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.

(* b=Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Balance_Shrunk_Left_Spec_Intro with (Avl_Node k d l r Left_Balanced).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Left_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Left_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Left_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) (has_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Is_Left_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: hasnot_shrunk_left (Avl_Node k d l r Left_Balanced) k d l r Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Hasnot_Shrunk_Left_Shift_Balanced. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* b=Right_Balanced *)
(* Goal: bal_shrunk_left_spec k d l r Right_Balanced *)
apply Balance_Shrunk_Left_Spec_Intro with (Avl_Node k d l r Balanced).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: has_shrunk_left (Avl_Node k d l r Balanced) k d l r Right_Balanced *)
apply Has_Shrunk_Left_Shift_Right. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
Qed.

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

Inductive delete_max_spec (t0 : avl_tree) : Set :=
    Del_Max_Spec_Intro :
      forall (k : Int) (d : B) (t : avl_tree),
      lookup k t0 d ->
      is_avl t ->
      is_below_avl t k ->
      lin_avl t0 = lin_avl t ++ (k, d) :: nil ->
      equiv_del k t0 t ->
      {height_avl t0 = height_avl t} + {height_avl t0 = S (height_avl t)} ->
      delete_max_spec t0.


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

Lemma delete_max :
 forall (k0 : Int) (d0 : B) (l0 r0 : avl_tree) (b0 : bal),
 is_avl (Avl_Node k0 d0 l0 r0 b0) ->
 delete_max_spec (Avl_Node k0 d0 l0 r0 b0).
(* Goal: forall (k0 : Int) (d0 : B) (l0 r0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 r0 b0)), delete_max_spec (Avl_Node k0 d0 l0 r0 b0) *)
intros k0 d0 l0 r0.
(* Goal: forall (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 r0 b0)), delete_max_spec (Avl_Node k0 d0 l0 r0 b0) *)
generalize l0; clear l0.
(* Goal: forall (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 r0 b0)), delete_max_spec (Avl_Node k0 d0 l0 r0 b0) *)
generalize d0; clear d0.
(* Goal: forall (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 r0 b0)), delete_max_spec (Avl_Node k0 d0 l0 r0 b0) *)
generalize k0; clear k0.
(* Goal: forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 r0 b0)), delete_max_spec (Avl_Node k0 d0 l0 r0 b0) *)
elim r0; clear r0.

(* r0=Avl_Nil *)
(* Goal: forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 Avl_Nil b0)), delete_max_spec (Avl_Node k0 d0 l0 Avl_Nil b0) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 a b0)), delete_max_spec (Avl_Node k0 d0 l0 a b0)) (a0 : avl_tree) (_ : forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 a0 b0)), delete_max_spec (Avl_Node k0 d0 l0 a0 b0)) (b0 : bal) (k0 : Int) (d0 : B) (l0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 l0 (Avl_Node i b a a0 b0) b1)), delete_max_spec (Avl_Node k0 d0 l0 (Avl_Node i b a a0 b0) b1) *)
intros k0 d0 l0 b0 avl_t0.
(* Goal: delete_max_spec (Avl_Node k0 d0 l0 Avl_Nil b0) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 a b0)), delete_max_spec (Avl_Node k0 d0 l0 a b0)) (a0 : avl_tree) (_ : forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 a0 b0)), delete_max_spec (Avl_Node k0 d0 l0 a0 b0)) (b0 : bal) (k0 : Int) (d0 : B) (l0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 l0 (Avl_Node i b a a0 b0) b1)), delete_max_spec (Avl_Node k0 d0 l0 (Avl_Node i b a a0 b0) b1) *)
apply Del_Max_Spec_Intro with k0 d0 l0.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_del_semi_leave; assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 Avl_Nil b0)) (S (height_avl l0)) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 a b0)), delete_max_spec (Avl_Node k0 d0 l0 a b0)) (a0 : avl_tree) (_ : forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 a0 b0)), delete_max_spec (Avl_Node k0 d0 l0 a0 b0)) (b0 : bal) (k0 : Int) (d0 : B) (l0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 l0 (Avl_Node i b a a0 b0) b1)), delete_max_spec (Avl_Node k0 d0 l0 (Avl_Node i b a a0 b0) b1) *)
inversion_clear H1.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.
(* Goal: @eq nat (S O) (S (height_avl r0)) *)
(* Goal: @eq nat (S O) (S (height_avl r0)) *)
(* Goal: @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0)), delete_spec key (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 discriminate H4.

(* r0=(Avl_Node kr0 dr0 lr0 rr0 br0) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 a b0)), delete_max_spec (Avl_Node k0 d0 l0 a b0)) (a0 : avl_tree) (_ : forall (k0 : Int) (d0 : B) (l0 : avl_tree) (b0 : bal) (_ : is_avl (Avl_Node k0 d0 l0 a0 b0)), delete_max_spec (Avl_Node k0 d0 l0 a0 b0)) (b0 : bal) (k0 : Int) (d0 : B) (l0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 l0 (Avl_Node i b a a0 b0) b1)), delete_max_spec (Avl_Node k0 d0 l0 (Avl_Node i b a a0 b0) b1) *)
intros kr0 dr0 lr0 ih_lr0 rr0 ih_rr0 br0 k0 d0 l0 b0 avl_t0.
(* Goal: delete_max_spec (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) *)
elim (ih_rr0 kr0 dr0 lr0 br0); clear ih_lr0 ih_rr0.
(* Goal: forall (k : Int) (d : B) (t : avl_tree) (_ : lookup k (Avl_Node kr0 dr0 lr0 rr0 br0) d) (_ : is_avl t) (_ : is_below_avl t k) (_ : @eq (list (prod Int B)) (lin_avl (Avl_Node kr0 dr0 lr0 rr0 br0)) (@app (prod Int B) (lin_avl t) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B))))) (_ : equiv_del k (Avl_Node kr0 dr0 lr0 rr0 br0) t) (_ : sumbool (@eq nat (height_avl (Avl_Node kr0 dr0 lr0 rr0 br0)) (height_avl t)) (@eq nat (height_avl (Avl_Node kr0 dr0 lr0 rr0 br0)) (S (height_avl t)))), delete_max_spec (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
intros k d r lookup_r avl_r below_avl_r lin_r equiv_del_r bal_or_shift.
(* Goal: delete_max_spec (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
elim (balance_shrunk_left k0 d0 l0 r b0). 
(* Goal: forall (t : avl_tree) (_ : is_avl t) (_ : @eq (list (prod Int B)) (lin_avl t) (lin_avl (Avl_Node k0 d0 l0 r b0))) (_ : equiv t (Avl_Node k0 d0 l0 r b0)) (_ : sumbool (hasnot_shrunk_left t k0 d0 l0 r b0) (has_shrunk_left t k0 d0 l0 r b0)), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros t avl_t lin_t equiv_t shrunk_dec.
(* Goal: delete_max_spec (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply Del_Max_Spec_Intro with k d t.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply below_below_avl.
(* Goal: is_below t k *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (@app (prod Int B) (lin_avl t) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))) *)
(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply below_equiv_below with (Avl_Node k0 d0 l0 r b0).
(* Goal: is_below (Avl_Node k0 d0 l0 r b0) k *)
(* Goal: equiv t (Avl_Node k0 d0 l0 r b0) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (@app (prod Int B) (lin_avl t) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))) *)
(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
cut (Less k0 k).
(* Goal: forall _ : Less k0 k, is_below (Avl_Node k0 d0 l0 r b0) k *)
(* Goal: Less k0 k *)
(* Goal: equiv t (Avl_Node k0 d0 l0 r b0) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (@app (prod Int B) (lin_avl t) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))) *)
(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
intro less_k0.
(* Goal: is_below (Avl_Node k0 d0 l0 r b0) k *)
(* Goal: Less k0 k *)
(* Goal: equiv t (Avl_Node k0 d0 l0 r b0) *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (@app (prod Int B) (lin_avl t) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))) *)
(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply Below_Node.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below l0 k *)
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
apply below_trans with k0.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_below_avl_is_below; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_below_avl_is_below; assumption.
(* Goal: Less k0 k *)
(* Goal: equiv_del k (Avl_Node kr0 dr0 lr0 rr0 br0) r *)
(* Goal: equiv (Avl_Node k0 d0 l0 r b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply lookup_above_greater with (Avl_Node kr0 dr0 lr0 rr0 br0) d.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_above_avl_is_above; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) l2) *)
(* Goal: lookup key r0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite lin_t.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (@app (prod Int B) (lin_avl lr0) (@cons (prod Int B) (@pair Int B kr0 dr0) (lin_avl rr0))))) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r))) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))) *)
(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
 rewrite (app_ass (lin_avl l0) ((k0, d0) :: lin_avl r) ((k, d) :: nil)).
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (@app (prod Int B) (lin_avl lr0) (@cons (prod Int B) (@pair Int B kr0 dr0) (lin_avl rr0))))) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (@app (prod Int B) (lin_avl r) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))))) *)
(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
 rewrite <- lin_r.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: equiv_del k (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply equiv_del_equiv_equiv_del with (Avl_Node k0 d0 l0 r b0).
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply equiv_del_right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: Less k0 k *)
(* Goal: equiv_del k (Avl_Node kr0 dr0 lr0 rr0 br0) r *)
(* Goal: equiv (Avl_Node k0 d0 l0 r b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply lookup_above_greater with (Avl_Node kr0 dr0 lr0 rr0 br0) d.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_above_avl_is_above; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_sym; assumption.


(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
clear equiv_t avl_t lin_r equiv_del_r below_avl_r lookup_r bal_or_shift.
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim shrunk_dec; clear shrunk_dec.

(* Goal: forall _ : hasnot_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
intros has_notshrunk.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
generalize H1; clear H H0 H1 H2 H3.
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
inversion_clear has_notshrunk.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear H; simpl in |- *. 
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite <- H0; clear H0.
(* Goal: forall _ : @eq nat match blr with | Left_Balanced => S (height_avl llr) | Balanced => S (height_avl llr) | Right_Balanced => S (height_avl rlr) end (S (height_avl r)), @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
intros Balanced_l; inversion_clear Balanced_l.
(* Goal: @eq nat (S match br0 with | Left_Balanced => S (height_avl lr0) | Balanced => S (height_avl lr0) | Right_Balanced => S (height_avl rr0) end) (S (S (height_avl l0))) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
 rewrite H.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.

(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; simpl in |- *; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; simpl in |- *; trivial.

(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
intro has_shrunk.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 (Avl_Node kr0 dr0 lr0 rr0 br0) b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_avl r *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
generalize H1; clear H1 H H0 H2 H3.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear has_shrunk; simpl in |- *.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : @eq nat match blr with | Left_Balanced => S (height_avl llr) | Balanced => S (height_avl llr) | Right_Balanced => S (height_avl rlr) end (S (height_avl r)), @eq nat (height_avl (Avl_Node klr dlr (Avl_Node kl dl ll llr match blr with | Left_Balanced => Balanced | Balanced => Balanced | Right_Balanced => Left_Balanced end) (Avl_Node k d rlr r match blr with | Left_Balanced => Right_Balanced | Balanced => Balanced | Right_Balanced => Balanced end) Balanced)) (height_avl (Avl_Node kl dl ll (Avl_Node klr dlr llr rlr blr) Right_Balanced)) *)
intros Balanced_l; inversion_clear Balanced_l.
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl l)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.

(* side premisses (Elim (balance ...)) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply above_above_avl.
(* Goal: is_above r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply above_equiv_del_above with (Avl_Node kr0 dr0 lr0 rr0 br0) k. 
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_above_avl_is_above; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
elim bal_or_shift; clear bal_or_shift; intros height_r.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
apply
 hasnot_grown_right__preserves_is_balanced_avl
  with (Avl_Node kr0 dr0 lr0 rr0 br0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
symmetry  in |- *; assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_balanced_avl_left_shift l0 r b0 *)
(* Goal: is_avl (Avl_Node kr0 dr0 lr0 rr0 br0) *)
apply Balanced_shrunk_left_balanced_shift with (Avl_Node kr0 dr0 lr0 rr0 br0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Side premiss of (Elim ih_rr0) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
Qed.

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


Inductive hasnot_shrunk_right (t : avl_tree) (k : Int) 
(d : B) (l r : avl_tree) : bal -> Prop :=
  | Hasnot_Shrunk_Right_Bal :
      forall b : bal,
      is_balanced_avl l r b ->
      height_avl t = height_avl (Avl_Node k d l r b) ->
      hasnot_shrunk_right t k d l r b
  | Hasnot_Shrunk_Right_Shift_Balanced :
      is_balanced_avl_right_shift l r Balanced ->
      height_avl t = S (height_avl r) ->
      hasnot_shrunk_right t k d l r Balanced
  | Hasnot_Shrunk_Right_Shift_Right :
      is_balanced_avl_right_shift l r Right_Balanced ->
      height_avl t = S (height_avl r) ->
      hasnot_shrunk_right t k d l r Right_Balanced.

Inductive has_shrunk_right (t : avl_tree) (k : Int) 
(d : B) (l r : avl_tree) : bal -> Prop :=
  | Has_Shrunk_Right_Shift_Left :
      is_balanced_avl_right_shift l r Left_Balanced ->
      height_avl t = S (height_avl r) ->
      has_shrunk_right t k d l r Left_Balanced
  | Has_Shrunk_Right_Shift_Right :
      is_balanced_avl_right_shift l r Right_Balanced ->
      height_avl t = height_avl r ->
      has_shrunk_right t k d l r Right_Balanced.




Inductive bal_shrunk_right_spec (k : Int) (d : B) (l r : avl_tree) 
(b : bal) : Set :=
    Balance_Shrunk_Right_Spec_Intro :
      forall t : avl_tree,
      is_avl t ->
      lin_avl t = lin_avl (Avl_Node k d l r b) ->
      equiv t (Avl_Node k d l r b) ->
      {hasnot_shrunk_right t k d l r b} + {has_shrunk_right t k d l r b} ->
      bal_shrunk_right_spec k d l r b.


Lemma balance_shrunk_right :
 forall (k : Int) (d : B) (l r : avl_tree) (b : bal),
 is_avl l ->
 is_below_avl l k ->
 is_avl r ->
 is_above_avl r k ->
 {is_balanced_avl l r b} + {is_balanced_avl_right_shift l r b} ->
 bal_shrunk_right_spec k d l r b.
(* Goal: forall (k : Int) (d : B) (l r : avl_tree) (b : bal) (_ : is_avl l) (_ : is_below_avl l k) (_ : is_avl r) (_ : is_above_avl r k) (_ : sumbool (is_balanced_avl l r b) (is_balanced_avl_right_shift l r b)), bal_shrunk_right_spec k d l r b *)
intros k d l r b avl_l below_avl_l avl_r above_avl_r bal_or_shift.
(* Goal: bal_shrunk_right_spec k d l r b *)
elim bal_or_shift; clear bal_or_shift.
(* l and r is Balanced with respect to b *)
(* Goal: forall _ : is_balanced_avl l r b, bal_shrunk_right_spec k d l r b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
intro Balanced_l.
(* Goal: bal_shrunk_right_spec k d l r b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
apply Balance_Shrunk_Right_Spec_Intro with (Avl_Node k d l r b). 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: hasnot_shrunk_right (Avl_Node k d l r b) k d l r b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
apply Hasnot_Shrunk_Right_Bal. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* l and r is'nt Balanced with respect to b *)
(* Goal: forall _ : is_balanced_avl_right_shift l r b, bal_shrunk_right_spec k d l r b *)
elim b; clear b; intros Balanced_shift_l.
(* b=Left_Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Left_Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Balance_Shrunk_Right_Spec_Intro with (Avl_Node k d l r Balanced).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Balanced)) (lin_avl (Avl_Node k d l r Left_Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Balanced) (Avl_Node k d l r Left_Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) (has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Fully_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: has_shrunk_right (Avl_Node k d l r Balanced) k d l r Left_Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Has_Shrunk_Right_Shift_Left. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq nat (S (height_avl l)) (S (height_avl r)) *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
inversion_clear Balanced_shift_l.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.

(* b=Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Balance_Shrunk_Right_Spec_Intro with (Avl_Node k d l r Right_Balanced).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Node_Is_Avl; try assumption.
(* Goal: is_balanced_avl l r Right_Balanced *)
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k d l r Right_Balanced)) (lin_avl (Avl_Node k d l r Balanced)) *)
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Is_Right_Balanced_Avl.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: equiv (Avl_Node k d l r Right_Balanced) (Avl_Node k d l r Balanced) *)
(* Goal: sumbool (hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) (has_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced) *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply equiv_refl.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: hasnot_shrunk_right (Avl_Node k d l r Right_Balanced) k d l r Balanced *)
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
apply Hasnot_Shrunk_Right_Shift_Balanced. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* b=Right_Balanced *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
elim (rebalance_right k d l r Right_Balanced); try assumption.
(* Goal: forall (x : avl_tree) (_ : and (is_avl x) (and (@eq (list (prod Int B)) (lin_avl x) (lin_avl (Avl_Node k d l r Right_Balanced))) (and (equiv x (Avl_Node k d l r Right_Balanced)) match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl x) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl x) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl x) (height_avl r) end))), bal_shrunk_right_spec k d l r Right_Balanced *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intros t (avl_t,(lin_t,(equiv_t,height_t))).
(* Goal: bal_shrunk_right_spec k d l r Right_Balanced *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
apply Balance_Shrunk_Right_Spec_Intro with t.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
clear lin_t equiv_t avl_l below_avl_l avl_r above_avl_r.
(* Goal: sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
generalize height_t; clear height_t.
(* Goal: forall _ : match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl t) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl t) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl t) (height_avl r) end, sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
generalize Balanced_shift_l; clear Balanced_shift_l.
(* Goal: forall (_ : is_balanced_avl_right_shift l r Right_Balanced) (_ : match r with | Avl_Nil => True | Avl_Node i b a a0 (Left_Balanced as b0) => @eq nat (height_avl t) (height_avl r) | Avl_Node i b a a0 (Balanced as b0) => @eq nat (height_avl t) (S (height_avl r)) | Avl_Node i b a a0 (Right_Balanced as b0) => @eq nat (height_avl t) (height_avl r) end), sumbool (hasnot_shrunk_right t k d l r Right_Balanced) (has_shrunk_right t k d l r Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
case r; clear r.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intro u0. 
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
inversion_clear u0.
(* Goal: False *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
 discriminate H.
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
intros kr dr lr rr br.
(* Goal: forall (_ : is_balanced_avl_right_shift l (Avl_Node kr dr lr rr br) Right_Balanced) (_ : match br with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node kr dr lr rr br)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node kr dr lr rr br))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node kr dr lr rr br)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node kr dr lr rr br) Right_Balanced) (has_shrunk_right t k d l (Avl_Node kr dr lr rr br) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
elim br; clear br; simpl in |- *; intros Balanced_shift_l height_t.
(* br=Left_Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Has_Shrunk_Right_Shift_Right; assumption.
(* br=Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Hasnot_Shrunk_Right_Shift_Right; assumption.
(* br=Right_Balanced *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Has_Shrunk_Right_Shift_Right; assumption.
(* side premisses of (Elim (rebalance ... )) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear Balanced_shift_l; assumption.
Qed.

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


Inductive lin_del_spec (key : Int) (d : B) (t0 t : avl_tree) : Prop :=
    Lin_Del_Spec_Intro :
      forall l0 l1 : list (Int * B),
      lin_avl t0 = l0 ++ (key, d) :: l1 ->
      lin_avl t = l0 ++ l1 -> lin_del_spec key d t0 t.


Inductive delete_spec (key : Int) (t0 : avl_tree) : Set :=
    Delete_Spec_Intro :
      forall t : avl_tree,
      lookup_dec_spec key t0 ->
      is_avl t ->
      (forall d : B, lookup key t0 d -> lin_del_spec key d t0 t) ->
      equiv_del key t0 t ->
      {height_avl t0 = height_avl t} + {height_avl t0 = S (height_avl t)} ->
      delete_spec key t0.


Lemma equiv_del_nil : forall key : Int, equiv_del key Avl_Nil Avl_Nil.
(* Goal: forall key : Int, equiv_del key Avl_Nil Avl_Nil *)
intros key.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 l b0) (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_del_intro.

(* Goal: forall (k : Int) (_ : Equal k key) (d : B) (_ : lookup k Avl_Nil d), False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k Avl_Nil data), lookup k Avl_Nil data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k Avl_Nil data), lookup k Avl_Nil data *)
intros k equal d lookup_nil.
(* Goal: False *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k Avl_Nil data), lookup k Avl_Nil data *)
(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k Avl_Nil data), lookup k Avl_Nil data *)
apply (inv_lookup_nil k d lookup_nil).

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k Avl_Nil data), lookup k Avl_Nil data *)
intros k d notequal lookup_nil.
(* Goal: lookup k Avl_Nil d *)
apply lookup_nil.

(* Goal: forall (k : Int) (data : B) (_ : not (Equal k key)) (_ : lookup k Avl_Nil data), lookup k Avl_Nil data *)
intros k d notequal lookup_nil.
(* Goal: lookup k Avl_Nil d *)
apply lookup_nil.
Qed.


Lemma equiv_del_right_semi_leave :
 forall (k : Int) (d : B) (r : avl_tree) (b : bal),
 is_avl (Avl_Node k d Avl_Nil r b) ->
 equiv_del k (Avl_Node k d Avl_Nil r b) r.
(* Goal: forall (k : Int) (d : B) (r : avl_tree) (b : bal) (_ : is_avl (Avl_Node k d Avl_Nil r b)), equiv_del k (Avl_Node k d Avl_Nil r b) r *)
intros k d r b avl_t.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 l b0) (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_del_intro.

(* Goal: forall (k0 : Int) (_ : Equal k0 k) (d : B) (_ : lookup k0 r d), False *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d Avl_Nil r b) data), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
intros k0 equal d0 lookup_r.
(* Goal: False *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d Avl_Nil r b) data), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
apply (less_irrefl k).
(* Goal: Less k k *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d Avl_Nil r b) data), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
apply (less_equal_less k k0 k).
(* Goal: Less k k0 *)
(* Goal: Equal k0 k *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d Avl_Nil r b) data), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
apply (lookup_above_greater k0 r d0 k lookup_r).
(* Goal: is_above r k *)
(* Goal: Equal k0 k *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d Avl_Nil r b) data), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear avl_t. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_above_avl_is_above; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 (Avl_Node k d Avl_Nil r b) data), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
intros k0 data notequal lookup_t.
(* Goal: lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
generalize notequal; clear notequal.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear lookup_t.
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro notequal.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply notequal.
(* Goal: Equal k0 k0 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply equal_refl.
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall _ : not (Equal k0 k), lookup k0 r data *)
(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
inversion_clear H.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
intros; assumption.

(* Goal: forall (k0 : Int) (data : B) (_ : not (Equal k0 k)) (_ : lookup k0 r data), lookup k0 (Avl_Node k d Avl_Nil r b) data *)
intros k0 data notequal lookup_l.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
Qed.


Lemma equiv_del_equal :
 forall (key k0 k : Int) (l0 l r0 : avl_tree) (b0 : bal) (d d0 : B),
 Equal key k0 ->
 equiv_del k l0 l ->
 lookup k l0 d ->
 is_below l0 k0 ->
 is_above r0 k0 ->
 is_avl l0 -> equiv_del key (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k d l r0 b0).
intros key k0 k l0 l r0 b0 d d0 equal_key equiv_del_l lookup_l below_l0
 above_r0 avl_l0.
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k d l r0 b0) *)
 rewrite (equal_eq key k0 equal_key); clear equal_key key.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 l b0) (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_del_intro.

(* Goal: forall (k1 : Int) (_ : Equal k1 k0) (d0 : B) (_ : lookup k1 (Avl_Node k d l r0 b0) d0), False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
intros k1 equal_k1 d1 lookup_d1.
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite (equal_eq k1 k0 equal_k1) in lookup_d1; clear equal_k1 k1.

(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
inversion lookup_d1.
(* Goal: False *)
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply lookup_below_false with k l0 d.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Left_Balanced)) (S (S (height_avl r0))) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
clear H0 H4 H3 H2 H1 H data b r l1 d2 k1 lookup_d1.
(* Goal: False *)
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply lookup_below_false with k0 l0 d1.
(* Goal: lookup k1 l0 d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
inversion_clear equiv_del_l.
(* Goal: lookup k0 l0 d1 *)
(* Goal: is_below l0 k0 *)
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply H1.
(* Goal: forall (_ : is_balanced_avl_right_shift l Avl_Nil Right_Balanced) (_ : True), sumbool (hasnot_shrunk_right t k d l Avl_Nil Right_Balanced) (has_shrunk_right t k d l Avl_Nil Right_Balanced) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b0 : bal) (_ : is_balanced_avl_right_shift l (Avl_Node i b a a0 b0) Right_Balanced) (_ : match b0 with | Left_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) | Balanced => @eq nat (height_avl t) (S (height_avl (Avl_Node i b a a0 b0))) | Right_Balanced => @eq nat (height_avl t) (height_avl (Avl_Node i b a a0 b0)) end), sumbool (hasnot_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) (has_shrunk_right t k d l (Avl_Node i b a a0 b0) Right_Balanced) *)
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r) *)
unfold not in |- *; intro u0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H with k0 d1; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
clear H0 H4 H3 H2 H1 H data b r l1 d2 k1 lookup_d1.
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply lookup_above_false with k0 r0 d1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k d l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
intros k1 d1 notequal lookup_t0.

(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
inversion lookup_t0; clear lookup_t0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply notequal.
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl l)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite H0.
(* Goal: Equal k0 k0 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply equal_refl.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
clear H0 H4 H3 H2 H1 H data b r l1 d2 k2.
(* Goal: lookup k1 l0 d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
elim (equal_dec k1 k).
(* Goal: forall _ : Equal k1 k, lookup k1 l0 d1 *)
(* Goal: forall _ : not (Equal k1 k), lookup k1 l0 d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
intro equal_k1.
(* Goal: lookup k1 r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
 rewrite (equal_eq k1 k equal_k1).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite <- (lookup_avl_equal k1 k l0 d1 d); try assumption.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.

(* Goal: forall _ : not (Equal k1 k), lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k d l r0 b0) d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
intros notequal0.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
apply Lookup_Left.
(* Goal: lookup k1 l0 d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
inversion_clear equiv_del_l.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H0; assumption.

(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
clear H0 H4 H3 H2 H1 H data b r l1 d2 k2.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
apply Lookup_Right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k0)) (_ : lookup k1 (Avl_Node k d l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
intros k1 d1 notequal lookup_k1.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
inversion lookup_k1.
(* Goal: lookup k (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
 rewrite <- H5.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
clear H0 H4 H3 H2 H1 H data b r l1 d2 k2.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
apply Lookup_Left.
(* Goal: lookup k1 l0 d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
inversion_clear equiv_del_l.
(* Goal: lookup k1 l0 d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
elim (equal_dec k1 k).
(* Goal: forall _ : Equal k1 k, lookup k1 l0 d1 *)
(* Goal: forall _ : not (Equal k1 k), lookup k1 l0 d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
intro equal_k1.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H with k1 d1; assumption.
(* Goal: forall _ : not (Equal k1 k), lookup k1 l0 d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
intro notequal_k1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H1; assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
Qed.


Lemma is_balanced_avl_is_balanced_avl_right_shift_left :
 forall (l l0 r0 : avl_tree) (b0 : bal),
 is_balanced_avl l0 r0 b0 ->
 S (height_avl l) = height_avl l0 -> is_balanced_avl_right_shift l r0 b0.
(* Goal: forall (l l0 r0 : avl_tree) (b0 : bal) (_ : is_balanced_avl l0 r0 b0) (_ : @eq nat (S (height_avl l)) (height_avl l0)), is_balanced_avl_right_shift l r0 b0 *)
intros l l0 r0 b0 Balanced_r0 height_l.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
inversion_clear Balanced_r0.
(* Goal: is_balanced_avl_right_shift l r0 Left_Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
apply Is_Left_Balanced_Avl_Right_Shift.
(* Goal: @eq nat (height_avl l) (height_avl r0) *)
(* Goal: is_balanced_avl_right_shift l r0 Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
 rewrite H in height_l.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection height_l; trivial.
(* Goal: is_balanced_avl_right_shift l r0 Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
apply Is_Fully_Balanced_Avl_Right_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite <- H; assumption.
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
apply Is_Right_Balanced_Avl_Right_Shift.
(* Goal: @eq nat (S (S (height_avl l))) (height_avl r0) *)
 rewrite height_l.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
Qed.


Lemma is_balanced_is_balanced_right_shift :
 forall (l l0 r0 : avl_tree) (b0 : bal),
 is_balanced_avl l0 r0 b0 ->
 height_avl l0 = S (height_avl l) -> is_balanced_avl_right_shift l r0 b0.
(* Goal: forall (l l0 r0 : avl_tree) (b0 : bal) (_ : is_balanced_avl l0 r0 b0) (_ : @eq nat (height_avl l0) (S (height_avl l))), is_balanced_avl_right_shift l r0 b0 *)
intros l l0 r0 b0 Balanced_l0 height_r.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
inversion_clear Balanced_l0.
(* Goal: is_balanced_avl_right_shift l r0 Left_Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
apply Is_Left_Balanced_Avl_Right_Shift.
(* Goal: @eq nat (height_avl l) (height_avl r0) *)
(* Goal: is_balanced_avl_right_shift l r0 Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
 rewrite H in height_r.
symmetry  in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 injection height_r; trivial.
(* Goal: is_balanced_avl_right_shift l r0 Balanced *)
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
apply Is_Fully_Balanced_Avl_Right_Shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 rewrite <- height_r; assumption.
(* Goal: is_balanced_avl_right_shift l r0 Right_Balanced *)
apply Is_Right_Balanced_Avl_Right_Shift.
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite height_r; trivial.
Qed.

Lemma equiv_del_trans_left :
 forall (k k0 : Int) (d0 : B) (l0 r0 l : avl_tree) (b0 : bal),
 Less k k0 ->
 is_above r0 k0 ->
 equiv_del k l0 l ->
 equiv_del k (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l r0 b0).
(* Goal: forall (k k0 : Int) (d0 : B) (l0 r0 l : avl_tree) (b0 : bal) (_ : Less k k0) (_ : is_above r0 k0) (_ : equiv_del k l0 l), equiv_del k (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l r0 b0) *)
intros k k0 d0 l0 r0 l b0 less_k above_r0 equiv_del_l0.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l r0 b0) *)
inversion_clear equiv_del_l0.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 l b0) (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_del_intro.

(* Goal: forall (k1 : Int) (_ : Equal k1 k) (d : B) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) d), False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
intros k1 equal_k1 d1 lookup1.
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
apply H with k1 d1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: lookup k1 r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
 rewrite (equal_eq k1 k equal_k1).
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
 rewrite (equal_eq k1 k equal_k1) in lookup1; clear equal_k1 k1.
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
inversion lookup1.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup k r0 d1 *)
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
apply less_irrefl with k0.
(* Goal: Less k0 k0 *)
(* Goal: lookup k l d1 *)
(* Goal: lookup k l d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
 rewrite H3 in less_k.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply lookup_above_false with k r0 d1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_above r0 k *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
apply above_trans with k0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
intros k1 d1 notequal lookup1.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
inversion_clear lookup1.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
apply Lookup_Left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.

(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
intros k1 d1 notequal lookup1.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
inversion_clear lookup1.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
(* Goal: lookup k1 (Avl_Node k0 d0 l0 r0 b0) d1 *)
apply Lookup_Left.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H1; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
Qed.


Lemma equiv_del_trans_right :
 forall (k k0 : Int) (d0 : B) (l0 r r0 : avl_tree) (b0 : bal),
 Less k0 k ->
 is_below l0 k0 ->
 equiv_del k r0 r ->
 equiv_del k (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b0).
(* Goal: forall (k k0 : Int) (d0 : B) (l0 r r0 : avl_tree) (b0 : bal) (_ : Less k0 k) (_ : is_below l0 k0) (_ : equiv_del k r0 r), equiv_del k (Avl_Node k0 d0 l0 r0 b0) (Avl_Node k0 d0 l0 r b0) *)
intros k k0 d0 l0 r0 l b0 greater_k below_l0 equiv_del_r0.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 l b0) (Avl_Node k0 d0 l0 r0 b0) *)
inversion_clear equiv_del_r0.
(* Goal: equiv_del k (Avl_Node k0 d0 l0 l b0) (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_del_intro.

(* Goal: forall (k1 : Int) (_ : Equal k1 k) (d : B) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) d), False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
intros k1 equal_k1 d1 lookup1.
(* Goal: False *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
apply H with k1 d1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: lookup k1 r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
 rewrite (equal_eq k1 k equal_k1).
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
 rewrite (equal_eq k1 k equal_k1) in lookup1; clear equal_k1 k1.
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
inversion lookup1.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup k r0 d1 *)
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
apply less_irrefl with k0.
(* Goal: Less k0 k0 *)
(* Goal: lookup k r0 d1 *)
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
 rewrite H3 in greater_k.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
apply lookup_below_false with k l0 d1.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below l0 k *)
(* Goal: lookup k r0 d1 *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 l b0) data), lookup k1 (Avl_Node k0 d0 l0 r0 b0) data *)
(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
apply below_trans with k0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
intros k1 d1 notequal lookup1.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
inversion_clear lookup1.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
apply Lookup_Right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H0; assumption.


(* Goal: forall (k1 : Int) (data : B) (_ : not (Equal k1 k)) (_ : lookup k1 (Avl_Node k0 d0 l0 r0 b0) data), lookup k1 (Avl_Node k0 d0 l0 l b0) data *)
intros k1 d1 notequal lookup1.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
inversion_clear lookup1.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: lookup k1 (Avl_Node k0 d0 l0 l b0) d1 *)
apply Lookup_Right.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply H1; assumption.
Qed.


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

Lemma delete_avl :
 forall (key : Int) (t0 : avl_tree), is_avl t0 -> delete_spec key t0.
(* Goal: forall _ : is_avl t0, avl_ins_spec key update init t0 *)
intros key t0; elim t0; clear t0.

(* t0=nil *)
(* Goal: forall _ : is_avl Avl_Nil, delete_spec key Avl_Nil *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
intros avl_t0.
(* Goal: delete_spec key Avl_Nil *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
apply Delete_Spec_Intro with (t := Avl_Nil).

(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: forall d : B, not (lookup key Avl_Nil d) *)
(* Goal: is_avl Avl_Nil *)
(* Goal: forall (d : B) (_ : lookup key Avl_Nil d), lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
unfold not in |- *; intros d lookup_t0.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: forall (d : B) (_ : lookup key Avl_Nil d), lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
intros d lookup_t0.
(* Goal: lin_del_spec key d Avl_Nil Avl_Nil *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
elimtype False.
(* Goal: False *)
(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
inversion_clear lookup_t0.

(* Goal: equiv_del key Avl_Nil Avl_Nil *)
(* Goal: sumbool (@eq nat (height_avl Avl_Nil) (height_avl Avl_Nil)) (@eq nat (height_avl Avl_Nil) (S (height_avl Avl_Nil))) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
apply equiv_del_nil.

(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left; simpl in |- *; trivial.

(* t0=(Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (i : Int) (b : B) (a : avl_tree) (_ : forall _ : is_avl a, delete_spec key a) (a0 : avl_tree) (_ : forall _ : is_avl a0, delete_spec key a0) (b0 : bal) (_ : is_avl (Avl_Node i b a a0 b0)), delete_spec key (Avl_Node i b a a0 b0) *)
intros k0 d0 l0 ih_l0 r0 ih_r0 b0 avl_t0.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim (equal_dec key k0).

(* (Equal key=k0)  *)
(* Goal: forall _ : Equal key k0, delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intros equal.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
clear ih_l0 ih_r0.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
generalize avl_t0; clear avl_t0.
(* Goal: forall _ : is_avl (Avl_Node k0 d0 l0 r0 b0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
case l0; clear l0.
(* l0=nil *)
(* Goal: forall _ : is_avl (Avl_Node k0 d0 Avl_Nil r0 b0), delete_spec key (Avl_Node k0 d0 Avl_Nil r0 b0) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0)), delete_spec key (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro avl_t0.
(* Goal: delete_spec key (Avl_Node k0 d0 Avl_Nil r0 b0) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0)), delete_spec key (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Delete_Spec_Intro with (t := r0).

(* Goal: lookup_dec_spec key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) *)
(* Goal: is_avl t *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
left with d0.
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (@cons (prod Int B) (@pair Int B key d1) (lin_avl r0))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (equal_eq key k0 equal).
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.

(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros d lookup0.
(* Goal: lin_del_spec key d (Avl_Node k0 d0 Avl_Nil r0 b0) r0 *)
(* Goal: equiv_del key (Avl_Node k0 d0 Avl_Nil r0 b0) r0 *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 Avl_Nil r0 b0)) (height_avl r0)) (@eq nat (height_avl (Avl_Node k0 d0 Avl_Nil r0 b0)) (S (height_avl r0))) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0)), delete_spec key (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lin_Del_Spec_Intro with (nil (A:=Int * B)) (lin_avl r0). 
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite (equal_eq key k0 equal); trivial.
 rewrite (lookup_avl_equal key k0 (Avl_Node k0 d0 Avl_Nil r0 b0) d d0);
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 try assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.

(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (@cons (prod Int B) (@pair Int B key d1) (lin_avl r0))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (equal_eq key k0 equal).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_del_right_semi_leave; assumption.

(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right. 
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear H1; simpl in |- *.
(* Goal: @eq nat (S O) (S (height_avl r0)) *)
(* Goal: @eq nat (S O) (S (height_avl r0)) *)
(* Goal: @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0)), delete_spec key (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 discriminate H4.
(* Goal: @eq nat (S O) (S (height_avl r0)) *)
(* Goal: @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0)), delete_spec key (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H4.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* l0=(node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall (i : Int) (b : B) (a a0 : avl_tree) (b1 : bal) (_ : is_avl (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0)), delete_spec key (Avl_Node k0 d0 (Avl_Node i b a a0 b1) r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intros kl0 dl0 ll0 rl0 bl0 avl_t0.
(* Goal: delete_spec key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim (delete_max kl0 dl0 ll0 rl0 bl0).

(* Goal: forall (k : Int) (d : B) (t : avl_tree) (_ : lookup k (Avl_Node kl0 dl0 ll0 rl0 bl0) d) (_ : is_avl t) (_ : is_below_avl t k) (_ : @eq (list (prod Int B)) (lin_avl (Avl_Node kl0 dl0 ll0 rl0 bl0)) (@app (prod Int B) (lin_avl t) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B))))) (_ : equiv_del k (Avl_Node kl0 dl0 ll0 rl0 bl0) t) (_ : sumbool (@eq nat (height_avl (Avl_Node kl0 dl0 ll0 rl0 bl0)) (height_avl t)) (@eq nat (height_avl (Avl_Node kl0 dl0 ll0 rl0 bl0)) (S (height_avl t)))), delete_spec key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intros k d l lookup_l0 avl_l below_l lin_l0 equiv_del_l0 bal_or_shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
elim (balance_shrunk_right k d l r0 b0); try assumption.
(* Goal: forall (t : avl_tree) (_ : is_avl t) (_ : @eq (list (prod Int B)) (lin_avl t) (lin_avl (Avl_Node k d l r0 b0))) (_ : equiv t (Avl_Node k d l r0 b0)) (_ : sumbool (hasnot_shrunk_right t k d l r0 b0) (has_shrunk_right t k d l r0 b0)), delete_spec key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intros t avl_t lin_t0 equiv_t0 shrunk_dec.
(* Goal: delete_spec key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Delete_Spec_Intro with (t := t).

(* Goal: lookup_dec_spec key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) *)
(* Goal: is_avl t *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
left with d0.
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (@cons (prod Int B) (@pair Int B key d1) (lin_avl r0))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (equal_eq key k0 equal).
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
simpl in |- *; apply Lookup_Equal.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intros d1 lookup0.
apply
 Lin_Del_Spec_Intro
  with (lin_avl ll0 ++ (kl0, dl0) :: lin_avl rl0) (lin_avl r0).
(* Goal: @eq (list (prod Int B)) (lin_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (@cons (prod Int B) (@pair Int B key d1) (lin_avl r0))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (equal_eq key k0 equal).
 rewrite
 (lookup_avl_equal key k0
    (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d1 d0)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 ; try assumption.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.
(* Goal: lookup k0 (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) d0 *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lookup_Equal.
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl ll0) (@cons (prod Int B) (@pair Int B kl0 dl0) (lin_avl rl0))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
generalize lin_l0; clear lin_l0; simpl in |- *; intro lin_l0.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) l1 (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0)))) *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite lin_l0.
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl l) (@cons (prod Int B) (@pair Int B k d) (@nil (prod Int B)))) (lin_avl r0)) *)
(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (app_ass (lin_avl l) ((k, d) :: nil) (lin_avl r0)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: equiv_del key (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply equiv_del_equiv_equiv_del with (t1 := Avl_Node k d l r0 b0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_del_equal; try assumption.
(* Goal: is_below (Avl_Node kl0 dl0 ll0 rl0 bl0) k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply is_below_avl_is_below.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: is_above r0 k0 *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: equiv (Avl_Node k d l r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply is_above_avl_is_above.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_sym; assumption.

(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
clear lin_t0 equiv_t0 avl_t bal_or_shift equiv_del_l0 below_l avl_l lookup_l0.
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim shrunk_dec; clear shrunk_dec.

(* Goal: forall _ : hasnot_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intros hasnot_shrunk.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
generalize H1; clear H1 H3 H2 H0 H.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear hasnot_shrunk.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear H; simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl l)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: @eq nat (S match bl0 with | Left_Balanced => S (height_avl ll0) | Balanced => S (height_avl ll0) | Right_Balanced => S (height_avl rl0) end) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r0)) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_right t k d l r0 b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Left_Balanced)) (S (S (height_avl r0))) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.

(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros has_shrunk.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
generalize H1; clear H H0 H1 H2 H3.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear has_shrunk.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Left_Balanced)) (S (S (height_avl r0))) *)
(* Goal: forall _ : is_balanced_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 (Avl_Node kl0 dl0 ll0 rl0 bl0) r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite <- H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.

(* side premisses (Elim balance_shrunk_right ...) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: is_above_avl r0 k *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply above_avl_trans with k0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: Less k k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply lookup_below_less with (Avl_Node kl0 dl0 ll0 rl0 bl0) d.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: is_below (Avl_Node kl0 dl0 ll0 rl0 bl0) k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: is_avl (Avl_Node kl0 dl0 ll0 rl0 bl0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply is_below_avl_is_below.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.

(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim bal_or_shift; clear bal_or_shift; intros height_l0.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
apply
 hasnot_grown_left__preserves_is_balanced_avl
  with (Avl_Node kl0 dl0 ll0 rl0 bl0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
symmetry  in |- *; assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
apply
 is_balanced_avl_is_balanced_avl_right_shift_left
  with (Avl_Node kl0 dl0 ll0 rl0 bl0).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
symmetry  in |- *; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.


(* ~(Equal key k0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro notequal.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim (less_dec key k0).

(* (Less key k0) *)
(* Goal: forall _ : Less key k0, delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro less.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Equal key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim (ih_l0 (inv_is_avl_left k0 d0 l0 r0 b0 avl_t0)); clear ih_l0 ih_r0.
(* Goal: forall (t : avl_tree) (_ : lookup_dec_spec key l0) (_ : is_avl t) (_ : forall (d : B) (_ : lookup key l0 d), lin_del_spec key d l0 t) (_ : equiv_del key l0 t) (_ : sumbool (@eq nat (height_avl l0) (height_avl t)) (@eq nat (height_avl l0) (S (height_avl t)))), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intros l lookup_l0 avl_l lin_l0 equiv_del_l0 bal_or_shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
elim (balance_shrunk_right k0 d0 l r0 b0); try assumption.
(* Goal: forall (t : avl_tree) (_ : is_avl t) (_ : @eq (list (prod Int B)) (lin_avl t) (lin_avl (Avl_Node k0 d0 l0 r b0))) (_ : equiv t (Avl_Node k0 d0 l0 r b0)) (_ : sumbool (hasnot_shrunk_left t k0 d0 l0 r b0) (has_shrunk_left t k0 d0 l0 r b0)), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros t avl_t lin_t equiv_t shrunk_dec.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Delete_Spec_Intro with t; try assumption.

(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim lookup_l0; clear lookup_l0.
(* Goal: forall (d : B) (_ : lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros d lookup_d.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left with d.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Left; assumption.
(* Goal: forall _ : forall d : B, not (lookup key l0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro not_lookup_l0.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: forall d : B, not (lookup key (Avl_Node k0 d0 l0 r0 b0) d) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
unfold not in |- *; intros d lookup_t.
(* Goal: False *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply (not_lookup_l0 d).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_avl_inv_less key k0 d0 l0 r0 b0 d); assumption.

(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
clear shrunk_dec equiv_t avl_t bal_or_shift equiv_del_l0 lookup_l0.
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros d lookup0.
(* Goal: lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim lin_l0 with d; clear lin_l0.
(* Goal: forall (l1 l2 : list (prod Int B)) (_ : @eq (list (prod Int B)) (lin_avl l0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) l2))) (_ : @eq (list (prod Int B)) (lin_avl l) (@app (prod Int B) l1 l2)), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intros l1 l2 lin_l0 lin_l.
(* Goal: lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply Lin_Del_Spec_Intro with l1 (l2 ++ (k0, d0) :: lin_avl r0).
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) l1 (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0)))) *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite lin_l0.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) l2)) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))))) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) l1 (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0)))) *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite (app_ass l1 ((key, d) :: l2) ((k0, d0) :: lin_avl r0)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) l2) *)
(* Goal: lookup key r0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite lin_t.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) l1 (@app (prod Int B) l2 (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0)))) *)
(* Goal: lookup key l0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
 rewrite lin_l.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite (app_ass l1 l2 ((k0, d0) :: lin_avl r0)); trivial.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_avl_inv_less key k0 d0 l0 r0 b0 d); assumption.

(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
clear shrunk_dec lin_t bal_or_shift lin_l0.
apply equiv_del_equiv_equiv_del with (t1 := Avl_Node k0 d0 l r0 b0);
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_del_trans_left; try assumption.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_above_avl_is_above; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_sym; assumption.

(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
clear lin_t equiv_t avl_t bal_or_shift equiv_del_l0 lookup_l0.
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim shrunk_dec; clear shrunk_dec.

(* Goal: forall _ : hasnot_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intro hasnot_shrunk.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
generalize H1; clear H H0 H1 H2 H3.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear hasnot_shrunk.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear H; simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros Balanced_l0; inversion_clear Balanced_l0; simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; trivial.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.

(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros has_shrunk.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
generalize H1; clear H H0 H1 H2 H3.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear has_shrunk.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; trivial.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.

(* side premisses (Elim (balance_shrunk_right ...) ) *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: is_below_avl l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply below_below_avl.
(* Goal: is_below l k0 *)
(* Goal: is_avl r0 *)
(* Goal: is_above_avl r0 k0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply below_equiv_del_below with l0 key. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_below_avl_is_below; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim bal_or_shift; clear bal_or_shift; intros height_l0.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_balanced_avl l r0 b0 *)
(* Goal: sumbool (is_balanced_avl l r0 b0) (is_balanced_avl_right_shift l r0 b0) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply hasnot_grown_left__preserves_is_balanced_avl with l0. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
symmetry  in |- *; assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
apply is_balanced_is_balanced_right_shift with l0. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* (Less k0 key) *)
(* Goal: forall _ : not (Less key k0), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
intro notless.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
generalize (notequal_notless_greater key k0 notequal notless); intro greater.
(* Goal: delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
elim ih_r0; clear ih_r0 ih_l0 notless.
(* Goal: forall (t : avl_tree) (_ : lookup_dec_spec key r0) (_ : is_avl t) (_ : forall (d : B) (_ : lookup key r0 d), lin_del_spec key d r0 t) (_ : equiv_del key r0 t) (_ : sumbool (@eq nat (height_avl r0) (height_avl t)) (@eq nat (height_avl r0) (S (height_avl t)))), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl r0 *)
intros r lookup_r0 avl_r lin_r0 equiv_r0 bal_or_shift.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
elim (balance_shrunk_left k0 d0 l0 r b0); try assumption.
(* Goal: forall (t : avl_tree) (_ : is_avl t) (_ : @eq (list (prod Int B)) (lin_avl t) (lin_avl (Avl_Node k0 d0 l0 r b0))) (_ : equiv t (Avl_Node k0 d0 l0 r b0)) (_ : sumbool (hasnot_shrunk_left t k0 d0 l0 r b0) (has_shrunk_left t k0 d0 l0 r b0)), delete_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros t avl_t lin_t equiv_t shrunk_dec.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Delete_Spec_Intro with t; try assumption.

(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim lookup_r0; clear lookup_r0.
(* Goal: forall (d : B) (_ : lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros d lookup_d.
(* Goal: lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left with d.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply Lookup_Right; assumption.
(* Goal: forall _ : forall d : B, not (lookup key r0 d), lookup_dec_spec key (Avl_Node k0 d0 l0 r0 b0) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intro not_lookup_r0.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: forall d : B, not (lookup key (Avl_Node k0 d0 l0 r0 b0) d) *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
unfold not in |- *; intros d lookup_t.
(* Goal: False *)
(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply (not_lookup_r0 d).
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_avl_inv_greater key k0 d0 l0 r0 b0 d); assumption.

(* Goal: forall (d : B) (_ : lookup key (Avl_Node k0 d0 l0 r0 b0) d), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros d lookup0.
(* Goal: lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim lin_r0 with d; clear lin_r0.
(* Goal: forall (l1 l2 : list (prod Int B)) (_ : @eq (list (prod Int B)) (lin_avl r0) (@app (prod Int B) l1 (@cons (prod Int B) (@pair Int B key d) l2))) (_ : @eq (list (prod Int B)) (lin_avl r) (@app (prod Int B) l1 l2)), lin_del_spec key d (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: lookup key r0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros l1 l2 lin_r0 lin_r.
apply Lin_Del_Spec_Intro with (lin_avl l0 ++ (k0, d0) :: l1) l2;
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r0))) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) (@cons (prod Int B) (@pair Int B key d) l2)) *)
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) l2) *)
(* Goal: lookup key r0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite (app_ass (lin_avl l0) ((k0, d0) :: l1) ((key, d) :: l2)).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite lin_r0; trivial.
(* Goal: @eq (list (prod Int B)) (lin_avl t) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) l2) *)
(* Goal: lookup key r0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite lin_t.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: @eq (list (prod Int B)) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) (lin_avl r))) (@app (prod Int B) (@app (prod Int B) (lin_avl l0) (@cons (prod Int B) (@pair Int B k0 d0) l1)) l2) *)
(* Goal: lookup key r0 d *)
(* Goal: equiv_del key (Avl_Node k0 d0 l0 r0 b0) t *)
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite (app_ass (lin_avl l0) ((k0, d0) :: l1) l2).
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite lin_r; trivial.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply (lookup_avl_inv_greater key k0 d0 l0 r0 b0 d); assumption.

apply equiv_del_equiv_equiv_del with (t1 := Avl_Node k0 d0 l0 r b0);
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
 try assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_del_trans_right; try assumption.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_below_avl_is_below; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply equiv_sym; assumption.

(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
clear lin_t equiv_t avl_t bal_or_shift equiv_r0 lookup_r0.
(* Goal: sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim shrunk_dec; clear shrunk_dec.

(* Goal: forall _ : hasnot_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intro hasnot_shrunk.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
generalize H1; clear H H0 H1 H2 H3.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear hasnot_shrunk.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear H; simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (S (height_avl r0)) (S (height_avl r)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (height_avl t) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Balanced)) (height_avl t) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite <- H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
trivial.

(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
intros has_shrunk.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
generalize H1; clear H H0 H1 H2 H3.
(* Goal: forall _ : is_balanced_avl l0 r0 b0, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear has_shrunk.

(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: forall _ : is_balanced_avl l0 r0 Left_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Left_Balanced)) (S (height_avl l0)) *)
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *; trivial.
(* Goal: forall _ : is_balanced_avl l0 r0 Right_Balanced, @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (height_avl t)) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; clear H0.
(* Goal: is_balanced_avl_right_shift l r0 b0 *)
intros Balanced_l0; inversion_clear Balanced_l0.
(* Goal: @eq nat (height_avl (Avl_Node k0 d0 l0 r0 Right_Balanced)) (S (S (height_avl l0))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
simpl in |- *.
(* Goal: forall _ : is_balanced_avl l0 r0 Balanced, @eq nat (S (height_avl l0)) (S (height_avl l0)) *)
(* Goal: forall _ : has_shrunk_left t k0 d0 l0 r b0, sumbool (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (height_avl t)) (@eq nat (height_avl (Avl_Node k0 d0 l0 r0 b0)) (S (height_avl t))) *)
(* Goal: is_avl l0 *)
(* Goal: is_below_avl l0 k0 *)
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
 rewrite H0; trivial.

(* side premisses (Elim (balance_shrunk_right ...) ) *)
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0.
(* Goal: is_above_avl r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply above_above_avl.
(* Goal: is_above r k0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply above_equiv_del_above with r0 key. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
apply is_above_avl_is_above; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
elim bal_or_shift; clear bal_or_shift; intros height_l0.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
left.
(* Goal: is_balanced_avl l0 r b0 *)
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
apply hasnot_grown_right__preserves_is_balanced_avl with r0. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
symmetry  in |- *; assumption.
(* Goal: sumbool (is_balanced_avl l0 r b0) (is_balanced_avl_left_shift l0 r b0) *)
(* Goal: is_avl r0 *)
right.
(* Goal: is_balanced_avl_left_shift l0 r b0 *)
(* Goal: is_avl r0 *)
apply Balanced_shrunk_left_balanced_shift with r0. 
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
assumption.

(* Goal: @eq nat (height_avl r0) (S (height_avl r)) *)
(* Goal: is_avl r0 *)
inversion_clear avl_t0; assumption.
Qed.

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

Inductive AVL : Set :=
    AVL_intro : forall t : avl_tree, is_avl t -> AVL.


Definition AVL_NIL := AVL_intro Avl_Nil Nil_Is_Avl.


Definition LOOKUP (key : Int) (T : AVL) (data : B) :=
  match T with
  | AVL_intro t _ => lookup key t data
  end.


Definition LOOKUP_Dec_Spec (key : Int) (T : AVL) :=
  match T with
  | AVL_intro t _ => lookup_dec_spec key t
  end.

Theorem LOOKUP_DEC : forall (key : Int) (T : AVL), LOOKUP_Dec_Spec key T.
(* Goal: forall (key : Int) (T : AVL), LOOKUP_Dec_Spec key T *)
intros key T.
(* Goal: LOOKUP_Dec_Spec key T *)
elim T; clear T.
(* Goal: forall (t : avl_tree) (i : is_avl t), LOOKUP_Dec_Spec key (AVL_intro t i) *)
exact (lookup_dec key).
Qed.


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

Definition LIN_AVL (T : AVL) := match T with
                                | AVL_intro t _ => lin_avl t
                                end.


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

Definition LIN_INS (key : Int) (update : B -> B) (init : B) 
  (T0 T : AVL) :=
  match T0 with
  | AVL_intro t0 _ =>
      match T with
      | AVL_intro t _ => lin_ins_spec key update init t0 t
      end
  end.

Definition EQUIV_INS (key : Int) (update : B -> B) 
  (init : B) (T0 T : AVL) :=
  match T0 with
  | AVL_intro t0 _ =>
      match T with
      | AVL_intro t _ => equiv_ins key update init t0 t
      end
  end.


Definition INSRT_Spec (key : Int) (update : B -> B) 
  (init : B) (T0 : AVL) :=
  match T0 with
  | AVL_intro t0 _ => avl_ins_spec key update init t0
  end.

Theorem INSRT_AVL :
 forall (key : Int) (update : B -> B) (init : B) (T0 : AVL),
 INSRT_Spec key update init T0.
(* Goal: forall (key : Int) (update : forall _ : B, B) (init : B) (T0 : AVL), INSRT_Spec key update init T0 *)
intros key update init T0.
(* Goal: DELETE_Spec key T0 *)
elim T0; clear T0.
(* Goal: forall (t : avl_tree) (i : is_avl t), INSRT_Spec key update init (AVL_intro t i) *)
exact (insert_avl key update init).
Qed.

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


Definition LIN_DEL (key : Int) (d : B) (T0 T : AVL) :=
  match T0 with
  | AVL_intro t0 _ =>
      match T with
      | AVL_intro t _ => lin_del_spec key d t0 t
      end
  end.


Definition EQUIV_DEL (key : Int) (T0 T : AVL) :=
  match T0 with
  | AVL_intro t0 _ => match T with
                      | AVL_intro t _ => equiv_del key t0 t
                      end
  end.


Definition DELETE_Spec (key : Int) (T0 : AVL) :=
  match T0 with
  | AVL_intro t0 _ => delete_spec key t0
  end.


Theorem DELETE_AVL : forall (key : Int) (T0 : AVL), DELETE_Spec key T0.
(* Goal: forall (key : Int) (T0 : AVL), DELETE_Spec key T0 *)
intros key T0.
(* Goal: DELETE_Spec key T0 *)
elim T0; clear T0.
(* Goal: forall (t : avl_tree) (i : is_avl t), DELETE_Spec key (AVL_intro t i) *)
exact (delete_avl key).
Qed.

End avl_trees.



(* In order to extract a ML program use:  *)

(*
Require Extraction.

Extract Constant Int => int.
Link Int := Int.
Extract Inductive sumbool => bool [ true false ].
Extract Constant equal_dec => "(=)".
Extract Constant less_dec => "(<)".

Write Caml File "avl_trees" [rebalance_left rebalance_right 
                            balance_left balance_right
                            balance_shrunk_left balance_shrunk_right
                            delete_max
                            lookup_dec insert_avl delete_avl lin_avl].
*)


