(* Sizes *)
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_function _ _ p t v => max (term_size t + value_size v) (max_active_size p)
end.
Fixpoint max_judgement_size (proof_tree : cbv) : nat :=
match proof_tree with
| cbv_constr lp t v => max (term_size t + value_size v) (maxl (map max_judgement_size lp))
| cbv_split lp p t v => max (term_size t + value_size v) (max (max_judgement_size p) (maxl (map max_judgement_size lp)))
| cbv_function _ _ p t v => max (term_size t + value_size v) (max_judgement_size p)
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_function _ _ p _ _ => sub_trees p
end ).

Lemma InCBV_In_sub_trees p p' : InCBV p p' <-> In p (sub_trees p').
Fixpoint proj_left_max_size_list (default : cbv) (proof_trees : list cbv) : cbv :=
match proof_trees with
| [] => default
| [p] => p
| p :: ps =>
let p' := proj_left_max_size_list default ps in
if leb (term_size (proj_left p)) (term_size (proj_left p')) then p' else p
end.