End GHist.
Hint Resolve hist_incl_nil hist_list_nil hist_list'_nil add_events_nil.
(*Hint Resolve ghost_var_precise ghost_var_precise'.*)
Hint Resolve (*ghost_var_init*) master_init (*ghost_map_init*) ghost_hist_init : init.
Ltac ghost_alloc G :=
match goal with |-semax _ (PROPx ?P (LOCALx ?Q (SEPx ?R))) _ _ =>
apply (semax_pre_bupd (PROPx P (LOCALx Q (SEPx ((EX g : _, G g) :: R)))));
[go_lower; rewrite !prop_true_andp by (repeat (split; auto));
rewrite <- emp_sepcon at 1; eapply derives_trans, bupd_frame_r;
apply sepcon_derives, derives_refl; apply own_alloc; auto; simpl; auto with init|] end.
Ltac ghosts_alloc G n :=
match goal with |-semax _ (PROPx ?P (LOCALx ?Q (SEPx ?R))) _ _ =>
apply (semax_pre_bupd (PROPx P (LOCALx Q (SEPx ((EX lg : _, !!(Zlength lg = n) && iter_sepcon G lg) :: R)))));
[go_lower; rewrite !prop_true_andp by (repeat (split; auto));
rewrite <- emp_sepcon at 1; eapply derives_trans, bupd_frame_r;
apply sepcon_derives, derives_refl; apply own_list_alloc'; auto; simpl; auto with init|] end.
(* weak view shift for use in funspecs *)
(* This could be replaced with P -* |==> Q. *)
Program Definition weak_view_shift (P Q: mpred): mpred :=
fun w => predicates_hered.derives (approx (S (level w)) P) (own.bupd (approx (S (level w)) Q)).
Next Obligation.
repeat intro.
destruct H1.
apply age_level in H.
lapply (H0 a0); [|split; auto; omega].
intro HQ; destruct (HQ _ H2) as (? & ? & ? & ? & ? & ? & []).
eexists; split; eauto; eexists; split; eauto; repeat split; auto; omega.
Defined.

Lemma view_shift_nonexpansive: forall P Q n,
approx n (weak_view_shift P Q) = approx n (weak_view_shift (approx n P) (approx n Q)).