Theory Language_Prelims

section ‹Prelim›

text ‹ This theory contains some preliminary facts about reflective transistive closure and the comparisons of two symmetric distances, where the later is useful for Relative Security invariants›

theory Language_Prelims imports Main
begin


lemma length_1_butlast[simp]: "length xs = Suc 0  butlast xs = []"
by (cases xs, auto)

(* The distance between two sets *)

definition "dist A B  (A - B)  (B - A)"

definition "distL A B  (A - B)"

definition "distR A B  (B - A)"

lemma distLR_int_empt[simp]:"distL A B  distR A B = {} " 
  unfolding distR_def distL_def 
  by auto

lemma distLR_imp_dist:"distL A B  distL C D  distR A B  distR C D  dist A B  dist C D"
  unfolding dist_def distL_def distR_def 
  by auto


lemma dist_insert: "dist A B = dist C D  dist (insert x A) (insert x B) = dist (insert x C) (insert x D)"
  unfolding dist_def by auto

lemma dist_refl[simp,intro]: "dist A A = {}"
unfolding dist_def by auto

lemma dist_empty_iff[simp]: "dist A B = {}  A = B"
unfolding dist_def by auto


lemma dist_match_grow[simp,intro]:"
        dist ls3 ls4  dist ls1 ls2 
     x  dist (insert a ls3) (insert a ls4)  
     x  dist (insert a ls1) (insert a ls2)"
  unfolding dist_def by auto

lemma dist_ignore[simp,intro]:"
     dist ls3 ls4  dist ls1 ls2 
     x  dist (insert a ls3) (insert a ls4) 
     x  dist ls1 ls2"

  unfolding dist_def by auto

(*cases: if x is not in either or in both, then dist (insert x A) (insert x B) = dist A B
  otherwise x is in one but not the other, then dist (insert x A) (insert x B) = dist A B - {x}
                                           hence
                                                dist (insert x A) (insert x B) ⊆ dist A B

  thus 
          dist ls3 ls4 ⊆ dist ls1 ls2 ⟹
          dist (insert a ls3) (insert a ls4) ⊆ dist ls1 ls2
*)

lemma dist_insert_su[simp,intro]: "dist (insert x A) (insert x B)  dist A B"
  unfolding dist_def by auto

lemma dist_ignore_insert[simp,intro]:"
     dist ls3 ls4  dist ls1 ls2 
     dist (insert a ls3) (insert a ls4)  dist ls1 ls2"

  unfolding dist_def by auto

(*
lemma desired:"
        dist ls3 ls4 ⊆ dist ls1 ls2 ⟹
        dist (insert a ls3) (insert b ls4) ⊆ dist (insert a ls1) (insert b ls2)"
  ls3 = {}
  ls4 = {}
  ls1 = {a1}
  ls2 = {}
  a = a2
  b = a1
*)

(*a sufficiently powerful premise*)
lemma dist_match_diff[simp,intro]:"
        dist ls3 ls4  dist ls1 ls2 
        ls1  ls3  ls2  ls4 
        dist (insert a ls3) (insert b ls4)  dist (insert a ls1) (insert b ls2)"
  unfolding dist_def by auto

lemma list_one[intro]:"A  {a}  A  {a}  A = {}"
  by auto

lemma dist_match_grow_diff[simp,intro]:"
        dist ls3 ls4  dist ls1 ls2 
        ls1  ls3  ls2  ls4 
     x  dist (insert a ls3) (insert b ls4)  
     x  dist (insert a ls1) (insert b ls2)"
  unfolding dist_def by auto

lemma dist_match_grow_diff1[simp,intro]:"dist C D  dist A B 
    A  C 
    B  D 
    dist (insert a C) (insert b D)
     dist (insert a A) (insert b B)" 
  using dist_match_grow_diff subsetI by auto

lemma dist_eq_grow_ab:"dist C D  dist A B 
    A  C 
    B  D 
    dist (C  a) (D  b)
     dist (A  a) (B  b)" 
  unfolding dist_def by auto 

lemma dist_eq_grow:"
dist C D  dist A B  A  C  B  D 
dist (C  a) (D  a)  dist (A  a) (B  a)"
  using dist_eq_grow_ab by metis

lemma dist_ignore_grow:"
dist C D  dist A B  A  C  B  D 
dist (C  a) (D  a)  dist A B"
  unfolding dist_def by auto


(*distL intros*)

lemma distL_insert: "distL A B = distL C D  distL (insert x A) (insert x B) = distL (insert x C) (insert x D)"
  unfolding distL_def by auto

lemma distL_refl[simp,intro]: "distL A A = {}"
unfolding distL_def by auto

lemma distL_insert_su[simp,intro]: "distL (insert x A) (insert x B)  distL A B"
  unfolding distL_def by auto


(*distR intros*)
lemma distR_insert: "distR A B = distR C D  distR (insert x A) (insert x B) = distR (insert x C) (insert x D)"
  unfolding distR_def by auto

lemma distR_refl[simp,intro]: "distR A A = {}"
unfolding distR_def by auto

lemma distR_insert_su[simp,intro]: "distR (insert x A) (insert x B)  distR A B"
unfolding distR_def by auto




lemma insert_null_grow[simp]:"a  ls3  insert a ls3 = ls3" by auto

lemma distL_match_grow_aux:"distL ls3 ls4  distL ls1 ls2 
ls1  ls3 ls2  ls4 
        distL (insert a ls3) (insert b ls4)
      distL (insert a ls1) (insert b ls2)"
  unfolding distL_def
  apply (cases "a=b")
  subgoal by blast
  subgoal
    apply (cases "a  ls3", cases "b  ls4")  
    apply simp
      apply (cases "b  ls2")
    by (cases "b  ls2", auto) . 



lemma distR_match_grow_aux:"distR ls3 ls4  distR ls1 ls2 
ls1  ls3 ls2  ls4 
        distR (insert a ls3) (insert b ls4)
      distR (insert a ls1) (insert b ls2)"

unfolding distR_def
  apply (cases "a=b")
  subgoal by blast
  subgoal
    apply (cases "b  ls2")  
      apply (cases "a  ls2")
    by (cases "a  ls4", auto) .

lemma distL_match_grow: "distL ls3 ls4  distL ls1 ls2 
ls1  ls3 ls2  ls4  (ls1 = ls3  ls2 = ls4) 
        distL (insert a ls3) (insert b ls4)
      distL (insert a ls1) (insert b ls2)"
  apply(cases "ls1 = ls3")
  subgoal by (metis Diff_mono Set.insert_mono distL_def)
  subgoal apply(cases "ls2 = ls4") by (simp add: distL_match_grow_aux)+ .


lemma distR_match_grow:"distR ls3 ls4  distR ls1 ls2 
ls1  ls3 ls2  ls4  (ls1 = ls3  ls2 = ls4) 
        distR (insert a ls3) (insert b ls4)
      distR (insert a ls1) (insert b ls2)"
  apply(cases "ls1 = ls3")
  subgoal by (metis Diff_mono Set.insert_mono distR_def)
  subgoal apply(cases "ls2 = ls4") by (simp add: distR_match_grow_aux)+ .

definition Dist where "Dist ls1 ls2 ls3 ls4 =
 (Language_Prelims.dist ls3 ls4  Language_Prelims.dist ls1 ls2  ls1  ls3  ls2  ls4)"

lemmas Dist_defs = Dist_def dist_def

lemma Dist_neq[simp]:"Dist ls1 ls2 ls3 ls4  ls3  ls4  ls1  ls2"
  unfolding Dist_def by auto

lemma Dist_eq[simp]:"Dist A B A B" by (simp add: Dist_def)
(*istate*)
lemma Dist_emp[simp]:"Dist {} {} {} {}" by (simp add: Dist_def)

(*for match*)
lemma Dist_match[intro]:"Dist ls1 ls2 ls3 ls4  Dist (insert a ls1) (insert b ls2) (insert a ls3) (insert b ls4)"
  by (metis Dist_def Set.insert_mono dist_match_grow_diff1)

lemma Dist_match_un[intro]:"Dist ls1 ls2 ls3 ls4  Dist (ls1  a) (ls2  b) (ls3  a) (ls4  b)"
  unfolding Dist_def by (metis dist_eq_grow_ab subset_refl sup_mono)

(*for ignore*)
lemma Dist_ignore[intro]:"Dist ls1 ls2 ls3 ls4  Dist ls1 ls2 (insert a ls3) (insert a ls4)"
  by (meson Dist_def dist_insert_su dual_order.trans subset_insertI)

lemma Dist_ignore_un[intro]:"Dist ls1 ls2 ls3 ls4  Dist ls1 ls2 (ls3  a) (ls4  a)"
  unfolding Dist_def by (simp add: dist_ignore_grow le_supI1)

(* Various reflexive-transitive closure operators *)

inductive
  star :: "('a  'a  bool)  'a  'a  bool"
for r where
refl:  "star r x x" |
step:  "r x y  star r y z  star r x z"

hide_fact (open) refl step  ― ‹names too generic›

lemma star_trans:
  "star r x y  star r y z  star r x z"
proof(induction rule: star.induct)
  case refl thus ?case .
next
  case step thus ?case by (metis star.step)
qed

lemmas star_induct =
  star.induct[of "r:: 'a*'b  'a*'b  bool", split_format(complete)]

lemmas star_induct4 =
  star.induct[of "r:: 'a*'b'*'c*'d  'a*'b'*'c*'d  bool", split_format(complete)]

declare star.refl[simp,intro]

lemma star_step1[simp, intro]: "r x y  star r x y"
by(metis star.refl star.step)

code_pred star .

(* *)

inductive
  starn :: "('a  'a  bool)  nat  'a  'a  bool"
for r where
refl:  "starn r 0 x x" |
step:  "r x y  starn r n y z  starn r (Suc n)x z"

hide_fact (open) refl step  ― ‹names too generic›

lemma starn_trans:
  "starn r m x y  starn r n y z  starn r (m+n) x z"
proof(induction rule: starn.induct)
  case refl thus ?case by simp
next
  case step thus ?case by simp (metis starn.step)
qed

lemmas starn_induct =
  starn.induct[of "r:: 'a*'b  'a*'b  bool", split_format(complete)]

declare starn.refl[simp,intro]

lemma starn_step1[simp, intro]: "r x y  starn r (Suc 0) x y"
by(metis starn.refl starn.step)

code_pred starn .

lemma star_starn: "star r x y  n. starn r n x y"
by (induct rule: star.induct, auto intro: starn.intros)

lemma starn_star: "starn r n x y  star r x y"
by (induct rule: starn.induct, auto intro: star.intros)

lemma star_iff_starn: "star r x y  (n. starn r n x y)"
by (meson star_starn starn_star)

(* *)

inductive
  starl :: "('a  'c  'a  bool)  'a  'c list  'a  bool"
for r where
refl:  "starl r x [] x" |
step:  "r x c y  starl r y cs z  starl r x (c#cs) z"

hide_fact (open) refl step  ― ‹names too generic›

lemma starl_trans:
  "starl r x cs y  starl r y ds z  starl r x (cs @ ds) z"
proof(induction rule: starl.induct)
  case refl thus ?case by simp
next
  case step thus ?case by simp (metis starl.step)
qed

lemmas starl_induct =
  starl.induct[of "r:: 'a*'b  'clist  'a*'b  bool", split_format(complete)]

declare starl.refl[simp,intro]

lemma starl_step1[simp, intro]: "r x c y  starl r x [c] y"
by(metis starl.refl starl.step)

lemma starl_snoc:
  "starl r x cs y  r y c z  starl r x (cs @ [c]) z"
by (simp add: starl_trans)

code_pred starl .

definition "final r x  y. ¬ r x y"

lemma final_star_eq: "final r x  star r x y  x = y"
by (metis final_def star.cases)

definition "lfinal r x  y cs. ¬ r x cs y"


end