(* * Copyright (c) 2009-2010, Andrew Appel, Robert Dockins and Aquinas Hobor. * *)
Declare Scope pred.
Delimit Scope pred with pred.
Local Open Scope pred.
(* A "pre-predicate" is hereditary iff whenever it is true at world a, it is also true at all worlds accessable from a via R. *)
Definition hereditary {A} (R:A->A->Prop) (p:A->Prop) :=
forall a a':A, R a a' -> p a -> p a'.
(* A predicate is a hereditary pre-predicate *)
Definition pred (A:Type) {AG:ageable A} :=
{ p:A -> Prop | hereditary age p }.
Bind Scope pred with pred.
(* Here is some junk that makes the definition of "pred" opaque to most tactics but still allows the "Program" extension to see it is a subset type.  The coercion is sugar that allows us to use predicates easily. *)
Definition app_pred {A} `{ageable A} (p:pred A) : A -> Prop := proj1_sig p.
Definition pred_hereditary `{ageable} (p:pred A) := proj2_sig p.
Coercion app_pred : pred >-> Funclass.
Global Opaque pred.
Hint Resolve @pred_hereditary : core.
Program Definition mkPred {A} `{ageable A} (p:A -> Prop) : pred A :=
fun x => forall x', necR x x' -> p x'.
Next Obligation.
repeat intro.
apply H1.
apply rt_trans with a'; auto.
apply rt_step; auto.
Qed.
(* The semantic notion of entailment. *)
Definition derives {A} `{ageable A} (P Q:pred A) := forall a:A, P a -> Q a.
Arguments derives [A] [H] _ _.
(* "valid" relations are those that commute with aging.  These relations are the ones that can be turned into modalities. *)
Definition valid_rel {A} `{ageable A} (R:relation A) : Prop :=
commut A age R /\ commut A R age.
(* A modaility is a valid relation *)
Definition modality {A} `{ageable A} := { R:relation A | valid_rel R }.
(* More black magic to make the definition of modaility mostly opaque. *)
Definition app_mode {A} `{ageable A} (m:modality) : A -> A -> Prop := proj1_sig m.
Definition mode_valid {A} `{ageable A} (m:modality) := proj2_sig m.
Global Opaque modality.
Coercion app_mode : modality >-> Funclass.
(* commutivity facts for the basic relations *)

Lemma valid_rel_commut_nec1 {A} `{ageable A} : forall R,
valid_rel R ->
commut A necR R.