Definition cbv_cache_entry (proof_tree : cbv) := (proj_left proof_tree, proj_right proof_tree).

(* Specifications: *)
Lemma cache_content (proof_tree : cbv) :
wf proof_tree ->
cache_right proof_tree =
map cbv_cache_entry (activations_cache_order proof_tree) ++
cache_left proof_tree.
Lemma cache_content_on_path c1 c2 lp:
andl (map wf lp) ->
cache_path c1 c2 lp = true ->
c2 = map cbv_cache_entry (revflatten (map activations_cache_order lp)) ++ c1.
Lemma cache_path_proj_left_in_tail_not_in_head t p lp c1 c2 :
cache_path c1 c2 (p :: lp) = true ->
andl (map wf (p :: lp)) ->
In t (map proj_left (revflatten (map activations_cache_order lp))) ->
~ In t (map proj_left (activations_cache_order p)).
Lemma whole_cache_path_consistent lp : forall c1 c2,
cache_path c1 c2 lp = true ->
andl (map wf lp) ->
exists C,
cache_beq c2 (C ++ c1) = true /\
(forall t, assoc_cache t C <> None -> assoc_cache t c1 = None).
Lemma cache_path_proj_left_not_in_init t lp c1 c2 :
cache_path c1 c2 lp = true ->
andl (map wf lp) ->
In t (map proj_left (revflatten (map activations_cache_order lp))) ->
~ In t (map fst c1).
Lemma cache_lookup_term (p: cbv) (ext: cache):
wf p ->
(forall t: term, assoc_cache t ext <> None -> assoc_cache t (cache_right p) = None) ->
cache_lookup (ext ++ cache_right p) (proj_left p) = @term_from_value _ _ _ (proj_right p).
Lemma first_activations_residues_activation i s p c1 t c2 v :
let proof_tree := cbv_update i s p c1 t c2 v in
wf proof_tree ->
Forall2 (fun p' t' =>
match (proj_left p', t') with
| (fapply f lv, fapply f' lt) =>
f = f' /\
Forall2 (fun t v => cache_lookup (cache_left p') t = v) lt lv
| _ => False
end)
(first_activations_and_semi proof_tree)
(fapplies_in_term (proj_left p)).
Lemma nb_nodes_bound i s p' c1 t c2 v :
let p := cbv_update i s p' c1 t c2 v in
nb_nodes p <= suml (map nb_judgements_sub (activations p)) + length (activations p).
Lemma nb_judgements_bound i s p' c1 t c2 v :
let p := cbv_update i s p' c1 t c2 v in
nb_judgements p <= suml (map nb_judgements_sub (activations p)) + length (activations p) + nb_read p.
Lemma nb_judgements_sub_rec_bound p :
wf p -> nb_judgements_sub_rec p <= term_size (proj_left p).
Lemma nb_judgements_sub_bound i s p c1 t c2 v :
wf (cbv_update i s p c1 t c2 v) ->
nb_judgements_sub (cbv_update i s p c1 t c2 v) <= activation_bound prog (term_size t).
Lemma right_from_activation_or_from_left p : wf p ->
maxl (map (fun tv : term * value => value_size (snd tv)) (cache_right p)) <=
max (max_active_size p) (maxl (map (fun tv : term * value => value_size (snd tv)) (cache_left p))).
Lemma right_from_activation_or_from_left_path lp c1 c2 : andl (map wf lp) ->
cache_path c1 c2 lp = true ->
maxl (map (fun tv : term * value => value_size (snd tv)) c2) <=
max (maxl (map max_active_size lp)) (maxl (map (fun tv : term * value => value_size (snd tv)) c1)).
Lemma value_size_bounded_by_nb_judgements p :
wf p -> value_size (proj_right p) <= (1 + max (max_active_size p) (maxl (map (fun tv => value_size (snd tv)) (cache_left p)))) * nb_judgements p.
Lemma size_bounded_nb_size_judgements p :
size p <= nb_judgements p * max_judgement_size p + cache_size (cache_left p).
Lemma nb_judgements_sub_bound_gen : forall p p',
let S := max_active_size p in
wf p ->
In p' (activations p) -> nb_judgements_sub p' <= activation_bound prog S.
Lemma nb_judgements_bound_gen : forall i s p' c1 t c2 v,
let p := cbv_update i s p' c1 t c2 v in
let A := length (activations p) in
let S := max_active_size p in
wf p ->
nb_judgements p <= A * activation_bound prog S + A + (Datatypes.S (max_arity * nb_nodes p)).
Lemma cache_path_incl : forall lp c1 c2,
andl (map wf lp) -> cache_path c1 c2 lp = true -> incl c1 c2.
Lemma InCBV_cache_right_incl p proof_tree :
wf proof_tree ->
InCBV p proof_tree ->
incl (cache_right p) (cache_right proof_tree).
Lemma InCBV_read_cache_right c t v p:
wf p ->
InCBV (cbv_read c t v) p ->
In (t, v) (cache_right p).
Lemma term_size_proj_left_bound : forall i s p' c1 t c2 v,
let p := cbv_update i s p' c1 t c2 v in
let S := max_active_size p in
wf p ->
forall p',
InCBV p' p -> term_size (proj_left p') <= activation_bound prog S + S + cache_size c1.
Lemma nb_nodes_bound_gen i s p' c1 t c2 v :
let p := cbv_update i s p' c1 t c2 v in
let A := length (activations p) in
let S := max_active_size p in
wf p ->
nb_nodes p <= A * (1 + activation_bound prog S).
Lemma size_judgement : forall i s p' c1 t c2 v,
let p := cbv_update i s p' c1 t c2 v in
let A := length (activations p) in
let S := max_active_size p in
let C := maxl (map (fun tv : term * value => value_size (snd tv)) c1) in
wf p ->
max_judgement_size p <=
activation_bound prog S + S + cache_size c1 +
(1 + max S C) * (1 + (A * activation_bound prog S + A) + max_arity * (A * activation_bound prog S + A)).
Theorem size_bound_gen : forall i s p' c1 t c2 v,
let p := cbv_update i s p' c1 t c2 v in
let A := length (activations p) in
let S := max_active_size p in
wf p ->
size p <=
(A * activation_bound prog S + A + 1 + (max_arity * A * (1 + activation_bound prog S))) *
(activation_bound prog S + S + cache_size c1 +
(1 + max S (maxl (map (fun tv : term * value => value_size (snd tv)) c1))) *
(1 + (A * activation_bound prog S + A) + max_arity * (A * activation_bound prog S + A))) +
cache_size c1.
(* This corollary corresponds to Proposition 6. *)
Corollary size_bound : forall i s p' t c v,
let p := cbv_update i s p' [] t c v in
let A := length (activations p) in
let S := max_active_size p in
wf p ->
size p <=
(A * activation_bound prog S + A + 1 + (max_arity * A * (1 + activation_bound prog S))) *
(activation_bound prog S + S +
(1 + S) *
(1 + (A * activation_bound prog S + A) + max_arity * (A * activation_bound prog S + A))).