Section PBTree.
Variable A : Type.
Variable empty : A.
Variable eqA_dec : forall a b : A, {a = b} + {a <> b}.
(* Partial Binary Tree (no more than 2 sons *)
Inductive pbtree : Type :=
| pbleaf : A -> pbtree
| pbleft : pbtree -> pbtree
| pbright : pbtree -> pbtree
| pbnode : pbtree -> pbtree -> pbtree.
Proof using.
intros p; case p; simpl in |- *;
try (intros; right; red in |- *; intros; discriminate).
intros a; left; exists a; simpl in |- *; auto.
Qed.
(* Predicate for belonging *)
Inductive inpb : pbtree -> pbtree -> Prop :=
| inpb_leaf : forall t : pbtree, inpb t t
| inpb_left : forall t t1 t2 : pbtree, inpb t t1 -> inpb t (pbleft t1)
| inpb_right : forall t t1 t2 : pbtree, inpb t t1 -> inpb t (pbright t1)
| inpb_node_l : forall t t1 t2 : pbtree, inpb t t1 -> inpb t (pbnode t1 t2)
| inpb_node_r : forall t t1 t2 : pbtree, inpb t t2 -> inpb t (pbnode t1 t2).
Hint Constructors inpb : core.
(* Equality on partial trees is decidable *)
Definition pbtree_dec : forall a b : pbtree, {a = b} + {a <> b}.
intros a; elim a; simpl in |- *; auto.
intros a0 b; case b; try (intros; right; red in |- *; intros; discriminate).
intros a1; case (eqA_dec a0 a1); intros H1.
left; rewrite H1; auto.
right; red in |- *; Contradict H1; inversion H1; auto.
intros p H b; case b; try (intros; right; red in |- *; intros; discriminate).
intros p1; case (H p1).
intros e; rewrite e; auto.
intros H1; right; Contradict H1; inversion H1; auto.
intros p H b; case b; try (intros; right; red in |- *; intros; discriminate).
intros p1; case (H p1).
intros e; rewrite e; auto.
intros H1; right; Contradict H1; inversion H1; auto.
intros p H p0 H0 b; case b;
try (intros; right; red in |- *; intros; discriminate).
intros p1 p2; case (H p1); intros H1.
case (H0 p2); intros H2.
left; rewrite H1; rewrite H2; auto.
right; Contradict H2; injection H2; auto.
right; Contradict H1; injection H1; auto.
Defined.
(* Belonging is decidable *)
Definition inpb_dec : forall a b, {inpb a b} + {~ inpb a b}.
intros a b; elim b.
intros a0; case a;
try (intros; right; red in |- *; intros HH; inversion HH; auto; fail).
intros a1; case (eqA_dec a1 a0); intros HH.
left; rewrite HH; auto.
right; Contradict HH; inversion HH; auto.
intros p Hp; case Hp; auto; intros HH.
case (pbtree_dec a (pbleft p)); intros HH1.
left; rewrite HH1; auto.
right; red in |- *; intros HH2; generalize HH HH1; inversion HH2; auto.
intros p Hp; case Hp; auto; intros HH.
case (pbtree_dec a (pbright p)); intros HH1.
left; rewrite HH1; auto.
right; red in |- *; intros HH2; generalize HH HH1; inversion HH2; auto.
intros p H p0 H0.
case H; auto; intros H1.
case H0; auto; intros H2.
case (pbtree_dec a (pbnode p p0)); intros HH1.
left; rewrite HH1; auto.
right; red in |- *; intros HH2; generalize H1 H2 HH1; inversion HH2; auto.
Defined.
Proof using.
intros t1 t2 t3 H H1; generalize t1 H; elim H1; clear H H1 t1 t2 t3; auto.
Qed.
Proof using.
intros t; elim t; simpl in |- *; auto.
intros a; exists a; auto.
intros b (a, H); exists a; auto.
intros b (a, H); exists a; auto.
intros b (a, H) b0 H0; exists a; auto.
Qed.
(* Predicate for Partial Trees with Different Leaves *)
Definition distinct_pbleaves (t : pbtree) : Prop :=
forall t0 t1 t2 : pbtree,
inpb (pbnode t1 t2) t -> inpb t0 t1 -> inpb t0 t2 -> False.
Proof using.
intros a; red in |- *.
intros a0 t1 t2 H; inversion H.
Qed.
Hint Resolve distinct_pbleaves_Leaf : core.
Proof using.
intros t1 t2 H; red in |- *.
intros a t0 t3 H0 H1 H2.
apply (H a t0 t3); auto.
Qed.

(* Direct subtrees of a tree with distinct leaves have distinct leaves *)
Theorem distinct_pbleaves_r :
forall t1 t2 : pbtree,
distinct_pbleaves (pbnode t1 t2) -> distinct_pbleaves t2.