(* ========================================================================= *)
(* Abstract version of symbolic trajectory evaluation.                       *)
(*                                                                           *)
(* Based on the paper "Symbolic Trajectory Evaluation in a Nutshell"         *)
(* by Tom Melham & Ashish Darbari, 2002 (still unpublished?)                 *)
(* ========================================================================= *)

parse_as_infix("&&",(16,"right"));;
parse_as_infix("<<=",(14,"right"));;
parse_as_infix(">->",(13,"right"));;
parse_as_infix(">~~>",(6,"right"));;

(* ------------------------------------------------------------------------- *)
(* Some type of nodes that we don't really care much about.                  *)
(* ------------------------------------------------------------------------- *)

let node_INDUCT,node_RECURSION = define_type
  "node = Node num";
; (* ------------------------------------------------------------------------- *) (* Also "abstract" propositional formulas (i.e. we never unfold "eval"). *) (* ------------------------------------------------------------------------- *)
let propform_INDUCT,propform_RECURSION = define_type
  "propform = Propform (num->bool)->bool";
;
let eval = new_recursive_definition propform_RECURSION
  `eval (Propform p) v = p v`;;
(* ------------------------------------------------------------------------- *) (* Quaternary lattice. *) (* ------------------------------------------------------------------------- *)
let quat_INDUCT,quat_RECURSION = define_type
 "quat = X | ZERO | ONE | TOP";
;
let quat_DISTINCT = prove_constructors_distinct quat_RECURSION;;
(* ------------------------------------------------------------------------- *) (* Basic lattice operations. *) (* ------------------------------------------------------------------------- *)
let qle = new_definition
  `x <<= y <=> x = X \/ y = TOP \/ x = y`;;
let qjoin = new_definition
  `x && y = if x <<= y then y else if y <<= x then x else TOP`;;
(* ------------------------------------------------------------------------- *) (* Trivial lemmas about the quaternary lattice. *) (* ------------------------------------------------------------------------- *)
let QLE_REFL = 
prove (`!x. x <<= x`,
REWRITE_TAC[qle]);;
let QLE_TRANS = 
prove (`!x y z. x <<= y /\ y <<= z ==> x <<= z`,
REPEAT(MATCH_MP_TAC quat_INDUCT THEN REPEAT CONJ_TAC) THEN REWRITE_TAC[qle; quat_DISTINCT]);;
let QLE_LJOIN = 
prove (`!x y z. x && y <<= z <=> x <<= z /\ y <<= z`,
REPEAT(MATCH_MP_TAC quat_INDUCT THEN REPEAT CONJ_TAC) THEN REWRITE_TAC[qjoin; qle; quat_DISTINCT]);;
let QLE_RJOIN = 
prove (`!x y. x <<= x && y /\ y <<= x && y`,
REPEAT(MATCH_MP_TAC quat_INDUCT THEN REPEAT CONJ_TAC) THEN REWRITE_TAC[qjoin; qle; quat_DISTINCT]);;
(* ------------------------------------------------------------------------- *) (* Choice expressions. *) (* ------------------------------------------------------------------------- *)
let choice = new_definition
  `b >-> x = if b then x else X`;;
let QLE_CHOICE = 
prove (`(b >-> x) <<= y <=> b ==> x <<= y`,
REPEAT GEN_TAC THEN REWRITE_TAC[choice] THEN COND_CASES_TAC THEN REWRITE_TAC[] THEN REWRITE_TAC[qle]);;
(* ------------------------------------------------------------------------- *) (* Basic type of trajectory formulas. *) (* ------------------------------------------------------------------------- *)
let trajform_INDUCT,trajform_RECURSION = define_type
 "trajform = Is_0 node
           | Is_1 node
           | Andj trajform trajform
           | When trajform propform
           | Next trajform";
; (* ------------------------------------------------------------------------- *) (* Semantics. *) (* ------------------------------------------------------------------------- *)
let tholds = new_recursive_definition trajform_RECURSION
  `(tholds (Is_0 nd) seq v <=> ZERO <<= seq 0 nd v) /\
   (tholds (Is_1 nd) seq v <=> ONE <<= seq 0 nd v) /\
   (tholds (Andj tf1 tf2) seq v <=> tholds tf1 seq v /\ tholds tf2 seq v) /\
   (tholds (When tf1 p) seq v <=> eval p v ==> tholds tf1 seq v) /\
   (tholds (Next(tf1)) seq v <=> tholds tf1 (\t. seq(t + 1)) v)`;;
(* ------------------------------------------------------------------------- *) (* Defining sequence. *) (* ------------------------------------------------------------------------- *)
let defseq = new_recursive_definition trajform_RECURSION
  `(defseq (Is_0 n) t nd v = ((n = nd) /\ (t = 0)) >-> ZERO) /\
   (defseq (Is_1 n) t nd v = ((n = nd) /\ (t = 0)) >-> ONE) /\
   (defseq (Andj tf1 tf2) t nd v = defseq tf1 t nd v && defseq tf2 t nd v) /\
   (defseq (When tf1 p) t nd v =  eval p v >-> defseq tf1 t nd v) /\
   (defseq (Next(tf1)) t nd v = ~(t = 0) >-> defseq tf1 (t - 1) nd v)`;;
(* ------------------------------------------------------------------------- *) (* Proof of the key property. *) (* ------------------------------------------------------------------------- *)
let DEFSEQ_MINIMAL = 
prove (`!tf seq v. tholds tf seq v <=> !t nd. defseq tf t nd v <<= seq t nd v`,
let cases_lemma = prove
   (`(!t. P t) <=> P 0 /\ !t. P(SUC t)`,MESON_TAC[num_CASES]) in
  MATCH_MP_TAC trajform_INDUCT THEN REWRITE_TAC[defseq; tholds] THEN
  REPEAT CONJ_TAC THENL
   [REPEAT GEN_TAC THEN REWRITE_TAC[QLE_CHOICE] THEN MESON_TAC[];
    REPEAT GEN_TAC THEN REWRITE_TAC[QLE_CHOICE] THEN MESON_TAC[];
    SIMP_TAC[QLE_LJOIN; FORALL_AND_THM];
    REWRITE_TAC[QLE_CHOICE] THEN MESON_TAC[];
    REPEAT STRIP_TAC THEN ONCE_REWRITE_TAC[cases_lemma] THEN
    ASM_REWRITE_TAC[QLE_CHOICE; NOT_SUC; ADD1; ADD_SUB]]);;
(* ------------------------------------------------------------------------- *) (* Notion of a trajectory w.r.t. a next-state function. *) (* ------------------------------------------------------------------------- *)
let trajectory = new_definition
  `trajectory next seq v <=> !t nd. next(seq t) nd v <<= seq (t + 1) nd v`;;
(* ------------------------------------------------------------------------- *) (* Defining trajectory of a formula. *) (* ------------------------------------------------------------------------- *)
let deftraj = new_recursive_definition num_RECURSION
  `(deftraj step tf 0 nd v = defseq tf 0 nd v) /\
   (deftraj step tf (SUC t) nd v =
        defseq tf (SUC t) nd v && step(deftraj step tf t) nd v)`;;
(* ------------------------------------------------------------------------- *) (* Obviously this is at least as strong as the defining sequence. *) (* ------------------------------------------------------------------------- *)
let DEFTRAJ_DEFSEQ = 
prove (`!tf t nd v. defseq tf t nd v <<= deftraj step tf t nd v`,
GEN_TAC THEN INDUCT_TAC THEN REWRITE_TAC[deftraj; QLE_REFL; QLE_RJOIN]);;
(* ------------------------------------------------------------------------- *) (* ...and it is indeed a trajectory. *) (* ------------------------------------------------------------------------- *)
let TRAJECTORY_DEFTRAJ = 
prove (`!step tf v. trajectory step (deftraj step tf) v`,
REPEAT GEN_TAC THEN REWRITE_TAC[trajectory] THEN REWRITE_TAC[GSYM ADD1; deftraj; QLE_RJOIN]);;
(* ------------------------------------------------------------------------- *) (* Monotonicity of next-state function. *) (* ------------------------------------------------------------------------- *)
let monotonic = new_definition
 `monotonic next v <=>
   !s1 s2. (!nd. s1 nd v <<= s2 nd v) ==> !nd. next s1 nd v <<= next s2 nd v`;;
(* ------------------------------------------------------------------------- *) (* Minimality property of defining trajectory (needs monotonicity). *) (* ------------------------------------------------------------------------- *)
let DEFTRAJ_MINIMAL = 
prove (`!step v. monotonic step v ==> !tf seq. trajectory step seq v ==> (tholds tf seq v <=> !t nd. deftraj step tf t nd v <<= seq t nd v)`,
REWRITE_TAC[monotonic; trajectory; RIGHT_IMP_FORALL_THM] THEN REPEAT STRIP_TAC THEN EQ_TAC THENL [ALL_TAC; MESON_TAC[DEFSEQ_MINIMAL; DEFTRAJ_DEFSEQ; QLE_TRANS]] THEN DISCH_TAC THEN INDUCT_TAC THEN REWRITE_TAC[deftraj; QLE_LJOIN] THEN ASM_MESON_TAC[DEFSEQ_MINIMAL; QLE_TRANS; ADD1]);;
(* ------------------------------------------------------------------------- *) (* Basic semantic notion in STE. *) (* ------------------------------------------------------------------------- *)
let ste = new_definition
  `(A >~~> C) ckt v <=>
      !seq. trajectory ckt seq v /\ tholds A seq v ==> tholds C seq v`;;
(* ------------------------------------------------------------------------- *) (* The "fundamental theorem of STE". *) (* ------------------------------------------------------------------------- *)
let STE_THM = 
prove (`monotonic ckt v ==> ((A >~~> C) ckt v <=> !t nd. defseq C t nd v <<= deftraj ckt A t nd v)`,