Section Elt.
Variable elt : Type.
Implicit Types m r : t elt.
(** * AVL trees *)
(** [avl s] : [s] is a properly balanced AVL tree, i.e. for any node the heights of the two children differ by at most 2 *)
Inductive avl : t elt -> Prop :=
| RBLeaf : avl (Leaf _)
| RBNode : forall x e l r h,
avl l ->
avl r ->
-(2) <= height l - height r <= 2 ->
h = max (height l) (height r) + 1 ->
avl (Node l x e r h).
(** * Automation and dedicated tactics about [avl]. *)
Hint Constructors avl : core.
Ltac avl_nn_hyp H :=
let nz := fresh "nz" in assert (nz := height_non_negative H).
Ltac avl_nn h :=
let t := type of h in
match type of t with
| Prop => avl_nn_hyp h
| _ => match goal with H : avl h |- _ => avl_nn_hyp H end
end.
(* Repeat the previous tactic. Drawback: need to clear the [avl _] hyps ... Thank you Ltac *)
Ltac avl_nns :=
match goal with
| H:avl _ |- _ => avl_nn_hyp H; clear H; avl_nns
| _ => idtac
end.
(** * Basic results about [avl], [height] *)
Hint Resolve avl_node : core.
(** Results about [height] *)
(** * Empty map *)
(** * Helper functions *)
Ltac omega_bal := match goal with
| H:avl ?l, H':avl ?r |- context [ bal ?l ?x ?e ?r ] =>
generalize (bal_height_1 x e H H') (bal_height_2 x e H H');
omega_max
end.
(** * Insertion *)

Lemma add_avl_1 :  forall m x e, avl m ->
avl (add x e m) /\ 0 <= height (add x e m) - height m <= 1.