Theory FWLifting

(*  Title:      JinjaThreads/Framework/FWLifting.thy
    Author:     Andreas Lochbihler
*)

section ‹Lifting of thread-local properties to the multithreaded case›

theory FWLifting
imports
  FWWellform
begin

text‹Lifting for properties that only involve thread-local state information and the shared memory.›

definition
  ts_ok :: "('t  'x  'm  bool)  ('l, 't,'x) thread_info  'm  bool"
where
  "ln. ts_ok P ts m  t. case (ts t) of None  True | (x, ln)  P t x m"

lemma ts_okI:
  " t x ln. ts t = (x, ln)  P t x m   ts_ok P ts m"
by(auto simp add: ts_ok_def)

lemma ts_okE:
  " ts_ok P ts m;  t x ln. ts t = (x, ln)  P t x m   Q   Q"
by(auto simp add: ts_ok_def)

lemma ts_okD:
  "ln.  ts_ok P ts m; ts t = (x, ln)   P t x m"
by(auto simp add: ts_ok_def)

lemma ts_ok_True [simp]:
  "ts_ok (λt m x. True) ts m"
by(auto intro: ts_okI)

lemma ts_ok_conj:
  "ts_ok (λt x m. P t x m  Q t x m) = (λts m. ts_ok P ts m  ts_ok Q ts m)"
by(auto intro: ts_okI intro!: ext dest: ts_okD)

lemma ts_ok_mono:
  " ts_ok P ts m; t x. P t x m  Q t x m   ts_ok Q ts m"
by(auto intro!: ts_okI dest: ts_okD)

text‹Lifting for properites, that also require additional data that does not change during execution›

definition
  ts_inv :: "('i  't  'x  'm  bool)  ('t  'i)  ('l,'t,'x) thread_info  'm  bool"
where
  "ln. ts_inv P I ts m  t. case (ts t) of None  True | (x, ln)  i. I t = i  P i t x m" 

lemma ts_invI:
  " t x ln. ts t = (x, ln)  i. I t = i  P i t x m   ts_inv P I ts m"
by(simp add: ts_inv_def)

lemma ts_invE:
  " ts_inv P I ts m; t x ln. ts t = (x, ln)  (i. I t = i  P i t x m)  R   R"
by(auto simp add: ts_inv_def)

lemma ts_invD:
  "ln.  ts_inv P I ts m; ts t = (x, ln)   i. I t = i  P i t x m"
by(auto simp add: ts_inv_def)

text ‹Wellformedness properties for lifting›

definition
  ts_inv_ok :: "('l,'t,'x) thread_info  ('t  'i)  bool"
where
  "ts_inv_ok ts I  t. ts t = None  I t = None"

lemma ts_inv_okI:
  "(t. ts t = None  I t = None)  ts_inv_ok ts I"
by(clarsimp simp add: ts_inv_ok_def)

lemma ts_inv_okI2:
  "(t. (v. ts t = v)  (v. I t = v))  ts_inv_ok ts I"
by(force simp add: ts_inv_ok_def)

lemma ts_inv_okE:
  " ts_inv_ok ts I; t. ts t = None  I t = None  P   P"
by(force simp add: ts_inv_ok_def)

lemma ts_inv_okE2:
  " ts_inv_ok ts I; t. (v. ts t = v)  (v. I t = v)  P   P"
by(force simp add: ts_inv_ok_def)

lemma ts_inv_okD:
  "ts_inv_ok ts I  (ts t = None)  (I t = None)"
by(erule ts_inv_okE, blast)

lemma ts_inv_okD2:
  "ts_inv_ok ts I  (v. ts t = v)  (v. I t = v)"
by(erule ts_inv_okE2, blast)

lemma ts_inv_ok_conv_dom_eq:
  "ts_inv_ok ts I  (dom ts = dom I)"
proof -
  have "ts_inv_ok ts I  (t. ts t = None  I t = None)"
    unfolding ts_inv_ok_def by blast
  also have "  (t. t  - dom ts  t  - dom I)" by(force)
  also have "  dom ts = dom I" by auto
  finally show ?thesis .
qed

lemma ts_inv_ok_upd_ts:
  " ts t = x; ts_inv_ok ts I   ts_inv_ok (ts(t  x')) I"
by(auto dest!: ts_inv_okD intro!: ts_inv_okI split: if_splits)

lemma ts_inv_upd_map_option:
  assumes "ts_inv P I ts m"
  and "x ln. ts t = (x, ln)  P (the (I t)) t (fst (f (x, ln))) m"
  shows "ts_inv P I (ts(t := (map_option f (ts t)))) m"
using assms
by(fastforce intro!: ts_invI split: if_split_asm dest: ts_invD)

fun upd_inv :: "('t  'i)  ('i  't  'x  'm  bool)  ('t,'x,'m) new_thread_action  ('t  'i)"
where
  "upd_inv I P (NewThread t x m) = I(t  SOME i. P i t x m)"
| "upd_inv I P _ = I"

fun upd_invs :: "('t  'i)  ('i  't  'x  'm  bool)  ('t,'x,'m) new_thread_action list  ('t  'i)"
where
  "upd_invs I P [] = I"
| "upd_invs I P (ta#tas) = upd_invs (upd_inv I P ta) P tas"

lemma upd_invs_append [simp]:
  "upd_invs I P (xs @ ys) = upd_invs (upd_invs I P xs) P ys"
by(induct xs arbitrary: I)(auto)

lemma ts_inv_ok_upd_inv':
 "ts_inv_ok ts I  ts_inv_ok (redT_updT' ts ta) (upd_inv I P ta)"
by(cases ta)(auto intro!: ts_inv_okI elim: ts_inv_okD del: iffI)

lemma ts_inv_ok_upd_invs':
  "ts_inv_ok ts I  ts_inv_ok (redT_updTs' ts tas) (upd_invs I P tas)"
proof(induct tas arbitrary: ts I)
  case Nil thus ?case by simp
next
  case (Cons TA TAS TS I)
  note IH = ts I. ts_inv_ok ts I  ts_inv_ok (redT_updTs' ts TAS) (upd_invs I P TAS)
  note esok = ts_inv_ok TS I
  from esok have "ts_inv_ok (redT_updT' TS TA) (upd_inv I P TA)"
    by -(rule ts_inv_ok_upd_inv')
  hence "ts_inv_ok (redT_updTs' (redT_updT' TS TA) TAS) (upd_invs (upd_inv I P TA) P TAS)"
    by (rule IH)
  thus ?case by simp
qed

lemma ts_inv_ok_upd_inv:
 "ts_inv_ok ts I  ts_inv_ok (redT_updT ts ta) (upd_inv I P ta)"
apply(cases ta)
apply(auto intro!: ts_inv_okI elim: ts_inv_okD del: iffI)
done

lemma ts_inv_ok_upd_invs:
  "ts_inv_ok ts I  ts_inv_ok (redT_updTs ts tas) (upd_invs I P tas)"
proof(induct tas arbitrary: ts I)
  case Nil thus ?case by simp
next
  case (Cons TA TAS TS I)
  note IH = ts I. ts_inv_ok ts I  ts_inv_ok (redT_updTs ts TAS) (upd_invs I P TAS)
  note esok = ts_inv_ok TS I
  from esok have "ts_inv_ok (redT_updT TS TA) (upd_inv I P TA)"
    by -(rule ts_inv_ok_upd_inv)
  hence "ts_inv_ok (redT_updTs (redT_updT TS TA) TAS) (upd_invs (upd_inv I P TA) P TAS)"
    by (rule IH)
  thus ?case by simp
qed

lemma ts_inv_ok_inv_ext_upd_inv:
  " ts_inv_ok ts I; thread_ok ts ta   I m upd_inv I P ta"
by(cases ta)(auto intro!: map_le_same_upd dest: ts_inv_okD)

lemma ts_inv_ok_inv_ext_upd_invs:
  " ts_inv_ok ts I; thread_oks ts tas
   I m upd_invs I P tas"
proof(induct tas arbitrary: ts I)
  case Nil thus ?case by simp
next
  case (Cons TA TAS TS I)
  note IH = ts I.  ts_inv_ok ts I; thread_oks ts TAS  I m upd_invs I P TAS
  note esinv = ts_inv_ok TS I
  note cct = thread_oks TS (TA # TAS)
  from esinv cct have "I m upd_inv I P TA"
    by(auto intro: ts_inv_ok_inv_ext_upd_inv)
  also from esinv cct have "ts_inv_ok (redT_updT' TS TA) (upd_inv I P TA)"
    by(auto intro: ts_inv_ok_upd_inv')
  with cct have "upd_inv I P TA m upd_invs (upd_inv I P TA) P TAS"
    by(auto intro: IH)
  finally show ?case by simp
qed

lemma upd_invs_Some:
  " thread_oks ts tas; I t = i; ts t = x   upd_invs I Q tas t = i"
proof(induct tas arbitrary: ts I)
  case Nil thus ?case by simp
next
  case (Cons TA TAS TS I)
  note IH = ts I. thread_oks ts TAS; I t = i; ts t = x  upd_invs I Q TAS t = i
  note cct = thread_oks TS (TA # TAS)
  note it = I t = i
  note est = TS t = x
  from cct have cctta: "thread_ok TS TA"
    and ccttas: "thread_oks (redT_updT' TS TA) TAS" by auto
  from cctta it est have "upd_inv I Q TA t = i"
    by(cases TA, auto)
  moreover
  have "redT_updT' TS TA t = x" using cctta est
    by - (rule redT_updT'_Some) 
  ultimately have "upd_invs (upd_inv I Q TA) Q TAS t = i" using ccttas
    by -(erule IH)
  thus ?case by simp
qed

lemma upd_inv_Some_eq:
  " thread_ok ts ta; ts t = x   upd_inv I Q ta t = I t"
by(cases ta, auto)

lemma upd_invs_Some_eq: " thread_oks ts tas; ts t = x   upd_invs I Q tas t = I t"
proof(induct tas arbitrary: ts I)
  case Nil thus ?case by simp
next
  case (Cons TA TAS TS I)
  note IH = ts I. thread_oks ts TAS; ts t = x  upd_invs I Q TAS t = I t
  note cct = thread_oks TS (TA # TAS)
  note est = TS t = x
  from cct est have "upd_invs (upd_inv I Q TA) Q TAS t = upd_inv I Q TA t"
    apply(clarsimp)
    apply(erule IH)
    by(rule redT_updT'_Some)
  also from cct est have " = I t" 
    by(auto elim: upd_inv_Some_eq)
  finally show ?case by simp
qed

lemma SOME_new_thread_upd_invs:
  assumes Qsome: "Q (SOME i. Q i t x m) t x m"
  and nt: "NewThread t x m  set tas"
  and cct: "thread_oks ts tas"
  shows "i. upd_invs I Q tas t = i  Q i t x m"
proof(rule exI[where x="SOME i. Q i t x m"])
  from nt cct have "upd_invs I Q tas t = SOME i. Q i t x m"
  proof(induct tas arbitrary: ts I)
    case Nil thus ?case by simp
  next
    case (Cons TA TAS TS I)
    note IH = ts I.  NewThread t x m  set TAS; thread_oks ts TAS   upd_invs I Q TAS t = SOME i. Q i t x m
    note nt = NewThread t x m  set (TA # TAS)
    note cct = thread_oks TS (TA # TAS)
    { assume nt': "NewThread t x m  set TAS"
      from cct have ?case
        apply(clarsimp)
        by(rule IH[OF nt']) }
    moreover
    { assume ta: "TA = NewThread t x m"
      with cct have rup: "redT_updT' TS TA t = (undefined, no_wait_locks)"
        by(simp)
      from cct have cctta: "thread_oks (redT_updT' TS TA) TAS" by simp
      from ta have "upd_inv I Q TA t = SOME i. Q i t x m"
        by(simp)
      hence ?case 
        by(clarsimp simp add: upd_invs_Some_eq[OF cctta, OF rup]) }
    ultimately show ?case using nt by auto
  qed
  with Qsome show "upd_invs I Q tas t = SOME i. Q i t x m  Q (SOME i. Q i t x m) t x m"
    by(simp)
qed

lemma ts_ok_into_ts_inv_const:
  assumes "ts_ok P ts m"
  obtains I where "ts_inv (λ_. P) I ts m"
proof -
  from assms have "ts_inv (λ_. P) (λt. if t  dom ts then Some undefined else None) ts m"
    by(auto intro!: ts_invI dest: ts_okD)
  thus thesis by(rule that)
qed

lemma ts_inv_const_into_ts_ok:
  "ts_inv (λ_. P) I ts m  ts_ok P ts m"
by(auto intro!: ts_okI dest: ts_invD)

lemma ts_inv_into_ts_ok_Ex:
  "ts_inv Q I ts m  ts_ok (λt x m. i. Q i t x m) ts m"
by(rule ts_okI)(blast dest: ts_invD)

lemma ts_ok_Ex_into_ts_inv:
  "ts_ok (λt x m. i. Q i t x m) ts m  I. ts_inv Q I ts m"
by(rule exI[where x="λt. SOME i. Q i t (fst (the (ts t))) m"])(auto 4 4 dest: ts_okD intro: someI intro: ts_invI)

lemma Ex_ts_inv_conv_ts_ok:
  "(I. ts_inv Q I ts m)  (ts_ok (λt x m. i. Q i t x m) ts m)"
by(auto dest: ts_inv_into_ts_ok_Ex ts_ok_Ex_into_ts_inv)

end