(*
 * Copyright (c) 2009-2016, Andrew Appel, Robert Dockins,
    Aquinas Hobor, and Le Xuan Bach
 *
 *)

Require Import VST.msl.base.
Require Import VST.msl.eq_dec.
Require Import VST.msl.sepalg.
Require Import VST.msl.boolean_alg.

Require Import Recdef.
Require Import NPeano.
Require Import Omega.
Require Import Coq.Arith.Max.

(** This module implements a share model
    via binary trees with boolean-labeled leaves.

    The development is complicated somewhat by the
    fact the ordering used defines multiple isomorphic
    representations of a share.  We must therefore chose
    one to be a canonical representation of the equivalence
    class in order to get strong antisymmetry
    (i.e., antisymmetry up to identity).

    The canonical tree is the one that contains no nonleaf
    full or empty subtrees. A full subtree has all
    leaves labeled with true, whereas an empty subtree
    has all leaves labeled with false.  Canonical trees
    always exists and are unique.  Furthermore, they
    can be straightforwardly calculated.

    Tree union and intersection may generate noncanonical
    trees, so the result must be canonicalized.  However,
    split always generates canonical trees when given a
    canonical tree, as does complement.
 **)

Module Share <: SHARE_MODEL.
  (* Definition of the trees and operations on them *)

  Inductive ShareTree : Set :=
  | Leaf : bool -> ShareTree
  | Node : ShareTree -> ShareTree -> ShareTree
  .

  Fixpoint nonFullTree (x:ShareTree) : Prop :=
   match x with
   | Leaf b   => b = false
   | Node l r => nonFullTree l \/ nonFullTree r
   end.

  Fixpoint nonEmptyTree (x:ShareTree) : Prop :=
   match x with
   | Leaf b   => b = true
   | Node l r => nonEmptyTree l \/ nonEmptyTree r
   end.

  Fixpoint canonicalTree (x:ShareTree) : Prop :=
   match x with
   | Leaf _   => True
   | Node l r => nonFullTree x /\ nonEmptyTree x /\
                 canonicalTree l /\ canonicalTree r
   end.

  Fixpoint union_tree (x y:ShareTree) { struct x } : ShareTree :=
    match x with
    | Leaf true  => Leaf true
    | Leaf false => y
    | Node l1 r1 =>
       match y with
       | Leaf true  => Leaf true
       | Leaf false => x
       | Node l2 r2 =>
            Node (union_tree l1 l2) (union_tree r1 r2)
       end
    end.

  Fixpoint intersect_tree (x y:ShareTree) { struct x } : ShareTree :=
    match x with
    | Leaf false => Leaf false
    | Leaf true  => y
    | Node l1 r1 =>
       match y with
       | Leaf false => Leaf false
       | Leaf true  => x
       | Node l2 r2 =>
            Node (intersect_tree l1 l2) (intersect_tree r1 r2)
       end
    end.

  Fixpoint comp_tree (x:ShareTree) : ShareTree :=
    match x with
    | Leaf b => Leaf (negb b)
    | Node l r => Node (comp_tree l) (comp_tree r)
    end.

  Fixpoint mkCanon (x:ShareTree) : ShareTree :=
    match x with
    | Leaf b => Leaf b
    | Node l r =>
       let l' := mkCanon l in
       let r' := mkCanon r in
       match l', r' with
       | Leaf b1, Leaf b2 =>
          if bool_dec b1 b2
             then Leaf b1
             else Node l' r'
       | _, _ => Node l' r'
       end
    end.

  Fixpoint relativ_tree (z a:ShareTree) {struct z} : ShareTree :=
    match z with
    | Leaf true  => a
    | Leaf false => Leaf false
    | Node l r   => Node (relativ_tree l a) (relativ_tree r a)
    end.

  (* The ordering relation on trees, and its induced isomorphism. *)

  Inductive shareTreeOrd : ShareTree -> ShareTree -> Prop :=
  | Leaf_Ord : forall b1 b2, implb b1 b2 = true ->
       shareTreeOrd (Leaf b1) (Leaf b2)
  | LeafNode_Ord : forall b l r,
       shareTreeOrd (Node (Leaf b) (Leaf b)) (Node l r) ->
       shareTreeOrd (Leaf b) (Node l r)
  | NodeLeaf_Ord : forall b l r,
       shareTreeOrd (Node l r) (Node (Leaf b) (Leaf b)) ->
       shareTreeOrd (Node l r) (Leaf b)
  | Node_Ord : forall l1 l2 r1 r2,
       shareTreeOrd l1 l2 ->
       shareTreeOrd r1 r2 ->
       shareTreeOrd (Node l1 r1) (Node l2 r2)
  .
  Hint Constructors shareTreeOrd.

  Definition shareTreeEq (x y:ShareTree) :=
      shareTreeOrd x y /\ shareTreeOrd y x.
  Hint Unfold shareTreeEq.

  Ltac destruct_bool :=
    repeat (match goal with [ b:bool |- _ ] => destruct b end).

  Ltac invert_ord :=
    repeat (
    match goal with
    | [ H:shareTreeEq _ _ |- _ ] => destruct H
    | [ H:shareTreeOrd (Leaf _) (Leaf _) |- _ ] => inversion H; clear H
    | [ H:shareTreeOrd (Leaf _) (Node _ _) |- _ ] => inversion H; clear H
    | [ H:shareTreeOrd (Node _ _) (Leaf _) |- _ ] => inversion H; clear H
    | [ H:shareTreeOrd (Node _ _) (Node _ _) |- _ ] => inversion H; clear H
    end; subst).

  (* Utility lemmas about full and empty trees, and
     the top and bottom elements. *)

  Lemma nonEmpty_dec : forall x, {nonEmptyTree x}+{~nonEmptyTree x}.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Defined.

  Lemma nonFull_dec : forall x, {nonFullTree x}+{~nonFullTree x}.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Defined.

  Lemma geTrueFull : forall x,
      shareTreeOrd (Leaf true) x -> ~nonFullTree x.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Qed.

  Lemma leFalseEmpty : forall x,
      shareTreeOrd x (Leaf false) -> ~nonEmptyTree x.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Qed.

  Lemma emptyLeFalse : forall x,
    ~nonEmptyTree x  -> shareTreeOrd x (Leaf false).
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Qed.

  Lemma fullGeTrue : forall x,
    ~nonFullTree x -> shareTreeOrd (Leaf true) x.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Qed.

  Lemma falseLeaf_bottom : forall x,
    shareTreeOrd (Leaf false) x.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd (Leaf false) x *)
    induction x; auto.
  Qed.

  Lemma trueLeaf_top : forall x,
    shareTreeOrd x (Leaf true).
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x (Leaf true) *)
    induction x; destruct_bool; auto.
  Qed.

  Hint Resolve geTrueFull leFalseEmpty emptyLeFalse fullGeTrue
     falseLeaf_bottom trueLeaf_top.

  Lemma eqFalseLeaf_empty : forall x,
    shareTreeEq (Leaf false) x -> ~nonEmptyTree x.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Qed.

  Lemma eqTrueLeaf_full : forall x,
    shareTreeEq (Leaf true) x ->
    ~nonFullTree x.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Qed.

  Lemma emptyTree_canonical_falseLeaf : forall x,
    ~nonEmptyTree x ->
    canonicalTree x ->
    x = Leaf false.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Qed.

  Lemma fullTree_canonical_trueLeaf : forall x,
    ~nonFullTree x ->
    canonicalTree x ->
    x = Leaf true.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Qed.

  Hint Resolve eqFalseLeaf_empty eqTrueLeaf_full emptyTree_canonical_falseLeaf
    fullTree_canonical_trueLeaf.

  (* Show that shareTreeOrd is a preorder (reflexive and transitive). *)

  Lemma shareTreeOrd_refl : forall x,
    shareTreeOrd x x.
  Proof.
(* Goal: forall x : ShareTree, shareTreeOrd x x *)
    induction x; simpl; intros; invert_ord; destruct_bool; intuition.
  Qed.

  Lemma shareTreeOrd_trans_leaf : forall x1 b x3,
    shareTreeOrd x1 (Leaf b) ->
    shareTreeOrd (Leaf b) x3 ->
    shareTreeOrd x1 x3.
  Proof.
(* Goal: forall (x1 : ShareTree) (b : bool) (x3 : ShareTree) (_ : shareTreeOrd x1 (Leaf b)) (_ : shareTreeOrd (Leaf b) x3), shareTreeOrd x1 x3 *)
    intro x1; induction x1; simpl; intros; invert_ord; destruct_bool; intuition.
(* Goal: shareTreeOrd (Node x1_1 x1_2) x3 *)
    inv H0; invert_ord; destruct_bool; intuition eauto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    discriminate.
(* Goal: shareTreeOrd (Node x1_1 x1_2) x3 *)
    inv H0; invert_ord; destruct_bool; intuition eauto.
  Qed.

  Lemma shareTreeOrd_trans : forall x1 x2 x3,
    shareTreeOrd x1 x2 -> shareTreeOrd x2 x3 -> shareTreeOrd x1 x3.
  Proof.
(* Goal: forall (x1 x2 x3 : ShareTree) (_ : shareTreeOrd x1 x2) (_ : shareTreeOrd x2 x3), shareTreeOrd x1 x3 *)
    intros x1 x2; revert x1; induction x2; simpl; intros.
(* Goal: shareTreeOrd x1 x3 *)
(* Goal: shareTreeOrd x1 x3 *)
    apply shareTreeOrd_trans_leaf with b; auto.
(* Goal: shareTreeOrd x1 x3 *)
    inv H; inv H0; invert_ord; eauto.
  Qed.

  (* Show that shareTreeEq is an equivalance relation. *)

  Lemma shareTreeEq_refl : forall x,
    shareTreeEq x x.
  Proof. unfold shareTreeEq; intuition; apply shareTreeOrd_refl. Qed.

  Lemma shareTreeEq_sym : forall x y,
    shareTreeEq x y ->
    shareTreeEq y x.
  Proof. unfold shareTreeEq; intuition. Qed.

  Lemma shareTreeEq_trans : forall x y z,
    shareTreeEq x y ->
    shareTreeEq y z ->
    shareTreeEq x z.
  Proof.
    unfold shareTreeEq; intuition;
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with y; auto.
  Qed.

  (* Show that mkCanon generates canonical trees that are
     equivalant to the original. *)

  Lemma mkCanon_correct : forall x,
    canonicalTree (mkCanon x).
  Proof.
(* Goal: forall (x : ShareTree) (_ : nonEmptyTree x), nonEmptyTree (mkCanon x) *)
    induction x; simpl; intros; auto.
(* Goal: canonicalTree match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
    case_eq (mkCanon x1); intros.
(* Goal: canonicalTree match mkCanon x2 with | Leaf b2 => if bool_dec b b2 then Leaf b else Node (Leaf b) (mkCanon x2) | Node s s0 => Node (Leaf b) (mkCanon x2) end *)
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
    case_eq (mkCanon x2); intros.
(* Goal: canonicalTree (if bool_dec b b0 then Leaf b else Node (Leaf b) (Leaf b0)) *)
(* Goal: canonicalTree (Node (Leaf b) (Node s s0)) *)
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
    case_eq (bool_dec b b0); intros; simpl; auto.
(* Goal: and (or (@eq bool b false) (@eq bool b0 false)) (and (or (@eq bool b true) (@eq bool b0 true)) (and True True)) *)
(* Goal: canonicalTree (Node (Leaf b) (Node s s0)) *)
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
    destruct_bool; intuition.
(* Goal: @eq ShareTree (Leaf true) x *)
(* Goal: @eq ShareTree (Node a1_1 a1_2) (Node (relativ_tree a1_1 x) (relativ_tree a1_2 x)) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill (False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (n H0)) (fun H0 : nonEmptyTree a2 => False_ind False (n0 H0)) H)) x) *)
    elim n; auto.
(* Goal: canonicalTree (Node (Leaf b) (Node s s0)) *)
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
    rewrite H0 in IHx2.
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
    simpl in *; intuition.
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
    rewrite H in IHx1.
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
    simpl in *; intuition.
  Qed.

  Lemma mkCanon_eq : forall x,
    shareTreeEq x (mkCanon x).
  Proof.
(* Goal: forall (x : ShareTree) (_ : nonEmptyTree x), nonEmptyTree (mkCanon x) *)
    induction x; simpl; intros; auto.
(* Goal: shareTreeEq (Leaf b) (Leaf b) *)
(* Goal: shareTreeEq (Node x1 x2) match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
    split; apply shareTreeOrd_refl.
    case_eq (mkCanon x1); intros; rewrite H in IHx1; destruct IHx1;
    case_eq (mkCanon x2); intros; rewrite H2 in IHx2; destruct IHx2;
      red.
(* Goal: nonEmptyTree (if bool_dec b b0 then Leaf b else Node (Leaf b) (Leaf b0)) *)
(* Goal: nonEmptyTree match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
    destruct (bool_dec b b0); subst; intuition; repeat econstructor; eauto.
(* Goal: and (shareTreeOrd (Node x1 x2) (Node (Node s s0) (Node s1 s2))) (shareTreeOrd (Node (Node s s0) (Node s1 s2)) (Node x1 x2)) *)
    split; repeat econstructor; auto.
(* Goal: and (shareTreeOrd (Node x1 x2) (Node (Node s s0) (Node s1 s2))) (shareTreeOrd (Node (Node s s0) (Node s1 s2)) (Node x1 x2)) *)
    split; repeat econstructor; auto.
(* Goal: and (shareTreeOrd (Node x1 x2) (Node (Node s s0) (Node s1 s2))) (shareTreeOrd (Node (Node s s0) (Node s1 s2)) (Node x1 x2)) *)
    split; repeat econstructor; auto.
  Qed.

  Lemma mkCanon_test : forall x y,
    mkCanon x = mkCanon y ->
    shareTreeEq x y.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: shareTreeEq x y *)
    apply shareTreeEq_trans with (mkCanon x).
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
    apply mkCanon_eq.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
    rewrite H.
(* Goal: shareTreeEq (union_tree (create_tok1 n x0) (create_tok2 n x0)) x0 *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
    apply shareTreeEq_sym.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
    apply mkCanon_eq.
  Qed.

  Lemma mkCanon_nonEmpty : forall x,
    nonEmptyTree x -> nonEmptyTree (mkCanon x).
  Proof.
(* Goal: forall (x : ShareTree) (_ : nonEmptyTree x), nonEmptyTree (mkCanon x) *)
    induction x; simpl; intros; auto.
    destruct H; [ apply IHx1 in H | apply IHx2 in H ];
      clear IHx1 IHx2.
(* Goal: nonEmptyTree match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
    destruct (mkCanon x1); destruct (mkCanon x2); simpl in *; auto.
(* Goal: nonEmptyTree (if bool_dec b b0 then Leaf b else Node (Leaf b) (Leaf b0)) *)
(* Goal: nonEmptyTree match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
    destruct (bool_dec b b0); subst; intuition; repeat econstructor; eauto.
(* Goal: nonEmptyTree match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
    destruct (mkCanon x1); destruct (mkCanon x2); simpl in *; auto.
(* Goal: nonEmptyTree (if bool_dec b b0 then Leaf b else Node (Leaf b) (Leaf b0)) *)
    destruct (bool_dec b b0); subst; intuition; simpl; auto.
  Qed.

  Hint Resolve mkCanon_nonEmpty mkCanon_correct mkCanon_eq.

  (* Show that union and intersection are the LUB and GLB
     for the lattice, respectively. *)

  Lemma union_commute : forall x y,
    union_tree x y = union_tree y x.
  Proof.
(* Goal: forall x y : ShareTree, @eq ShareTree (intersect_tree x y) (intersect_tree y x) *)
    intro x; induction x; destruct y; simpl; intros; auto.
(* Goal: @eq ShareTree (if b then Leaf b0 else Leaf false) (if b0 then Leaf b else Leaf false) *)
(* Goal: @eq ShareTree (Node (intersect_tree x1 y1) (intersect_tree x2 y2)) (Node (intersect_tree y1 x1) (intersect_tree y2 x2)) *)
    destruct b; destruct b0; simpl; auto.
(* Goal: @eq ShareTree (Node (relativ_tree x1 (relativ_tree y z)) (relativ_tree x2 (relativ_tree y z))) (Node (relativ_tree (relativ_tree x1 y) z) (relativ_tree (relativ_tree x2 y) z)) *)
    rewrite IHx1.
(* Goal: @eq ShareTree (Node (relativ_tree (relativ_tree x1 y) z) (relativ_tree x2 (relativ_tree y z))) (Node (relativ_tree (relativ_tree x1 y) z) (relativ_tree (relativ_tree x2 y) z)) *)
    rewrite IHx2.
(* Goal: @eq t c c *)
    auto.
  Qed.

  Lemma intersect_commute : forall x y,
    intersect_tree x y = intersect_tree y x.
  Proof.
(* Goal: forall x y : ShareTree, @eq ShareTree (intersect_tree x y) (intersect_tree y x) *)
    intro x; induction x; destruct y; simpl; intros; auto.
(* Goal: @eq ShareTree (if b then Leaf b0 else Leaf false) (if b0 then Leaf b else Leaf false) *)
(* Goal: @eq ShareTree (Node (intersect_tree x1 y1) (intersect_tree x2 y2)) (Node (intersect_tree y1 x1) (intersect_tree y2 x2)) *)
    destruct b; destruct b0; simpl; auto.
(* Goal: @eq ShareTree (Node (relativ_tree x1 (relativ_tree y z)) (relativ_tree x2 (relativ_tree y z))) (Node (relativ_tree (relativ_tree x1 y) z) (relativ_tree (relativ_tree x2 y) z)) *)
    rewrite IHx1.
(* Goal: @eq ShareTree (Node (relativ_tree (relativ_tree x1 y) z) (relativ_tree x2 (relativ_tree y z))) (Node (relativ_tree (relativ_tree x1 y) z) (relativ_tree (relativ_tree x2 y) z)) *)
    rewrite IHx2.
(* Goal: @eq t c c *)
    auto.
  Qed.

  Lemma union_upper_bound : forall x y,
    shareTreeOrd x (union_tree x y).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intro x; induction x; simpl; intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
    destruct b.
(* Goal: shareTreeOrd y (Leaf true) *)
(* Goal: shareTreeOrd (Leaf false) (Leaf false) *)
(* Goal: shareTreeOrd match y with | Leaf (true as b) => Node x1 x2 | Leaf (false as b) => Leaf false | Node l2 r2 => Node (intersect_tree x1 l2) (intersect_tree x2 r2) end (Node x1 x2) *)
    apply trueLeaf_top.
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
    apply falseLeaf_bottom.
(* Goal: shareTreeOrd match y with | Leaf (true as b) => Node x1 x2 | Leaf (false as b) => Leaf false | Node l2 r2 => Node (intersect_tree x1 l2) (intersect_tree x2 r2) end (Node x1 x2) *)
    destruct y; simpl.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
    destruct b.
(* Goal: shareTreeOrd y (Leaf true) *)
(* Goal: shareTreeOrd (Leaf false) (Leaf false) *)
(* Goal: shareTreeOrd match y with | Leaf (true as b) => Node x1 x2 | Leaf (false as b) => Leaf false | Node l2 r2 => Node (intersect_tree x1 l2) (intersect_tree x2 r2) end (Node x1 x2) *)
    apply trueLeaf_top.
(* Goal: shareTreeOrd x x *)
    apply shareTreeOrd_refl.
(* Goal: @eq t c c *)
    apply Node_Ord; auto.
  Qed.

  Lemma intersection_lower_bound: forall x y,
    shareTreeOrd (intersect_tree x y) x.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intro x; induction x; simpl; intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
    destruct b.
(* Goal: shareTreeOrd y (Leaf true) *)
(* Goal: shareTreeOrd (Leaf false) (Leaf false) *)
(* Goal: shareTreeOrd match y with | Leaf (true as b) => Node x1 x2 | Leaf (false as b) => Leaf false | Node l2 r2 => Node (intersect_tree x1 l2) (intersect_tree x2 r2) end (Node x1 x2) *)
    apply trueLeaf_top.
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
    apply falseLeaf_bottom.
(* Goal: shareTreeOrd match y with | Leaf (true as b) => Node x1 x2 | Leaf (false as b) => Leaf false | Node l2 r2 => Node (intersect_tree x1 l2) (intersect_tree x2 r2) end (Node x1 x2) *)
    destruct y; simpl.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
    destruct b.
(* Goal: shareTreeOrd x x *)
    apply shareTreeOrd_refl.
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
    apply falseLeaf_bottom.
(* Goal: @eq t c c *)
    apply Node_Ord; auto.
  Qed.

  Lemma union_least_bound : forall x y z,
    shareTreeOrd x z ->
    shareTreeOrd y z ->
    shareTreeOrd (union_tree x y) z.
  Proof.
(* Goal: @eq t c c *)
    induction x; simpl; intros; invert_ord; try destruct_bool; auto.
(* Goal: @eq t c c *)
    destruct y; invert_ord; try destruct_bool; auto.
    destruct z; invert_ord; try destruct_bool;
(* Goal: @eq t c c *)
      repeat econstructor; auto.
  Qed.

  Lemma intersection_greatest_bound : forall x y z,
    shareTreeOrd z x ->
    shareTreeOrd z y ->
    shareTreeOrd z (intersect_tree x y).
  Proof.
(* Goal: @eq t c c *)
    induction x; simpl; intros; invert_ord; destruct_bool; auto.
(* Goal: @eq t c c *)
    destruct y; invert_ord; try destruct_bool; auto.
    destruct z; invert_ord; try destruct_bool;
(* Goal: @eq t c c *)
      repeat econstructor; auto.
  Qed.

  (* Now prove a few other utility lemmas about
     union and intersection. *)

  Lemma union_idem : forall x,
    x = union_tree x x.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction x; simpl; intros.
(* Goal: @eq t c c *)
    destruct b; simpl; auto.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
  Qed.

  Lemma intersect_idem : forall x,
     x = intersect_tree x x.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction x; simpl; intros.
(* Goal: @eq t c c *)
    destruct b; simpl; auto.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
  Qed.

  Lemma union_absorb : forall x y,
     x = union_tree x (intersect_tree x y).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intro x; induction x; simpl; intros.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: @eq t c c *)
    destruct y; auto.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: @eq t c c *)
    repeat rewrite <- union_idem; auto.
(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (Node (intersect_tree (union_tree x1 y1) (union_tree x1 z1)) (intersect_tree (union_tree x2 y2) (union_tree x2 z2))) *)
    rewrite <- IHx1.
(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (Node (union_tree x1 (intersect_tree y1 z1)) (intersect_tree (union_tree x2 y2) (union_tree x2 z2))) *)
    rewrite <- IHx2.
(* Goal: @eq t c c *)
    auto.
  Qed.

  Lemma intersect_absorb : forall x y,
     x = intersect_tree x (union_tree x y).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intro x; induction x; simpl; intros.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: @eq t c c *)
    destruct y; auto.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: @eq t c c *)
    repeat rewrite <- intersect_idem; auto.
(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (Node (intersect_tree (union_tree x1 y1) (union_tree x1 z1)) (intersect_tree (union_tree x2 y2) (union_tree x2 z2))) *)
    rewrite <- IHx1.
(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (Node (union_tree x1 (intersect_tree y1 z1)) (intersect_tree (union_tree x2 y2) (union_tree x2 z2))) *)
    rewrite <- IHx2.
(* Goal: @eq t c c *)
    auto.
  Qed.

  (* Demonstrate that intersection distributes over
     union and vice-versa. *)

  Lemma intersect_distrib : forall x y z,
    intersect_tree x (union_tree y z) =
    union_tree (intersect_tree x y) (intersect_tree x z).
  Proof.
(* Goal: @eq t c c *)
    induction x; simpl; intros; try destruct_bool; simpl; auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    case_eq (union_tree y z); intros.

(* Goal: @eq t c c *)
    destruct y; destruct z; destruct_bool; simpl in *; try discriminate; auto.
(* Goal: @eq t c c *)
    repeat rewrite <- union_idem; auto.
(* Goal: @eq t c c *)
    repeat rewrite <- union_absorb; auto.
(* Goal: @eq t c c *)
    repeat (rewrite union_commute; rewrite <- union_absorb); auto.

(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (intersect_tree match y with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node x1 x2 | Node l2 r2 => Node (union_tree x1 l2) (union_tree x2 r2) end match z with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node x1 x2 | Node l2 r2 => Node (union_tree x1 l2) (union_tree x2 r2) end) *)
    destruct y; destruct z; destruct_bool; try discriminate; simpl in *.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (Node (intersect_tree (union_tree x1 y1) (union_tree x1 z1)) (intersect_tree (union_tree x2 y2) (union_tree x2 z2))) *)
    rewrite <- IHx1.
(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (Node (union_tree x1 (intersect_tree y1 z1)) (intersect_tree (union_tree x2 y2) (union_tree x2 z2))) *)
    rewrite <- IHx2.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
  Qed.

  Lemma union_distrib : forall x y z,
    union_tree x (intersect_tree y z) =
    intersect_tree (union_tree x y) (union_tree x z).
  Proof.
(* Goal: @eq t c c *)
    induction x; simpl; intros; try destruct_bool; simpl; auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    case_eq (intersect_tree y z); intros.

(* Goal: @eq t c c *)
    destruct y; destruct z; destruct_bool; simpl in *; try discriminate; auto.
(* Goal: @eq t c c *)
    repeat rewrite <- intersect_idem; auto.
(* Goal: @eq t c c *)
    repeat rewrite <- intersect_absorb; auto.
(* Goal: @eq t c c *)
    repeat (rewrite intersect_commute; rewrite <- intersect_absorb); auto.

(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (intersect_tree match y with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node x1 x2 | Node l2 r2 => Node (union_tree x1 l2) (union_tree x2 r2) end match z with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node x1 x2 | Node l2 r2 => Node (union_tree x1 l2) (union_tree x2 r2) end) *)
    destruct y; destruct z; destruct_bool; try discriminate; simpl in *.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (Node (intersect_tree (union_tree x1 y1) (union_tree x1 z1)) (intersect_tree (union_tree x2 y2) (union_tree x2 z2))) *)
    rewrite <- IHx1.
(* Goal: @eq ShareTree (Node (union_tree x1 s) (union_tree x2 s0)) (Node (union_tree x1 (intersect_tree y1 z1)) (intersect_tree (union_tree x2 y2) (union_tree x2 z2))) *)
    rewrite <- IHx2.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
  Qed.

  (* Demonstrate that union and intersection are
     congruences WRT the shareTreeEq relation. *)

  Lemma Node_Eq : forall x x' y y',
    shareTreeEq x x' ->
    shareTreeEq y y' ->
    shareTreeEq (Node x y) (Node x' y').
  Proof.
(* Goal: @eq t c c *)
    unfold shareTreeEq; intuition; econstructor; auto.
  Qed.

  Lemma intersect_cong0 : forall y x x',
    shareTreeOrd x x' ->
    shareTreeOrd
      (intersect_tree x  y)
      (intersect_tree x' y).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction y; simpl; intros.
(* Goal: shareTreeOrd (intersect_tree x (Leaf b)) (intersect_tree x' (Leaf b)) *)
(* Goal: shareTreeOrd (intersect_tree x (Node y1 y2)) (intersect_tree x' (Node y1 y2)) *)
    rewrite (intersect_commute x (Leaf b)).
(* Goal: shareTreeOrd (intersect_tree (Leaf b) x) (intersect_tree x' (Leaf b)) *)
(* Goal: shareTreeOrd (intersect_tree x (Node y1 y2)) (intersect_tree x' (Node y1 y2)) *)
    rewrite (intersect_commute x' (Leaf b)).
    revert b x' H; induction x; simpl; intros; destruct_bool;
      solve [ auto | apply falseLeaf_bottom ].

    induction H; simpl in *; intros; destruct_bool; simpl in *; try discriminate;
      solve [ apply shareTreeOrd_refl
            | apply falseLeaf_bottom
            | invert_ord; repeat econstructor; auto
            ].
  Qed.

  Lemma union_cong0 : forall y x x',
    shareTreeOrd x x' ->
    shareTreeOrd
      (union_tree x  y)
      (union_tree x' y).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction y; simpl; intros.
(* Goal: shareTreeOrd (union_tree x (Leaf b)) (union_tree x' (Leaf b)) *)
(* Goal: shareTreeOrd (union_tree x (Node y1 y2)) (union_tree x' (Node y1 y2)) *)
    rewrite (union_commute x (Leaf b)).

(* Goal: shareTreeOrd (union_tree (Leaf b) x) (union_tree x' (Leaf b)) *)
(* Goal: shareTreeOrd (union_tree x (Node y1 y2)) (union_tree x' (Node y1 y2)) *)
    rewrite (union_commute x' (Leaf b)).
    revert b x' H; induction x; simpl; intros; destruct_bool;
      solve [ auto | apply trueLeaf_top ].

    induction H; simpl in *; intros; destruct_bool; simpl in *; try discriminate;
      solve [ apply shareTreeOrd_refl
            | apply trueLeaf_top
            | invert_ord; repeat econstructor; auto
            ].
  Qed.

  Lemma intersect_cong1 : forall x x' y,
    shareTreeEq x x' ->
    shareTreeEq
      (intersect_tree x  y)
      (intersect_tree x' y).
  Proof.
(* Goal: @eq t c c *)
    unfold shareTreeEq; intuition; apply intersect_cong0; auto.
  Qed.

  Lemma union_cong1 : forall x x' y,
    shareTreeEq x x' ->
    shareTreeEq
      (union_tree x  y)
      (union_tree x' y).
  Proof.
(* Goal: @eq t c c *)
    unfold shareTreeEq; intuition; apply union_cong0; auto.
  Qed.

  Lemma intersect_cong : forall x x' y y',
    shareTreeEq x x' ->
    shareTreeEq y y' ->
    shareTreeEq
      (intersect_tree x y)
      (intersect_tree x' y').

  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: shareTreeEq (intersect_tree x y) (intersect_tree x' y') *)
    apply shareTreeEq_trans with (intersect_tree x' y).
(* Goal: @eq t c c *)
    apply intersect_cong1; auto.
(* Goal: shareTreeEq (intersect_tree x' y) (intersect_tree x' y') *)
    rewrite (intersect_commute x' y).
(* Goal: shareTreeEq (intersect_tree y x') (intersect_tree x' y') *)
    rewrite (intersect_commute x' y').
(* Goal: @eq t c c *)
    apply intersect_cong1; auto.
  Qed.

  Lemma union_cong : forall x x' y y',
    shareTreeEq x x' ->
    shareTreeEq y y' ->
    shareTreeEq
      (union_tree x y)
      (union_tree x' y').
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: shareTreeEq (union_tree x y) (union_tree x' y') *)
    apply shareTreeEq_trans with (union_tree x' y).
(* Goal: @eq t c c *)
    apply union_cong1; auto.
(* Goal: shareTreeEq (union_tree x' y) (union_tree x' y') *)
    rewrite (union_commute x' y).
(* Goal: shareTreeEq (union_tree y x') (union_tree x' y') *)
    rewrite (union_commute x' y').
(* Goal: @eq t c c *)
    apply union_cong1; auto.
  Qed.

  Lemma comp_cong0 : forall x x',
    shareTreeOrd x x' ->
    shareTreeOrd (comp_tree x') (comp_tree x).
  Proof.
(* Goal: forall (x x' : ShareTree) (_ : shareTreeOrd x x'), shareTreeOrd (comp_tree x') (comp_tree x) *)
    induction x; simpl.
    induction x'; simpl; intros; invert_ord; destruct_bool;
      repeat econstructor; solve [ auto ].

(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    simpl; intros.
(* Goal: shareTreeOrd (comp_tree x') (Node (comp_tree x1) (comp_tree x2)) *)
    inversion H; clear H; subst; invert_ord; destruct_bool; simpl.
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
    apply falseLeaf_bottom.
(* Goal: shareTreeOrd (Node (comp_tree l2) (comp_tree r2)) (Node (comp_tree x1) (comp_tree x2)) *)
    repeat econstructor.
(* Goal: @eq t c c *)
    apply (IHx1 (Leaf false)); auto.
(* Goal: @eq t c c *)
    apply (IHx2 (Leaf false)); auto.
(* Goal: shareTreeOrd (Node (comp_tree l2) (comp_tree r2)) (Node (comp_tree x1) (comp_tree x2)) *)
    repeat econstructor.
(* Goal: @eq t c c *)
    apply IHx1; auto.
(* Goal: @eq t c c *)
    apply IHx2; auto.
  Qed.

  Lemma comp_cong : forall x x',
    shareTreeEq x x' ->
    shareTreeEq (comp_tree x') (comp_tree x).
  Proof.
    unfold shareTreeEq; intuition;
(* Goal: @eq t c c *)
     apply comp_cong0; auto.
  Qed.

  Lemma tree_comp1 : forall x,
     shareTreeOrd (Leaf true) (union_tree x (comp_tree x)).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction x; simpl; intros.
(* Goal: shareTreeOrd x x *)
    destruct b; apply shareTreeOrd_refl.
(* Goal: @eq t c c *)
    apply LeafNode_Ord; apply Node_Ord; auto.
  Qed.

  Lemma tree_comp2 : forall x,
    shareTreeOrd (intersect_tree x (comp_tree x)) (Leaf false).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction x; simpl; intros.
(* Goal: shareTreeOrd x x *)
    destruct b; apply shareTreeOrd_refl.
(* Goal: @eq t c c *)
    apply NodeLeaf_Ord; apply Node_Ord; auto.
  Qed.

  (* Show that two isomorphic canonical trees are identical. *)
  Lemma canonicalUnique : forall c1 c2,
    shareTreeEq c1 c2 ->
    canonicalTree c1 ->
    canonicalTree c2 ->
    c1 = c2.
  Proof.
(* Goal: forall (c1 c2 : ShareTree) (_ : shareTreeEq c1 c2) (_ : canonicalTree c1) (_ : canonicalTree c2), @eq ShareTree c1 c2 *)
    intro c1; induction c1; simpl; intros; destruct H.
(* Goal: @eq t c c *)
    destruct c2; invert_ord; destruct_bool; simpl in *; auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    intuition.
(* Goal: @eq t c c *)
    elim (geTrueFull c2_1); auto.
(* Goal: @eq t c c *)
    elim (geTrueFull c2_1); auto.
(* Goal: @eq t c c *)
    elim (geTrueFull c2_2); auto.
(* Goal: @eq t c c *)
    elim (geTrueFull c2_2); auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    intuition.
(* Goal: @eq t c c *)
    elim (leFalseEmpty c2_1); auto.
(* Goal: @eq t c c *)
    elim (leFalseEmpty c2_2); auto.
(* Goal: @eq t c c *)
    elim (leFalseEmpty c2_1); auto.
(* Goal: @eq t c c *)
    elim (leFalseEmpty c2_2); auto.
(* Goal: @eq t c c *)
    destruct c2; invert_ord; destruct_bool; simpl in *; auto.
(* Goal: @eq ShareTree (Node c1_1 c1_2) (Node c2_1 c2_2) *)
    replace c2_1 with c1_1.
(* Goal: @eq t c c *)
    replace c2_2 with c1_2; auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    intuition.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    intuition.
  Qed.

  Lemma mkCanon_test2 : forall x y,
    shareTreeEq x y ->
    mkCanon x = mkCanon y.
  Proof.
(* Goal: @eq t c c *)
    intros; apply canonicalUnique; auto.
(* Goal: @eq t c c *)
    apply shareTreeEq_trans with x; auto.
(* Goal: @eq t c c *)
    apply shareTreeEq_sym; auto.
(* Goal: @eq t c c *)
    apply shareTreeEq_trans with y; auto.
  Qed.

  (* Some basic facts about the relativization operation:
     It is injective when a is nonempty; a number of facts
     about nonemptyness, nonfullness and canonical trees;
     it commutes with union, intersection, mkCanon; and
     it is an associative operation.
   *)

  Lemma relativ_inv : forall a x y,
    nonEmptyTree a ->
    shareTreeOrd (relativ_tree a x) (relativ_tree a y) ->
    shareTreeOrd x y.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction a; simpl; intros.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    invert_ord; auto; try discriminate.
(* Goal: @eq t c c *)
    invert_ord; destruct H; auto.
  Qed.

  Lemma relativ_empty : forall a x,
    nonEmptyTree a -> nonEmptyTree x ->
    nonEmptyTree (relativ_tree a x).
  Proof.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    induction a; simpl; intros; destruct_bool; try discriminate; intuition.
  Qed.

  Lemma relativ_empty1 : forall a x,
    nonEmptyTree (relativ_tree a x) ->
    nonEmptyTree a.
  Proof.
(* Goal: @eq t c c *)
    induction a; simpl; intros; auto.
(* Goal: @eq t c c *)
    destruct b; try discriminate; auto.
(* Goal: @eq t c c *)
    intuition; eauto.
  Qed.

  Lemma relativ_empty2 : forall a x,
    nonEmptyTree (relativ_tree a x) ->
    nonEmptyTree x.
  Proof.
(* Goal: @eq t c c *)
    induction a; simpl; intros; auto.
(* Goal: @eq t c c *)
    destruct b; simpl in *; auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    discriminate.
(* Goal: @eq t c c *)
    intuition; eauto.
  Qed.

  Lemma relativ_full1 : forall a x,
    nonFullTree a ->
    nonFullTree (relativ_tree a x).
  Proof.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    induction a; simpl; intros; destruct_bool; try discriminate; intuition.
  Qed.

  Lemma relativ_full2 : forall a x,
    nonFullTree x ->
    nonFullTree (relativ_tree a x).
  Proof.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    induction a; simpl; intros; destruct_bool; try discriminate; simpl; intuition.
  Qed.

  Lemma relativ_full : forall a,
    relativ_tree a (Leaf true) = a.
  Proof.
(* Goal: @eq t c c *)
    induction a; simpl; intros; auto.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: @eq t c c *)
    rewrite IHa1; rewrite IHa2; auto.
  Qed.

  Hint Resolve relativ_empty relativ_empty1 relativ_empty2
    relativ_full relativ_full1 relativ_full2 relativ_inv.

  Lemma relativ_almost_canon : forall a x,
    canonicalTree a ->
    canonicalTree x ->
    nonEmptyTree x ->
    canonicalTree (relativ_tree a x).
  Proof.
(* Goal: @eq t c c *)
    induction a; simpl; intros; destruct_bool; auto.
(* Goal: @eq t c c *)
    intuition auto.
  Qed.

  Lemma relativ_cong : forall a x y,
    shareTreeOrd x y ->
    shareTreeOrd (relativ_tree a x) (relativ_tree a y).
  Proof.
(* Goal: @eq t c c *)
    induction a; simpl; intros; auto.
(* Goal: @eq t c c *)
    destruct b; repeat econstructor; auto.
  Qed.

  Lemma relativ_canon_commute : forall a x,
    canonicalTree a ->
    nonEmptyTree x ->
    mkCanon (relativ_tree a x) =
    relativ_tree a (mkCanon x).
  Proof.
    intros; apply canonicalUnique.
    2: apply mkCanon_correct.
(* Goal: @eq t c c *)
    2: apply relativ_almost_canon; auto.
    apply shareTreeEq_trans with (relativ_tree a x).
(* Goal: @eq t c c *)
    apply shareTreeEq_sym; auto.
    destruct (mkCanon_eq x).
(* Goal: @eq t c c *)
    split; apply relativ_cong; auto.
  Qed.

  Lemma relativ_intersect : forall a x y,
    relativ_tree a (intersect_tree x y) =
    intersect_tree (relativ_tree a x) (relativ_tree a y).
  Proof.
(* Goal: @eq t c c *)
    induction a; simpl; intros; auto.
(* Goal: @eq t c c *)
    destruct b; simpl; auto.
(* Goal: @eq t c c *)
    rewrite IHa1; rewrite IHa2; auto.
  Qed.

  Lemma relativ_union : forall a x y,
    relativ_tree a (union_tree x y) =
    union_tree (relativ_tree a x) (relativ_tree a y).
  Proof.
(* Goal: @eq t c c *)
    induction a; simpl; intros; auto.
(* Goal: @eq t c c *)
    destruct b; simpl; auto.
(* Goal: @eq t c c *)
    rewrite IHa1; rewrite IHa2; auto.
  Qed.

  Lemma relativ_assoc : forall x y z,
    relativ_tree x (relativ_tree y z) =
    relativ_tree (relativ_tree x y) z.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction x; simpl; intros.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: @eq ShareTree (Node (relativ_tree x1 (relativ_tree y z)) (relativ_tree x2 (relativ_tree y z))) (Node (relativ_tree (relativ_tree x1 y) z) (relativ_tree (relativ_tree x2 y) z)) *)
    rewrite IHx1.
(* Goal: @eq ShareTree (Node (relativ_tree (relativ_tree x1 y) z) (relativ_tree x2 (relativ_tree y z))) (Node (relativ_tree (relativ_tree x1 y) z) (relativ_tree (relativ_tree x2 y) z)) *)
    rewrite IHx2.
(* Goal: @eq t c c *)
    auto.
  Qed.

  (* Here we have an unfortunate detour to develop a theory
     of many-hole contexts, which allows us to prove
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
     that relativization is injective on the left. *)

  Inductive Sctx : Set :=
  | NodeB : Sctx -> Sctx -> Sctx
  | NodeR : ShareTree -> Sctx -> Sctx
  | NodeL : Sctx -> ShareTree -> Sctx
  | Hole : Sctx
  .

  Fixpoint Sctx_app (c1 c2:Sctx) {struct c1} : Sctx :=
  match c1 with
  | NodeB l r => NodeB (Sctx_app l c2) (Sctx_app r c2)
  | NodeR l r => NodeR l (Sctx_app r c2)
  | NodeL l r => NodeL (Sctx_app l c2) r
  | Hole      => c2
  end.

  Fixpoint fill (c:Sctx) (x:ShareTree) {struct c} : ShareTree :=
  match c with
  | NodeR l r => Node l (fill r x)
  | NodeL l r => Node (fill l x) r
  | NodeB l r => Node (fill l x) (fill r x)
  | Hole      => x
  end.

  Lemma fill_app : forall c1 c2 x,
    fill c1 (fill c2 x) = fill (Sctx_app c1 c2) x.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction c1; simpl; intros.
(* Goal: @eq ShareTree (Node (fill c1_1 (fill c2 x)) (fill c1_2 (fill c2 x))) (Node (fill (Sctx_app c1_1 c2) x) (fill (Sctx_app c1_2 c2) x)) *)
(* Goal: @eq ShareTree (Node s (fill c1 (fill c2 x))) (Node s (fill (Sctx_app c1 c2) x)) *)
(* Goal: @eq ShareTree (Node (fill c1 (fill c2 x)) s) (Node (fill (Sctx_app c1 c2) x) s) *)
(* Goal: @eq ShareTree (fill c2 x) (fill c2 x) *)
    rewrite <- IHc1_1.
(* Goal: @eq ShareTree (Node (fill c1_1 (fill c2 x)) (fill c1_2 (fill c2 x))) (Node (fill c1_1 (fill c2 x)) (fill (Sctx_app c1_2 c2) x)) *)
(* Goal: @eq ShareTree (Node s (fill c1 (fill c2 x))) (Node s (fill (Sctx_app c1 c2) x)) *)
(* Goal: @eq ShareTree (Node (fill c1 (fill c2 x)) s) (Node (fill (Sctx_app c1 c2) x) s) *)
(* Goal: @eq ShareTree (fill c2 x) (fill c2 x) *)
    rewrite <- IHc1_2.
(* Goal: @eq t c c *)
    auto.
(* Goal: @eq t c c *)
    rewrite IHc1; auto.
(* Goal: @eq t c c *)
    rewrite IHc1; auto.
(* Goal: @eq t c c *)
    auto.
  Qed.

  Lemma fill_id : forall x c,
    fill c x = x -> c = Hole.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction x; simpl; intros.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    destruct c; simpl in *; auto; discriminate.
(* Goal: @eq Sctx c Hole *)
    destruct c; auto; simpl in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H.
    replace (fill c1 (Node x1 x2))
      with (fill (Sctx_app c1 (NodeL Hole x2)) x1) in H1.
(* Goal: @eq Sctx (NodeL c x2) Hole *)
(* Goal: @eq ShareTree (fill (Sctx_app c (NodeL Hole x2)) x1) (fill c (Node x1 x2)) *)
    generalize (IHx1 _ H1).
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    destruct c1; simpl; intros; discriminate.
(* Goal: @eq t c c *)
    rewrite <- fill_app; simpl; auto.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H.
    replace (fill c (Node x1 x2)) with
      (fill (Sctx_app c (NodeR x1 Hole)) x2) in H2.
(* Goal: @eq Sctx (NodeR x1 c) Hole *)
(* Goal: @eq ShareTree (fill (Sctx_app c (NodeR x1 Hole)) x2) (fill c (Node x1 x2)) *)
(* Goal: @eq Sctx (NodeL c s) Hole *)
    generalize (IHx2 _ H2).
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    destruct c; simpl; intros; discriminate.
(* Goal: @eq t c c *)
    rewrite <- fill_app; simpl; auto.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H.
    replace (fill c (Node x1 x2)) with
      (fill (Sctx_app c (NodeL Hole x2)) x1) in H1.
(* Goal: @eq Sctx (NodeL c x2) Hole *)
(* Goal: @eq ShareTree (fill (Sctx_app c (NodeL Hole x2)) x1) (fill c (Node x1 x2)) *)
    generalize (IHx1 _ H1).
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    destruct c; simpl; intros; discriminate.
(* Goal: @eq t c c *)
    rewrite <- fill_app; simpl; auto.
  Qed.

  Definition to_Sctx (a:ShareTree) : nonEmptyTree a -> Sctx.
(* Goal: forall _ : nonEmptyTree a, Sctx *)
   revert a.
    refine (fix f (a:ShareTree)  {struct a} : nonEmptyTree a -> Sctx :=
           match a as a' return nonEmptyTree a' -> Sctx with
           | Leaf true => fun H => Hole
           | Leaf false => fun H => False_rec _ _
           | Node l r => fun H =>
              match nonEmpty_dec l, nonEmpty_dec r with
              | left  Hl, left Hr => NodeB (f l Hl) (f r Hr)
              | left  Hl, right _  => NodeL (f l Hl) r
              | right _ , left  Hr => NodeR l (f r Hr)
              | right Hl, right Hr => False_rec _ _
              end
           end).
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    simpl in H; discriminate.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    simpl in H; intuition.
  Defined.

  Lemma relativ_to_Sctx : forall a x H,
    relativ_tree a x = fill (to_Sctx a H) x.
  Proof.
(* Goal: forall (a x : ShareTree) (H : nonEmptyTree a), @eq ShareTree (relativ_tree a x) (fill (to_Sctx a H) x) *)
    induction a; simpl.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    destruct b; intros; try discriminate.
(* Goal: @eq t c c *)
    simpl; auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill match nonEmpty_dec a1 with | left Hl => match nonEmpty_dec a2 with | left Hr => NodeB (to_Sctx a1 Hl) (to_Sctx a2 Hr) | right n => NodeL (to_Sctx a1 Hl) a2 end | right Hl => match nonEmpty_dec a2 with | left Hr => NodeR a1 (to_Sctx a2 Hr) | right Hr => False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (Hl H0)) (fun H0 : nonEmptyTree a2 => False_ind False (Hr H0)) H) end end x) *)
    destruct (nonEmpty_dec a1); destruct (nonEmpty_dec a2); simpl.
(* Goal: @eq t c c *)
    rewrite <- IHa1; rewrite <- IHa2; auto.
(* Goal: @eq t c c *)
    rewrite <- IHa1; auto.
(* Goal: @eq t c c *)
    replace (relativ_tree a2 x) with a2; auto.
(* Goal: @eq ShareTree a2 (relativ_tree a2 x) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (Node a1 (fill (to_Sctx a2 n0) x)) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill (False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (n H0)) (fun H0 : nonEmptyTree a2 => False_ind False (n0 H0)) H)) x) *)
    clear -n0.
(* Goal: @eq ShareTree a2 (relativ_tree a2 x) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (Node a1 (fill (to_Sctx a2 n0) x)) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill (False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (n H0)) (fun H0 : nonEmptyTree a2 => False_ind False (n0 H0)) H)) x) *)
    induction a2; simpl.
(* Goal: @eq t c c *)
    destruct b; simpl in *; auto.
(* Goal: @eq t c c *)
    elim n0; auto.
(* Goal: @eq ShareTree (Node a2_1 a2_2) (Node (relativ_tree a2_1 x) (relativ_tree a2_2 x)) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (Node a1 (fill (to_Sctx a2 n0) x)) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill (False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (n H0)) (fun H0 : nonEmptyTree a2 => False_ind False (n0 H0)) H)) x) *)
    rewrite <- IHa2_1.
(* Goal: @eq t c c *)
    rewrite <- IHa2_2; auto.
(* Goal: @eq t c c *)
    intro; apply n0; simpl; auto.
(* Goal: @eq t c c *)
    intro; apply n0; simpl; auto.
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (Node a1 (fill (to_Sctx a2 n0) x)) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill (False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (n H0)) (fun H0 : nonEmptyTree a2 => False_ind False (n0 H0)) H)) x) *)
    rewrite <- IHa2.
(* Goal: @eq t c c *)
    replace (relativ_tree a1 x) with a1; auto.
(* Goal: @eq ShareTree a1 (relativ_tree a1 x) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill (False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (n H0)) (fun H0 : nonEmptyTree a2 => False_ind False (n0 H0)) H)) x) *)
    clear -n.
(* Goal: @eq ShareTree a1 (relativ_tree a1 x) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill (False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (n H0)) (fun H0 : nonEmptyTree a2 => False_ind False (n0 H0)) H)) x) *)
    induction a1; simpl.
(* Goal: @eq t c c *)
    destruct b; simpl in *; auto.
(* Goal: @eq ShareTree (Leaf true) x *)
(* Goal: @eq ShareTree (Node a1_1 a1_2) (Node (relativ_tree a1_1 x) (relativ_tree a1_2 x)) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill (False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (n H0)) (fun H0 : nonEmptyTree a2 => False_ind False (n0 H0)) H)) x) *)
    elim n; auto.
(* Goal: @eq ShareTree (Node a1_1 a1_2) (Node (relativ_tree a1_1 x) (relativ_tree a1_2 x)) *)
(* Goal: @eq ShareTree (Node (relativ_tree a1 x) (relativ_tree a2 x)) (fill (False_rec Sctx (@or_ind (nonEmptyTree a1) (nonEmptyTree a2) False (fun H0 : nonEmptyTree a1 => False_ind False (n H0)) (fun H0 : nonEmptyTree a2 => False_ind False (n0 H0)) H)) x) *)
    rewrite <- IHa1_1.
(* Goal: @eq t c c *)
    rewrite <- IHa1_2; auto.
(* Goal: @eq t c c *)
    intro; apply n; simpl; auto.
(* Goal: @eq t c c *)
    intro; apply n; simpl; auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    elimtype False; intuition.
  Qed.

  Lemma relativ_stupid1 : forall x y a,
    nonEmptyTree x ->
    x = relativ_tree a (Node x y) ->
    False.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq ShareTree x y *)
    assert (nonEmptyTree a).
(* Goal: nonEmptyTree a *)
(* Goal: False *)
    apply relativ_empty1 with (Node x y).
(* Goal: @eq t c c *)
    rewrite <- H0; auto.
(* Goal: False *)
    rewrite (relativ_to_Sctx a (Node x y) H1) in H0.
    replace (fill (to_Sctx a H1) (Node x y))
       with (fill (Sctx_app (to_Sctx a H1) (NodeL Hole y)) x) in H0.
(* Goal: False *)
(* Goal: @eq ShareTree (fill (Sctx_app (to_Sctx a H1) (NodeR x Hole)) y) (fill (to_Sctx a H1) (Node x y)) *)
    symmetry in H0.
(* Goal: False *)
    generalize (fill_id _ _ H0).
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    destruct (to_Sctx a H1); simpl; intros; discriminate.
(* Goal: @eq t c c *)
    rewrite <- fill_app; auto.
  Qed.

  Lemma relativ_stupid2 : forall x y a,
    nonEmptyTree y ->
    y = relativ_tree a (Node x y) ->
    False.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq ShareTree x y *)
    assert (nonEmptyTree a).
(* Goal: nonEmptyTree a *)
(* Goal: False *)
    apply relativ_empty1 with (Node x y).
(* Goal: @eq t c c *)
    rewrite <- H0; auto.
(* Goal: False *)
    rewrite (relativ_to_Sctx a (Node x y) H1) in H0.
    replace (fill (to_Sctx a H1) (Node x y))
       with (fill (Sctx_app (to_Sctx a H1) (NodeR x  Hole)) y) in H0.
(* Goal: False *)
(* Goal: @eq ShareTree (fill (Sctx_app (to_Sctx a H1) (NodeR x Hole)) y) (fill (to_Sctx a H1) (Node x y)) *)
    symmetry in H0.
(* Goal: False *)
    generalize (fill_id _ _ H0).
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    destruct (to_Sctx a H1); simpl; intros; discriminate.
(* Goal: @eq t c c *)
    rewrite <- fill_app; auto.
  Qed.

  Lemma relativ_stupid3 : forall a1 a2 x,
    nonEmptyTree x ->
    relativ_tree (Node a1 a2) x = x ->
    False.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: False *)
    assert (nonEmptyTree (Node a1 a2)).
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
    rewrite <- H0 in H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
    destruct H.
(* Goal: @eq t c c *)
    left; apply relativ_empty1 with x; auto.
(* Goal: @eq t c c *)
    right; apply relativ_empty1 with x; auto.
(* Goal: False *)
    rewrite (relativ_to_Sctx (Node a1 a2) x H1) in H0.
(* Goal: False *)
    generalize (fill_id _ _ H0).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    destruct (nonEmpty_dec a1); destruct (nonEmpty_dec a2); intros; try discriminate.
(* Goal: False *)
    clear H0 H2.
(* Goal: @eq t c c *)
    simpl in H1; destruct H1; auto.
  Qed.

  (* detour finished.  now we can prove the result of interest,
     which is that relativization is injective on the left
   *)
  Lemma relativ_inv2 : forall a1 a2 x,
    nonEmptyTree x ->
    relativ_tree a1 x = relativ_tree a2 x ->
    a1 = a2.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction a1; intros.
(* Goal: @eq ShareTree (Leaf b) a2 *)
(* Goal: @eq ShareTree (Node a1_1 a1_2) a2 *)
    destruct b; simpl in *.
(* Goal: @eq ShareTree (Leaf true) a2 *)
(* Goal: @eq ShareTree (Leaf false) a2 *)
(* Goal: @eq ShareTree (Node a1_1 a1_2) a2 *)
    revert a2 H0.
(* Goal: forall (a2 : ShareTree) (_ : @eq ShareTree x (relativ_tree a2 x)), @eq ShareTree (Leaf true) a2 *)
(* Goal: @eq ShareTree (Leaf false) a2 *)
(* Goal: @eq ShareTree (Node a1_1 a1_2) a2 *)
    induction x; simpl in *.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    subst b; simpl; intros.
(* Goal: @eq ShareTree (Node a1_1 a1_2) a2 *)
    destruct a2; simpl in *.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    discriminate.

(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq ShareTree (Node a1_1 a1_2) a2 *)
    destruct a2; simpl in *.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    discriminate.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    injection H0; intros.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
    destruct H.
(* Goal: @eq t c c *)
    elim relativ_stupid1 with x1 x2 a2_1; auto.
(* Goal: @eq t c c *)
    elim relativ_stupid2 with x1 x2 a2_2; auto.

(* Goal: @eq ShareTree (Node a1_1 a1_2) a2 *)
    destruct a2; simpl in *.
(* Goal: @eq t c c *)
    destruct b; auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    subst x; simpl in H; discriminate.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    discriminate.

(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    simpl in *.
(* Goal: @eq ShareTree (Node a1_1 a1_2) a2 *)
    destruct a2; simpl in *.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
    destruct b; try discriminate.
(* Goal: @eq ShareTree (Node a1_1 a1_2) (Leaf true) *)
(* Goal: @eq ShareTree (Node a1_1 a1_2) (Node a2_1 a2_2) *)
    elimtype False; clear -H H0.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    revert H0.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: False *)
(* Goal: @eq ShareTree (Node a1_1 a1_2) (Node a2_1 a2_2) *)
    apply (relativ_stupid3 _ _ _ H H0).

(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    injection H0; intros.
(* Goal: @eq t c c *)
    rewrite IHa1_1 with a2_1 x; auto.
(* Goal: @eq t c c *)
    rewrite IHa1_2 with a2_2 x; auto.
  Qed.

  (* Define the subset type canonTree and show that it has
     decidable equality. *)

  Definition canonTree :=  { t:ShareTree | canonicalTree t }.

  Lemma shareTree_dec_eq : forall x y:ShareTree, {x=y}+{x<>y}.
  Proof. decide equality; apply bool_dec. Defined.

  Lemma canonTree_eq : forall x y:canonTree, proj1_sig x = proj1_sig y -> x = y.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: sumbool (@eq canonTree x y) (not (@eq canonTree x y)) *)
    destruct x as [x Hx].
(* Goal: sumbool (@eq canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) x Hx) y) (not (@eq canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) x Hx) y)) *)
    destruct y as [y Hy].
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    simpl in *.
(* Goal: @eq canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) x Hx) (@exist ShareTree (fun t : ShareTree => canonicalTree t) y Hy) *)
    subst y.
(* Goal: @eq t c c *)
    replace Hy with Hx by apply proof_irr; auto.
  Qed.

  Lemma canonTree_eq_dec : forall x y:canonTree, {x=y}+{x<>y}.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: sumbool (@eq canonTree x y) (not (@eq canonTree x y)) *)
    destruct x as [x Hx].
(* Goal: sumbool (@eq canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) x Hx) y) (not (@eq canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) x Hx) y)) *)
    destruct y as [y Hy].
(* Goal: sumbool (@eq canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) x Hx) (@exist ShareTree (fun t : ShareTree => canonicalTree t) y Hy)) (not (@eq canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) x Hx) (@exist ShareTree (fun t : ShareTree => canonicalTree t) y Hy))) *)
    destruct (shareTree_dec_eq x y); [ left | right ].
(* Goal: @eq t c c *)
    apply canonTree_eq; simpl; auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    red; intros.
(* Goal: False *)
    injection H.
(* Goal: @eq t c c *)
    auto.
  Defined.

  Instance EqDec_canonTree : EqDec canonTree := canonTree_eq_dec.

  (* Show that complement preserves canonical trees *)

  Lemma comp_tree_inv : forall t, comp_tree (comp_tree t) = t.
  Proof.
(* Goal: @eq t c c *)
    induction t; simpl; intros; try destruct_bool; auto.
(* Goal: @eq t c c *)
    rewrite IHt1; rewrite IHt2; auto.
  Qed.

  Lemma comp_full_empty : forall x,
    nonFullTree x -> nonEmptyTree (comp_tree x).
  Proof.
(* Goal: and (or (@eq bool b false) (@eq bool b0 false)) (and (or (@eq bool b true) (@eq bool b0 true)) (and True True)) *)
(* Goal: canonicalTree (Node (Leaf b) (Node s s0)) *)
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
    intro x; induction x; simpl; intros; destruct_bool; intuition.
  Qed.

  Lemma comp_empty_full : forall x,
    nonEmptyTree x -> nonFullTree (comp_tree x).
  Proof.
(* Goal: and (or (@eq bool b false) (@eq bool b0 false)) (and (or (@eq bool b true) (@eq bool b0 true)) (and True True)) *)
(* Goal: canonicalTree (Node (Leaf b) (Node s s0)) *)
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
    intro x; induction x; simpl; intros; destruct_bool; intuition.
  Qed.

  Hint Resolve comp_full_empty comp_empty_full.

  Lemma comp_canonical : forall x,
    canonicalTree x -> canonicalTree (comp_tree x).
  Proof.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
    intro x; induction x; simpl; intros; intuition.
  Qed.

  (*** Begin Module Signature Definitions and lemmas ***)

  (* Here we show that canonical share trees form a boolean algrbra.  These
     proofs mainly involve showing that the results above commute in the proper
     ways with mkCanon. *)
  Module BA <: BOOLEAN_ALGEBRA.
    Definition t := canonTree.
    Definition Ord (x y:canonTree) := shareTreeOrd (proj1_sig x) (proj1_sig y).

    Definition lub (x y:canonTree) : canonTree :=
      exist (fun t => canonicalTree t)
      (mkCanon (union_tree (proj1_sig x) (proj1_sig y)))
      (mkCanon_correct _).

    Definition glb (x y:canonTree) : canonTree :=
      exist (fun t => canonicalTree t)
      (mkCanon (intersect_tree (proj1_sig x) (proj1_sig y)))
      (mkCanon_correct _).

    Definition top : canonTree := exist (fun t => canonicalTree t) (Leaf true) I.
    Definition bot : canonTree := exist (fun t => canonicalTree t) (Leaf false) I.

    Definition comp (x:canonTree) : canonTree :=
      exist (fun t => canonicalTree t) (comp_tree (proj1_sig x))
      (comp_canonical _ (proj2_sig x)).

    Lemma ord_refl : forall x, Ord x x.
    Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      intros [x Hx]; unfold Ord; simpl.
(* Goal: shareTreeOrd x x *)
      apply shareTreeOrd_refl.
    Qed.

    Lemma ord_trans : forall x y z, Ord x y -> Ord y z -> Ord x z.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros [x Hx] [y Hy] [z Hz]; unfold Ord; simpl; intros.
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with y; auto.
    Qed.

    Lemma ord_antisym : forall x y, Ord x y -> Ord y x -> x = y.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros [x Hx] [y Hy]; unfold Ord; simpl; intros.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
(* Goal: @eq t c c *)
      apply canonicalUnique; try split; auto.
    Qed.

    Lemma lub_upper1 : forall x y, Ord x (lub x y).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros [x Hx] [y Hy]; unfold Ord; simpl; intros.
(* Goal: shareTreeOrd (mkCanon (union_tree x y)) z *)
      destruct (mkCanon_eq (union_tree x y)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (union_tree x y); auto.
(* Goal: shareTreeOrd t1 (union_tree t1 t0) *)
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      apply union_upper_bound.
    Qed.

    Lemma lub_upper2 : forall x y, Ord y (lub x y).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros [x Hx] [y Hy]; unfold Ord; simpl; intros.
(* Goal: shareTreeOrd (mkCanon (union_tree x y)) z *)
      destruct (mkCanon_eq (union_tree x y)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (union_tree x y); auto.
(* Goal: @eq ShareTree (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b) (Leaf false))) (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)) *)
      rewrite union_commute.
(* Goal: shareTreeOrd t1 (union_tree t1 t0) *)
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      apply union_upper_bound.
    Qed.

    Lemma lub_least : forall x y z,
      Ord x z -> Ord y z -> Ord (lub x y) z.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros [x Hx] [y Hy] [z Hz]; unfold Ord; simpl; intros.
(* Goal: shareTreeOrd (mkCanon (union_tree x y)) z *)
      destruct (mkCanon_eq (union_tree x y)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (union_tree x y); auto.
(* Goal: @eq t c c *)
      apply union_least_bound; auto.
    Qed.

    Lemma glb_lower1 : forall x y, Ord (glb x y) x.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros [x Hx] [y Hy]; unfold Ord; simpl; intros.
(* Goal: shareTreeOrd z (mkCanon (intersect_tree x y)) *)
      destruct (mkCanon_eq (intersect_tree x y)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (intersect_tree x y); auto.
(* Goal: shareTreeOrd (intersect_tree y x) y *)
      apply intersection_lower_bound.
    Qed.

    Lemma glb_lower2 : forall x y, Ord (glb x y) y.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros [x Hx] [y Hy]; unfold Ord; simpl; intros.
(* Goal: shareTreeOrd z (mkCanon (intersect_tree x y)) *)
      destruct (mkCanon_eq (intersect_tree x y)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (intersect_tree x y); auto.
(* Goal: shareTreeOrd (intersect_tree x y) y *)
      rewrite intersect_commute.
(* Goal: shareTreeOrd (intersect_tree y x) y *)
      apply intersection_lower_bound.
    Qed.

    Lemma glb_greatest : forall x y z,
      Ord z x -> Ord z y -> Ord z (glb x y).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros [x Hx] [y Hy] [z Hz]; unfold Ord; simpl; intros.
(* Goal: shareTreeOrd z (mkCanon (intersect_tree x y)) *)
      destruct (mkCanon_eq (intersect_tree x y)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (intersect_tree x y); auto.
(* Goal: @eq t c c *)
      apply intersection_greatest_bound; auto.
    Qed.

    Lemma top_correct : forall x, Ord x top.
    Proof.
(* Goal: @eq t c c *)
      intros [x Hx]; unfold Ord; simpl; auto.
    Qed.

    Lemma bot_correct : forall x, Ord bot x.
    Proof.
(* Goal: @eq t c c *)
      intros [x Hx]; unfold Ord; simpl; auto.
    Qed.

    Lemma comp1 : forall x, lub x (comp x) = top.
    Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      intros [x Hx]; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
      apply fullTree_canonical_trueLeaf.
      2: apply mkCanon_correct.
      apply geTrueFull.
      apply shareTreeOrd_trans with (union_tree x (comp_tree x)).
(* Goal: @eq t c c *)
      2: destruct (mkCanon_eq (union_tree x (comp_tree x))); auto.
      apply tree_comp1.
    Qed.

    Lemma comp2 : forall x, glb x (comp x) = bot.
    Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      intros [x Hx]; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
      apply emptyTree_canonical_falseLeaf.
      2: apply mkCanon_correct.
      apply leFalseEmpty.
      apply shareTreeOrd_trans with (intersect_tree x (comp_tree x)).
(* Goal: @eq t c c *)
      destruct (mkCanon_eq (intersect_tree x (comp_tree x))); auto.
      apply tree_comp2.
    Qed.

    Lemma nontrivial : top <> bot.
    Proof. discriminate. Qed.

    Lemma distrib1 : forall x y z,
      glb x (lub y z) = lub (glb x y) (glb x z).
    Proof.
      intros [x Hx] [y Hy] [z Hz]; unfold glb, lub.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
      apply canonicalUnique;
(* Goal: canonicalTree (mkCanon t0) *)
(* Goal: isToken' (mkCanon (Node (Leaf false) (split_tok2 n0 t0))) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
        try apply mkCanon_correct.
      apply shareTreeEq_trans with
        (intersect_tree x (mkCanon (union_tree y z))).
(* Goal: shareTreeEq (union_tree (create_tok1 n x0) (create_tok2 n x0)) x0 *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply shareTreeEq_sym.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply mkCanon_eq.
      apply shareTreeEq_trans with
        (union_tree (mkCanon (intersect_tree x y)) (mkCanon (intersect_tree x z))).
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      2: apply mkCanon_eq.
      apply shareTreeEq_trans with
        (intersect_tree x (union_tree y z)).
(* Goal: shareTreeEq (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) (intersect_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) *)
(* Goal: shareTreeOrd (intersect_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) (Leaf false) *)
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
      apply intersect_cong.
(* Goal: shareTreeEq (Node (Node fac1_1 fac1_2) fac2) (Node (Node fac1_1 fac1_2) fac2) *)
      apply shareTreeEq_refl.
(* Goal: shareTreeEq (union_tree (create_tok1 n x0) (create_tok2 n x0)) x0 *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply shareTreeEq_sym.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply mkCanon_eq.
      apply shareTreeEq_trans with
        (union_tree (intersect_tree x y) (intersect_tree x z)).
      rewrite intersect_distrib.
(* Goal: shareTreeEq (Node (Node fac1_1 fac1_2) fac2) (Node (Node fac1_1 fac1_2) fac2) *)
      apply shareTreeEq_refl.
(* Goal: shareTreeEq (union_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply union_cong.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply mkCanon_eq.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply mkCanon_eq.
    Qed.

  End BA.

  Module BAF := BA_Facts BA.
  Include BAF.

  (* Now, we prove the axioms about relativization.
     Again, this mostly involves packing and unpacking
     the canonTree type and pushing around mkCanon.
   *)

    Definition rel (a x:t) : t.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      case_eq (proj1_sig x); intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      destruct b.
(* Goal: t *)
(* Goal: t *)
(* Goal: t *)
      exact a.
(* Goal: t *)
(* Goal: t *)
      exact (exist (fun t => canonicalTree t) (Leaf false) I).
(* Goal: t *)
      refine (exist _ (relativ_tree (proj1_sig a) (proj1_sig x)) _).
(* Goal: canonicalTree (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x)) *)
      apply relativ_almost_canon.
(* Goal: canonicalTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) *)
(* Goal: canonicalTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) *)
(* Goal: nonEmptyTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) *)
      apply (proj2_sig a).
(* Goal: canonicalTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) *)
(* Goal: nonEmptyTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) *)
      apply (proj2_sig x).
(* Goal: canonicalTree (Node (Node s s0) (mkCanon x2)) *)
      destruct x; simpl in *; subst; simpl in *; intuition.
    Defined.

    Lemma relativ_tree_empty : forall a x,
      nonEmptyTree a -> nonEmptyTree x ->
      nonEmptyTree (relativ_tree a x).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      induction a; simpl; intros.
(* Goal: @eq t c c *)
      destruct b; auto.
(* Goal: @eq t c c *)
      intuition; eauto.
    Qed.

    Lemma relativ_tree_nonid : forall a x1 x2,
      nonEmptyTree a ->
      a = relativ_tree a (Node x1 x2) ->
      False.
    Proof.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      induction a; simpl; intros; try destruct_bool; try discriminate.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      injection H0; clear H0; intros.
(* Goal: @eq t c c *)
      intuition; eauto.
    Qed.

    Lemma rel_classification : forall a x,
      { x = bot /\ rel a x = bot } +
      { x <> bot /\ proj1_sig (rel a x) = relativ_tree (proj1_sig a) (proj1_sig x)
        /\ (a = bot <-> rel a x = bot) }.
    Proof.
(* Goal: forall a x : t, sumbool (and (@eq t x bot) (@eq t (rel a x) bot)) (and (not (@eq t x bot)) (and (@eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a x)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x))) (iff (@eq t a bot) (@eq t (rel a x) bot)))) *)
      intros [a ?] [x ?].
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct x; try destruct_bool; simpl.
(* Goal: sumbool (and (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) bot)) (and (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) bot)) (and (@eq ShareTree (relativ_tree a (Node x1 x2)) (relativ_tree a (Node x1 x2))) (iff (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) bot)))) *)
      right; split.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      red; intros.
(* Goal: False *)
(* Goal: and (@eq ShareTree a (relativ_tree a (Leaf true))) (iff (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) c0)) bot)) *)
(* Goal: sumbool (and (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) bot)) (and (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) bot)) (and (@eq ShareTree (Leaf false) (relativ_tree a (Leaf false))) (iff (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) bot)))) *)
(* Goal: sumbool (and (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) bot)) (and (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) bot)) (and (@eq ShareTree (relativ_tree a (Node x1 x2)) (relativ_tree a (Node x1 x2))) (iff (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) bot)))) *)
      discriminate H.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
      split.
(* Goal: @eq t c c *)
      rewrite relativ_full; auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      split; intros.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      injection H; clear H; intros.
(* Goal: @eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) c0)) bot *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) bot *)
(* Goal: sumbool (and (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) bot)) (and (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) bot)) (and (@eq ShareTree (Leaf false) (relativ_tree a (Leaf false))) (iff (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) bot)))) *)
(* Goal: sumbool (and (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) bot)) (and (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) bot)) (and (@eq ShareTree (relativ_tree a (Node x1 x2)) (relativ_tree a (Node x1 x2))) (iff (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) bot)))) *)
      subst a.
(* Goal: @eq t c c *)
      apply canonTree_eq; simpl; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
(* Goal: @eq t c c *)
      injection H; auto.
(* Goal: @eq t c c *)
      left; split; auto.
(* Goal: @eq t c c *)
      apply canonTree_eq; auto.
(* Goal: sumbool (and (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) bot)) (and (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) bot)) (and (@eq ShareTree (relativ_tree a (Node x1 x2)) (relativ_tree a (Node x1 x2))) (iff (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) bot) (@eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) a c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) bot)))) *)
      right; split.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      red; intros; discriminate.
(* Goal: @eq t c c *)
      split; auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      split; intros.
(* Goal: @eq t c c *)
      apply canonTree_eq; simpl; auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      injection H; clear H; intros.
(* Goal: @eq t c c *)
      rewrite H; auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      injection H; clear H; intros.
(* Goal: @eq t c c *)
      apply canonTree_eq; simpl; auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      destruct a; simpl in *; destruct_bool; auto; try discriminate.
    Defined.

    Lemma rel_inj_r : forall a1 a2 x, x <> bot -> rel a1 x = rel a2 x -> a1 = a2.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros.
(* Goal: @eq t (rel a (lub x y)) (lub (rel a x) (rel a y)) *)
      apply canonTree_eq.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification a1 x); intuition.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification a2 x); intuition.
(* Goal: @eq t c c *)
      apply relativ_inv2 with (proj1_sig x); auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct x; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct x; simpl.
(* Goal: @eq t c c *)
      destruct b; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      elim H; simpl.
(* Goal: @eq t c c *)
      apply canonTree_eq; auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      generalize c; simpl; intuition.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
      rewrite <- H3.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a1 x)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a2) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x)) *)
      rewrite <- H7.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
      rewrite H0.
(* Goal: @eq t c c *)
      auto.
    Qed.

    Lemma rel_inj_l : forall a x y, a <> bot -> rel a x = rel a y -> x = y.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros.
(* Goal: @eq t (rel a (lub x y)) (lub (rel a x) (rel a y)) *)
      apply canonTree_eq.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct a as [a ?]; destruct x as [x ?]; destruct y as [y ?]; simpl.
(* Goal: @eq ShareTree x y *)
      assert (nonEmptyTree a).
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
      destruct a; simpl in *.
(* Goal: @eq t c c *)
      destruct b; auto.
(* Goal: @eq t c c *)
      elim H; apply canonTree_eq; simpl; auto.
(* Goal: @eq t c c *)
      decompose [and] c; auto.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
      unfold rel in *; simpl in *.
      destruct x; destruct y;
        destruct_bool; auto;
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
        injection H0; clear H0; try congruence; intros.

(* Goal: @eq t c c *)
      elim (relativ_tree_nonid a y1 y2); auto.
(* Goal: @eq ShareTree (Leaf false) (Node y1 y2) *)
(* Goal: @eq ShareTree (Node x1 x2) (Leaf true) *)
(* Goal: @eq ShareTree (Node x1 x2) (Leaf false) *)
(* Goal: @eq ShareTree (Node x1 x2) (Node y1 y2) *)
      simpl in c1; decompose [and] c1.
(* Goal: @eq ShareTree (Leaf false) (Node y1 y2) *)
(* Goal: @eq ShareTree (Node x1 x2) (Leaf true) *)
(* Goal: @eq ShareTree (Node x1 x2) (Leaf false) *)
(* Goal: @eq ShareTree (Node x1 x2) (Node y1 y2) *)
      generalize (relativ_tree_empty a (Node y1 y2) H1 H4).
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      rewrite <- H0; simpl; intros; discriminate.
(* Goal: @eq t c c *)
      elim (relativ_tree_nonid a x1 x2); auto.
(* Goal: @eq ShareTree (Node x1 x2) (Leaf false) *)
(* Goal: @eq ShareTree (Node x1 x2) (Node y1 y2) *)
      simpl in c0; decompose [and] c0.
(* Goal: @eq ShareTree (Node x1 x2) (Leaf false) *)
(* Goal: @eq ShareTree (Node x1 x2) (Node y1 y2) *)
      generalize (relativ_tree_empty a (Node x1 x2) H1 H4).
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      rewrite H0; simpl; intros; discriminate.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
(* Goal: shareTreeOrd x x *)
      split; apply relativ_inv with a; auto; rewrite H0; apply shareTreeOrd_refl.
    Qed.

    Lemma rel_assoc : forall x y z, rel x (rel y z) = rel (rel x y) z.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros.
(* Goal: @eq t (rel a (lub x y)) (lub (rel a x) (rel a y)) *)
      apply canonTree_eq.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification x (rel y z)); intuition.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
      rewrite H0.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification (rel x y) z); intuition.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
      rewrite H1.
(* Goal: @eq t c c *)
      simpl; auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification x y); intuition.
(* Goal: @eq t c c *)
      rewrite H7; auto.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
      rewrite H3.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) bot) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel x y)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) z)) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel x (rel y z))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (rel x y) z)) *)
      rewrite H7.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) bot) (relativ_tree (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) z)) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel x (rel y z))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (rel x y) z)) *)
      rewrite <- relativ_assoc.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification y z); intuition.

(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
      rewrite H1.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification y z); intuition.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification (rel x y) z); intuition.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      rewrite H9.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification x y); intuition.
(* Goal: @eq ShareTree (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel y z))) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel x y)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) z)) *)
      rewrite H13.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
      rewrite H5.
(* Goal: @eq ShareTree (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) z))) (relativ_tree (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) z)) *)
      apply relativ_assoc.
    Qed.

    Lemma rel_bot1 : forall a, rel a bot = bot.
    Proof.
(* Goal: @eq t c c *)
      intros [a ?]; auto.
    Qed.

    Lemma rel_bot2 : forall x, rel bot x = bot.
    Proof.
(* Goal: forall x : t, @eq t (rel bot x) bot *)
      intros e.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification bot e); intuition.
    Qed.

    Lemma rel_top1 : forall a, rel a top = a.
    Proof.
(* Goal: forall a : t, @eq t (rel a top) a *)
      intros a.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification a top); intuition.
    Qed.

    Lemma rel_top2 : forall x, rel top x = x.
    Proof.
(* Goal: forall x : t, @eq t (rel top x) x *)
      intro x.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification top x); intuition.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
      congruence.
(* Goal: @eq t (rel a (lub x y)) (lub (rel a x) (rel a y)) *)
      apply canonTree_eq.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
      rewrite H1.
(* Goal: @eq t c c *)
      simpl; auto.
    Qed.

    Lemma rel_preserves_glb : forall a x y, rel a (glb x y) = glb (rel a x) (rel a y).
    Proof.
(* Goal: forall a x y : t, @eq t (rel a (lub x y)) (lub (rel a x) (rel a y)) *)
      intros a x y.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification a x); intuition.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
      rewrite H0.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
      rewrite H.
(* Goal: @eq t (glb (lub t2 t3) t2) t2 *)
      rewrite glb_commute.
(* Goal: @eq t (rel a bot) (glb (rel a x) bot) *)
(* Goal: @eq t (rel a (glb x y)) (glb (rel a x) (rel a y)) *)
      rewrite glb_bot.
(* Goal: @eq t (rel a bot) (glb bot (rel a y)) *)
(* Goal: @eq t (rel a (glb x y)) (glb (rel a x) (rel a y)) *)
      rewrite rel_bot1.
(* Goal: @eq t (glb (lub t2 t3) t2) t2 *)
      rewrite glb_commute.
(* Goal: @eq t (rel a bot) (glb (rel a x) bot) *)
(* Goal: @eq t (rel a (glb x y)) (glb (rel a x) (rel a y)) *)
      rewrite glb_bot.
(* Goal: @eq t c c *)
      auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification a y); intuition.
(* Goal: @eq ShareTree (mkCanon (Leaf b0)) match mkCanon (Leaf b0) with | Leaf b1 => match mkCanon (Leaf b0) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) | Node s s0 => Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) end | Node s s0 => Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      rewrite H4.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
      rewrite H2.
(* Goal: @eq t (rel a bot) (glb (rel a x) bot) *)
(* Goal: @eq t (rel a (glb x y)) (glb (rel a x) (rel a y)) *)
      rewrite glb_bot.
(* Goal: @eq t (rel a bot) (glb (rel a x) bot) *)
(* Goal: @eq t (rel a (glb x y)) (glb (rel a x) (rel a y)) *)
      rewrite glb_bot.
(* Goal: @eq t (rel x bot) bot *)
      apply rel_bot1.
(* Goal: @eq t (rel a (lub x y)) (lub (rel a x) (rel a y)) *)
      apply canonTree_eq.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
      rewrite H1.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
      rewrite H5.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (glb x y))) (mkCanon (intersect_tree (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      rewrite <- relativ_intersect.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification a (glb x y)); intuition.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      rewrite H8.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      injection H6; intros.
(* Goal: @eq ShareTree (Leaf false) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
      apply (mkCanon_test2 (Leaf false)).
(* Goal: shareTreeEq (Leaf false) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      apply shareTreeEq_trans with (relativ_tree (proj1_sig a) (Leaf false)).
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
      split.
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
      apply falseLeaf_bottom.
(* Goal: shareTreeOrd (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false)) (Leaf false) *)
(* Goal: shareTreeEq (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      apply emptyLeFalse.
(* Goal: not (nonEmptyTree (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) *)
(* Goal: shareTreeEq (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      intro G.
(* Goal: @eq t c c *)
      generalize (relativ_empty2 _ _ G); auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      simpl; intros; discriminate.
(* Goal: shareTreeEq (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      generalize (mkCanon_test _ (Leaf false) H9).
(* Goal: @eq t c c *)
      unfold shareTreeEq; intuition; apply relativ_cong; auto.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      rewrite H9.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: @eq t c c *)
      rewrite relativ_canon_commute; auto.
(* Goal: @eq t c c *)
      destruct a; auto.
(* Goal: @eq t c c *)
      destruct (nonEmpty_dec (intersect_tree (proj1_sig x) (proj1_sig y))); auto.
(* Goal: nonEmptyTree (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)) *)
      elim H6.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
(* Goal: @eq t s bot *)
(* Goal: @identity t Join_ba s *)
      symmetry.
(* Goal: @eq ShareTree (Leaf false) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
      apply (mkCanon_test2 (Leaf false)).
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
      split.
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
      apply falseLeaf_bottom.
(* Goal: @eq t c c *)
      apply emptyLeFalse; auto.
    Qed.

    Lemma rel_preserves_lub : forall a x y, rel a (lub x y) = lub (rel a x) (rel a y).
    Proof.
(* Goal: forall a x y : t, @eq t (rel a (lub x y)) (lub (rel a x) (rel a y)) *)
      intros a x y.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification a x); intuition.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
      rewrite H0.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
      rewrite H.
(* Goal: @eq t (lub bot (glb t3 (comp t2))) (glb t3 (comp t2)) *)
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
      rewrite lub_commute.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
      rewrite lub_bot.
(* Goal: @eq t (lub bot (glb t3 (comp t2))) (glb t3 (comp t2)) *)
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
      rewrite lub_commute.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
      rewrite lub_bot.
(* Goal: @eq t c c *)
      auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification a y); intuition.
(* Goal: @eq ShareTree (mkCanon (Leaf b0)) match mkCanon (Leaf b0) with | Leaf b1 => match mkCanon (Leaf b0) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) | Node s s0 => Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) end | Node s s0 => Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      rewrite H4.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
      rewrite H2.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
      rewrite lub_bot.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
      rewrite lub_bot.
(* Goal: @eq t c c *)
      auto.

(* Goal: @eq t (rel a (lub x y)) (lub (rel a x) (rel a y)) *)
      apply canonTree_eq.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
      rewrite H1.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
      rewrite H5.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (union_tree (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      rewrite <- relativ_union.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct (rel_classification a (lub x y)); intuition.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      rewrite H8.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      injection H6; intros.
(* Goal: @eq ShareTree (Leaf false) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
      apply (mkCanon_test2 (Leaf false)).
(* Goal: shareTreeEq (Leaf false) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      apply shareTreeEq_trans with (relativ_tree (proj1_sig a) (Leaf false)).
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
      split.
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
      apply falseLeaf_bottom.
(* Goal: shareTreeOrd (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false)) (Leaf false) *)
(* Goal: shareTreeEq (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      apply emptyLeFalse.
(* Goal: not (nonEmptyTree (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) *)
(* Goal: shareTreeEq (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      intro G.
(* Goal: False *)
(* Goal: shareTreeEq (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      generalize (relativ_empty2 _ _ G).
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      simpl; intros; discriminate.
(* Goal: shareTreeEq (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false)) (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      generalize (mkCanon_test _ (Leaf false) H9).
(* Goal: @eq t c c *)
      unfold shareTreeEq; intuition; apply relativ_cong; auto.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel a (lub x y))) (mkCanon (relativ_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)))) *)
      rewrite H9.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: @eq t c c *)
      rewrite relativ_canon_commute; auto.
(* Goal: @eq t c c *)
      destruct a; auto.
(* Goal: @eq t c c *)
      destruct (nonEmpty_dec (union_tree (proj1_sig x) (proj1_sig y))); intros; auto.
(* Goal: nonEmptyTree (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)) *)
      elim H6.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
(* Goal: @eq t s bot *)
(* Goal: @identity t Join_ba s *)
      symmetry.
(* Goal: @eq ShareTree (Leaf false) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
      apply (mkCanon_test2 (Leaf false)).
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
      split.
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
      apply falseLeaf_bottom.
(* Goal: @eq t c c *)
      apply emptyLeFalse; auto.
    Qed.

  (* Axioms about splittability. These follow easily from relativization.
   *)

    Definition leftTree : canonTree.
(* Goal: canonTree *)
      exists (Node (Leaf true) (Leaf false)).
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      simpl; intuition.
    Defined.

    Definition rightTree : canonTree.
(* Goal: canonTree *)
      exists (Node (Leaf false) (Leaf true)).
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      simpl; intuition.
    Defined.

    Definition split (x:canonTree) := (rel x leftTree, rel x rightTree).

    Lemma split_disjoint : forall x1 x2 x,
      split x = (x1, x2) -> glb x1 x2 = bot.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      unfold split; intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: @eq t (glb (rel x leftTree) (rel x rightTree)) bot *)
      rewrite <- rel_preserves_glb.
(* Goal: @eq t (rel x (glb leftTree rightTree)) bot *)
      replace (glb leftTree rightTree) with bot.
(* Goal: @eq t (rel x bot) bot *)
      apply rel_bot1.
(* Goal: @eq t c c *)
      apply canonTree_eq; simpl; auto.
    Qed.

    Lemma split_together : forall x1 x2 x,
      split x = (x1, x2) -> lub x1 x2 = x.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      unfold split; intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: @eq t (lub (rel x leftTree) (rel x rightTree)) x *)
      rewrite <- rel_preserves_lub.
(* Goal: @eq t (rel x (lub leftTree rightTree)) x *)
      replace (lub leftTree rightTree) with top.
(* Goal: @eq t (rel x top) x *)
(* Goal: @eq t top (lub leftTree rightTree) *)
      apply rel_top1.
(* Goal: @eq t c c *)
      apply canonTree_eq; simpl; auto.
    Qed.

    Lemma split_nontrivial : forall x1 x2 x,
      split x = (x1, x2) ->
        (x1 = bot \/ x2 = bot) ->
        x = bot.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      unfold split; intros.
(* Goal: @eq canonTree x bot *)
      inv H; destruct H0.
(* Goal: @eq t c c *)
      destruct (canonTree_eq_dec x bot); auto.
(* Goal: @eq canonTree x bot *)
      replace bot with (rel x bot) in H.
(* Goal: @eq t c c *)
      apply rel_inj_l in H; auto.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: @eq t (rel x bot) bot *)
      apply rel_bot1.
(* Goal: @eq t c c *)
      destruct (canonTree_eq_dec x bot); auto.
(* Goal: @eq canonTree x bot *)
      replace bot with (rel x bot) in H.
(* Goal: @eq t c c *)
      apply rel_inj_l in H; auto.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: @eq t (rel x bot) bot *)
      apply rel_bot1.
    Qed.

    (* Token Factory definitions and proofs.
       We specify token factories and tokens
       inductively on trees, which makes
       the proofs fairly straightforward.
     *)

    Inductive isTokenFactory' : ShareTree -> nat -> Prop :=
      | isTokFac_0 : isTokenFactory' (Leaf true) O
      | isTokFac_S_true : forall t n,
          isTokenFactory' t (S n) ->
          isTokenFactory' (Node (Leaf true) t) (S n)
      | isTokFac_S_false : forall t n,
          isTokenFactory' t n ->
          isTokenFactory' (Node (Leaf false) t) (S n).

    Inductive isToken' : ShareTree -> nat -> Prop :=
      | isTok_0 : isToken' (Leaf false) O
      | isTok_S_true : forall t n,
          isToken' t n ->
          isToken' (Node (Leaf true) t) (S n)
      | isTok_S_false : forall t n,
          isToken' t (S n) ->
          isToken' (Node (Leaf false) t) (S n).

    Definition isTokenFactory (x:t) (n:nat) := isTokenFactory' (proj1_sig x) n.
    Definition isToken (x:t) (n:nat) := isToken' (proj1_sig x) n.

    Lemma isTokenFactory_canon : forall n fac,
      isTokenFactory' fac n -> canonicalTree fac.
    Proof.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      intros n fac H; induction H; simpl; intuition.
(* Goal: @eq t c c *)
      right; destruct t0; simpl in *; auto.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      intuition.
(* Goal: @eq t c c *)
      right; destruct t0; simpl in *; auto.
(* Goal: @eq t c c *)
      inv H; auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      intuition.
    Qed.

    Lemma isToken_canon : forall n tok,
      isToken' tok n -> canonicalTree tok.
    Proof.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      intros n tok H; induction H; simpl; intuition.
(* Goal: @eq t c c *)
      right; destruct t0; simpl in *; auto.
(* Goal: @eq t c c *)
      inv H; auto.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      intuition.
(* Goal: @eq t c c *)
      right; destruct t0; simpl in *; auto.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      intuition.
    Qed.


    Fixpoint split_tok1 (n:nat) (x:ShareTree) {struct x} : ShareTree :=
      match x with
      | Node (Leaf true)  t2 =>
          match n with
          | O    => Node (Leaf true) (Leaf false)
          | S n' => Node (Leaf true) (split_tok1 n' t2)
          end
      | Node (Leaf false) t2 => Node (Leaf false) (split_tok1 n t2)
      | _ => Leaf false
      end.

    Fixpoint split_tok2 (n:nat) (x:ShareTree) {struct x} : ShareTree :=
      match x with
      | Node (Leaf true)  t2 =>
          match n with
          | O    => Node (Leaf false) t2
          | S n' => Node (Leaf false) (split_tok2 n' t2)
          end
      | Node (Leaf false) t2 => Node (Leaf false) (split_tok2 n t2)
      | _ => x
      end.

    Lemma split_tok_lub : forall tok n,
      shareTreeEq tok (union_tree (split_tok1 n tok) (split_tok2 n tok)).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      induction tok; simpl; intros.
(* Goal: @eq t c c *)
      destruct b; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct tok1; simpl.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      destruct b.
(* Goal: @eq t c c *)
      destruct n; simpl; auto.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: shareTreeEq (Node (Node fac1_1 fac1_2) fac2) (Node (Node fac1_1 fac1_2) fac2) *)
      apply shareTreeEq_refl.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: shareTreeEq (Node (Node fac1_1 fac1_2) fac2) (Node (Node fac1_1 fac1_2) fac2) *)
      apply shareTreeEq_refl.
(* Goal: shareTreeEq (Node (Node fac1_1 fac1_2) fac2) (Node (Node fac1_1 fac1_2) fac2) *)
      apply shareTreeEq_refl.
(* Goal: shareTreeEq (Node (Node fac1_1 fac1_2) fac2) (Node (Node fac1_1 fac1_2) fac2) *)
      apply shareTreeEq_refl.
    Qed.

    Lemma split_tok_glb : forall tok n,
      shareTreeOrd (intersect_tree (split_tok1 n tok) (split_tok2 n tok)) (Leaf false).
    Proof.
(* Goal: @eq t c c *)
      induction tok; simpl; intros; auto.
(* Goal: @eq t c c *)
      destruct tok1; simpl; auto.
(* Goal: @eq t c c *)
      destruct b; simpl; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct n; simpl.
(* Goal: @eq t c c *)
      constructor; auto.
(* Goal: @eq t c c *)
      constructor; auto.
    Qed.

    Lemma split_tok1_correct : forall tok n m,
      isToken' tok m ->
      gt m n ->
      isToken' (split_tok1 n tok) (S n).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros tok n m H; revert n; induction H; intros.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      inv H; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      destruct n0.
(* Goal: False *)
      inv H0.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: isToken' (split_tok1 n0 t0) (S n0) *)
      apply IHisToken'.
(* Goal: le (S O) (S n) *)
      omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: isToken' (split_tok1 n0 t0) (S n0) *)
      apply IHisToken'.
(* Goal: @eq t c c *)
      auto.
    Qed.

    Lemma split_tok2_correct : forall tok n m,
      isToken' tok m ->
      gt m n ->
      isToken' (mkCanon (split_tok2 n tok)) (m - (S n)).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros tok n m H; revert n; induction H; intros.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      destruct n0.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: isToken' match mkCanon t0 with | Leaf b2 => if if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (mkCanon t0) | Node s s0 => Node (Leaf false) (mkCanon t0) end (S (Init.Nat.add n O)) *)
(* Goal: isToken' (mkCanon (Node (Leaf true) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      replace (mkCanon t0) with t0.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      inv H; simpl.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t c c *)
      constructor; auto.
(* Goal: @eq t c c *)
      constructor; auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t c c *)
      constructor; auto.
(* Goal: @eq ShareTree t0 (mkCanon t0) *)
(* Goal: isToken' (mkCanon (Node (Leaf false) (split_tok2 n0 t0))) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      apply canonicalUnique.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply mkCanon_eq.
(* Goal: @eq t c c *)
      apply isToken_canon with n; auto.
(* Goal: canonicalTree (mkCanon t0) *)
(* Goal: isToken' (mkCanon (Node (Leaf false) (split_tok2 n0 t0))) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      apply mkCanon_correct.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      case_eq (mkCanon (split_tok2 n0 t0)); intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      destruct b.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
      elimtype False.
(* Goal: False *)
(* Goal: isToken' (Leaf false) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      clear - H H1.
(* Goal: False *)
(* Goal: isToken' (Leaf false) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      revert n0 H H1.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      induction t0; simpl; intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      discriminate.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      destruct n0.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
      simpl in H1.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      destruct (mkCanon t0_2); try discriminate.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      destruct b; discriminate.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
      simpl in H1.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      destruct (mkCanon (split_tok2 n0 t0_2)); try discriminate.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      destruct b; discriminate.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
      simpl in H1.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      destruct (mkCanon (split_tok2 n0 t0_2)); try discriminate.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      destruct b; discriminate.
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      specialize ( IHisToken' n0).
(* Goal: isToken' (Leaf false) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      spec IHisToken'; [ omega | ].
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      rewrite H1 in IHisToken'.
(* Goal: isToken' (Leaf false) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      inv IHisToken'.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      specialize ( IHisToken' n0).
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      spec IHisToken'.
(* Goal: le (S O) (S n) *)
      omega.
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (Init.Nat.sub n (S n0)) *)
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      rewrite H1 in IHisToken'.
(* Goal: isToken' (mkCanon (Node (Leaf false) (split_tok2 n0 t0))) (Init.Nat.sub (S n) (S n0)) *)
      inversion IHisToken'.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
      subst.
(* Goal: @eq t c c *)
      constructor; auto.
(* Goal: @eq t c c *)
      rewrite H5; auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t c c *)
      subst; rewrite H5; auto.
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      specialize ( IHisToken' n0 H0).
(* Goal: isToken' (mkCanon (split_tok2 n0 (Node (Leaf false) t0))) (Init.Nat.sub (S n) (S n0)) *)
      simpl split_tok2.
(* Goal: isToken' (mkCanon (Node (Leaf false) (split_tok2 n0 t0))) (Init.Nat.sub (S n) (S n0)) *)
      inversion IHisToken'.
(* Goal: isToken' (mkCanon (Node (Leaf false) (split_tok2 n0 t0))) (Init.Nat.sub (S n) (S n0)) *)
(* Goal: isToken' (mkCanon (Node (Leaf false) (split_tok2 n0 t0))) (Init.Nat.sub (S n) (S n0)) *)
(* Goal: isToken' (mkCanon (Node (Leaf false) (split_tok2 n0 t0))) (Init.Nat.sub (S n) (S n0)) *)
      simpl minus.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: @eq ShareTree (mkCanon (if b then Node (mkCanon t1_1) (mkCanon t1_2) else Leaf false)) match mkCanon (intersect_tree t1_1 t2_1) with | Leaf b1 => match mkCanon (intersect_tree t1_2 t2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      rewrite <- H2.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
      rewrite <- H3.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: @eq ShareTree (Node x1 x2) match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
      rewrite <- H1.
(* Goal: @eq ShareTree (mkCanon (if b then Node (mkCanon t1_1) (mkCanon t1_2) else Leaf false)) match mkCanon (intersect_tree t1_1 t2_1) with | Leaf b1 => match mkCanon (intersect_tree t1_2 t2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      rewrite <- H2.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
      rewrite H1.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
      rewrite H2.
(* Goal: @eq t c c *)
      auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: @eq ShareTree (Node x1 x2) match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
      rewrite <- H1.
(* Goal: @eq ShareTree (mkCanon (if b then Node (mkCanon t1_1) (mkCanon t1_2) else Leaf false)) match mkCanon (intersect_tree t1_1 t2_1) with | Leaf b1 => match mkCanon (intersect_tree t1_2 t2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      rewrite <- H2.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
      rewrite H1.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
      rewrite H2.
(* Goal: @eq t c c *)
      auto.
    Qed.

    Definition split_token (n:nat) (tok:t) : t * t :=
      match n with
      | O => (bot,tok)
      | S n' =>
        (exist (fun x => canonicalTree x) (mkCanon (split_tok1 n' (proj1_sig tok))) (mkCanon_correct _)
        ,exist (fun x => canonicalTree x) (mkCanon (split_tok2 n' (proj1_sig tok))) (mkCanon_correct _)
        )
      end.

    Lemma Eq_Ord : forall x y,
      shareTreeEq x y -> shareTreeOrd x y.
    Proof.
(* Goal: forall (x y : ShareTree) (_ : shareTreeEq x y), shareTreeOrd x y *)
      unfold shareTreeEq; intuition.
    Qed.

    Lemma split_token_correct : forall n1 n2 tok tok1 tok2,
      isToken tok (n1+n2) ->
      split_token n1 tok = (tok1,tok2) ->
        isToken tok1 n1 /\
        isToken tok2 n2 /\
        join tok1 tok2 tok.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros.
(* Goal: and (isToken tok1 n1) (and (isToken tok2 n2) (@join t Join_ba tok1 tok2 tok)) *)
      destruct tok as [tok Ht0].
(* Goal: and (isToken tok1 n1) (and (isToken tok2 n2) (@join t Join_ba tok1 tok2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0))) *)
      destruct tok1 as [tok1 Ht1].
(* Goal: and (isToken (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok1 Ht1) n1) (and (isToken tok2 n2) (@join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok1 Ht1) tok2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0))) *)
      destruct tok2 as [tok2 Ht2].
(* Goal: and (isToken (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok1 Ht1) n1) (and (isToken (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok2 Ht2) n2) (@join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok1 Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok2 Ht2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0))) *)
      unfold isToken in *.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
      simpl in *.
(* Goal: and (isToken' tok1 n1) (and (isToken' tok2 n2) (@join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok1 Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok2 Ht2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0))) *)
      unfold split_token in H0.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
      simpl in H0.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      destruct n1; inv H0; simpl; intuition.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      hnf; split; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      unfold glb; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      unfold BA.glb; simpl.
(* Goal: @eq t c c *)
      apply canonTree_eq; simpl; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      unfold lub; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      unfold BA.lub; simpl.
(* Goal: @eq t c c *)
      apply canonTree_eq; simpl; auto.
(* Goal: @eq t c c *)
      symmetry; apply canonicalUnique; auto.
(* Goal: isToken' (mkCanon (split_tok1 n1 tok)) (S n1) *)
(* Goal: isToken' (mkCanon (split_tok2 n1 tok)) n2 *)
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
      assert (isToken' (split_tok1 n1 tok) (S n1)).
(* Goal: @eq t c c *)
      eapply split_tok1_correct; eauto.
(* Goal: le (S O) (S n) *)
      omega.
      replace (mkCanon (split_tok1 n1 tok))
(* Goal: @eq t c c *)
        with (split_tok1 n1 tok); auto.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
(* Goal: @eq t c c *)
      eapply isToken_canon; eauto.
(* Goal: le (S O) (S n) *)
      replace n2 with ((S n1 + n2) - S n1)%nat by omega.
(* Goal: @eq t c c *)
      eapply split_tok2_correct; auto.
(* Goal: le (S O) (S n) *)
      omega.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
      hnf; simpl; split.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      unfold glb; unfold BA.glb; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))))) (Leaf false) *)
(* Goal: @eq t (lub (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))))) fac *)
      change (Leaf false) with (mkCanon (Leaf false)).
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon (create_tok1 n x0)) (mkCanon (create_tok2 n x0)))) (mkCanon x0) *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply mkCanon_test2.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
      split.
      apply shareTreeOrd_trans with
        (intersect_tree (split_tok1 n1 tok) (split_tok2 n1 tok)).
(* Goal: shareTreeOrd (intersect_tree (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (intersect_tree (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)) (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) *)
(* Goal: shareTreeOrd (intersect_tree (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)) (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (Leaf false) *)
(* Goal: @eq t (lub (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))))) fac *)
      apply Eq_Ord.
(* Goal: shareTreeEq (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) (intersect_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) *)
(* Goal: shareTreeOrd (intersect_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) (Leaf false) *)
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
      apply intersect_cong.
(* Goal: shareTreeEq (union_tree (create_tok1 n x0) (create_tok2 n x0)) x0 *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply shareTreeEq_sym.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply mkCanon_eq.
(* Goal: shareTreeEq (union_tree (create_tok1 n x0) (create_tok2 n x0)) x0 *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply shareTreeEq_sym.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply mkCanon_eq.
(* Goal: shareTreeOrd (intersect_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) (Leaf false) *)
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
      apply split_tok_glb.
(* Goal: shareTreeOrd (Leaf false) (intersect_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok1 n1 tok)) Ht1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (split_tok2 n1 tok)) Ht2)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) tok Ht0) *)
      apply falseLeaf_bottom.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok)))) tok *)
      pattern tok at 3.
(* Goal: (fun s : ShareTree => @eq ShareTree (mkCanon (union_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok)))) s) tok *)
      replace tok with (mkCanon tok).
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon (create_tok1 n x0)) (mkCanon (create_tok2 n x0)))) (mkCanon x0) *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply mkCanon_test2.
      apply shareTreeEq_trans with
        (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)).
(* Goal: shareTreeEq (union_tree (mkCanon (split_tok1 n1 tok)) (mkCanon (split_tok2 n1 tok))) (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply union_cong.
(* Goal: shareTreeEq (union_tree (create_tok1 n x0) (create_tok2 n x0)) x0 *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply shareTreeEq_sym.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply mkCanon_eq.
(* Goal: shareTreeEq (union_tree (create_tok1 n x0) (create_tok2 n x0)) x0 *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply shareTreeEq_sym.
(* Goal: shareTreeEq (split_tok2 n1 tok) (mkCanon (split_tok2 n1 tok)) *)
(* Goal: shareTreeEq (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) tok *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply mkCanon_eq.
(* Goal: shareTreeEq (union_tree (create_tok1 n x0) (create_tok2 n x0)) x0 *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply shareTreeEq_sym.
(* Goal: shareTreeEq tok (union_tree (split_tok1 n1 tok) (split_tok2 n1 tok)) *)
(* Goal: @eq ShareTree (mkCanon tok) tok *)
      apply split_tok_lub.
(* Goal: @eq t s bot *)
(* Goal: @identity t Join_ba s *)
      symmetry.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
    Qed.

    Fixpoint new_fac (n:nat) {struct n} : ShareTree :=
      match n with
      | O => Node (Leaf false) (Leaf true)
      | S n' => Node (Leaf false) (new_fac n')
      end.

    Fixpoint create_tok1 (n:nat) (x:ShareTree) {struct x} : ShareTree :=
      match x with
      | Node (Leaf true)  t2 =>
          match n with
          | O    => Node (Leaf false) t2
          | S n' => Node (Leaf false) (create_tok1 n' t2)
          end
      | Node (Leaf false) t2 => Node (Leaf false) (create_tok1 n t2)
      | Leaf true => new_fac n
      | _  => x
      end.

    Fixpoint create_tok2 (n:nat) (x:ShareTree) {struct x} : ShareTree :=
      match x with
      | Node (Leaf true)  t2 =>
          match n with
          | O    => Node (Leaf true) (Leaf false)
          | S n' => Node (Leaf true) (create_tok2 n' t2)
          end
      | Node (Leaf false) t2 => Node (Leaf false) (create_tok2 n t2)
      | Leaf true => comp_tree (new_fac n)
      | _ => Leaf false
      end.

    Lemma create_tok1_correct : forall fac m n,
      isTokenFactory' fac n ->
      isTokenFactory' (create_tok1 m fac) (S m + n).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      induction fac; simpl; intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      induction m; simpl.
(* Goal: canonicalTree (Leaf b) *)
      constructor; constructor.
(* Goal: @eq t c c *)
      constructor; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      inv H; simpl.
(* Goal: isToken' match m with | O => Node (Leaf true) (Leaf false) | S n' => Node (Leaf true) (create_tok2 n' fac2) end (S m) *)
(* Goal: isToken' (Node (Leaf false) (create_tok2 m fac2)) (S m) *)
      destruct m.
(* Goal: @eq t c c *)
      constructor; simpl; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      constructor; simpl.
(* Goal: @eq t c c *)
      apply (IHfac2 m) in H3; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      constructor; simpl.
(* Goal: @eq t c c *)
      apply (IHfac2 m) in H3; auto.
(* Goal: @eq t c c *)
      replace (m + S n0)%nat with (S m + n0)%nat by omega; auto.
    Qed.

    Lemma create_tok2_correct : forall fac m n,
      isTokenFactory' fac n ->
      isToken' (create_tok2 m fac) (S m).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      induction fac; intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: @eq t c c *)
      induction m; simpl; auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor; constructor.
(* Goal: @eq t c c *)
      constructor; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      inv H; simpl.
(* Goal: isToken' match m with | O => Node (Leaf true) (Leaf false) | S n' => Node (Leaf true) (create_tok2 n' fac2) end (S m) *)
(* Goal: isToken' (Node (Leaf false) (create_tok2 m fac2)) (S m) *)
      destruct m.
(* Goal: canonicalTree (Leaf b) *)
      constructor; constructor.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t c c *)
      apply (IHfac2 m) in H3; auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t c c *)
      apply (IHfac2 m) in H3; auto.
    Qed.

    Lemma create_tok_lub : forall fac n,
      shareTreeEq fac (union_tree (create_tok1 n fac) (create_tok2 n fac)).
    Proof.
(* Goal: @eq t c c *)
      induction fac; simpl; intros; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      induction n; simpl.
(* Goal: @eq t c c *)
      destruct b; simpl; auto.
(* Goal: @eq t c c *)
      destruct b; simpl; auto.
(* Goal: shareTreeEq (Leaf true) (Node (Leaf true) (union_tree (new_fac n) (comp_tree (new_fac n)))) *)
(* Goal: shareTreeEq (Node fac1 fac2) (union_tree match fac1 with | Leaf (true as b) => match n with | O => Node (Leaf false) fac2 | S n' => Node (Leaf false) (create_tok1 n' fac2) end | Leaf (false as b) => Node (Leaf false) (create_tok1 n fac2) | Node s s0 => Node fac1 fac2 end match fac1 with | Leaf (true as b) => match n with | O => Node (Leaf true) (Leaf false) | S n' => Node (Leaf true) (create_tok2 n' fac2) end | Leaf (false as b) => Node (Leaf false) (create_tok2 n fac2) | Node s s0 => Leaf false end) *)
      apply shareTreeEq_trans with (Node (Leaf true) (Leaf true)).
(* Goal: @eq t c c *)
      split; do 3 constructor; auto.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct fac1; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct b; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct n; simpl.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: @eq t c c *)
      rewrite union_commute; simpl; auto.
(* Goal: shareTreeEq (Node (Node fac1_1 fac1_2) fac2) (Node (Node fac1_1 fac1_2) fac2) *)
      apply shareTreeEq_refl.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: shareTreeEq (Node (Node fac1_1 fac1_2) fac2) (Node (Node fac1_1 fac1_2) fac2) *)
      apply shareTreeEq_refl.
    Qed.

    Lemma create_tok_glb : forall fac n,
      shareTreeOrd (intersect_tree (create_tok1 n fac) (create_tok2 n fac)) (Leaf false).
    Proof.
(* Goal: @eq t c c *)
      induction fac; simpl; intros; auto.
(* Goal: @eq t c c *)
      destruct b; simpl; auto.
(* Goal: @eq t c c *)
      induction n; simpl; auto.
(* Goal: @eq t c c *)
      destruct fac1; simpl; auto.
(* Goal: @eq t c c *)
      destruct b; simpl; auto.
(* Goal: @eq t c c *)
      destruct n; simpl; auto.
(* Goal: @eq t c c *)
      do 2 constructor; auto.
(* Goal: @eq t c c *)
      rewrite intersect_commute; simpl; auto.
    Qed.

    Definition create_token (n:nat) (fac:t) : t*t :=
      match n with
      | O => (fac,bot)
      | S n' =>
         (exist (fun x => canonicalTree x) (mkCanon (create_tok1 n' (proj1_sig fac))) (mkCanon_correct _),
          exist (fun x => canonicalTree x) (mkCanon (create_tok2 n' (proj1_sig fac))) (mkCanon_correct _))
      end.

    Lemma create_token_correct : forall fac fac' tok x n,
      create_token n fac = (fac',tok) ->
      isTokenFactory fac x ->
         isTokenFactory fac' (n+x) /\
        isToken tok n /\
        join fac' tok fac.
    Proof.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      intros; destruct n; simpl in H; inv H; simpl; intuition.
(* Goal: canonicalTree (Leaf b) *)
      hnf; constructor.
(* Goal: @join t Join_ba fac' bot fac' *)
(* Goal: isTokenFactory (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (S (Init.Nat.add n x)) *)
(* Goal: isToken (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (S n) *)
(* Goal: @join t Join_ba (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) fac *)
      split; [ apply glb_bot | apply lub_bot ].
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      hnf; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct fac as [fac H]; simpl.
(* Goal: isTokenFactory' (mkCanon (create_tok1 n fac)) (S (Init.Nat.add n x)) *)
(* Goal: isToken (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (S n) *)
(* Goal: @join t Join_ba (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) fac *)
      assert (isTokenFactory' (create_tok1 n fac) (S (n+x))).
(* Goal: @eq t c c *)
      apply create_tok1_correct; auto.
(* Goal: @eq t c c *)
      replace (mkCanon (create_tok1 n fac)) with (create_tok1 n fac); auto.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
(* Goal: @eq t c c *)
      eapply isTokenFactory_canon; eauto.
(* Goal: isToken (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (S n) *)
(* Goal: @join t Join_ba (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) fac *)
      hnf.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct fac as [fac H]; simpl.
(* Goal: isToken' (mkCanon (create_tok2 n fac)) (S n) *)
(* Goal: @join t Join_ba (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) fac *)
      assert (isToken' (create_tok2 n fac) (S n)).
(* Goal: @eq t c c *)
      eapply create_tok2_correct; eauto.
(* Goal: @eq t c c *)
      replace (mkCanon (create_tok2 n fac)) with (create_tok2 n fac); auto.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
(* Goal: @eq t c c *)
      eapply isToken_canon; eauto.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
      split.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))))) (Leaf false) *)
(* Goal: @eq t (lub (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))))) fac *)
      change (Leaf false) with (mkCanon (Leaf false)).
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon (create_tok1 n x0)) (mkCanon (create_tok2 n x0)))) (mkCanon x0) *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply mkCanon_test2.
(* Goal: @eq t c c *)
      split; auto.
      apply shareTreeOrd_trans with
        (intersect_tree (create_tok1 n (proj1_sig fac))
          (create_tok2 n (proj1_sig fac))).
(* Goal: shareTreeOrd (intersect_tree (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (intersect_tree (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)) (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) *)
(* Goal: shareTreeOrd (intersect_tree (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)) (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (Leaf false) *)
(* Goal: @eq t (lub (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))))) fac *)
      apply Eq_Ord.
(* Goal: @eq t c c *)
      apply intersect_cong; apply shareTreeEq_sym; auto.
(* Goal: shareTreeOrd (intersect_tree (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)) (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (Leaf false) *)
(* Goal: @eq t (lub (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok1 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac)))) (@exist ShareTree (fun x : ShareTree => canonicalTree x) (mkCanon (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))) (mkCanon_correct (create_tok2 n (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) fac))))) fac *)
      apply create_tok_glb.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      apply canonTree_eq; simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      destruct fac; simpl.
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon (create_tok1 n x0)) (mkCanon (create_tok2 n x0)))) x0 *)
      pattern x0 at 3.
(* Goal: (fun s : ShareTree => @eq ShareTree (mkCanon (union_tree (mkCanon (create_tok1 n x0)) (mkCanon (create_tok2 n x0)))) s) x0 *)
      replace x0 with (mkCanon x0).
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon (create_tok1 n x0)) (mkCanon (create_tok2 n x0)))) (mkCanon x0) *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply mkCanon_test2.
      apply shareTreeEq_trans with
        (union_tree (create_tok1 n x0) (create_tok2 n x0)).
(* Goal: @eq t c c *)
      apply union_cong; apply shareTreeEq_sym; auto.
(* Goal: shareTreeEq (union_tree (create_tok1 n x0) (create_tok2 n x0)) x0 *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply shareTreeEq_sym.
(* Goal: shareTreeEq x0 (union_tree (create_tok1 n x0) (create_tok2 n x0)) *)
(* Goal: @eq ShareTree (mkCanon x0) x0 *)
      apply create_tok_lub.
(* Goal: @eq t s bot *)
(* Goal: @identity t Join_ba s *)
      symmetry.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
    Qed.

    Local Open Scope nat_scope.

    Lemma fac_tok_classification : forall fac n,
      isTokenFactory' fac n ->
      forall tok m,
        isToken' tok m ->
        shareTreeOrd (intersect_tree fac tok) (Leaf false) ->
         ( n = m -> shareTreeEq (union_tree tok fac) (Leaf true)) /\
         ( n < m -> False ) /\
         ( n > m -> shareTreeEq (union_tree tok fac) (Leaf true) -> False).
    Proof.
(* Goal: or (nonEmptyTree t0_1) (nonEmptyTree t0_2) *)
      intros fac n H; induction H; simpl; intuition.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      subst m; inv H.
(* Goal: @eq t c c *)
      simpl; auto.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
      inv H1.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      invert_ord; discriminate.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      invert_ord.
(* Goal: False *)
(* Goal: shareTreeEq (union_tree tok (Node (Leaf true) t0)) (Leaf true) *)
(* Goal: False *)
(* Goal: False *)
(* Goal: shareTreeEq (union_tree tok (Node (Leaf false) t0)) (Leaf true) *)
(* Goal: False *)
(* Goal: False *)
      clear -H2 H7.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      revert n H2 H7; induction t0; simpl; intros.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
      inv H2.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
      inv H2.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      invert_ord; discriminate.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      invert_ord.
(* Goal: @eq t c c *)
      eapply IHt0_2; eauto.
(* Goal: shareTreeEq (union_tree tok (Node (Leaf false) t0)) (Leaf true) *)
(* Goal: False *)
(* Goal: False *)
      subst m.
(* Goal: False *)
      inv H0.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      invert_ord; discriminate.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      invert_ord.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
      destruct (IHisTokenFactory' _ _ H4 H7)
        as [? [? ?]].
(* Goal: @eq t c c *)
      apply shareTreeEq_trans with (Node (Leaf true) (Leaf true)); auto.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: False *)
      inv H0.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
      inv H2.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      invert_ord; discriminate.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      invert_ord.
      destruct (IHisTokenFactory' _ _ H3 H8)
        as [? [? ?]].
(* Goal: @eq t c c *)
      apply H1; auto.
(* Goal: False *)
(* Goal: shareTreeEq (union_tree tok (Node (Leaf false) t0)) (Leaf true) *)
(* Goal: False *)
(* Goal: False *)
      rewrite union_commute in H3.
(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
      simpl in H3.
      destruct tok; try destruct b;
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
        invert_ord; try discriminate.
(* Goal: False *)
      inv H0.
(* Goal: False *)
(* Goal: False *)
(* Goal: shareTreeEq (union_tree tok (Node (Leaf false) t0)) (Leaf true) *)
(* Goal: False *)
(* Goal: False *)
      clear -H H11.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      revert n H H11; induction t0; simpl; intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: @eq t c c *)
      inv H; invert_ord; eauto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      discriminate.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      inv H0; invert_ord; try discriminate.
      destruct (IHisTokenFactory' _ _ H7 H10)
        as [? [? ?]].
(* Goal: @eq t c c *)
      apply H6; auto.
(* Goal: @eq t c c *)
      split; auto.
(* Goal: @eq t c c *)
      rewrite union_commute; auto.
(* Goal: shareTreeEq (union_tree tok (Node (Leaf false) t0)) (Leaf true) *)
(* Goal: False *)
(* Goal: False *)
      subst m.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      inv H0; invert_ord; try discriminate.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
      destruct (IHisTokenFactory' _ _ H4 H7)
        as [? [? ?]].
(* Goal: @eq t c c *)
      apply shareTreeEq_trans with (Node (Leaf true) (Leaf true)); auto.
(* Goal: @eq t c c *)
      apply Node_Eq; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
      destruct(IHisTokenFactory' _ _ H4 H7)
        as [? [? ?]].
(* Goal: @eq t c c *)
      elim H1; auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      destruct tok; try destruct b; invert_ord; try discriminate.
(* Goal: False *)
      inv H0.
(* Goal: False *)
      inv H0.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
      inv H2.
(* Goal: False *)
      inv H0.
      destruct (IHisTokenFactory' _ _ H6 H8)
        as [? [? ?]].
(* Goal: le (S O) (S n) *)
      elim H1; omega.
      destruct (IHisTokenFactory' _ _ H6 H8)
        as [? [? ?]].
(* Goal: le (S O) (S n) *)
      elim H1; omega.
(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
      rewrite union_commute in H3; simpl in H3.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      inv H0; invert_ord; try discriminate.
      destruct (IHisTokenFactory' _ _ H4 H10)
        as [? [? ?]].
(* Goal: False *)
      elim H7; [omega |].
(* Goal: @eq t c c *)
      rewrite union_commute; auto.
    Qed.

    Lemma token_nonbot : forall tok n,
      isToken' tok n ->
      n > 0 ->
      shareTreeOrd tok (Leaf false) ->
      False.
    Proof.
      intros tok n H; induction H; intros;
(* Goal: @eq t c c *)
        invert_ord; try discriminate; eauto.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
    Qed.

    Lemma tokens_nonfull : forall tok1 n,
      isToken' tok1 n ->
      forall tok2 m,
        isToken' tok2 m ->
        shareTreeOrd (Leaf true) (union_tree tok1 tok2) ->
        False.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros tok1 n H; induction H; simpl; intros.
(* Goal: @eq t c c *)
      induction H; invert_ord; try discriminate; auto.
(* Goal: @eq t c c *)
      inv H0; invert_ord; eauto.
(* Goal: False *)
      clear -H H6.
(* Goal: @eq t c c *)
      induction H; invert_ord; try discriminate; auto.
(* Goal: @eq t c c *)
      inv H0; invert_ord; eauto.
(* Goal: False *)
      clear -H H6.
(* Goal: @eq t c c *)
      induction H; invert_ord; try discriminate; auto.
    Qed.

    Lemma tokenFactory_nonbot : forall fac n,
      isTokenFactory' fac n ->
      shareTreeOrd fac (Leaf false) ->
      False.
    Proof.
      intros fac n H; induction H; intros;
(* Goal: @eq t c c *)
        invert_ord; try discriminate; eauto.
    Qed.

    Lemma absorbToken : forall fac fac' tok x n,
      isTokenFactory fac' (n+x) ->
      isToken tok n ->
      join fac' tok fac ->
      isTokenFactory fac x.
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros.
(* Goal: isTokenFactory fac x *)
      destruct fac as [fac ?].
(* Goal: isTokenFactory (@exist ShareTree (fun t : ShareTree => canonicalTree t) fac c) x *)
      destruct fac' as [fac' ?].
(* Goal: isTokenFactory (@exist ShareTree (fun t : ShareTree => canonicalTree t) fac c) x *)
      destruct tok as [tok ?].
(* Goal: isTokenFactory (@exist ShareTree (fun t : ShareTree => canonicalTree t) fac c) x *)
      unfold isToken, isTokenFactory in *.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
      simpl in *.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
      destruct H1; simpl in *.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
      inv H1.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
      inv H2.
(* Goal: isToken' (mkCanon (union_tree tok1 tok2)) (Init.Nat.add n1 n2) *)
      clear c c0 c1.
(* Goal: isTokenFactory' (mkCanon (union_tree fac' tok)) x *)
      assert (shareTreeOrd (intersect_tree fac' tok) (Leaf false)).
(* Goal: shareTreeOrd (intersect_tree fac' tok) (Leaf false) *)
(* Goal: isTokenFactory' (mkCanon (union_tree fac' tok)) x *)
      rewrite <- H4.
(* Goal: @eq t c c *)
      apply Eq_Ord; auto.
(* Goal: isTokenFactory' (mkCanon (union_tree fac' tok)) x *)
      clear H4.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      revert tok x n H H0 H1; induction fac'; simpl; intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: le (S O) (S n) *)
      replace x with O by omega.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: False *)
      inv H0.
      replace (mkCanon (Node fac'1 fac'2)) with
(* Goal: @eq t c c *)
        (Node fac'1 fac'2); auto.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
(* Goal: @eq t c c *)
      eapply isTokenFactory_canon; eauto.
(* Goal: isTokenFactory' (mkCanon (Node (union_tree fac'1 (Leaf false)) (union_tree fac'2 t0))) x *)
      rewrite intersect_commute in H1.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
      simpl in H1.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      invert_ord; discriminate.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      case_eq (mkCanon (union_tree fac'2 t0)); intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      destruct b.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      invert_ord.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
      destruct x.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
      destruct (fac_tok_classification fac'2 (n0+S x)) with t0 n0
(* Goal: @eq t c c *)
        as [? [? ?]]; auto.
(* Goal: isTokenFactory' (Leaf true) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf true) (Leaf false)) x *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) x *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      elim H5; [omega|].
(* Goal: @eq t c c *)
      apply mkCanon_test; simpl; auto.
(* Goal: @eq t c c *)
      rewrite union_commute; auto.
(* Goal: isTokenFactory' (Leaf false) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf false) (Node s s0)) (S x) *)
      change (Leaf false) with (mkCanon (Leaf false)) in H.
(* Goal: isTokenFactory' (Leaf false) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf false) (Node s s0)) (S x) *)
      apply mkCanon_test in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
      destruct H.
(* Goal: isTokenFactory' (Leaf false) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf false) (Node s s0)) (S x) *)
      assert (shareTreeOrd fac'2 (Leaf false)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (union_tree fac'2 t0); auto.
(* Goal: shareTreeOrd t1 (union_tree t1 t0) *)
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      apply union_upper_bound.
(* Goal: @eq t c c *)
      elim (tokenFactory_nonbot fac'2 (n0+x)); auto.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
      destruct x.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
      elimtype False.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      invert_ord.
      destruct (fac_tok_classification fac'2 (n0+0)) with t0 n0
(* Goal: @eq t c c *)
        as [? [? ?]]; auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      spec H0; [ omega |].
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      apply mkCanon_test2 in H0.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree fac'1 (Leaf false)) (union_tree fac'2 t0))) x *)
      rewrite union_commute in H0.
(* Goal: le (tree_heightP t') (tree_heightP (Leaf b)) *)
(* Goal: le (tree_heightP t') (tree_heightP (Node t0_1 t0_2)) *)
      rewrite H in H0.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      discriminate.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq ShareTree (Leaf b) match mkCanon t'2 with | Leaf b1 => match mkCanon t'2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t'2) (mkCanon t'2) | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Leaf b)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
      rewrite <- H.
(* Goal: @eq t c c *)
      eapply IHfac'2; eauto.
(* Goal: @eq t c c *)
      invert_ord; auto.
(* Goal: isTokenFactory' (mkCanon (Node (union_tree fac'1 (Leaf false)) (union_tree fac'2 t0))) x *)
      rewrite intersect_commute in H1.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
      simpl in H1.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      invert_ord.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      case_eq (mkCanon (union_tree fac'2 t0)); intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      destruct b.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
      destruct x.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
      destruct (fac_tok_classification fac'2 (S (n0+S x))) with t0 (S n0)
(* Goal: @eq t c c *)
        as [? [? ?]]; auto.
(* Goal: isTokenFactory' (Leaf true) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf true) (Leaf false)) x *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) x *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      elim H5; [ omega |].
(* Goal: shareTreeEq (union_tree t0 fac'2) (Leaf true) *)
(* Goal: isTokenFactory' (Node (Leaf true) (Leaf false)) x *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) x *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      apply mkCanon_test.
(* Goal: @eq ShareTree (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b) (Leaf false))) (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)) *)
      rewrite union_commute.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
      rewrite H.
(* Goal: @eq t c c *)
      auto.
(* Goal: isTokenFactory' (Leaf false) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf false) (Node s s0)) (S x) *)
      change (Leaf false) with (mkCanon (Leaf false)) in H.
(* Goal: isTokenFactory' (Leaf false) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf false) (Node s s0)) (S x) *)
      apply mkCanon_test in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
      destruct H.
(* Goal: isTokenFactory' (Leaf false) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf false) (Node s s0)) (S x) *)
      assert (shareTreeOrd fac'2 (Leaf false)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (union_tree fac'2 t0); auto.
(* Goal: shareTreeOrd t1 (union_tree t1 t0) *)
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      apply union_upper_bound.
(* Goal: @eq t c c *)
      elim (tokenFactory_nonbot fac'2 (S (n0+x))); auto.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
      destruct x.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
      elimtype False.
      destruct (fac_tok_classification fac'2 (S (n0 + 0))) with t0 (S n0)
(* Goal: @eq t c c *)
        as [? [? ?]]; auto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      spec H0; [ omega |].
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      apply mkCanon_test2 in H0.
(* Goal: le (tree_heightP t') (tree_heightP (Leaf b)) *)
(* Goal: le (tree_heightP t') (tree_heightP (Node t0_1 t0_2)) *)
      rewrite union_commute in H0; rewrite H in H0.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      discriminate.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq ShareTree (Leaf b) match mkCanon t'2 with | Leaf b1 => match mkCanon t'2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t'2) (mkCanon t'2) | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Leaf b)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
      rewrite <- H.
(* Goal: @eq t c c *)
      eapply IHfac'2; eauto.
(* Goal: @eq t c c *)
      invert_ord; auto.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
      destruct x.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
      elimtype False.
      destruct (fac_tok_classification fac'2 (n0 + 0)) with t0 (S n0)
(* Goal: @eq t c c *)
        as [? [? ?]]; auto.
(* Goal: le (S O) (S n) *)
      elim H0; omega.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      case_eq (mkCanon (union_tree fac'2 t0)); intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      destruct b.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq ShareTree (Leaf b) match mkCanon t'2 with | Leaf b1 => match mkCanon t'2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t'2) (mkCanon t'2) | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Leaf b)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
      rewrite <- H.
(* Goal: @eq t c c *)
      eapply IHfac'2; eauto.
(* Goal: @eq t c c *)
      replace (S n0 + x) with (n0 + S x) by omega; auto.
(* Goal: isTokenFactory' (Leaf false) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf false) (Node s s0)) (S x) *)
      change (Leaf false) with (mkCanon (Leaf false)) in H.
(* Goal: isTokenFactory' (Leaf false) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf false) (Node s s0)) (S x) *)
      apply mkCanon_test in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
      destruct H.
(* Goal: isTokenFactory' (Leaf false) (S x) *)
(* Goal: isTokenFactory' (Node (Leaf false) (Node s s0)) (S x) *)
      assert (shareTreeOrd fac'2 (Leaf false)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (union_tree fac'2 t0); auto.
(* Goal: shareTreeOrd t1 (union_tree t1 t0) *)
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      apply union_upper_bound.
(* Goal: @eq t c c *)
      elim (tokenFactory_nonbot fac'2 (n0 + S x)); auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq ShareTree (Leaf b) match mkCanon t'2 with | Leaf b1 => match mkCanon t'2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t'2) (mkCanon t'2) | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Leaf b)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
      rewrite <- H.
(* Goal: @eq t c c *)
      eapply IHfac'2; eauto.
(* Goal: @eq t c c *)
      replace (S n0 + x) with (n0 + S x) by omega; auto.
    Qed.

    Lemma mergeToken : forall tok1 n1 tok2 n2 tok',
      isToken tok1 n1 ->
      isToken tok2 n2 ->
      join tok1 tok2 tok' ->
      isToken tok' (n1+n2).
    Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      intros.
(* Goal: isToken tok' (Init.Nat.add n1 n2) *)
      destruct tok1 as [tok1 ?].
(* Goal: isToken tok' (Init.Nat.add n1 n2) *)
      destruct tok2 as [tok2 ?].
(* Goal: isToken tok' (Init.Nat.add n1 n2) *)
      destruct tok' as [tok' ?].
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
      unfold isToken in *; simpl in *.
(* Goal: lt (tree_height t') (S n) *)
      destruct H1.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
      inv H1; inv H2.
(* Goal: isToken' (mkCanon (union_tree tok1 tok2)) (Init.Nat.add n1 n2) *)
      clear c c0 c1.
(* Goal: isToken' (mkCanon (union_tree tok1 tok2)) (Init.Nat.add n1 n2) *)
      change (Leaf false) with (mkCanon (Leaf false)) in H4.
(* Goal: isToken' (mkCanon (union_tree tok1 tok2)) (Init.Nat.add n1 n2) *)
      apply mkCanon_test in H4.
(* Goal: isToken' (mkCanon (union_tree tok1 tok2)) (Init.Nat.add n1 n2) *)
      destruct H4.
(* Goal: isToken' (mkCanon (union_tree tok1 tok2)) (Init.Nat.add n1 n2) *)
      clear H2.
(* Goal: isToken' (mkCanon (union_tree tok1 tok2)) (Init.Nat.add n1 n2) *)
      revert tok2 n2 H0 H1.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      induction H; simpl; intros; invert_ord.
(* Goal: @eq t c c *)
      replace (mkCanon tok2) with tok2; auto.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
(* Goal: @eq t c c *)
      eapply isToken_canon; eauto.
(* Goal: False *)
(* Goal: isTokenFactory' (Node (Leaf true) (Node s s0)) (S x) *)
(* Goal: isTokenFactory' (mkCanon (Node (union_tree (Leaf false) (Leaf false)) (union_tree fac'2 t0))) x *)
      induction H0; simpl; intros; invert_ord; try discriminate.
(* Goal: isToken' match mkCanon t0 with | Leaf b2 => if if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (mkCanon t0) | Node s s0 => Node (Leaf false) (mkCanon t0) end (S (Init.Nat.add n O)) *)
(* Goal: isToken' (mkCanon (Node (Leaf true) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      replace (mkCanon t0) with t0.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      inv H; simpl.
(* Goal: canonicalTree (Leaf b) *)
      do 2 constructor.
(* Goal: canonicalTree (Leaf b) *)
      do 2 constructor.
(* Goal: @eq t c c *)
      replace (n0+0) with n0 by omega; auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t c c *)
      replace (n0+0) with n0 by omega; auto.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
(* Goal: @eq t c c *)
      eapply isToken_canon; eauto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      case_eq (mkCanon (union_tree t0 t1)); intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      destruct b.
(* Goal: isToken' (Leaf true) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      change (Leaf true) with (mkCanon (Leaf true)) in H1.
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      apply mkCanon_test in H1.
(* Goal: lt (tree_height t') (S n) *)
      destruct H1.
(* Goal: @eq t c c *)
      elim (tokens_nonfull _ _ H _ _ H0); auto.
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      change (Leaf false) with (mkCanon (Leaf false)) in H1.
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      apply mkCanon_test in H1.
(* Goal: lt (tree_height t') (S n) *)
      destruct H1.
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      assert (shareTreeOrd t1 (Leaf false)).
(* Goal: @eq t c c *)
      apply shareTreeOrd_trans with (union_tree t0 t1); auto.
(* Goal: @eq ShareTree (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b) (Leaf false))) (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)) *)
      rewrite union_commute.
(* Goal: shareTreeOrd t1 (union_tree t1 t0) *)
(* Goal: isToken' (Node (Leaf true) (Leaf false)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf true) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon match tok2 with | Leaf (true as b) => Leaf true | Leaf (false as b) => Node (Leaf false) t0 | Node l2 r2 => Node l2 (union_tree t0 r2) end) (S (Init.Nat.add n n2)) *)
      apply union_upper_bound.
(* Goal: @eq t c c *)
      elim (token_nonbot t1 (S n0)); auto.
(* Goal: le (S O) (S n) *)
      omega.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq ShareTree (Node x1 x2) match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
      rewrite <- H1.
(* Goal: @eq t c c *)
      apply IHisToken'; auto.
(* Goal: False *)
      inv H0.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: isToken' match mkCanon t0 with | Leaf b2 => if if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (mkCanon t0) | Node s s0 => Node (Leaf false) (mkCanon t0) end (S (Init.Nat.add n O)) *)
(* Goal: isToken' (mkCanon (Node (Leaf true) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      replace (mkCanon t0) with t0.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
(* Goal: canonicalTree (Leaf b) *)
      do 2 constructor.
(* Goal: @eq t c c *)
      replace (n+0) with n by omega; auto.
(* Goal: canonicalTree (Leaf b) *)
      do 2 constructor.
(* Goal: @eq t c c *)
      replace (n+0) with n by omega; auto.
(* Goal: @eq t c c *)
      apply canonicalUnique; auto.
(* Goal: @eq t c c *)
      eapply isToken_canon; eauto.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      invert_ord.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      case_eq (mkCanon (union_tree t0 t1)); intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      destruct b.
(* Goal: isToken' (Node (Leaf false) (Leaf true)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Leaf false) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      change (Leaf true) with (mkCanon (Leaf true)) in H0.
(* Goal: isToken' (Node (Leaf false) (Leaf true)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Leaf false) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      apply mkCanon_test in H0.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
      destruct H0.
(* Goal: @eq t c c *)
      elim (tokens_nonfull _ _ H _ _ H2); auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t (glb t1 t2) t2 *)
      rewrite <- H0.
(* Goal: le (S O) (S n) *)
      replace (n + S n0) with (S n + n0) by omega.
(* Goal: @eq t c c *)
      apply IHisToken'; auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t (glb t1 t2) t2 *)
      rewrite <- H0.
(* Goal: le (S O) (S n) *)
      replace (n + S n0) with (S n + n0) by omega.
(* Goal: @eq t c c *)
      apply IHisToken'; auto.
(* Goal: isToken' (mkCanon (Node (Leaf false) (union_tree t0 t1))) (S (Init.Nat.add n (S n0))) *)
      invert_ord.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      case_eq (mkCanon (union_tree t0 t1)); intros.
(* Goal: isToken' (if if b as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (Leaf b)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      destruct b.
(* Goal: isToken' (Node (Leaf false) (Leaf true)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Leaf false) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      change (Leaf true) with (mkCanon (Leaf true)) in H0.
(* Goal: isToken' (Node (Leaf false) (Leaf true)) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Leaf false) (S (Init.Nat.add n (S n0))) *)
(* Goal: isToken' (Node (Leaf false) (Node s s0)) (S (Init.Nat.add n (S n0))) *)
      apply mkCanon_test in H0.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
      destruct H0.
(* Goal: @eq t c c *)
      elim (tokens_nonfull _ _ H _ _ H2); auto.
(* Goal: @eq t (glb t1 t2) t2 *)
      rewrite <- H0.
(* Goal: @eq t c c *)
      apply IHisToken'; auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
(* Goal: @eq t (glb t1 t2) t2 *)
      rewrite <- H0.
(* Goal: @eq t c c *)
      apply IHisToken'; auto.
    Qed.

    Lemma factoryOverlap : forall f1 f2 n1 n2,
      isTokenFactory f1 n1 -> isTokenFactory f2 n2 -> glb f1 f2 <> bot.
    Proof.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      repeat intro.
(* Goal: False *)
      destruct f1 as [f1 ?].
(* Goal: False *)
      destruct f2 as [f2 ?].
(* Goal: False *)
      inv H1; hnf in H, H0.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
      simpl in *.
(* Goal: False *)
      change (Leaf false) with (mkCanon (Leaf false)) in H3.
(* Goal: False *)
      apply mkCanon_test in H3.
(* Goal: False *)
      destruct H3.
(* Goal: False *)
      clear c c0 H2.
(* Goal: False *)
      revert f2 n2 H0 H1.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
      induction H; simpl; intros.
(* Goal: @eq t c c *)
      induction H0; simpl; invert_ord; try discriminate; auto.
(* Goal: @eq t c c *)
      inv H0; invert_ord; try discriminate; eauto.
(* Goal: @eq t c c *)
      inv H0; invert_ord; try discriminate; eauto.
(* Goal: False *)
      clear -H H6.
(* Goal: @eq t c c *)
      induction H; simpl; invert_ord; try discriminate; auto.
    Qed.

    Lemma fullFactory : forall x, isTokenFactory x 0 <-> x = top.
    Proof.
(* Goal: forall x : t, iff (isToken x O) (@eq t x bot) *)
      intros [x ?].
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      unfold isTokenFactory; simpl.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      split; intro H; inv H.
(* Goal: @eq t c c *)
      apply canonTree_eq; auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
    Qed.

    Lemma identityToken : forall x, isToken x 0 <-> x = bot.
    Proof.
(* Goal: forall x : t, iff (isToken x O) (@eq t x bot) *)
      intros [x ?].
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      unfold isToken; simpl.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      split; intro H; inv H.
(* Goal: @eq t c c *)
      apply canonTree_eq; auto.
(* Goal: canonicalTree (Leaf b) *)
      constructor.
    Qed.

    Lemma nonidentityToken : forall x n, (n > 0)%nat -> isToken x n -> x <> bot.
    Proof.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      repeat intro.
(* Goal: False *)
      destruct x as [x ?].
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
      inv H1.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
      hnf in H0; simpl in H0.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H0; inv H.
    Qed.

    Lemma nonidentityFactory : forall x n, isTokenFactory x n -> x <> bot.
    Proof.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      repeat intro.
(* Goal: False *)
      destruct x as [x ?].
(* Goal: False *)
      inv H0.
(* Goal: and (@join (@sig ShareTree (fun t : ShareTree => canonicalTree t)) Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31))) (@join (@sig ShareTree (fun t : ShareTree => canonicalTree t)) Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t22) (mkCanon_correct t22)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32))) *)
      hnf in H.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
      simpl in *.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
      inv H.
    Qed.

    Instance EqDec_share : EqDec t := EqDec_canonTree.

(* Credits for the next part of this file:
  Specification of "unrel" operator by Andrew W. Appel and Robert Dockins
  Definition of "unrel", and all the proofs about it, by Le Xuan Bach
*)

   Program Definition tree_decompose (ct : canonTree) :(canonTree * canonTree) :=
     let (t, pf) := ct in
     match t with
     |Leaf b => (Leaf b, Leaf b)
     |Node t1 t2 => (t1 ,t2)
     end.
   Next Obligation.
(* Goal: @eq t c c *)
    destruct pf. tauto.
   Defined.
   Next Obligation.
(* Goal: @eq t c c *)
    destruct pf. tauto.
   Defined.

   Instance decompose_tree : decomposible t :=
     Decomposible tree_decompose.

  Fixpoint tree_heightP (t : ShareTree) : nat :=
   match t with
   | Leaf b  => 0
   | Node l r => (max (tree_heightP l) (tree_heightP r)) + 1
  end.

  Definition tree_height (t : canonTree) := tree_heightP (proj1_sig t).
  Definition tree_height_zero (t : canonTree) : {tree_height t = 0} + {tree_height t <> 0}.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
    destruct t. destruct x.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    left. reflexivity.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    right. unfold tree_height. simpl. intro. rewrite plus_comm in H. inversion H.
  Defined.
  Instance tree_heightable : heightable t :=
    Heightable tree_height tree_height_zero.

  Function unrel (t1 : t) (t2 : t) {measure tree_height t1} : t :=
   match t1 with
    | exist _ (Leaf b) _ => t2
    | _ => let (ltr1, rtr1) := decompose t1 in
           let (ltr2, rtr2) := decompose t2 in
              match ltr1 with
               | exist _ (Leaf true) _ => ltr2
               | exist _ (Leaf false) _ => unrel rtr1 rtr2
               | _ => unrel ltr1 ltr2
              end
   end.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
 clear -teq1.
 inv teq1.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct c as [? [? [? ?]]].
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl. unfold tree_height.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (S O) (S n) *)
 omega.

(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
 clear -teq1.
 inv teq1.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct c as [? [? [? ?]]].
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 unfold tree_height. simpl.
 remember (max (tree_heightP s1) (tree_heightP s2) + 1).
 assert (n1 <= max n1 (tree_heightP s0)).
(* Goal: ge (PeanoNat.Nat.max (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2))) (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
   apply le_max_l.
(* Goal: le (S O) (S n) *)
 omega.
Set Warnings "-funind-cannot-build-inversion,-funind-cannot-define-graph".
 Defined.
Set Warnings "+funind-cannot-build-inversion,+funind-cannot-define-graph".

Lemma canonTree_Leaf : forall b, canonicalTree (Leaf b).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: canonicalTree (Leaf b) *)
  constructor.
Qed.

Lemma mkCanon_identity : forall t, canonicalTree t -> mkCanon t = t.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  induction t0;intros.
(* Goal: @eq (option ShareTree) (mkFull O (Leaf b)) (@Some ShareTree (Leaf b)) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Node t0_1 t0_2)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
  compute;trivial.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  simpl in H.
(* Goal: @eq (prod (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0))) ((let (decompose) := decompose_tree in decompose) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x x0) H)) (@pair t t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x0 c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) b *)
  destruct H as [? [? [? ?]]].
(* Goal: @eq ShareTree match mkCanon t0_1 with | Leaf b1 => match mkCanon t0_2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t0_1) (mkCanon t0_2) | Node s s0 => Node (mkCanon t0_1) (mkCanon t0_2) end | Node s s0 => Node (mkCanon t0_1) (mkCanon t0_2) end (Node t0_1 t0_2) *)
  specialize ( IHt0_1 H1).
(* Goal: @eq ShareTree match mkCanon t0_1 with | Leaf b1 => match mkCanon t0_2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t0_1) (mkCanon t0_2) | Node s s0 => Node (mkCanon t0_1) (mkCanon t0_2) end | Node s s0 => Node (mkCanon t0_1) (mkCanon t0_2) end (Node t0_1 t0_2) *)
  specialize ( IHt0_2 H2).
(* Goal: @eq ShareTree match mkCanon t0_1 with | Leaf b1 => match mkCanon t0_2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t0_1) (mkCanon t0_2) | Node s s0 => Node (mkCanon t0_1) (mkCanon t0_2) end | Node s s0 => Node (mkCanon t0_1) (mkCanon t0_2) end (Node t0_1 t0_2) *)
  rewrite IHt0_1.
(* Goal: @eq ShareTree match t0_1 with | Leaf b1 => match mkCanon t0_2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node t0_1 (mkCanon t0_2) | Node s s0 => Node t0_1 (mkCanon t0_2) end | Node s s0 => Node t0_1 (mkCanon t0_2) end (Node t0_1 t0_2) *)
  rewrite IHt0_2.
(* Goal: @eq ShareTree match t0_1 with | Leaf b1 => match t0_2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node t0_1 t0_2 | Node s s0 => Node t0_1 t0_2 end | Node s s0 => Node t0_1 t0_2 end (Node t0_1 t0_2) *)
  icase t0_1;icase t0_2.
(* Goal: and (@eq (option t) (tree_round_left (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x3_1 x3_2) c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c1))) (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x3_1 x3_2) c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) c2))) *)
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
  icase (bool_dec b b0).
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
  subst.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  elimtype False.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
  icase b0;compute in  H;compute in H0; firstorder.
Qed.

Lemma identity_tree: identity (exist (fun t0 => canonicalTree t0) (Leaf false) (canonTree_Leaf _)).
Proof.
(* Goal: @identity (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) Join_ba (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) (canonTree_Leaf false)) *)
  unfold identity,join,BAF.Join_ba.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) a b *)
  unfold BAF.lub in H0.
(* Goal: False *)
  inv H0.
(* Goal: forall (a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
  destruct a.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
  apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: @eq t s bot *)
(* Goal: @identity t Join_ba s *)
  symmetry.
(* Goal: @eq ShareTree (mkCanon (Node x1 x2)) (Node x1 x2) *)
  apply mkCanon_identity.
(* Goal: @eq t c0 c0 *)
  trivial.
Qed.

Lemma nonEmpty_nonidentity: forall x c,nonEmptyTree x -> nonidentity (exist _ x c).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  icase x.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  intro.
  specialize ( H0 (exist (fun t0 => canonicalTree t0) (Leaf false) (canonTree_Leaf _))
          (exist (fun t0 => canonicalTree t0) (Leaf true) (canonTree_Leaf _))).
(* Goal: False *)
  detach H0.
(* Goal: False *)
  inv H0.
(* Goal: @join (@sig ShareTree (fun t : ShareTree => canonicalTree t)) Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) c) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) (canonTree_Leaf false)) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) (canonTree_Leaf true)) *)
(* Goal: @nonidentity (@sig ShareTree (fun t : ShareTree => canonicalTree t)) Join_ba pa (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) *)
  unfold join,BAF.Join_ba.
(* Goal: @eq (option ShareTree) (mkFull O (Leaf b)) (@Some ShareTree (Leaf b)) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Node t0_1 t0_2)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
  split;apply exist_ext;compute;trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  intro.
(* Goal: False *)
  unfold identity in H0.
  specialize ( H0 (exist (fun t0 => canonicalTree t0) (Leaf false) (canonTree_Leaf _))
          (exist (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)).
(* Goal: False *)
  detach H0.
(* Goal: False *)
  inv H0.
(* Goal: @join (@sig ShareTree (fun t : ShareTree => canonicalTree t)) Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) (canonTree_Leaf false)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) *)
  apply join_comm.
(* Goal: @join (@sig ShareTree (fun t : ShareTree => canonicalTree t)) Join_ba (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) (canonTree_Leaf false)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) *)
  unfold join.
(* Goal: Join_ba (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) (canonTree_Leaf false)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) *)
  unfold BAF.Join_ba,BAF.glb,BAF.lub.
(* Goal: @eq t c0 c0 *)
  split;apply exist_ext;simpl;trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (mkCanon_identity _ c);intro.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  simpl in H0.
(* Goal: @eq t c0 c0 *)
  trivial.
Qed.

Lemma unrel_rel: forall x sh,
    nonidentity x -> unrel x (rel x sh) = sh.
Proof.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  intro.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
  destruct x.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  induction x;intros.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
  rewrite unrel_equation.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: @eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) c) sh) sh *)
(* Goal: @eq t (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) sh)) sh *)
  assert (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf true) c = top).
(* Goal: @eq t (let (x, _) := top in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree top in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
   unfold top.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t c0 c0 *)
   trivial.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
  rewrite H0.
(* Goal: @eq t (rel top sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
  apply rel_top2.

(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  elimtype False.
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
  apply H.
  assert (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf false) c =
                 core (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf false) c)).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: @eq (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) c) bot *)
(* Goal: @identity t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) sh)) sh *)
  unfold BAF.bot.
(* Goal: @eq t c0 c0 *)
  apply exist_ext;trivial.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
  rewrite H0.
(* Goal: @identity t Join_ba (@core (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) Join_ba sa (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) c)) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) sh)) sh *)
  apply core_identity.

(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
  rewrite unrel_equation.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  destruct c as [? [? [? ?]]].
  assert (decompose (exist _ (Node x1 x2)
          (conj n (conj n0 (conj c c0)))) =
          (exist (fun t0 : ShareTree => canonicalTree t0) x1 c,
           exist (fun t0 : ShareTree => canonicalTree t0) x2 c0)).
(* Goal: @eq t c0 c0 *)
    simpl;trivial.
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  unfold decompose,decompose_tree in *.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (mkCanon_correct (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  rewrite H0;clear H0.
  assert (decompose (rel (exist (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2)
         (conj n (conj n0 (conj c c0)))) sh) =
         (rel (exist _ x1 c) sh, rel (exist _ x2 c0) sh)).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (rel_classification);intro.
   specialize ( X (exist (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2)
          (conj n (conj n0 (conj c c0)))) sh).
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) match mkCanon x with | Leaf b2 => if if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (mkCanon x) | Node s s0 => Node (Leaf false) (mkCanon x) end *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
   icase X.
(* Goal: @eq (prod t t) (@decompose t decompose_tree (rel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) sh)) (@pair t t (rel (@exist ShareTree canonicalTree x1 c) sh) (rel (@exist ShareTree canonicalTree x2 c0) sh)) *)
(* Goal: @eq (prod t t) (@decompose t decompose_tree (rel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) sh)) (@pair t t (rel (@exist ShareTree canonicalTree x1 c) sh) (rel (@exist ShareTree canonicalTree x2 c0) sh)) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) sh) in match x1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) ltr2 end) sh *)
   destruct a;subst sh.
(* Goal: iff (@join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))))) (and (@join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31)))) (@join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))))) *)
   clear.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
   apply injective_projections;simpl;symmetry;
(* Goal: @eq t (rel x bot) bot *)
   apply rel_bot1.

(* Goal: forall (a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
   destruct a.
(* Goal: lt (tree_height t') (S n) *)
   destruct H1.
(* Goal: @eq (prod (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@decompose (@sig ShareTree (fun t : ShareTree => canonicalTree t)) decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c)) (@pair (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 c2)) *)
   unfold decompose.
   remember (rel (exist (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2)
            (conj n (conj n0 (conj c c0)))) sh).
(* Goal: or (or (@eq t t0 top) (@eq t t0 bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex ((fun t : ShareTree => canonicalTree t) (Node t1 t2)) (fun c : (fun t : ShareTree => canonicalTree t) (Node t1 t2) => @eq t t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c))))) *)
   destruct t0.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
   simpl in H1.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   icase x.
(* Goal: and (le (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) n) (le (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) n) *)
   destruct c1 as [? [? [? ?]]].
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
   inv H1.
   apply injective_projections;simpl;
   destruct sh;
(* Goal: @eq t c0 c0 *)
   icase x;unfold rel;simpl;try apply exist_ext;trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase b.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t match x1 with | Leaf (true as b) => t0 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) t1 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) t0 end bot *)
   icase x1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase b.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase x2.
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  unfold decompose,decompose_tree in *.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (mkCanon_correct (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  rewrite H0;clear H0.
(* Goal: @eq t match x1 with | Leaf (true as b) => t0 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) t1 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) t0 end bot *)
  icase x1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: @eq t (rel (@exist ShareTree canonicalTree (Leaf true) c) sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
   assert (exist _ (Leaf true) c = top).
(* Goal: @eq t (let (x, _) := top in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree top in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
   unfold top.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t c0 c0 *)
   trivial.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
  rewrite H0.
(* Goal: @eq t (rel top sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
  apply rel_top2.
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
  apply IHx2.
(* Goal: @nonidentity t Join_ba pa (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) *)
  apply nonEmpty_nonidentity.
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
  icase n0.
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
  apply IHx1.
(* Goal: @nonidentity t Join_ba pa (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) *)
  apply nonEmpty_nonidentity.
(* Goal: nonEmptyTree (Node x1_1 x1_2) *)
  clear - c.
(* Goal: nonEmptyTree (Node x1_1 x1_2) *)
  destruct c as [_ [? _]].
(* Goal: @eq t c0 c0 *)
  trivial.
Qed.

Definition Lsh  : Share.t := fst (Share.split Share.top).
Definition Rsh  : Share.t := snd (Share.split Share.top).

Definition splice (a b: t) : t := Share.lub (rel Lsh a) (rel Rsh b).

Lemma mkCanon_Leaf : forall b , mkCanon (Leaf b) = Leaf b.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
Qed.

 Lemma mkCanon_double : forall t, mkCanon (mkCanon t) = mkCanon t.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_correct t0);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_identity _ H);intro.
(* Goal: @eq t c0 c0 *)
    trivial.
 Qed.

 Lemma mkCanon_split : forall t1 t2 t1' t2', mkCanon (Node t1 t2) = Node t1' t2' ->
                                            mkCanon t1 = t1' /\ mkCanon t2 = t2'.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
    icase (mkCanon t1);icase (mkCanon t2);
(* Goal: @eq t c c *)
    try icase (bool_dec b b0);inversion H1;auto.
 Qed.

 Lemma mkCanon_Leaf_split : forall t1 t2 b, Leaf b = mkCanon (Node t1 t2) ->
                                           mkCanon t1 = Leaf b /\ mkCanon t2 = Leaf b.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: @eq ShareTree match mkCanon t1 with | Leaf b1 => match mkCanon t2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t1) (mkCanon t2) | Node s s0 => Node (mkCanon t1) (mkCanon t2) end | Node s s0 => Node (mkCanon t1) (mkCanon t2) end match mkCanon t1 with | Leaf b1 => match mkCanon t2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t1) (mkCanon t2) | Node s s0 => Node (mkCanon t1) (mkCanon t2) end | Node s s0 => Node (mkCanon t1) (mkCanon t2) end *)
    icase (mkCanon t1);icase (mkCanon t2).
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
    icase (bool_dec b0 b1);inversion H1;subst.
(* Goal: @eq t c c *)
    tauto.
  Qed.

 Lemma mkCanon_union : forall t1 t2, mkCanon (union_tree (mkCanon t1) (mkCanon t2)) =
                                      mkCanon (union_tree t1 t2).
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
    assert (exists n, n >= max (tree_heightP t1) (tree_heightP t2)).
(* Goal: le (S O) (S n) *)
      exists (max (tree_heightP t1) (tree_heightP t2));omega.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
    destruct H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
    revert H.
(* Goal: forall _ : ge x (PeanoNat.Nat.max (tree_heightP t1) (tree_heightP t2)), @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
    revert t2 t1.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction x;intros.
(* Goal: @ex bool (fun b1 : bool => @ex bool (fun b2 : bool => and (@eq ShareTree t1 (Leaf b1)) (and (@eq ShareTree t2 (Leaf b2)) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b2) (canonTree_Leaf b2)))))) *)
      icase t1;icase t2.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
      remember (tree_heightP (Node t2_1 t2_2)).
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
      icase n.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
      inversion Heqn.
(* Goal: le (S O) (S n) *)
      destruct (max (tree_heightP t2_1) (tree_heightP t2_2));elimtype False ;omega.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
      inversion H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
      inversion H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
      destruct (max (tree_heightP t1_1) (tree_heightP t1_2));inversion H1.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
      inversion H.
      destruct (max (tree_heightP t1_1) (tree_heightP t1_2));
      destruct (max (tree_heightP t2_1) (tree_heightP t2_2));
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (tree_height s1) s1) (countBLeafCT (tree_height s1) s2)) (countBLeafCT (tree_height s1) s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
      inversion H1.
(* Goal: @ex bool (fun b1 : bool => @ex bool (fun b2 : bool => and (@eq ShareTree t1 (Leaf b1)) (and (@eq ShareTree t2 (Leaf b2)) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b2) (canonTree_Leaf b2)))))) *)
    icase t1;icase t2.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    replace (mkCanon (Leaf b)) with (Leaf b) by apply mkCanon_Leaf.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: @eq ShareTree (mkCanon (union_tree (Leaf false) (mkCanon (Node t1_1 t1_2)))) (mkCanon (union_tree (Leaf false) (Node t1_1 t1_2))) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (union_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    unfold union_tree.
(* Goal: @eq ShareTree (mkCanon (mkCanon (Node t1_1 t1_2))) (mkCanon (Node t1_1 t1_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    apply mkCanon_double.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    replace (mkCanon (Leaf b)) with (Leaf b) by apply mkCanon_Leaf.
    replace (union_tree (mkCanon (Node t1_1 t1_2)) (Leaf b))
    with (union_tree(Leaf b)(mkCanon (Node t1_1 t1_2)))
    by apply union_commute.
    replace (union_tree ( (Node t1_1 t1_2)) (Leaf b))
    with (union_tree(Leaf b)(Node t1_1 t1_2))
    by apply union_commute.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: @eq ShareTree (mkCanon (union_tree (Leaf false) (mkCanon (Node t1_1 t1_2)))) (mkCanon (union_tree (Leaf false) (Node t1_1 t1_2))) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (union_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    unfold union_tree.
(* Goal: @eq ShareTree (mkCanon (mkCanon (Node t1_1 t1_2))) (mkCanon (Node t1_1 t1_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    apply mkCanon_double.

(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    assert (x >= max (tree_heightP t1_1) (tree_heightP t2_1)).
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
      simpl in H.
      replace (max (tree_heightP t1_1) (tree_heightP t1_2) + 1)
      with (S (max (tree_heightP t1_1) (tree_heightP t1_2)))
(* Goal: le (S O) (S n) *)
      in H by omega.
      replace (max (tree_heightP t2_1) (tree_heightP t2_2) + 1)
      with (S (max (tree_heightP t2_1) (tree_heightP t2_2)))
(* Goal: le (S O) (S n) *)
      in H by omega.
      generalize (succ_max_distr ((max (tree_heightP t1_1) (tree_heightP t1_2)))
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      ((max (tree_heightP t2_1) (tree_heightP t2_2))));intro.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t2_1)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      rewrite<- H0 in H;clear H0.
      assert (x >= max (max (tree_heightP t1_1) (tree_heightP t1_2))
(* Goal: le (S O) (S n) *)
         (max (tree_heightP t2_1) (tree_heightP t2_2))) by omega.
      assert (max (max (tree_heightP t1_1) (tree_heightP t1_2))
       (max (tree_heightP t2_1) (tree_heightP t2_2)) >= max (tree_heightP t1_1) (tree_heightP t1_2)).
(* Goal: ge (PeanoNat.Nat.max (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2))) (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_l.
      assert (max (max (tree_heightP t1_1) (tree_heightP t1_2))
       (max (tree_heightP t2_1) (tree_heightP t2_2)) >= max (tree_heightP t2_1) (tree_heightP t2_2)).
(* Goal: ge (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2)) (tree_heightP t2_2) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_r.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t2_1)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      assert (max (tree_heightP t1_1) (tree_heightP t1_2) >= tree_heightP t1_1).
(* Goal: ge (PeanoNat.Nat.max (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2))) (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_l.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t2_1)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      assert (max (tree_heightP t2_1) (tree_heightP t2_2) >= tree_heightP t2_1).
(* Goal: ge (PeanoNat.Nat.max (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2))) (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_l.
(* Goal: le (S O) (S n) *)
      apply max_lub;omega.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    assert (x >= max (tree_heightP t1_2) (tree_heightP t2_2)).
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
      simpl in H.
      replace (max (tree_heightP t1_1) (tree_heightP t1_2) + 1)
      with (S (max (tree_heightP t1_1) (tree_heightP t1_2)))
(* Goal: le (S O) (S n) *)
      in H by omega.
      replace (max (tree_heightP t2_1) (tree_heightP t2_2) + 1)
      with (S (max (tree_heightP t2_1) (tree_heightP t2_2)))
(* Goal: le (S O) (S n) *)
      in H by omega.
      generalize (succ_max_distr ((max (tree_heightP t1_1) (tree_heightP t1_2)))
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      ((max (tree_heightP t2_1) (tree_heightP t2_2))));intro.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      rewrite<- H1 in H;clear H1.
      assert (x >= max (max (tree_heightP t1_1) (tree_heightP t1_2))
(* Goal: le (S O) (S n) *)
         (max (tree_heightP t2_1) (tree_heightP t2_2))) by omega.
      assert (max (max (tree_heightP t1_1) (tree_heightP t1_2))
       (max (tree_heightP t2_1) (tree_heightP t2_2)) >= max (tree_heightP t1_1) (tree_heightP t1_2)).
(* Goal: ge (PeanoNat.Nat.max (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2))) (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_l.
      assert (max (max (tree_heightP t1_1) (tree_heightP t1_2))
       (max (tree_heightP t2_1) (tree_heightP t2_2)) >= max (tree_heightP t2_1) (tree_heightP t2_2)).
(* Goal: ge (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2)) (tree_heightP t2_2) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_r.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      assert (max (tree_heightP t1_1) (tree_heightP t1_2) >= tree_heightP t1_2).
(* Goal: ge (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2)) (tree_heightP t2_2) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_r.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      assert (max (tree_heightP t2_1) (tree_heightP t2_2) >= tree_heightP t2_2).
(* Goal: ge (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2)) (tree_heightP t2_2) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_r.
(* Goal: le (S O) (S n) *)
      apply max_lub;omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHx _ _ H0);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHx _ _ H1);intro.
    remember (mkCanon (Node t1_1 t1_2));
    remember (mkCanon (Node t2_1 t2_2)).
(* Goal: @eq ShareTree (mkCanon (intersect_tree s s0)) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    icase s;icase s0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H4 as [H41 H42].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H5 as [H51 H52].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H41 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Leaf b0))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H51 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H42 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Leaf b0))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H52 in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    rewrite<-  H2.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    rewrite<- H3.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf b0);intro.
(* Goal: @eq ShareTree (mkCanon (Leaf b0)) match mkCanon (Leaf b0) with | Leaf b1 => match mkCanon (Leaf b0) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) | Node s s0 => Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) end | Node s s0 => Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H4.
(* Goal: @eq t c0 c0 *)
    icase (bool_dec b0 b0);trivial.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    firstorder.


(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    symmetry in Heqs0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_split _ _ _ _ Heqs0);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H4 as [H41 H42].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H5 as [H51 H52].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H41 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H42 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H51 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node (mkCanon t2_1) s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H52 in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq ShareTree (mkCanon (if b then Node (mkCanon t1_1) (mkCanon t1_2) else Leaf false)) match mkCanon (intersect_tree t1_1 t2_1) with | Leaf b1 => match mkCanon (intersect_tree t1_2 t2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H2.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    rewrite<-H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.

(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro.
(* Goal: iff (@eq (option ShareTree) (mkFull (S n) (Node s1 s2)) (@Some ShareTree (Node t1' t2'))) (and (@eq (option ShareTree) (mkFull n (mkCanon t1)) (@Some ShareTree t1')) (@eq (option ShareTree) (mkFull n (mkCanon t2)) (@Some ShareTree t2'))) *)
    symmetry in Heqs.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_split _ _ _ _ Heqs);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H4 as [H41 H42].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H5 as [H51 H52].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H41 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H42 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H51 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node (mkCanon t2_1) s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H52 in *.
    replace (union_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Leaf b))
    with (union_tree (Leaf b) (Node (mkCanon t1_1) (mkCanon t1_2)))
    by apply union_commute.
    replace (union_tree (mkCanon t1_1) (Leaf b))
    with (union_tree (Leaf b)(mkCanon t1_1)) in H2
    by apply union_commute.
    replace (union_tree (mkCanon t1_2) (Leaf b))
    with (union_tree (Leaf b)(mkCanon t1_2)) in H3
    by apply union_commute.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq ShareTree (mkCanon (if b then Node (mkCanon t1_1) (mkCanon t1_2) else Leaf false)) match mkCanon (intersect_tree t1_1 t2_1) with | Leaf b1 => match mkCanon (intersect_tree t1_2 t2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H2.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    rewrite<-H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.

(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    symmetry in Heqs, Heqs0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_split _ _ _ _ Heqs);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_split _ _ _ _ Heqs0);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H4 as [H41 H42].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H5 as [H51 H52].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H41 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H42 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H51 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node (mkCanon t2_1) s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H52 in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H3.
(* Goal: @eq t c0 c0 *)
    trivial.
 Qed.

 Lemma splice_rewrite: forall a b, splice a b =
      exist (fun t0 => canonicalTree t0) (mkCanon (Node (proj1_sig a) (proj1_sig b))) (mkCanon_correct _).
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: @eq t (splice a b) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
  unfold splice.
(* Goal: @eq t (lub (rel Lsh a) (rel Rsh b)) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
  unfold lub,Lsh,Rsh.
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (@fst t t (split top)) a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (@snd t t (split top)) b)))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (@fst t t (split top)) a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (@snd t t (split top)) b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
  unfold split,fst,snd.
(* Goal: @eq t (rel top sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
  assert (rel top leftTree = leftTree) by apply rel_top2.
(* Goal: @eq t (let (ltr1, rtr1) := tree_decompose (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) b *)
  rewrite H;clear H.
(* Goal: @eq t (rel top sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
  assert (rel top rightTree = rightTree) by apply rel_top2.
(* Goal: @eq t (let (ltr1, rtr1) := tree_decompose (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) b *)
  rewrite H;clear H.
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
  assert (proj1_sig (rel leftTree a) = mkCanon (Node (proj1_sig a) (Leaf false))).
    destruct a;
(* Goal: @eq t (unrel leftTree (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))))) a *)
    unfold leftTree.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (rel_classification);intro.
    specialize ( X (exist (fun t0 : ShareTree => canonicalTree t0)
        (Node (Leaf true) (Leaf false))
          (conj (or_intror (true = false) (Logic.eq_refl false))
           (conj (or_introl (false = true) (Logic.eq_refl true)) (conj I I))))
     (exist (fun t0 : ShareTree => canonicalTree t0) x c)).
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) match mkCanon x with | Leaf b2 => if if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (mkCanon x) | Node s s0 => Node (Leaf false) (mkCanon x) end *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
    icase X.
(* Goal: forall (a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
    destruct a.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
    rewrite H0.
(* Goal: @eq (option ShareTree) (mkFull O (Leaf b)) (@Some ShareTree (Leaf b)) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Node t0_1 t0_2)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    compute;trivial.
(* Goal: forall (a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
    destruct a.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
    destruct H0.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
    rewrite H0.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_identity _ c);intro.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    icase x.
(* Goal: @eq ShareTree (Node (Leaf b0) (Leaf false)) (if bool_dec b0 false then Leaf b0 else Node (Leaf b0) (Leaf false)) *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
    icase b0.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
  rewrite H.
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
  assert (proj1_sig (rel rightTree b) = mkCanon (Node (Leaf false) (proj1_sig b))).
    destruct b;
(* Goal: @eq t (unrel rightTree (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))))) b *)
    unfold rightTree.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (rel_classification);intro.
    specialize ( X (exist (fun t0 : ShareTree => canonicalTree t0)
        (Node (Leaf false) (Leaf true))
         (conj (or_introl (true = false) (Logic.eq_refl false))
           (conj (or_intror (false = true) (Logic.eq_refl true)) (conj I I))))
     (exist (fun t0 : ShareTree => canonicalTree t0) x c)).
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) match mkCanon x with | Leaf b2 => if if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (mkCanon x) | Node s s0 => Node (Leaf false) (mkCanon x) end *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
    icase X.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) match mkCanon x with | Leaf b2 => if if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (mkCanon x) | Node s s0 => Node (Leaf false) (mkCanon x) end *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
    destruct a0.
(* Goal: False *)
    inv H0.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
    rewrite H1.
(* Goal: @eq (option ShareTree) (mkFull O (Leaf b)) (@Some ShareTree (Leaf b)) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Node t0_1 t0_2)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    compute;trivial.
(* Goal: @eq ShareTree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) match mkCanon x with | Leaf b2 => if if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false) then Leaf false else Node (Leaf false) (mkCanon x) | Node s s0 => Node (Leaf false) (mkCanon x) end *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
    destruct a0.
(* Goal: lt (tree_height t') (S n) *)
    destruct H1.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
    rewrite H1.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_identity _ c);intro.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H3.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    icase x.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
  rewrite H0.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
  apply exist_ext.
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (Leaf false))) (mkCanon (Node (Leaf false) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))))) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) *)
  rewrite mkCanon_union.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
  f_equal.
(* Goal: @eq ShareTree (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b) (Leaf false))) (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)) *)
  rewrite union_commute.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: @eq ShareTree (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b) (Leaf false))) (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)) *)
  rewrite union_commute.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: @eq t c0 c0 *)
  trivial.
 Qed.

 Lemma canonTree_check: forall x y, canonicalTree x -> canonicalTree y ->
                       (exists b, x = Leaf b /\ y = Leaf b) \/ (canonicalTree (Node x y)).
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  icase x.
(* Goal: or (@ex bool (fun b0 : bool => and (@eq ShareTree (Leaf b) (Leaf b0)) (@eq ShareTree y (Leaf b0)))) (canonicalTree (Node (Leaf b) y)) *)
(* Goal: or (@ex bool (fun b : bool => and (@eq ShareTree (Node x1 x2) (Leaf b)) (@eq ShareTree y (Leaf b)))) (canonicalTree (Node (Node x1 x2) y)) *)
  icase y.
(* Goal: @eq ShareTree (Node (Leaf b0) (Leaf false)) (if bool_dec b0 false then Leaf b0 else Node (Leaf b0) (Leaf false)) *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
  icase b;icase b0.
(* Goal: @eq t c c *)
  left;exists true;auto.
(* Goal: @eq t c c *)
  right;compute;tauto.
(* Goal: @eq t c c *)
  right;compute;tauto.
(* Goal: @eq t c c *)
  left;exists false;auto.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  right.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
  firstorder.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  right.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
  firstorder.
 Qed.

 Lemma unrel_splice_L:
  forall a b, unrel Lsh (splice a b) = a.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (splice_rewrite a b);intro.
(* Goal: @eq t (let (ltr1, rtr1) := tree_decompose (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) b *)
  rewrite H;clear H.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
  unfold Lsh,fst,split.
(* Goal: @eq t (rel top sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
  assert (rel top leftTree = leftTree) by apply rel_top2.
(* Goal: @eq t (let (ltr1, rtr1) := tree_decompose (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) b *)
  rewrite H;clear H.
(* Goal: @eq t (unrel leftTree (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))))) a *)
  unfold leftTree.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
  rewrite unrel_equation.
  assert  (decompose
          (exist (fun t0 : ShareTree => canonicalTree t0)
          (Node (Leaf true) (Leaf false))
          (conj (or_intror (true = false) (Logic.eq_refl false))
             (conj (or_introl (false = true) (Logic.eq_refl true)) (conj I I))))=
          (top,bot)).
(* Goal: @eq t c0 c0 *)
   compute;apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  unfold decompose,decompose_tree in *.
(* Goal: @eq t (let (ltr1, rtr1) := tree_decompose (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) b *)
  rewrite H;clear H.
  assert  (decompose ((exist (fun t0 : ShareTree => canonicalTree t0)
          (mkCanon (Node (proj1_sig a) (proj1_sig b)))
          (mkCanon_correct (Node (proj1_sig a) (proj1_sig b))))) = (a,b)).
(* Goal: @eq (prod (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0))) (@decompose (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) decompose_tree (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))))) (@pair t t a b) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) b *)
    destruct a,b.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
    unfold proj1_sig.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (canonTree_check _ _ c c0);intro.
(* Goal: @eq (prod (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0))) (@decompose (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) decompose_tree (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x0)) (mkCanon_correct (Node x x0)))) (@pair t t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x0 c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) b *)
    icase H.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
    destruct H as [? [? ?]];subst.
    icase x1;unfold decompose;apply injective_projections;
(* Goal: @eq t c0 c0 *)
     simpl;  apply exist_ext;simpl;trivial.
    assert ((exist (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x0))
           (mkCanon_correct (Node x x0))) = exist (fun t0 => canonicalTree t0) (Node x x0) H).
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
      apply exist_ext.
(* Goal: @eq ShareTree (mkCanon (Node x1 x2)) (Node x1 x2) *)
      apply mkCanon_identity.
(* Goal: @eq t c0 c0 *)
      trivial.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
    rewrite H0.
(* Goal: @eq (prod (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@decompose (@sig ShareTree (fun t : ShareTree => canonicalTree t)) decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c)) (@pair (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 c2)) *)
    unfold decompose.
(* Goal: @eq (prod (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0))) ((let (decompose) := decompose_tree in decompose) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x x0) H)) (@pair t t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x0 c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) b *)
    destruct H as [? [? [? ?]]].
(* Goal: @eq t c0 c0 *)
    apply injective_projections;simpl;apply exist_ext;trivial.
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
    unfold decompose,decompose_tree in *.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
    rewrite H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    unfold top;simpl.
(* Goal: @eq t c0 c0 *)
    trivial.
 Qed.

 Lemma unrel_splice_R:
  forall a b, unrel Rsh (splice a b) = b.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (splice_rewrite a b);intro.
(* Goal: @eq t (let (ltr1, rtr1) := tree_decompose (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) b *)
  rewrite H;clear H.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
  unfold Rsh,snd,split.
(* Goal: @eq t (rel top sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
  assert (rel top rightTree = rightTree) by apply rel_top2.
(* Goal: @eq t (let (ltr1, rtr1) := tree_decompose (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) b *)
  rewrite H;clear H.
(* Goal: @eq t (unrel rightTree (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))))) b *)
  unfold rightTree.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
  rewrite unrel_equation.
  assert  (decompose
          (exist (fun t0 : ShareTree => canonicalTree t0)
          (Node (Leaf false) (Leaf true))
           (conj (or_introl (true = false) (Logic.eq_refl false))
             (conj (or_intror (false = true) (Logic.eq_refl true)) (conj I I)))) =
          (bot,top)).
(* Goal: @eq t c0 c0 *)
   compute;apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  unfold decompose,decompose_tree in *.
(* Goal: @eq t (let (ltr1, rtr1) := tree_decompose (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) b *)
  rewrite H;clear H.
  assert  (decompose ((exist (fun t0 : ShareTree => canonicalTree t0)
          (mkCanon (Node (proj1_sig a) (proj1_sig b)))
          (mkCanon_correct (Node (proj1_sig a) (proj1_sig b))))) = (a,b)).
(* Goal: @eq (prod (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0))) (@decompose (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) decompose_tree (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))))) (@pair t t a b) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) b *)
    destruct a,b.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
    unfold proj1_sig.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (canonTree_check _ _ c c0);intro.
(* Goal: @eq (prod (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0))) (@decompose (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) decompose_tree (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x0)) (mkCanon_correct (Node x x0)))) (@pair t t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x0 c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) b *)
    icase H.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
    destruct H as [? [? ?]];subst.
    icase x1;unfold decompose;apply injective_projections;
(* Goal: @eq t c0 c0 *)
    simpl; apply exist_ext;simpl;trivial.
    assert ((exist (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x0))
           (mkCanon_correct (Node x x0))) = exist (fun t0 => canonicalTree t0) (Node x x0) H).
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
      apply exist_ext.
(* Goal: @eq ShareTree (mkCanon (Node x1 x2)) (Node x1 x2) *)
      apply mkCanon_identity.
(* Goal: @eq t c0 c0 *)
      trivial.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
    rewrite H0.
(* Goal: @eq (prod (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@decompose (@sig ShareTree (fun t : ShareTree => canonicalTree t)) decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c)) (@pair (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 c2)) *)
    unfold decompose.
(* Goal: @eq (prod (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0))) ((let (decompose) := decompose_tree in decompose) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x x0) H)) (@pair t t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x0 c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) b *)
    destruct H as [? [? [? ?]]].
(* Goal: @eq t c0 c0 *)
    apply injective_projections;simpl;apply exist_ext;trivial.
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  unfold decompose,decompose_tree in *.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
  rewrite H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold bot;simpl.
(* Goal: @eq t (unrel top b) b *)
  reflexivity.
 Qed.

Lemma contains_Lsh_e:
   forall sh,
       join_sub Lsh sh -> unrel Lsh sh = top.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
 destruct H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
 destruct H.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 subst.
(* Goal: @eq t (unrel Lsh (lub Lsh x)) top *)
 unfold Lsh,fst in *.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
 simpl in *.
(* Goal: @eq t (rel top sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
 assert (rel top leftTree = leftTree) by apply rel_top2.
(* Goal: @eq t (unrel (rel top rightTree) (lub (rel top rightTree) x)) top *)
 rewrite H0 in *;clear H0.
(* Goal: @eq t (unrel leftTree (lub leftTree x)) top *)
 unfold leftTree in *.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t (let (ltr1, rtr1) := @decompose t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) x) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) top *)
 assert (CT: canonicalTree (Node (Leaf true) (Leaf false))).
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
  repeat split. right; reflexivity. left; reflexivity.
 assert (@decompose t _
        (exist (fun t0 : ShareTree => canonicalTree t0)
        (Node (Leaf true) (Leaf false))
          (conj (or_intror eq_refl) (conj (or_introl eq_refl) (conj I I))))
         = (top,bot)).
(* Goal: @eq t c0 c0 *)
   compute;apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq t (let (ltr1, rtr1) := @decompose t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) in let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) x) in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) top *)
 simpl nonFullTree in H0; simpl nonEmptyTree in H0.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
 rewrite H0. clear H0.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
 destruct x.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 icase x.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase b.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: @eq (prod BAF.t BAF.t) (@pair canonTree canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) match mkCanon_correct (Node (Leaf true) (Leaf false)) with | conj H H0 => @and_ind (or (@eq bool true true) (@eq bool false true)) (and True True) True (fun (_ : or (@eq bool true true) (@eq bool false true)) (H2 : and True True) => @and_ind True True True (fun H3 _ : True => H3) H2) H0 end) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) match mkCanon_correct (Node (Leaf true) (Leaf false)) with | conj H H0 => @and_ind (or (@eq bool true true) (@eq bool false true)) (and True True) True (fun (_ : or (@eq bool true true) (@eq bool false true)) (H2 : and True True) => @and_ind True True True (fun _ H4 : True => H4) H2) H0 end)) (@pair t (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) c0)) *)
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (Leaf true) (Node x2_1 x2_2))) (mkCanon_correct (Node (Leaf true) (Node x2_1 x2_2))))) (@pair t (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x2_1 x2_2) c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := top in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel bot rtr2 | Node s s0 => unrel top ltr2 end) top *)
 destruct (mkCanon_correct (Node (Leaf true) (Leaf false))) as [? [? [? ?]]].
(* Goal: @eq t c0 c0 *)
 unfold top.  apply exist_ext;trivial.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct c as [? [? [? ?]]].
 assert (decompose
       (BAF.lub
          (exist (fun t0 : ShareTree => canonicalTree t0)
             (Node (Leaf true) (Leaf false))
             (conj (or_intror eq_refl) (conj (or_introl eq_refl) (conj I I))))
          (exist (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2)
             (conj n (conj n0 (conj c c0))))) =
        (top, exist (fun t0 : ShareTree => canonicalTree t0) x2 c0)).
(* Goal: iff (@eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) (and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32)))) *)
   unfold BAF.lub.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
   unfold proj1_sig.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (Node (Leaf true) (Leaf false)) (Node x1 x2))) (mkCanon_correct (union_tree (Node (Leaf true) (Leaf false)) (Node x1 x2))))) (@pair t (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := top in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel bot rtr2 | Node s s0 => unrel top ltr2 end) top *)
   assert (union_tree (Node (Leaf true) (Leaf false)) (Node x1 x2) = Node (Leaf true) x2).
(* Goal: @eq t c0 c0 *)
     unfold union_tree;trivial.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (mkCanon_correct (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
   rewrite H0;clear H0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase x2.
   icase b;
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t c0 c0 *)
   apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq (prod BAF.t BAF.t) (@pair canonTree canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) match mkCanon_correct (Node (Leaf true) (Leaf false)) with | conj H H0 => @and_ind (or (@eq bool true true) (@eq bool false true)) (and True True) True (fun (_ : or (@eq bool true true) (@eq bool false true)) (H2 : and True True) => @and_ind True True True (fun H3 _ : True => H3) H2) H0 end) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) match mkCanon_correct (Node (Leaf true) (Leaf false)) with | conj H H0 => @and_ind (or (@eq bool true true) (@eq bool false true)) (and True True) True (fun (_ : or (@eq bool true true) (@eq bool false true)) (H2 : and True True) => @and_ind True True True (fun _ H4 : True => H4) H2) H0 end)) (@pair t (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) c0)) *)
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (Leaf true) (Node x2_1 x2_2))) (mkCanon_correct (Node (Leaf true) (Node x2_1 x2_2))))) (@pair t (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x2_1 x2_2) c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := top in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel bot rtr2 | Node s s0 => unrel top ltr2 end) top *)
   destruct (mkCanon_correct (Node (Leaf true) (Leaf false))) as [? [? [? ?]]].
(* Goal: @eq t c0 c0 *)
   apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (Leaf true) (Node x2_1 x2_2))) (mkCanon_correct (Node (Leaf true) (Node x2_1 x2_2))))) (@pair t (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x2_1 x2_2) c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := top in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel bot rtr2 | Node s s0 => unrel top ltr2 end) top *)
   assert (canonicalTree (Node (Leaf true) (Node x2_1 x2_2) )).
    destruct c0 as [? [? [? ?]]];
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    firstorder.
   assert (exist (fun t0 : ShareTree => canonicalTree t0)
     (mkCanon (Node (Leaf true) (Node x2_1 x2_2)))
     (mkCanon_correct (Node (Leaf true) (Node x2_1 x2_2)))=
          (exist (fun t0 : ShareTree => canonicalTree t0) (Node (Leaf true) (Node x2_1 x2_2)) H0)).
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
    destruct c0 as [? [? [? ?]]].
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_identity x2_1 c0);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_identity x2_2 c1);intro.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H1;rewrite H2.
(* Goal: @eq ShareTree match match x2_1 with | Leaf b1 => match x2_2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x2_1 x2_2 | Node s s0 => Node x2_1 x2_2 end | Node s s0 => Node x2_1 x2_2 end with | Leaf b2 => if if b2 as b return (sumbool (@eq bool true b) (not (@eq bool true b))) then @left (@eq bool true true) (not (@eq bool true true)) (@eq_refl bool true) else @right (@eq bool true false) (not (@eq bool true false)) (fun H : @eq bool true false => False_ind False (@eq_ind bool true (fun e : bool => if e then True else False) I false H)) then Leaf true else Node (Leaf true) match x2_1 with | Leaf b1 => match x2_2 with | Leaf b3 => if bool_dec b1 b3 then Leaf b1 else Node x2_1 x2_2 | Node s s0 => Node x2_1 x2_2 end | Node s s0 => Node x2_1 x2_2 end | Node s s0 => Node (Leaf true) match x2_1 with | Leaf b1 => match x2_2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x2_1 x2_2 | Node s1 s2 => Node x2_1 x2_2 end | Node s1 s2 => Node x2_1 x2_2 end end (Node (Leaf true) (Node x2_1 x2_2)) *)
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (Leaf true) (Node x2_1 x2_2))) (mkCanon_correct (Node (Leaf true) (Node x2_1 x2_2))))) (@pair t (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x2_1 x2_2) c0)) *)
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := top in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel bot rtr2 | Node s s0 => unrel top ltr2 end) top *)
    icase x2_1;icase x2_2.
    icase b;icase b0;
    simpl;
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    elimtype False;firstorder.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
  rewrite H1.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: @eq (prod BAF.t BAF.t) (@pair canonTree canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) match H0 with | conj H H0 => @and_ind (or (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (@eq bool true true)) (and (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True) (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) (fun (_ : or (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (@eq bool true true)) (H2 : and (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True) => @and_ind (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) (fun (H3 : and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) (_ : True) => H3) H2) H0 end) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) match H0 with | conj H H0 => @and_ind (or (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (@eq bool true true)) (and (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True) True (fun (_ : or (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (@eq bool true true)) (H2 : and (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True) => @and_ind (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True True (fun (_ : and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) (H4 : True) => H4) H2) H0 end)) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  destruct H0 as [? [? [? ?]]].
(* Goal: @eq t c0 c0 *)
  apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := top in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel bot rtr2 | Node s s0 => unrel top ltr2 end) top *)
  change BAF.lub with lub in H0.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := top in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel bot rtr2 | Node s s0 => unrel top ltr2 end) top *)
  simpl nonFullTree in H0|-*; simpl nonEmptyTree in H0|-*.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
 rewrite H0.
(* Goal: @eq t (let (x, _) := bot in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree bot in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
 unfold bot.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t (let (x, _) := top in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree top in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
 unfold top.
(* Goal: @eq t c0 c0 *)
 trivial.
Qed.

 Lemma contains_Rsh_e: forall sh,
       join_sub Rsh sh ->
       unrel Rsh sh = top.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
  subst.
(* Goal: @eq t (unrel Rsh (lub Rsh x)) top *)
  unfold Rsh,snd in *.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: @eq t (rel top sh) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x2 c0) (rel (@exist ShareTree canonicalTree x2 c0) sh)) sh *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) (rel (@exist ShareTree canonicalTree (Node x1_1 x1_2) c) sh)) sh *)
  assert (rel top rightTree = rightTree) by apply rel_top2.
(* Goal: @eq t (unrel (rel top rightTree) (lub (rel top rightTree) x)) top *)
  rewrite H0 in *;clear H0.
(* Goal: @eq t (unrel rightTree (lub rightTree x)) top *)
  unfold rightTree in *.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
  rewrite unrel_equation.
  assert (decompose
        (exist (fun t0 : ShareTree => canonicalTree t0)
        (Node (Leaf false) (Leaf true))
         (conj (or_introl (true = false) (Logic.eq_refl false))
            (conj (or_intror (false = true) (Logic.eq_refl true)) (conj I I))))
         = (bot,top)).
(* Goal: @eq t c0 c0 *)
   compute;apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  unfold decompose,decompose_tree in *.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (mkCanon_correct (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  rewrite H0;clear H0.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
  destruct x.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  icase x.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: @eq (prod BAF.t BAF.t) (@pair canonTree canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) match mkCanon_correct (Node (Leaf false) (Leaf true)) with | conj H H0 => @and_ind (or (@eq bool false true) (@eq bool true true)) (and True True) True (fun (_ : or (@eq bool false true) (@eq bool true true)) (H2 : and True True) => @and_ind True True True (fun H3 _ : True => H3) H2) H0 end) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) match mkCanon_correct (Node (Leaf false) (Leaf true)) with | conj H H0 => @and_ind (or (@eq bool false true) (@eq bool true true)) (and True True) True (fun (_ : or (@eq bool false true) (@eq bool true true)) (H2 : and True True) => @and_ind True True True (fun _ H4 : True => H4) H2) H0 end)) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) c) top) *)
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (Node x1_1 x1_2) (Leaf true))) (mkCanon_correct (Node (Node x1_1 x1_2) (Leaf true))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  destruct (mkCanon_correct (Node (Leaf false) (Leaf true))) as [? [? [? ?]]].
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
  rewrite unrel_equation.
(* Goal: @eq t (let (x, _) := top in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree top in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
  unfold top.
(* Goal: @eq t c0 c0 *)
  apply exist_ext;trivial.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  destruct c as [? [? [? ?]]].
  assert (decompose
        (BAF.lub
        (exist (fun t0 : ShareTree => canonicalTree t0)
        (Node (Leaf false) (Leaf true))
       (conj (or_introl (true = false) (Logic.eq_refl false))
                (conj (or_intror (false = true) (Logic.eq_refl true))
                   (conj I I))))
        (exist (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2)
        (conj n (conj n0 (conj c c0))))) =
        (exist (fun t0 : ShareTree => canonicalTree t0) x1 c, top)).
(* Goal: iff (@eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) (and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32)))) *)
   unfold BAF.lub.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
   unfold proj1_sig.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (mkCanon_correct (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
   assert (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2) = Node x1 (Leaf true)).
(* Goal: @eq t c0 c0 *)
     unfold union_tree;trivial.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (mkCanon_correct (union_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) x1 c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
   rewrite H0;clear H0.
(* Goal: @eq t match x1 with | Leaf (true as b) => t0 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) t1 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) t0 end bot *)
   icase x1.
   icase b;
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t c0 c0 *)
   apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq (prod BAF.t BAF.t) (@pair canonTree canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) match mkCanon_correct (Node (Leaf false) (Leaf true)) with | conj H H0 => @and_ind (or (@eq bool false true) (@eq bool true true)) (and True True) True (fun (_ : or (@eq bool false true) (@eq bool true true)) (H2 : and True True) => @and_ind True True True (fun H3 _ : True => H3) H2) H0 end) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) match mkCanon_correct (Node (Leaf false) (Leaf true)) with | conj H H0 => @and_ind (or (@eq bool false true) (@eq bool true true)) (and True True) True (fun (_ : or (@eq bool false true) (@eq bool true true)) (H2 : and True True) => @and_ind True True True (fun _ H4 : True => H4) H2) H0 end)) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) c) top) *)
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (Node x1_1 x1_2) (Leaf true))) (mkCanon_correct (Node (Node x1_1 x1_2) (Leaf true))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
   destruct (mkCanon_correct (Node (Leaf false) (Leaf true))) as [? [? [? ?]]].
(* Goal: @eq t c0 c0 *)
   apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (Node x1_1 x1_2) (Leaf true))) (mkCanon_correct (Node (Node x1_1 x1_2) (Leaf true))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
   assert (canonicalTree (Node (Node x1_1 x1_2) (Leaf true))).
    destruct c as [? [? [? ?]]];
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    firstorder.
   assert (exist (fun t0 : ShareTree => canonicalTree t0)
          (mkCanon (Node (Node x1_1 x1_2) (Leaf true)))
          (mkCanon_correct (Node (Node x1_1 x1_2) (Leaf true))) =
          (exist (fun t0 : ShareTree => canonicalTree t0) (Node (Node x1_1 x1_2) (Leaf true)) H0)).
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    destruct c as [? [? [? ?]]].
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_identity x1_1 c);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_identity x1_2 c1);intro.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H1;rewrite H2.
(* Goal: @eq ShareTree match match x1_1 with | Leaf b1 => match x1_2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x1_1 x1_2 | Node s s0 => Node x1_1 x1_2 end | Node s s0 => Node x1_1 x1_2 end with | Leaf b1 => if bool_dec b1 true then Leaf b1 else Node match x1_1 with | Leaf b2 => match x1_2 with | Leaf b3 => if bool_dec b2 b3 then Leaf b2 else Node x1_1 x1_2 | Node s s0 => Node x1_1 x1_2 end | Node s s0 => Node x1_1 x1_2 end (Leaf true) | Node s s0 => Node match x1_1 with | Leaf b1 => match x1_2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x1_1 x1_2 | Node s1 s2 => Node x1_1 x1_2 end | Node s1 s2 => Node x1_1 x1_2 end (Leaf true) end (Node (Node x1_1 x1_2) (Leaf true)) *)
(* Goal: @eq (prod BAF.t BAF.t) (@decompose BAF.t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (Node x1_1 x1_2) (Leaf true))) (mkCanon_correct (Node (Node x1_1 x1_2) (Leaf true))))) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
    icase x1_1;icase x1_2.
    icase b;icase b0;
    simpl;
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    elimtype False;firstorder.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
  rewrite H1.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: @eq (prod BAF.t BAF.t) (@pair canonTree canonTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) match H0 with | conj H H0 => @and_ind (or (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (@eq bool true true)) (and (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True) (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) (fun (_ : or (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (@eq bool true true)) (H2 : and (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True) => @and_ind (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) (fun (H3 : and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) (_ : True) => H3) H2) H0 end) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) match H0 with | conj H H0 => @and_ind (or (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (@eq bool true true)) (and (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True) True (fun (_ : or (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (@eq bool true true)) (H2 : and (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True) => @and_ind (and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) True True (fun (_ : and (or (nonFullTree x1_1) (nonFullTree x1_2)) (and (or (nonEmptyTree x1_1) (nonEmptyTree x1_2)) (and (canonicalTree x1_1) (canonicalTree x1_2)))) (H4 : True) => H4) H2) H0 end)) (@pair (@sig ShareTree (fun t0 : ShareTree => canonicalTree t0)) t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node x1_1 x1_2) c) top) *)
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
  destruct H0 as [? [? [? ?]]].
(* Goal: @eq t c0 c0 *)
  apply injective_projections;apply exist_ext;trivial.
(* Goal: @eq t (let (ltr2, rtr2) := tree_decompose (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf true)) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))))) in let (x, _) := bot in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel top rtr2 | Node s s0 => unrel bot ltr2 end) top *)
 unfold decompose,decompose_tree in *.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
 rewrite H0.
(* Goal: @eq t (let (x, _) := bot in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree bot in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
 unfold bot.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t (let (x, _) := top in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree top in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
 unfold top.
(* Goal: @eq t c0 c0 *)
 trivial.
Qed.


(*START HERE*)
  Fixpoint fullTreeP (t : ShareTree) (d  : nat): Prop :=
   match t with
    | Leaf b => d = 0
    | Node l r => (d > 0) /\ (fullTreeP l (d - 1)) /\ (fullTreeP r (d - 1))
   end.

  Definition fullTree (t : ShareTree) : Prop :=
   fullTreeP t (tree_heightP t).

  Fixpoint mkFull (d : nat)  (t : ShareTree) : option ShareTree :=
   match d with
    |0 => match t with
          |Leaf b => Some (Leaf b)
          |Node l r => None
          end
    |S n => match t with
            |Leaf b => match (mkFull n (Leaf b)) with
                       | Some t => Some (Node t t)
                       |_ => None
                       end
            |Node l r => match (mkFull n l, mkFull n r) with
                         | (Some t1, Some t2) => Some (Node t1 t2)
                         |_ => None
                         end
             end
   end.

  Fixpoint tree_round_leftP (n : nat) (t : ShareTree) : option ShareTree :=
    match n with
    | 0 => None
    | 1 => match t with
           | Node (Leaf b1) (Leaf b2) => Some (Leaf b1)
           |_=> None
           end
    | S n' => match t with
              | Leaf b => Some (Leaf b)
              | Node t1 t2 => match (tree_round_leftP n' t1, tree_round_leftP n' t2) with
                              | (Some t1', Some t2') => Some (Node t1' t2')
                              | _ => None
                              end
              end
    end.

   Definition tree_round_left (n : nat) (t : canonTree) : option canonTree:=
    match mkFull n (proj1_sig t) with
    | Some t' => match tree_round_leftP n t' with
                  | Some t'' => Some (exist (fun t => canonicalTree t) (mkCanon t'') (mkCanon_correct _))
                  | None => None
                  end
     | None => None
     end.
   Instance  roundableL_tree : roundableLeft t :=
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    RoundableLeft tree_round_left.

   Fixpoint tree_round_rightP (n : nat) (t : ShareTree) : option ShareTree :=
    match n with
    | 0 => None
    | 1 => match t with
           | Node (Leaf b1) (Leaf b2) => Some (Leaf b2)
           |_=> None
           end
    | S n' => match t with
              | Leaf b => Some (Leaf b)
              | Node t1 t2 => match (tree_round_rightP n' t1, tree_round_rightP n' t2) with
                              | (Some t1', Some t2') => Some (Node t1' t2')
                              | _ => None
                              end
              end
    end.

   Definition tree_round_right (n : nat) (t : canonTree) : option canonTree:=
    match mkFull n (proj1_sig t) with
    | Some t' => match tree_round_rightP n t' with
                  | Some t'' => Some (exist (fun t => canonicalTree t) (mkCanon t'') (mkCanon_correct _))
                  | None => None
                  end
     | None => None
     end.
  Instance  roundableR_tree : roundableRight t :=
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   RoundableRight tree_round_right.

   Fixpoint tree_avgP (t1 t2 : ShareTree) : option ShareTree :=
    match (t1,t2) with
    |(Leaf b1, Leaf b2) => Some (Node (Leaf b1) (Leaf b2))
    |(Node t11 t12, Node t21 t22) => match (tree_avgP t11 t21, tree_avgP t12 t22) with
                                     |(Some t1', Some t2') => Some (Node t1' t2')
                                     |_ => None
                                     end
    |_ => None
    end.

   Definition tree_avg (n : nat) (t1 t2 : canonTree) : option canonTree :=
    match n with
    |0 => None
    |S n' => match (mkFull n' (proj1_sig t1), mkFull n' (proj1_sig t2)) with
             |(Some t1', Some t2') => match (tree_avgP t1' t2') with
                                      |Some t' => Some (exist (fun t => canonicalTree t) (mkCanon t') (mkCanon_correct _))
                                      |None => None
                                      end
             |_ => None
             end
    end.
   Instance avgable_tree : avgable t :=
     Avgable tree_avg.

  Lemma compose_canon1 : forall b1 b2,b1 <> b2 -> canonicalTree (Leaf b1) ->
                                                  canonicalTree (Leaf b2) ->
                                                  canonicalTree (Node (Leaf b1) (Leaf b2)).
  Proof.
   intros;
(* Goal: @eq t c c *)
   try icase b1;try icase b2;compute in *;tauto.
  Qed.

  Lemma compose_canon2 : forall b t1 t2, canonicalTree (Leaf b) ->
                                         canonicalTree (Node t1 t2)->
                                         canonicalTree (Node (Leaf b) (Node t1 t2)).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
   simpl;
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   firstorder.
  Qed.

  Lemma compose_canon3 : forall t1 t2 b, canonicalTree (Node t1 t2)->
                                         canonicalTree (Leaf b) ->
                                         canonicalTree (Node (Node t1 t2) (Leaf b) ).
  Proof.
   intros;
   simpl;
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   firstorder.
  Qed.

  Lemma compose_canon4 : forall t1 t2 t3 t4, canonicalTree (Node t1 t2) ->
                                             canonicalTree (Node t3 t4) ->
                                             canonicalTree (Node (Node t1 t2) (Node t3 t4)).
  Proof.
   intros;
   simpl;
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   firstorder.
  Qed.

   Definition recompose (tt : (canonTree*canonTree)): canonTree :=
   let (t1, t2) := tt in
   let (x1, c1) := t1 in
   let (x2, c2) := t2 in
   match x1 as s return (canonicalTree s -> canonTree) with
   | Leaf b1 =>
       fun c3 : canonicalTree (Leaf b1) =>
       match x2 as s return (canonicalTree s -> canonTree) with
       | Leaf b2 =>
           fun c4 : canonicalTree (Leaf b2) =>
           match bool_dec b1 b2 with
           | left e =>
               let H :=
                 eq_rec b1
                   (fun b3 : bool => canonicalTree (Leaf b3) -> canonTree)
                   (fun _ : canonicalTree (Leaf b1) =>
                    exist (fun t : ShareTree => canonicalTree t) (Leaf b1) c3)
                   b2 e in
               H c4
           | right n =>
               exist (fun t : ShareTree => canonicalTree t)
                 (Node (Leaf b1) (Leaf b2)) (compose_canon1 b1 b2 n c3 c4)
           end
       | Node x21 x22 =>
           fun c4 : canonicalTree (Node x21 x22) =>
           exist (fun t : ShareTree => canonicalTree t)
                (Node (Leaf b1) (Node x21 x22)) (compose_canon2 b1 x21 x22 c3 c4)
       end c2
   | Node x11 x12 =>
       fun c3 : canonicalTree (Node x11 x12) =>
       match x2 as s return (canonicalTree s -> canonTree) with
       | Leaf b2 =>
           fun c4 : canonicalTree (Leaf b2) =>
           exist (fun t : ShareTree => canonicalTree t)
             (Node (Node x11 x12) (Leaf b2)) (compose_canon3 x11 x12 b2 c3 c4)
       | Node x21 x22 =>
           fun c4 : canonicalTree (Node x21 x22) =>
           exist (fun t : ShareTree => canonicalTree t)
             (Node (Node x11 x12) (Node x21 x22))
             (compose_canon4 x11 x12 x21 x22 c3 c4)
       end c2
   end c1.

(*End Definition*)


  Lemma tree_height_diff : forall t1 t2, height t1 <> height t2 -> t1 <> t2.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
    intro H1;apply H.
(* Goal: @eq t c0 c0 *)
    rewrite H1;trivial.
  Qed.

  Lemma fullTreeP_subL : forall n t1 t2, fullTreeP (Node t1 t2) (S n) -> fullTreeP t1 n.
   Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: fullTreeP t1 n *)
    destruct H as [_ [? _]].
(* Goal: le (S O) (S n) *)
    replace (n-0) with n in * by omega.
(* Goal: @eq t c0 c0 *)
    trivial.
   Qed.

  Lemma fullTreeP_subR : forall n t1 t2, fullTreeP (Node t1 t2) (S n) -> fullTreeP t2 n.
   Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: fullTreeP t2 n *)
    destruct H as [_ [_ ?]].
(* Goal: le (S O) (S n) *)
    replace (n-0) with n in * by omega.
(* Goal: @eq t c0 c0 *)
    trivial.
   Qed.

  Lemma fullTreeP_height : forall n t, fullTreeP t n -> tree_heightP t = n.
   Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction n;intros.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    destruct t0;inversion H.
(* Goal: @eq t c0 c0 *)
    simpl;trivial.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H0.
(* Goal: or (or (@eq t t0 top) (@eq t t0 bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex ((fun t : ShareTree => canonicalTree t) (Node t1 t2)) (fun c : (fun t : ShareTree => canonicalTree t) (Node t1 t2) => @eq t t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c))))) *)
    destruct t0.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: @eq nat (tree_heightP (Node t0_1 t0_2)) (S n) *)
    destruct H as [_ [? ?]].
(* Goal: le (S O) (S n) *)
    replace (n-0) with n in * by omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHn t0_1 H);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHn t0_2 H0);intro.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
    rewrite H1.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2.
(* Goal: le (S O) (S n) *)
    rewrite max_l; omega.
  Qed.

  Lemma fullTreeP_combine : forall t1 t2 n, fullTreeP t1 n -> fullTreeP t2 n ->
                                          fullTreeP (Node t1 t2) (S n).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
   split.
(* Goal: le (S O) (S n) *)
   omega.
   split;
   replace (n-0) with n in * by omega;
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.

  Lemma fullTree_double : forall t, fullTree t -> fullTree (Node t t).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: fullTree (Node t1 t2) *)
   unfold fullTree in *.
(* Goal: fullTreeP (Node t0 t0) (tree_heightP (Node t0 t0)) *)
   remember (tree_heightP (Node t0 t0)).
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
   icase n.
   simpl in  Heqn.
(* Goal: @eq t c0 c0 *)
   rewrite max_l in Heqn; trivial.
   destruct (tree_heightP t0);
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
   inversion Heqn.
   apply fullTreeP_combine;
   simpl in Heqn;
   rewrite max_l in Heqn;trivial;
   assert (n = tree_heightP t0) by omega;
   rewrite H0;
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.

  Lemma fullTree_sub : forall t1 t2, fullTree (Node t1 t2) <->
                                      (fullTree t1 /\ fullTree t2 /\ tree_heightP t1 = tree_heightP t2).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
    split.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: fullTree (Node t1 t2) *)
    unfold fullTree in *.
(* Goal: and (fullTreeP t1 (tree_heightP t1)) (and (fullTreeP t2 (tree_heightP t2)) (@eq nat (tree_heightP t1) (tree_heightP t2))) *)
(* Goal: forall _ : and (fullTree t1) (and (fullTree t2) (@eq nat (tree_heightP t1) (tree_heightP t2))), fullTree (Node t1 t2) *)
    remember (tree_heightP (Node t1 t2)).
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.
(* Goal: and (fullTreeP t1 (tree_heightP t1)) (and (fullTreeP t2 (tree_heightP t2)) (@eq nat (tree_heightP t1) (tree_heightP t2))) *)
(* Goal: and (fullTreeP t1 (tree_heightP t1)) (and (fullTreeP t2 (tree_heightP t2)) (@eq nat (tree_heightP t1) (tree_heightP t2))) *)
(* Goal: forall _ : and (fullTree t1) (and (fullTree t2) (@eq nat (tree_heightP t1) (tree_heightP t2))), fullTree (Node t1 t2) *)
    simpl in Heqn.
    destruct ( max (tree_heightP t1) (tree_heightP t2));
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
    inversion Heqn.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (fullTreeP_subL n t1 t2 H);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (fullTreeP_subR n t1 t2 H);intro.
(* Goal: and (fullTreeP t1 (tree_heightP t1)) (and (fullTreeP t2 (tree_heightP t2)) (@eq nat (tree_heightP t1) (tree_heightP t2))) *)
(* Goal: forall _ : and (fullTree t1) (and (fullTree t2) (@eq nat (tree_heightP t1) (tree_heightP t2))), fullTree (Node t1 t2) *)
    assert (tree_heightP t1 = n /\ tree_heightP t2 = n).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (fullTreeP_height n t1 H0);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (fullTreeP_height n t2 H1);intro.
(* Goal: @eq t c c *)
    tauto.
(* Goal: canonicalTree (Node t1 t2) *)
    destruct H2.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H3.
(* Goal: @eq t c c *)
    tauto.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    intro.
(* Goal: fullTree (Node t1 t2) *)
    destruct H as [? [? ?]].
(* Goal: fullTree (Node t1 t2) *)
    unfold fullTree in *.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    simpl in *.
(* Goal: and (gt (Init.Nat.add (PeanoNat.Nat.max (tree_heightP t1) (tree_heightP t2)) (S O)) O) (and (fullTreeP t1 (Init.Nat.sub (Init.Nat.add (PeanoNat.Nat.max (tree_heightP t1) (tree_heightP t2)) (S O)) (S O))) (fullTreeP t2 (Init.Nat.sub (Init.Nat.add (PeanoNat.Nat.max (tree_heightP t1) (tree_heightP t2)) (S O)) (S O)))) *)
    rewrite H1 in *.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
    split.
(* Goal: le (S O) (S n) *)
    destruct (max (tree_heightP t2) (tree_heightP t2));omega.
(* Goal: @eq t c0 c0 *)
    rewrite max_l;trivial.
(* Goal: le (S O) (S n) *)
    replace (tree_heightP t2 + 1 - 1) with (tree_heightP t2) in * by omega.
(* Goal: @eq t c c *)
    tauto.
  Qed.

  Lemma mkFull_height : forall n t t', mkFull n t = Some t' -> tree_heightP t' = n.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction n;intros.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    destruct t0;inversion H.
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    destruct t0;inversion H.
(* Goal: @eq ShareTree (mkCanon (Leaf b)) (mkCanon (Node t'1 t'2)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Leaf b)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
    remember (mkFull n (Leaf b)).
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
    destruct o.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    symmetry in Heqo.
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
    specialize ( IHn (Leaf b) s Heqo).
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (tree_height s1) s1) (countBLeafCT (tree_height s1) s2)) (countBLeafCT (tree_height s1) s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
    inversion H1.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq t c0 c0 *)
    rewrite max_l;trivial.
(* Goal: le (S O) (S n) *)
    omega.
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (tree_height s1) s1) (countBLeafCT (tree_height s1) s2)) (countBLeafCT (tree_height s1) s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
    inversion H1.
(* Goal: fullTree t' *)
    remember (mkFull n t0_1).
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
    destruct o.
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
    remember (mkFull n t0_2).
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
    destruct o.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    symmetry in Heqo.
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
    symmetry in Heqo0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHn t0_1 s Heqo);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHn t0_2 s0 Heqo0);intro.
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (tree_height s1) s1) (countBLeafCT (tree_height s1) s2)) (countBLeafCT (tree_height s1) s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
    inversion H1.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
    rewrite H0.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2.
(* Goal: @eq t c0 c0 *)
    rewrite max_l;trivial.
(* Goal: le (S O) (S n) *)
    omega.
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (tree_height s1) s1) (countBLeafCT (tree_height s1) s2)) (countBLeafCT (tree_height s1) s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
    inversion H1.
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (tree_height s1) s1) (countBLeafCT (tree_height s1) s2)) (countBLeafCT (tree_height s1) s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
    inversion H1.
  Qed.

  Lemma mkFull_correct : forall n t t', mkFull n t = Some t' -> fullTree t'.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   induction n;intros.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   destruct t0;inversion H.
(* Goal: @eq t (rel rightTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
   compute.
(* Goal: @eq t c0 c0 *)
   trivial.
(* Goal: or (or (@eq t t0 top) (@eq t t0 bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex ((fun t : ShareTree => canonicalTree t) (Node t1 t2)) (fun c : (fun t : ShareTree => canonicalTree t) (Node t1 t2) => @eq t t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c))))) *)
   destruct t0.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
   simpl in H.
(* Goal: @eq ShareTree (mkCanon (Leaf b)) (mkCanon (Node t'1 t'2)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Leaf b)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
   remember (mkFull n (Leaf b)).
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
   destruct o.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
   symmetry in Heqo.
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
   specialize ( IHn (Leaf b) s Heqo).
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   inversion H.
(* Goal: @eq t c0 c0 *)
   apply fullTree_double;trivial.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   inversion H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
   simpl in H.
(* Goal: fullTree t' *)
   remember (mkFull n t0_1).
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
   destruct o.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
   symmetry in Heqo.
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
   remember (mkFull n t0_2).
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
   destruct o.
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
   symmetry in Heqo0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (IHn t0_1 s Heqo);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (IHn t0_2 s0 Heqo0);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   inversion H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (fullTree_sub s s0);intro.
(* Goal: canonicalTree (Node t1 t2) *)
   destruct H2.
(* Goal: fullTree (Node s s0) *)
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
   apply H4.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkFull_height n t0_1 s Heqo);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkFull_height n t0_2 s0 Heqo0);intro.
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
   congruence.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   inversion H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   inversion H.
  Qed.

  Lemma mkFull_mkCanon : forall n t t', mkFull n t = Some t' ->
                                        mkCanon t = mkCanon t'.
  Proof.
   induction n;intros;
   icase t0;icase t';
(* Goal: @eq t c0 c0 *)
   inv H;trivial.

(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t1' => match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) *)
   icase (mkFull n (Leaf b)).
(* Goal: @eq ShareTree (mkCanon (Leaf b)) (mkCanon (Node t'1 t'2)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Leaf b)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
   remember (mkFull n (Leaf b)).
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
   icase o.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
   symmetry in Heqo.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
   inv H1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (IHn _ _ Heqo);intro.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq ShareTree (Leaf b) match mkCanon t'2 with | Leaf b1 => match mkCanon t'2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t'2) (mkCanon t'2) | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end | Node s s0 => Node (mkCanon t'2) (mkCanon t'2) end *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Leaf b)) *)
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
   rewrite<- H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase b.
   icase (mkFull n t0_1);
   icase (mkFull n t0_2).
   remember (mkFull n t0_1);
(* Goal: fullTree t' *)
(* Goal: fullTree t' *)
   remember (mkFull n t0_2).
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
   icase o;icase o0.
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
   symmetry in Heqo, Heqo0.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
   inv H1.
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
   generalize (IHn _ _ Heqo);intro H1.
(* Goal: @eq ShareTree (mkCanon (Node t0_1 t0_2)) (mkCanon (Node t'1 t'2)) *)
   generalize (IHn _ _ Heqo0);intro H2.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq nat (tree_heightP match mkCanon x3 with | Leaf b1 => match mkCanon x4 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x3) (mkCanon x4) | Node s s0 => Node (mkCanon x3) (mkCanon x4) end | Node s s0 => Node (mkCanon x3) (mkCanon x4) end) (S (S n)) *)
   rewrite H1,H2.
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.

  Lemma mkFull_split : forall n t1 t2 t1' t2',
                       mkFull (S n) (Node t1 t2) = Some (Node t1' t2') <->
                       (mkFull n t1 = Some t1' /\ mkFull n t2 = Some t2').
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    split;
    remember (mkFull n t1);
    remember (mkFull n t2);
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    icase o;icase o0;intros.
(* Goal: @eq t c c *)
    inv H;tauto.
(* Goal: @eq t c0 c0 *)
    destruct H as [H1 H2];inv H1; inv H2;trivial.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    destruct H as [H1 H2];inv H1;inv H2.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    destruct H as [H1 H2];inv H1;inv H2.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    destruct H as [H1 H2];inv H1;inv H2.
  Qed.

  Lemma mkFull_mkCanon_simpl : forall n t1 t2, mkFull (S n) (mkCanon (Node t1 t2)) =
                                       mkFull (S n) (Node (mkCanon t1) (mkCanon t2)).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq ShareTree match mkCanon t1 with | Leaf b1 => match mkCanon t2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t1) (mkCanon t2) | Node s s0 => Node (mkCanon t1) (mkCanon t2) end | Node s s0 => Node (mkCanon t1) (mkCanon t2) end match mkCanon t1 with | Leaf b1 => match mkCanon t2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t1) (mkCanon t2) | Node s s0 => Node (mkCanon t1) (mkCanon t2) end | Node s s0 => Node (mkCanon t1) (mkCanon t2) end *)
    icase (mkCanon t1);icase (mkCanon t2).
(* Goal: @eq t c0 c0 *)
    icase (bool_dec b b0);subst;trivial.
(* Goal: @eq (option ShareTree) match mkFull n (Leaf b0) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end match mkFull n (Leaf b0) with | Some t1 => match mkFull n (Leaf b0) with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end *)
    icase (mkFull n (Leaf b0)).
  Qed.

  Lemma mkFull_None : forall n t, n < tree_heightP t -> mkFull n t = None.
  Proof.
   induction n;intros;
(* Goal: @ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @eq ShareTree (mkCanon t0) (mkCanon (Node t1 t2)))) *)
   icase t0.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   inversion H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
   inversion H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
   simpl in H.
(* Goal: le (S O) (S n) *)
   assert (n < max (tree_heightP t0_1) (tree_heightP t0_2)) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (Nat.max_lt_iff);intro.
(* Goal: @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@None ShareTree) *)
   specialize ( H1 (tree_heightP t0_1) (tree_heightP t0_2) n).
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t11) (mkCanon t21))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t11) (mkCanon t21))) (mkCanon t31) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
   destruct H1 as [? _].
(* Goal: @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@None ShareTree) *)
   specialize ( H1 H0).
(* Goal: lt (tree_height t') (S n) *)
   destruct H1.
(* Goal: @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@None ShareTree) *)
(* Goal: @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@None ShareTree) *)
   specialize ( IHn t0_1 H1).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
   rewrite IHn;
(* Goal: @eq t c0 c0 *)
   trivial.
(* Goal: @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@None ShareTree) *)
   specialize ( IHn t0_2 H1).
(* Goal: @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@None ShareTree) *)
   simpl;rewrite IHn.
(* Goal: @eq t c0 c0 *)
   icase (mkFull n t0_1);trivial.
  Qed.

  Lemma mkFull_Some : forall n t, n >= tree_heightP t -> exists t', mkFull n t = Some t'.
  Proof.
    induction n;intros;
(* Goal: @ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @eq ShareTree (mkCanon t0) (mkCanon (Node t1 t2)))) *)
    icase t0.
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Node t0_1 t0_2)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    exists (Leaf b).
(* Goal: @eq (option ShareTree) (mkFull O (Leaf b)) (@Some ShareTree (Leaf b)) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Node t0_1 t0_2)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    compute;trivial.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H.
(* Goal: le (S O) (S n) *)
    elimtype False;omega.
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    assert (n >= tree_heightP (Leaf b)).
(* Goal: le (S O) (S n) *)
      compute;omega.
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    specialize ( IHn (Leaf b) H0).
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    destruct IHn.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
    rewrite H1.
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (@Some ShareTree (Node x x)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    exists (Node x x).
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: le (S O) (S n) *)
    assert (n >= max (tree_heightP t0_1) (tree_heightP t0_2)) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (le_max_l (tree_heightP t0_1) (tree_heightP t0_2));intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (le_max_r (tree_heightP t0_1) (tree_heightP t0_2));intro.
(* Goal: le (S O) (S n) *)
    assert (n >= tree_heightP t0_1) by omega.
(* Goal: le (S O) (S n) *)
    assert (n >= tree_heightP t0_2) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHn _ H3);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHn _ H4);intro.
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    destruct H5.
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
    destruct H6.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
    rewrite H5.
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) match mkFull n t0_2 with | Some t2 => @Some ShareTree (Node x t2) | None => @None ShareTree end (@Some ShareTree t')) *)
    rewrite H6.
(* Goal: @eq t c0 c0 *)
    exists (Node x x0);trivial.
  Qed.

  Lemma mkCanon_eq_split : forall t1 t2 t1' t2', mkCanon (Node t1 t2) = mkCanon (Node t1' t2')
                                                -> mkCanon t1 = mkCanon t1' /\ mkCanon t2 = mkCanon t2'.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
    icase (mkCanon t1);icase (mkCanon t2);
    icase (mkCanon t1');icase (mkCanon t2');
    try icase (bool_dec b b0);try icase (bool_dec b1 b2);inversion H;try subst;auto;
    try icase (bool_dec b0 b1).
  Qed.

  Lemma mkCanon_simpl : forall t1 t2, mkCanon (Node (mkCanon t1) (mkCanon t2)) = mkCanon (Node t1 t2).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_double t1);intro.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
    rewrite H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_double t2);intro.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
    rewrite H0.
(* Goal: @eq ShareTree match mkCanon t1 with | Leaf b1 => match mkCanon t2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t1) (mkCanon t2) | Node s s0 => Node (mkCanon t1) (mkCanon t2) end | Node s s0 => Node (mkCanon t1) (mkCanon t2) end match mkCanon t1 with | Leaf b1 => match mkCanon t2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t1) (mkCanon t2) | Node s s0 => Node (mkCanon t1) (mkCanon t2) end | Node s s0 => Node (mkCanon t1) (mkCanon t2) end *)
    icase (mkCanon t1);icase (mkCanon t2).
  Qed.

  Lemma mkCanon_height : forall t t', mkCanon t = t' ->  tree_heightP t' <= tree_heightP t.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   induction t0;intros.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkCanon_Leaf b);intro.
(* Goal: le (tree_heightP t') (tree_heightP (Leaf b)) *)
(* Goal: le (tree_heightP t') (tree_heightP (Node t0_1 t0_2)) *)
   rewrite H in H0.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
   rewrite H0.
(* Goal: le (S O) (S n) *)
   omega.

(* Goal: le (tree_heightP t') (tree_heightP (Node t0_1 t0_2)) *)
   icase t'.
(* Goal: le (tree_heightP (Leaf b)) (tree_heightP (Node t0_1 t0_2)) *)
(* Goal: le (tree_heightP (Node t'1 t'2)) (tree_heightP (Node t0_1 t0_2)) *)
   symmetry in H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkCanon_Leaf_split _ _ _ H);intro.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkCanon_split _ _ _ _ H);intro.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   destruct H0 as [? ?].
(* Goal: le (tree_heightP (Node t'1 t'2)) (tree_heightP (Node t0_1 t0_2)) *)
   specialize ( IHt0_1 t'1 H0).
(* Goal: le (tree_heightP (Node t'1 t'2)) (tree_heightP (Node t0_1 t0_2)) *)
   specialize (IHt0_2 t'2 H1).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (Init.Nat.add (PeanoNat.Nat.max (tree_heightP t'1) (tree_heightP t'2)) (S O)) (Init.Nat.add (PeanoNat.Nat.max (tree_heightP t0_1) (tree_heightP t0_2)) (S O)) *)
   assert (max (tree_heightP t'1) (tree_heightP t'2) <= max (tree_heightP t0_1) (tree_heightP t0_2) ).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (le_max_l (tree_heightP t0_1) (tree_heightP t0_2));intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (le_max_r (tree_heightP t0_1) (tree_heightP t0_2));intro.
(* Goal: le (S O) (S n) *)
    apply max_lub;omega.
(* Goal: le (S O) (S n) *)
   omega.
  Qed.

  Lemma mkCanon_rewrite : forall t, exists t1, exists t2, mkCanon t = mkCanon (Node t1 t2).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: @ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @eq ShareTree (mkCanon t0) (mkCanon (Node t1 t2)))) *)
   icase t0.
   exists (Leaf b);
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Node t0_1 t0_2)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
   exists (Leaf b).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase b.

(* Goal: @eq t c0 c0 *)
   exists t0_1;exists t0_2;trivial.
  Qed.

  Lemma canonTree_rewrite1 : forall (t' : canonTree), exists t1, exists t2,
                            t' = (exist (fun t => canonicalTree t)
                           (mkCanon (Node t1 t2))
                           (mkCanon_correct _)).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: @ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @eq canonTree t' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1 t2)) (mkCanon_correct (Node t1 t2))))) *)
   destruct t' as [x c].
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   icase x.
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull O (Node t0_1 t0_2)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Leaf b)) (@Some ShareTree t')) *)
(* Goal: @ex ShareTree (fun t' : ShareTree => @eq (option ShareTree) (mkFull (S n) (Node t0_1 t0_2)) (@Some ShareTree t')) *)
   exists (Leaf b);exists (Leaf b).
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase b.
   exists x1;
(* Goal: @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node x1 t2)) (fun c0 : canonicalTree (Node x1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 t2) c0))) *)
   exists x2.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t s bot *)
(* Goal: @identity t Join_ba s *)
   symmetry.
(* Goal: @eq ShareTree (mkCanon (Node x1 x2)) (Node x1 x2) *)
   apply mkCanon_identity.
(* Goal: @eq t c0 c0 *)
   trivial.
   Qed.

  Lemma canonTree_rewrite2: forall (t : canonTree), t =
        exist (fun t => canonicalTree t) (mkCanon (proj1_sig t)) (mkCanon_correct _).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: sumbool (@eq nat (tree_height t0) O) (not (@eq nat (tree_height t0) O)) *)
   destruct t0 as [x c].
(* Goal: @eq t c0 c0 *)
   apply exist_ext;simpl;trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkCanon_identity x c);intro.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
   congruence.
  Qed.

  Lemma mkCanon_height_split : forall n t11 t12 t21 t22,
        max (tree_heightP (mkCanon (Node t11 t12)))
            (tree_heightP (mkCanon (Node t21 t22))) < S (S n) ->
        max (tree_heightP (mkCanon t11))
            (tree_heightP (mkCanon t21)) < S n /\
        max (tree_heightP (mkCanon t12))
            (tree_heightP (mkCanon t22)) < S n.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
   remember (mkCanon (Node t11 t12));
   remember (mkCanon (Node t21 t22)).
(* Goal: @eq ShareTree (mkCanon (intersect_tree s s0)) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
   icase s;icase s0.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
   generalize (mkCanon_Leaf_split _ _ _ Heqs);intro H1.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
   generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro H2.
   destruct H1 as [H11 H12];
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   destruct H2 as [H21 H22].
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   rewrite H11,H12,H21,H22.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   omega.

(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
   symmetry in Heqs0.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
   generalize (mkCanon_Leaf_split _ _ _ Heqs);intro H1.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   generalize (mkCanon_split _ _ _ _ Heqs0);intro H2.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   destruct H1 as [H11 H12].
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   destruct H2 as [H21 H22].
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   rewrite H11,H12,H21,H22.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
   simpl in H.
(* Goal: le (S O) (S n) *)
   assert (max (tree_heightP s0_1) (tree_heightP s0_2) < S n) by omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: and (lt (tree_heightP s0_1) (S n)) (lt (tree_heightP s0_2) (S n)) *)
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   generalize (le_max_l (tree_heightP s0_1) (tree_heightP s0_2));intro H31.
(* Goal: and (lt (tree_heightP s0_1) (S n)) (lt (tree_heightP s0_2) (S n)) *)
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   generalize (le_max_r (tree_heightP s0_1) (tree_heightP s0_2));intro H32.
(* Goal: le (S O) (S n) *)
   omega.

(* Goal: iff (@eq (option ShareTree) (mkFull (S n) (Node s1 s2)) (@Some ShareTree (Node t1' t2'))) (and (@eq (option ShareTree) (mkFull n (mkCanon t1)) (@Some ShareTree t1')) (@eq (option ShareTree) (mkFull n (mkCanon t2)) (@Some ShareTree t2'))) *)
   symmetry in Heqs.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   generalize (mkCanon_split _ _ _ _ Heqs);intro H1.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
   generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro H2.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   destruct H1 as [H11 H12].
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   destruct H2 as [H21 H22].
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   rewrite H11,H12,H21,H22.
   replace (max (tree_heightP (Node s1 s2)) (tree_heightP (Leaf b)))
   with (max (tree_heightP (Leaf b)) (tree_heightP (Node s1 s2)) ) in H
   by apply max_comm.
   replace (max (tree_heightP s1) (tree_heightP (Leaf b)))
   with (max (tree_heightP (Leaf b)) (tree_heightP s1))
   by apply max_comm.
   replace (max (tree_heightP s2) (tree_heightP (Leaf b)))
   with (max (tree_heightP (Leaf b)) (tree_heightP s2))
   by apply max_comm.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
   simpl in H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   assert (max (tree_heightP s1) (tree_heightP s2) < S n) by omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: and (lt (tree_heightP s1) (S n)) (lt (tree_heightP s2) (S n)) *)
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   generalize (le_max_l (tree_heightP s1) (tree_heightP s2));intro H31.
(* Goal: and (lt (tree_heightP s1) (S n)) (lt (tree_heightP s2) (S n)) *)
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   generalize (le_max_r (tree_heightP s1) (tree_heightP s2));intro H32.
(* Goal: le (S O) (S n) *)
   omega.

(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
   symmetry in Heqs,Heqs0.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   generalize (mkCanon_split _ _ _ _ Heqs);intro H1.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   generalize (mkCanon_split _ _ _ _ Heqs0);intro H2.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   destruct H1 as [H11 H12].
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   destruct H2 as [H21 H22].
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
   rewrite H11,H12,H21,H22.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
   simpl in H.
   generalize (plus_max_distr_r (max (tree_heightP s1) (tree_heightP s2))
                                (max (tree_heightP s0_1) (tree_heightP s0_2))
                                 1);
(* Goal: not (@eq t (glb s s') s) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
   intro H3.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s0_1)) (S n)) (lt (PeanoNat.Nat.max (tree_heightP s2) (tree_heightP s0_2)) (S n)) *)
   rewrite H3 in H.
   assert (max (max (tree_heightP s1) (tree_heightP s2))
(* Goal: le (S O) (S n) *)
               (max (tree_heightP s0_1) (tree_heightP s0_2)) < S n) by omega.
   generalize (le_max_r (max (tree_heightP s1) (tree_heightP s2))
                        (max (tree_heightP s0_1) (tree_heightP s0_2)));intro H4.
   generalize (le_max_l (max (tree_heightP s1) (tree_heightP s2))
                        (max (tree_heightP s0_1) (tree_heightP s0_2)));intro H5.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s0_1)) (S n)) (lt (PeanoNat.Nat.max (tree_heightP s2) (tree_heightP s0_2)) (S n)) *)
   generalize (le_max_r (tree_heightP s1) (tree_heightP s2));intro H6.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s0_1)) (S n)) (lt (PeanoNat.Nat.max (tree_heightP s2) (tree_heightP s0_2)) (S n)) *)
   generalize (le_max_l (tree_heightP s1) (tree_heightP s2));intro H7.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s0_1)) (S n)) (lt (PeanoNat.Nat.max (tree_heightP s2) (tree_heightP s0_2)) (S n)) *)
   generalize (le_max_r (tree_heightP s0_1) (tree_heightP s0_2));intro H8.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s0_1)) (S n)) (lt (PeanoNat.Nat.max (tree_heightP s2) (tree_heightP s0_2)) (S n)) *)
   generalize (le_max_l (tree_heightP s0_1) (tree_heightP s0_2));intro H9.
(* Goal: le (S O) (S n) *)
   assert (tree_heightP s1 <= n) by omega.
(* Goal: le (S O) (S n) *)
   assert (tree_heightP s2 <= n) by omega.
(* Goal: le (S O) (S n) *)
   assert (tree_heightP s0_1 <= n) by omega.
(* Goal: le (S O) (S n) *)
   assert (tree_heightP s0_2 <= n) by omega.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s0_1)) (S n)) (lt (PeanoNat.Nat.max (tree_heightP s2) (tree_heightP s0_2)) (S n)) *)
   generalize (max_lub _ _ _ H1 H10);intro H14.
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s0_1)) (S n)) (lt (PeanoNat.Nat.max (tree_heightP s2) (tree_heightP s0_2)) (S n)) *)
   generalize (max_lub _ _ _ H2 H13);intro H15.
(* Goal: le (S O) (S n) *)
   omega.
  Qed.

  Lemma mkCanon_diff : forall t11 t12 t21 t22,
                       mkCanon (Node t11 t12) <> mkCanon (Node t21 t22) ->
                       mkCanon t11 <> mkCanon t21 \/
                       mkCanon t12 <> mkCanon t22.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: or (not (@eq ShareTree (mkCanon t11) (mkCanon t21))) (not (@eq ShareTree (mkCanon t12) (mkCanon t22))) *)
   generalize (shareTree_dec_eq (mkCanon t11) (mkCanon t21));intro H1.
(* Goal: lt (tree_height t') (S n) *)
   destruct H1.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   right.
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
   intro H1;apply H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t c0 c0 *)
   rewrite e,H1;trivial.

(* Goal: @eq t c0 c0 *)
   left;trivial.
  Qed.

  Lemma canonTree_proof_irr: forall t1 t2 c1 c2, t1 = t2 -> exist (fun t => canonicalTree t) t1 c1 =
                                                            exist (fun t => canonicalTree t) t2 c2.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: @eq t c0 c0 *)
   apply exist_ext;trivial.
  Qed.

  Lemma canonTree_combine : forall t1 t2, canonicalTree t1 ->
                                          canonicalTree t2 ->
                                          max (tree_heightP t1) (tree_heightP t2) > 0 ->
                                          canonicalTree (Node t1 t2).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: canonicalTree (Node t1 t2) *)
    generalize (max_dec (tree_heightP t1) (tree_heightP t2));intro H2.
(* Goal: canonicalTree (Node t1 t2) *)
    destruct H2.
(* Goal: canonicalTree (Node t1 t2) *)
    rewrite e in H1.
(* Goal: @eq t match t1 with | Leaf (true as b) => a1 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) a2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) a1 end (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
    icase t1.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
    inv H1.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    simpl in *.
(* Goal: @eq t c c *)
    tauto.
(* Goal: canonicalTree (Node t1 t2) *)
    rewrite e in H1.
(* Goal: canonicalTree (Node t1 t2) *)
    icase t2.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
    inv H1.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    simpl in *.
(* Goal: @eq t c c *)
    tauto.
  Qed.

  Lemma mkCanon_intersect : forall t1 t2, mkCanon (intersect_tree (mkCanon t1) (mkCanon t2)) =
                                          mkCanon (intersect_tree t1 t2).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
    assert (exists n, n >= max (tree_heightP t1) (tree_heightP t2)).
(* Goal: le (S O) (S n) *)
      exists (max (tree_heightP t1) (tree_heightP t2));omega.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
    destruct H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
    revert H.
(* Goal: forall _ : ge x (PeanoNat.Nat.max (tree_heightP t1) (tree_heightP t2)), @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
    revert t2 t1.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction x;intros.
(* Goal: @ex bool (fun b1 : bool => @ex bool (fun b2 : bool => and (@eq ShareTree t1 (Leaf b1)) (and (@eq ShareTree t2 (Leaf b2)) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b2) (canonTree_Leaf b2)))))) *)
      icase t1;icase t2.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
      remember (tree_heightP (Node t2_1 t2_2)).
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
      icase n.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Leaf b)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Leaf b) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
      inversion Heqn.
(* Goal: le (S O) (S n) *)
      destruct (max (tree_heightP t2_1) (tree_heightP t2_2));elimtype False ;omega.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
      inversion H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
      inversion H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t1) (mkCanon t2))) (mkCanon (intersect_tree t1 t2)) *)
      destruct (max (tree_heightP t1_1) (tree_heightP t1_2));inversion H1.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
      inversion H.
      destruct (max (tree_heightP t1_1) (tree_heightP t1_2));
      destruct (max (tree_heightP t2_1) (tree_heightP t2_2));
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (tree_height s1) s1) (countBLeafCT (tree_height s1) s2)) (countBLeafCT (tree_height s1) s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
      inversion H1.
(* Goal: @ex bool (fun b1 : bool => @ex bool (fun b2 : bool => and (@eq ShareTree t1 (Leaf b1)) (and (@eq ShareTree t2 (Leaf b2)) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b2) (canonTree_Leaf b2)))))) *)
    icase t1;icase t2.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    replace (mkCanon (Leaf b)) with (Leaf b) by apply mkCanon_Leaf.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf true) (mkCanon (Node t1_1 t1_2)))) (mkCanon (intersect_tree (Leaf true) (Node t1_1 t1_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    unfold intersect_tree.
(* Goal: @eq ShareTree (mkCanon (mkCanon (Node t1_1 t1_2))) (mkCanon (Node t1_1 t1_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    apply mkCanon_double.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Leaf b)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Leaf b))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    replace (mkCanon (Leaf b)) with (Leaf b) by apply mkCanon_Leaf.
    replace (intersect_tree (mkCanon (Node t1_1 t1_2)) (Leaf b))
    with (intersect_tree(Leaf b)(mkCanon (Node t1_1 t1_2)))
    by apply intersect_commute.
    replace (intersect_tree ( (Node t1_1 t1_2)) (Leaf b))
    with (intersect_tree(Leaf b)(Node t1_1 t1_2))
    by apply intersect_commute.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf true) (mkCanon (Node t1_1 t1_2)))) (mkCanon (intersect_tree (Leaf true) (Node t1_1 t1_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    unfold intersect_tree.
(* Goal: @eq ShareTree (mkCanon (mkCanon (Node t1_1 t1_2))) (mkCanon (Node t1_1 t1_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    apply mkCanon_double.

(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    assert (x >= max (tree_heightP t1_1) (tree_heightP t2_1)).
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
      simpl in H.
      replace (max (tree_heightP t1_1) (tree_heightP t1_2) + 1)
      with (S (max (tree_heightP t1_1) (tree_heightP t1_2)))
(* Goal: le (S O) (S n) *)
      in H by omega.
      replace (max (tree_heightP t2_1) (tree_heightP t2_2) + 1)
      with (S (max (tree_heightP t2_1) (tree_heightP t2_2)))
(* Goal: le (S O) (S n) *)
      in H by omega.
      generalize (succ_max_distr ((max (tree_heightP t1_1) (tree_heightP t1_2)))
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      ((max (tree_heightP t2_1) (tree_heightP t2_2))));intro.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t2_1)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      rewrite<- H0 in H;clear H0.
      assert (x >= max (max (tree_heightP t1_1) (tree_heightP t1_2))
(* Goal: le (S O) (S n) *)
         (max (tree_heightP t2_1) (tree_heightP t2_2))) by omega.
      assert (max (max (tree_heightP t1_1) (tree_heightP t1_2))
       (max (tree_heightP t2_1) (tree_heightP t2_2)) >= max (tree_heightP t1_1) (tree_heightP t1_2)).
(* Goal: ge (PeanoNat.Nat.max (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2))) (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_l.
      assert (max (max (tree_heightP t1_1) (tree_heightP t1_2))
       (max (tree_heightP t2_1) (tree_heightP t2_2)) >= max (tree_heightP t2_1) (tree_heightP t2_2)).
(* Goal: ge (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2)) (tree_heightP t2_2) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_r.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t2_1)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      assert (max (tree_heightP t1_1) (tree_heightP t1_2) >= tree_heightP t1_1).
(* Goal: ge (PeanoNat.Nat.max (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2))) (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_l.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t2_1)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      assert (max (tree_heightP t2_1) (tree_heightP t2_2) >= tree_heightP t2_1).
(* Goal: ge (PeanoNat.Nat.max (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2))) (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_l.
(* Goal: le (S O) (S n) *)
      apply max_lub;omega.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    assert (x >= max (tree_heightP t1_2) (tree_heightP t2_2)).
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
      simpl in H.
      replace (max (tree_heightP t1_1) (tree_heightP t1_2) + 1)
      with (S (max (tree_heightP t1_1) (tree_heightP t1_2)))
(* Goal: le (S O) (S n) *)
      in H by omega.
      replace (max (tree_heightP t2_1) (tree_heightP t2_2) + 1)
      with (S (max (tree_heightP t2_1) (tree_heightP t2_2)))
(* Goal: le (S O) (S n) *)
      in H by omega.
      generalize (succ_max_distr ((max (tree_heightP t1_1) (tree_heightP t1_2)))
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      ((max (tree_heightP t2_1) (tree_heightP t2_2))));intro.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      rewrite<- H1 in H;clear H1.
      assert (x >= max (max (tree_heightP t1_1) (tree_heightP t1_2))
(* Goal: le (S O) (S n) *)
         (max (tree_heightP t2_1) (tree_heightP t2_2))) by omega.
      assert (max (max (tree_heightP t1_1) (tree_heightP t1_2))
       (max (tree_heightP t2_1) (tree_heightP t2_2)) >= max (tree_heightP t1_1) (tree_heightP t1_2)).
(* Goal: ge (PeanoNat.Nat.max (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2))) (PeanoNat.Nat.max (tree_heightP t1_1) (tree_heightP t1_2)) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_l.
      assert (max (max (tree_heightP t1_1) (tree_heightP t1_2))
       (max (tree_heightP t2_1) (tree_heightP t2_2)) >= max (tree_heightP t2_1) (tree_heightP t2_2)).
(* Goal: ge (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2)) (tree_heightP t2_2) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_r.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      assert (max (tree_heightP t1_1) (tree_heightP t1_2) >= tree_heightP t1_2).
(* Goal: ge (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2)) (tree_heightP t2_2) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_r.
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
      assert (max (tree_heightP t2_1) (tree_heightP t2_2) >= tree_heightP t2_2).
(* Goal: ge (PeanoNat.Nat.max (tree_heightP t2_1) (tree_heightP t2_2)) (tree_heightP t2_2) *)
(* Goal: ge x (PeanoNat.Nat.max (tree_heightP t1_2) (tree_heightP t2_2)) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon (Node t1_1 t1_2)) (mkCanon (Node t2_1 t2_2)))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
       apply le_max_r.
(* Goal: le (S O) (S n) *)
      apply max_lub;omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHx _ _ H0);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHx _ _ H1);intro.
    remember (mkCanon (Node t1_1 t1_2));
    remember (mkCanon (Node t2_1 t2_2)).
(* Goal: @eq ShareTree (mkCanon (intersect_tree s s0)) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    icase s;icase s0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H4 as [H41 H42].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H5 as [H51 H52].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H41 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Leaf b0))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H51 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H42 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Leaf b0))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H52 in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    rewrite<-  H2.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    rewrite<- H3.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf b0);intro.
(* Goal: @eq ShareTree (mkCanon (Leaf b0)) match mkCanon (Leaf b0) with | Leaf b1 => match mkCanon (Leaf b0) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) | Node s s0 => Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) end | Node s s0 => Node (mkCanon (Leaf b0)) (mkCanon (Leaf b0)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H4.
(* Goal: @eq t c0 c0 *)
    icase (bool_dec b0 b0);trivial.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    firstorder.


(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Leaf b) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    symmetry in Heqs0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_split _ _ _ _ Heqs0);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H4 as [H41 H42].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H5 as [H51 H52].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H41 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H42 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H51 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node (mkCanon t2_1) s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H52 in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq ShareTree (mkCanon (if b then Node (mkCanon t1_1) (mkCanon t1_2) else Leaf false)) match mkCanon (intersect_tree t1_1 t2_1) with | Leaf b1 => match mkCanon (intersect_tree t1_2 t2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H2.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    rewrite<-H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.

(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro.
(* Goal: iff (@eq (option ShareTree) (mkFull (S n) (Node s1 s2)) (@Some ShareTree (Node t1' t2'))) (and (@eq (option ShareTree) (mkFull n (mkCanon t1)) (@Some ShareTree t1')) (@eq (option ShareTree) (mkFull n (mkCanon t2)) (@Some ShareTree t2'))) *)
    symmetry in Heqs.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_split _ _ _ _ Heqs);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H4 as [H41 H42].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H5 as [H51 H52].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H41 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Leaf b))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite H42 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H51 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node (mkCanon t2_1) s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H52 in *.
    replace (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Leaf b))
    with (intersect_tree (Leaf b) (Node (mkCanon t1_1) (mkCanon t1_2)))
    by apply intersect_commute.
    replace (intersect_tree (mkCanon t1_1) (Leaf b))
    with (intersect_tree (Leaf b)(mkCanon t1_1)) in H2
    by apply intersect_commute.
    replace (intersect_tree (mkCanon t1_2) (Leaf b))
    with (intersect_tree (Leaf b)(mkCanon t1_2)) in H3
    by apply intersect_commute.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq ShareTree (mkCanon (if b then Node (mkCanon t1_1) (mkCanon t1_2) else Leaf false)) match mkCanon (intersect_tree t1_1 t2_1) with | Leaf b1 => match mkCanon (intersect_tree t1_2 t2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end | Node s s0 => Node (mkCanon (intersect_tree t1_1 t2_1)) (mkCanon (intersect_tree t1_2 t2_2)) end *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H2.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    rewrite<-H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.

(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    symmetry in Heqs, Heqs0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_split _ _ _ _ Heqs);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_split _ _ _ _ Heqs0);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H4 as [H41 H42].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H5 as [H51 H52].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H41 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<- H42 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H51 in *.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node (mkCanon t1_1) (mkCanon t1_2)) (Node (mkCanon t2_1) s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    rewrite<-H52 in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H3.
(* Goal: @eq t c0 c0 *)
    trivial.
  Qed.

  Lemma mkCanon_join_split : forall t11 t12 t21 t22 t31 t32,
                     join (exist (fun t => canonicalTree t)(mkCanon (Node t11 t12)) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon (Node t21 t22)) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon (Node t31 t32)) (mkCanon_correct _))->
                     join (exist (fun t => canonicalTree t)(mkCanon t11) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon t21) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon t31) (mkCanon_correct _))/\
                     join (exist (fun t => canonicalTree t)(mkCanon t12) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon t22) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon t32) (mkCanon_correct _)).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: and (@join (@sig ShareTree (fun t : ShareTree => canonicalTree t)) Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31))) (@join (@sig ShareTree (fun t : ShareTree => canonicalTree t)) Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t22) (mkCanon_correct t22)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32))) *)
    red in H. hnf in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
    destruct H. split; red; hnf;
    inversion H;
    inversion H0;
    split;
    unfold BAF.glb, BAF.lub;
    apply exist_ext;
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.

(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    clear - H2.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    assert (Leaf false = mkCanon (Node (Leaf false) (Leaf false))).
(* Goal: @eq t c c *)
      compute;auto.
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
    rewrite H in H2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_intersect ((Node t11 t12)) ((Node t21 t22)));intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H0.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    rewrite H3 in H2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_eq_split _ _ _ _ H2);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t11) (mkCanon t21))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t11) (mkCanon t21))) (mkCanon t31) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    destruct H1 as [? _].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    assert (mkCanon (Leaf false) = Leaf false).
(* Goal: @eq t c c *)
      compute;auto.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    rewrite H4 in H1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_intersect t11 t21);intro.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
    rewrite H5.
(* Goal: @eq t c0 c0 *)
    trivial.

(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
    clear - H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_union((Node t11 t12)) ((Node t21 t22)));intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H.
(* Goal: and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32))) *)
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    rewrite H1 in H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_eq_split _ _ _ _ H3);intro.
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t11) (mkCanon t21))) (mkCanon t31) *)
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    destruct H0 as [? _].
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_union t11 t21);intro.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2.
(* Goal: @eq t c0 c0 *)
    trivial.

(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    clear - H2.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    assert (Leaf false = mkCanon (Node (Leaf false) (Leaf false))).
(* Goal: @eq t c c *)
      compute;auto.
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
    rewrite H in H2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_intersect ((Node t11 t12)) ((Node t21 t22)));intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H0.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    rewrite H3 in H2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_eq_split _ _ _ _ H2);intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    destruct H1 as [_ ?].
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    assert (mkCanon (Leaf false) = Leaf false).
(* Goal: @eq t c c *)
      compute;auto.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (mkCanon t12) (mkCanon t22))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    rewrite H4 in H1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_intersect t12 t22);intro.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
    rewrite H5.
(* Goal: @eq t c0 c0 *)
    trivial.

(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
    clear - H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_union((Node t11 t12)) ((Node t21 t22)));intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H.
(* Goal: and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32))) *)
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    rewrite H1 in H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_eq_split _ _ _ _ H3);intro.
(* Goal: @eq ShareTree (mkCanon (union_tree (mkCanon t12) (mkCanon t22))) (mkCanon t32) *)
    destruct H0 as [_ ?].
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_union t12 t22);intro.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2.
(* Goal: @eq t c0 c0 *)
    trivial.
  Qed.

  Lemma mkCanon_join_combine : forall t11 t12 t21 t22 t31 t32,
                     join (exist (fun t => canonicalTree t)(mkCanon t11) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon t21) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon t31) (mkCanon_correct _))->
                     join (exist (fun t => canonicalTree t)(mkCanon t12) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon t22) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon t32) (mkCanon_correct _))->
                     join (exist (fun t => canonicalTree t)(mkCanon (Node t11 t12)) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon (Node t21 t22)) (mkCanon_correct _))
                          (exist (fun t => canonicalTree t)(mkCanon (Node t31 t32)) (mkCanon_correct _)).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @join (@sig ShareTree (fun t : ShareTree => canonicalTree t)) Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    hnf in *.
(* Goal: and (@eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) bot) (@eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
    destruct H as [H11 H12].
(* Goal: and (@eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) bot) (@eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
    destruct H0 as [H21 H22].
(* Goal: and (@eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) bot) (@eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
    unfold BAF.glb, BAF.lub in *.
(* Goal: and (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon_correct (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22))))))) bot) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22))))))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
    inv H11;inv H12;inv H21;inv H22.
    split;
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.

(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    generalize (mkCanon_intersect t11 t21);intro H31.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    generalize (mkCanon_intersect t12 t22);intro H32.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    generalize (mkCanon_intersect (Node t11 t12) (Node t21 t22));intro H33.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    rewrite H31 in H0;clear H31.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    rewrite H32 in H2;clear H32.
    simpl;simpl in H33;
    rewrite H33;clear H33.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
    rewrite H0.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2.
(* Goal: @eq ShareTree (if bool_dec false false then Leaf false else Node (Leaf false) (Leaf false)) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    icase (bool_dec false false).
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    firstorder.

(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    generalize (mkCanon_union t11 t21);intro H31.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    generalize (mkCanon_union t12 t22);intro H32.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    generalize (mkCanon_union (Node t11 t12) (Node t21 t22));intro H33.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    rewrite H31 in H1;clear H31.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    rewrite H32 in H3;clear H32.
    simpl;simpl in H33;
    rewrite H33;clear H33.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
    rewrite H1.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H3.
(* Goal: @eq t c0 c0 *)
    trivial.
  Qed.

  Lemma mkCanon_mkFull_split : forall n t1 t2 t1' t2', mkFull (S n) (mkCanon (Node t1 t2)) =
                                                 Some (Node t1' t2') <->
                                                 mkFull n (mkCanon t1) = Some t1' /\
                                                 mkFull n (mkCanon t2) = Some t2'.
  Proof.
    intros;
    remember (mkCanon (Node t1 t2));
(* Goal: or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) s pf) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) s pf) bot) *)
    icase s.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs);intro H1.
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
    destruct H1 as [H1 H2].
(* Goal: @eq nat (tree_heightP match mkCanon x3 with | Leaf b1 => match mkCanon x4 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x3) (mkCanon x4) | Node s s0 => Node (mkCanon x3) (mkCanon x4) end | Node s s0 => Node (mkCanon x3) (mkCanon x4) end) (S (S n)) *)
    rewrite H1,H2.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    icase (mkFull n (Leaf b));
    split;intro H;inv H;auto;
(* Goal: @eq t c c *)
    inv H0;inv H3;auto.

(* Goal: iff (@eq (option ShareTree) (mkFull (S n) (Node s1 s2)) (@Some ShareTree (Node t1' t2'))) (and (@eq (option ShareTree) (mkFull n (mkCanon t1)) (@Some ShareTree t1')) (@eq (option ShareTree) (mkFull n (mkCanon t2)) (@Some ShareTree t2'))) *)
    symmetry in Heqs.
(* Goal: iff (@eq (option ShareTree) (mkFull (S n) (Node s1 s2)) (@Some ShareTree (Node t1' t2'))) (and (@eq (option ShareTree) (mkFull n (mkCanon t1)) (@Some ShareTree t1')) (@eq (option ShareTree) (mkFull n (mkCanon t2)) (@Some ShareTree t2'))) *)
    generalize (mkCanon_split _ _ _ _ Heqs);intro H.
(* Goal: le (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
    destruct H as [H1 H2].
(* Goal: @eq nat (tree_heightP match mkCanon x3 with | Leaf b1 => match mkCanon x4 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x3) (mkCanon x4) | Node s s0 => Node (mkCanon x3) (mkCanon x4) end | Node s s0 => Node (mkCanon x3) (mkCanon x4) end) (S (S n)) *)
    rewrite H1,H2.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
    apply mkFull_split.
  Qed.
  (*L20*)
  Lemma tree_round_left_zero : forall t, roundL 0 t = None.
  Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   unfold tree_round_left.
(* Goal: @eq (option t) match mkFull O (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t0) with | Some t' => match tree_round_rightP O t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@None t) *)
   icase (mkFull 0 (proj1_sig t0)).
  Qed.

  Lemma tree_round_left_combine: forall n t1 t2 t1' t2',
                                roundL n (exist (fun t => canonicalTree t)(mkCanon t1) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon t1') (mkCanon_correct _)) ->
                                roundL n (exist (fun t => canonicalTree t)(mkCanon t2) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon t2') (mkCanon_correct _))->
                                roundL (S n) (exist (fun t => canonicalTree t)(mkCanon (Node t1 t2)) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon (Node t1' t2')) (mkCanon_correct _)).
  Proof.
(* Goal: forall (n : nat) (t1 t2 t3 t1' t2' t3' : t) (_ : @join t Join_ba t1 t2 t3) (_ : @eq (option t) (@roundL t roundableL_tree n t1) (@Some t t1')) (_ : @eq (option t) (@roundL t roundableL_tree n t2) (@Some t t2')) (_ : @eq (option t) (@roundL t roundableL_tree n t3) (@Some t t3')), @join t Join_ba t1' t2' t3' *)
    unfold roundL,roundableL_tree.
(* Goal: forall (n : nat) (t1 t2 t1' t2' : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1) (mkCanon_correct t1))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2) (mkCanon_correct t2))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))), @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1 t2)) (mkCanon_correct (Node t1 t2)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2')))) *)
    intros ? ? ? ? ? H1 H2.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_left (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1) (mkCanon_correct t1))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_left (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2) (mkCanon_correct t2))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    unfold tree_round_left in *.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    unfold proj1_sig in *.
    remember (mkFull n (mkCanon t1)) as o1;
    remember (mkFull n (mkCanon t2)) as o2.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon (Node t1 t2)) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2')))) *)
    icase o1;icase o2.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon (Node t1 t2)) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2')))) *)
    symmetry in Heqo1,Heqo2.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon (Node t1 t2)) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2')))) *)
    generalize (mkCanon_mkFull_split n t1 t2 s s0);intro H.
(* Goal: @join t Join_ba t1' t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    destruct H as [_ H].
(* Goal: @eq t c c *)
    detach H;auto.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
    rewrite H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.
    icase (tree_round_leftP (S n) s);
    icase (tree_round_leftP (S n) s0).
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H1;inv H2.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    f_equal;apply exist_ext.
(* Goal: @eq ShareTree (Node x1 x2) match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
    rewrite<- H1.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    rewrite<- H3.
(* Goal: @eq t c0 c0 *)
    trivial.
  Qed.

  Lemma tree_round_left_split : forall n t1 t2 t1' t2',
                                roundL (S (S n)) (exist (fun t => canonicalTree t)(mkCanon (Node t1 t2)) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon (Node t1' t2')) (mkCanon_correct _)) ->
                                roundL (S n) (exist (fun t => canonicalTree t)(mkCanon t1) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon t1') (mkCanon_correct _)) /\
                                roundL (S n) (exist (fun t => canonicalTree t)(mkCanon t2) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon t2') (mkCanon_correct _)).
  Proof.
(* Goal: forall (n : nat) (t1 t2 t3 t1' t2' t3' : t) (_ : @join t Join_ba t1 t2 t3) (_ : @eq (option t) (@roundL t roundableL_tree n t1) (@Some t t1')) (_ : @eq (option t) (@roundL t roundableL_tree n t2) (@Some t t2')) (_ : @eq (option t) (@roundL t roundableL_tree n t3) (@Some t t3')), @join t Join_ba t1' t2' t3' *)
    unfold roundL,roundableL_tree.
(* Goal: forall (n : nat) (t1 t2 t1' t2' : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1 t2)) (mkCanon_correct (Node t1 t2)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2'))))), and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1) (mkCanon_correct t1))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2) (mkCanon_correct t2))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    intros ? ? ? ? ? H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_left (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1) (mkCanon_correct t1))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_left (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2) (mkCanon_correct t2))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    unfold tree_round_left in *.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    unfold proj1_sig in *.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    remember (mkFull (S (S n)) (mkCanon (Node t1 t2))) as o.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    icase o.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    symmetry in Heqo.
    icase s;
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
    remember (S n) as nk.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    icase (mkCanon (Node t1 t2)).
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    simpl in Heqo; icase (mkFull nk (Leaf b0)).
    simpl in Heqo;icase (mkFull nk s1);
    icase (mkFull nk s2).
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    generalize (mkCanon_mkFull_split nk t1 t2 s1 s2);intro H1.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    destruct H1 as [H1 _].
(* Goal: @eq t c0 c0 *)
    detach H1;trivial.
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
    destruct H1 as [H1 H2].
(* Goal: @eq nat (tree_heightP match mkCanon x3 with | Leaf b1 => match mkCanon x4 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x3) (mkCanon x4) | Node s s0 => Node (mkCanon x3) (mkCanon x4) end | Node s s0 => Node (mkCanon x3) (mkCanon x4) end) (S (S n)) *)
    rewrite H1,H2.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match tree_round_rightP nk s1 with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match tree_round_rightP nk s2 with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    rewrite Heqnk in *.
    icase (tree_round_leftP (S n) s1);
    icase (tree_round_leftP (S n) s2).
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s) (mkCanon_correct s))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s0) (mkCanon_correct s0))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    generalize (mkCanon_eq_split _ _ _ _ H3);intro H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s) (mkCanon_correct s))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s0) (mkCanon_correct s0))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    destruct H as [H4 H5].
(* Goal: @eq t c0 c0 *)
    split;f_equal;apply exist_ext;trivial.
  Qed.

  Lemma tree_round_left_Leaf : forall b n,
  roundL (S n) (exist (fun t => canonicalTree t)(Leaf b) (canonTree_Leaf _))
  = Some (exist (fun t => canonicalTree t)(Leaf b) (canonTree_Leaf _)).
  Proof.
(* Goal: forall (n : nat) (t1 t2 t3 t1' t2' t3' : t) (_ : @join t Join_ba t1 t2 t3) (_ : @eq (option t) (@roundL t roundableL_tree n t1) (@Some t t1')) (_ : @eq (option t) (@roundL t roundableL_tree n t2) (@Some t t2')) (_ : @eq (option t) (@roundL t roundableL_tree n t3) (@Some t t3')), @join t Join_ba t1' t2' t3' *)
    unfold roundL,roundableL_tree.
(* Goal: forall n : nat, @eq nat (countBLeafCT n bot) O *)
    induction n.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    unfold tree_round_left.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
    f_equal.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: @eq t c0 c0 *)
    trivial.

    generalize (canonTree_proof_irr (Leaf b) (mkCanon (Leaf b))
               (canonTree_Leaf _) (mkCanon_correct _));
    intro H.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
    detach H.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
(* Goal: @eq ShareTree (Leaf b) (mkCanon (Leaf b)) *)
    rewrite H in IHn.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
(* Goal: @eq ShareTree (Leaf b) (mkCanon (Leaf b)) *)
    generalize (tree_round_left_combine _ _ _ _ _ IHn IHn);intro H1.
    generalize (canonTree_proof_irr (Leaf b) (mkCanon (Node (Leaf b) (Leaf b)))
               (canonTree_Leaf _) (mkCanon_correct _));
    intro H2.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
(* Goal: @eq ShareTree (Leaf b) (mkCanon (Leaf b)) *)
    detach H2.
(* Goal: @eq t c0 c0 *)
    rewrite H2;trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
  Qed.
  (*L15*)
  Lemma tree_round_left_identity : forall n t, height t < n ->
                                               roundL n t = Some t.
  Proof.
(* Goal: forall (n : nat) (t1 t2 t3 t1' t2' t3' : t) (_ : @join t Join_ba t1 t2 t3) (_ : @eq (option t) (@roundL t roundableL_tree n t1) (@Some t t1')) (_ : @eq (option t) (@roundL t roundableL_tree n t2) (@Some t t2')) (_ : @eq (option t) (@roundL t roundableL_tree n t3) (@Some t t3')), @join t Join_ba t1' t2' t3' *)
   unfold roundL,roundableL_tree.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: le (S O) (S n) *)
   assert (H1 : n > height t0) by omega.
(* Goal: @eq (option t) (tree_round_right n t0) (@Some t t0) *)
   clear H;rename H1 into H.
(* Goal: @eq (option t) (tree_round_right n t0) (@Some t t0) *)
   revert H;revert t0.
(* Goal: forall (t0 : t) (_ : gt n (@height t tree_heightable t0)), @eq (option t) (tree_round_left n t0) (@Some t t0) *)
   induction n;intros;unfold height;simpl in *; unfold tree_height in *.
(* Goal: @ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @eq ShareTree (mkCanon t0) (mkCanon (Node t1 t2)))) *)
   inversion H;icase t0.
(* Goal: sumbool (@eq nat (tree_height t0) O) (not (@eq nat (tree_height t0) O)) *)
   destruct t0 as [x c].
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   icase x.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) *)
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   generalize (canonTree_proof_irr (Leaf b) (Leaf b) c (canonTree_Leaf _));intro H1.
(* Goal: @eq t c0 c0 *)
   detach H1;trivial.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
   rewrite H1.
(* Goal: @eq (option t) (tree_round_left (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
(* Goal: @eq (option t) (tree_round_left (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   apply tree_round_left_Leaf.

(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
   simpl in H.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   assert ( n > tree_heightP x1 /\ n > tree_heightP x2).
(* Goal: and (gt n (tree_heightP x1)) (gt n (tree_heightP x2)) *)
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
     generalize (le_max_l (tree_heightP x1) (tree_heightP x2)).
(* Goal: forall _ : le (tree_heightP x1) (PeanoNat.Nat.max (tree_heightP x1) (tree_heightP x2)), and (gt n (tree_heightP x1)) (gt n (tree_heightP x2)) *)
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
     generalize (le_max_r (tree_heightP x1) (tree_heightP x2)).
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
     intros.
(* Goal: le (S O) (S n) *)
     omega.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   destruct H0 as [H1 H2].
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   copy c.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
   simpl in c.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
   destruct c as [H3 [H4 [H5 H6]]].
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (IHn (exist (fun t => canonicalTree t) x1 H5) H1);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (IHn (exist (fun t => canonicalTree t) x2 H6) H2);intro.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
   generalize (canonTree_proof_irr x1 (mkCanon x1) H5 (mkCanon_correct _));intro H8.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
   detach H8.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   generalize (canonTree_proof_irr x2 (mkCanon x2) H6 (mkCanon_correct _));intro H9.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   detach H9.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree x2 (mkCanon x2) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   generalize (canonTree_proof_irr (Node x1 x2) (mkCanon (Node x1 x2)) c0 (mkCanon_correct _));intro H10.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree x2 (mkCanon x2) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   detach H10.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree (Node x1 x2) (mkCanon (Node x1 x2)) *)
(* Goal: @eq ShareTree x2 (mkCanon x2) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   rewrite H8,H9,H10 in *.
(* Goal: @eq t c0 c0 *)
   apply tree_round_left_combine;trivial.
(* Goal: @eq t c0 c0 *)
   symmetry; apply mkCanon_identity;trivial.
(* Goal: @eq t c0 c0 *)
   symmetry; apply mkCanon_identity;trivial.
(* Goal: @eq t c0 c0 *)
   symmetry; apply mkCanon_identity;trivial.
  Qed.

  Lemma tree_round_left_one : forall t1 t2 t c,
   roundL 1 (exist (fun t => canonicalTree t)(Node t1 t2) c) = Some t ->
   exists b1,exists b2, t1 = Leaf b1 /\ t2 = Leaf b2 /\
   t = (exist (fun t => canonicalTree t)(Leaf b1) (canonTree_Leaf _)).
  Proof.
(* Goal: forall (n : nat) (t1 t2 t3 t1' t2' t3' : t) (_ : @join t Join_ba t1 t2 t3) (_ : @eq (option t) (@roundL t roundableL_tree n t1) (@Some t t1')) (_ : @eq (option t) (@roundL t roundableL_tree n t2) (@Some t t2')) (_ : @eq (option t) (@roundL t roundableL_tree n t3) (@Some t t3')), @join t Join_ba t1' t2' t3' *)
   unfold roundL,roundableL_tree.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: @ex bool (fun b1 : bool => @ex bool (fun b2 : bool => and (@eq ShareTree t1 (Leaf b1)) (and (@eq ShareTree t2 (Leaf b2)) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b2) (canonTree_Leaf b2)))))) *)
   icase t1;icase t2.
(* Goal: @ex bool (fun b1 : bool => @ex bool (fun b2 : bool => and (@eq ShareTree (Leaf b) (Leaf b1)) (and (@eq ShareTree (Leaf b0) (Leaf b2)) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b2) (canonTree_Leaf b2)))))) *)
   exists b;exists b0.
(* Goal: lt (tree_height t') O *)
(* Goal: lt (tree_height t') (S n) *)
   compute in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   inv H.
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.
  (*L14*)
  Lemma tree_round_left_join : forall n t1 t2 t3 t1' t2' t3',
    join t1 t2 t3 ->
    roundL n t1 = Some t1' ->
    roundL n t2 = Some t2' ->
    roundL n t3 = Some t3' ->
    join t1' t2' t3'.
   Proof.
(* Goal: forall (n : nat) (t1 t2 t3 t1' t2' t3' : t) (_ : @join t Join_ba t1 t2 t3) (_ : @eq (option t) (@roundL t roundableL_tree n t1) (@Some t t1')) (_ : @eq (option t) (@roundL t roundableL_tree n t2) (@Some t t2')) (_ : @eq (option t) (@roundL t roundableL_tree n t3) (@Some t t3')), @join t Join_ba t1' t2' t3' *)
    unfold roundL,roundableL_tree.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction n;intros.
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    destruct t1.
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    unfold tree_round_left in H0.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    simpl in H0.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    icase x.

(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.

    destruct t1 as [t1 ?];
    destruct t2 as [t2 ?];
    destruct t3 as [t3 ?].
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    icase t1;icase t2;icase t3.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    inv H3.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    inv H4.
(* Goal: False *)
    inv H0.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
    inv H1.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H2.
    icase b;icase b0;icase b1;
(* Goal: @eq t c0 c0 *)
    compute;split;apply exist_ext;trivial.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    generalize (tree_round_left_one _ _ _ _ H2);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
    destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba t1' t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    destruct H as [_ H].
(* Goal: @join t Join_ba t1' t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    elimtype False;clear-H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H1);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
   destruct H as [H3 H4].
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   elimtype False;clear-H3 H4 c0.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H3.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H4.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkCanon_identity _ c0);intro.
   icase b;
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
   congruence.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H1);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b31) (canonTree_Leaf b31)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H2);intro H4.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H4 as [b41 [b42 [H41 [H42 H43]]]];subst.
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b31) (canonTree_Leaf b31)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b41) (canonTree_Leaf b41)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_Leaf b 0);intro H5.
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   assert (canonTree_Leaf b = c) by apply proof_irr.
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   rewrite H3 in H5;clear H3.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundL,roundableL_tree in *.
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   rewrite H5 in H0;clear H5.
(* Goal: False *)
   inv H0.
   icase b;
   inv H;
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H3.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   icase (bool_dec b31 b32).
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H4.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
   split.
(* Goal: @eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) bot *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   unfold BAF.glb.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t c0 c0 *)
   trivial.
(* Goal: iff (@eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) (and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32)))) *)
   unfold BAF.lub.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t c0 c0 *)
   trivial.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H0);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   elimtype False;clear -H c.
(* Goal: le (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
   destruct H as [H1 H2].
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
   inv H1;inv H2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkCanon_identity _ c);intro.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
   icase b;congruence.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H0);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b31) (canonTree_Leaf b31)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H2);intro H4.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H4 as [b41 [b42 [H41 [H42 H43]]]];subst.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (tree_round_left_Leaf b 0);intro.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   assert (canonTree_Leaf b = c0) by apply proof_irr.
(* Goal: isTokenFactory' (mkCanon (union_tree fac' tok)) x *)
   rewrite H4 in H3;clear H4.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundL,roundableL_tree in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   rewrite H3 in H1;clear H3.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
   inv H1.
   icase b;
   inv H;
   inv H3;
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H4.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   icase (bool_dec b31 b32).
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H3.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
   split.
(* Goal: @eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) bot *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   unfold BAF.glb.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t c0 c0 *)
   icase b41;trivial.
(* Goal: iff (@eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) (and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32)))) *)
   unfold BAF.lub.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
   icase b41;
(* Goal: @eq t c0 c0 *)
   trivial.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H0);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b31) (canonTree_Leaf b31)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H1);intro H4.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H4 as [b41 [b42 [H41 [H42 H43]]]];subst.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (tree_round_left_Leaf b 0);intro.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   assert (canonTree_Leaf b = c1) by apply proof_irr.
(* Goal: isTokenFactory' (mkCanon (union_tree fac' tok)) x *)
   rewrite H4 in H3;clear H4.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundL,roundableL_tree in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   rewrite H3 in H2;clear H3.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
   inv H2.
   icase b;
   inv H;
   inv H2;inv H3;
   icase b31;icase b41;icase b32;icase b42;inv H4;inv H2;
   split;
   unfold BAF.glb, BAF.lub;
   apply exist_ext;
(* Goal: @eq t c0 c0 *)
   simpl;trivial.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H0);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b31) (canonTree_Leaf b31)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H1);intro H4.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H4 as [b41 [b42 [H41 [H42 H43]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b31) (canonTree_Leaf b31)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b41) (canonTree_Leaf b41)) t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_left_one _ _ _ _ H2);intro H5.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H5 as [b51 [b52 [H51 [H52 H53]]]];subst.
   inv H;
   inv H2;inv H3;
   icase b31;icase b41;icase b32;icase b42;inv H4;inv H2;
   split;
   unfold BAF.glb, BAF.lub;
   apply exist_ext;
(* Goal: @eq t c0 c0 *)
   simpl;trivial.

   generalize (canonTree_rewrite1 t1);intro H3;
   generalize (canonTree_rewrite1 t2);intro H4;
   generalize (canonTree_rewrite1 t3);intro H5;
   generalize (canonTree_rewrite1 t1');intro H6;
   generalize (canonTree_rewrite1 t2');intro H7;
   generalize (canonTree_rewrite1 t3');intro H8;
   destruct H3 as [? [? ?]];
   destruct H4 as [? [? ?]];
   destruct H5 as [? [? ?]];
   destruct H6 as [? [? ?]];
   destruct H7 as [? [? ?]];
   destruct H8 as [? [? ?]].
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   subst.

(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (tree_round_left_split _ _ _ _ _ H0);intro H01.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (tree_round_left_split _ _ _ _ _ H1);intro H11.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (tree_round_left_split _ _ _ _ _ H2);intro H21.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   destruct H01 as [H01 H02].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   destruct H11 as [H11 H12].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   destruct H21 as [H21 H22].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (mkCanon_join_split _ _ _ _ _ _ H);intro H3.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
   destruct H3 as [H31 H32].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (IHn _ _ _ _ _ _ H31 H01 H11 H21);intro H41.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (IHn _ _ _ _ _ _ H32 H02 H12 H22);intro H42.
(* Goal: @eq t c0 c0 *)
   apply mkCanon_join_combine;trivial.
  Qed.
  (*L16*)
  Lemma tree_round_left_None : forall n t,
   n < height t ->
   roundL n t = None.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundL,roundableL_tree in *.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   unfold tree_round_left.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkFull_None _ _ H);intro.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
   rewrite H0.
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.
  (*L17*)
  Lemma tree_round_left_decrease : forall n t,
   S n = height t ->
   exists t', roundL (S n) t = Some t' /\ height t' <= n.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
  unfold roundL,roundableL_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  intro.
  induction n;intros;
  destruct t0;
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  icase x.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
  icase x1;icase x2;unfold tree_height in *;inversion H.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_left (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf b) (Leaf b0)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_left (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf b) (Node x2_1 x2_2)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_left (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x1_1 x1_2) (Leaf b)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_left (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x1_1 x1_2) (Node x2_1 x2_2)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
  exists (exist (fun t => canonicalTree t) (Leaf b) (canonTree_Leaf _)).
(* Goal: @eq t c0 c0 *)
  compute;split;try omega;try f_equal;try apply exist_ext;trivial.
(* Goal: le (S O) (S n) *)
  elimtype False;omega.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x1_1 x1_2) (Node x2_1 x2_2)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
  elimtype False;clear -H1.
  assert (0 = max (max (tree_heightP x1_1) (tree_heightP x1_2) + 1) 0) by omega;
  clear H1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (max_0_r (max (tree_heightP x1_1) (tree_heightP x1_2) + 1));intro.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) x) in let (x, _) := top in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel bot rtr2 | Node s s0 => unrel top ltr2 end) top *)
  rewrite H0 in H;clear H0.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x1_1 x1_2) (Node x2_1 x2_2)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
  elimtype False;clear -H1.
  assert (0 = max (max (tree_heightP x1_1) (tree_heightP x1_2) + 1)
       (max (tree_heightP x2_1) (tree_heightP x2_2) + 1)) by omega;
  clear H1.
  generalize (plus_max_distr_r (max (tree_heightP x1_1) (tree_heightP x1_2))
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
                               (max (tree_heightP x2_1) (tree_heightP x2_2)) 1);intro.
(* Goal: le (S O) (S n) *)
  rewrite H0 in H;omega.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
  remember (S n) as nk.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  unfold tree_height in H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  simpl in H.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (nk = max (tree_heightP x1) (tree_heightP x2)) by omega;clear H.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (lt_dec (tree_heightP x1) (tree_heightP x2) );intro H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (nk = tree_heightP x2).
(* Goal: le (S O) (S n) *)
    assert (tree_heightP x1 <= tree_heightP x2 ) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (max_r _ _ H);intro.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite<- H in l.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
  copy c.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  simpl in c;destruct c as [? [? [? ?]]].
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (IHn (exist (fun t => canonicalTree t) x2 H4) H);intro H21.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_left (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_left (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (tree_round_left_identity _ (exist (fun t => canonicalTree t) x1 H3) l);intro H11.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct H21 as [? [H21 H22]].
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
  destruct x.
  assert (tree_round_left nk (exist (fun t : ShareTree => canonicalTree t) x2 H4)=
          tree_round_left nk (exist (fun t => canonicalTree t) (mkCanon x2) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H4);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H21;clear H5.
  assert (exist (fun t : ShareTree => canonicalTree t) x c =
          exist (fun t => canonicalTree t) (mkCanon x) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H21;clear H5.
  assert (exist (fun t : ShareTree => canonicalTree t) x1 H3 =
          exist (fun t => canonicalTree t) (mkCanon x1) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H3);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H11;clear H5.
  assert (tree_round_left (S nk) (exist (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) c0) =
          tree_round_left (S nk) (exist (fun t => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c0);intro H33;
    simpl in H33;
    rewrite H33;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5;clear H5.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (tree_round_left_combine _ _ _ _ _ H11 H21);intro.
(* Goal: lt (tree_height t') (S n) *)
  unfold roundL,roundableL_tree in *.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5;clear H5.
  exists (exist (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x1 x))
          (mkCanon_correct (Node x1 x))).
(* Goal: and (@eq (option t) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) (@Some t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2))))) (le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) nk) *)
  split;trivial;subst nk.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x1 x)) (mkCanon_correct (Node x1 x)))) (S n) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  clear -H22 l.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x1 x)) (mkCanon_correct (Node x1 x)))) (S n) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (tree_heightP x1 <= n) by omega;clear l.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  unfold tree_height in *;simpl in *.
(* Goal: le (tree_heightP match mkCanon x1 with | Leaf b1 => match mkCanon x with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x) | Node s s0 => Node (mkCanon x1) (mkCanon x) end | Node s s0 => Node (mkCanon x1) (mkCanon x) end) (S n) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (tree_heightP (Node x1 x) <= S n).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (max_lub _ _ _ H H22);intro.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: @eq t c0 c0 *)
  assert (mkCanon (Node x1 x) = mkCanon (Node x1 x)) by trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (mkCanon_height _ _ H1);intro.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (S O) (S n) *)
  omega.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (tree_heightP x1 = tree_heightP x2 \/ tree_heightP x1 > tree_heightP x2).
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite<- H in H0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (max_idempotent (tree_heightP x1));intro.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H1 in H0.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite<- H0 in H.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  clear n0 H1.
  assert (tree_round_left (S nk) (exist (fun t => canonicalTree t) (Node x1 x2) c) =
          tree_round_left (S nk) (exist (fun t => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct _))).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
    f_equal.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_identity _ c);intro.
(* Goal: @eq ShareTree (Node x1 x2) match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
    rewrite<-H1.
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H1;clear H1.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
  copy c.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  simpl in c.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  destruct c as [? [? [? ?]]].
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (IHn (exist (fun t => canonicalTree t) x1 H3) H0);intro H5.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (IHn (exist (fun t => canonicalTree t) x2 H4) H);intro H6.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct H5 as [? [H11 H12]].
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct H6 as [? [H21 H22]].
  assert (tree_round_left nk (exist (fun t : ShareTree => canonicalTree t) x1 H3)=
          tree_round_left nk (exist (fun t => canonicalTree t) (mkCanon x1) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H3);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H11;clear H5.
  assert (tree_round_left nk (exist (fun t : ShareTree => canonicalTree t) x2 H4)=
          tree_round_left nk (exist (fun t => canonicalTree t) (mkCanon x2) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H4);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H21;clear H5.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
  destruct x.
  assert (exist (fun t : ShareTree => canonicalTree t) x c =
          exist (fun t => canonicalTree t) (mkCanon x) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H11;clear H5.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct x0.
  assert (exist (fun t : ShareTree => canonicalTree t) x0 c1 =
          exist (fun t => canonicalTree t) (mkCanon x0) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c1);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H21;clear H5.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (tree_round_left_combine _ _ _ _ _ H11 H21);intro.
(* Goal: lt (tree_height t') (S n) *)
  unfold roundL,roundableL_tree in *.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5.
  exists (exist (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x0))
         (mkCanon_correct (Node x x0))).
(* Goal: @eq t c0 c0 *)
  split;trivial.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x0)) (mkCanon_correct (Node x x0)))) nk *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  clear - H12 H22 Heqnk.
(* Goal: sumbool (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O) (not (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O)) *)
  unfold tree_height in *.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (tree_heightP match mkCanon x with | Leaf b1 => match mkCanon x0 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x) (mkCanon x0) | Node s s0 => Node (mkCanon x) (mkCanon x0) end | Node s s0 => Node (mkCanon x) (mkCanon x0) end) nk *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  subst nk.
(* Goal: le (tree_heightP match mkCanon x with | Leaf b1 => match mkCanon x0 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x) (mkCanon x0) | Node s s0 => Node (mkCanon x) (mkCanon x0) end | Node s s0 => Node (mkCanon x) (mkCanon x0) end) (S n) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (tree_heightP (Node x x0) <= S n).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (max_lub _ _ _ H12 H22);intro.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: @eq t c0 c0 *)
  assert (mkCanon (Node x x0) = mkCanon (Node x x0)) by trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (mkCanon_height _ _ H0);intro.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (S O) (S n) *)
  omega.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (nk = tree_heightP x1).
(* Goal: le (S O) (S n) *)
    assert (tree_heightP x2 <= tree_heightP x1 ) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (max_l _ _ H1);intro.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite<- H1 in H.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
  copy c.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  simpl in c;destruct c as [? [? [? ?]]].
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (IHn (exist (fun t => canonicalTree t) x1 H4) H1);intro H11.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_left (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (tree_round_left_identity _ (exist (fun t => canonicalTree t) x2 H5) H);intro H21.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct H11 as [? [H11 H12]].
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
  destruct x.
  assert (tree_round_left nk (exist (fun t : ShareTree => canonicalTree t) x1 H4)=
          tree_round_left nk (exist (fun t => canonicalTree t) (mkCanon x1) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H4);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6 in H11;clear H6.
  assert (exist (fun t : ShareTree => canonicalTree t) x c =
          exist (fun t => canonicalTree t) (mkCanon x) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6 in H11;clear H6.
  assert (exist (fun t : ShareTree => canonicalTree t) x2 H5 =
          exist (fun t => canonicalTree t) (mkCanon x2) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H5);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6 in H21;clear H6.
  assert (tree_round_left (S nk) (exist (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) c0) =
          tree_round_left (S nk) (exist (fun t => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c0);intro H33;
    simpl in H33;
    rewrite H33;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6;clear H6.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (tree_round_left_combine _ _ _ _ _ H11 H21);intro.
(* Goal: lt (tree_height t') (S n) *)
  unfold roundL,roundableL_tree in *.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6;clear H6.
  exists (exist (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2))
          (mkCanon_correct (Node x x2))).
(* Goal: and (@eq (option t) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) (@Some t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2))))) (le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) nk) *)
  split;trivial;subst nk.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) (S n) *)
  clear -H12 H.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) (S n) *)
  assert (tree_heightP x2 <= n) by omega;clear H.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  unfold tree_height in *;simpl in *.
(* Goal: le (tree_heightP match mkCanon x with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x) (mkCanon x2) | Node s s0 => Node (mkCanon x) (mkCanon x2) end | Node s s0 => Node (mkCanon x) (mkCanon x2) end) (S n) *)
  assert (tree_heightP (Node x x2) <= S n).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (max_lub _ _ _ H12 H0);intro.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: @eq t c0 c0 *)
  assert (mkCanon (Node x x2) = mkCanon (Node x x2)) by trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (mkCanon_height _ _ H1);intro.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (S O) (S n) *)
  omega.
  Qed.
  (*L18*)
  Lemma tree_round_left_Some : forall n t,
   height t <= S n ->
   exists t', roundL (S n) t = Some t'.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundL,roundableL_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   inv H.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   symmetry in H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   copy H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_left_decrease in H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   destruct H1 as [? [? ?]].
(* Goal: @ex t (fun t' : t => @eq (option t) (tree_round_right (tree_height t0) t0) (@Some t t')) *)
(* Goal: @ex t (fun t' : t => @eq (option t) (tree_round_right (S n) t0) (@Some t t')) *)
   exists x.
(* Goal: @eq t (glb t1 t2) t2 *)
   rewrite<- H0.
(* Goal: @eq t c0 c0 *)
   trivial.

(* Goal: le (S O) (S n) *)
   assert (H2 : tree_height t0 < S n) by omega.
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_left_identity in H2.
(* Goal: @ex t (fun t' : t => @eq (option t) (tree_round_right (S n) t0) (@Some t t')) *)
   exists t0.
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.
  (*L19*)
  Lemma tree_round_left_height_compare : forall t t' n,
   roundL n t = Some t' ->
   height t' < n.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundL,roundableL_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: lt (tree_height t') n *)
   destruct n.
(* Goal: or (or (@eq t t0 top) (@eq t t0 bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex ((fun t : ShareTree => canonicalTree t) (Node t1 t2)) (fun c : (fun t : ShareTree => canonicalTree t) (Node t1 t2) => @eq t t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c))))) *)
   destruct t0.
(* Goal: lt (tree_height t') O *)
(* Goal: lt (tree_height t') (S n) *)
   compute in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   icase x.
(* Goal: lt (tree_height t') (S n) *)
   assert (H1 := le_lt_dec (tree_height t0) (S n)).
(* Goal: lt (tree_height t') (S n) *)
   destruct H1.
(* Goal: lt (tree_height t') (S n) *)
   inv l.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   symmetry in H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   copy H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_left_decrease in H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   destruct H1 as [? [? ?]].
(* Goal: lt (tree_height t') (S n) *)
   unfold roundL,roundableL_tree in *.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   rewrite H in H1.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
   inv H1.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
   simpl in *.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: le (S O) (S n) *)
   assert (H2 : tree_height t0 < S n) by omega.
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_left_identity in H2.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundL,roundableL_tree in *.
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   rewrite H in H2.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
   inv H2.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_left_None in l.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundL,roundableL_tree in *.
(* Goal: lt (tree_height t') (S n) *)
   rewrite H in l.
(* Goal: lt (tree_height t') (S n) *)
   inv l.
  Qed.

  Lemma tree_round_right_combine : forall n t1 t2 t1' t2',
                                roundR n (exist (fun t => canonicalTree t)(mkCanon t1) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon t1') (mkCanon_correct _)) ->
                                roundR n (exist (fun t => canonicalTree t)(mkCanon t2) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon t2') (mkCanon_correct _))->
                                roundR (S n) (exist (fun t => canonicalTree t)(mkCanon (Node t1 t2)) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon (Node t1' t2')) (mkCanon_correct _)).
  Proof.
(* Goal: lt (tree_height t') (S n) *)
    unfold roundR,roundableR_tree in *.
(* Goal: forall (n : nat) (t1 t2 t1' t2' : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1) (mkCanon_correct t1))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2) (mkCanon_correct t2))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))), @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1 t2)) (mkCanon_correct (Node t1 t2)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2')))) *)
    intros ? ? ? ? ? H1 H2.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1) (mkCanon_correct t1))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2) (mkCanon_correct t2))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    unfold tree_round_right in *.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    unfold proj1_sig in *.
    remember (mkFull n (mkCanon t1)) as o1;
    remember (mkFull n (mkCanon t2)) as o2.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon (Node t1 t2)) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2')))) *)
    icase o1;icase o2.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon (Node t1 t2)) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2')))) *)
    symmetry in Heqo1,Heqo2.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon (Node t1 t2)) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2')))) *)
    generalize (mkCanon_mkFull_split n t1 t2 s s0);intro H.
(* Goal: @join t Join_ba t1' t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    destruct H as [_ H].
(* Goal: @eq t c c *)
    detach H;auto.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
    rewrite H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.
    icase (tree_round_rightP (S n) s);
    icase (tree_round_rightP (S n) s0).
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H1;inv H2.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    f_equal;apply exist_ext.
(* Goal: @eq ShareTree (Node x1 x2) match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
    rewrite<- H1.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    rewrite<- H3.
(* Goal: @eq t c0 c0 *)
    trivial.
  Qed.

  Lemma tree_round_right_split : forall n t1 t2 t1' t2',
                                roundR (S (S n)) (exist (fun t => canonicalTree t)(mkCanon (Node t1 t2)) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon (Node t1' t2')) (mkCanon_correct _)) ->
                                roundR (S n) (exist (fun t => canonicalTree t)(mkCanon t1) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon t1') (mkCanon_correct _)) /\
                                roundR (S n) (exist (fun t => canonicalTree t)(mkCanon t2) (mkCanon_correct _))
                                = Some (exist (fun t => canonicalTree t)(mkCanon t2') (mkCanon_correct _)).
  Proof.
(* Goal: lt (tree_height t') (S n) *)
    unfold roundR,roundableR_tree in *.
(* Goal: forall (n : nat) (t1 t2 t1' t2' : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1 t2)) (mkCanon_correct (Node t1 t2)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t1' t2')) (mkCanon_correct (Node t1' t2'))))), and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1) (mkCanon_correct t1))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2) (mkCanon_correct t2))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    intros ? ? ? ? ? H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1) (mkCanon_correct t1))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2) (mkCanon_correct t2))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    unfold tree_round_right in *.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    unfold proj1_sig in *.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    remember (mkFull (S (S n)) (mkCanon (Node t1 t2))) as o.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    icase o.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t1) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull (S n) (mkCanon t2) with | Some t' => match tree_round_rightP (S n) t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    symmetry in Heqo.
    icase s;
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
    remember (S n) as nk.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    icase (mkCanon (Node t1 t2)).
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    simpl in Heqo; icase (mkFull nk (Leaf b0)).
    simpl in Heqo;icase (mkFull nk s1);
    icase (mkFull nk s2).
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    generalize (mkCanon_mkFull_split nk t1 t2 s1 s2);intro H1.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t1) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull nk (mkCanon t2) with | Some t' => match tree_round_rightP nk t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    destruct H1 as [H1 _].
(* Goal: @eq t c0 c0 *)
    detach H1;trivial.
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
    destruct H1 as [H1 H2].
(* Goal: @eq nat (tree_heightP match mkCanon x3 with | Leaf b1 => match mkCanon x4 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x3) (mkCanon x4) | Node s s0 => Node (mkCanon x3) (mkCanon x4) end | Node s s0 => Node (mkCanon x3) (mkCanon x4) end) (S (S n)) *)
    rewrite H1,H2.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match tree_round_rightP nk s1 with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match tree_round_rightP nk s2 with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    rewrite Heqnk in *.
    icase (tree_round_rightP (S n) s1);
    icase (tree_round_rightP (S n) s2).
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s) (mkCanon_correct s))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s0) (mkCanon_correct s0))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    generalize (mkCanon_eq_split _ _ _ _ H3);intro H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s) (mkCanon_correct s))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t1') (mkCanon_correct t1')))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s0) (mkCanon_correct s0))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t2') (mkCanon_correct t2')))) *)
    destruct H as [H4 H5].
(* Goal: @eq t c0 c0 *)
    split;f_equal;apply exist_ext;trivial.
  Qed.

  Lemma tree_round_right_Leaf : forall b n,
   roundR (S n) (exist (fun t => canonicalTree t)(Leaf b) (canonTree_Leaf _))
   = Some (exist (fun t => canonicalTree t)(Leaf b) (canonTree_Leaf _)).
  Proof.
(* Goal: lt (tree_height t') (S n) *)
    unfold roundR,roundableR_tree in *.
(* Goal: forall n : nat, @eq nat (countBLeafCT n bot) O *)
    induction n.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    unfold tree_round_right.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
    f_equal.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: @eq t c0 c0 *)
    trivial.

    generalize (canonTree_proof_irr (Leaf b) (mkCanon (Leaf b))
               (canonTree_Leaf _) (mkCanon_correct _));
    intro H.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
    detach H.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
(* Goal: @eq ShareTree (Leaf b) (mkCanon (Leaf b)) *)
    rewrite H in IHn.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
(* Goal: @eq ShareTree (Leaf b) (mkCanon (Leaf b)) *)
    generalize (tree_round_right_combine _ _ _ _ _ IHn IHn);intro H1.
    generalize (canonTree_proof_irr (Leaf b) (mkCanon (Node (Leaf b) (Leaf b)))
               (canonTree_Leaf _) (mkCanon_correct _));
    intro H2.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
(* Goal: @eq ShareTree (Leaf b) (mkCanon (Leaf b)) *)
    detach H2.
(* Goal: @eq t c0 c0 *)
    rewrite H2;trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
  Qed.
  (*L22*)
  Lemma tree_round_right_identity : forall n t,
   height t < n ->
   roundR n t = Some t.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: le (S O) (S n) *)
   assert ( H1 : n > tree_height t0) by omega.
(* Goal: @eq (option t) (tree_round_right n t0) (@Some t t0) *)
   clear H;rename H1 into H.
(* Goal: @eq (option t) (tree_round_right n t0) (@Some t t0) *)
   revert H;revert t0.
(* Goal: sumbool (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O) (not (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O)) *)
   induction n;intros;unfold tree_height in *.
(* Goal: @ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @eq ShareTree (mkCanon t0) (mkCanon (Node t1 t2)))) *)
   inversion H;icase t0.
(* Goal: sumbool (@eq nat (tree_height t0) O) (not (@eq nat (tree_height t0) O)) *)
   destruct t0 as [x c].
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   icase x.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) *)
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   generalize (canonTree_proof_irr (Leaf b) (Leaf b) c (canonTree_Leaf _));intro H1.
(* Goal: @eq t c0 c0 *)
   detach H1;trivial.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
   rewrite H1.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) (canonTree_Leaf b))) *)
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   apply tree_round_right_Leaf.

(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
   simpl in H.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   assert ( n > tree_heightP x1 /\ n > tree_heightP x2).
(* Goal: and (gt n (tree_heightP x1)) (gt n (tree_heightP x2)) *)
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
     generalize (le_max_l (tree_heightP x1) (tree_heightP x2)).
(* Goal: forall _ : le (tree_heightP x1) (PeanoNat.Nat.max (tree_heightP x1) (tree_heightP x2)), and (gt n (tree_heightP x1)) (gt n (tree_heightP x2)) *)
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
     generalize (le_max_r (tree_heightP x1) (tree_heightP x2)).
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
     intros.
(* Goal: le (S O) (S n) *)
     omega.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   destruct H0 as [H1 H2].
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
   copy c.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
   simpl in c.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
   destruct c as [H3 [H4 [H5 H6]]].
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (IHn (exist (fun t => canonicalTree t) x1 H5) H1);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (IHn (exist (fun t => canonicalTree t) x2 H6) H2);intro.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
   generalize (canonTree_proof_irr x1 (mkCanon x1) H5 (mkCanon_correct _));intro H8.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
   detach H8.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   generalize (canonTree_proof_irr x2 (mkCanon x2) H6 (mkCanon_correct _));intro H9.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   detach H9.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree x2 (mkCanon x2) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   generalize (canonTree_proof_irr (Node x1 x2) (mkCanon (Node x1 x2)) c0 (mkCanon_correct _));intro H10.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree x2 (mkCanon x2) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   detach H10.
(* Goal: @eq (option t) (tree_round_right (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
(* Goal: @eq ShareTree (Node x1 x2) (mkCanon (Node x1 x2)) *)
(* Goal: @eq ShareTree x2 (mkCanon x2) *)
(* Goal: @eq ShareTree x1 (mkCanon x1) *)
   rewrite H8,H9,H10 in *.
(* Goal: @eq t c0 c0 *)
   apply tree_round_right_combine;trivial.
(* Goal: @eq t c0 c0 *)
   symmetry; apply mkCanon_identity;trivial.
(* Goal: @eq t c0 c0 *)
   symmetry; apply mkCanon_identity;trivial.
(* Goal: @eq t c0 c0 *)
   symmetry; apply mkCanon_identity;trivial.
  Qed.

  Lemma tree_round_right_one : forall t1 t2 t c,
   roundR 1 (exist (fun t => canonicalTree t)(Node t1 t2) c) = Some t ->
   exists b1,exists b2, t1 = Leaf b1 /\ t2 = Leaf b2 /\
   t = (exist (fun t => canonicalTree t)(Leaf b2) (canonTree_Leaf _)).
  Proof.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: @ex bool (fun b1 : bool => @ex bool (fun b2 : bool => and (@eq ShareTree t1 (Leaf b1)) (and (@eq ShareTree t2 (Leaf b2)) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b2) (canonTree_Leaf b2)))))) *)
   icase t1;icase t2.
(* Goal: @ex bool (fun b1 : bool => @ex bool (fun b2 : bool => and (@eq ShareTree (Leaf b) (Leaf b1)) (and (@eq ShareTree (Leaf b0) (Leaf b2)) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b2) (canonTree_Leaf b2)))))) *)
   exists b;exists b0.
(* Goal: lt (tree_height t') O *)
(* Goal: lt (tree_height t') (S n) *)
   compute in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   inv H.
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.
  (*L21*)
  Lemma tree_round_right_join : forall n t1 t2 t3 t1' t2' t3',
    join t1 t2 t3 ->
    roundR n t1 = Some t1' ->
    roundR n t2 = Some t2' ->
    roundR n t3 = Some t3' ->
    join t1' t2' t3'.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
    unfold roundR,roundableR_tree in *.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction n;intros.
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    destruct t1.
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    unfold tree_round_right in H0.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    simpl in H0.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    icase x.

(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.

    destruct t1 as [t1 ?];
    destruct t2 as [t2 ?];
    destruct t3 as [t3 ?].
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    icase t1;icase t2;icase t3.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    inv H3.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    inv H4.
(* Goal: False *)
    inv H0.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
    inv H1.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H2.
    icase b;icase b0;icase b1;
(* Goal: @eq t c0 c0 *)
    compute;split;apply exist_ext;trivial.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    generalize (tree_round_right_one _ _ _ _ H2);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
    destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba t1' t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    destruct H as [_ H].
(* Goal: @join t Join_ba t1' t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    elimtype False;clear-H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H1);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
   destruct H as [H3 H4].
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   elimtype False;clear-H3 H4 c0.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H3.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H4.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkCanon_identity _ c0);intro.
   icase b;
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
   congruence.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H1);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H2);intro H4.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H4 as [b41 [b42 [H41 [H42 H43]]]];subst.
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_Leaf b 0);intro H5.
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   assert (canonTree_Leaf b = c) by apply proof_irr.
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   rewrite H3 in H5;clear H3.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: @join t Join_ba t1' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   rewrite H5 in H0;clear H5.
(* Goal: False *)
   inv H0.
   icase b;
   inv H;
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H3.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   icase (bool_dec b31 b32).
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H4.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
   split.
(* Goal: @eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) bot *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   unfold BAF.glb.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t c0 c0 *)
   trivial.
(* Goal: iff (@eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) (and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32)))) *)
   unfold BAF.lub.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t c0 c0 *)
   trivial.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H0);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   elimtype False;clear -H c.
(* Goal: le (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
   destruct H as [H1 H2].
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
   inv H1;inv H2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkCanon_identity _ c);intro.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
   icase b;congruence.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H0);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H2);intro H4.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H4 as [b41 [b42 [H41 [H42 H43]]]];subst.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (tree_round_right_Leaf b 0);intro.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   assert (canonTree_Leaf b = c0) by apply proof_irr.
(* Goal: isTokenFactory' (mkCanon (union_tree fac' tok)) x *)
   rewrite H4 in H3;clear H4.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   rewrite H3 in H1;clear H3.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
   inv H1.
   icase b;
   inv H;
   inv H3;
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H4.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   icase (bool_dec b31 b32).
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   inv H3.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
   split.
(* Goal: @eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) bot *)
(* Goal: @eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   unfold BAF.glb.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq ShareTree (mkCanon (if b42 then Leaf true else Leaf false)) (Leaf b42) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   icase b42.
(* Goal: iff (@eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) (and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32)))) *)
   unfold BAF.lub.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq ShareTree (mkCanon (if b42 then Leaf true else Leaf false)) (Leaf b42) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   icase b42.


(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H0);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H1);intro H4.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H4 as [b41 [b42 [H41 [H42 H43]]]];subst.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (tree_round_right_Leaf b 0);intro.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   assert (canonTree_Leaf b = c1) by apply proof_irr.
(* Goal: isTokenFactory' (mkCanon (union_tree fac' tok)) x *)
   rewrite H4 in H3;clear H4.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   rewrite H3 in H2;clear H3.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
   inv H2.
   icase b;
   inv H;
   inv H2;inv H3;
   icase b31;icase b41;icase b32;icase b42;inv H4;inv H2;
   split;
   unfold BAF.glb, BAF.lub;
   apply exist_ext;
(* Goal: @eq t c0 c0 *)
   simpl;trivial.

(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H0);intro H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H3 as [b31 [b32 [H31 [H32 H33]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H1);intro H4.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H4 as [b41 [b42 [H41 [H42 H43]]]];subst.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
   generalize (tree_round_right_one _ _ _ _ H2);intro H5.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   destruct H5 as [b51 [b52 [H51 [H52 H53]]]];subst.
   inv H;
   inv H2;inv H3;
   icase b31;icase b41;icase b32;icase b42;inv H4;inv H2;
   split;
   unfold BAF.glb, BAF.lub;
   apply exist_ext;
(* Goal: @eq t c0 c0 *)
   simpl;trivial.

   generalize (canonTree_rewrite1 t1);intro H3;
   generalize (canonTree_rewrite1 t2);intro H4;
   generalize (canonTree_rewrite1 t3);intro H5;
   generalize (canonTree_rewrite1 t1');intro H6;
   generalize (canonTree_rewrite1 t2');intro H7;
   generalize (canonTree_rewrite1 t3');intro H8;
   destruct H3 as [? [? ?]];
   destruct H4 as [? [? ?]];
   destruct H5 as [? [? ?]];
   destruct H6 as [? [? ?]];
   destruct H7 as [? [? ?]];
   destruct H8 as [? [? ?]].
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   subst.

(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (tree_round_right_split _ _ _ _ _ H0);intro H01.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (tree_round_right_split _ _ _ _ _ H1);intro H11.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (tree_round_right_split _ _ _ _ _ H2);intro H21.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   destruct H01 as [H01 H02].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   destruct H11 as [H11 H12].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   destruct H21 as [H21 H22].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (mkCanon_join_split _ _ _ _ _ _ H);intro H3.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
   destruct H3 as [H31 H32].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (IHn _ _ _ _ _ _ H31 H01 H11 H21);intro H41.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
   generalize (IHn _ _ _ _ _ _ H32 H02 H12 H22);intro H42.
(* Goal: @eq t c0 c0 *)
   apply mkCanon_join_combine;trivial.
  Qed.
  (*L23*)
  Lemma tree_round_right_None : forall n t,
   n < height t ->
   roundR n t = None.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   unfold tree_round_right.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkFull_None _ _ H);intro.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
   rewrite H0.
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.
  (*L24*)
  Lemma tree_round_right_decrease : forall n t,
   S n = height t ->
   exists t', roundR (S n) t = Some t' /\ height t' <= n.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
  unfold roundR,roundableR_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
  induction n;intros;
  destruct t0;
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  icase x.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
  icase x1;icase x2;unfold tree_height in *;inversion H.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf b) (Leaf b0)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf b) (Node x2_1 x2_2)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x1_1 x1_2) (Leaf b)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x1_1 x1_2) (Node x2_1 x2_2)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
  exists (exist (fun t => canonicalTree t) (Leaf b0) (canonTree_Leaf _)).
(* Goal: @eq t c0 c0 *)
  compute;split;try omega;try f_equal;try apply exist_ext;trivial.
(* Goal: le (S O) (S n) *)
  elimtype False;omega.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x1_1 x1_2) (Node x2_1 x2_2)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
  elimtype False;clear -H1.
  assert (0 = max (max (tree_heightP x1_1) (tree_heightP x1_2) + 1) 0) by omega;
  clear H1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (max_0_r (max (tree_heightP x1_1) (tree_heightP x1_2) + 1));intro.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf true) (Leaf false)) (@conj (or (@eq bool true false) (@eq bool false false)) (and (or (@eq bool true true) (@eq bool false true)) (and True True)) (@or_intror (@eq bool true false) (@eq bool false false) (@eq_refl bool false)) (@conj (or (@eq bool true true) (@eq bool false true)) (and True True) (@or_introl (@eq bool true true) (@eq bool false true) (@eq_refl bool true)) (@conj True True I I)))) x) in let (x, _) := top in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel bot rtr2 | Node s s0 => unrel top ltr2 end) top *)
  rewrite H0 in H;clear H0.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x1_1 x1_2) (Node x2_1 x2_2)) c)) (@Some t t')) (le (tree_heightP (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t')) O)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
  elimtype False;clear -H1.
  assert (0 = max (max (tree_heightP x1_1) (tree_heightP x1_2) + 1)
       (max (tree_heightP x2_1) (tree_heightP x2_2) + 1)) by omega;
  clear H1.
  generalize (plus_max_distr_r (max (tree_heightP x1_1) (tree_heightP x1_2))
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
                               (max (tree_heightP x2_1) (tree_heightP x2_2)) 1);intro.
(* Goal: le (S O) (S n) *)
  rewrite H0 in H;omega.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') (S n))) *)
  remember (S n) as nk.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  unfold tree_height in H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  simpl in H.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (nk = max (tree_heightP x1) (tree_heightP x2)) by omega;clear H.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (lt_dec (tree_heightP x1) (tree_heightP x2) );intro H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (nk = tree_heightP x2).
(* Goal: le (S O) (S n) *)
    assert (tree_heightP x1 <= tree_heightP x2 ) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (max_r _ _ H);intro.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite<- H in l.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
  copy c.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  simpl in c;destruct c as [? [? [? ?]]].
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (IHn (exist (fun t => canonicalTree t) x2 H4) H);intro H21.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (tree_round_right_identity _ (exist (fun t => canonicalTree t) x1 H3) l);intro H11.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct H21 as [? [H21 H22]].
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
  destruct x.
  assert (tree_round_right nk (exist (fun t : ShareTree => canonicalTree t) x2 H4)=
          tree_round_right nk (exist (fun t => canonicalTree t) (mkCanon x2) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H4);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H21;clear H5.
  assert (exist (fun t : ShareTree => canonicalTree t) x c =
          exist (fun t => canonicalTree t) (mkCanon x) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H21;clear H5.
  assert (exist (fun t : ShareTree => canonicalTree t) x1 H3 =
          exist (fun t => canonicalTree t) (mkCanon x1) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H3);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H11;clear H5.
  assert (tree_round_right (S nk) (exist (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) c0) =
          tree_round_right (S nk) (exist (fun t => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c0);intro H33;
    simpl in H33;
    rewrite H33;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5;clear H5.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (tree_round_right_combine _ _ _ _ _ H11 H21);intro.
(* Goal: lt (tree_height t') (S n) *)
  unfold roundR,roundableR_tree in *.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5;clear H5.
  exists (exist (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x1 x))
          (mkCanon_correct (Node x1 x))).
(* Goal: and (@eq (option t) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) (@Some t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2))))) (le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) nk) *)
  split;trivial;subst nk.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x1 x)) (mkCanon_correct (Node x1 x)))) (S n) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  clear -H22 l.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x1 x)) (mkCanon_correct (Node x1 x)))) (S n) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (tree_heightP x1 <= n) by omega;clear l.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  unfold tree_height in *;simpl in *.
(* Goal: le (tree_heightP match mkCanon x1 with | Leaf b1 => match mkCanon x with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x) | Node s s0 => Node (mkCanon x1) (mkCanon x) end | Node s s0 => Node (mkCanon x1) (mkCanon x) end) (S n) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (tree_heightP (Node x1 x) <= S n).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (max_lub _ _ _ H H22);intro.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: @eq t c0 c0 *)
  assert (mkCanon (Node x1 x) = mkCanon (Node x1 x)) by trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (mkCanon_height _ _ H1);intro.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (S O) (S n) *)
  omega.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (tree_heightP x1 = tree_heightP x2 \/ tree_heightP x1 > tree_heightP x2).
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite<- H in H0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (max_idempotent (tree_heightP x1));intro.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H1 in H0.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite<- H0 in H.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  clear n0 H1.
  assert (tree_round_right (S nk) (exist (fun t => canonicalTree t) (Node x1 x2) c) =
          tree_round_right (S nk) (exist (fun t => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct _))).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
    f_equal.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_identity _ c);intro.
(* Goal: @eq ShareTree (Node x1 x2) match mkCanon x1 with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x1) (mkCanon x2) | Node s s0 => Node (mkCanon x1) (mkCanon x2) end | Node s s0 => Node (mkCanon x1) (mkCanon x2) end *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
    rewrite<-H1.
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H1;clear H1.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
  copy c.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  simpl in c.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  destruct c as [? [? [? ?]]].
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (IHn (exist (fun t => canonicalTree t) x1 H3) H0);intro H5.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (IHn (exist (fun t => canonicalTree t) x2 H4) H);intro H6.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct H5 as [? [H11 H12]].
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct H6 as [? [H21 H22]].
  assert (tree_round_right nk (exist (fun t : ShareTree => canonicalTree t) x1 H3)=
          tree_round_right nk (exist (fun t => canonicalTree t) (mkCanon x1) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H3);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H11;clear H5.
  assert (tree_round_right nk (exist (fun t : ShareTree => canonicalTree t) x2 H4)=
          tree_round_right nk (exist (fun t => canonicalTree t) (mkCanon x2) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H4);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H21;clear H5.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
  destruct x.
  assert (exist (fun t : ShareTree => canonicalTree t) x c =
          exist (fun t => canonicalTree t) (mkCanon x) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H11;clear H5.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct x0.
  assert (exist (fun t : ShareTree => canonicalTree t) x0 c1 =
          exist (fun t => canonicalTree t) (mkCanon x0) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c1);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5 in H21;clear H5.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (tree_round_right_combine _ _ _ _ _ H11 H21);intro.
(* Goal: lt (tree_height t') (S n) *)
  unfold roundR,roundableR_tree in *.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H5.
  exists (exist (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x0))
         (mkCanon_correct (Node x x0))).
(* Goal: @eq t c0 c0 *)
  split;trivial.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x0)) (mkCanon_correct (Node x x0)))) nk *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  clear - H12 H22 Heqnk.
(* Goal: sumbool (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O) (not (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O)) *)
  unfold tree_height in *.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (tree_heightP match mkCanon x with | Leaf b1 => match mkCanon x0 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x) (mkCanon x0) | Node s s0 => Node (mkCanon x) (mkCanon x0) end | Node s s0 => Node (mkCanon x) (mkCanon x0) end) nk *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  subst nk.
(* Goal: le (tree_heightP match mkCanon x with | Leaf b1 => match mkCanon x0 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x) (mkCanon x0) | Node s s0 => Node (mkCanon x) (mkCanon x0) end | Node s s0 => Node (mkCanon x) (mkCanon x0) end) (S n) *)
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (tree_heightP (Node x x0) <= S n).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (max_lub _ _ _ H12 H22);intro.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: @eq t c0 c0 *)
  assert (mkCanon (Node x x0) = mkCanon (Node x x0)) by trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (mkCanon_height _ _ H0);intro.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (S O) (S n) *)
  omega.

(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  assert (nk = tree_heightP x1).
(* Goal: le (S O) (S n) *)
    assert (tree_heightP x2 <= tree_heightP x1 ) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (max_l _ _ H1);intro.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    congruence.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite<- H1 in H.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
  copy c.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  simpl in c;destruct c as [? [? [? ?]]].
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (IHn (exist (fun t => canonicalTree t) x1 H4) H1);intro H11.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  generalize (tree_round_right_identity _ (exist (fun t => canonicalTree t) x2 H5) H);intro H21.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  destruct H11 as [? [H11 H12]].
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
  destruct x.
  assert (tree_round_right nk (exist (fun t : ShareTree => canonicalTree t) x1 H4)=
          tree_round_right nk (exist (fun t => canonicalTree t) (mkCanon x1) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H4);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6 in H11;clear H6.
  assert (exist (fun t : ShareTree => canonicalTree t) x c =
          exist (fun t => canonicalTree t) (mkCanon x) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c);intro H13;
    rewrite H13;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6 in H11;clear H6.
  assert (exist (fun t : ShareTree => canonicalTree t) x2 H5 =
          exist (fun t => canonicalTree t) (mkCanon x2) (mkCanon_correct _)).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ H5);intro H23;
    rewrite H23;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6 in H21;clear H6.
  assert (tree_round_right (S nk) (exist (fun t0 : ShareTree => canonicalTree t0) (Node x1 x2) c0) =
          tree_round_right (S nk) (exist (fun t => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct _))).
    simpl;
    f_equal;
    apply exist_ext;
    generalize (mkCanon_identity _ c0);intro H33;
    simpl in H33;
    rewrite H33;
(* Goal: @eq t c0 c0 *)
    trivial.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6;clear H6.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (tree_round_right_combine _ _ _ _ _ H11 H21);intro.
(* Goal: lt (tree_height t') (S n) *)
  unfold roundR,roundableR_tree in *.
(* Goal: @ex t (fun t' : t => and (@eq (option t) (tree_round_right (S nk) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x1 x2)) (mkCanon_correct (Node x1 x2)))) (@Some t t')) (le (tree_height t') nk)) *)
  rewrite H6;clear H6.
  exists (exist (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2))
          (mkCanon_correct (Node x x2))).
(* Goal: and (@eq (option t) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) (@Some t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2))))) (le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) nk) *)
  split;trivial;subst nk.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) (S n) *)
  clear -H12 H.
(* Goal: le (tree_height (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node x x2)) (mkCanon_correct (Node x x2)))) (S n) *)
  assert (tree_heightP x2 <= n) by omega;clear H.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  unfold tree_height in *;simpl in *.
(* Goal: le (tree_heightP match mkCanon x with | Leaf b1 => match mkCanon x2 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x) (mkCanon x2) | Node s s0 => Node (mkCanon x) (mkCanon x2) end | Node s s0 => Node (mkCanon x) (mkCanon x2) end) (S n) *)
  assert (tree_heightP (Node x x2) <= S n).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (max_lub _ _ _ H12 H0);intro.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: @eq t c0 c0 *)
  assert (mkCanon (Node x x2) = mkCanon (Node x x2)) by trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (mkCanon_height _ _ H1);intro.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (S O) (S n) *)
  omega.
 Qed.
 (*L25*)
 Lemma tree_round_right_Some : forall n t,
   height t <= S n ->
   exists t', roundR (S n) t = Some t'.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   inv H.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   symmetry in H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   copy H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_right_decrease in H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   destruct H1 as [? [? ?]].
(* Goal: @ex t (fun t' : t => @eq (option t) (tree_round_right (tree_height t0) t0) (@Some t t')) *)
(* Goal: @ex t (fun t' : t => @eq (option t) (tree_round_right (S n) t0) (@Some t t')) *)
   exists x.
(* Goal: @eq t (glb t1 t2) t2 *)
   rewrite<- H0.
(* Goal: @eq t c0 c0 *)
   trivial.

(* Goal: le (S O) (S n) *)
   assert (H2 : tree_height t0 < S n) by omega.
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_right_identity in H2.
(* Goal: @ex t (fun t' : t => @eq (option t) (tree_round_right (S n) t0) (@Some t t')) *)
   exists t0.
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.
  (*L26*)
  Lemma tree_round_right_height_compare : forall t t' n,
   roundR n t = Some t' ->
   height t' < n.
  Proof.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: lt (tree_height t') n *)
   destruct n.
(* Goal: or (or (@eq t t0 top) (@eq t t0 bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex ((fun t : ShareTree => canonicalTree t) (Node t1 t2)) (fun c : (fun t : ShareTree => canonicalTree t) (Node t1 t2) => @eq t t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c))))) *)
   destruct t0.
(* Goal: lt (tree_height t') O *)
(* Goal: lt (tree_height t') (S n) *)
   compute in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   icase x.
(* Goal: lt (tree_height t') (S n) *)
   assert (H1 := le_lt_dec (tree_height t0) (S n)).
(* Goal: lt (tree_height t') (S n) *)
   destruct H1.
(* Goal: lt (tree_height t') (S n) *)
   inv l.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   symmetry in H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   copy H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_right_decrease in H1.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   destruct H1 as [? [? ?]].
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: lt (tree_height t') (tree_height t0) *)
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   rewrite H in H1.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
   inv H1.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
   simpl in *.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: le (S O) (S n) *)
   assert (H2 : tree_height t0 < S n) by omega.
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_right_identity in H2.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: lt (tree_height t') (S n) *)
(* Goal: lt (tree_height t') (S n) *)
   rewrite H in H2.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
   inv H2.
(* Goal: le (S O) (S n) *)
   omega.
(* Goal: lt (tree_height t') (S n) *)
   apply tree_round_right_None in l.
(* Goal: lt (tree_height t') (S n) *)
   unfold roundR,roundableR_tree in *.
(* Goal: lt (tree_height t') (S n) *)
   rewrite H in l.
(* Goal: lt (tree_height t') (S n) *)
   inv l.
  Qed.

 (*L27*)
  Lemma tree_round_right_zero : forall t, roundR 0 t = None.
  Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   unfold tree_round_right.
(* Goal: @eq (option t) match mkFull O (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t0) with | Some t' => match tree_round_rightP O t' with | Some t'' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t'') (mkCanon_correct t'')) | None => @None canonTree end | None => @None canonTree end (@None t) *)
   icase (mkFull 0 (proj1_sig t0)).
  Qed.

 Lemma tree_avg_Leaf : forall n b c,
  avg (S n) (exist (fun t => canonicalTree t)(Leaf b) c)
  (exist (fun t => canonicalTree t)(Leaf b) c)
  = Some (exist (fun t => canonicalTree t)(Leaf b) c).
  Proof.
(* Goal: forall (n : nat) (t11 t12 t21 t22 t31 t32 : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t22) (mkCanon_correct t22))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))), @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
   unfold avg,avgable_tree in *.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   induction n ;intros.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   f_equal;apply exist_ext.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase b.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
   simpl in *.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t1' => match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) *)
   specialize ( IHn b c).
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t1' => match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) *)
   icase (mkFull n (Leaf b)).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match tree_avgP s s with | Some t1' => match tree_avgP s s with | Some t2' => @Some ShareTree (Node t1' t2') | None => @None ShareTree end | None => @None ShareTree end with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) *)
   icase (tree_avgP s s).
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
   f_equal;apply exist_ext.
(* Goal: @eq ShareTree (mkCanon (Node s0 s0)) (Leaf b) *)
   inv IHn.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
   rewrite H0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase b.
  Qed.

  (*L29*)
  Lemma tree_avg_identity : forall n t,
   height t < n ->
   avg n t t = Some t.
  Proof.
(* Goal: forall (n : nat) (t11 t12 t21 t22 t31 t32 : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t22) (mkCanon_correct t22))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))), @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
    unfold avg,avgable_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    unfold height;simpl.
    induction n;intros;
    destruct t0;
(* Goal: sumbool (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O) (not (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O)) *)
    unfold tree_height in *.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    icase x.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) *)
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
    apply tree_avg_Leaf.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
    assert (tree_heightP x1 < n /\ tree_heightP x2 < n).
(* Goal: le (S O) (S n) *)
      assert (max (tree_heightP x1) (tree_heightP x2) < n) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      generalize (le_max_l (tree_heightP x1) (tree_heightP x2));intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      generalize (le_max_r (tree_heightP x1) (tree_heightP x2));intro.
(* Goal: le (S O) (S n) *)
      split;omega.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
    destruct H0 as [? ?].
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) *)
    copy c.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
    simpl in c0.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c0)) *)
    destruct c0 as [? [? [? ?]]].
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHn (exist (fun t => canonicalTree t) x1 c0) H0);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (IHn (exist (fun t => canonicalTree t) x2 c1) H1);intro.
(* Goal: @eq (option t) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (or (nonFullTree x1) (nonFullTree x2)) (and (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2))) o (@conj (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) o0 (@conj (canonicalTree x1) (canonicalTree x2) c0 c1)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (or (nonFullTree x1) (nonFullTree x2)) (and (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2))) o (@conj (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) o0 (@conj (canonicalTree x1) (canonicalTree x2) c0 c1))))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (or (nonFullTree x1) (nonFullTree x2)) (and (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2))) o (@conj (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) o0 (@conj (canonicalTree x1) (canonicalTree x2) c0 c1))))) *)
    clear - H2 H3.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl in H2,H3;simpl.
    icase (mkFull n x1);
    icase (mkFull n x2).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    icase (tree_avgP s s);
    icase (tree_avgP s0 s0).
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    inv H2;inv H3.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
    apply f_equal.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    icase (mkCanon s1);
    icase (mkCanon s2).
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    icase b; icase b0;simpl in *.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    elimtype False; firstorder.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    elimtype False; firstorder.
  Qed.

  (*L30*)
  Lemma tree_avg_None : forall n t1 t2,
   n <= max (height t1) (height t2) ->
   avg n t1 t2 = None.
  Proof.
(* Goal: forall (n : nat) (t11 t12 t21 t22 t31 t32 : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t22) (mkCanon_correct t22))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))), @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
   unfold avg,avgable_tree in *.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
   icase n.
(* Goal: @eq (option t) (tree_avg (S n) t1 t2) (@None t) *)
   assert (n < tree_height t1 \/n < tree_height t2).
(* Goal: le (S O) (S n) *)
    assert (n < max (tree_height t1) (tree_height t2)) by omega.
(* Goal: or (lt n (tree_height t1)) (lt n (tree_height t2)) *)
(* Goal: @eq (option t) (tree_avg (S n) t1 t2) (@None t) *)
    apply Nat.max_lt_iff.
(* Goal: @eq t c0 c0 *)
    trivial.
   destruct t1;destruct t2;
   simpl;destruct H0;
   unfold tree_height in *;
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
   simpl in *.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkFull_None _ _ H0);intro.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
   rewrite H1.
(* Goal: @eq t c0 c0 *)
   trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   generalize (mkFull_None _ _ H0);intro.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
   rewrite H1.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => @None canonTree | None => @None canonTree end (@None t) *)
   icase (mkFull n x).
  Qed.

  Lemma tree_avg_split : forall n t11 t12 t21 t22 t31 t32,
                         avg (S (S n)) (exist (fun t => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct _))
                                            (exist (fun t => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct _))
                                     = Some (exist (fun t => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct _))->
                         avg (S n )    (exist (fun t => canonicalTree t) (mkCanon t11) (mkCanon_correct _))
                                            (exist (fun t => canonicalTree t) (mkCanon t21) (mkCanon_correct _))
                                     = Some (exist (fun t => canonicalTree t) (mkCanon t31) (mkCanon_correct _)) /\
                         avg (S n )    (exist (fun t => canonicalTree t) (mkCanon t12) (mkCanon_correct _))
                                            (exist (fun t => canonicalTree t) (mkCanon t22) (mkCanon_correct _))
                                     = Some (exist (fun t => canonicalTree t) (mkCanon t32) (mkCanon_correct _)).
  Proof.
(* Goal: forall (n : nat) (t11 t12 t21 t22 t31 t32 : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t22) (mkCanon_correct t22))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))), @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
    unfold avg,avgable_tree in *.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    simpl in *.
    remember (mkCanon (Node t11 t12));
    remember (mkCanon (Node t21 t22));
    simpl in Heqs,Heqs0;
    rewrite<- Heqs in H;
    rewrite<-Heqs0 in H;
(* Goal: @eq ShareTree (mkCanon (intersect_tree s s0)) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    icase s;icase s0.

(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs);intro H1.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro H2.
    destruct H1 as [H11 H12];
    destruct H2 as [H21 H22];
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    rewrite H11,H12,H21,H22 in *.
    icase (mkFull n (Leaf b));
(* Goal: @eq (option ShareTree) match mkFull n (Leaf b0) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end match mkFull n (Leaf b0) with | Some t1 => match mkFull n (Leaf b0) with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end *)
    icase (mkFull n (Leaf b0)).
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match tree_avgP s s0 with | Some t1' => match tree_avgP s s0 with | Some t2' => @Some ShareTree (Node t1' t2') | None => @None ShareTree end | None => @None ShareTree end with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    icase (tree_avgP s s0).
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    generalize (mkCanon_eq_split _ _ _ _ H1);intro H3.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    destruct H3 as [H31 H32].
(* Goal: @eq t c0 c0 *)
    split;f_equal;apply exist_ext;trivial.

    symmetry in Heqs0;
    generalize (mkCanon_Leaf_split _ _ _ Heqs);intro H1;
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
    generalize (mkCanon_split _ _ _ _ Heqs0);intro H2.
    destruct H1 as [H11 H12];
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
    destruct H2 as [H21 H22].
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    rewrite H11,H12,H21,H22 in *.
    icase (mkFull n (Leaf b));
    icase (mkFull n s0_1);
    icase (mkFull n s0_2).
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
    icase (tree_avgP s s0);
    icase (tree_avgP s s1).
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    generalize (mkCanon_eq_split _ _ _ _ H1);intro H3.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    destruct H3 as [H31 H32].
(* Goal: @eq t c0 c0 *)
    split;f_equal;apply exist_ext;trivial.

    symmetry in Heqs;
    generalize (mkCanon_split _ _ _ _ Heqs);intro H1;
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t11) with | Some t1' => match mkFull n (mkCanon t21) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match mkFull n (mkCanon t12) with | Some t1' => match mkFull n (mkCanon t22) with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro H2.
    destruct H1 as [H11 H12];
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
    destruct H2 as [H21 H22].
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    rewrite H11,H12,H21,H22 in *.
    icase (mkFull n s1);
    icase (mkFull n s2);
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t1' => match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) *)
    icase (mkFull n (Leaf b)).
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
    icase (tree_avgP s s3);
    icase (tree_avgP s0 s3).
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    generalize (mkCanon_eq_split _ _ _ _ H1);intro H3.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    destruct H3 as [H31 H32].
(* Goal: @eq t c0 c0 *)
    split;f_equal;apply exist_ext;trivial.

    symmetry in Heqs,Heqs0;
    generalize (mkCanon_split _ _ _ _ Heqs);intro H1;
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
    generalize (mkCanon_split _ _ _ _ Heqs0);intro H2.
    destruct H1 as [H11 H12];
(* Goal: and (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21))) (S n)) (lt (PeanoNat.Nat.max (tree_heightP (mkCanon t12)) (tree_heightP (mkCanon t22))) (S n)) *)
    destruct H2 as [H21 H22].
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    rewrite H11,H12,H21,H22 in *.
    icase (mkFull n s1);
    icase (mkFull n s2);
    icase (mkFull n s0_1);
    icase (mkFull n s0_2).
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
    icase (tree_avgP s s3);
    icase (tree_avgP s0 s4).
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    generalize (mkCanon_eq_split _ _ _ _ H1);intro H3.
(* Goal: and (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s5) (mkCanon_correct s5))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (@eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon s6) (mkCanon_correct s6))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))) *)
    destruct H3 as [H31 H32].
(* Goal: @eq t c0 c0 *)
    split;f_equal;apply exist_ext;trivial.
  Qed.

  Lemma tree_avg_combine : forall n t11 t12 t21 t22 t31 t32,
                           avg n (exist (fun t => canonicalTree t) (mkCanon t11) (mkCanon_correct _))
                                            (exist (fun t => canonicalTree t) (mkCanon t21) (mkCanon_correct _))
                                     = Some (exist (fun t => canonicalTree t) (mkCanon t31) (mkCanon_correct _)) ->
                           avg n (exist (fun t => canonicalTree t) (mkCanon t12) (mkCanon_correct _))
                                            (exist (fun t => canonicalTree t) (mkCanon t22) (mkCanon_correct _))
                                     = Some (exist (fun t => canonicalTree t) (mkCanon t32) (mkCanon_correct _)) ->
                           avg (S n) (exist (fun t => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct _))
                                            (exist (fun t => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct _))
                                     = Some (exist (fun t => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct _)).
   Proof.
(* Goal: forall (n : nat) (t11 t12 t21 t22 t31 t32 : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t22) (mkCanon_correct t22))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))), @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@avg (@sig ShareTree (fun t : ShareTree => canonicalTree t)) avgable_tree (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
    unfold avg,avgable_tree in *.
(* Goal: forall (n : nat) (t11 t12 t21 t22 t31 t32 : ShareTree) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_avg n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t31) (mkCanon_correct t31)))) (_ : @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_avg n (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t22) (mkCanon_correct t22))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t32) (mkCanon_correct t32)))), @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_avg (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) *)
    intros ? ? ? ? ? ? ? H1 H2.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    simpl in *.
    remember (mkCanon (Node t11 t12));
    remember (mkCanon (Node t21 t22));
    simpl in Heqs,Heqs0;
    rewrite<- Heqs;
    rewrite<- Heqs0;
(* Goal: @eq ShareTree (mkCanon (intersect_tree s s0)) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    icase s;icase s0.

    generalize (mkCanon_Leaf_split _ _ _ Heqs);intro H11;
    generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro H21.
    destruct H11 as [H11 H12];
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
    destruct H21 as [H21 H22].
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    rewrite H11,H12,H21,H22 in *.
    icase (mkFull n (Leaf b));
(* Goal: @eq (option ShareTree) match mkFull n (Leaf b0) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end match mkFull n (Leaf b0) with | Some t1 => match mkFull n (Leaf b0) with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end *)
    icase (mkFull n (Leaf b0)).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match tree_avgP s s0 with | Some t1' => match tree_avgP s s0 with | Some t2' => @Some ShareTree (Node t1' t2') | None => @None ShareTree end | None => @None ShareTree end with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    icase (tree_avgP s s0).
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H1;inv H2.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    f_equal;apply exist_ext.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq t c0 c0 *)
    rewrite<-H0;rewrite<-H1;trivial.

    symmetry in Heqs0;
    generalize (mkCanon_Leaf_split _ _ _ Heqs);intro H11;
    generalize (mkCanon_split _ _ _ _ Heqs0);intro H21.
    destruct H11 as [H11 H12];
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
    destruct H21 as [H21 H22].
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    rewrite H11,H12,H21,H22 in *.
    icase (mkFull n (Leaf b));
    icase (mkFull n s0_1);
    icase (mkFull n s0_2).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    icase (tree_avgP s s0);
    icase (tree_avgP s s1).
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H1;inv H2.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    f_equal;apply exist_ext.
(* Goal: @eq t c0 c0 *)
    rewrite<-H0;rewrite<-H1;trivial.

    symmetry in Heqs;
    generalize (mkCanon_split _ _ _ _ Heqs);intro H11;
    generalize (mkCanon_Leaf_split _ _ _ Heqs0);intro H21.
    destruct H11 as [H11 H12];
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
    destruct H21 as [H21 H22].
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    rewrite H11,H12,H21,H22 in *.
    icase (mkFull n s1);
    icase (mkFull n s2);
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t1' => match match mkFull n (Leaf b) with | Some t => @Some ShareTree (Node t t) | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) *)
    icase (mkFull n (Leaf b)).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    icase (tree_avgP s s3);
    icase (tree_avgP s0 s3).
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H1;inv H2.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    f_equal;apply exist_ext.
(* Goal: @eq t c0 c0 *)
    rewrite<- H0;rewrite<- H1;trivial.

    symmetry in Heqs,Heqs0;
    generalize (mkCanon_split _ _ _ _ Heqs);intro H11;
    generalize (mkCanon_split _ _ _ _ Heqs0);intro H21.
    destruct H11 as [H11 H12];
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x5 x6)) (mkCanon_correct (Node x5 x6))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x7 x8)) (mkCanon_correct (Node x7 x8))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x9 x10)) (mkCanon_correct (Node x9 x10))) *)
    destruct H21 as [H21 H22].
(* Goal: @eq (option (@sig ShareTree (fun t : ShareTree => canonicalTree t))) match match mkFull n s1 with | Some t1 => match mkFull n s2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t1' => match match mkFull n s0_1 with | Some t1 => match mkFull n s0_2 with | Some t2 => @Some ShareTree (Node t1 t2) | None => @None ShareTree end | None => @None ShareTree end with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end (mkCanon_correct (Node t31 t32)))) *)
    rewrite H11,H12,H21,H22 in *.
    icase (mkFull n s1);
    icase (mkFull n s2);
    icase (mkFull n s0_1);
    icase (mkFull n s0_2).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    icase (tree_avgP s s3);
    icase (tree_avgP s0 s4).
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H1;inv H2.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    f_equal;apply exist_ext.
(* Goal: @eq t c0 c0 *)
    rewrite<- H0;rewrite<- H1;trivial.
  Qed.
  (*L31*)
  Lemma tree_avg_round2avg : forall n t1 t2 t3,
   roundL n t3 = Some t1 ->
   roundR n t3 = Some t2 ->
   avg n t1 t2 = Some t3.
  Proof.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    simpl in *.
(* Goal: forall (n : nat) (t1 t2 t3 : t) (_ : @eq (option t) (tree_round_left n t3) (@Some t t1)) (_ : @eq (option t) (tree_round_right n t3) (@Some t t2)), @eq (option t) (tree_avg n t1 t2) (@Some t t3) *)
    induction n;intros ? ? ? H1 H2.
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    destruct t3 as [x3 c3].
(* Goal: @eq ShareTree match x3 with | Leaf b1 => match mkCanon t22 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x3 (mkCanon t22) | Node s s0 => Node x3 (mkCanon t22) end | Node s s0 => Node x3 (mkCanon t22) end (Node x3 (mkCanon t22)) *)
(* Goal: @eq nat (tree_heightP (mkCanon (Node x3 t22))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    icase x3.

    destruct t1 as [x1 c1];
    destruct t2 as [x2 c2];
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    destruct t3 as [x3 c3].
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.
(* Goal: @eq ShareTree match x3 with | Leaf b1 => match mkCanon t22 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x3 (mkCanon t22) | Node s s0 => Node x3 (mkCanon t22) end | Node s s0 => Node x3 (mkCanon t22) end (Node x3 (mkCanon t22)) *)
(* Goal: @eq nat (tree_heightP (mkCanon (Node x3 t22))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    icase x3.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H1;inv H2.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply f_equal;apply exist_ext.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.
(* Goal: @eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x3_1 x3_2) c3)) *)
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    icase x3_1;icase x3_2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase x1;icase x2.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    inv H1;inv H2.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply f_equal;apply exist_ext.
(* Goal: @eq ShareTree (if bool_dec b1 b2 then Leaf b1 else Node (Leaf b1) (Leaf b2)) (Node (Leaf b1) (Leaf b2)) *)
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    icase b1;icase b2;compute in c3.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    elimtype False.
(* Goal: False *)
(* Goal: @eq ShareTree (if bool_dec false false then Leaf false else Node (Leaf false) (Leaf false)) (Node (Leaf false) (Leaf false)) *)
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    destruct c3 as [c3 ?].
    destruct c3;
(* Goal: False *)
    inv H0.
(* Goal: @eq ShareTree (if bool_dec false false then Leaf false else Node (Leaf false) (Leaf false)) (Node (Leaf false) (Leaf false)) *)
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    destruct c3 as [? [c3 ?]].
    destruct c3;
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
    inv H1.

(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (mkCanon_identity _ c3);intro H31.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (mkCanon_rewrite x3);intro H32.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    destruct H32 as [x31 [x32 H32]].
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    rewrite H32 in H31.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c3 H31);intro H33.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    generalize (mkCanon_identity _ c1);intro H11.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (mkCanon_rewrite x1);intro H12.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    destruct H12 as [x11 [x12 H12]].
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    rewrite H12 in H11.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c1 H11);intro H13.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    generalize (mkCanon_identity _ c2);intro H21.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (mkCanon_rewrite x2);intro H22.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    destruct H22 as [x21 [x22 H22]].
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    rewrite H22 in H21.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c2 H21);intro H23.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    rewrite<- H33 in H1,H2.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    rewrite<- H13 in H1.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    rewrite<- H23 in H2.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    generalize (tree_round_left_split _ _ _ _ _ H1);intro H14.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    generalize (tree_round_right_split _ _ _ _ _ H2);intro H24.
    destruct H14 as [H14 H15];
    destruct H24 as [H24 H25].
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    generalize (IHn _ _ _ H14 H24);intro H34.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    generalize (IHn _ _ _ H15 H25);intro H35.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    generalize (tree_avg_combine _ _ _ _ _ _ _ H34 H35);intro H36.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    rewrite H13 in H36.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    rewrite H23 in H36.
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    rewrite H33 in H36.
(* Goal: @eq t c0 c0 *)
    trivial.
   Qed.
  (*L32*)
  Lemma tree_avg_avg2round : forall n t1 t2 t3,
   avg n t1 t2 = Some t3 ->
   roundL n t3 = Some t1 /\
   roundR n t3 = Some t2.
  Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    induction n;intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.

    destruct t1 as [x1 c1];
    destruct t2 as [x2 c2];
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    destruct t3 as [x3 c3].
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.
    icase x1;
    icase x2;
(* Goal: @eq ShareTree match x3 with | Leaf b1 => match mkCanon t22 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x3 (mkCanon t22) | Node s s0 => Node x3 (mkCanon t22) end | Node s s0 => Node x3 (mkCanon t22) end (Node x3 (mkCanon t22)) *)
(* Goal: @eq nat (tree_heightP (mkCanon (Node x3 t22))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    icase x3.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: and (@eq (option t) (tree_round_left (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x3_1 x3_2) c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c1))) (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x3_1 x3_2) c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) c2))) *)
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    icase (bool_dec b b0).
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
    inv H1.
    unfold tree_round_left;
    unfold tree_round_right;
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
    try subst.
(* Goal: @eq t c0 c0 *)
    split;apply f_equal;apply exist_ext;trivial.
(* Goal: and (@eq (option t) (tree_round_left (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x3_1 x3_2) c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c1))) (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x3_1 x3_2) c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) c2))) *)
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    unfold tree_avg in H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
    simpl in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    inv H.
(* Goal: and (@eq (option t) (tree_round_left (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x3_1 x3_2) c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c1))) (@eq (option t) (tree_round_right (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x3_1 x3_2) c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) c2))) *)
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    icase (bool_dec b b0).
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
    inv H1.
    unfold tree_round_left;
    unfold tree_round_right;
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: @eq t c0 c0 *)
    split;apply f_equal;apply exist_ext;trivial.

    generalize (mkCanon_identity _ c1);intro H11;
(* Goal: @eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) *)
    generalize (mkCanon_identity _ c2);intro H21.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (mkCanon_identity _ c3);intro H31.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (mkCanon_rewrite x1);intro H12.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (mkCanon_rewrite x2);intro H22.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (mkCanon_rewrite x3);intro H32.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    destruct H12 as [x11 [x12 H12]].
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    destruct H22 as [x21 [x22 H22]].
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    destruct H32 as [x31 [x32 H32]].
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    rewrite H12 in H11.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    rewrite H22 in H21.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    rewrite H32 in H31.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c1 H11);intro H13.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c2 H21);intro H23.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c3 H31);intro H33.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    rewrite<-H13 in *.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x11 x12)) (mkCanon_correct (Node x11 x12))))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2))) *)
    rewrite<-H23 in *.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x11 x12)) (mkCanon_correct (Node x11 x12))))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x21 x22)) (mkCanon_correct (Node x21 x22))))) *)
    rewrite<-H33 in *.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x11 x12)) (mkCanon_correct (Node x11 x12))))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x21 x22)) (mkCanon_correct (Node x21 x22))))) *)
    generalize (tree_avg_split _ _ _ _ _ _ _ H);intro H34.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x11 x12)) (mkCanon_correct (Node x11 x12))))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x21 x22)) (mkCanon_correct (Node x21 x22))))) *)
    destruct H34 as [H34 H35].
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x11 x12)) (mkCanon_correct (Node x11 x12))))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x21 x22)) (mkCanon_correct (Node x21 x22))))) *)
    generalize (IHn _ _ _ H34);intro H36.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x11 x12)) (mkCanon_correct (Node x11 x12))))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x21 x22)) (mkCanon_correct (Node x21 x22))))) *)
    destruct H36 as [H36 H37].
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x11 x12)) (mkCanon_correct (Node x11 x12))))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x21 x22)) (mkCanon_correct (Node x21 x22))))) *)
    generalize (IHn _ _ _ H35);intro H38.
(* Goal: and (@eq (option t) (tree_round_left (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x11 x12)) (mkCanon_correct (Node x11 x12))))) (@eq (option t) (tree_round_right (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x31 x32)) (mkCanon_correct (Node x31 x32)))) (@Some t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x21 x22)) (mkCanon_correct (Node x21 x22))))) *)
    destruct H38 as [H38 H39].
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
    split.
(* Goal: @eq t c0 c0 *)
    apply tree_round_left_combine;trivial.
(* Goal: @eq t c0 c0 *)
    apply tree_round_right_combine;trivial.
  Qed.
  (*L33*)
  Lemma tree_avg_join : forall n t11 t12 t13 t21 t22 t23 t31 t32 t33,
   avg n t11 t12 =  Some t13 ->
   avg n t21 t22 = Some t23 ->
   avg n t31 t32 = Some t33 ->
   join t11 t21 t31 ->
   join t12 t22 t32 ->
   join t13 t23 t33.
  Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    induction n;
    intros ? ? ? ? ? ? ? ? ? H1 H2 H3 H4 H5.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
    inv H1.

    destruct t11 as [x11 c11];
    destruct t12 as [x12 c12];
    destruct t13 as [x13 c13];
    destruct t21 as [x21 c21];
    destruct t22 as [x22 c22];
    destruct t23 as [x23 c23];
    destruct t31 as [x31 c31];
    destruct t32 as [x32 c32];
    destruct t33 as [x33 c33].
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
    icase n.

    icase x11;icase x12;
    icase x21;icase x22;
    icase x31;icase x32.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    unfold tree_avg in *;simpl in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b32) (canonTree_Leaf b32)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c0) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b42) (canonTree_Leaf b42)) *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
(* Goal: @join t Join_ba t1' t2' t3' *)
    inv H1;inv H2;inv H3.
    destruct H4 as [H41 H42];
(* Goal: @eq ShareTree (mkCanon (intersect_tree (Node s1 s2) (Node s0_1 s0_2))) (mkCanon (intersect_tree (Node t1_1 t1_2) (Node t2_1 t2_2))) *)
    destruct H5 as [H51 H52].
    split;
    unfold BAF.glb, BAF.lub in *;simpl in *;
    inv H41;inv H42;inv H51;inv H52;
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (if bool_dec b b0 then Leaf b else Node (Leaf b) (Leaf b0)) (if bool_dec b1 b2 then Leaf b1 else Node (Leaf b1) (Leaf b2)))) (Leaf false) *)
(* Goal: @eq ShareTree (mkCanon (union_tree (if bool_dec b b0 then Leaf b else Node (Leaf b) (Leaf b0)) (if bool_dec b1 b2 then Leaf b1 else Node (Leaf b1) (Leaf b2)))) (if bool_dec b3 b4 then Leaf b3 else Node (Leaf b3) (Leaf b4)) *)
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    icase b;icase b0;icase b1;icase b2.
(* Goal: @eq ShareTree (mkCanon (union_tree (if bool_dec b b0 then Leaf b else Node (Leaf b) (Leaf b0)) (if bool_dec b1 b2 then Leaf b1 else Node (Leaf b1) (Leaf b2)))) (if bool_dec b3 b4 then Leaf b3 else Node (Leaf b3) (Leaf b4)) *)
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    icase b;icase b0;icase b1;icase b2;icase b3;icase b4.

(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (mkCanon_identity _ c11);intro H11.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (mkCanon_identity _ c12);intro H12.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (mkCanon_identity _ c13);intro H13.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (mkCanon_identity _ c21);intro H21.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (mkCanon_identity _ c22);intro H22.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (mkCanon_identity _ c23);intro H23.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (mkCanon_identity _ c31);intro H31.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (mkCanon_identity _ c32);intro H32.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (mkCanon_identity _ c33);intro H33.
    generalize (mkCanon_rewrite x11);intro H14;
    destruct H14 as [x111 [x112 H14]].
    generalize (mkCanon_rewrite x12);intro H15;
    destruct H15 as [x121 [x122 H15]].
    generalize (mkCanon_rewrite x13);intro H16;
    destruct H16 as [x131 [x132 H16]].
    generalize (mkCanon_rewrite x21);intro H24;
    destruct H24 as [x211 [x212 H24]].
    generalize (mkCanon_rewrite x22);intro H25;
    destruct H25 as [x221 [x222 H25]].
    generalize (mkCanon_rewrite x23);intro H26;
    destruct H26 as [x231 [x232 H26]].
    generalize (mkCanon_rewrite x31);intro H34;
    destruct H34 as [x311 [x312 H34]].
    generalize (mkCanon_rewrite x32);intro H35;
    destruct H35 as [x321 [x322 H35]].
    generalize (mkCanon_rewrite x33);intro H36;
    destruct H36 as [x331 [x332 H36]].
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    rewrite H14 in H11.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite H15 in H12.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite H16 in H13.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite H24 in H21.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite H25 in H22.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite H26 in H23.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite H34 in H31.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite H35 in H32.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite H36 in H33.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c11 H11);intro H111.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c12 H12);intro H121.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c13 H13);intro H131.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c21 H21);intro H211.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c22 H22);intro H221.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c23 H23);intro H231.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c31 H31);intro H311.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c32 H32);intro H321.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    generalize (canonTree_proof_irr _ _ (mkCanon_correct _) c33 H33);intro H331.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite<-H111 in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite<-H121 in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) x13 c13) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite<-H131 in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite<-H211 in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite<-H221 in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x23 c23) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite<-H231 in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite<-H311 in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite<-H321 in *.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x33 c33) *)
    rewrite<-H331 in *.

(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    generalize (tree_avg_split _ _ _ _ _ _ _ H1);intro H6.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    generalize (tree_avg_split _ _ _ _ _ _ _ H2);intro H7.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    generalize (tree_avg_split _ _ _ _ _ _ _ H3);intro H8.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    destruct H6 as [H61 H62].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    destruct H7 as [H71 H72].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    destruct H8 as [H81 H82].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    generalize (mkCanon_join_split _ _ _ _ _ _ H4);intro H9.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    generalize (mkCanon_join_split _ _ _ _ _ _ H5);intro H10.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    destruct H9 as [H91 H92].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    destruct H10 as [H101 H102].
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    generalize (IHn _ _ _ _ _ _ _ _ _ H61 H71 H81 H91 H101);intro Hr1.
(* Goal: @join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x131 x132)) (mkCanon_correct (Node x131 x132))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x231 x232)) (mkCanon_correct (Node x231 x232))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node x331 x332)) (mkCanon_correct (Node x331 x332))) *)
    generalize (IHn _ _ _ _ _ _ _ _ _ H62 H72 H82 H92 H102);intro Hr2.
(* Goal: @eq t c0 c0 *)
    apply mkCanon_join_combine;trivial.
  Qed.

  Lemma tree_avg_increase : forall n t1 t2,
   t1 <> t2 -> max (height t1) (height t2) < n ->
   exists t3, avg n t1 t2 = Some t3 /\ height t3 = n.
  Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   induction n;intros.
(* Goal: False *)
   inv H0.

(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S n) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S n))) *)
   unfold tree_height in H0.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
   icase n.
   destruct t1 as [x1 c1];
   destruct t2 as [x2 c2].
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
   simpl in H0.
(* Goal: le (S O) (S n) *)
   assert (max (tree_heightP x1) (tree_heightP x2) = 0) by omega.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (le_max_l (tree_heightP x1) (tree_heightP x2));intro H2.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (le_max_r (tree_heightP x1) (tree_heightP x2));intro H3.
(* Goal: le (S O) (S n) *)
   assert (tree_heightP x1 = 0) by omega.
(* Goal: le (S O) (S n) *)
   assert (tree_heightP x2 = 0) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
   icase x1;icase x2.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (@Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (if bool_dec b b0 then Leaf b else Node (Leaf b) (Leaf b0)) (mkCanon_correct (Node (Leaf b) (Leaf b0))))) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x2_1 x2_2) c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x2_1 x2_2) c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   assert (b<> b0).
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
   intro;apply H.
(* Goal: @eq t c0 c0 *)
   rewrite H6;apply exist_ext;trivial.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   icase b;icase b0;simpl.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x2_1 x2_2) c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x2_1 x2_2) c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   try (elimtype False; tauto). (*useless in Coq.8.6 but required in Coq.8.6 *)
   exists (exist (fun t0 : ShareTree => canonicalTree t0)
          (Node (Leaf true) (Leaf false))
          (mkCanon_correct (Node (Leaf true) (Leaf false)))).
(* Goal: @eq t c0 c0 *)
   split;trivial.
   exists (exist (fun t0 : ShareTree => canonicalTree t0)
          (Node (Leaf false) (Leaf true))
          (mkCanon_correct (Node (Leaf false) (Leaf true)))).
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x2_1 x2_2) c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S O) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x2_1 x2_2) c2)) (@Some t t3)) (@eq nat (tree_height t3) (S O))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   try (elimtype False; tauto). (*useless in Coq.8.6 but required in Coq.8.6 *)
(* Goal: le (S O) (S n) *)
   inv H5;inv H4;elimtype False;omega.
(* Goal: le (S O) (S n) *)
   inv H5;inv H4;elimtype False;omega.
(* Goal: le (S O) (S n) *)
   inv H5;inv H4;elimtype False;omega.

(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (canonTree_rewrite1 t1);intro H3.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (canonTree_rewrite1 t2);intro H4.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct H3 as [t11 [t12 H3]].
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct H4 as [t21 [t22 H4]].
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) t1 t2) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H3,H4 in *.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (mkCanon_height_split _ _ _ _ _ H0);intro H5.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct H5 as [H5 H6].
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   assert (mkCanon (Node t11 t12) <> mkCanon (Node t21 t22)).
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
     intro;apply H.
(* Goal: @eq t c0 c0 *)
     apply exist_ext;trivial.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (mkCanon_diff _ _ _ _ H1);intro H7.

(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (shareTree_dec_eq (mkCanon t11) (mkCanon t21));intro H8.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct H8.

(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   assert (mkCanon t12 <> mkCanon t22).
(* Goal: not (@eq ShareTree (mkCanon t12) (mkCanon t22)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
     destruct H7.
(* Goal: @eq t c c *)
     tauto.
(* Goal: @eq t c0 c0 *)
     trivial.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   assert (tree_heightP (mkCanon t11) < S n).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
     generalize (le_max_l (tree_heightP (mkCanon t11)) (tree_heightP (mkCanon t21)));intro.
(* Goal: le (S O) (S n) *)
     omega.
   generalize (tree_avg_identity (S n)
              (exist (fun t => canonicalTree t) (mkCanon t11) (mkCanon_correct _)) H8);
   intro H9.
   assert (exist (fun t => canonicalTree t) (mkCanon t12) (mkCanon_correct _) <>
           exist (fun t => canonicalTree t) (mkCanon t22) (mkCanon_correct _)).
(* Goal: @eq t c0 c0 *)
     intro H10;apply H2;inv H10;trivial.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (IHn _ _ H10 H6);intro H11.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct H11 as [ t3 [H11 H12]].
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (canonTree_rewrite2 t3);intro H13.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H13 in H11.
   assert ((exist (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) =
           (exist (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21))).
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t21) (mkCanon_correct t21)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
     apply canonTree_proof_irr.
(* Goal: @eq t c0 c0 *)
     trivial.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H14 in H9 at 2.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (tree_avg_combine _ _ _ _ _ _ _ H9 H11);intro H15.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   unfold avg, avgable_tree in H15.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H15.
   exists (exist (fun t4 : ShareTree => canonicalTree t4)
          (mkCanon (Node t11 (proj1_sig t3)))
          (mkCanon_correct (Node t11 (proj1_sig t3)))).
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct t3 as [x3 c3].
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   unfold proj1_sig in *.
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node t11 x3)) (mkCanon_correct (Node t11 x3)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   assert (mkCanon (Node t11 x3) = Node (mkCanon t11) x3).
(* Goal: @eq ShareTree (mkCanon (Node t11 x3)) (Node (mkCanon t11) x3) *)
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node t11 x3)) (mkCanon_correct (Node t11 x3)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
      clear - c3 H12.
(* Goal: @eq ShareTree (mkCanon (Node t11 x3)) (Node (mkCanon t11) x3) *)
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node t11 x3)) (mkCanon_correct (Node t11 x3)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
      unfold tree_height in H12;simpl in H12.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
      simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
      generalize (mkCanon_identity _ c3);intro.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
      rewrite H.
(* Goal: @eq ShareTree match mkCanon t11 with | Leaf b1 => match x3 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t11) x3 | Node s s0 => Node (mkCanon t11) x3 end | Node s s0 => Node (mkCanon t11) x3 end (Node (mkCanon t11) x3) *)
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node t11 x3)) (mkCanon_correct (Node t11 x3)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
      icase (mkCanon t11).
(* Goal: @eq ShareTree match x3 with | Leaf b1 => match mkCanon t22 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x3 (mkCanon t22) | Node s s0 => Node x3 (mkCanon t22) end | Node s s0 => Node x3 (mkCanon t22) end (Node x3 (mkCanon t22)) *)
(* Goal: @eq nat (tree_heightP (mkCanon (Node x3 t22))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
      icase x3.
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node t11 x3)) (mkCanon_correct (Node t11 x3)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   clear -H8 H12 H16.
(* Goal: le (tree_heightP (mkCanon (intersect_tree (Node s1_1 s1_2) (Node s2_1 s2_2)))) (S n) *)
   unfold tree_height,proj1_sig in *.
(* Goal: @eq nat (tree_heightP (mkCanon (Node t11 x3))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H16.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
   replace (max (tree_heightP (mkCanon t11)) (tree_heightP x3) + 1) with
(* Goal: le (S O) (S n) *)
   (S (max (tree_heightP (mkCanon t11)) (tree_heightP x3))) by omega.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
   f_equal.
(* Goal: le (S O) (S n) *)
   assert (tree_heightP (mkCanon t11) <= tree_heightP x3 ) by omega.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (mkCanon t11)) (tree_heightP x3)) (S n) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite<- H12.
(* Goal: @eq t c0 c0 *)
   apply max_r;trivial.

(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (shareTree_dec_eq (mkCanon t12) (mkCanon t22));intro H8.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   unfold proj1_sig in *.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct H8.
   assert (exist (fun t => canonicalTree t) (mkCanon t11) (mkCanon_correct _) <>
           exist (fun t => canonicalTree t) (mkCanon t21) (mkCanon_correct _)).
(* Goal: @eq t c0 c0 *)
     intro H8;apply n0;inv H8;trivial.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (IHn _ _ H2 H5);intro H8.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct H8 as [t3 [H8 H9]].
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite e in H6.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   assert (tree_heightP (mkCanon t22) < S n).
     generalize (le_max_r (tree_heightP (mkCanon t22))
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
                          (tree_heightP (mkCanon t22)));intro.
(* Goal: le (S O) (S n) *)
     omega.
   generalize (tree_avg_identity (S n) (exist (fun t => canonicalTree t)
              (mkCanon t22) (mkCanon_correct _)) H10);intro H11.
   assert (exist (fun t : ShareTree => canonicalTree t) (mkCanon t12) (mkCanon_correct t12) =
           exist (fun t : ShareTree => canonicalTree t) (mkCanon t22) (mkCanon_correct t22)).
(* Goal: @eq t c0 c0 *)
     apply canonTree_proof_irr;trivial.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite<- H12 in H11 at 1.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (canonTree_rewrite2 t3);intro H13.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H13 in H8.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (tree_avg_combine _ _ _ _ _ _ _ H8 H11);intro H14.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   unfold avg,avgable_tree in H14.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H14.
   exists (exist (fun t4 : ShareTree => canonicalTree t4)
          (mkCanon (Node (proj1_sig t3) t22))
          (mkCanon_correct (Node (proj1_sig t3) t22))).
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct t3 as [x3 c3].
(* Goal: le (tree_heightP (mkCanon (intersect_tree (Node s1_1 s1_2) (Node s2_1 s2_2)))) (S n) *)
   unfold tree_height,proj1_sig in *.
(* Goal: @eq nat (tree_heightP (mkCanon (Node x3 t22))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   clear - H9 H10 c3.
(* Goal: @eq nat (tree_heightP (mkCanon (Node x3 t22))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   assert (mkCanon (Node x3 t22) = Node x3 (mkCanon t22)).
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq ShareTree match mkCanon x3 with | Leaf b1 => match mkCanon t22 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x3) (mkCanon t22) | Node s s0 => Node (mkCanon x3) (mkCanon t22) end | Node s s0 => Node (mkCanon x3) (mkCanon t22) end (Node x3 (mkCanon t22)) *)
(* Goal: @eq nat (tree_heightP (mkCanon (Node x3 t22))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (mkCanon_identity _ c3);intro H.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
   rewrite H.
(* Goal: @eq ShareTree match x3 with | Leaf b1 => match mkCanon t22 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x3 (mkCanon t22) | Node s s0 => Node x3 (mkCanon t22) end | Node s s0 => Node x3 (mkCanon t22) end (Node x3 (mkCanon t22)) *)
(* Goal: @eq nat (tree_heightP (mkCanon (Node x3 t22))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   icase x3.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
   rewrite H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
   assert (max (tree_heightP x3) (tree_heightP (mkCanon t22)) + 1 =
(* Goal: le (S O) (S n) *)
           S (max (tree_heightP x3) (tree_heightP (mkCanon t22)))) by omega.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
   rewrite H0;f_equal.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP x3) (tree_heightP (mkCanon t22))) (S n) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite<- H9 in *.
(* Goal: le (S O) (S n) *)
   assert (tree_heightP (mkCanon t22) <= tree_heightP x3) by omega.
(* Goal: @eq t c0 c0 *)
   apply max_l;trivial.

   assert (exist (fun t => canonicalTree t) (mkCanon t11) (mkCanon_correct _) <>
           exist (fun t => canonicalTree t) (mkCanon t21) (mkCanon_correct _)).
(* Goal: @eq t c0 c0 *)
    intro H8;apply n0;inv H8;trivial.
   assert (exist (fun t => canonicalTree t) (mkCanon t12) (mkCanon_correct _) <>
           exist (fun t => canonicalTree t) (mkCanon t22) (mkCanon_correct _)).
(* Goal: @eq t c0 c0 *)
    intro H8;apply n1;inv H8;trivial.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (IHn _ _ H2 H5);intro H9.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct H9 as [t3 [H9 H10]].
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (IHn _ _ H8 H6);intro H11.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   destruct H11 as [t4 [H11 H12]].
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (canonTree_rewrite2 t3);intro H13.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (canonTree_rewrite2 t4);intro H14.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H13 in H9.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H14 in H11.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   generalize (tree_avg_combine _ _ _ _ _ _ _ H9 H11);intro H15.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   unfold avg,avgable_tree in H15.
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
   rewrite H15.
   exists (exist (fun t5 : ShareTree => canonicalTree t5)
          (mkCanon (Node (proj1_sig t3) (proj1_sig t4)))
          (mkCanon_correct (Node (proj1_sig t3) (proj1_sig t4)))).
(* Goal: @eq t c0 c0 *)
   split;trivial.
   destruct t3 as [x3 c3];
   destruct t4 as [x4 c4].
(* Goal: le (tree_heightP (mkCanon (intersect_tree (Node s1_1 s1_2) (Node s2_1 s2_2)))) (S n) *)
   unfold tree_height,proj1_sig in *.
(* Goal: @eq nat (tree_heightP (mkCanon (Node x3 x4))) (S (S n)) *)
   clear -c3 c4 H10 H12.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: @eq nat (tree_heightP match mkCanon x3 with | Leaf b1 => match mkCanon x4 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x3) (mkCanon x4) | Node s s0 => Node (mkCanon x3) (mkCanon x4) end | Node s s0 => Node (mkCanon x3) (mkCanon x4) end) (S (S n)) *)
   generalize (mkCanon_identity _ c3);intro H1.
(* Goal: @eq nat (tree_heightP match mkCanon x3 with | Leaf b1 => match mkCanon x4 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x3) (mkCanon x4) | Node s s0 => Node (mkCanon x3) (mkCanon x4) end | Node s s0 => Node (mkCanon x3) (mkCanon x4) end) (S (S n)) *)
   generalize (mkCanon_identity _ c4);intro H2.
(* Goal: @eq nat (tree_heightP match mkCanon x3 with | Leaf b1 => match mkCanon x4 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon x3) (mkCanon x4) | Node s s0 => Node (mkCanon x3) (mkCanon x4) end | Node s s0 => Node (mkCanon x3) (mkCanon x4) end) (S (S n)) *)
   rewrite H1,H2.
(* Goal: @eq nat (tree_heightP match x3 with | Leaf b1 => match x4 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node x3 x4 | Node s s0 => Node x3 x4 end | Node s s0 => Node x3 x4 end) (S (S n)) *)
   icase x3;icase x4.
(* Goal: @eq nat (tree_heightP (Node (Node x3_1 x3_2) (Node x4_1 x4_2))) (S (S n)) *)
   simpl in *;clear -H10 H12.
(* Goal: @eq nat (Init.Nat.add (PeanoNat.Nat.max (Init.Nat.add (PeanoNat.Nat.max (tree_heightP x3_1) (tree_heightP x3_2)) (S O)) (Init.Nat.add (PeanoNat.Nat.max (tree_heightP x4_1) (tree_heightP x4_2)) (S O))) (S O)) (S (S n)) *)
   rewrite H10,H12.
(* Goal: @eq nat (Init.Nat.add (PeanoNat.Nat.max (S n) (S n)) (S O)) (S (S n)) *)
   generalize (max_idempotent (S n));intro H.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
   rewrite H.
(* Goal: le (S O) (S n) *)
   omega.
  Qed.

  (*L34*)
  Lemma tree_avg_ex: forall n t1 t2,
   height t1 < n ->
   height t2 < n ->
   exists t3, avg n t1 t2 = Some t3.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   simpl;intros.
(* Goal: @ex t (fun t3 : t => @eq (option t) (tree_avg n t1 t2) (@Some t t3)) *)
   assert (H1 := eq_dec t1 t2).
(* Goal: @ex t (fun t3 : t => @eq (option t) (tree_avg n t1 t2) (@Some t t3)) *)
   destruct H1 as [H1|H1].
(* Goal: @ex t (fun t3 : t => @eq (option t) (tree_avg n t1 t2) (@Some t t3)) *)
(* Goal: @ex t (fun t3 : t => @eq (option t) (tree_avg n t1 t2) (@Some t t3)) *)
   subst t2.
(* Goal: @ex t (fun s' : t => @ex t (fun s'' : t => and (@eq (option t) (@roundL t roundableL_tree (S n) s) (@Some t s')) (and (@eq (option t) (@roundR t roundableR_tree (S n) s) (@Some t s'')) (@eq (option t) (@avg t avgable_tree (S n) s' s'') (@Some t s))))) *)
   exists t1.
(* Goal: @eq (option t) (@avg t avgable_tree (S n) bot bot) (@Some t bot) *)
   apply tree_avg_identity.
(* Goal: @eq t c0 c0 *)
   trivial.
(* Goal: @ex t (fun t3 : t => @eq (option t) (tree_avg n t1 t2) (@Some t t3)) *)
   assert (H2 : max (height t1) (height t2) < n).
(* Goal: @eq t c0 c0 *)
    apply Nat.max_lub_lt;trivial.
(* Goal: @ex t (fun t3 : t => @eq (option t) (tree_avg n t1 t2) (@Some t t3)) *)
   assert (H3 := tree_avg_increase _ _ _ H1 H2).
(* Goal: @ex t (fun t3 : t => @eq (option t) (tree_avg n t1 t2) (@Some t t3)) *)
   destruct H3 as [t3 [H3 H4]].
(* Goal: @ex t (fun t3 : t => @eq (option t) (tree_avg n t1 t2) (@Some t t3)) *)
   exists t3.
(* Goal: @eq t c0 c0 *)
   trivial.
  Qed.

  (*L35*)
  Lemma avg_share_correct: forall n s,
   (height s <= S n)%nat ->
   exists s', exists s'',
    roundL (S n) s = Some s' /\
    roundR (S n) s = Some s'' /\
    avg (S n) s' s'' = Some s.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: @ex t (fun s' : t => @ex t (fun s'' : t => and (@eq (option t) (@roundL t roundableL_tree (S n) s) (@Some t s')) (and (@eq (option t) (@roundR t roundableR_tree (S n) s) (@Some t s'')) (@eq (option t) (@avg t avgable_tree (S n) s' s'') (@Some t s))))) *)
   copy H.
(* Goal: @ex t (fun s' : t => @ex t (fun s'' : t => and (@eq (option t) (@roundL t roundableL_tree (S n) s) (@Some t s')) (and (@eq (option t) (@roundR t roundableR_tree (S n) s) (@Some t s'')) (@eq (option t) (@avg t avgable_tree (S n) s' s'') (@Some t s))))) *)
   apply tree_round_left_Some in H.
(* Goal: @ex t (fun s' : t => @ex t (fun s'' : t => and (@eq (option t) (@roundL t roundableL_tree (S n) s) (@Some t s')) (and (@eq (option t) (@roundR t roundableR_tree (S n) s) (@Some t s'')) (@eq (option t) (@avg t avgable_tree (S n) s' s'') (@Some t s))))) *)
   apply tree_round_right_Some in H0.
(* Goal: @ex t (fun s' : t => @ex t (fun s'' : t => and (@eq (option t) (@roundL t roundableL_tree (S n) s) (@Some t s')) (and (@eq (option t) (@roundR t roundableR_tree (S n) s) (@Some t s'')) (@eq (option t) (@avg t avgable_tree (S n) s' s'') (@Some t s))))) *)
   destruct H as [t1 H].
(* Goal: @ex t (fun s' : t => @ex t (fun s'' : t => and (@eq (option t) (@roundL t roundableL_tree (S n) s) (@Some t s')) (and (@eq (option t) (@roundR t roundableR_tree (S n) s) (@Some t s'')) (@eq (option t) (@avg t avgable_tree (S n) s' s'') (@Some t s))))) *)
   destruct H0 as [t2 H0].
(* Goal: @ex t (fun s' : t => @ex t (fun s'' : t => and (@eq (option t) (@roundL t roundableL_tree (S n) s) (@Some t s')) (and (@eq (option t) (@roundR t roundableR_tree (S n) s) (@Some t s'')) (@eq (option t) (@avg t avgable_tree (S n) s' s'') (@Some t s))))) *)
   exists t1.
(* Goal: @ex t (fun s'' : t => and (@eq (option t) (@roundL t roundableL_tree (S n) s) (@Some t t1)) (and (@eq (option t) (@roundR t roundableR_tree (S n) s) (@Some t s'')) (@eq (option t) (@avg t avgable_tree (S n) t1 s'') (@Some t s)))) *)
   exists t2.
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq t c0 c0 *)
   split;trivial.
(* Goal: @eq t c0 c0 *)
   apply tree_avg_round2avg;trivial.
  Qed.

  (*L5*)
  Lemma decompose_recompose: forall t,
        decompose (recompose t) = t.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: @eq (prod canonTree canonTree) (@decompose canonTree decompose_tree (recompose t0)) t0 *)
    destruct t0 as [t1 t2].
    destruct t1 as [x1 c1];
    destruct t2 as [x2 c2].
    icase x1;icase x2;
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    icase (bool_dec b b0);
    try subst b0;
    unfold decompose;
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
    f_equal;
    apply exist_ext;
(* Goal: @eq t c0 c0 *)
    trivial.

    destruct (compose_canon1 b b0 n c1 c2) as [? [? [? ?]]];
    f_equal;
    apply exist_ext;
(* Goal: @eq t c0 c0 *)
    trivial.

    destruct (compose_canon2 b x2_1 x2_2 c1 c2) as [? [? [? ?]]];
    f_equal;
(* Goal: @eq t c0 c0 *)
    apply exist_ext;trivial.

    destruct (compose_canon3 x1_1 x1_2 b c1 c2) as [? [? [? ?]]];
    f_equal;
(* Goal: @eq t c0 c0 *)
    apply exist_ext;trivial.

    destruct (compose_canon4 x1_1 x1_2 x2_1 x2_2 c1 c2) as [? [? [? ?]]];
    f_equal;
(* Goal: @eq t c0 c0 *)
    apply exist_ext;trivial.
  Qed.
  (*L6*)
  Lemma recompose_decompose: forall t,
        recompose(decompose t) = t.
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: sumbool (@eq nat (tree_height t0) O) (not (@eq nat (tree_height t0) O)) *)
    destruct t0 as [x c].
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    icase x.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase b.

(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    simpl in *.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
    destruct c as [? [? [? ?]]].
(* Goal: @eq canonTree (match x1 as s return (forall _ : canonicalTree s, canonTree) with | Leaf b1 => fun c3 : True => match x2 as s return (forall _ : canonicalTree s, canonTree) with | Leaf b2 => fun c4 : True => match bool_dec b1 b2 with | left e => @eq_rec bool b1 (fun _ : bool => forall _ : True, canonTree) (fun _ : True => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b1) c3) b2 e c4 | right n => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf b1) (Leaf b2)) (compose_canon1 b1 b2 n c3 c4) end | Node x21 x22 => fun c4 : and (or (nonFullTree x21) (nonFullTree x22)) (and (or (nonEmptyTree x21) (nonEmptyTree x22)) (and (canonicalTree x21) (canonicalTree x22))) => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf b1) (Node x21 x22)) (compose_canon2 b1 x21 x22 c3 c4) end (@and_ind (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) (canonicalTree x2) (fun (_ : or (nonEmptyTree x1) (nonEmptyTree x2)) (H2 : and (canonicalTree x1) (canonicalTree x2)) => @and_ind (canonicalTree x1) (canonicalTree x2) (canonicalTree x2) (fun (_ : canonicalTree x1) (H3 : canonicalTree x2) => H3) H2) (@conj (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) o0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))) | Node x11 x12 => fun c3 : and (or (nonFullTree x11) (nonFullTree x12)) (and (or (nonEmptyTree x11) (nonEmptyTree x12)) (and (canonicalTree x11) (canonicalTree x12))) => match x2 as s return (forall _ : canonicalTree s, canonTree) with | Leaf b2 => fun c4 : True => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x11 x12) (Leaf b2)) (compose_canon3 x11 x12 b2 c3 c4) | Node x21 x22 => fun c4 : and (or (nonFullTree x21) (nonFullTree x22)) (and (or (nonEmptyTree x21) (nonEmptyTree x22)) (and (canonicalTree x21) (canonicalTree x22))) => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Node x11 x12) (Node x21 x22)) (compose_canon4 x11 x12 x21 x22 c3 c4) end (@and_ind (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) (canonicalTree x2) (fun (_ : or (nonEmptyTree x1) (nonEmptyTree x2)) (H2 : and (canonicalTree x1) (canonicalTree x2)) => @and_ind (canonicalTree x1) (canonicalTree x2) (canonicalTree x2) (fun (_ : canonicalTree x1) (H3 : canonicalTree x2) => H3) H2) (@conj (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) o0 (@conj (canonicalTree x1) (canonicalTree x2) c c0))) end (@and_ind (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) (canonicalTree x1) (fun (_ : or (nonEmptyTree x1) (nonEmptyTree x2)) (H2 : and (canonicalTree x1) (canonicalTree x2)) => @and_ind (canonicalTree x1) (canonicalTree x2) (canonicalTree x1) (fun (H0 : canonicalTree x1) (_ : canonicalTree x2) => H0) H2) (@conj (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) o0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (or (nonFullTree x1) (nonFullTree x2)) (and (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2))) o (@conj (or (nonEmptyTree x1) (nonEmptyTree x2)) (and (canonicalTree x1) (canonicalTree x2)) o0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) *)
    unfold recompose.
    icase x1;
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
    icase x2.
    icase (bool_dec b b0);try subst b0;
    simpl;
(* Goal: @eq t c0 c0 *)
    apply exist_ext;trivial.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    icase b;elimtype False;firstorder.

    f_equal;
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
    apply proof_irr.

    f_equal;
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
    apply proof_irr.

    f_equal;
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
    apply proof_irr.
 Qed.


 Lemma decompose_rewrite : forall t t1 t2, decompose t = (t1 ,t2)
       <-> t = exist (fun t => canonicalTree t)
              (mkCanon (Node (proj1_sig t1) (proj1_sig t2))) (mkCanon_correct _).
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
  destruct t0 as [x c];
  destruct t1 as [x1 c1];
  destruct t2 as [x2 c2].
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  icase x.

(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
  split;intros; inv H;
  generalize (mkCanon_identity _ c1);intro;
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (mkCanon_identity _ c2);intro.
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
  apply exist_ext.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
  rewrite H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.

  f_equal;
  apply exist_ext;
  rewrite H in H1;rewrite H0 in H1;
  icase x1;icase x2;
  icase b0;icase b1.

  split;intro;
  try apply exist_ext;
  simpl in H,c;
  destruct c as [? [? [? ?]]];
  inv H;
  simpl;
  generalize (mkCanon_identity _ c1);intro;
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (mkCanon_identity _ c2);intro.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
  rewrite H;rewrite H0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase x1;icase x2.
(* Goal: @eq ShareTree (Node (Leaf b0) (Leaf false)) (if bool_dec b0 false then Leaf b0 else Node (Leaf b0) (Leaf false)) *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
  icase b;icase b0.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
  elimtype False;firstorder.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
  elimtype False;firstorder.
  f_equal;apply exist_ext;
  rewrite H in H1;rewrite H0 in H1;
(* Goal: @eq t c c *)
  icase x1;icase x2;try icase b;try icase b0;inv H1;auto.
 Qed.
 (*L4*)
 Lemma decompose_height : forall n t1 t2 t3,
  height t1 = S n ->
  decompose t1 = (t2, t3) ->
  height t2 <= n /\ height t3 <= n.
  Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
    destruct t1 as [x1 c1];
    destruct t2 as [x2 c2];
(* Goal: @eq nat (tree_height (@exist ShareTree (fun t4 : ShareTree => canonicalTree t4) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t3) t22)))) (S (S n)) *)
(* Goal: @ex t (fun t3 : t => and (@eq (option t) (tree_avg (S (S n)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@Some t t3)) (@eq nat (tree_height t3) (S (S n)))) *)
    destruct t3 as [x3 c3].
(* Goal: @eq t match x1 with | Leaf (true as b) => t0 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) t1 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) t0 end bot *)
    icase x1.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
    simpl in H0.
(* Goal: and (le (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c2)) n) (le (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x3 c3)) n) *)
    destruct c1 as [? [? [? ?]]].
(* Goal: False *)
    inv H0.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
    unfold tree_height in *;simpl in *.
(* Goal: le (S O) (S n) *)
    assert (max (tree_heightP x2) (tree_heightP x3) <= n) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (max_lub_l _ _ _ H0);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (max_lub_r _ _ _ H0);intro.
(* Goal: @eq t c c *)
    tauto.
  Qed.
 (*L7*)
 Lemma decompose_join : forall t1 t11 t12 t2 t21 t22 t3 t31 t32,
    decompose t1 = (t11, t12) ->
    decompose t2 = (t21, t22) ->
    decompose t3 = (t31, t32) ->
    (join t1 t2 t3 <->
    (join t11 t21 t31 /\ join t12 t22 t32)).
 Proof.
(* Goal: forall (t1 t11 t12 t2 t21 t22 t3 t31 t32 : t) (_ : @eq (prod t t) (@decompose t decompose_tree t1) (@pair t t t11 t12)) (_ : @eq (prod t t) (@decompose t decompose_tree t2) (@pair t t t21 t22)) (_ : @eq (prod t t) (@decompose t decompose_tree t3) (@pair t t t31 t32)), iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   intros ? ? ? ? ? ? ? ? ? H1 H2 H3.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   generalize (decompose_rewrite t1 t11 t12);intro H11.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   generalize (decompose_rewrite t2 t21 t22);intro H21.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   generalize (decompose_rewrite t3 t31 t32);intro H31.
   destruct H11 as [H11 _];
   destruct H21 as [H21 _];
   destruct H31 as [H31 _].
   specialize ( H11 H1);
   specialize ( H21 H2);
   specialize ( H31 H3).
   generalize (canonTree_rewrite2 t11);intro H12;
   generalize (canonTree_rewrite2 t12);intro H13;
   generalize (canonTree_rewrite2 t21);intro H22;
   generalize (canonTree_rewrite2 t22);intro H23;
   generalize (canonTree_rewrite2 t31);intro H32;
   generalize (canonTree_rewrite2 t32);intro H33.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   rewrite H12,H13,H22,H23,H32,H33,H11,H21,H31.
(* Goal: iff (@join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))))) (and (@join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31)))) (@join t Join_ba (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))))) *)
   clear.

(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   split;intro.
(* Goal: @eq t c0 c0 *)
   apply mkCanon_join_split;trivial.
(* Goal: le (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
   destruct H as [H1 H2].
(* Goal: @eq t c0 c0 *)
   apply mkCanon_join_combine;trivial.
  Qed.

  Lemma is_height_zero : forall t, {height t = 0} + {height t <> 0}.
  Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros.
(* Goal: sumbool (@eq nat (tree_height t0) O) (not (@eq nat (tree_height t0) O)) *)
   destruct t0 as [x c].
(* Goal: sumbool (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O) (not (@eq nat (tree_height (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) O)) *)
   unfold tree_height in *.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
   icase x.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   right.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
   simpl.
(* Goal: le (S O) (S n) *)
   omega.
  Defined.


(*START THE MEASUREMENT FOR BLACK NODES*)

Fixpoint countBLeafST (n : nat) (s : ShareTree) : nat :=
 match (n,s) with
 | (0,Leaf true) => 1
 | (0,Leaf false) => 0
 | (0, Node s1 s2) => 0
 | (S n', Leaf true) => (countBLeafST n' (Leaf true)) + (countBLeafST n' (Leaf true))
 | (S n', Leaf false) => 0
 | (S n', Node s1 s2) => (countBLeafST n' s1) + (countBLeafST n' s2)
 end.

Definition countBLeafCT (n : nat) (s : canonTree) : nat :=
  countBLeafST n (proj1_sig s).
(*L11*)
Lemma decompose_height_le : forall n s s1 s2,
 decompose s = (s1,s2) ->
 height s <= S n ->
 height s1 <= n /\ height s2 <= n.
Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
  destruct s as [s pf];
  destruct s1 as [s1 pf1];
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
  destruct s2 as [s2 pf2].
  icase s;
  simpl in H;
  destruct pf;
  inv H;
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  unfold tree_height in *;simpl in *.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: le (S O) (S n) *)
  assert (max (tree_heightP s1) (tree_heightP s2) <= n) by omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (max_lub_l _ _ _ H);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (max_lub_r _ _ _ H);intro.
(* Goal: @eq t c c *)
  tauto.
Qed.
(*12*)
Lemma decompose_le: forall s1 s2 s11 s12 s21 s22,
 (s1 <= s2)%ba ->
 decompose s1 = (s11,s12) ->
 decompose s2 = (s21,s22) ->
 (s11 <= s21)%ba /\ (s12 <= s22)%ba.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
 destruct s1 as [s1 pf1];
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
 destruct s2 as [s2 pf2].
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
 unfold Ord in H;simpl in H.
 icase s1;icase s2;inv H0;inv H1;unfold Ord;
 simpl in pf1,pf2;
 destruct pf1;
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 destruct pf2;simpl.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 icase b;icase b0;inv H.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 inversion H;subst.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 inversion H2;subst.
(* Goal: @eq t c c *)
 tauto.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 inversion H;subst.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 inversion H1;subst.
(* Goal: @eq t c c *)
 tauto.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 inversion H;subst.
(* Goal: @eq t c c *)
 tauto.
Qed.
(*L13*)
Lemma decompose_diff: forall s1 s2 s11 s12 s21 s22,
 s1 <> s2 ->
 decompose s1 = (s11,s12) ->
 decompose s2 = (s21,s22) ->
 s11 <> s21 \/ s12 <> s22.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: or (not (@eq t s11 s21)) (not (@eq t s12 s22)) *)
 assert (H2 := canonTree_eq_dec s11 s21).
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
 destruct H2 as [H2|H2].
(* Goal: or (not (@eq t s11 s21)) (not (@eq t s12 s22)) *)
(* Goal: or (not (@eq t s11 s21)) (not (@eq t s12 s22)) *)
 subst s11.
(* Goal: or (not (@eq t s21 s21)) (not (@eq t s12 s22)) *)
(* Goal: or (not (@eq t s11 s21)) (not (@eq t s12 s22)) *)
 assert (H2 := canonTree_eq_dec s12 s22).
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
 destruct H2 as [H2|H2].
(* Goal: or (not (@eq t s21 s21)) (not (@eq t s12 s22)) *)
(* Goal: or (not (@eq t s21 s21)) (not (@eq t s12 s22)) *)
(* Goal: or (not (@eq t s11 s21)) (not (@eq t s12 s22)) *)
 subst s12.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
 elimtype False.
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
 apply H.
(* Goal: @eq t s1 s2 *)
(* Goal: or (not (@eq t s21 s21)) (not (@eq t s12 s22)) *)
(* Goal: or (not (@eq t s11 s21)) (not (@eq t s12 s22)) *)
 rewrite<- H1 in H0.
(* Goal: @eq t s1 s2 *)
(* Goal: or (not (@eq t s21 s21)) (not (@eq t s12 s22)) *)
(* Goal: or (not (@eq t s11 s21)) (not (@eq t s12 s22)) *)
 assert (H2 : recompose (decompose s1) = recompose (decompose s2)).
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
   f_equal.
(* Goal: @eq t c0 c0 *)
   trivial.
(* Goal: @eq t s1 s2 *)
(* Goal: or (not (@eq t s21 s21)) (not (@eq t s12 s22)) *)
(* Goal: or (not (@eq t s11 s21)) (not (@eq t s12 s22)) *)
 repeat rewrite recompose_decompose in H2.
(* Goal: @eq t c0 c0 *)
 trivial.
(* Goal: @eq t c0 c0 *)
 right;trivial.
(* Goal: @eq t c0 c0 *)
 left;trivial.
Qed.

(*L36*)
Lemma countBLeafCT_decompose : forall n s s1 s2,
 decompose s = (s1,s2) ->
 countBLeafCT (S n) s = countBLeafCT n s1 + countBLeafCT n s2.
Proof.
(* Goal: @eq nat (tree_height (comp s)) (tree_height s) *)
  destruct s as [s pf].
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  icase s;intros.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  simpl in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold countBLeafCT;simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: le (S O) (S n) *)
  icase n;compute;omega.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  simpl in H.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
  simpl in pf.
(* Goal: @eq nat (countBLeafCT (S n) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (Init.Nat.add (countBLeafCT n s0) (countBLeafCT n s3)) *)
  destruct pf as [H1 [H2 [H3 H4]]].
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold countBLeafCT;simpl.
(* Goal: @eq t c0 c0 *)
  trivial.
Qed.

(*L37*)
Lemma countBLeafCT_le : forall n s1 s2,
  (s1 <= s2)%ba -> countBLeafCT n s1 <= countBLeafCT n s2.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  induction n;intros.
  destruct s1 as [s1 pf1];
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
  destruct s2 as [s2 pf2].
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold countBLeafCT;simpl.
  icase s1;icase s2;
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  try icase b;try icase b0;inv H.
(* Goal: le (S O) O *)
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  compute in H2.
(* Goal: le (S O) O *)
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  inversion H2.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  inv H2.
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  simpl in pf2.
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  destruct pf2 as [H6 [H7 [H8 H9]]].
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  assert (H10 := top_correct (exist (fun t => canonicalTree t) s2_1 H8)).
(* Goal: @eq t c c *)
  assert (H11 : (top <= exist (fun t => canonicalTree t) s2_1 H8)%ba) by auto.
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  assert (H12 := ord_antisym _ _ H10 H11).
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  unfold top in H12;inv H12.
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  assert (H13 := top_correct (exist (fun t => canonicalTree t) s2_2 H9)).
(* Goal: @eq t c c *)
  assert (H14 : (top <= exist (fun t => canonicalTree t) s2_2 H9)%ba) by auto.
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  assert (H15 := ord_antisym _ _ H13 H14).
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  unfold top in H15;inv H15.
(* Goal: le (S O) O *)
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  destruct H6 as [H6|H6];inv H6.
  (*INDUCTIVE CASE*)
  remember (decompose s1) as ds1;
  remember (decompose s2) as ds2;
  destruct ds1 as [s11 s12];
  destruct ds2 as [s21 s22];
  symmetry in Heqds1, Heqds2.
(* Goal: @eq t c0 c0 *)
  apply decompose_le with (s11:=s11) (s12:=s12) (s21:=s21) (s22:=s22) in H;trivial.
(* Goal: le (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
  destruct H as [H1 H2].
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  assert (H3 := IHn _ _ H1).
(* Goal: le (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  assert (H4 := IHn _ _ H2).
(* Goal: @eq t c0 c0 *)
  rewrite countBLeafCT_decompose with (s1:=s11) (s2:=s12);trivial.
(* Goal: @eq t c0 c0 *)
  rewrite countBLeafCT_decompose with (s1:=s21) (s2:=s22);trivial.
(* Goal: le (S O) (S n) *)
  omega.
Qed.
(*L38*)
Lemma countBLeafCT_lt : forall n s1 s2,
  (s1 <= s2)%ba ->
   s1 <> s2 ->
   height s2 <= n ->
   countBLeafCT n s1 < countBLeafCT n s2.
Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  induction n;intros.
  destruct s1 as [s1 pf1];
  destruct s2 as [s2 pf2];
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold countBLeafCT;simpl.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) s1 pf1) s2)) (S n) *)
  icase s1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  elimtype False.
(* Goal: not (@eq t bot s) *)
(* Goal: le (@height t tree_heightable s) n *)
  apply H0.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) bot *)
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  apply ord_antisym.
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
  apply H.
(* Goal: Ord (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node s1_1 s1_2) pf1) top *)
(* Goal: not (@eq t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node s1_1 s1_2) pf1) top) *)
(* Goal: le (@height t tree_heightable top) n2 *)
(* Goal: le (S O) (Init.Nat.sub (countBLeafCT n2 top) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT n2 s2) (countBLeafCT n2 s1)) *)
  apply top_correct.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) s2 pf2))) (S n) *)
  icase s2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  elimtype False.
(* Goal: not (@eq t bot s) *)
(* Goal: le (@height t tree_heightable s) n *)
  apply H0.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
  f_equal.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  apply proof_irr.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  elimtype False.
(* Goal: False *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  unfold tree_height in H1.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
  simpl in H1.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) s2 pf2))) (S n) *)
  icase s2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  assert (exist (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1 = bot).
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) bot *)
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
    apply ord_antisym.
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
    apply H.
(* Goal: Ord bot s *)
(* Goal: not (@eq t bot s) *)
(* Goal: le (@height t tree_heightable s) n *)
    apply bot_correct.
(* Goal: lt O O *)
(* Goal: lt O O *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  inv H2.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  elimtype False.
(* Goal: False *)
(* Goal: lt (countBLeafCT (S n) s1) (countBLeafCT (S n) s2) *)
  unfold tree_height in H1.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
  simpl in H1.
(* Goal: le (S O) (S n) *)
  omega.
  (*INDUCTIVE CASE*)
  remember (decompose s1) as ds1;
  remember (decompose s2) as ds2;
  destruct ds1 as [s11 s12];
  destruct ds2 as [s21 s22];
  symmetry in Heqds1,Heqds2.
(* Goal: @eq t c0 c0 *)
  rewrite countBLeafCT_decompose with (s1:=s11) (s2:=s12);trivial.
(* Goal: @eq t c0 c0 *)
  rewrite countBLeafCT_decompose with (s1:=s21) (s2:=s22);trivial.
(* Goal: @eq t c0 c0 *)
  apply decompose_height_le with (s1:=s21) (s2:=s22) in H1;trivial.
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
  destruct H1 as [H1 H2].
(* Goal: @eq t c0 c0 *)
  apply decompose_le with (s11:=s11) (s12:=s12) (s21:=s21) (s22:=s22) in H;trivial.
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
  destruct H as [H3 H4].
(* Goal: @eq t c0 c0 *)
  apply decompose_diff with (s11:=s11) (s12:=s12) (s21:=s21) (s22:=s22) in H0;trivial.
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
  destruct H0 as [H0|H0].
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
  specialize ( IHn s11 s21 H3 H0 H1).
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
  assert (H5 := countBLeafCT_le n _ _ H4).
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
  specialize ( IHn s12 s22 H4 H0 H2).
(* Goal: lt (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22)) *)
  assert (H5 := countBLeafCT_le n _ _ H3).
(* Goal: le (S O) (S n) *)
  omega.
Qed.


Fixpoint power (base : nat) (exp : nat) : nat :=
 match exp with
 | 0 => 1
 | S n => base * (power base n)
 end.

(*L39*)
Lemma countBLeafCT_limit: forall n s, countBLeafCT n s <= power 2 n.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 induction n;intros.
 simpl;
 destruct s as [s pf];unfold countBLeafCT;simpl;
(* Goal: or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) s pf) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) s pf) bot) *)
 icase s.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase b.
 (*INDUCTIVE CASE*)
 remember (decompose s) as ds;
 destruct ds as [s1 s2];
(* Goal: le (countBLeafCT (S n1) s) (countBLeafCT (S n2) s) *)
 symmetry in Heqds.
(* Goal: @eq t c0 c0 *)
 rewrite countBLeafCT_decompose with (s1:=s1) (s2:=s2);trivial.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (Init.Nat.add (countBLeafCT n s1) (countBLeafCT n s2)) (Init.Nat.add (power (S (S O)) n) (Init.Nat.add (power (S (S O)) n) O)) *)
 assert (H1 := IHn s1).
(* Goal: le (Init.Nat.add (countBLeafCT n s1) (countBLeafCT n s2)) (Init.Nat.add (power (S (S O)) n) (Init.Nat.add (power (S (S O)) n) O)) *)
 assert (H2 := IHn s2).
(* Goal: le (S O) (S n) *)
 omega.
Qed.

(*L40*)
Lemma countBLeafCT_bot: forall n, countBLeafCT n bot = 0.
Proof.
(* Goal: forall n : nat, @eq nat (countBLeafCT n bot) O *)
 induction n.
(* Goal: @eq nat (countBLeafCT O bot) O *)
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 assert (H1 := countBLeafCT_lt 0 bot top).
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H1.
(* Goal: Ord bot s *)
(* Goal: not (@eq t bot s) *)
(* Goal: le (@height t tree_heightable s) n *)
 apply bot_correct.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 intro.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 inv H.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H1.
(* Goal: le (S O) (S n) *)
 compute;omega.
(* Goal: @eq nat (countBLeafCT O bot) O *)
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 assert (H2 := countBLeafCT_limit 0 top).
(* Goal: @eq nat (countBLeafCT O bot) O *)
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 simpl in H2.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 assert (decompose bot = (bot,bot)).
(* Goal: @eq t c c *)
  tauto.
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 apply countBLeafCT_decompose with (n := n) in H .
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 rewrite IHn in H.
(* Goal: le (S O) (S n) *)
 omega.
Qed.

(*L41*)
Lemma countBLeafCT_top: forall n, countBLeafCT n top = power 2 n.
Proof.
(* Goal: forall n : nat, @eq nat (countBLeafCT n bot) O *)
 induction n.
(* Goal: @eq nat (countBLeafCT O bot) O *)
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 assert (H1 := countBLeafCT_lt 0 bot top).
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H1.
(* Goal: Ord bot s *)
(* Goal: not (@eq t bot s) *)
(* Goal: le (@height t tree_heightable s) n *)
 apply bot_correct.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 intro.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 inv H.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H1.
(* Goal: le (S O) (S n) *)
 compute;omega.
(* Goal: @eq nat (countBLeafCT O bot) O *)
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 assert (H2 := countBLeafCT_limit 0 top).
(* Goal: @eq nat (countBLeafCT O bot) O *)
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 simpl in H2.
 rewrite countBLeafCT_bot in H1.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: @eq t c c *)
 assert (H : decompose top = (top,top)) by auto.
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 apply countBLeafCT_decompose with (n:=n) in H.
(* Goal: @eq nat (countBLeafCT (S n) bot) O *)
 rewrite IHn in H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (S O) (S n) *)
 omega.
Qed.

(*L42*)
Lemma countBLeafCT_positive : forall s n,
 height s <= n -> bot <> s ->
 0 < countBLeafCT n s.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: lt O (countBLeafCT n s) *)
 replace 0 with (countBLeafCT n bot) by apply countBLeafCT_bot.
(* Goal: lt (countBLeafCT n2 (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node s1_1 s1_2) pf1)) (countBLeafCT n2 top) *)
(* Goal: le (S O) (Init.Nat.sub (countBLeafCT n2 top) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT n2 s2) (countBLeafCT n2 s1)) *)
 apply countBLeafCT_lt.
(* Goal: Ord bot s *)
(* Goal: not (@eq t bot s) *)
(* Goal: le (@height t tree_heightable s) n *)
 apply bot_correct.
(* Goal: not (@eq t bot s) *)
(* Goal: le (@height t tree_heightable s) n *)
 apply H0.
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
 apply H.
Qed.

(*L43*)
Lemma countBLeafCT_mono_le: forall n1 n2 s,
 n1 <= n2 ->
 countBLeafCT n1 s <= countBLeafCT n2 s .
Proof.
(* Goal: forall (n1 n2 : nat) (s : canonTree) (_ : le n1 n2), le (countBLeafCT n1 s) (countBLeafCT n2 s) *)
 induction n1.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 destruct s as [s pf];intros.
(* Goal: iff (not (@eq t s bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct s.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase b.
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf)) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) with top.
(* Goal: lt (countBLeafCT O top) (countBLeafCT (S n2) top) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 repeat rewrite countBLeafCT_top.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: lt (power (S (S O)) O) (power (S (S O)) (S n2)) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 induction n2.
(* Goal: le (S O) (S n) *)
 simpl;omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: lt (power (S (S O)) O) (power (S (S O)) (S (S n2))) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 spec IHn2.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: @eq t (let (x, _) := top in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree top in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
 unfold top.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 f_equal;apply proof_irr.
(* Goal: @eq t (rel rightTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 icase n2;compute.
(* Goal: le (S O) (S n) *)
 compute;omega.
 (*INDUCTIVE CASE*)
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: le (share_metric (S n1) s) (share_metric n2 s) *)
 icase n2.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 inv H.
(* Goal: le (S O) (S n) *)
 assert (H1 : n1 <= n2) by omega.
(* Goal: le (countBLeafCT (S n1) s) (countBLeafCT (S n2) s) *)
 remember (decompose s) as ds.
(* Goal: le (countBLeafCT (S n1) s) (countBLeafCT (S n2) s) *)
 destruct ds as [s1 s2].
(* Goal: le (countBLeafCT (S n1) s) (countBLeafCT (S n2) s) *)
 symmetry in Heqds.
(* Goal: le (countBLeafCT (S n1) s) (countBLeafCT (S n2) s) *)
 assert (H2 := countBLeafCT_decompose n1 _ _ _ Heqds).
(* Goal: le (countBLeafCT (S n1) s) (countBLeafCT (S n2) s) *)
 assert (H3 := countBLeafCT_decompose n2 _ _ _ Heqds).
(* Goal: le (countBLeafCT (S n1) s) (countBLeafCT (S n2) s) *)
 assert (H4 := IHn1 n2 s1).
(* Goal: le (countBLeafCT (S n1) s) (countBLeafCT (S n2) s) *)
 assert (H5 := IHn1 n2 s2).
(* Goal: le (S O) (S n) *)
 omega.
Qed.

(*L44*)
Lemma countBLeafCT_mono_diff: forall n1 n2 s1 s2,
 n1 <= n2 ->
 (s1 <= s2)%ba ->
 countBLeafCT n1 s2 - countBLeafCT n1 s1 <= countBLeafCT n2 s2 - countBLeafCT n2 s1.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 induction n1;intros.
 destruct s1 as [s1 pf1];
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
 destruct s2 as [s2 pf2].
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) s2 pf2))) (S n) *)
 icase s1;icase s2.
(* Goal: @eq ShareTree (Node (Leaf b0) (Leaf false)) (if bool_dec b0 false then Leaf b0 else Node (Leaf b0) (Leaf false)) *)
(* Goal: @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b)))) (mkCanon_correct (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel leftTree a)) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (rel rightTree b))))) (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) a) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) b)))) *)
 icase b;icase b0.
(* Goal: le (tree_height (glb s2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf1))) (S n) *)
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf1) with top.
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (S n) *)
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) with top.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 unfold top;f_equal;apply proof_irr.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 unfold top;f_equal;apply proof_irr.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2))) (S n) *)
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf false) pf2) with bot.
(* Goal: le (Init.Nat.sub (countBLeafCT O bot) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf1))) (Init.Nat.sub (countBLeafCT n2 bot) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf1))) *)
(* Goal: @eq t bot (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) pf2) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT n2 s2) (countBLeafCT n2 s1)) *)
 repeat rewrite countBLeafCT_bot.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 unfold bot;f_equal;apply proof_irr.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (S n) *)
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) with top.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1) s2)) (S n) *)
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf false) pf1) with bot.
(* Goal: le (S O) (Init.Nat.sub (countBLeafCT n2 top) (countBLeafCT n2 bot)) *)
(* Goal: @eq t bot (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) pf1) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT n2 s2) (countBLeafCT n2 s1)) *)
 rewrite countBLeafCT_bot.
(* Goal: le (S O) (Init.Nat.sub (countBLeafCT n2 top) O) *)
(* Goal: @eq t bot (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf false) pf1) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT n2 s2) (countBLeafCT n2 s1)) *)
 rewrite countBLeafCT_top.
(* Goal: lt (power (S (S O)) O) (power (S (S O)) (S n2)) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 induction n2.
(* Goal: le (S O) (S n) *)
 simpl;omega.
(* Goal: lt (power (S (S O)) O) (power (S (S O)) (S (S n2))) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 spec IHn2.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: le (S O) (S n) *)
 simpl;omega.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 unfold bot;f_equal;apply proof_irr.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 unfold top;f_equal;apply proof_irr.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase b.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase b.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (S n) *)
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) with top.
(* Goal: le (S O) (Init.Nat.sub (countBLeafCT n2 top) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT n2 s2) (countBLeafCT n2 s1)) *)
 assert (H1 : countBLeafCT n2 (exist (fun t0 : ShareTree => canonicalTree t0) (Node s1_1 s1_2) pf1) < countBLeafCT n2 top).
(* Goal: lt (countBLeafCT n2 (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node s1_1 s1_2) pf1)) (countBLeafCT n2 top) *)
(* Goal: le (S O) (Init.Nat.sub (countBLeafCT n2 top) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT n2 s2) (countBLeafCT n2 s1)) *)
   apply countBLeafCT_lt.
(* Goal: Ord (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node s1_1 s1_2) pf1) top *)
(* Goal: not (@eq t (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Node s1_1 s1_2) pf1) top) *)
(* Goal: le (@height t tree_heightable top) n2 *)
(* Goal: le (S O) (Init.Nat.sub (countBLeafCT n2 top) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) (Init.Nat.sub (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2)) (countBLeafCT n2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1))) *)
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT n2 s2) (countBLeafCT n2 s1)) *)
   apply top_correct.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   intro.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
   inv H1.
(* Goal: le (S O) (S n) *)
   compute;omega.
 remember (countBLeafCT n2
       (exist (fun t0 : ShareTree => canonicalTree t0) (Node s1_1 s1_2) pf1)) as n0.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 unfold top;f_equal;apply proof_irr.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: le (S O) (S n) *)
 omega.
 (*INDUCTIVE CASE*)
(* Goal: le (share_metric (S n1) s) (share_metric n2 s) *)
 icase n2.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 inv H.
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 assert (H1 : n1 <= n2).
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 remember (decompose s1) as ds1.
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 destruct ds1 as [s11 s12].
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 symmetry in Heqds1.
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 remember (decompose s2) as ds2.
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 destruct ds2 as [s21 s22].
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 symmetry in Heqds2.
(* Goal: @eq t c0 c0 *)
 apply decompose_le with (s11:=s11) (s12:=s12) (s21:=s21) (s22:=s22) in H0;trivial.
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 destruct H0 as [H2 H3].
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 assert (H4 := IHn1 n2 s11 s21 H1 H2).
(* Goal: le (Init.Nat.sub (countBLeafCT (S n1) s2) (countBLeafCT (S n1) s1)) (Init.Nat.sub (countBLeafCT (S n2) s2) (countBLeafCT (S n2) s1)) *)
 assert (H5 := IHn1 n2 s12 s22 H1 H3).
(* Goal: @eq t c0 c0 *)
 rewrite countBLeafCT_decompose with (s1:=s21) (s2:=s22);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite countBLeafCT_decompose with (s1:=s11) (s2:=s12);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite countBLeafCT_decompose with (s1:=s21) (s2:=s22);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite countBLeafCT_decompose with (s1:=s11) (s2:=s12);trivial.
(* Goal: le (Init.Nat.sub (Init.Nat.add (countBLeafCT n1 s21) (countBLeafCT n1 s22)) (Init.Nat.add (countBLeafCT n1 s11) (countBLeafCT n1 s12))) (Init.Nat.sub (Init.Nat.add (countBLeafCT n2 s21) (countBLeafCT n2 s22)) (Init.Nat.add (countBLeafCT n2 s11) (countBLeafCT n2 s12))) *)
 assert (H6 := countBLeafCT_le n2 _ _ H2).
(* Goal: le (Init.Nat.sub (Init.Nat.add (countBLeafCT n1 s21) (countBLeafCT n1 s22)) (Init.Nat.add (countBLeafCT n1 s11) (countBLeafCT n1 s12))) (Init.Nat.sub (Init.Nat.add (countBLeafCT n2 s21) (countBLeafCT n2 s22)) (Init.Nat.add (countBLeafCT n2 s11) (countBLeafCT n2 s12))) *)
 assert (H7 := countBLeafCT_le n2 _ _ H3).
(* Goal: le (S O) (S n) *)
 omega.
Qed.

(*L45*)
Lemma countBLeafCT_mono_lt: forall n1 n2 s,
 n1 < n2 ->
 0 < countBLeafCT n1 s ->
 countBLeafCT n1 s < countBLeafCT n2 s .
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 induction n1;intros.
(* Goal: le (share_metric (S n1) s) (share_metric n2 s) *)
 icase n2.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 inv H.
(* Goal: @eq nat (tree_height (comp s)) (tree_height s) *)
 destruct s as [s pf].
(* Goal: or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) s pf) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) s pf) bot) *)
 icase s.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase b.
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf)) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) with top.
(* Goal: lt (countBLeafCT O top) (countBLeafCT (S n2) top) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 repeat rewrite countBLeafCT_top.
(* Goal: lt (power (S (S O)) O) (power (S (S O)) (S n2)) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 induction n2.
(* Goal: le (S O) (S n) *)
 compute;omega.
(* Goal: lt (power (S (S O)) O) (power (S (S O)) (S (S n2))) *)
(* Goal: @eq t top (@exist ShareTree (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf) *)
(* Goal: lt (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) (countBLeafCT (S n2) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1 s2) pf)) *)
(* Goal: lt (countBLeafCT (S n1) s) (countBLeafCT n2 s) *)
 spec IHn2.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: le (S O) (S n) *)
 simpl in *;omega.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 unfold top;f_equal;apply proof_irr.
(* Goal: False *)
 inv H0.
 (*INDUCTIVE CASE*)
(* Goal: le (share_metric (S n1) s) (share_metric n2 s) *)
 icase n2.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 inv H.
(* Goal: le (S O) (S n) *)
 assert ( H1 : n1 < n2) by omega.
 remember (decompose s) as ds;
 destruct ds as [s1 s2];
(* Goal: le (countBLeafCT (S n1) s) (countBLeafCT (S n2) s) *)
 symmetry in Heqds.
(* Goal: @eq t c0 c0 *)
 repeat rewrite countBLeafCT_decompose with (s1:=s1)(s2:=s2);trivial.
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
 assert (H2 : 0 < countBLeafCT n1 s1 \/ 0 < countBLeafCT n1 s2).
(* Goal: or (lt O (countBLeafCT n1 s1)) (lt O (countBLeafCT n1 s2)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
  apply countBLeafCT_decompose with (n:=n1) in Heqds.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
 destruct H2 as [H2|H2].
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
 specialize ( IHn1 n2 s1 H1 H2).
(* Goal: le (S O) (S n) *)
 assert (H3 : n1 <= n2) by omega.
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
 apply countBLeafCT_mono_le with (s:=s2) in H3.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
 specialize ( IHn1 n2 s2 H1 H2).
(* Goal: le (S O) (S n) *)
 assert (H3 : n1 <= n2) by omega.
(* Goal: lt (Init.Nat.add (countBLeafCT n1 s1) (countBLeafCT n1 s2)) (Init.Nat.add (countBLeafCT n2 s1) (countBLeafCT n2 s2)) *)
 apply countBLeafCT_mono_le with (s:=s1) in H3.
(* Goal: le (S O) (S n) *)
 omega.
Qed.

(*Borrow those two lemmas from to_formula*)
 Lemma bot_join: forall t1 t2,
   join bot t1 t2 ->  t1 = t2.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq t c0 c0 *)
  rewrite lub_commute in H0. rewrite lub_bot in H0. trivial.
 Qed.

 Lemma join_top : forall t1 t2, join top t1 t2 -> t1 = bot /\ t2 = top.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
   intros. destruct H.
(* Goal: and (@eq t t1 bot) (@eq t t2 top) *)
   rewrite glb_commute, glb_top in H.
(* Goal: @eq t c c *)
   rewrite lub_commute, lub_top in H0. split; auto.
 Qed.

 Lemma tree_height_0: forall s, height s = 0 -> s = top \/ s = bot.
 Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: @eq nat (tree_height (comp s)) (tree_height s) *)
  destruct s as [s pf].
(* Goal: or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) s pf) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) s pf) bot) *)
  icase s.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  left;unfold top;f_equal;apply proof_irr.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  right;unfold bot;f_equal;apply proof_irr.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  unfold tree_height in H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  simpl in H.
(* Goal: le (S O) (S n) *)
  elimtype False;omega.
 Qed.

 (*L55*)
 Lemma tree_height_glb_limit: forall n s1 s2,
  height s1 <= n ->
  height s2 <= n ->
  height (glb s1 s2) <= n.
Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 induction n;intros.
(* Goal: False *)
 inv H;inv H0.
(* Goal: @eq ShareTree match mkCanon (intersect_tree t11 t21) with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon (intersect_tree t11 t21)) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
 rewrite H2.
(* Goal: le (tree_height (lub s1 s2)) (tree_height s1) *)
(* Goal: le (tree_height (lub s1 s2)) (S n) *)
 apply tree_height_0 in H1.
(* Goal: le (tree_height (lub s1 s2)) (tree_height s1) *)
(* Goal: le (tree_height (lub s1 s2)) (S n) *)
 apply tree_height_0 in H2.
(* Goal: le (S O) (S n) *)
 destruct H1;destruct H2;subst;compute;omega.
(* Goal: le (tree_height (lub s1 s2)) (S n) *)
 destruct s1 as [s1 pf1].
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) s1 pf1) s2)) (S n) *)
 icase s1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase b.
(* Goal: @eq t (glb (lub t2 t3) t2) t2 *)
 rewrite glb_commute.
(* Goal: le (tree_height (glb s2 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf1))) (S n) *)
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf1) with top.
(* Goal: @eq t (glb (lub t2 t1) top) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
 rewrite glb_top.
(* Goal: @eq t c0 c0 *)
 trivial.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 unfold top;f_equal;apply proof_irr.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
 destruct s2 as [s2 pf2].
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) s2 pf2))) (S n) *)
 icase s2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase b.
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (S n) *)
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
 replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf true) pf2) with top.
(* Goal: @eq t (glb (lub t2 t1) top) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
 rewrite glb_top.
(* Goal: @eq t c0 c0 *)
 trivial.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 unfold top;f_equal;apply proof_irr.
(* Goal: le (tree_height (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
 unfold tree_height,glb,proj1_sig.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
 simpl in pf1,pf2.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
 destruct pf1 as [? [? [? ?]]].
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) (@conj (or (nonFullTree s1_1) (nonFullTree s1_2)) (and (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2))) o (@conj (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2)) o0 (@conj (canonicalTree s1_1) (canonicalTree s1_2) c c0)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
 destruct pf2 as [? [? [? ?]]].
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) (@conj (or (nonFullTree s1_1) (nonFullTree s1_2)) (and (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2))) o (@conj (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2)) o0 (@conj (canonicalTree s1_1) (canonicalTree s1_2) c c0)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) (@conj (or (nonFullTree s2_1) (nonFullTree s2_2)) (and (or (nonEmptyTree s2_1) (nonEmptyTree s2_2)) (and (canonicalTree s2_1) (canonicalTree s2_2))) o1 (@conj (or (nonEmptyTree s2_1) (nonEmptyTree s2_2)) (and (canonicalTree s2_1) (canonicalTree s2_2)) o2 (@conj (canonicalTree s2_1) (canonicalTree s2_2) c1 c2)))))) (S n) *)
 assert (H1 := IHn (exist (fun t => canonicalTree t) s1_1 c)(exist (fun t => canonicalTree t) s2_1 c1)).
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) (@conj (or (nonFullTree s1_1) (nonFullTree s1_2)) (and (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2))) o (@conj (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2)) o0 (@conj (canonicalTree s1_1) (canonicalTree s1_2) c c0)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) (@conj (or (nonFullTree s2_1) (nonFullTree s2_2)) (and (or (nonEmptyTree s2_1) (nonEmptyTree s2_2)) (and (canonicalTree s2_1) (canonicalTree s2_2))) o1 (@conj (or (nonEmptyTree s2_1) (nonEmptyTree s2_2)) (and (canonicalTree s2_1) (canonicalTree s2_2)) o2 (@conj (canonicalTree s2_1) (canonicalTree s2_2) c1 c2)))))) (S n) *)
 assert (H2 := IHn (exist (fun t => canonicalTree t) s1_2 c0)(exist (fun t => canonicalTree t) s2_2 c2)).
(* Goal: le (tree_heightP (mkCanon (intersect_tree (Node s1_1 s1_2) (Node s2_1 s2_2)))) (S n) *)
 unfold tree_height,proj1_sig in *.
(* Goal: le (tree_heightP (mkCanon (intersect_tree (Node s1_1 s1_2) (Node s2_1 s2_2)))) (S n) *)
 simpl in H,H0,H1,H2.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H1.
(* Goal: le (S O) (S n) *)
 assert (Help := le_max_l (tree_heightP s1_1) (tree_heightP s1_2));clear -H Help;omega.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H1.
(* Goal: le (S O) (S n) *)
 assert (Help := le_max_l (tree_heightP s2_1) (tree_heightP s2_2));clear -H0 Help;omega.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H2.
(* Goal: le (S O) (S n) *)
 assert (Help := le_max_r (tree_heightP s1_1) (tree_heightP s1_2));clear -H Help;omega.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
 spec H2.
(* Goal: le (S O) (S n) *)
 assert (Help := le_max_r (tree_heightP s2_1) (tree_heightP s2_2));clear -H0 Help;omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
 icase (mkCanon (intersect_tree s1_1 s2_1));
 icase (mkCanon (intersect_tree s1_2 s2_2)).
(* Goal: le (S O) (S n) *)
 icase b;icase b0;compute;omega.
(* Goal: le (S O) (S n) *)
 simpl in *;omega.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
 simpl in *.
(* Goal: le (Init.Nat.add (PeanoNat.Nat.max (Init.Nat.add (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) (S O)) O) (S O)) (S n) *)
(* Goal: le (tree_heightP (Node (Node s1 s2) (Node s3 s4))) (S n) *)
 rewrite max_0_r.
(* Goal: le (S O) (S n) *)
 omega.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
 simpl in *.
(* Goal: le (Init.Nat.add (PeanoNat.Nat.max (Init.Nat.add (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) (S O)) (Init.Nat.add (PeanoNat.Nat.max (tree_heightP s3) (tree_heightP s4)) (S O))) (S O)) (S n) *)
 assert (H3 := max_lub _ _ _ H1 H2).
(* Goal: le (S O) (S n) *)
 omega.
Qed.

 (*L57*)
 Lemma height_glb1 : forall s1 s2,
  height s1 <= tree_height s2->
  height (glb s1 s2) <= height s2.
 Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold tree_height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: le (tree_height (glb s1 s2)) (tree_height s2) *)
  apply tree_height_glb_limit.
(* Goal: @eq t c0 c0 *)
  trivial.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
(* Goal: le (S O) (S n) *)
  omega.
 Qed.

 (*L54*)
 Lemma tree_height_lub_limit: forall n s1 s2,
  height s1 <= n ->
  height s2 <= n ->
  height (lub s1 s2) <= n.
 Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  induction n;intros.
(* Goal: False *)
  inv H;inv H0.
(* Goal: le (tree_height (lub s1 s2)) (tree_height s1) *)
(* Goal: le (tree_height (lub s1 s2)) (S n) *)
  apply tree_height_0 in H1.
(* Goal: le (tree_height (lub s1 s2)) (tree_height s1) *)
(* Goal: le (tree_height (lub s1 s2)) (S n) *)
  apply tree_height_0 in H2.
(* Goal: le (S O) (S n) *)
  destruct H1;destruct H2;subst;compute;omega.
(* Goal: le (tree_height (lub s1 s2)) (S n) *)
  destruct s1 as [s1 pf1].
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) s1 pf1) s2)) (S n) *)
  icase s1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1) s2)) (S n) *)
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
  replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf false) pf1) with bot.
(* Goal: @eq t (lub bot (glb t3 (comp t2))) (glb t3 (comp t2)) *)
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite lub_commute.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
  rewrite lub_bot.
(* Goal: @eq t c0 c0 *)
  trivial.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  unfold bot;f_equal;apply proof_irr.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) s2)) (S n) *)
  destruct s2 as [s2 pf2].
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) s2 pf2))) (S n) *)
  icase s2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2))) (S n) *)
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
  replace (exist (fun t0 : ShareTree => canonicalTree t0) (Leaf false) pf2) with bot.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
  rewrite lub_bot.
(* Goal: @eq t c0 c0 *)
  trivial.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  unfold bot;f_equal;apply proof_irr.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
  simpl in pf1,pf2.
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
  destruct pf1 as [? [? [? ?]]].
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) (@conj (or (nonFullTree s1_1) (nonFullTree s1_2)) (and (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2))) o (@conj (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2)) o0 (@conj (canonicalTree s1_1) (canonicalTree s1_2) c c0)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (S n) *)
  destruct pf2 as [? [? [? ?]]].
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) (@conj (or (nonFullTree s1_1) (nonFullTree s1_2)) (and (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2))) o (@conj (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2)) o0 (@conj (canonicalTree s1_1) (canonicalTree s1_2) c c0)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) (@conj (or (nonFullTree s2_1) (nonFullTree s2_2)) (and (or (nonEmptyTree s2_1) (nonEmptyTree s2_2)) (and (canonicalTree s2_1) (canonicalTree s2_2))) o1 (@conj (or (nonEmptyTree s2_1) (nonEmptyTree s2_2)) (and (canonicalTree s2_1) (canonicalTree s2_2)) o2 (@conj (canonicalTree s2_1) (canonicalTree s2_2) c1 c2)))))) (S n) *)
  assert (H1 := IHn (exist (fun t => canonicalTree t) s1_1 c)(exist (fun t => canonicalTree t) s2_1 c1)).
(* Goal: le (tree_height (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) (@conj (or (nonFullTree s1_1) (nonFullTree s1_2)) (and (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2))) o (@conj (or (nonEmptyTree s1_1) (nonEmptyTree s1_2)) (and (canonicalTree s1_1) (canonicalTree s1_2)) o0 (@conj (canonicalTree s1_1) (canonicalTree s1_2) c c0)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) (@conj (or (nonFullTree s2_1) (nonFullTree s2_2)) (and (or (nonEmptyTree s2_1) (nonEmptyTree s2_2)) (and (canonicalTree s2_1) (canonicalTree s2_2))) o1 (@conj (or (nonEmptyTree s2_1) (nonEmptyTree s2_2)) (and (canonicalTree s2_1) (canonicalTree s2_2)) o2 (@conj (canonicalTree s2_1) (canonicalTree s2_2) c1 c2)))))) (S n) *)
  assert (H2 := IHn (exist (fun t => canonicalTree t) s1_2 c0)(exist (fun t => canonicalTree t) s2_2 c2)).
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  unfold tree_height,proj1_sig in *;simpl in *.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
  spec H1.
(* Goal: le (S O) (S n) *)
  assert (Help := le_max_l (tree_heightP s1_1) (tree_heightP s1_2));clear -H Help;omega.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
  spec H1.
(* Goal: le (S O) (S n) *)
  assert (Help := le_max_l (tree_heightP s2_1) (tree_heightP s2_2));clear -H0 Help;omega.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
  spec H2.
(* Goal: le (S O) (S n) *)
  assert (Help := le_max_r (tree_heightP s1_1) (tree_heightP s1_2));clear -H Help;omega.
(* Goal: le (tree_heightP match mkCanon (union_tree s1_1 s2_1) with | Leaf b1 => match mkCanon (union_tree s1_2 s2_2) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end | Node s s0 => Node (mkCanon (union_tree s1_1 s2_1)) (mkCanon (union_tree s1_2 s2_2)) end) (S n) *)
  spec H2.
(* Goal: le (S O) (S n) *)
  assert (Help := le_max_r (tree_heightP s2_1) (tree_heightP s2_2));clear -H0 Help;omega.
  icase (mkCanon (union_tree s1_1 s2_1));
  icase (mkCanon (union_tree s1_2 s2_2)).
(* Goal: le (S O) (S n) *)
  icase b;icase b0;compute;omega.
(* Goal: le (S O) (S n) *)
  simpl in *;omega.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (Init.Nat.add (PeanoNat.Nat.max (Init.Nat.add (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) (S O)) O) (S O)) (S n) *)
(* Goal: le (tree_heightP (Node (Node s1 s2) (Node s3 s4))) (S n) *)
  rewrite max_0_r.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  simpl in *.
(* Goal: le (Init.Nat.add (PeanoNat.Nat.max (Init.Nat.add (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) (S O)) (Init.Nat.add (PeanoNat.Nat.max (tree_heightP s3) (tree_heightP s4)) (S O))) (S O)) (S n) *)
  assert (H3 := max_lub _ _ _ H1 H2).
(* Goal: le (S O) (S n) *)
  omega.
 Qed.

 (*L56*)
 Lemma height_lub1 : forall s1 s2,
  height s1 <= height s2->
  height (lub s1 s2) <= height s2.
 Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: le (tree_height (lub s1 s2)) (tree_height s2) *)
  apply tree_height_lub_limit.
(* Goal: @eq t c0 c0 *)
  trivial.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
(* Goal: le (S O) (S n) *)
  omega.
 Qed.
 (*L58*)
 Lemma height_comp: forall s, height (comp s)= height s.
 Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold height;simpl.
(* Goal: forall s : t, @eq nat (tree_height (comp s)) (tree_height s) *)
  intro s.
(* Goal: @eq nat (tree_height (comp s)) (tree_height s) *)
  destruct s as [s pf].
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  induction s;unfold tree_height;simpl.
(* Goal: @eq t c0 c0 *)
  trivial.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
  f_equal.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
  simpl in pf.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
  destruct pf as [? [? [? ?]]].
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
  specialize ( IHs1 H1).
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
  specialize ( IHs2 H2).
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  unfold tree_height in *;simpl in *.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
  congruence.
 Qed.

 (*L46*)
 Lemma countBLeafCT_join_le: forall n s1 s2 s3,
  join s1 s2 s3 ->
  countBLeafCT n s1 + countBLeafCT n s2 <= countBLeafCT n s3.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  induction n;intros.
  destruct s1 as [s1 pf1];
  destruct s2 as [s2 pf2];
  destruct s3 as [s3 pf3].
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) s1 pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) s2 pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) s3 pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  icase s1;icase s2;icase s3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  replace (exist (fun t : ShareTree => canonicalTree t) (Leaf true) pf1) with top in H.
(* Goal: @eq nat (Init.Nat.add (countBLeafCT O top) (countBLeafCT O s2)) (countBLeafCT O s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT O bot) (countBLeafCT O s2)) (countBLeafCT O s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  apply join_top in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
  rewrite H;rewrite H0.
(* Goal: @eq t (rel rightTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
  compute.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  unfold top;f_equal;apply proof_irr.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b1) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  replace (exist (fun t : ShareTree => canonicalTree t) (Leaf false) pf1) with bot in H.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: @eq t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  apply bot_join in H.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
  rewrite H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  unfold bot;f_equal;apply proof_irr.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  elimtype False.
(* Goal: le (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
  destruct H as [H1 H2].
(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  assert (tree_height (exist (fun t : ShareTree => canonicalTree t) (Leaf b) pf1) <= 0) by (compute;omega).
(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  assert (tree_height (exist (fun t : ShareTree => canonicalTree t) (Leaf b0) pf2) <= 0) by (compute;omega).
(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  assert (H3 := tree_height_lub_limit _ _ _ H H0).
(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  rewrite H2 in H3.
(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  clear - H3.
(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  unfold height in H3;simpl in H3;unfold tree_height,proj1_sig in H3.
(* Goal: False *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  simpl in H3.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold countBLeafCT;simpl.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  replace (exist (fun t : ShareTree => canonicalTree t) (Leaf true) pf1) with top in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite glb_commute in H.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: @eq t top (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  rewrite glb_top in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  unfold top;f_equal;apply proof_irr.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  replace (exist (fun t : ShareTree => canonicalTree t) (Leaf true) pf1) with top in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite glb_commute in H.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: @eq t top (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  rewrite glb_top in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  unfold top;f_equal;apply proof_irr.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  apply join_comm in H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  replace (exist (fun t : ShareTree => canonicalTree t) (Leaf true) pf2) with top in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite glb_commute in H.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: @eq t top (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  rewrite glb_top in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  unfold top;f_equal;apply proof_irr.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  replace (exist (fun t : ShareTree => canonicalTree t) (Leaf false) pf2) with bot in H.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b0) pf3)) *)
(* Goal: @eq t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) pf2) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  apply bot_join in H.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
  rewrite H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  unfold countBLeafCT,proj1_sig;simpl.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  unfold bot;f_equal;apply proof_irr.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  apply join_comm in H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  replace (exist (fun t : ShareTree => canonicalTree t) (Leaf true) pf2) with top in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite glb_commute in H.
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s3_1 s3_2) pf3)) *)
(* Goal: @eq t top (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) pf2) *)
(* Goal: le (Init.Nat.add (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s1_1 s1_2) pf1)) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node s2_1 s2_2) pf2))) (countBLeafCT O (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) pf3)) *)
(* Goal: le (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
  rewrite glb_top in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  unfold top;f_equal;apply proof_irr.
(* Goal: @eq t (rel rightTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
  compute.
(* Goal: le (S O) (S n) *)
  omega.
  (*INDUCTIVE CASE*)
  remember (decompose s1) as ds1;
  remember (decompose s2) as ds2;
  remember (decompose s3) as ds3;
  destruct ds1 as [s11 s12];
  destruct ds2 as [s21 s22];
  destruct ds3 as [s31 s32];
  symmetry in Heqds1,Heqds2,Heqds3.
(* Goal: @eq t c0 c0 *)
  rewrite countBLeafCT_decompose with (s1:=s11) (s2:=s12);trivial.
(* Goal: @eq t c0 c0 *)
  rewrite countBLeafCT_decompose with (s1:=s21) (s2:=s22);trivial.
(* Goal: @eq t c0 c0 *)
  rewrite countBLeafCT_decompose with (s1:=s31) (s2:=s32);trivial.
(* Goal: @eq t c0 c0 *)
  rewrite decompose_join with (t11:=s11) (t12:=s12) (t21:=s21) (t22:=s22) (t31:=s31) (t32:=s32)in H;trivial.
(* Goal: le (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
  destruct H as [H1 H2].
(* Goal: le (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
  assert (H4 := IHn _ _ _ H1).
(* Goal: le (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
  assert (H5 := IHn _ _ _ H2).
(* Goal: le (S O) (S n) *)
  omega.
 Qed.

(*L47*)
Lemma countBLeafCT_join_eq: forall n s1 s2 s3,
 join s1 s2 s3 ->
 height s1 <= n ->
 height s2 <= n ->
 countBLeafCT n s1 + countBLeafCT n s2 = countBLeafCT n s3.
Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 unfold height;simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 induction n;intros.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
 inversion H0.
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (tree_height s1) s1) (countBLeafCT (tree_height s1) s2)) (countBLeafCT (tree_height s1) s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
 inversion H1.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
 rewrite H3.
(* Goal: @eq nat (Init.Nat.add (countBLeafCT O s1) (countBLeafCT O s2)) (countBLeafCT O s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
 apply tree_height_0 in H3.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 destruct H3 as [H3|H3];subst.
(* Goal: @eq nat (Init.Nat.add (countBLeafCT O top) (countBLeafCT O s2)) (countBLeafCT O s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT O bot) (countBLeafCT O s2)) (countBLeafCT O s3) *)
(* Goal: @eq nat (Init.Nat.add (countBLeafCT (S n) s1) (countBLeafCT (S n) s2)) (countBLeafCT (S n) s3) *)
 apply join_top in H.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 destruct H;subst.
(* Goal: le (S O) (S n) *)
 compute;omega.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 apply bot_join in H;subst.
(* Goal: @eq t (rel rightTree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 compute.
(* Goal: le (S O) (S n) *)
 omega.
 (*INDUCTIVE CASE*)
 remember (decompose s1) as ds1;
 remember (decompose s2) as ds2;
 remember (decompose s3) as ds3;
 destruct ds1 as [s11 s12];
 destruct ds2 as [s21 s22];
 destruct ds3 as [s31 s32];
 symmetry in Heqds1,Heqds2,Heqds3.
(* Goal: @eq t c0 c0 *)
 apply decompose_height_le with (s1:= s11) (s2:=s12)in H0;trivial.
(* Goal: @eq t c0 c0 *)
 apply decompose_height_le with (s1:= s21) (s2:=s22)in H1;trivial.
 destruct H0 as [H2 H3];
 destruct H1 as [H4 H5].
(* Goal: @eq t c0 c0 *)
 rewrite countBLeafCT_decompose with (s1:=s11) (s2:=s12);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite countBLeafCT_decompose with (s1:=s21) (s2:=s22);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite countBLeafCT_decompose with (s1:=s31) (s2:=s32);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite decompose_join with (t11:=s11) (t12:=s12) (t21:=s21) (t22:=s22) (t31:=s31) (t32:=s32)in H;trivial.
(* Goal: @eq nat (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
 destruct H as [H6 H7].
(* Goal: @eq nat (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
 assert (H8 := IHn _ _ _ H6 H2 H4).
(* Goal: @eq nat (Init.Nat.add (Init.Nat.add (countBLeafCT n s11) (countBLeafCT n s12)) (Init.Nat.add (countBLeafCT n s21) (countBLeafCT n s22))) (Init.Nat.add (countBLeafCT n s31) (countBLeafCT n s32)) *)
 assert (H9 := IHn _ _ _ H7 H3 H5).
(* Goal: le (S O) (S n) *)
 omega.
Qed.

Definition share_metric (n : nat) (s : canonTree) : nat :=
 match n with
 | 0 => 0
 | S n => match le_dec (height s) n with
          | left _ => countBLeafCT n s + 1
          | right _ => 0
         end
 end.
 (*L48*)
 Lemma share_metric_nerr : forall s n,
  height s < n ->
  0 < share_metric n s.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
  icase n.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: forall _ : lt O (if le_dec (tree_height s) n then Init.Nat.add (countBLeafCT n s) (S O) else O), lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  icase (le_dec (tree_height s) n).
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  unfold height in H;simpl in H.
(* Goal: le (S O) (S n) *)
  omega.
 Qed.

 (*L49*)
 Lemma share_metric_err  : forall s n,
  n <= height s ->
  share_metric n s = 0.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
  icase n.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: forall _ : lt O (if le_dec (tree_height s) n then Init.Nat.add (countBLeafCT n s) (S O) else O), lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  icase (le_dec (tree_height s) n).
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  unfold height in H;simpl in H.
(* Goal: le (S O) (S n) *)
  elimtype False;omega.
 Qed.
 (*L50*)
 Lemma share_metric_height_monotonic : forall s n1 n2,
  n1<=n2 ->
  share_metric n1 s <= share_metric n2 s.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: le (share_metric n1 s) (share_metric n2 s) *)
  icase n1.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: le (share_metric (S n1) s) (share_metric n2 s) *)
  icase n2.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: le (S O) (S n) *)
  assert (H1 : n1 <= n2) by omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
  icase (le_dec (tree_height s) n1);
  icase (le_dec (tree_height s) n2).
(* Goal: le (Init.Nat.add (countBLeafCT n1 s) (S O)) (Init.Nat.add (countBLeafCT n2 s) (S O)) *)
(* Goal: le (Init.Nat.add (countBLeafCT n1 s) (S O)) O *)
(* Goal: le O (Init.Nat.add (countBLeafCT n2 s) (S O)) *)
  assert (H2 := countBLeafCT_mono_le _ _ s H1).
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: le (S O) (S n) *)
  omega.
 Qed.
 (*L51*)
 Lemma share_metric_lub : forall s s' n,
  ~(s'<=s)%ba->
  0 < share_metric n s ->
  0 < share_metric n (lub s s') ->
  (share_metric n s<share_metric n (lub s s')).
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
  icase n.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
  icase (le_dec (tree_height s) n);
  icase (le_dec (tree_height (lub s s')) n).
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) (Init.Nat.add (countBLeafCT n (lub s s')) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
  assert (H2 := lub_upper1 s s').
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) (Init.Nat.add (countBLeafCT n (lub s s')) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
  assert (H3 : s <> lub s s').
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
   intro.
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
   apply H.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
   rewrite H3.
(* Goal: Ord s' (lub s s') *)
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) (Init.Nat.add (countBLeafCT n (lub s s')) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
   apply lub_upper2.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  assert (H4 := countBLeafCT_lt _ _ _ H2 H3 l0).
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
  simpl in H1.
(* Goal: lt (Init.Nat.add (countBLeafCT n s) (S O)) O *)
  revert H1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  icase (le_dec (tree_height (lub s s')) n);intro.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
  inv H1.
 Qed.
 (*L52*)
 Lemma share_metric_glb : forall s s' n,
  ~(s<=s')%ba->
  0 < share_metric n s ->
  0 < share_metric n (glb s s') ->
 (share_metric n (glb s s') < share_metric n s)%nat.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
  icase n.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
  icase (le_dec (tree_height (glb s s')) n);
(* Goal: forall _ : lt O (if le_dec (tree_height s) n then Init.Nat.add (countBLeafCT n s) (S O) else O), lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  icase (le_dec (tree_height s) n).
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  assert (H2 := glb_lower1 s s').
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  assert (H3 : glb s s' <> s).
(* Goal: not (@eq t (glb s s') s) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
   intro H3.
(* Goal: @eq t bot s *)
(* Goal: @identity t Join_ba s *)
   apply H.
(* Goal: Ord s s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
   rewrite<- H3.
(* Goal: Ord (glb s s') s' *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
   apply glb_lower2.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) (Init.Nat.add (countBLeafCT n s) (S O)) *)
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  assert (H4 := countBLeafCT_lt _ _ _ H2 H3 l0).
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  simpl in H0.
(* Goal: lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  revert H0.
(* Goal: forall _ : lt O (if le_dec (tree_height s) n then Init.Nat.add (countBLeafCT n s) (S O) else O), lt (Init.Nat.add (countBLeafCT n (glb s s')) (S O)) O *)
  icase (le_dec (tree_height s) n).
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  intro.
(* Goal: False *)
  inv H0.
 Qed.

 (*L53*)
 Lemma share_metric_dif_monotonic: forall s1 s2 n n0,
 (s1<=s2)%ba -> n<=n0 ->
  height s1 < n ->
  height s2 < n ->
 (share_metric n s2 - share_metric n s1 <=
  share_metric n0 s2 - share_metric n0 s1).
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
  icase n.
(* Goal: le (Init.Nat.sub (share_metric O s2) (share_metric O s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
  inv H1.
(* Goal: le (Init.Nat.sub (share_metric (S n) s2) (share_metric (S n) s1)) (Init.Nat.sub (share_metric n0 s2) (share_metric n0 s1)) *)
  icase n0.
(* Goal: False *)
  inv H0.
(* Goal: le (S O) (S n) *)
  assert (H3 : n <= n0) by omega.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
  simpl.
  icase (le_dec (tree_height s1) n);
  icase (le_dec (tree_height s2) n);
  icase (le_dec (tree_height s1) n0);
  icase (le_dec (tree_height s2) n0);
(* Goal: le (S O) (S n) *)
  simpl;try omega.
(* Goal: le (Init.Nat.sub (Init.Nat.add (countBLeafCT n s2) (S O)) (Init.Nat.add (countBLeafCT n s1) (S O))) (Init.Nat.sub (Init.Nat.add (countBLeafCT n0 s2) (S O)) (Init.Nat.add (countBLeafCT n0 s1) (S O))) *)
(* Goal: le (Init.Nat.sub (Init.Nat.add (countBLeafCT n s2) (S O)) O) (Init.Nat.sub (Init.Nat.add (countBLeafCT n0 s2) (S O)) (Init.Nat.add (countBLeafCT n0 s1) (S O))) *)
(* Goal: le (Init.Nat.sub (Init.Nat.add (countBLeafCT n s2) (S O)) O) (Init.Nat.sub (Init.Nat.add (countBLeafCT n0 s2) (S O)) O) *)
  assert (H4 := countBLeafCT_mono_diff _ _ _ _ H3 H).
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  unfold height in *;simpl in *.
(* Goal: le (S O) (S n) *)
  omega.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
  unfold height in *;simpl in *.
(* Goal: le (S O) (S n) *)
  omega.
 Qed.

 Lemma shareTreeOrd_dec: forall t1 t2 : ShareTree,
  {shareTreeOrd t1 t2} + {~shareTreeOrd t1 t2}.
(* Goal: @eq t c c *)
 Proof with try tauto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  induction t1;intros.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b. induction t2.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  icase b. right. repeat intro.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H. inv H2.
  destruct IHt2_1. destruct IHt2_2.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  left. apply LeafNode_Ord;apply Node_Ord...
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  right. intro. inv H. inv H2...
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  right. intro. inv H. inv H2...
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase t2. icase b.
  specialize ( IHt1_1 (Leaf false)).
  specialize ( IHt1_2 (Leaf false)).
  destruct IHt1_1. destruct IHt1_2.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  left. apply NodeLeaf_Ord;apply Node_Ord...
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  right. intro. inv H. inv H1...
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  right. intro. inv H. inv H1...
  specialize ( IHt1_1 t2_1). specialize ( IHt1_2 t2_2).
  destruct IHt1_1. destruct IHt1_2.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  left. apply Node_Ord...
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  right. intro. inv H...
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  right. intro. inv H...
 Defined.

(*L0*)
 Lemma leq_dec : forall (x y : t), {(x <= y)%ba} + {~ (x <= y)%ba}.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros. unfold Ord.
(* Goal: sumbool (shareTreeOrd (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y)) (not (shareTreeOrd (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) x) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) y))) *)
  apply shareTreeOrd_dec.
 Defined.

(*L1*)
 Lemma height_top : height top = 0.
 Proof.
(* Goal: @eq t c c *)
  tauto.
 Qed.
(*L2*)
 Lemma height_bot: height bot = 0.
 Proof.
(* Goal: @eq t c c *)
  tauto.
 Qed.
(*L3*)
 Lemma height_zero_eq: forall t,
  height t = 0 -> {t = top} + {t = bot}.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: or (or (@eq t t0 top) (@eq t t0 bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex ((fun t : ShareTree => canonicalTree t) (Node t1 t2)) (fun c : (fun t : ShareTree => canonicalTree t) (Node t1 t2) => @eq t t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c))))) *)
  destruct t0.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  icase x.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
  icase b.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  left.
(* Goal: @eq t (let (x, _) := top in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree top in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
  unfold top.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
  f_equal.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  apply proof_irr.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  right.
(* Goal: @eq t (let (x, _) := bot in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree bot in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
  unfold bot.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
  f_equal.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
  apply proof_irr.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  simpl in H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  unfold tree_height in H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  simpl in H.
(* Goal: sumbool (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot) *)
  elimtype False.
(* Goal: le (S O) (S n) *)
  omega.
 Defined.
(*D10*)
 Definition add (x y : canonTree) : option canonTree :=
  match eq_dec (glb x y) bot with
  | left _ => Some (lub x y)
  | right _ => None
  end.
(*L8*)
 Lemma add_join : forall t1 t2 t3,
  add t1 t2 = Some t3 <-> join t1 t2 t3.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: iff (@eq (option canonTree) (add t1 t2) (@Some canonTree t3)) (@join canonTree Join_ba t1 t2 t3) *)
  unfold add.
(* Goal: iff (@eq (option canonTree) (if @eq_dec t EqDec_share (glb t1 t2) bot then @Some t (lub t1 t2) else @None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t1 t2 t3) *)
  icase (eq_dec (glb t1 t2) bot).
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  split;intros.
(* Goal: @eq t c c *)
  split;auto.
(* Goal: @eq t c c *)
  inv H;auto.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
  f_equal.
(* Goal: @eq t c c *)
  destruct H;auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  split;intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: @eq t c c *)
  destruct H;tauto.
 Qed.
(*D11*)
 Definition sub (x y : canonTree) : option canonTree :=
  match eq_dec (glb x y) y with
  | left _ => Some (glb x (comp y))
  | right _ => None
  end.
(*L9*)
 Lemma sub_join : forall t1 t2 t3,
  sub t1 t2 = Some t3 <-> join t2 t3 t1.
 Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: iff (@eq (option canonTree) (sub t1 t2) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  unfold sub.
(* Goal: iff (@eq (option canonTree) (if @eq_dec t EqDec_share (glb t1 t2) t2 then @Some t (glb t1 (comp t2)) else @None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  icase (eq_dec (glb t1 t2) t2).
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  split;intros.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
  inversion H.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
  split.
(* Goal: @eq t (glb (lub t2 t3) t2) t2 *)
  rewrite glb_commute.
(* Goal: @eq t (glb (glb t1 (comp t2)) t2) bot *)
(* Goal: @eq t (lub t2 (glb t1 (comp t2))) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite glb_assoc.
(* Goal: @eq t (glb t1 (glb (comp t2) t2)) bot *)
(* Goal: @eq t (lub t2 (glb t1 (comp t2))) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  replace (glb (comp t2) t2) with (glb t2 (comp t2)) by apply glb_commute.
(* Goal: @eq t (lub (glb t2 (comp t2)) (glb (comp t2) t3)) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite comp2.
(* Goal: @eq t (glb s bot) bot *)
(* Goal: @eq t (lub s bot) s *)
(* Goal: @identity t Join_ba s *)
  apply glb_bot.
(* Goal: @eq t (lub t2 (glb t1 (comp t2))) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite distrib2.
(* Goal: @eq t (glb (lub t2 t1) (lub t2 (comp t2))) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  replace (lub (comp t2) t2) with (lub t2 (comp t2)) by apply lub_commute.
(* Goal: @eq t (glb (lub t2 t1) (lub t2 (comp t2))) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite comp1.
(* Goal: @eq t (glb (lub t2 t1) top) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite glb_top.
(* Goal: @eq t (lub t2 t1) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite<- e.
(* Goal: @eq t (lub bot (glb t3 (comp t2))) (glb t3 (comp t2)) *)
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite lub_commute.
(* Goal: @eq t (lub t1 (glb t1 t2)) t1 *)
(* Goal: @eq (option canonTree) (@Some t (glb t1 (comp t2))) (@Some canonTree t3) *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  apply lub_absorb.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
  f_equal.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq t (glb t1 t2) t2 *)
  rewrite <- H0.
(* Goal: @eq t (glb (lub t2 t3) t2) t2 *)
  rewrite glb_commute.
(* Goal: @eq t (glb t2 (lub t2 t3)) t2 *)
  rewrite distrib1.
(* Goal: @eq t (glb (lub t2 t3) t2) t2 *)
  rewrite glb_commute.
(* Goal: @eq t (lub (glb t2 (comp t2)) (glb (comp t2) t3)) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite comp2.
(* Goal: @eq t (lub bot (glb t3 (comp t2))) (glb t3 (comp t2)) *)
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite lub_commute.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
  rewrite lub_bot.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite glb_commute in H.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  assert (H1 : lub (glb t3 t2) (glb t3 (comp t2)) = glb t3 (comp t2)).
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
  rewrite H.
(* Goal: @eq t (lub bot (glb t3 (comp t2))) (glb t3 (comp t2)) *)
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite lub_commute.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
  rewrite lub_bot.
(* Goal: @eq t c0 c0 *)
  trivial.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite<- distrib1 in H1.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite comp1 in H1.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite glb_top in H1.
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
  rewrite H1 at 2.
(* Goal: @eq t (glb (lub t2 t3) t2) t2 *)
  rewrite glb_commute.
(* Goal: @eq t c0 c0 *)
  trivial.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  split;intros.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
(* Goal: @eq (option canonTree) (@None canonTree) (@Some canonTree t3) *)
  elimtype False;apply n.
(* Goal: @eq t (glb t1 t2) t2 *)
  rewrite<- H0.
(* Goal: @eq t (glb (lub t2 t3) t2) t2 *)
  rewrite glb_commute.
(* Goal: @eq t (glb t2 (lub t2 t3)) t2 *)
  rewrite distrib1.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
  rewrite H.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
  rewrite lub_bot.
(* Goal: @eq t (glb t2 t2) t2 *)
  apply glb_idem.
 Qed.
 (*L10*)
 Lemma decompose_share_height_no_increase: forall sh sh' sh'' ,
  decompose sh = (sh',sh'')->
  height sh' <= height sh /\ height sh'' <= height sh.
Proof.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: and (le (tree_height sh') (tree_height sh)) (le (tree_height sh'') (tree_height sh)) *)
 remember (tree_height sh) as n.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
 icase n.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
 symmetry in Heqn.
(* Goal: and (le (tree_height sh') O) (le (tree_height sh'') O) *)
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
 apply height_zero_eq in Heqn.
 icase Heqn;subst;
(* Goal: le (S O) (S n) *)
 inv H;compute;omega.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
 symmetry in Heqn.
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
 assert (H1 := decompose_height _ _ _ _ Heqn H).
(* Goal: and (le (tree_height sh') (S n)) (le (tree_height sh'') (S n)) *)
 simpl in *.
(* Goal: le (S O) (S n) *)
 omega.
Qed.


Lemma tree_top_rewrite : forall c,
 exist _ (Leaf true) c = top.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: @eq t (let (x, _) := top in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree top in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
 unfold top. f_equal. apply proof_irr.
Qed.

Lemma tree_bot_rewrite : forall c,
 exist _ (Leaf false) c = bot.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: @eq t (let (x, _) := bot in match x with | Leaf b => a | Node s s0 => let (ltr1, rtr1) := @decompose t decompose_tree bot in let (ltr2, rtr2) := @decompose t decompose_tree a in let (x0, _) := ltr1 in match x0 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s1 s2 => unrel ltr1 ltr2 end end) a *)
 unfold bot.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 f_equal. apply proof_irr.
Qed.

Lemma tree_basic_rewrite : forall b c,
exist _ (Leaf b) c = top \/ exist _ (Leaf b) c = bot.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros. icase b.
(* Goal: or (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) c) top) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf true) c) bot) *)
(* Goal: or (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) top) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) bot) *)
 left;apply tree_top_rewrite.
(* Goal: or (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) top) (@eq (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) bot) *)
 right;apply tree_bot_rewrite.
Qed.

Lemma tree_case_rewrite : forall t,
(t = top \/ t = bot) \/ exists t1 t2 c, t = exist _ (Node t1 t2) c.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: or (or (@eq t t0 top) (@eq t t0 bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex ((fun t : ShareTree => canonicalTree t) (Node t1 t2)) (fun c : (fun t : ShareTree => canonicalTree t) (Node t1 t2) => @eq t t0 (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c))))) *)
 destruct t0.
(* Goal: or (or (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) top) (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (@ex ShareTree (fun t1 : ShareTree => @ex ShareTree (fun t2 : ShareTree => @ex (canonicalTree (Node t1 t2)) (fun c0 : canonicalTree (Node t1 t2) => @eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c0))))) *)
 destruct x. left;apply tree_basic_rewrite.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 right. exists x1. exists x2. exists c.
(* Goal: @eq t c0 c0 *)
 trivial.
Qed.

Lemma decompose_basic: forall b c c1 c2,
 decompose (exist _ (Leaf b) c) = (exist _ (Leaf b) c1,exist _ (Leaf b) c2).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: @eq (prod (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@decompose (@sig ShareTree (fun t : ShareTree => canonicalTree t)) decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c)) (@pair (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c2)) *)
 unfold decompose,decompose_tree.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl. f_equal. f_equal. apply proof_irr.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 f_equal. apply proof_irr.
Qed.

Lemma decompose_top: decompose top = (top,top).
Proof.
(* Goal: @eq (prod t t) (@decompose t decompose_tree bot) (@pair t t bot bot) *)
 apply decompose_basic.
Qed.

Lemma decompose_bot: decompose bot = (bot,bot).
Proof.
(* Goal: @eq (prod t t) (@decompose t decompose_tree bot) (@pair t t bot bot) *)
 apply decompose_basic.
Qed.

Lemma decompose_Node: forall t1 t2 c c1 c2,
 decompose (exist _ (Node t1 t2) c) = (exist _ t1 c1, exist _ t2 c2).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: @eq (prod (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (@decompose (@sig ShareTree (fun t : ShareTree => canonicalTree t)) decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c)) (@pair (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 c2)) *)
 unfold decompose. unfold decompose_tree.
(* Goal: @eq (prod (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t))) (tree_decompose (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node t1 t2) c)) (@pair (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 c2)) *)
 unfold tree_decompose.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct c as [? [? [? ?]]].
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 f_equal. f_equal. apply proof_irr.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 f_equal. apply proof_irr.
Qed.

Lemma identity_bot: forall s, identity s <-> s = bot.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 repeat intro. split;intros.
(* Goal: @eq t s bot *)
(* Goal: @identity t Join_ba s *)
 specialize ( H bot s).
(* Goal: @eq t s bot *)
(* Goal: @identity t Join_ba s *)
 symmetry. apply H.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
 split. apply glb_bot.
(* Goal: @eq t (lub s bot) s *)
(* Goal: @identity t Join_ba s *)
 apply lub_bot.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
 subst. repeat intro. destruct H.
(* Goal: @eq t a b *)
 rewrite lub_commute in H0.
(* Goal: @eq t c0 c0 *)
 rewrite lub_bot in H0. trivial.
Qed.

Lemma tree_proof_replace: forall (t : ShareTree) c1 c2,
 exist (fun t => canonicalTree t) t c1 = exist _ t c2.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros. f_equal. apply proof_irr.
Qed.

Lemma top_unrel: forall a,
 unrel top a = a.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t c0 c0 *)
 unfold top. trivial.
Qed.

Lemma bot_unrel: forall a,
 unrel bot a = a.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t c0 c0 *)
 unfold bot. trivial.
Qed.

  Lemma mkCanon_lub : forall t11 t12 t21 t22 t31 t32,
                     lub (exist _ (mkCanon (Node t11 t12)) (mkCanon_correct _))
                         (exist _ (mkCanon (Node t21 t22)) (mkCanon_correct _)) =
                         (exist _ (mkCanon (Node t31 t32)) (mkCanon_correct _))<->
                     lub (exist _ (mkCanon t11) (mkCanon_correct _))
                         (exist _ (mkCanon t21) (mkCanon_correct _)) =
                         (exist _ (mkCanon t31) (mkCanon_correct _))/\
                     lub (exist _ (mkCanon t12) (mkCanon_correct _))
                         (exist _ (mkCanon t22) (mkCanon_correct _)) =
                         (exist _ (mkCanon t32) (mkCanon_correct _)).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: iff (@eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) (and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32)))) *)
    unfold BAF.lub.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    split;intros.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    simpl. inversion H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_union((Node t11 t12)) ((Node t21 t22)));intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H0. rewrite H1 in H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_eq_split _ _ _ _ H3);intro.
(* Goal: and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32))) *)
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    destruct H2 as [? ?].
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    split;apply exist_ext;rewrite mkCanon_union;congruence.

(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    destruct H. inversion H. inversion H0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_union (Node t11 t12) (Node t21 t22));intro.
(* Goal: @eq ShareTree (mkCanon (union_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    rewrite mkCanon_union in H2.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    rewrite mkCanon_union in H3. simpl.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
    simpl in H1;rewrite H1.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2. rewrite H3.
(* Goal: @eq t c0 c0 *)
    trivial.
  Qed.

  Lemma mkCanon_glb : forall t11 t12 t21 t22 t31 t32,
                     glb (exist _ (mkCanon (Node t11 t12)) (mkCanon_correct _))
                         (exist _ (mkCanon (Node t21 t22)) (mkCanon_correct _)) =
                         (exist _ (mkCanon (Node t31 t32)) (mkCanon_correct _))<->
                     glb (exist _ (mkCanon t11) (mkCanon_correct _))
                         (exist _ (mkCanon t21) (mkCanon_correct _)) =
                         (exist _ (mkCanon t31) (mkCanon_correct _))/\
                     glb (exist _ (mkCanon t12) (mkCanon_correct _))
                         (exist _ (mkCanon t22) (mkCanon_correct _)) =
                         (exist _ (mkCanon t32) (mkCanon_correct _)).
  Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    intros.
(* Goal: iff (@eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32)))) (and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32)))) *)
    unfold BAF.lub.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
    split;intros.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    simpl. inversion H.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_intersect((Node t11 t12)) ((Node t21 t22)));intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    inversion H0. rewrite H1 in H3.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_eq_split _ _ _ _ H3);intro.
(* Goal: and (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t11) (mkCanon_correct t11)) (@exist ShareTree canonicalTree (mkCanon t21) (mkCanon_correct t21))) (@exist ShareTree canonicalTree (mkCanon t31) (mkCanon_correct t31))) (@eq t (glb (@exist ShareTree canonicalTree (mkCanon t12) (mkCanon_correct t12)) (@exist ShareTree canonicalTree (mkCanon t22) (mkCanon_correct t22))) (@exist ShareTree canonicalTree (mkCanon t32) (mkCanon_correct t32))) *)
(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    destruct H2 as [? ?].
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
    split;apply exist_ext; simpl; rewrite mkCanon_intersect;congruence.

(* Goal: @eq t (glb (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12))) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))) (@exist ShareTree canonicalTree (mkCanon (Node t31 t32)) (mkCanon_correct (Node t31 t32))) *)
    apply exist_ext.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    destruct H. inversion H. inversion H0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
    generalize (mkCanon_intersect (Node t11 t12) (Node t21 t22));intro.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
    rewrite mkCanon_intersect in H2.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
    rewrite mkCanon_intersect in H3. simpl.
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
    simpl in H1;rewrite H1.
(* Goal: @eq ShareTree match mkCanon t31 with | Leaf b1 => match mkCanon (intersect_tree t12 t22) with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end | Node s s0 => Node (mkCanon t31) (mkCanon (intersect_tree t12 t22)) end match mkCanon t31 with | Leaf b1 => match mkCanon t32 with | Leaf b2 => if bool_dec b1 b2 then Leaf b1 else Node (mkCanon t31) (mkCanon t32) | Node s s0 => Node (mkCanon t31) (mkCanon t32) end | Node s s0 => Node (mkCanon t31) (mkCanon t32) end *)
    rewrite H2. rewrite H3.
(* Goal: @eq t c0 c0 *)
    trivial.
  Qed.


Lemma decompose_lub: forall t1 t11 t12 t2 t21 t22 t3 t31 t32,
 decompose t1 = (t11,t12) ->
 decompose t2 = (t21,t22) ->
 decompose t3 = (t31,t32) ->
 (lub t1 t2 = t3 <-> (lub t11 t21 = t31 /\ lub t12 t22 = t32)).
Proof.
(* Goal: forall (t1 t11 t12 t2 t21 t22 t3 t31 t32 : t) (_ : @eq (prod t t) (@decompose t decompose_tree t1) (@pair t t t11 t12)) (_ : @eq (prod t t) (@decompose t decompose_tree t2) (@pair t t t21 t22)) (_ : @eq (prod t t) (@decompose t decompose_tree t3) (@pair t t t31 t32)), iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   intros ? ? ? ? ? ? ? ? ? H1 H2 H3.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   generalize (decompose_rewrite t1 t11 t12);intro H11.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   generalize (decompose_rewrite t2 t21 t22);intro H21.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   generalize (decompose_rewrite t3 t31 t32);intro H31.
   destruct H11 as [H11 _];
   destruct H21 as [H21 _];
   destruct H31 as [H31 _].
   specialize ( H11 H1);
   specialize ( H21 H2);
   specialize ( H31 H3).
   generalize (canonTree_rewrite2 t11);intro H12;
   generalize (canonTree_rewrite2 t12);intro H13;
   generalize (canonTree_rewrite2 t21);intro H22;
   generalize (canonTree_rewrite2 t22);intro H23;
   generalize (canonTree_rewrite2 t31);intro H32;
   generalize (canonTree_rewrite2 t32);intro H33.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   rewrite H12,H13,H22,H23,H32,H33,H11,H21,H31.
(* Goal: iff (@eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22))))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))))) (and (@eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31)))) (@eq t (lub (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))))) *)
   apply mkCanon_lub.
Qed.

Lemma decompose_glb: forall t1 t11 t12 t2 t21 t22 t3 t31 t32,
 decompose t1 = (t11,t12) ->
 decompose t2 = (t21,t22) ->
 decompose t3 = (t31,t32) ->
 (glb t1 t2 = t3 <-> (glb t11 t21 = t31 /\ glb t12 t22 = t32)).
Proof.
(* Goal: forall (t1 t11 t12 t2 t21 t22 t3 t31 t32 : t) (_ : @eq (prod t t) (@decompose t decompose_tree t1) (@pair t t t11 t12)) (_ : @eq (prod t t) (@decompose t decompose_tree t2) (@pair t t t21 t22)) (_ : @eq (prod t t) (@decompose t decompose_tree t3) (@pair t t t31 t32)), iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   intros ? ? ? ? ? ? ? ? ? H1 H2 H3.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   generalize (decompose_rewrite t1 t11 t12);intro H11.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   generalize (decompose_rewrite t2 t21 t22);intro H21.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   generalize (decompose_rewrite t3 t31 t32);intro H31.
   destruct H11 as [H11 _];
   destruct H21 as [H21 _];
   destruct H31 as [H31 _].
   specialize ( H11 H1);
   specialize ( H21 H2);
   specialize ( H31 H3).
   generalize (canonTree_rewrite2 t11);intro H12;
   generalize (canonTree_rewrite2 t12);intro H13;
   generalize (canonTree_rewrite2 t21);intro H22;
   generalize (canonTree_rewrite2 t22);intro H23;
   generalize (canonTree_rewrite2 t31);intro H32;
   generalize (canonTree_rewrite2 t32);intro H33.
(* Goal: iff (@eq t (glb t1 t2) t3) (and (@eq t (glb t11 t21) t31) (@eq t (glb t12 t22) t32)) *)
   rewrite H12,H13,H22,H23,H32,H33,H11,H21,H31.
(* Goal: iff (@eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22))))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))) (mkCanon_correct (Node (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))))) (and (@eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t11))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t21)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t31)))) (@eq t (glb (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t12))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t22)))) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32)) (mkCanon_correct (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) t32))))) *)
   apply mkCanon_glb.
Qed.

Lemma unrel_right_obmit: forall a a1 a2 t1 t2 c c1,
 t1 <> Leaf false ->
 decompose a = (a1,a2) ->
 unrel (exist _ (Node t1 t2) c) a = unrel (exist _ t1 c1) a1.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl. destruct c as [? [? [? ?]]].
(* Goal: @eq t c0 c0 *)
 replace (tree_decompose a) with (decompose a) by trivial.
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a in match t1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t2 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t2) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t2) (fun (_ : canonicalTree t1) (H3 : canonicalTree t2) => H3) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 (@and_ind (or (nonEmptyTree t1) (nonEmptyTree t2)) (and (canonicalTree t1) (canonicalTree t2)) (canonicalTree t1) (fun (_ : or (nonEmptyTree t1) (nonEmptyTree t2)) (H2 : and (canonicalTree t1) (canonicalTree t2)) => @and_ind (canonicalTree t1) (canonicalTree t2) (canonicalTree t1) (fun (H0 : canonicalTree t1) (_ : canonicalTree t2) => H0) H2) (@conj (nonEmptyTree (Node t1 t2)) (and (canonicalTree t1) (canonicalTree t2)) n0 (@conj (canonicalTree t1) (canonicalTree t2) c c0)))) ltr2 end) (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) t1 c1) a1) *)
 rewrite H0.
(* Goal: @eq t c c *)
 icase t1. icase b. try tauto.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 repeat f_equal. apply proof_irr.
Qed.

Lemma unrel_left_obmit: forall a a1 a2 t c c',
 decompose a = (a1,a2) ->
 unrel (exist _ (Node (Leaf false) t) c) a =
 unrel (exist _ t c') a2.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 simpl. destruct c as [? [? [? ?]]].
(* Goal: @eq t c0 c0 *)
 replace (tree_decompose a) with (decompose a) by trivial.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
 rewrite H.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 repeat f_equal.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 apply proof_irr.
Qed.

Lemma unrel_lub: forall a b1 b2,
 unrel a (lub b1 b2) = lub (unrel a b1) (unrel a b2).
Proof.
(* Goal: forall (a a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
 intro a.
(* Goal: forall (a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
 destruct a.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 induction x;intros;rewrite unrel_equation.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 generalize (tree_basic_rewrite b c);intro.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
 destruct H;rewrite H.
(* Goal: @eq t c0 c0 *)
 repeat rewrite top_unrel. trivial.
(* Goal: @eq t c0 c0 *)
 repeat rewrite bot_unrel. trivial.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct c as [? [? [? ?]]].
(* Goal: @eq t (let (ltr1, rtr1) := @decompose t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) in let (ltr2, rtr2) := @decompose t decompose_tree a' in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) bot *)
 rewrite decompose_Node with (c1:=c) (c2:=c0).
 remember (lub b1 b2) as b3.
 symmetry in Heqb3.
 remember (decompose b1); remember (decompose b2);remember (decompose b3).
 destruct p; destruct p0; destruct p1.
 symmetry in Heqp,Heqp0,Heqp1.
 eapply decompose_lub in Heqb3.
 2: apply Heqp.
 2: apply Heqp0.
 2: apply Heqp1.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 destruct Heqb3;subst.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase x1. icase b.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_right_obmit with (c1:=c)(a1:=t0)(a2:=t1);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_right_obmit with (c1:=c) (a1:=t2) (a2:=t3);trivial.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
 intro. inversion H. intro. inversion H.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_left_obmit with (c':=c0)(a1:=t0)(a2:=t1);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_left_obmit with (c':=c0)(a1:=t2)(a2:=t3);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_right_obmit with (c1:=c) (a1:=t0) (a2:=t1);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_right_obmit with (c1:=c) (a1:=t2) (a2:=t3);trivial.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
 intro. inversion H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
 intro. inversion H.
Qed.

Lemma unrel_glb: forall a b1 b2,
 unrel a (glb b1 b2) = glb (unrel a b1) (unrel a b2).
Proof.
(* Goal: forall (a a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
 intro a.
(* Goal: forall (a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
 destruct a.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 induction x;intros;rewrite unrel_equation.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 generalize (tree_basic_rewrite b c);intro.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
 destruct H;rewrite H.
(* Goal: @eq t c0 c0 *)
 repeat rewrite top_unrel. trivial.
(* Goal: @eq t c0 c0 *)
 repeat rewrite bot_unrel. trivial.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct c as [? [? [? ?]]].
(* Goal: @eq t (let (ltr1, rtr1) := @decompose t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) in let (ltr2, rtr2) := @decompose t decompose_tree a' in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) bot *)
 rewrite decompose_Node with (c1:=c) (c2:=c0).
 remember (glb b1 b2) as b3.
 symmetry in Heqb3.
 remember (decompose b1); remember (decompose b2);remember (decompose b3).
 destruct p; destruct p0; destruct p1.
 symmetry in Heqp,Heqp0,Heqp1.
 eapply decompose_glb in Heqb3.
 2: apply Heqp.
 2: apply Heqp0.
 2: apply Heqp1.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 destruct Heqb3;subst.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase x1. icase b.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_right_obmit with (c1:=c)(a1:=t0)(a2:=t1);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_right_obmit with (c1:=c) (a1:=t2) (a2:=t3);trivial.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
 intro. inversion H. intro. inversion H.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_left_obmit with (c':=c0)(a1:=t0)(a2:=t1);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_left_obmit with (c':=c0)(a1:=t2)(a2:=t3);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_right_obmit with (c1:=c) (a1:=t0) (a2:=t1);trivial.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_right_obmit with (c1:=c) (a1:=t2) (a2:=t3);trivial.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
 intro. inversion H.
(* Goal: @eq ShareTree (mkCanon (intersect_tree (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t11 t12)) (mkCanon_correct (Node t11 t12)))) (@proj1_sig ShareTree (fun t : ShareTree => canonicalTree t) (@exist ShareTree canonicalTree (mkCanon (Node t21 t22)) (mkCanon_correct (Node t21 t22)))))) (mkCanon (Node t31 t32)) *)
 intro. inversion H.
Qed.

Lemma unrel_bot: forall a,
 unrel a bot = bot.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: forall (a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
 destruct a. induction x. trivial.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct c as [? [? [? ?]]].
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t (let (ltr1, rtr1) := @decompose t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) in let (ltr2, rtr2) := @decompose t decompose_tree a' in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) bot *)
 rewrite decompose_Node with (c1:=c) (c2:=c0).
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree bot in match x1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) ltr2 end) bot *)
 rewrite decompose_bot.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase x1. icase b.
Qed.

Lemma unrel_top: forall a,
 unrel a top = top.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: forall (a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
 destruct a. induction x. trivial.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct c as [? [? [? ?]]].
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t (let (ltr1, rtr1) := @decompose t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) in let (ltr2, rtr2) := @decompose t decompose_tree a' in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) bot *)
 rewrite decompose_Node with (c1:=c) (c2:=c0).
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree top in match x1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) ltr2 end) top *)
 rewrite decompose_top.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase x1. icase b.
Qed.

Lemma unrel_join: forall x a b c,
 join a b c ->
 join (unrel x a) (unrel x b) (unrel x c).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
 destruct H.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
 split. rewrite<- unrel_glb.
(* Goal: @eq t (unrel x (glb a b)) bot *)
(* Goal: @eq t (lub (unrel x a) (unrel x b)) (unrel x c) *)
 rewrite H. apply unrel_bot.
(* Goal: @eq t c0 c0 *)
 rewrite<- unrel_lub. f_equal. trivial.
Qed.

Lemma unrel_disjoint: forall a a',
 a <> bot ->
 glb a a' = bot ->
 unrel a a' = bot.
Proof.
(* Goal: forall (a a' : t) (_ : not (@eq t a bot)) (_ : @eq t (glb a a') bot), @eq t (unrel a a') bot *)
 intro a.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 destruct a. induction x;intros.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase b. rewrite tree_top_rewrite in *.
(* Goal: @eq t t0 bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) t1) bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 rewrite glb_commute in H0.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 rewrite glb_top in H0. subst.
(* Goal: @eq t (unrel top bot) bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 apply top_unrel.
(* Goal: @eq t c c *)
 rewrite tree_bot_rewrite in *. tauto.

(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 destruct c as [? [? [? ?]]].
(* Goal: @eq t (let (ltr1, rtr1) := @decompose t decompose_tree (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) in let (ltr2, rtr2) := @decompose t decompose_tree a' in let (x, _) := ltr1 in match x with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel rtr1 rtr2 | Node s s0 => unrel ltr1 ltr2 end) bot *)
 rewrite decompose_Node with (c1:=c)(c2:=c0).
(* Goal: @eq t (let (ltr2, rtr2) := @decompose t decompose_tree a' in match x1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) ltr2 end) bot *)
 remember (decompose a').
(* Goal: @eq t (let (ltr2, rtr2) := p in match x1 with | Leaf (true as b) => ltr2 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) rtr2 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) ltr2 end) bot *)
 icase p. symmetry in Heqp.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 generalize (decompose_Node x1 x2 (conj n (conj n0 (conj c c0))) c c0);intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 generalize decompose_bot;intro.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 generalize (decompose_glb _ _ _ _ _ _ _ _ _ H1 Heqp H2);intro.
(* Goal: @eq t match x1 with | Leaf (true as b) => t0 | Leaf (false as b) => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) t1 | Node s s0 => unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) t0 end bot *)
 rewrite H3 in H0.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
 destruct H0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase x1. icase b.
(* Goal: @eq t t0 bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) t1) bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 rewrite tree_top_rewrite in H0.
(* Goal: @eq t t0 bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) t1) bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 rewrite glb_commute in H0.
(* Goal: @eq t c0 c0 *)
 rewrite glb_top in H0. trivial.
(* Goal: @eq t c0 c0 *)
 apply IHx2;trivial.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 destruct n0. inversion n0.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf b) c0) bot) *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1_1 x1_2) c) t0) bot *)
 icase x2. icase b.
(* Goal: @eq t c0 c0 *)
 apply IHx1;trivial.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
 intro.
(* Goal: False *)
 inversion H5.
Qed.

Lemma decompose_height_zero: forall s sL sR,
  decompose s = (sL,sR) ->
  height s = 0 ->
  sL = s /\ sR = s.
(* Goal: @eq t c c *)
Proof with try tauto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
 apply height_zero_eq in H0.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 destruct H0;subst.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 rewrite decompose_top in H. inv H...
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 rewrite decompose_bot in H. inv H...
Qed.

Lemma decompose_equal: forall a b aL aR bL bR,
 decompose a = (aL,aR) ->
 decompose b = (bL,bR) ->
 (a = b <-> aL = bL /\ aR = bR).
(* Goal: @eq t c c *)
Proof with auto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
  assert (forall x y, x = y <-> join bot x y).
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
   intros;split;intro. subst.
(* Goal: @join t Join_ba (unrel x a) (unrel x b) (unrel x c) *)
   split.
(* Goal: @eq t (glb (lub t2 t3) t2) t2 *)
   rewrite glb_commute.
(* Goal: @eq t (glb s bot) bot *)
(* Goal: @eq t (lub s bot) s *)
(* Goal: @identity t Join_ba s *)
   apply glb_bot.
(* Goal: @eq t (lub bot (glb t3 (comp t2))) (glb t3 (comp t2)) *)
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
   rewrite lub_commute.
(* Goal: @eq t (lub s bot) s *)
(* Goal: @identity t Join_ba s *)
   apply lub_bot.
   apply bot_join...
(* Goal: @eq (option t) match mkFull n x with | Some t1' => match mkFull n x0 with | Some t2' => match tree_avgP t1' t2' with | Some t' => @Some (@sig ShareTree (fun t : ShareTree => canonicalTree t)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) (mkCanon t') (mkCanon_correct t')) | None => @None canonTree end | None => @None canonTree end | None => @None canonTree end (@None t) *)
  repeat rewrite H1.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  generalize (decompose_bot);intro.
  apply decompose_join...
Qed.

Lemma decompose_nonzero: forall sL sR s,
 decompose s = (sL,sR) ->
 (s <> bot <-> sL <> bot \/ sR <> bot).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: iff (not (@eq t s bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  destruct s.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  icase x.
  rewrite decompose_basic  with (c1:=c) (c2:=c)in H.
(* Goal: @eq t c c *)
  inv H. icase b;tauto.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  destruct c as [? [? [? ?]]].
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  rewrite decompose_Node with (c1 :=c) (c2:=c0)in H.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  split;intros.
(* Goal: or (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x1 c) bot)) (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot)) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  destruct n0.
(* Goal: False *)
  left. repeat intro. inv H0. inv n0.
(* Goal: False *)
  right. repeat intro. inv H0. inv n0.
(* Goal: False *)
  intro. inv H0.
Qed.

Lemma tree_avg_equal: forall sL sR sL' sR' s n,
 avg n sL sR = Some s ->
 avg n sL' sR' = Some s ->
 sL = sL' /\ sR = sR'.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
 apply tree_avg_avg2round in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
 apply tree_avg_avg2round in H0.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
 destruct H. destruct H0.
(* Goal: @eq nat (PeanoNat.Nat.max (tree_heightP (comp_tree s1)) (tree_heightP (comp_tree s2))) (PeanoNat.Nat.max (tree_heightP s1) (tree_heightP s2)) *)
 split;congruence.
Qed.

Lemma tree_avg_bot: forall n,
 avg (S n) bot bot = Some bot.
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: @eq (option t) (@avg t avgable_tree (S n) bot bot) (@Some t bot) *)
 apply tree_avg_identity.
(* Goal: le (S O) (S n) *)
 compute. omega.
Qed.

Lemma tree_avg_zero: forall sL sR s n,
  avg n sL sR = Some s ->
  (s = bot <-> sL = bot /\ sR = bot).
(* Goal: @eq t c c *)
Proof with try tauto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
(* Goal: and (le (tree_height sh') n) (le (tree_height sh'') n) *)
 icase n.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 split;intros.
 subst s.
 apply tree_avg_equal with bot (S n)...
 apply tree_avg_bot.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
 destruct H0;subst.
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
 rewrite tree_avg_bot in H. inv H...
Qed.

Lemma tree_avg_nonzero: forall sL sR s n,
  avg n sL sR = Some s ->
  (s <> bot <-> sL <> bot \/ sR <> bot).
(* Goal: @eq t c c *)
Proof with try tauto.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros.
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) x2 c0) bot) *)
(* Goal: not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot) *)
  split;repeat intro. icase n.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
  destruct (eq_dec sL bot)... subst.
(* Goal: @eq t (unrel top a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) c) a') bot *)
(* Goal: @eq t (unrel (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) c) a') bot *)
  destruct (eq_dec sR bot)... subst.
  apply tree_avg_zero in H...
  apply tree_avg_zero in H...
Qed.

Lemma tree_avg_bound: forall sL sR s n,
  avg n sL sR = Some s -> (height s <= n)%nat.
(* Goal: le (S O) (S n) *)
Proof with try tauto;try omega.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
  intros. icase n.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  apply tree_avg_avg2round in H.
(* Goal: and (@eq t sL sL') (@eq t sR sR') *)
  destruct H.
  destruct (le_dec (height s) (S n))...
  rewrite tree_round_left_None in H...
(* Goal: iff (not (@eq t (@exist ShareTree (fun t : ShareTree => canonicalTree t) (Node x1 x2) (@conj (nonFullTree (Node x1 x2)) (and (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2))) n (@conj (nonEmptyTree (Node x1 x2)) (and (canonicalTree x1) (canonicalTree x2)) n0 (@conj (canonicalTree x1) (canonicalTree x2) c c0)))) bot)) (or (not (@eq t sL bot)) (not (@eq t sR bot))) *)
  inv H.
Qed.

Lemma Lsh_recompose: Lsh = recompose (top, bot).
Proof.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 compute;f_equal.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 apply proof_irr.
Qed.

Lemma Rsh_recompose: Rsh = recompose (bot,top).
Proof.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 compute;f_equal.
(* Goal: @eq (canonicalTree (relativ_tree (Node (Leaf false) (Leaf true)) (Node x1 x2))) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end) (compose_canon2 false x1 x2 I c) *)
 apply proof_irr.
Qed.

Lemma decompose_Rsh: forall sh,
 unrel Rsh sh = snd (decompose sh).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros. unfold Rsh. simpl.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 unfold rel;simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 destruct (tree_decompose sh);simpl.
(* Goal: @eq t c0 c0 *)
 rewrite unrel_equation. trivial.
Qed.

Lemma decompose_Lsh: forall sh,
 unrel Lsh sh = fst (decompose sh).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros. unfold Lsh. simpl.
(* Goal: @eq t (unrel (rel top leftTree) sh) (@fst t t (tree_decompose sh)) *)
 rewrite unrel_equation.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 unfold rel;simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 destruct (tree_decompose sh);simpl.
(* Goal: @eq t c c *)
 auto.
Qed.

Lemma rel_Lsh: forall sh,
rel Lsh sh = recompose (sh,bot).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros. destruct sh.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 unfold Lsh. simpl.
(* Goal: @eq t (rel (rel top rightTree) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (match x as s return (forall _ : canonicalTree s, canonTree) with | Leaf b2 => fun c4 : True => match (if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false)) with | left e => @eq_rec bool false (fun _ : bool => forall _ : True, canonTree) (fun _ : True => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) I) b2 e c4 | right n => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf b2)) (compose_canon1 false b2 n I c4) end | Node x21 x22 => fun c4 : and (or (nonFullTree x21) (nonFullTree x22)) (and (or (nonEmptyTree x21) (nonEmptyTree x22)) (and (canonicalTree x21) (canonicalTree x22))) => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Node x21 x22)) (compose_canon2 false x21 x22 I c4) end c) *)
 rewrite rel_top2.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 icase x;simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 icase b;simpl.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 compute. f_equal. apply proof_irr.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 compute. f_equal. apply proof_irr.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 compute. f_equal. apply proof_irr.
Qed.

Lemma rel_Rsh: forall sh,
rel Rsh sh = recompose (bot,sh).
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros. destruct sh.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 unfold Rsh. simpl.
(* Goal: @eq t (rel (rel top rightTree) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (match x as s return (forall _ : canonicalTree s, canonTree) with | Leaf b2 => fun c4 : True => match (if b2 as b return (sumbool (@eq bool false b) (not (@eq bool false b))) then @right (@eq bool false true) (not (@eq bool false true)) (fun H : @eq bool false true => False_ind False (@eq_ind bool false (fun e : bool => if e then False else True) I true H)) else @left (@eq bool false false) (not (@eq bool false false)) (@eq_refl bool false)) with | left e => @eq_rec bool false (fun _ : bool => forall _ : True, canonTree) (fun _ : True => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Leaf false) I) b2 e c4 | right n => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Leaf b2)) (compose_canon1 false b2 n I c4) end | Node x21 x22 => fun c4 : and (or (nonFullTree x21) (nonFullTree x22)) (and (or (nonEmptyTree x21) (nonEmptyTree x22)) (and (canonicalTree x21) (canonicalTree x22))) => @exist ShareTree (fun t : ShareTree => canonicalTree t) (Node (Leaf false) (Node x21 x22)) (compose_canon2 false x21 x22 I c4) end c) *)
 rewrite rel_top2.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 icase x;simpl.
(* Goal: @eq t (rel (@snd t t (split top)) (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c)) (recompose (@pair t t bot (@exist ShareTree (fun t : ShareTree => canonicalTree t) x c))) *)
 icase b;simpl.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 compute. f_equal. apply proof_irr.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 compute. f_equal. apply proof_irr.
Qed.

Lemma lub_rel_recompose: forall sh1 sh2,
lub (rel Lsh sh1) (rel Rsh sh2) = recompose (sh1,sh2).
Proof.
(* Goal: forall sh : t, @eq t (rel Rsh sh) (recompose (@pair t t bot sh)) *)
 intros.
 rewrite rel_Lsh, rel_Rsh.
(* Goal: @eq t c c *)
 erewrite decompose_lub;eauto.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 rewrite decompose_recompose. f_equal.
(* Goal: @eq (@sig ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (relativ_almost_canon (Node (Leaf false) (Leaf true)) (Node x1 x2) (@conj (or (@eq bool false false) (@eq bool true false)) (and (or (@eq bool false true) (@eq bool true true)) (and True True)) (@or_introl (@eq bool false false) (@eq bool true false) (@eq_refl bool false)) (@conj (or (@eq bool false true) (@eq bool true true)) (and True True) (@or_intror (@eq bool false true) (@eq bool true true) (@eq_refl bool true)) (@conj True True I I))) c match c with | conj H (conj H1 (conj H3 H4 as H2) as H0) => match H with | or_introl H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end | or_intror H5 => match H1 with | or_introl H6 => @or_introl ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 | or_intror H6 => @or_intror ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x1) ((fix nonEmptyTree (x : ShareTree) : Prop := match x with | Leaf b => @eq bool b true | Node l r => or (nonEmptyTree l) (nonEmptyTree r) end) x2) H6 end end end)) (@exist ShareTree (fun t : ShareTree => (fix canonicalTree (x : ShareTree) : Prop := match x with | Leaf b => True | Node l r => and ((fix nonFullTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b false | Node l0 r0 => or (nonFullTree l0) (nonFullTree r0) end) x) (and ((fix nonEmptyTree (x0 : ShareTree) : Prop := match x0 with | Leaf b => @eq bool b true | Node l0 r0 => or (nonEmptyTree l0) (nonEmptyTree r0) end) x) (and (canonicalTree l) (canonicalTree r))) end) t) (Node (Leaf false) (Node x1 x2)) (compose_canon2 false x1 x2 I c)) *)
 rewrite decompose_recompose. f_equal.
 rewrite decompose_recompose.
(* Goal: @eq t (lub (glb t2 t2) bot) t2 *)
 rewrite lub_bot.
(* Goal: @eq t (lub bot (glb t3 (comp t2))) (glb t3 (comp t2)) *)
(* Goal: @eq t (glb (comp t2) t3) t3 *)
(* Goal: iff (@eq (option canonTree) (@None canonTree) (@Some canonTree t3)) (@join canonTree Join_ba t2 t3 t1) *)
 rewrite lub_commute.
(* Goal: @eq t c0 c0 *)
 rewrite lub_bot;trivial.
Qed.

End Share.


