(*****************************************************************************************)
(*                  QI of function symbols / terms                                       *)
(*****************************************************************************************)

(* c'est cette forme qui est utilisée partout *)
Definition subterm (qif:assignment_function) := forall f l x, In x l -> x <= qif f l.(*monotonicity*)
Definition monotonicity_qif (qif:assignment_function) :=
  forall f lx ly, Forall2 le lx ly -> qif f lx <= qif f ly.(* assignment of a term*)
Fixpoint term_assignment (qic:assignment_constructor) (qif:assignment_function)
(t:term) {struct t}:=
   match t with
  | var v=> 0 (* pas necessaire. Les QI sont toujours appliquées sur des termes clots. *)
  | capply c lt => qic c (map (term_assignment qic qif) lt)
  | fapply f lt=> qif f (map (term_assignment qic qif)  lt) 
 end.(*Definition 12*)
Definition compatible_QI qic qif := forall f lp t, forall s:variable -> value,
  let ru := rule_intro f lp t in (* f(p1, ..., pn) -> t *)
  (In ru prog) -> 
  term_assignment qic qif (subst s t) <= term_assignment qic qif (subst s (lhs_of_rule ru)).(* pour toute substitution, QI(t) <= QI(f(p1, ..., pn)) *)

Definition valid_QI qic qif cs :=
  (additive qic cs) /\ (mcs_is_max_constructor_size cs) /\ (constructor_non_zero cs) /\
  (subterm qif) /\ (monotonicity_qif qif) /\ (compatible_QI qic qif).Definition cache_bounded qic qif (c:cache): Prop  := 
  Forall (fun t => value_assignment qic (snd t) <= term_assignment qic qif (fst t)) c.

Lemma left_bound_to_right_bound qic qif cs:forall pi:cbv, valid_QI qic qif cs -> (wf pi) -> cache_bounded qic qif (cache_left pi) -> (value_assignment qic (proj_right pi) <= term_assignment qic qif (proj_left pi) /\ cache_bounded qic qif (cache_right pi)).