parse_as_infix(";;",(18,"right"));;
 (c2:(S->bool)->(S->bool)) = c1 o c2`;;
let if_def = new_definition
 `If e (c:(S->bool)->(S->bool)) q = {s | if e s then c q s else q s}`;;let ite_def = new_definition
 `Ite e (c1:(S->bool)->(S->bool)) c2 q =
    {s | if e s then c1 q s else c2 q s}`;;let while_def = new_definition
 `While e c q =
    {s | !w. (!s:S. (if e(s) then c w s else q s) ==> w s) ==> w s}`;;let MONOTONIC_SEQ = prove
 (`monotonic c1 /\ monotonic c2 ==> monotonic (c1 ;; c2)`,
  REWRITE_TAC[monotonic; sequence; 
o_THM] THEN SET_TAC[]);;
 
let WHILE_THM = prove
 (`!e c q:S->bool.
    monotonic c
    ==> (!s. If e (c ;; While e c) q s ==> While e c q s) /\
        (!w'. (!s. If e (c ;; (\q. w')) q s ==> w' s)
              ==> (!a. While e c q a ==> w' a)) /\
        (!s. While e c q s <=> If e (c ;; While e c) q s)`,
  REPEAT GEN_TAC THEN DISCH_TAC THEN
  (MP_TAC o GEN_ALL o DISCH_ALL o derive_nonschematic_inductive_relations)
   `!s:S. (if e s then c w s else q s) ==> w s` THEN
  REWRITE_TAC[
if_def; sequence; 
o_THM; 
IN_ELIM_THM; IMP_IMP] THEN
  DISCH_THEN MATCH_MP_TAC THEN
  REWRITE_TAC[
FUN_EQ_THM; 
while_def; 
IN_ELIM_THM] THEN
  POP_ASSUM MP_TAC THEN REWRITE_TAC[monotonic] THEN SET_TAC[]);;
 
let CORRECT_POSTWEAK = prove
 (`!p c q q'. monotonic c /\ correct p c q' /\ q' 
SUBSET q ==> correct p c q`,
  REWRITE_TAC[correct; monotonic] THEN SET_TAC[]);;
 
let CORRECT_SEQ = prove
 (`!p q r c1 c2.
        monotonic c1 /\ correct p c1 r /\ correct r c2 q
        ==> correct p (c1 ;; c2) q`,
  REWRITE_TAC[correct; sequence; monotonic; 
o_THM] THEN SET_TAC[]);;
 
let CORRECT_WHILE = prove
 (`!(<<) p c q e invariant.
      monotonic c /\
      
WF(<<) /\
      p 
SUBSET invariant /\
      (
UNIV DIFF e) 
INTER invariant 
SUBSET q /\
      (!X:S. correct (invariant 
INTER e 
INTER (\s. X = s)) c
                     (invariant 
INTER (\s. s << X)))
      ==> correct p (While e c) q`,
  REWRITE_TAC[correct; 
SUBSET; 
IN_INTER; 
IN_UNIV; 
IN_DIFF; 
IN] THEN
  REPEAT GEN_TAC THEN STRIP_TAC THEN
  SUBGOAL_THEN `!s:S. invariant s ==> While e c q s` MP_TAC THENL
   [ALL_TAC; ASM_MESON_TAC[]] THEN
  FIRST_ASSUM(MATCH_MP_TAC o REWRITE_RULE[
WF_IND]) THEN
  X_GEN_TAC `s:S` THEN REPEAT DISCH_TAC THEN
  FIRST_ASSUM(fun th -> ONCE_REWRITE_TAC[MATCH_MP 
WHILE_FIX th]) THEN
  REWRITE_TAC[
if_def; sequence; 
o_THM; 
IN_ELIM_THM] THEN
  COND_CASES_TAC THENL [ALL_TAC; ASM_MESON_TAC[]] THEN
  FIRST_X_ASSUM(MP_TAC o SPECL [`s:S`; `s:S`]) THEN ASM_REWRITE_TAC[] THEN
  FIRST_X_ASSUM(MP_TAC o GEN_REWRITE_RULE I [monotonic]) THEN
  REWRITE_TAC[
SUBSET; 
IN; 
RIGHT_IMP_FORALL_THM] THEN
  DISCH_THEN MATCH_MP_TAC THEN ASM_SIMP_TAC[
INTER; 
IN_ELIM_THM; 
IN]);;
 
let assert_def = new_definition
 `assert (p:S->bool) (q:S->bool) = q`;;
let variant_def = new_definition
 `variant ((<<):S->S->bool) (q:S->bool) = q`;;
let CORRECT_SEQ_VC = prove
 (`!p q r c1 c2.
        monotonic c1 /\ correct p c1 r /\ correct r c2 q
        ==> correct p (c1 ;; assert r ;; c2) q`,
  REWRITE_TAC[correct; sequence; monotonic; 
assert_def; 
o_THM] THEN SET_TAC[]);;