Fixpoint nb_judgements (proof_tree : cbv) : nat :=
  match proof_tree with
  | cbv_constr lp _ _ _ _ => 1 + suml (map nb_judgements lp)
  | cbv_split lp p _ _ _ _ => 1 + nb_judgements p + suml (map nb_judgements lp)
  | cbv_update _ _ p _ _ _ _ => 1 + nb_judgements p
  | cbv_read _ _ _=> 1
  end.Fixpoint nb_judgements_sub_rec (proof_tree : cbv) : nat :=
  match proof_tree with
  | cbv_constr lp _ _ _ _ => 1 + suml (map nb_judgements_sub_rec lp)
  | cbv_split lp p _ _ _ _ => 1 + nb_judgements_sub_rec p + suml (map nb_judgements_sub_rec lp)
  | cbv_update _ _ _ _ _ _ _ => 0
  | cbv_read _ _ _ => 0
  end.Definition nb_judgements_sub (proof_tree : cbv) : nat :=
  match proof_tree with
  | cbv_constr _ _ _ _ _ => 0
  | cbv_split _ _ _ _ _ _ => 0
  | cbv_update _ _ p _ _ _ _ => nb_judgements_sub_rec p
 | cbv_read _ _ _ => 0
  end.Fixpoint nb_nodes (proof_tree : cbv) : nat :=
  match proof_tree with
  | cbv_constr [] _ _ _ _ => 0
  | cbv_constr lp _ _ _ _ => 1 + suml (map nb_nodes lp)
  | cbv_split lp p _ _ _ _ => 1 + nb_nodes p + suml (map nb_nodes lp)
  | cbv_update _ _ p _ _ _ _ => 1 + nb_nodes p
  | cbv_read _ _ _ => 0
  end.Fixpoint nb_read (proof_tree : cbv) : nat :=
  match proof_tree with
  | cbv_constr lp _ _ _ _ => suml (map nb_read lp)
  | cbv_split lp p _ _ _ _ => nb_read p + suml (map nb_read lp)
  | cbv_update _ _ p _ _ _ _ => nb_read p
  | cbv_read _ _ _ => 1
  end.Definition arity_cbv (proof_tree : cbv) : nat :=
  match proof_tree with
  | cbv_constr lp _ _ _ _  => length lp
  | cbv_split lp p _ _ _ _ => 1 + length lp
  | cbv_update _ _ p _ _ _ _ => 1
  | cbv_read _ _ _ => 0
  end.

(* Specifications: *)
Lemma wf_arity p : wf p -> arity_cbv p <= S max_arity.
Lemma nb_read_bound : forall p, wf p -> nb_read p <= S (max_arity * nb_nodes p).