(* 
  Predicate that checks if a position (a list of bool) can
  be safely added (adding an element is done without any removing)
*)
Inductive pbfree : list bool -> pbtree -> Prop :=
  | pbfree_left1 : forall b l, pbfree (true :: l) (pbleft b)
  | pbfree_left2 : forall b l, pbfree l b -> pbfree (false :: l) (pbleft b)
  | pbfree_right1 : forall b l, pbfree (false :: l) (pbright b)
  | pbfree_right2 : forall b l, pbfree l b -> pbfree (true :: l) (pbright b)
  | pbfree_node1 :
      forall b c l, pbfree l b -> pbfree (false :: l) (pbnode b c)
  | pbfree_node2 :
      forall b c l, pbfree l b -> pbfree (true :: l) (pbnode c b).(* 
  Predicate that checks if a position (a list of bool) can
  be safely added (adding an element is done without any removing)
*)
Inductive pbfree : list bool -> pbtree -> Prop :=
  | pbfree_left1 : forall b l, pbfree (true :: l) (pbleft b)
  | pbfree_left2 : forall b l, pbfree l b -> pbfree (false :: l) (pbleft b)
  | pbfree_right1 : forall b l, pbfree (false :: l) (pbright b)
  | pbfree_right2 : forall b l, pbfree l b -> pbfree (true :: l) (pbright b)
  | pbfree_node1 :
      forall b c l, pbfree l b -> pbfree (false :: l) (pbnode b c)
  | pbfree_node2 :
      forall b c l, pbfree l b -> pbfree (true :: l) (pbnode c b).(* 
  Predicate that checks if a position (a list of bool) can
  be safely added (adding an element is done without any removing)
*)
Inductive pbfree : list bool -> pbtree -> Prop :=
  | pbfree_left1 : forall b l, pbfree (true :: l) (pbleft b)
  | pbfree_left2 : forall b l, pbfree l b -> pbfree (false :: l) (pbleft b)
  | pbfree_right1 : forall b l, pbfree (false :: l) (pbright b)
  | pbfree_right2 : forall b l, pbfree l b -> pbfree (true :: l) (pbright b)
  | pbfree_node1 :
      forall b c l, pbfree l b -> pbfree (false :: l) (pbnode b c)
  | pbfree_node2 :
      forall b c l, pbfree l b -> pbfree (true :: l) (pbnode c b).(* 
  Predicate that checks if a position (a list of bool) can
  be safely added (adding an element is done without any removing)
*)
Inductive pbfree : list bool -> pbtree -> Prop :=
  | pbfree_left1 : forall b l, pbfree (true :: l) (pbleft b)
  | pbfree_left2 : forall b l, pbfree l b -> pbfree (false :: l) (pbleft b)
  | pbfree_right1 : forall b l, pbfree (false :: l) (pbright b)
  | pbfree_right2 : forall b l, pbfree l b -> pbfree (true :: l) (pbright b)
  | pbfree_node1 :
      forall b c l, pbfree l b -> pbfree (false :: l) (pbnode b c)
  | pbfree_node2 :
      forall b c l, pbfree l b -> pbfree (true :: l) (pbnode c b).(* 
  Predicate that checks if a position (a list of bool) can
  be safely added (adding an element is done without any removing)
*)
Inductive pbfree : list bool -> pbtree -> Prop :=
  | pbfree_left1 : forall b l, pbfree (true :: l) (pbleft b)
  | pbfree_left2 : forall b l, pbfree l b -> pbfree (false :: l) (pbleft b)
  | pbfree_right1 : forall b l, pbfree (false :: l) (pbright b)
  | pbfree_right2 : forall b l, pbfree l b -> pbfree (true :: l) (pbright b)
  | pbfree_node1 :
      forall b c l, pbfree l b -> pbfree (false :: l) (pbnode b c)
  | pbfree_node2 :
      forall b c l, pbfree l b -> pbfree (true :: l) (pbnode c b).(* 
  Predicate that checks if a position (a list of bool) can
  be safely added (adding an element is done without any removing)
*)
Inductive pbfree : list bool -> pbtree -> Prop :=
  | pbfree_left1 : forall b l, pbfree (true :: l) (pbleft b)
  | pbfree_left2 : forall b l, pbfree l b -> pbfree (false :: l) (pbleft b)
  | pbfree_right1 : forall b l, pbfree (false :: l) (pbright b)
  | pbfree_right2 : forall b l, pbfree l b -> pbfree (true :: l) (pbright b)
  | pbfree_node1 :
      forall b c l, pbfree l b -> pbfree (false :: l) (pbnode b c)
  | pbfree_node2 :
      forall b c l, pbfree l b -> pbfree (true :: l) (pbnode c b).(* 
  Predicate that checks if a position (a list of bool) can
  be safely added (adding an element is done without any removing)
*)
Inductive pbfree : list bool -> pbtree -> Prop :=
  | pbfree_left1 : forall b l, pbfree (true :: l) (pbleft b)
  | pbfree_left2 : forall b l, pbfree l b -> pbfree (false :: l) (pbleft b)
  | pbfree_right1 : forall b l, pbfree (false :: l) (pbright b)
  | pbfree_right2 : forall b l, pbfree l b -> pbfree (true :: l) (pbright b)
  | pbfree_node1 :
      forall b c l, pbfree l b -> pbfree (false :: l) (pbnode b c)
  | pbfree_node2 :
      forall b c l, pbfree l b -> pbfree (true :: l) (pbnode c b).(* Add an element in a tree at a given position (list of bool) *)
Fixpoint pbadd (a : A) (t : pbtree) (l : list bool) {struct l} : pbtree :=
  match l with
  | nil => pbleaf a
  | false :: l1 =>
      match t with
      | pbnode t1 t2 => pbnode (pbadd a t1 l1) t2
      | pbleft t1 => pbleft (pbadd a t1 l1)
      | pbright t2 => pbnode (pbadd a (pbleaf empty) l1) t2
      | _ => pbleft (pbadd a (pbleaf empty) l1)
      end
  | true :: l1 =>
      match t with
      | pbnode t1 t2 => pbnode t1 (pbadd a t2 l1)
      | pbright t2 => pbright (pbadd a t2 l1)
      | pbleft t1 => pbnode t1 (pbadd a (pbleaf empty) l1)
      | _ => pbright (pbadd a (pbleaf empty) l1)
      end
  end.

Theorem pbadd_prop2 : forall a1 l1 l2, pbfree l1 l2 -> permutation (compute_pbcode (pbadd a1 l2 l1)) ((a1, l1) :: compute_pbcode l2).