Definition activation_rank (p : cbv) : nat :=
  match p with
  | cbv_update _ _ _ _ (fapply f _) _ _ => rank f
  | _                                   => 0
  end.

(* Specifications: *)
Lemma fapplies_rec_PPO t t': In t (fapplies_in_term t') -> clos_refl PPO t t'.
Lemma PPO_value_is_value t v : PPO t v -> term_value v -> term_value t.
Lemma PPO_activation_le_rank f1 lt1 f2 lv2 : PPO (fapply f1 lt1) (fapply f2 (map (@term_from_value _ _ _) lv2)) -> rank f1 <= rank f2.
Lemma PPO_pattern_le_rank f1 lt1 f2 lp2 : PPO (fapply f1 lt1) (fapply f2 (map (@term_from_pattern _ _ _) lp2)) -> rank f1 <= rank f2.
Lemma subfapplies_activation_le_rank i s p c1 f lt c2 v f' lt' : let proof_tree := cbv_update i s p c1 (fapply f lt) c2 v in PPO_prog -> wf proof_tree -> In (fapply f' lt') (fapplies_in_term (proj_left p)) -> rank f' <= rank f.
Lemma le_rank_first_activation 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 proof_tree) -> activation_rank p' <= activation_rank proof_tree.
Lemma PPO_first_activations 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 proof_tree) -> PPO (proj_left p') (proj_left proof_tree).
Lemma PPO_activations 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' (activations proof_tree) -> p' = proof_tree \/ PPO (proj_left p') (proj_left proof_tree).
Lemma same_rank_same_prod vv ff cc lt ls rk rk': (forall t s, In t lt -> In s ls -> (forall f, In f (functions_of_term t) -> rk f = rk' f) -> (forall f, In f (functions_of_term s) -> rk f = rk' f) -> PPO rk t s -> PPO rk' t s) -> (forall f, In f (flat_map (@functions_of_term vv ff cc) lt) -> rk f = rk' f) -> (forall f, In f (flat_map (@functions_of_term _ _ _) ls) -> rk f = rk' f) -> product (PPO rk) lt ls -> product (PPO rk') lt ls.
Lemma same_rank_same_ppo vv ff cc (t : term vv ff cc) s rk rk': (forall f, In f (functions_of_term t) -> rk f = rk' f) -> (forall f, In f (functions_of_term s) -> rk f = rk' f) -> PPO rk t s -> PPO rk' t s.
Lemma same_rank_same_ppo_rule vv ff cc f lp (t : term vv ff cc) rk rk': rk f = rk' f -> (forall g, g ∈ (functions_of_term t) -> rk g = rk' g) -> PPO rk t (fapply f (map (@term_from_pattern _ _ _) lp)) -> PPO rk' t (fapply f (map (@term_from_pattern _ _ _) lp)).