Definition activation_function (function_default : function) (p: cbv) :=
  match p with
    | cbv_update _ _ _ _ (fapply f _) _ _ => f
    | _                                   => function_default
  end.

(* Specifications: *)
Lemma first_activations_at_given_rank_rank rk p p' : In p' (first_activations_at_given_rank rk p) -> rk = activation_rank rank p'.
Lemma first_activations_at_given_rank_sublist_activations rk p : sublist (first_activations_at_given_rank rk p) (activations p).
Lemma NoDup_activations i s p c1 t c2 v : PPO_prog -> wf (cbv_update i s p c1 t c2 v) -> NoDup (activations (cbv_update i s p c1 t c2 v)).
Lemma NoDup_first_activations_at_given_rank rk i s p c1 t c2 v : PPO_prog -> wf (cbv_update i s p c1 t c2 v) -> NoDup (first_activations_at_given_rank rk (cbv_update i s p c1 t c2 v)).
Lemma first_activations_at_given_rank_activations rk p: incl (first_activations_at_given_rank rk p) (activations p).
Lemma A_T_activation_rank (p p' : cbv) : In p' (first_activations_at_given_rank (activation_rank rank p') p) -> length (activations_at_rank (activation_rank rank p') p') <= A_T p.
Lemma activation_eq_dec p i s p0 c1 t c2 v: let proof_tree := cbv_update i s p0 c1 t c2 v in PPO_prog -> wf proof_tree -> In p (activations proof_tree) -> p = proof_tree \/ p <> proof_tree.
Lemma activations_trans p p' p'' : wf p'' -> In p (activations p') -> In p' (activations p'') -> In p (activations p'').
Lemma first_activation_down p i s p0 c1 t c2 v: let proof_tree := cbv_update i s p0 c1 t c2 v in PPO_prog -> wf proof_tree -> p <> proof_tree -> In p (activations proof_tree) -> exists p', In p' (activations proof_tree) /\ In p (first_activations p').
Lemma FA_path_app p p' p'' lp1 lp2 : FA_path p p' lp1 /\ FA_path p' p'' lp2 -> FA_path p p'' (lp1 ++ lp2).
Lemma first_activations_at_given_rank_path p p' i s p0 c1 t c2 v : let proof_tree := cbv_update i s p0 c1 t c2 v in In p' (activations proof_tree) -> In p (activations p') -> exists lp, FA_path p p' lp.
Lemma FA_path_activation p p' i s p0 c1 t c2 v lp : let proof_tree := cbv_update i s p0 c1 t c2 v in wf proof_tree -> In p' (activations proof_tree) -> FA_path p p' lp -> In p (activations p').
Lemma FA_path_app_destruct p p' lp1 lp2 : FA_path p p' (lp1 ++ lp2) -> exists p'', FA_path p p'' lp1 /\ FA_path p'' p' lp2.
Lemma FA_path_uniqueness p i s p0 c1 t c2 v lp1 lp2 : PPO_prog -> let p' := (cbv_update i s p0 c1 t c2 v) in wf p' -> FA_path p p' lp1 -> FA_path p p' lp2 -> lp1 = lp2.
Lemma first_activation_down_rank_lt p p' i s p0 c1 t c2 v: let proof_tree := cbv_update i s p0 c1 t c2 v in PPO_prog -> wf proof_tree -> In p' (activations proof_tree) -> In p (first_activations p') -> In p (first_activations_at_given_rank (activation_rank rank p) proof_tree) -> activation_rank rank p < activation_rank rank p'.
Lemma first_activations_at_given_rank_lt_previous i s p c1 t c2 v p': let proof_tree := cbv_update i s p c1 t c2 v in PPO_prog -> wf proof_tree -> In p' (first_activations_at_given_rank (activation_rank rank p') proof_tree) -> activation_rank rank p' < activation_rank rank proof_tree -> exists p'', In p'' (activations proof_tree) /\ In p' (first_activations p'') /\ activation_rank rank p' < activation_rank rank p''.
Lemma length_fapplies_le_functions s t : length (fapplies_in_term (@subst variable function constructor s t)) <= length (functions_of_term t).
Lemma first_activations_length_le_first_and_semi_activations n s p c1 f l c2 v : length (first_activations (cbv_update n s p c1 (@fapply variable function constructor f l) c2 v)) <= length (first_activations_and_semi (cbv_update n s p c1 (fapply f l) c2 v)).
Lemma degree_bounded p : wf p -> length (first_activations p) <= max_nb_rhs_functions prog.
Lemma split_activations_by_first_activations_at_rank rk p : wf p -> activations_at_rank rk p = flat_map (activations_at_rank rk) (first_activations_at_given_rank rk p).
Lemma activations_at_rank_activation_rank proof_tree p: In p (activations proof_tree) -> In p (activations_at_rank (activation_rank rank p) proof_tree).
Lemma first_activations_at_given_rank_incl i s p c1 t c2 v r : let proof_tree := cbv_update i s p c1 t c2 v in PPO_prog -> wf proof_tree -> r < activation_rank rank proof_tree -> incl (first_activations_at_given_rank r proof_tree) (flat_map (@first_activations _ _ _) (flat_map (fun r' => activations_at_rank r' proof_tree) (seq (1 + r) (max_rank - r)))).