(* Sizes *)

Definition cache_size (c : cache) : nat :=
  suml (map (fun tv => term_size (fst tv) + value_size (snd tv)) c).Fixpoint size_rec (proof_tree : cbv) : nat :=
  match proof_tree with
  | cbv_constr l c1 t c2 v => term_size t + value_size v + suml (map size_rec l)
  | cbv_split l p c1 t c2 v => term_size t + value_size v + size_rec p + suml (map size_rec l)
  | cbv_update _ _ p c1 t c2 v => size_rec p + term_size t + value_size v
  | cbv_read c t v => term_size t + value_size v
  end.Definition size (proof_tree : cbv) : nat :=
  size_rec proof_tree + cache_size (cache_left proof_tree).Fixpoint max_active_size (proof_tree : cbv) : nat :=
  match proof_tree with
  | cbv_constr lp _ _ _ _ => maxl (map max_active_size lp)
  | cbv_split lp p _ _ _ _ => max (max_active_size p) (maxl (map max_active_size lp)) 
  | cbv_update _ _ p _ t _ v => max (term_size t + value_size v) (max_active_size p)
  | cbv_read c t v => 0
  end.Fixpoint max_judgement_size (proof_tree : cbv) : nat :=
  match proof_tree with
  | cbv_constr lp c1 t c2 v => max (term_size t + value_size v) (maxl (map max_judgement_size lp))
  | cbv_split lp p c1 t c2 v => max (term_size t + value_size v) (max (max_judgement_size p) (maxl (map max_judgement_size lp)))
  | cbv_update _ _ p c1 t c2 v => max (term_size t + value_size v) (max_judgement_size p)
  | cbv_read c t v => term_size t + value_size v
  end.(* Sub-trees *)

Fixpoint sub_trees (proof_tree : cbv) : list cbv :=
  proof_tree :: (
    match proof_tree with
    | cbv_constr lp _ _ _ _ => flat_map sub_trees lp
    | cbv_split lp p _ _ _ _ => flat_map sub_trees (p :: lp)
    | cbv_update _ _ p _ _ _ _ => sub_trees p
    | cbv_read _ _ _ => []
    end ).

(* Specifications: *)
Lemma sub_trees_neq_nil : forall p, sub_trees p <> [].
Lemma InCBV_In_sub_trees p p' : InCBV p p' <-> In p (sub_trees p').
Lemma sub_trees_size_rec_le p proof_tree : In p (sub_trees proof_tree) -> size_rec p <= size_rec proof_tree.