Notation value := (Syntax.value constructor).Notation term := (Syntax.term variable function constructor).Notation pattern := (Syntax.pattern variable constructor).Notation rule := (Syntax.rule variable function constructor).Notation cache := (CBV_cache.cache variable function constructor).Notation cbv := (CBV_cache.cbv variable function constructor).Notation wf := (CBV_cache.wf variable_eq_dec function_eq_dec constructor_eq_dec rule_default
                prog max_arity).Definition gsp := (Bounds.gary_seven_poly variable function constructor prog max_rank).Definition bep := (Bounds.bobby_eight_poly variable function constructor max_arity prog).Notation cache_bounded := (QI.cache_bounded variable function constructor qic qif).Definition CBV_bound A S C :=  (* generic bound *)
  (* A : number of activations
     S : max size of an activation 
     C : cache *)
  (A * activation_bound prog S + A + 1 + (max_arity * A * (1 + activation_bound prog S))) *
  (activation_bound prog S + S + cache_size C +
  (1 + max S (maxl (map (fun tv : term * value => value_size (snd tv)) C))) *
  (1 + (A * activation_bound prog S + A) + max_arity * (A * activation_bound prog S + A))) +
  cache_size C.Definition PPO_bound S := gsp (bep S).(* S : max size of an activation *)

Definition QI_bound (f:function) (lv: list term) := 
  (* f : active function symbol
     lv : list of its arguments *)
  (max_arity + 1) * (qif f (map (fun x=> mcs * (term_size (fapply f lv))) lv)) + 1.Definition global_bound f lv C :=
  let S:= QI_bound f lv in
  let A:= PPO_bound S in
  CBV_bound A S C.

(* Specifications: *)
Lemma gary_increase: (* move to Ordering ? *) forall x y, x <=y -> gsp x <= gsp y.
Lemma PPO_bound_increase: forall x y, x <= y -> PPO_bound x <= PPO_bound y.
Lemma activation_bound_increase: forall x y, x <= y -> activation_bound prog x <= activation_bound prog y.
Lemma CBV_bound_increase: forall x1 y1 x2 y2 C, x1 <= y1 -> x2 <= y2 -> CBV_bound x1 x2 C <= CBV_bound y1 y2 C.
Theorem P_criterion: forall i s p c f lv d v, let t := (fapply f lv) in let pi := cbv_update i s p c t d v in wf pi -> cache_bounded c -> size pi <= global_bound f lv c.