```//
// Course: BU CAS CS 520, Fall 2009
// Instructor: Hongwei Xi (hwxi AT cs DOT bu DOT edu)
//

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

datasort bt = btcons of (bt, bt) | btnil of ()

dataprop SZ (bt, int) =
| SZnil (btnil, 0)
| {t1,t2:bt} {s1,s2:nat}
SZcons (btcons (t1, t2), 1+s1+s2) of (SZ (t1, s1), SZ (t2, s2))
// end of [SZ]

dataprop HT (bt, int) =
| HTnil (btnil, 0)
| {t1,t2:bt} {h1,h2:nat}
HTcons (btcons (t1, t2), 1+max(h1,h2)) of (HT (t1, h1), HT (t2, h2))
// end of [HT]

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

dataprop POW2 (int, int) =
| POW2bas (0, 1)
| {n:nat} {p:nat} POW2ind (n+1, 2*p) of POW2 (n, p)
// end of [POW2]

// POW2 is total (w.r.t. its first argument)
prfun pow2_istot {n:nat} .<n>. (): [p:nat] POW2 (n, p) =
sif n > 0 then POW2ind (pow2_istot {n-1} ()) else POW2bas ()
// end of [pow2_istot]

// POW2 is a functional relation
prfun pow2_isfun {n:nat} {p1,p2:int} .<n>.
(pf1: POW2 (n, p1), pf2: POW2 (n, p2)): [p1==p2] void =
case+ (pf1, pf2) of
| (POW2ind pf1, POW2ind pf2) => pow2_isfun (pf1, pf2)
| (POW2bas (), POW2bas ()) => ()
// end of [pow2_isfun]

// pow2 is an increasing function
prfun pow2_isinc {n1,n2:nat | n1 <= n2}
{p1,p2:int} .<n2>. (pf1: POW2 (n1, p1), pf2: POW2 (n2, p2)): [p1 <= p2] void =
sif n1 < n2 then let
prval POW2ind pf20 = pf2
prval () = pow2_isinc (pf1, pf20)
in
// nothing
end else let
prval () = pow2_isfun (pf1, pf2)
in
// nothing
end // end of [sif]
// end of [pow2_isinc]

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

prfun lemma_SZ_HT {t:bt} {s,h,p:int} .<t>.
(pf1: SZ (t, s), pf2: HT (t, h), pf3: POW2 (h, p)): [s < p] void =
case+ pf1 of
| SZnil () => let
prval HTnil () = pf2
prval POW2bas () = pf3
in
// nothing
end // end of [SZnil]
| SZcons (pf11, pf12) => let
// t = btcons (t1, t2); pf11: SZ (t1, s1), pf12: SZ (t2, s2)
prval HTcons {t1,t2} {h1,h2} (pf21, pf22) = pf2 // pf21: HT (t1, h1), HT (t2, h2)
prval POW2ind (pf30) = pf3
prval [p1:int] pf31 = pow2_istot {h1} () // pf32: POW2 (h1, p1)
prval () = lemma_SZ_HT (pf11, pf21, pf31)
prval [p2:int] pf32 = pow2_istot {h2} () // pf32: POW2 (h2, p2)
prval () = lemma_SZ_HT (pf12, pf22, pf32)
prval () = pow2_isinc (pf31, pf30)
prval () = pow2_isinc (pf32, pf30)
in
// nothing
end // end of [SZcons]
// end of [lemma_SZ_HT]

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

(* end of [tree.dats] *)
```