//
//
// Proving [size(t) < 2^height(t)] for any given binary tree [t].
//
// Hongwei Xi (hwxi AT cs DOT bu DOT edu)
// Septemeber 30, 2008
//

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

datasort bt = B of (bt, bt) | E of ()

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

dataprop btsz (bt, int) =
  | {t1,t2:bt} {s1,s2:nat}
    btsz_B (B (t1, t2), 1 + s1 + s2) of (btsz (t1, s1), btsz (t2, s2))
  | btsz_E (E (), 0)

dataprop btht (bt, int) =
  | {t1,t2:bt} {h1,h2:nat}
    btht_B (B (t1, t2), 1 + max (h1, h2)) of (btht (t1, h1), btht (t2, h2))
  | btht_E (E (), 0)

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

dataprop POW2 (int, int) =
  | POW2bas (0, 1) | {p:nat} {n:nat} POW2ind (p+1, n+n) of POW2 (p, n)

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

prfun pow2_total_lemma {p:nat} .<p>. (): [n:nat] POW2 (p, n) =
  sif p > 0 then POW2ind (pow2_total_lemma {p-1} ()) else POW2bas ()
// end of [pow2_total_lemma]

prfun pow2_monotone_lemma
  {p1,p2:nat | p1 <= p2} {n1,n2:nat} .<p2>.
  (pf1: POW2 (p1, n1), pf2: POW2 (p2, n2)): [n1 <= n2] void =
  case+ pf2 of
  | POW2ind (pf2) => begin case+ pf1 of
    | POW2ind (pf1) => pow2_monotone_lemma (pf1, pf2)
    | POW2bas () => pow2_monotone_lemma (pf1, pf2)
    end // end of [POW2ind]
  | POW2bas () => begin
      let prval POW2bas () = pf1 in () end
    end // end of [POW2bas]
// end of [pow2_monotone_lemma]

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

prfun bintree_size_height_lemma {t:bt} {s,h,n:nat} .<t>.
  (pf1: btsz (t, s), pf2: btht (t, h), pf3: POW2 (h, n)): [s < n] void =
  case+ pf1 of
  | btsz_E () => let
      prval btht_E () = pf2; prval POW2bas () = pf3 in ()
    end // end of [btsz_E]
  | btsz_B {t1,t2} {s1,s2} (pf11, pf12) => let
      prval btht_B {t1,t2} {h1,h2} (pf21, pf22) = pf2
      prval POW2ind {h12_max} {n2} (pf30) = pf3 // n2+n2 = n
      prval pf30_1 = pow2_total_lemma {h1} ()
      prval () = pow2_monotone_lemma {h1,h12_max} (pf30_1, pf30) // 2^h1 <= n2
      prval () = bintree_size_height_lemma (pf11, pf21, pf30_1)  // s1 + 1 <= 2^h1
      prval pf30_2 = pow2_total_lemma {h2} ()
      prval () = pow2_monotone_lemma {h2,h12_max} (pf30_2, pf30) // 2^h2 <= n2
      prval () = bintree_size_height_lemma (pf12, pf22, pf30_2)  // s2 + 1 <= 2^h2
    in
      // empty
    end // end of [btsz_B]
// end of [bintree_size_height_lemma]

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

(* end of [bintree-2008-09-30.dats] *)