(****************************************************************************)
(*                 The Calculus of Inductive Constructions                  *)
(*                                                                          *)
(*                                Projet Coq                                *)
(*                                                                          *)
(*                     INRIA        LRI-CNRS        ENS-CNRS                *)
(*              Rocquencourt         Orsay          Lyon                    *)
(*                                                                          *)
(*                                 Coq V6.2                                 *)
(*                               May 1st 1998                               *)
(*                                                                          *)
(****************************************************************************)
(*                                Avl_prog.v                                *)
(****************************************************************************)

Require Export Le.

Lemma O_S' : (m:nat) ~((S m)=O).
Red; Intros m H.
Apply (O_S m).
Auto.
Save.
Hint O_S'.

Section trees.

(*************************************************)
(*		Variables		  	 *)
(*************************************************)

Axiom a : Set.
Axiom inf : a -> a -> Prop.

Axiom inf_dec : (x,y:a) {inf x y}+{inf y x}.
Axiom inf_trans : (x,y,z:a) (inf x y) -> (inf y z) -> (inf x z).

(*********************************************************)
(*		Definitions and5, and3		         *)
(*********************************************************)

Inductive and5 [a1,a2,a3,a4,a5:Prop] : Prop
	:= conj5 : a1 -> a2 -> a3 -> a4 -> a5 -> (and5 a1 a2 a3 a4 a5).

Hint conj5.

(******
Lemma and5_rec : (A1,A2,A3,A4,A5:Prop)
     (C:Set)(A1->A2->A3->A4->A5->C)->(and5 A1 A2 A3 A4 A5)->C.
Intros A1 A2 A3 A4 A5 C F A.
Apply F; Elim A; Auto.
Save.
********)

Inductive and3 [a1,a2,a3:Prop] : Prop
	:= conj3 : a1 -> a2 -> a3  -> (and3 a1 a2 a3).

Hint conj3.

(*******
Lemma and3_rec : (A1,A2,A3:Prop)
     (C:Set)(A1->A2->A3->C)->(and3 A1 A2 A3)->C.
Intros A1 A2 A3 C F A.
Apply F; Elim A; Auto.
Save.
********)

(*************************************************)
(*		Definition max		  	 *)
(*************************************************)

Fixpoint max [n:nat] : nat -> nat :=
 [m:nat]Case n of
     (* O *) m
   (* S p *) [p:nat]Case m of
                 (* O *) (S p) 
               (* S q *) [q:nat](S (max p q)) 
		    end
	end.

(*************************************************)
(*		Definition equil		 *)
(*************************************************)

Inductive equil : Set
	:= ga : equil
	| mi : equil
	| dr : equil.

(*************************************************)
(*		Definition abe		  	 *)
(*************************************************)

Inductive abe : Set
	:= nil : abe
	| node : a -> abe -> abe -> equil -> abe.

(*************************************************)
(*		Definition haut		  	 *)
(*************************************************)

Fixpoint haut [h:abe] : nat :=
 	Case h of
           (* nil *) O
(* node l g d des *) [l:a][g,d:abe][des:equil] 
                       (S (max (haut g) (haut d))) 
	end.

Lemma haut_node : (l:a)(g,d:abe)(e:equil)
     (S (max (haut g) (haut d)))=(haut (node l g d e)).
Auto.
Save.

(*************************************************)
(*		Definition or3		  	 *)
(*************************************************)

Inductive or3 [A,B,C:Prop] : Prop :=
    cas1 : A -> (or3 A B C)
  | cas2 : B -> (or3 A B C)
  | cas3 : C -> (or3 A B C).

Hint cas1 cas2 cas3.

(*************************************************)
(*		Definition in		  	 *)
(*************************************************)

Inductive In [x:a] : abe->Prop
 := In_left : (y:a)(g,d:abe)(e:equil)(In x g)->(In x (node y g d e))
 | In_right : (y:a)(g,d:abe)(e:equil)(In x d)->(In x (node y g d e))
 | In_node :  (g,d:abe)(e:equil)(In x (node x g d e)).

Hint In_node In_left In_right.

Lemma In_node_eq : (x,l:a)(g,d:abe)(e:equil)(l=x)->(In x (node l g d e)).
Induction 1; Auto.
Save.
Hint In_node_eq.

Local in_inverse 
   [x:a][h:abe]
     Case h of
      (* nil *)     False  
(* node l g d eq *) [l:a][g,d:abe][des:equil]
                            (or3 (In x g) (In x d) (l=x))
	end.

Lemma In_nil : (x:a)~(In x nil).
Red; Intros x H; Change (in_inverse x nil).
Elim H; Simpl; Auto.
Save.
Hint In_nil.

Lemma In_node_inv : (x:a)(l:a)(g,d:abe)(e:equil)
     (In x (node l g d e))->(or3 (In x g) (In x d) (l=x)).
Intros x l g d e H; Change (in_inverse x (node l g d e)).
Elim H; Simpl; Auto.
Save.
(*Hint In_node_inv.*)



(*************************************************)
(*		Definition inft		  	 *)
(*************************************************)

Inductive inft [x:a] : abe -> Prop
  := inft_nil : (inft x nil)
  | inft_node : (l:a)(g,d:abe)(des:equil)
                (inf x l)->(inft x g)->(inft x d)->(inft x (node l g d des)).

Hint inft_nil inft_node.

Local inft_inverse
   [x:a][t:abe]Case t of
                (* nil *) True
     (* node l g d des *) [l:a][g,d:abe][des:equil]
	                         (and3 (inf x l) (inft x g) (inft x d))
		end.

Lemma inft_node_inv : (x,l:a)(g,d:abe)(des:equil)
     (inft x (node l g d des))->(and3 (inf x l) (inft x g) (inft x d)).
Intros x l g d des H; Change (inft_inverse x (node l g d des)); Elim H; Simpl;Auto.
Save.

Lemma inft_in_inf : (x:a)(t:abe)(inft x t)->(y:a)(In y t)->(inf x y).
Induction 1; Intros.
Absurd (In y nil); Auto.
Elim (In_node_inv y l g d des); Auto.
Induction 1; Auto.
Save.

Lemma in_inf_inft : (x:a)(t:abe)((y:a)(In y t)->(inf x y))->(inft x t).
Induction t; Auto.
Save.

(*************************************************)
(*		Definition supt		  	 *)
(*************************************************)

Inductive supt [x:a] : abe -> Prop
  := supt_nil : (supt x nil)
  | supt_node : (l:a)(g,d:abe)(des:equil)
                (inf l x)->(supt x g)->(supt x d)->(supt x (node l g d des)).

Hint supt_nil supt_node.

Local supt_inverse
   [x:a][t:abe]Case t of
                (* nil *) True
     (* node l g d des *) [l:a][g,d:abe][des:equil]
                          (and3 (inf l x) (supt x g) (supt x d))
		end.

Lemma supt_node_inv : (x,l:a)(g,d:abe)(des:equil)
     (supt x (node l g d des))->(and3 (inf l x) (supt x g) (supt x d)).
Intros x l g d des H; Change (supt_inverse x (node l g d des)); Elim H; Simpl;Auto.
Save.

Lemma supt_in_inf : (x:a)(t:abe)(supt x t)->(y:a)(In y t)->(inf y x).
Induction 1; Intros.
Absurd (In y nil); Auto.
Elim (In_node_inv y l g d des); Auto.
Induction 1; Auto.
Save.

Lemma in_inf_supt : (x:a)(t:abe)((y:a)(In y t)->(inf y x))->(supt x t).
Induction t; Auto.
Save.


(*************************************************)
(*		Definition bal		  	 *)
(*************************************************)

Inductive bal [g,d:abe] : equil->Prop
   := bal_ga : ((haut g)=(S(haut d))) -> (bal g d ga)
   | bal_mi : ((haut g)=(haut d)) -> (bal g d mi)
   | bal_dr : ((S (haut g))=(haut d)) -> (bal g d dr).

Hint bal_ga bal_mi bal_dr.

Local bal_inverse  [g,d:abe][e:equil]
     Case e of
         (* ga *)  ((haut g)=(S(haut d)))
         (* mi *)  ((haut g)=(haut d))
	 (* dr *)  ((S(haut g))=(haut d))
     end.

Lemma bal_ga_inv : (g,d:abe)(bal g d ga)->(haut g)=(S(haut d)).
Intros g d H; Change (bal_inverse g d ga); Elim H; Simpl; Auto.
Save.
Immediate bal_ga_inv.

Lemma bal_mi_inv : (g,d:abe)(bal g d mi)->(haut g)=(haut d).
Intros g d H; Change (bal_inverse g d mi); Elim H; Simpl; Auto.
Save.
Immediate bal_mi_inv.


Lemma bal_dr_inv : (g,d:abe)(bal g d dr)->(S (haut g))=(haut d).
Intros g d H; Change (bal_inverse g d dr); Elim H; Simpl; Auto.
Save.
Immediate bal_dr_inv.

Lemma bal_rec : (g,d:abe)(P:equil->Set)
          (((haut g)=(S (haut d)))->(P ga))->
          (((haut g)=(haut d))->(P mi))->
          (((S (haut g))=(haut d))->(P dr))->
          (e:equil)(bal g d e)->(P e).
Realizer [g,d:abe][P:Set][H,H0,H1:P][e:equil]
		Cases e of
		    ga => H 
	          | mi => H0 
		  | dr => H1
		end.
Program_all.
Save.


(*************************************************)
(*		Definition avl		  	 *)
(*************************************************)

Inductive avl : abe -> Prop
:= avl_nil : (avl nil)
| avl_node : (l:a)(g,d:abe)(des:equil)
             (avl g)->(avl d)->(bal g d des)->(supt l g)->(inft l d)
             ->(avl (node l g d des)).

Hint avl_nil avl_node.

Definition avl_inverse := 
[u:abe]Case u of
           (* nil *) True
(* node l g d des *) [l:a][g,d:abe][des:equil]
    	             (and5 (avl g) (avl d) (supt l g) (inft l d) (bal g d des))
	end.

Lemma avl_inv : (l:a)(g,d:abe)(des:equil)(avl (node l g d des))
     ->(and5 (avl g) (avl d) (supt l g) (inft l d) (bal g d des)).
Intros l g d des H; Change (avl_inverse (node l g d des)).
Elim H; Simpl; Auto.
Save.

Lemma avl_rec : 
     (t:abe)(P:abe->Set)
     (P nil)
     ->((l:a)(g,d:abe)(des:equil)(avl g)->(P g)->(avl d)->(P d)
         ->(supt l g)->(inft l d) ->(bal g d des)->(P (node l g d des)))
     ->(avl t)->(P t).
Realizer [t:abe][P:Set][H0:P][H1:a->abe->abe->equil->P->P->P]
                Match t with
		  H0
                  [l,g,Pg,d,Pd,des](H1 l g d des Pg Pd)
		end.
Program_all.
Elim (avl_inv a1 a2 a3 e); Auto.
Elim (avl_inv a1 a2 a3 e); Auto.
Elim (avl_inv a1 a2 a3 e); Auto.
Elim (avl_inv a1 a2 a3 e); Auto.
Elim (avl_inv a1 a2 a3 e); Auto.
Elim (avl_inv a1 a2 a3 e); Auto.
Elim (avl_inv a1 a2 a3 e); Auto.
Save.

(*************************************************************)
(*    	  A special kind of avl obtained after an insertion  *)
(*        that modifies the heigth                           *)
(*************************************************************)

Inductive avl_ins : abe -> Prop
  := ins_ga : (l:a)(g,d:abe)(avl g)->(avl d)->
              ((haut g)=(S (haut d)))->
              (supt l g)->(inft l d)->(avl_ins (node l g d ga))
  | ins_mil : (l:a)(avl_ins (node l nil nil mi))
  | ins_dr : (l:a)(g,d:abe)(avl g)->(avl d)->
              ((S (haut g))=(haut d))->
              (supt l g)->(inft l d)->(avl_ins (node l g d dr)).

Hint ins_ga ins_mil ins_dr.
        
Definition avl_ins_inverse := 
[t:abe]Case t of
           (* nil *) False
(* node l g d des *) [l:a][g,d:abe][des:equil] 
                       Case des of
                       (* ga *) (and5 (avl g) (avl d) 
                                      ((haut g)=(S (haut d)))
                                      (supt l g) (inft l d))
                       (* mi *) ((nil=g)/\ (nil=d))
                       (* dr *) (and5 (avl g) (avl d) 
                                      ((S (haut g))=(haut d))
                                      (supt l g) (inft l d))
			end 
	end.

Lemma avl_ins_nil_inv : ~(avl_ins nil).
Red; Intro H; Change (avl_ins_inverse nil); Elim H; Simpl; Auto.
Save.

Lemma avl_ins_ga_inv : (l:a)(g,d:abe)
     (avl_ins (node l g d ga))->
     (and5 (avl g) (avl d) ((haut g)=(S (haut d))) (supt l g) (inft l d)).
Intros l g d H; Change (avl_ins_inverse  (node l g d ga)); Elim H; Simpl;Auto.
Save.

Lemma avl_ins_mi_inv : (l:a)(g,d:abe)
     (avl_ins (node l g d mi))->((nil=g)/\ (nil=d)).
Intros l g d H; Change (avl_ins_inverse  (node l g d mi)); Elim H; Simpl;Auto.
Save.

Lemma avl_ins_dr_inv : (l:a)(g,d:abe)
     (avl_ins (node l g d dr))->
     (and5 (avl g) (avl d) ((S (haut g))=(haut d)) (supt l g) (inft l d)).
Intros l g d H; Change (avl_ins_inverse  (node l g d dr)); Elim H; Simpl;Auto.
Save.

Lemma avl_ins_avl : (t:abe)(avl_ins t)->(avl t).
Induction 1; Auto.
Save.
Immediate avl_ins_avl.

Lemma avl_ins_rec : (P:abe->Set)
        ((l:a)(g,d:abe)(avl g)->(avl d)->
               ((haut g)=(S (haut d)))->
               (supt l g)->(inft l d)->(P (node l g d ga)))
        ->((l:a)(P (node l nil nil mi)))->
        ((l:a)(g,d:abe)(avl g)->(avl d)->
               ((S (haut g))=(haut d))->
               (supt l g)->(inft l d)->(P (node l g d dr)))
        ->(a:abe)(avl_ins a)->(P a).

Realizer [P:Set][H:a->abe->abe->P][H0:a->P][H1:a->abe->abe->P][a0:abe]
             Cases a0 of
		nil => (False_rec P)
              | (node l g d ga) => (H l g d)
	      | (node l _ _ mi) => (H0 l)
              | (node l g d dr) => (H1 l g d)
	     end.


Program_all.
Elim avl_ins_nil_inv; Auto.
Elim (avl_ins_ga_inv l g d); Auto.
Elim (avl_ins_ga_inv l g d); Auto.
Elim (avl_ins_ga_inv l g d); Auto.
Elim (avl_ins_ga_inv l g d); Auto.
Elim (avl_ins_ga_inv l g d); Auto.
Elim (avl_ins_mi_inv l g d); Auto.
Destruct 1; Destruct 1; Auto.
Elim (avl_ins_dr_inv l g d); Auto.
Elim (avl_ins_dr_inv l g d); Auto.
Elim (avl_ins_dr_inv l g d); Auto.
Elim (avl_ins_dr_inv l g d); Auto.
Elim (avl_ins_dr_inv l g d); Auto.
Save.

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

Definition equiv_abe :=
  [t,t':abe](((x:a)(In x t)->(In x t'))/\ ((x:a)(In x t')->(In x t))).

Inductive equiv [y:a;t,t':abe] : Prop :=
  equiv_intro : 
   ((x:a)(In x t)->(In x t'))->
   (In y t')->((x:a)(In x t')->((In x t)\/y=x))
   -> (equiv y t t').
Hint equiv_intro.

(*************************************************)
(*    Lemmas                                     *)
(*************************************************)

Lemma equiv_equiv_abe : (x:a)(t,u,v:abe)(equiv x t u)->(equiv_abe u v)->(equiv x t v).
Intros x t u v H H0; Elim H; Intros H1 H2 H3; Elim H0; Intros H4 H5; Auto.
Save.

Lemma equiv_gauche : (y,l:a)(g,g',d:abe)(des,des':equil)
     (equiv y g g')->(equiv y (node l g d des) (node l g' d des')).
Intros.
Elim H ; Intros.
Apply equiv_intro; Auto.
Intros x H3; Elim (In_node_inv x l g d des) ; Auto.
Intros x H3; Elim (In_node_inv x l g' d des') ; Auto.
Intro H4; Elim (H2 x); Auto.
Save.

Lemma equiv_droite : (y,l:a)(g,d,d':abe)(des,des':equil)
     (equiv y d d')->(equiv y (node l g d des) (node l g d' des')).
Intros.
Elim H ; Intros.
Apply equiv_intro; Auto.
Intros x H3; Elim (In_node_inv x l g d des) ; Auto.
Intros x H3; Elim (In_node_inv x l g d' des') ; Auto.
Intro H4; Elim (H2 x); Auto.
Save.

Hint equiv_gauche equiv_droite.



(*************************************************)
(*		Definition avl_spec	  	 *)
(*************************************************)

Inductive avl_spec [x:a;t:abe] : Set
	:= h_eq : (h:abe)(avl h)->(equiv x t h)->((haut h)=(haut t)) 
                 -> (avl_spec x t)
	| h_plus : (h:abe)(avl_ins h)->(equiv x t h)
                 -> ((haut h)=(S(haut t))) ->(avl_spec x t).

Definition h_eqc := [x:a][t:abe][h:abe](h_eq x t h).
Definition h_plusc := [x:a][t:abe][h:abe](h_plus x t h).

(*************************************************)
(*		Definition abe_match	  	 *)
(*************************************************)
Lemma abe_match : (P:abe->Set)
       (P nil)
     ->((l:a)(g:abe)(d:abe)(des:equil) (P (node l g d des)))
     ->(t:abe)(P t).
Realizer [P:Set][H:P][H0:a->abe->abe->equil->P][t:abe]
                 Cases t of
		    nil => H
                 | (node a0 y y0 e) => (H0 a0 y y0 e)
		  end.
Program_all.
Save.

(*************************************************)
(*		Definition abe_case	  	 *)
(*************************************************)

Lemma abe_case : (t:abe)(P:abe->Prop)
       ((nil=t)->(P nil))
     ->((l:a)(g:abe)(d:abe)(des:equil)
         ((node l g d des)=t)->(P (node l g d des)))
     ->(P t).

Intro t.
Elim t ; Intros ; Auto.
Save.

Lemma equiv_sup_g : (g,g':abe)(l,x:a)
     (equiv x g g')-> (supt l g)-> (inf x l) -> (supt l g').
Induction 1; Intros H1 H2 H3 S I.
Apply in_inf_supt.
Intros y H4; Elim (H3 y); Trivial.
Intro H5; Apply supt_in_inf with g; Auto.
Induction 1; Auto.
Save.

Lemma bal_haut : (g,g',d,d':abe)(des:equil)
     ((haut g')=(haut g))->((haut d')=(haut d))
      ->(bal g d des)->(bal g' d' des).
Intros g g' d d' des Hg Hd B;
Elim B; Elim Hg; Elim Hd; Auto.
Save.

Lemma equiv_inf_g : (g,g':abe)(l,x:a)
     (equiv x g g') -> (inft l g) -> (inf l x) -> (inft l g').
Induction 1; Intros H1 H2 H3 S I.
Apply in_inf_inft.
Intros y H4; Elim (H3 y); Trivial.
Intro H5; Apply inft_in_inf with g; Auto.
Induction 1; Auto.
Save.

Lemma inft_trans : (l,l':a)(t:abe)(inf l l')->(inft l' t)->(inft l t).
Induction 2; Auto.
Intros l0 g d des I' ITg' ITg ITd' ITd.
Cut (inf l l0); Auto.
Apply inf_trans with l'; Auto.
Save.

Lemma supt_trans : (l,l':a)(t:abe)(inf l' l)->(supt l' t)->(supt l t).
Induction 2; Auto.
Intros l0 g d des I' ITg' ITg ITd' ITd.
Cut (inf l0 l); Auto.
Apply inf_trans with l'; Auto.
Save.

Lemma haut_plus : (g,g':abe)(des:equil)(d:abe)(l:a)
     ((haut g)=(haut g'))->
     ((haut (node l g' d des))=(haut (node l g d des))).
Intros g g' des d l H; Simpl; Elim H; Auto.
Save.
Hint haut_plus.

Lemma max_n_n : (n:nat)(n=(max n n)).
Induction n ; Simpl ; Auto.
Save.
Hint max_n_n.

Lemma max_Sn_n : (n:nat)((S n)=(max (S n) n)).
Induction n ; Simpl ; Auto.
Save.
Hint max_Sn_n.

Lemma max_n_Sn : (n:nat)((S n)=(max n (S n))).
Induction n ; Simpl ; Auto.
Save.
Hint max_n_Sn.

Lemma le_max : (m,n:nat)(le n m)->(m=(max m n)).
Intros m n Le; Pattern n m; Apply le_elim_rel; Simpl; Auto.
Induction p; Simpl; Auto.
Save.
Hint le_max.

Lemma max_case : (n,m:nat)((n=(max n m))\/(m=(max n m))).
Induction n.
Simpl; Auto.
Induction m.
Simpl; Auto.
Intros p H0; Simpl; Elim (H p); Auto.
Save.

Lemma max_sym : (n,m:nat)(max m n)=(max n m).
Induction n;Induction m; Simpl; Auto.
Save.

(*************************************************)
(*						 *)
(*   Rotations                             	 *)
(*						 *)
(*************************************************)

Chapter rotations.

Variables l, m :a.
Variables t,v : abe.

Hypothesis avlv : (avl v).
Hypothesis avlt : (avl t).

Hypothesis inflv : (inft l v).
Hypothesis supmt : (supt m t).

Hint inflv supmt avlt avlv.

Section simple_rotations.

Variable u : abe.
Hypothesis avlu : (avl u).
Hint avlu.

Section right_rotation.

Hypothesis suplmtu : (supt l (node m t u ga)).
Hypothesis infmu : (inft m u).

Hint suplmtu infmu.

Lemma infml : (inf m l).
Elim (supt_node_inv l m t u ga); Auto.
Save.
Hint infml.

Lemma suptlu : (supt l u).
Elim (supt_node_inv l m t u ga); Auto.
Save.
Hint suptlu.

Hypothesis Htu : (haut t)=(S (haut u)).
Hypothesis Huv : (haut u)=(haut v).

Hint Huv Htu.

Definition rot_d := (node m t (node l u v mi) mi).

Lemma avl_rotd : (avl rot_d).
Unfold rot_d.
Apply avl_node; Auto.
Apply bal_mi; Simpl.
Elim Huv.
Elim max_n_n; Auto.
Apply inft_node; Auto.
Apply inft_trans with l; Auto.
Save.

Lemma equiv_rotd : (eql:equil)(equiv_abe (node l (node m t u ga) v eql) rot_d).
Intro eql; Unfold equiv_abe rot_d; Split.
Intros x H; Elim (In_node_inv x l (node m t u ga) v eql); Auto.
Intro H0; Elim (In_node_inv x m t u ga); Auto.
Intros x H; Elim (In_node_inv x m t (node l u v mi) mi); Auto.
Intro H0; Elim (In_node_inv x l u v mi); Auto.
Save.

Lemma haut_rotd : (S (haut t))=(haut rot_d).
Simpl.
Elim Huv.
Elim max_n_n.
Elim Htu; Auto.
Save.

Opaque rot_d.

End right_rotation.

Section left_rotation.

Hypothesis inftmuv : (inft m (node l u v dr)).
Hypothesis suplu : (supt l u).

Hint inftmuv suplu.

Lemma infml' : (inf m l).
Elim (inft_node_inv m l u v dr); Auto.
Save.
Hint infml'.

Lemma inftmu : (inft m u).
Elim (inft_node_inv m l u v dr); Auto.
Save.
Hint inftmu.

Hypothesis Hut : (haut u)=(haut t).
Hypothesis Huv : (haut v)=(S (haut u)).

Hint Huv Hut.

Definition rot_g := (node l (node m t u mi) v mi).

Lemma avl_rotg : (avl rot_g).
Unfold rot_g.
Apply avl_node; Auto.
Apply bal_mi; Simpl.
Elim Hut.
Elim max_n_n; Auto.
Apply supt_node; Auto.
Apply supt_trans with m; Auto.
Save.

Lemma equiv_rotg : (eqm:equil)(equiv_abe (node m t (node l u v dr) eqm) rot_g).
Intros eqm; Unfold equiv_abe rot_g; Split.
Intros x H; Elim (In_node_inv x m t (node l u v dr) eqm); Auto.
Intro H0; Elim (In_node_inv x l u v dr); Auto.
Intros x H; Elim (In_node_inv x l (node m t u mi) v mi); Auto.
Intro H0; Elim (In_node_inv x m t u mi); Auto.
Save.

Lemma haut_rotg : (S (haut v))=(haut rot_g).
Unfold rot_g; Elim haut_node.
Elim haut_node.
Elim Hut.
Elim max_n_n.
Elim Huv; Auto.
Save.

Opaque rot_g.

End left_rotation.

End simple_rotations.

Section double_rotations.

Variable n:a.
Variables u1,u2:abe.
Variable eqn : equil.

Local u :=  (node n u1 u2 eqn).
Hypothesis avlu : (avl u).

Hypothesis infmu : (inft m u).
Hypothesis suplu : (supt l u).
Hypothesis infml : (inf m l).

Hint avlu infmu suplu infml.

Lemma infmu1 : (inft m u1).
Elim (inft_node_inv m n u1 u2 eqn); Auto.
Save.

Lemma suplu2 : (supt l u2).
Elim (supt_node_inv l n u1 u2 eqn); Auto.
Save.

Lemma infnl : (inf n l).
Elim (supt_node_inv l n u1 u2 eqn); Auto.
Save.

Lemma infmn : (inf m n).
Elim (inft_node_inv m n u1 u2 eqn); Auto.
Save.

Hint infmu1 suplu2 infnl infmn.

Lemma supnt : (supt n t).
Apply supt_trans with m; Auto.
Save.

Lemma infnv : (inft n v).
Apply inft_trans with l; Auto.
Save.

Hint supnt infnv.

Hypothesis Htu : (S (haut t))=(haut u).
Hypothesis Htv : (haut t)=(haut v).

Hint Htu Htv.

Local eqm := Case eqn of (* ga *) mi (* mi *) mi (* dr *) ga end.
Local eql := Case eqn of (* ga *) dr (* mi *) mi (* dr *) mi end.

Definition rot_gd := (node n (node m t u1 eqm) (node l u2 v eql) mi).

Lemma equiv_rotgd : (eql':equil)(equiv_abe (node l (node m t u dr) v eql') rot_gd).
Intros eql'; Unfold equiv_abe rot_gd; Split.
Intros x H; Elim (In_node_inv x l (node m t u dr) v eql'); Auto.
Intros H0; Elim (In_node_inv x m t u dr); Auto.
Intros H1; Elim (In_node_inv x n u1 u2 eqn); Auto.
Unfold u; Intros x H; 
       Elim (In_node_inv x n (node m t u1 eqm) (node l u2 v eql) mi);Trivial.
Intros H0; Elim (In_node_inv x  m t u1 eqm); Auto.
Intros H0; Elim (In_node_inv x l u2 v eql); Auto.
Auto.
Save.

Lemma equiv_rotdg : (eql':equil)(equiv_abe (node m t (node l u v ga) eql') rot_gd).
Intros eql'; Unfold equiv_abe rot_gd; Split.
Intros x H; Elim (In_node_inv x m t (node l u v ga) eql'); Auto.
Intros H0; Elim (In_node_inv x l u v ga); Auto.
Intros H1; Elim (In_node_inv x n u1 u2 eqn); Auto.
Unfold u; Intros x H; 
       Elim (In_node_inv x n (node m t u1 eqm) (node l u2 v eql) mi);Trivial.
Intros H0; Elim (In_node_inv x  m t u1 eqm); Auto.
Intros H0; Elim (In_node_inv x l u2 v eql); Auto.
Auto.
Save.

Lemma avl_rotgd : (avl rot_gd).
Unfold rot_gd.
Elim (avl_inv n u1 u2 eqn); Trivial.
Intros avlu1 avlu2 supnu1 infnu2 balu1u2.
Unfold eqm eql; Elim balu1u2.
Intro Hu1u2; Cut (haut t)=(haut u1).
Intro Htu1; Cut (S (haut u2))=(haut v).
Intro Hu2v; Apply avl_node; Auto.
Apply bal_mi; Simpl.
Elim Htu1; Elim max_n_n; Elim Hu2v; Elim max_n_Sn; Elim Hu1u2; Auto.
Elim Htv; Elim Hu1u2; Auto.
Apply eq_add_S; Replace (S (haut u1)) with (haut u); Auto.
Simpl; Rewrite -> Hu1u2; Auto.
Intro Hu1u2; Cut (haut t)=(haut u1).
Intro Htu1; Cut (haut u2)=(haut v).
Intro Hu2v; Apply avl_node; Auto.
Apply bal_mi; Simpl.
Elim Htu1; Elim max_n_n; Elim Hu2v; Elim max_n_n; Elim Hu1u2; Auto.
Elim Htv; Elim Hu1u2; Auto.
Apply eq_add_S; Replace (S (haut u1)) with (haut u); Auto. 
Simpl; Elim Hu1u2; Auto.
Intro Hu1u2; Cut (haut t)=(S (haut u1)).
Intro Htu1; Cut (haut u2)=(haut v).
Intro Hu2v; Apply avl_node; Auto.
Apply bal_mi; Simpl.
Rewrite -> Htu1.
Elim max_Sn_n; Elim Hu2v; Elim max_n_n; Auto.
Elim Htv; Rewrite -> Htu1; Auto.
Apply eq_add_S; Rewrite -> Htu; Simpl.
Elim Hu1u2; Auto.
Save.

Lemma haut_rotgd : (S (S (haut v)))=(haut rot_gd).
Unfold rot_gd.
Elim haut_node.
Elim haut_node.
Elim haut_node.
Elim Htv.
Replace (haut t) with (max (haut u1) (haut u2)).
Elim (max_sym (haut u2)).
Elim (max_case (haut u1) (haut u2)); Intro H.
Elim H.
Elim H.
Elim max_n_n; Auto.
Elim H.
Elim max_n_n.
Elim (max_sym (haut u2)); Elim H; Auto.
Apply eq_add_S; Auto.
Save.

Opaque rot_gd.

End double_rotations.

End rotations.
Hint equiv_rotd equiv_rotg equiv_rotgd equiv_rotdg haut_rotd haut_rotg haut_rotgd.

Theorem insert : (x:a)(t:abe)(avl t)->(avl_spec x t).
Realizer 
[x:a][t:abe][{Hyp:(avl t)}]
  (avl_rec t avl_spec 
      (h_plusc x nil (node x nil nil mi))
      [l:a][g,d:abe][des:equil][avlsg,avlsd:avl_spec]
        Case (inf_dec x l) of
            Case avlsg of
                [g'](h_eqc x (node l g d des) (node l g' d des))
                (bal_rec g d abe->avl_spec
                    [g':abe][{H:(avl_ins g')}]
                       (avl_ins_rec avl_spec
                           [m:a][g'g,g'd:abe]
		       	     (h_eqc x (node l g d ga) (rot_d l m g'g d g'd))
                           [l0:a](False_rec avl_spec)
                           [m:a][g'g,g'd:abe]
                             Case g'd of
                                 (False_rec avl_spec)
                                 [n,g'd1,g'd2,eqn]
                                   (h_eqc x (node l g d ga)
                                            (rot_gd l m g'g d n g'd1 g'd2 eqn))
			     end
                        g')
                    [g':abe](h_plusc x (node l g d mi) (node l g' d ga))
                    [g':abe](h_eqc x (node l g d dr) (node l g' d mi))
                 des)
	    end
            Case avlsd of
                 [d'](h_eqc x (node l g d des) (node l g d' des))
                 (bal_rec g d abe->avl_spec
                     [d':abe](h_eqc x (node l g d ga) (node l g d' mi))
                     [d':abe](h_plusc x (node l g d mi) (node l g d' dr))
                     [d':abe][{H:(avl_ins d')}]
                        (avl_ins_rec avl_spec
                            [m:a][d'g,d'd:abe]
                              Case d'g of
                                  (False_rec avl_spec)
                                  [n,d'g1,d'g2,eqn]
                                    (h_eqc x (node l g d dr)
                                             (rot_gd m l g d'd n d'g1 d'g2 eqn))
                              end
                            [m:a](False_rec avl_spec)
                            [m:a][d'g,d'd:abe]
                              (h_eqc x (node l g d dr) (rot_g m l g d'd d'g))
                         d')
                  des)
	     end
        end).

Program_all.
(* (equiv x nil (node x nil nil mi)) *)
Apply equiv_intro ; Intros ; Auto.
Elim  (In_node_inv x0 x nil nil mi) ; Auto.
(* (avl (node l h d des)) *)
Apply avl_node ; Auto.
Apply bal_haut with g d ; Trivial.
Apply equiv_sup_g with g x ; Auto.
(* (avl (rot_d l m g'g d g'd)) *)
Apply avl_rotd ; Auto.
Apply equiv_sup_g with g x; Auto.
Apply eq_add_S ; Elim H8 ; Apply eq_add_S ; Elim H4 . 
Elim e0 ; Elim haut_node.
Rewrite -> H8; Auto.
(* (equiv x (node l g d ga) (rot_d l m g'g d g'd))  *)
Apply equiv_equiv_abe with (node l (node m g'g g'd ga) d ga) ; Auto.
(* (haut (rot_d l m g'g d g'd))=(haut (node l g d ga)) *)
Elim haut_node.
Rewrite -> H4.
Elim max_Sn_n.
Elim haut_rotd ; Auto.
Elim H4 ; Elim e0.
Elim haut_node.
Rewrite -> H8.
Elim max_Sn_n ; Auto.
Apply eq_add_S ; Elim H8 ; Apply eq_add_S ; Elim H4. 
Elim e0 ; Elim haut_node.
Rewrite -> H8; Auto.
(* False *)
Absurd O=(haut g); Auto.
Rewrite -> H4 ; Auto.
(* False *)
Absurd (S (haut g'g))=O ; Auto.
(* (avl (rot_gd l m g'g d n g'd1 g'd2 eqn)) *)
Apply avl_rotgd; Auto.
Elim (supt_node_inv l m g'g (node n g'd1 g'd2 eqn) dr); Auto.
Apply equiv_sup_g with g x ; Auto.
Apply eq_add_S ; Elim H8 ; Apply eq_add_S ; Elim H4.
Elim e0; Elim haut_node.
Elim H8; Auto.
(* (equiv x (node l g d ga) (rot_gd l m g'g d n g'd1 g'd2 eqn)) *)
Apply equiv_equiv_abe with (node l (node m g'g (node n g'd1 g'd2 eqn) dr) d ga) ; Auto.
(* (haut (rot_gd l m g'g d n g'd1 g'd2 eqn))=(haut (node l g d ga)) *)
Elim haut_rotgd ; Auto.
Elim haut_node.
Rewrite -> H4 ; Auto.
Apply eq_add_S ; Elim H8 ; Apply eq_add_S ; Elim H4.
Elim e0 ; Elim haut_node.
Elim H8 ; Auto.
(* (avl_ins (node l g' d ga)) *)
Apply ins_ga ; Auto.
Elim H4 ; Auto.
Apply equiv_sup_g with g x ; Auto.
(* (haut (node l g' d ga))=(S (haut (node l g d mi))) *)
Elim haut_node; Elim haut_node; Elim H4; Elim max_n_n.
Rewrite -> e0; Auto.
(* (avl (node l g' d mi)) *)
Apply avl_node ; Auto.
Apply bal_mi ; Auto.
Elim H4; Auto.
Apply equiv_sup_g with g x ; Auto.
(* (haut (node l g' d mi))=(haut (node l g d dr)) *)
Elim haut_node; Elim haut_node; Elim H4; Elim max_n_Sn.
Elim e0 ; Auto.
(* (avl (node l g d' des)) *)
Apply avl_node ; Auto.
Apply bal_haut with g d ; Trivial.
Apply equiv_inf_g with d x ; Auto.
(* (haut (node l g d' des))=(haut (node l g d des)) *)
Simpl; Elim e0; Auto.
(* (avl (node l g d' mi)) *)
Apply avl_node ; Auto.
Apply bal_mi ; Auto.
Rewrite -> H4; Auto.
Apply equiv_inf_g with d x ; Auto.
(* (haut (node l g d' mi))=(haut (node l g d ga)) *)
Simpl; Rewrite -> e0.
Rewrite -> H4.
Elim max_Sn_n; Auto.
(* (avl_ins (node l g d' dr)) *)
Apply ins_dr ; Auto.
Apply trans_equal with (S (haut d)); Auto.
Apply equiv_inf_g with d x ; Auto.
(* (haut (node l g d' dr))=(S (haut (node l g d mi))) *)
Elim haut_node; Elim haut_node; Rewrite -> H4.
Elim max_n_n; Rewrite e0; Auto.
(* False *)
Absurd O=(S (haut d'd)); Auto.
(* (avl (rot_gd m l g d'd n d'g1 d'g2 eqn)) *)
Apply avl_rotgd ; Auto.
Elim (inft_node_inv l m (node n d'g1 d'g2 eqn) d'd ga); Auto.
Apply equiv_inf_g with d x ; Auto.
Simpl.
Rewrite -> H4.
Apply eq_add_S; Elim e0.
Elim haut_node.
Replace (S (max (haut (node n d'g1 d'g2 eqn)) (haut d'd))) with (max (S (haut (node n d'g1 d'g2 eqn))) (S (haut d'd))).
Elim H8.
Cut ((haut (node n d'g1 d'g2 eqn))=(S (max (haut d'g1) (haut d'g2)))); Auto.
Auto.
Apply eq_add_S; Rewrite -> H4.
Elim H8.
Apply eq_add_S; Elim e0.
Elim haut_node.
Replace (S (max (haut (node n d'g1 d'g2 eqn)) (haut d'd))) with (max (S (haut (node n d'g1 d'g2 eqn))) (S (haut d'd))).
Elim H8; Auto.
Auto.
(* (equiv x (node l g d dr) (rot_gd m l g d'd n d'g1 d'g2 eqn)) *)
Apply equiv_equiv_abe with (node l g (node m (node n d'g1 d'g2 eqn) d'd ga) dr) ; Auto.
(* (haut (rot_gd m l g d'd n d'g1 d'g2 eqn))=(haut (node l g d dr)) *)
Elim haut_node; Elim haut_rotgd; Auto.
Elim H4; Elim max_n_Sn.
Rewrite -> H4.
Elim e0.
(* Rewrite -> H8; Auto. *)
Elim haut_node.
Replace (S (max (haut (node n d'g1 d'g2 eqn)) (haut d'd))) with (max (S (haut (node n d'g1 d'g2 eqn))) (S (haut d'd))); Auto.
Elim H8; Auto.
Rewrite -> H4.
Apply eq_add_S; Elim e0.
Elim haut_node.
Replace (S (max (haut (node n d'g1 d'g2 eqn)) (haut d'd))) with (max (S (haut (node n d'g1 d'g2 eqn))) (S (haut d'd))); Auto.
Elim H8; Auto.
Apply eq_add_S; Rewrite -> H4.
Apply eq_add_S; Elim e0.
Elim H8.
Elim haut_node.
Replace (S (max (haut (node n d'g1 d'g2 eqn)) (haut d'd))) with (max (S (haut (node n d'g1 d'g2 eqn))) (S (haut d'd))); Auto.
Elim H8; Auto.
(* False *)
Absurd O=(haut d); Auto.
Elim H4; Auto.
(* (avl (rot_g m l g d'd d'g)) *)
Apply avl_rotg ; Auto.
Apply equiv_inf_g with d x ; Auto.
Apply eq_add_S; Rewrite -> H4.
Apply eq_add_S; Elim e0; Simpl; Elim H8; Auto.
(* (equiv x (node l g d dr) (rot_g m l g d'd d'g)) *)
Apply equiv_equiv_abe with (node l g (node m d'g d'd dr) dr) ; Auto.
(* (haut (rot_g m l g d'd d'g))=(haut (node l g d dr)) *)
Elim haut_rotg.
Elim haut_node.
Elim H4; Elim max_n_Sn.
Rewrite -> H4.
Elim e0; Simpl.
Elim H8; Auto.
Apply eq_add_S; Rewrite -> H4.
Apply eq_add_S; Elim e0; Simpl; Elim H8; Auto.
Auto.
Save.

End trees.

(* $Id: Avl_prog.v,v 1.4 1998/04/30 16:45:48 mohring Exp $ *)
