Section HeightPred.
Variable A : Type.
Variable f : A -> nat.
Variable eqA_dec : forall a b : A, {a = b} + {a <> b}.
(* A predicate that associates an initial height, a list of height, a cover and a tree *)
Inductive height_pred : nat -> list nat -> list (btree A) -> btree A -> Prop :=
| height_pred_nil :
forall (n : nat) (t : btree A), height_pred n (n :: nil) (t :: nil) t
| height_pred_node :
forall (n : nat) (ln1 ln2 : list nat) (t1 t2 : btree A)
(l1 l2 : list (btree A)),
height_pred (S n) ln1 l1 t1 ->
height_pred (S n) ln2 l2 t2 ->
height_pred n (ln1 ++ ln2) (l1 ++ l2) (node t1 t2).
Hint Resolve height_pred_nil height_pred_node : core.
Proof using.
intros n ln t l H; elim H; simpl in |- *; auto.
Qed.
Proof using.
intros n ln t l H; elim H; simpl in |- *; auto.
intros; discriminate.
intros n0 ln1 ln2 t1 t2 l1 l2 H0; case ln1; simpl in |- *; auto.
intros; discriminate.
Qed.
Proof using.
intros n ln t l H; elim H; simpl in |- *; auto.
intros; discriminate.
intros n0 ln1 ln2 t1 t2 l1 l2 H0; case l1; simpl in |- *; auto.
intros; discriminate.
Qed.
Proof using.
intros n ln t l H; elim H; simpl in |- *; auto.
intros; repeat rewrite length_app; auto with arith.
Qed.
Proof using.
intros n ln t l H; elim H; simpl in |- *; auto.
intros n0 ln1 ln2 t1 t2 l1 l2 H0 H1 H2 H3.
rewrite prod2list_app; auto with arith.
rewrite <- H3; rewrite <- H1; ring.
apply height_pred_length with (1 := H0); auto.
Qed.
Proof using.
intros n t l H; generalize n; elim H; clear n t l H.
intros t l n; exists (n :: nil); auto.
intros t1 t2 l1 l2 l3 H H0 H1 H2 n.
case (H0 (S n)); intros ln1 HH1.
case (H2 (S n)); intros ln2 HH2.
exists (ln1 ++ ln2); auto.
Qed.
Proof using.
intros n n1 ln t l H; generalize n1; elim H; clear H n ln t l n1;
auto with arith.
intros n t n1 [H2| H2]; [ rewrite H2 | case H2 ]; auto.
intros n ln1 ln2 t1 t2 l1 l2 H H0 H1 H2 n1 H3; apply le_trans with (S n);
auto with arith.
case in_app_or with (1 := H3); auto.
Qed.
Proof using.
intros n n1 ln t l H; generalize n1; elim H; clear H n ln t l n1; auto.
intros n ln1 ln2 t1 t2 l1 l2 H H0 H1 H2 n1 H3; left;
apply lt_le_trans with (S n); auto.
case in_app_or with (1 := H3).
intros H4; apply height_pred_larger with (1 := H); auto.
intros H4; apply height_pred_larger with (1 := H1); auto.
Qed.
Proof using.
intros n ln t l H; elim H; clear H n ln t l.
intros n t; exists n; auto with datatypes.
intros n ln1 ln2 t1 t2 l1 l2 H (n1, (HH1, HH2)) H1 H2.
exists n1; auto with datatypes arith.
Qed.

Lemma height_pred_disj_larger_aux :
forall (n : nat) (ln : list nat) (t : btree A) (l : list (btree A)),
height_pred n ln l t ->
forall ln1 ln2 a,
ln = ln1 ++ a :: ln2 ->
(forall n1 : nat, In n1 ln1 -> n1 < a) ->
(forall n1 : nat, In n1 ln2 -> n1 <= a) ->
(exists ln3 : _, ln2 = a :: ln3) \/ ln = n :: nil /\ l = t :: nil.