theory localesDef imports cache
begin

locale pRule0VsPInv0=
  fixes paraRule ::"  rule"  and paraInv::"formula "
  assumes

  b:"
  invHoldForRule' s   (paraInv) (paraRule )  (invariants N) "
begin
theorem  pRule0VsPInv0:

  shows "invHoldForRule' s   (paraInv) (paraRule  )   (invariants N) "
  by(cut_tac a1 b,auto)
end

locale pRule0VspInv1=
  fixes paraRule ::"rule"  and paraInv::"nat\<Rightarrow>formula "
  and iInv1::"nat"   and N::"nat"
  assumes
  b:"invHoldForRule' s   (paraInv iInv1) (paraRule)  invariants  "
begin
theorem  pRule10VspInv1:
   assumes a1:"iInv1 \<le> N"

  shows "invHoldForRule' s   (paraInv iInv1) (paraRule )   invariants  "
  by(cut_tac a1 b,auto)
end

locale pRule0VsPInv2=
  fixes paraRule ::"  rule"  and paraInv::"nat\<Rightarrow>nat\<Rightarrow>formula "  and iInv1::"nat" and iInv2::"nat" and N::"nat" and  invariants::"formula set"
  assumes

  b:" invHoldForRule' s  (paraInv iInv1 iInv2) (paraRule)  invariants  "
begin
theorem  pRule0VsPInv2:
    assumes  a2:" iInv1 \<le> N " and a3:"iInv2 \<le> N "
  and a4:"iInv1 \<noteq> iInv2"

  shows "invHoldForRule' s  (paraInv iInv1 iInv2) (paraRule )   invariants "

  by(cut_tac a1 b,auto)
end

locale pRule0VsPInv3=
  fixes paraRule ::"  rule"  and paraInv::"nat\<Rightarrow>nat\<Rightarrow>nat\<Rightarrow>formula "  and iInv1::"nat" and iInv2::"nat"
  and iInv3::"nat"  and N::"nat" and  invariants::"formula set"
  assumes  a2:" iInv1 \<le> N " and a3:"iInv2 \<le> N " and a4:"iInv3 \<le> N "
  and a5:"iInv1 \<noteq> iInv2" and a6:"iInv1 \<noteq> iInv3" and a7:"iInv2 \<noteq> iInv3" and

  b:" invHoldForRule' s  (paraInv iInv1 iInv2 iInv3) (paraRule)  invariants  "
begin
theorem  pRule0VsPInv2:

  shows "invHoldForRule' s  (paraInv iInv1 iInv2 iInv3) (paraRule )   invariants "

  by(cut_tac  b,auto)
end

locale pRule1VsPInv0=
  fixes paraRule ::"nat \<Rightarrow>  rule"  and paraInv::"formula "
  and iRule1::"nat"   and N::"nat"  and  invariants::"formula set"
  assumes
  b:"
  invHoldForRule' s   (paraInv) (paraRule iRule1)  invariants "
begin
theorem  pRule1VsPInv0:
   assumes
  a1:"iRule1 \<le> N "

  shows "invHoldForRule' s   (paraInv) (paraRule iRule1 )   invariants "
  (is "?P paraInv  paraRule iRule1    invs")
  by(cut_tac a1 b,auto)
end

locale pRule1VspInv1=
  fixes paraRule ::"nat \<Rightarrow> rule"  and paraInv::"nat \<Rightarrow> formula "
  and iRule::"nat" and iInv1::"nat"  and N::"nat"  and  invariants::"formula set"
  assumes

  b:" iRule = iInv1 \<longrightarrow>
  (invHoldForRule' s   (paraInv iInv1) (paraRule iRule)  invariants )"  and
  c:"  iRule \<noteq> iInv1 \<longrightarrow>
  (invHoldForRule' s   (paraInv iInv1) (paraRule iRule)  invariants  )"
begin
theorem pRule1VspInv1:
  assumes
   a1:"iRule \<le> N"  and a2:" iInv1 \<le> N "
  shows "(invHoldForRule' s   (paraInv iInv1) (paraRule iRule)  invariants  )"
    (is "?P paraInv iInv1 paraRule iRule  invariants")
  proof -
   have e2:"iRule=iInv1  \<or> iRule \<noteq> iInv1 "  by auto

   moreover
   {assume e3:" iRule=iInv1 "

     have "?P paraInv iInv1 paraRule iRule  invariants"
       by (metis a1 a2 b e3)
   }
   moreover
   {assume e3:"iRule\<noteq>iInv1 "
     have "?P paraInv iInv1 paraRule iRule  invariants "
       by (metis a1 a2 c e3)
   }
   ultimately show "?P paraInv iInv1 paraRule iRule  invariants "
     by blast
 qed
end

 locale pRule1VspInv2=
  fixes paraRule ::"nat \<Rightarrow> rule"  and paraInv::"nat \<Rightarrow> nat\<Rightarrow>formula "
  and iRule::"nat" and iInv1::"nat" and iInv2::"nat" and N::"nat"   and  invariants::"formula set"

  assumes
  b:"iRule \<le> N\<longrightarrow> iInv1 \<le> N \<longrightarrow>iInv2 \<le> N\<longrightarrow>iInv1 \<noteq> iInv2 \<longrightarrow> iRule = iInv1\<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule)  invariants "  and
  c:"iRule \<le> N\<longrightarrow> iInv1 \<le> N \<longrightarrow>iInv2 \<le> N\<longrightarrow>iInv1 \<noteq> iInv2 \<longrightarrow>iRule = iInv2 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule) invariants"  and
  d:"iRule \<le> N\<longrightarrow> iInv1 \<le> N \<longrightarrow>iInv2 \<le> N\<longrightarrow>iInv1 \<noteq> iInv2 \<longrightarrow>iRule \<noteq> iInv1 \<longrightarrow>iRule \<noteq> iInv2 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule)  invariants"
begin
theorem  pRule1VspInv2:
 assumes  a1:"iRule \<le> N"  and a2:" iInv1 \<le> N " and a3:"iInv2 \<le> N "and a4:"iInv1 \<noteq> iInv2"

  shows "invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule)   invariants "  (is "?P paraInv iInv paraRule iRule  invs")
  proof -
   have d2:"iRule=iInv1 \<or> iRule=iInv2 \<or> ((iRule \<noteq> iInv1) \<and> (iRule\<noteq>iInv2))"  by auto
   moreover
   {assume e1:"iRule=iInv1"
     have "?P paraInv iInv paraRule iRule  invs "
       by (metis  a2 a3 a4 b e1)

   }

   moreover
   {assume e1:"iRule = iInv2"
     have "?P paraInv iInv paraRule iRule  invs"
       by (metis  a2 a3 a4 c e1)
   }

   moreover
   {assume e1:"iRule\<noteq>iInv1 \<and> iRule\<noteq>iInv2"
     have "?P paraInv iInv paraRule iRule  invs"
       by (metis  a1 a2 a3 a4 d e1)

   }
   ultimately show "?P paraInv iInv paraRule iRule  invs"
     by blast
 qed
end

locale pRule1VspInv3=
  fixes paraRule ::"nat \<Rightarrow> rule"  and paraInv::"nat \<Rightarrow> nat\<Rightarrow>nat\<Rightarrow>formula "
  and iRule::"nat" and iInv1::"nat" and iInv2::"nat" and iInv3::"nat" and N::"nat"   and  invariants::"formula set"
  assumes
  b:"iRule = iInv1 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule)  invariants "  and
  c:" iRule = iInv2 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule) invariants"  and
  d:"  iRule = iInv3 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule)  invariants" and

  e:" iRule \<noteq> iInv1 \<longrightarrow>iRule \<noteq> iInv2 \<longrightarrow> iRule \<noteq> iInv3 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule)  invariants"
begin
theorem  pRule1VspInv3:
  assumes a1:"iRule \<le> N"  and a2:" iInv1 \<le> N " and a3:"iInv2 \<le> N " and a4:"iInv3 \<le> N "
  and a5:"iInv1 \<noteq> iInv2"  and a6:"iInv1 \<noteq> iInv3"   and a7:"iInv2 \<noteq> iInv3"
  shows "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule)   invariants "
  proof -
   have d2:"iRule=iInv1 \<or> iRule=iInv2 \<or> iRule=iInv3 \<or> ((iRule \<noteq> iInv1) \<and> (iRule\<noteq>iInv2) \<and> iRule \<noteq> iInv3 )"  by auto
   moreover
   {assume e1:"iRule=iInv1"
     have "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule)   invariants "
       by (cut_tac b e1, auto)

   }
   moreover
   {assume e1:"iRule = iInv2"
     have "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule)   invariants "
       by (cut_tac c e1,auto)
   }

   moreover
   {assume e1:"iRule = iInv3"
     have "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule)   invariants "
       by (cut_tac  d  e1,auto)

   }

   moreover
   {assume e1:"iRule\<noteq>iInv1 \<and> iRule\<noteq>iInv2 \<and> iRule\<noteq>iInv3"
      have "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule)   invariants "
      by (metis e e1)

   }
   ultimately show "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule)   invariants "
     by blast
 qed
end

locale paraRuleInstValidateExLessInvInst=
  fixes paraRule ::"nat \<Rightarrow> rule"  and paraInv::"nat \<Rightarrow> formula "
  and iRule::"nat" and iInv1::"nat"  and N::"nat"
  assumes
  b:"iRule \<le> N \<longrightarrow>iInv1 \<le> N\<longrightarrow> iRule = iInv1 \<longrightarrow>
  (invHoldForRule' s  (paraInv iInv1) (paraRule iRule)  invariants )"  and
  c:"iRule \<le> N \<longrightarrow>iInv1 \<le> N\<longrightarrow>  iRule \<noteq> iInv1 \<longrightarrow>
  (invHoldForRule' s  (paraInv iInv1) (paraRule iRule)  invariants  )"
begin
theorem paraRuleInstValidateExLessInvInst:
  assumes a1:"iRule \<le> N"  and a2:" iInv1 \<le> N "
  shows "(invHoldForRule' s  (paraInv iInv1) (paraRule iRule)  invariants  )"
    (is "?P paraInv iInv1 paraRule iRule  invariants")
  proof -
   have e2:"iRule=iInv1  \<or> iRule \<noteq> iInv1 "  by auto

   moreover
   {assume e3:" iRule=iInv1 "

     have "?P paraInv iInv1 paraRule iRule  invariants"
       by (metis a1 a2 b e3)
   }
   moreover
   {assume e3:"iRule\<noteq>iInv1 "
     have "?P paraInv iInv1 paraRule iRule  invariants "
       by (metis a1 a2 c e3)
   }
   ultimately show "?P paraInv iInv1 paraRule iRule  invariants "
     by blast
 qed
end

locale paraRuleInstValidateExTwoLessInvInst=
  fixes paraRule ::"nat \<Rightarrow> rule"  and paraInv::"nat \<Rightarrow> nat\<Rightarrow>formula "
  and iRule::"nat" and iInv1::"nat" and iInv2::"nat" and N::"nat"
  assumes
  b:"iInv1 \<noteq> iInv2\<longrightarrow>iRule \<le> N \<longrightarrow>iInv1 \<le> N\<longrightarrow>iInv2 \<le> N\<longrightarrow>iRule = iInv1 \<longrightarrow>
  invHoldForRule' s  (paraInv iInv1 iInv2) (paraRule iRule)  invariants "  and
  c:"iInv1 \<noteq> iInv2\<longrightarrow>iRule \<le> N \<longrightarrow>iInv1 \<le> N\<longrightarrow>iInv2 \<le> N\<longrightarrow>iRule = iInv2 \<longrightarrow>
  invHoldForRule' s  (paraInv iInv1 iInv2) (paraRule iRule) invariants"  and
  d:"iInv1 \<noteq> iInv2\<longrightarrow>iRule \<le> N \<longrightarrow>iInv1 \<le> N\<longrightarrow>iInv2 \<le> N\<longrightarrow>iRule \<noteq> iInv1 \<longrightarrow>iRule \<noteq> iInv2 \<longrightarrow>
  invHoldForRule' s  (paraInv iInv1 iInv2) (paraRule iRule)  invariants"
begin
theorem paraRuleInstValidateExTwoLessInvInst:
  assumes a1:"iRule \<le> N"  and a2:" iInv1 \<le> N " and a3:"iInv2 \<le> N "
  and a4:"iInv1 \<noteq> iInv2"
  shows "invHoldForRule' s  (paraInv iInv1 iInv2) (paraRule iRule)   invariants "  (is "?P paraInv iInv paraRule iRule  invs")
  proof -
   have d2:"iRule=iInv1 \<or> iRule=iInv2 \<or> ((iRule \<noteq> iInv1) \<and> (iRule\<noteq>iInv2))"  by auto
   moreover
   {assume e1:"iRule=iInv1"
     have "?P paraInv iInv paraRule iRule  invs "
       by (metis  a2 a3 a4 b e1)

   }
   moreover
   {assume e1:"iRule = iInv2"
     have "?P paraInv iInv paraRule iRule  invs"
       by (metis  a2 a3 a4 c e1)
   }

   moreover
   {assume e1:"iRule\<noteq>iInv1 \<and> iRule\<noteq>iInv2"
     have "?P paraInv iInv paraRule iRule  invs"
       by (metis  a1 a2 a3 a4 d e1)

   }
   ultimately show "?P paraInv iInv paraRule iRule  invs"
     by blast
 qed
end

locale pRule2VsPInv0=
  fixes paraRule ::"nat \<Rightarrow> nat\<Rightarrow> rule"  and paraInv::"formula "
  and iRule1::"nat" and iRule2::"nat"  and N::"nat"
  assumes

  b:"
  invHoldForRule' s   (paraInv) (paraRule iRule1 iRule2)  invariants "
begin
theorem  pRule12sPInv0:
  assumes a1:"iRule1 \<le> N"  and a2:"iRule2 \<le>N"

  shows "invHoldForRule' s   (paraInv) (paraRule iRule1 iRule2)   invariants "

  by(cut_tac a1 a2 b,auto)
end

locale pRule2VspInv1=
  fixes paraRule ::"nat \<Rightarrow>nat\<Rightarrow> rule"  and paraInv::"nat \<Rightarrow> formula "
  and iRule1::"nat" and iRule2::"nat" and iInv1::"nat"  and N::"nat"
  assumes
  b:" iRule1 = iInv1 \<longrightarrow>
  (invHoldForRule' s   (paraInv iInv1) (paraRule iRule1  iRule2)  invariants )"  and
  c:"  iRule2= iInv1  \<longrightarrow>
  (invHoldForRule' s   (paraInv iInv1) (paraRule iRule1  iRule2)  invariants  )"   and
  d:"  iRule1\<noteq> iInv1  \<longrightarrow>iRule2\<noteq> iInv1 \<longrightarrow>
  (invHoldForRule' s   (paraInv iInv1) (paraRule iRule1  iRule2)  invariants  )"
begin
theorem pRule2VspInv1:
  assumes a1:"iRule1 \<le> N"  and a2:" iRule2 \<le> N " and a3:" iInv1 \<le> N "
  shows "(invHoldForRule' s   (paraInv iInv1) (paraRule  iRule1  iRule2)  invariants  )"
  proof -
   have e2:"iRule1=iInv1  \<or> iRule2 = iInv1 \<or> (iRule1\<noteq> iInv1  \<and> iRule2\<noteq> iInv1) "  by auto

   moreover
   {assume e3:" iRule1=iInv1 "

     have "(invHoldForRule' s   (paraInv iInv1) (paraRule  iRule1  iRule2)  invariants  )"
       by (cut_tac b e3,auto )
   }
   moreover
   {assume e3:" iRule2=iInv1 "

     have "(invHoldForRule' s   (paraInv iInv1) (paraRule  iRule1  iRule2)  invariants  )"
       by (cut_tac c e3,auto )
   }
    moreover
   {assume e3:" (iRule1\<noteq> iInv1  \<and> iRule2\<noteq> iInv1) "

     have "(invHoldForRule' s   (paraInv iInv1) (paraRule  iRule1  iRule2)  invariants  )"
       by (cut_tac d e3,auto )
   }
   ultimately show"(invHoldForRule' s   (paraInv iInv1) (paraRule  iRule1  iRule2)  invariants  )"
     by blast
 qed
end

locale pRule2VsPInv2=
  fixes paraRule ::"nat \<Rightarrow> nat\<Rightarrow>rule"  and paraInv::"nat \<Rightarrow> nat\<Rightarrow>formula "
  and iRule1::"nat" and iRule2::"nat"  and iInv1::"nat" and iInv2::"nat" and N::"nat" and invariants::"formula set"
  assumes
  b:"iRule1 = iInv1 \<and> iRule2 = iInv2\<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2)  invariants "  and
  c:"iRule1 = iInv1 \<and> iRule2 \<noteq> iInv2\<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2)  invariants "  and
  d:"iRule1 = iInv2 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2) invariants"  and
  e:"iRule1 \<noteq> iInv2 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2)  invariants"
begin
theorem  pRule1VspInv2:
  assumes a1:"iRule \<le> N"  and a2:" iInv1 \<le> N " and a3:"iInv2 \<le> N "
  and a4:"iInv1 \<noteq> iInv2"
  shows "invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2)   invariants "
  proof -
   have d2:"(iRule1 = iInv1 \<and> iRule2 = iInv2)\<and> (iRule1 = iInv1 \<and> iRule2 \<noteq> iInv2) \<or> iRule1=iInv2 \<or> ( (iRule1\<noteq>iInv2))"  by auto
   moreover
   {assume e1:"iRule1=iInv1 \<and> iRule2 = iInv2"
     have "invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2)   invariants "
       by (cut_tac b e1,auto)

   }
   moreover
   {assume e1:"iRule1 = iInv1 \<and> iRule2 \<noteq> iInv2"
     have "invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2)   invariants "
       by (metis  a2 a3 a4 c e1)
   }

   moreover
   {assume e1: "iRule1=iInv2 "
     have "invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2)   invariants "
       by (metis  d e1)

   }
   moreover
   {assume e1: "iRule1\<noteq>iInv2 "
     have "invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2)   invariants "
       by (metis e e1)

   }
   ultimately show "invHoldForRule' s   (paraInv iInv1 iInv2) (paraRule iRule1 iRule2)   invariants "
     by blast
 qed
end

locale pRule2VspInv3=
  fixes paraRule ::"nat \<Rightarrow> nat\<Rightarrow>rule"  and paraInv::"nat \<Rightarrow> nat\<Rightarrow>nat\<Rightarrow>formula "
  and iRule1::"nat"  and  iRule2::"nat"  and iInv1::"nat" and iInv2::"nat"  and iInv3::"nat" and N::"nat"
  and invariants::"formula set"
  assumes
  b:"iRule1 = iInv1 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2)  invariants "  and
  c:" iRule1 = iInv2 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2 ) invariants"  and
  d:"  iRule1 = iInv3 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2)  invariants" and

  e:" iRule1 \<noteq> iInv1 \<longrightarrow>iRule1 \<noteq> iInv2 \<longrightarrow> iRule1 \<noteq> iInv3 \<longrightarrow>
  invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2)  invariants"
begin
theorem  pRule1VspInv3:
  assumes a1:"iRule \<le> N"  and a2:" iInv1 \<le> N " and a3:"iInv2 \<le> N " and a4:"iInv3 \<le> N "
  and a5:"iInv1 \<noteq> iInv2"  and a6:"iInv1 \<noteq> iInv3"   and a7:"iInv2 \<noteq> iInv3"
  shows "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2)  invariants "
  proof -
   have d2:"iRule1=iInv1 \<or> iRule1=iInv2 \<or> iRule1=iInv3 \<or> ((iRule1 \<noteq> iInv1) \<and> (iRule1\<noteq>iInv2) \<and> iRule1 \<noteq> iInv3 )"  by auto
   moreover
   {assume e1:"iRule1=iInv1"
     have "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2)  invariants  "
       by (cut_tac b e1, auto)

   }
   moreover
   {assume e1:"iRule1 = iInv2"
     have "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2)  invariants  "
       by (cut_tac c e1,auto)
   }

   moreover
   {assume e1:"iRule1=iInv3"
     have "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2)  invariants  "
       by (cut_tac  d  e1,auto)

   }

   moreover
   {assume e1:"iRule1\<noteq>iInv1 \<and> iRule1\<noteq>iInv2 \<and> iRule1\<noteq>iInv3"
      have "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2)  invariants  "
       by (cut_tac  e  e1,auto)

   }
   ultimately show "invHoldForRule' s   (paraInv iInv1 iInv2 iInv3) (paraRule iRule1 iRule2)  invariants  "
     by blast
 qed
end

locale iniImplyInv0=
  fixes paraInv ::"  formula" and specOnAVar::"formula" and specOnAVars::"formula list"
  assumes a:" formEval  specOnAVar  s \<longrightarrow>formEval ( paraInv  ) s" and
  b:"specOnAVar \<in>set specOnAVars"
begin
theorem iniImplyInv:
  assumes a1:"ex0P N (  invariant = paraInv  )" and
   a2:"formEval  (andList specOnAVars) s"
  shows "formEval invariant  s "
proof -

  have b2:"formEval  specOnAVar  s"
  by (metis a2 andList1 b)

  then show b5:"formEval (  invariant )   s"

    apply -
    apply(cut_tac a1 a2 a)
    by (metis (poly_guards_query) a ex0P_def)

qed
end

locale iniImplyInv1=
  fixes paraInv ::" nat \<Rightarrow> formula"  and N::"nat" and specOnAVar::"formula" and specOnAVars::"formula list"
  assumes a:"\<forall>i . i\<le>N \<longrightarrow> formEval  specOnAVar  s \<longrightarrow>formEval ( paraInv i ) s" and
  b:"specOnAVar \<in>set specOnAVars"
begin
theorem iniImplyInv:
  assumes a1: " ex1P N (%i.  invariant = paraInv i )"
  and a2:"formEval  (andList specOnAVars) s"
  shows "formEval invariant  s "
proof -
  from a1 obtain i j where b1:"i \<le> N \<and> invariant =paraInv  i"
    apply -
    apply(simp add:ex1P_def)
    apply auto
    done

  have b2:"formEval  specOnAVar  s"
  by (metis a2 andList1 b)

  then have b5:"formEval ( paraInv i)   s"

    apply -
    apply(cut_tac a1 b2 a)
    by (metis b1 local.a)

 then  show  "formEval invariant s "
 by (metis b1)

qed
end

locale iniImplyInv2=
  fixes paraInv ::" nat \<Rightarrow>nat \<Rightarrow> formula"  and N::"nat" and specOnAVar::"formula" and specOnAVars::"formula list"
  assumes a:"\<forall>i j. i\<le>N \<longrightarrow>  j\<le>N \<longrightarrow> formEval  specOnAVar  s \<longrightarrow>formEval ( paraInv i j) s" and
  b:"specOnAVar \<in>set specOnAVars"
begin
theorem iniImplyInv:
  assumes a1: " ex2P N (%i j.  invariant = paraInv i j)"
  and a2:"formEval  (andList specOnAVars) s"
  shows "formEval invariant  s "
proof -
  from a1 obtain i j where b1:"i \<le> N \<and> j\<le>N \<and> invariant =paraInv  i j"
    apply -
    apply(simp add:ex2P_def)
    apply auto
    done

  have b2:"formEval  specOnAVar  s"
  by (metis a2 andList1 b)

  then have b5:"formEval ( paraInv i j)   s"

    apply -
    apply(cut_tac a1 b2 a)
    by (metis b1 local.a)

 then  show  "formEval invariant s "
 by (metis b1)

qed
end

locale iniImplyInv3=
  fixes paraInv ::" nat \<Rightarrow>nat \<Rightarrow> nat\<Rightarrow>formula"  and N::"nat" and specOnAVar::"formula" and specOnAVars::"formula list"
  assumes a:"\<forall>i j k. i\<le>N \<longrightarrow>  j\<le>N \<longrightarrow> k \<le>N \<longrightarrow> formEval  specOnAVar  s \<longrightarrow>formEval ( paraInv i j k) s" and
  b:"specOnAVar \<in>set specOnAVars"
begin
theorem iniImplyInv:
  assumes a1: " ex3P N (%i j k.  invariant = paraInv i j k)"
  and a2:"formEval  (andList specOnAVars) s"
  shows "formEval invariant  s "
proof -
  from a1 obtain i j k where b1:"i \<le> N \<and> j\<le>N \<and> k \<le>N \<and>  invariant =paraInv  i j k"
    apply -
    apply(simp add:ex3P_def)
    apply auto
    done

  have b2:"formEval  specOnAVar  s"
  by (metis a2 andList1 b)

  then have b5:"formEval ( paraInv i j k)   s"

    apply -
    apply(cut_tac a1 b2 a)
    by (metis b1 local.a)

 then  show  "formEval invariant s "
 by (metis b1)

qed
end

end


(*  Title:      HOL/Library/Old_SMT.thy
    Author:     Sascha Boehme, TU Muenchen
*)

section \<open>Old Version of Bindings to Satisfiability Modulo Theories (SMT) solvers\<close>

theory Old_SMT
imports "../Real" "../Word/Word"
keywords "old_smt_status" :: diag
begin

ML_file "Old_SMT/old_smt_utils.ML"
ML_file "Old_SMT/old_smt_failure.ML"
ML_file "Old_SMT/old_smt_config.ML"

subsection \<open>Triggers for quantifier instantiation\<close>

text \<open>
Some SMT solvers support patterns as a quantifier instantiation
heuristics.  Patterns may either be positive terms (tagged by "pat")
triggering quantifier instantiations -- when the solver finds a
term matching a positive pattern, it instantiates the corresponding
quantifier accordingly -- or negative terms (tagged by "nopat")
inhibiting quantifier instantiations.  A list of patterns
of the same kind is called a multipattern, and all patterns in a
multipattern are considered conjunctively for quantifier instantiation.
A list of multipatterns is called a trigger, and their multipatterns
act disjunctively during quantifier instantiation.  Each multipattern
should mention at least all quantified variables of the preceding
quantifier block.
\<close>

typedecl pattern

consts
  pat :: "'a \<Rightarrow> pattern"
  nopat :: "'a \<Rightarrow> pattern"

definition trigger :: "pattern list list \<Rightarrow> bool \<Rightarrow> bool" where "trigger _ P = P"

subsection \<open>Quantifier weights\<close>

text \<open>
Weight annotations to quantifiers influence the priority of quantifier
instantiations.  They should be handled with care for solvers, which support
them, because incorrect choices of weights might render a problem unsolvable.
\<close>

definition weight :: "int \<Rightarrow> bool \<Rightarrow> bool" where "weight _ P = P"

text \<open>
Weights must be non-negative.  The value \<open>0\<close> is equivalent to providing
no weight at all.

Weights should only be used at quantifiers and only inside triggers (if the
quantifier has triggers).  Valid usages of weights are as follows:

\begin{itemize}
\item
@{term "\<forall>x. trigger [[pat (P x)]] (weight 2 (P x))"}
\item
@{term "\<forall>x. weight 3 (P x)"}
\end{itemize}
\<close>

subsection \<open>Higher-order encoding\<close>

text \<open>
Application is made explicit for constants occurring with varying
numbers of arguments.  This is achieved by the introduction of the
following constant.
\<close>

definition fun_app where "fun_app f = f"

text \<open>
Some solvers support a theory of arrays which can be used to encode
higher-order functions.  The following set of lemmas specifies the
properties of such (extensional) arrays.
\<close>

lemmas array_rules = ext fun_upd_apply fun_upd_same fun_upd_other
  fun_upd_upd fun_app_def

subsection \<open>First-order logic\<close>

text \<open>
Some SMT solvers only accept problems in first-order logic, i.e.,
where formulas and terms are syntactically separated. When
translating higher-order into first-order problems, all
uninterpreted constants (those not built-in in the target solver)
are treated as function symbols in the first-order sense.  Their
occurrences as head symbols in atoms (i.e., as predicate symbols) are
turned into terms by logically equating such atoms with @{term True}.
For technical reasons, @{term True} and @{term False} occurring inside
terms are replaced by the following constants.
\<close>

definition term_true where "term_true = True"
definition term_false where "term_false = False"

subsection \<open>Integer division and modulo for Z3\<close>

definition z3div :: "int \<Rightarrow> int \<Rightarrow> int" where
  "z3div k l = (if 0 \<le> l then k div l else -(k div (-l)))"

definition z3mod :: "int \<Rightarrow> int \<Rightarrow> int" where
  "z3mod k l = (if 0 \<le> l then k mod l else k mod (-l))"

subsection \<open>Setup\<close>

ML_file "Old_SMT/old_smt_builtin.ML"
ML_file "Old_SMT/old_smt_datatypes.ML"
ML_file "Old_SMT/old_smt_normalize.ML"
ML_file "Old_SMT/old_smt_translate.ML"
ML_file "Old_SMT/old_smt_solver.ML"
ML_file "Old_SMT/old_smtlib_interface.ML"
ML_file "Old_SMT/old_z3_interface.ML"
ML_file "Old_SMT/old_z3_proof_parser.ML"
ML_file "Old_SMT/old_z3_proof_tools.ML"
ML_file "Old_SMT/old_z3_proof_literals.ML"
ML_file "Old_SMT/old_z3_proof_methods.ML"
named_theorems old_z3_simp "simplification rules for Z3 proof reconstruction"
ML_file "Old_SMT/old_z3_proof_reconstruction.ML"
ML_file "Old_SMT/old_z3_model.ML"
ML_file "Old_SMT/old_smt_setup_solvers.ML"

setup \<open>
  Old_SMT_Config.setup #>
  Old_SMT_Normalize.setup #>
  Old_SMTLIB_Interface.setup #>
  Old_Z3_Interface.setup #>
  Old_SMT_Setup_Solvers.setup
\<close>

method_setup old_smt = \<open>
  Scan.optional Attrib.thms [] >>
    (fn thms => fn ctxt =>
      (legacy_feature "Proof method \"old_smt\" will be discontinued soon -- use \"smt\" instead";
       METHOD (fn facts => HEADGOAL (Old_SMT_Solver.smt_tac ctxt (thms @ facts)))))
\<close> "apply an SMT solver to the current goal"

subsection \<open>Configuration\<close>

text \<open>
The current configuration can be printed by the command
\<open>old_smt_status\<close>, which shows the values of most options.
\<close>

subsection \<open>General configuration options\<close>

text \<open>
The option \<open>old_smt_solver\<close> can be used to change the target SMT
solver.  The possible values can be obtained from the \<open>old_smt_status\<close>
command.

Due to licensing restrictions, Yices and Z3 are not installed/enabled
by default.  Z3 is free for non-commercial applications and can be enabled
by setting the \<open>OLD_Z3_NON_COMMERCIAL\<close> environment variable to
\<open>yes\<close>.
\<close>

declare [[ old_smt_solver = z3 ]]

text \<open>
Since SMT solvers are potentially non-terminating, there is a timeout
(given in seconds) to restrict their runtime.  A value greater than
120 (seconds) is in most cases not advisable.
\<close>

declare [[ old_smt_timeout = 20 ]]

text \<open>
SMT solvers apply randomized heuristics.  In case a problem is not
solvable by an SMT solver, changing the following option might help.
\<close>

declare [[ old_smt_random_seed = 1 ]]

text \<open>
In general, the binding to SMT solvers runs as an oracle, i.e, the SMT
solvers are fully trusted without additional checks.  The following
option can cause the SMT solver to run in proof-producing mode, giving
a checkable certificate.  This is currently only implemented for Z3.
\<close>

declare [[ old_smt_oracle = false ]]

text \<open>
Each SMT solver provides several commandline options to tweak its
behaviour.  They can be passed to the solver by setting the following
options.
\<close>

declare [[ old_cvc3_options = "" ]]
declare [[ old_yices_options = "" ]]
declare [[ old_z3_options = "" ]]

text \<open>
Enable the following option to use built-in support for datatypes and
records.  Currently, this is only implemented for Z3 running in oracle
mode.
\<close>

declare [[ old_smt_datatypes = false ]]

text \<open>
The SMT method provides an inference mechanism to detect simple triggers
in quantified formulas, which might increase the number of problems
solvable by SMT solvers (note: triggers guide quantifier instantiations
in the SMT solver).  To turn it on, set the following option.
\<close>

declare [[ old_smt_infer_triggers = false ]]

text \<open>
The SMT method monomorphizes the given facts, that is, it tries to
instantiate all schematic type variables with fixed types occurring
in the problem.  This is a (possibly nonterminating) fixed-point
construction whose cycles are limited by the following option.
\<close>

declare [[ monomorph_max_rounds = 5 ]]

text \<open>
In addition, the number of generated monomorphic instances is limited
by the following option.
\<close>

declare [[ monomorph_max_new_instances = 500 ]]

subsection \<open>Certificates\<close>

text \<open>
By setting the option \<open>old_smt_certificates\<close> to the name of a file,
all following applications of an SMT solver a cached in that file.
Any further application of the same SMT solver (using the very same
configuration) re-uses the cached certificate instead of invoking the
solver.  An empty string disables caching certificates.

The filename should be given as an explicit path.  It is good
practice to use the name of the current theory (with ending
\<open>.certs\<close> instead of \<open>.thy\<close>) as the certificates file.
Certificate files should be used at most once in a certain theory context,
to avoid race conditions with other concurrent accesses.
\<close>

declare [[ old_smt_certificates = "" ]]

text \<open>
The option \<open>old_smt_read_only_certificates\<close> controls whether only
stored certificates are should be used or invocation of an SMT solver
is allowed.  When set to \<open>true\<close>, no SMT solver will ever be
invoked and only the existing certificates found in the configured
cache are used;  when set to \<open>false\<close> and there is no cached
certificate for some proposition, then the configured SMT solver is
invoked.
\<close>

declare [[ old_smt_read_only_certificates = false ]]

subsection \<open>Tracing\<close>

text \<open>
The SMT method, when applied, traces important information.  To
make it entirely silent, set the following option to \<open>false\<close>.
\<close>

declare [[ old_smt_verbose = true ]]

text \<open>
For tracing the generated problem file given to the SMT solver as
well as the returned result of the solver, the option
\<open>old_smt_trace\<close> should be set to \<open>true\<close>.
\<close>

declare [[ old_smt_trace = false ]]

text \<open>
From the set of assumptions given to the SMT solver, those assumptions
used in the proof are traced when the following option is set to
@{term true}.  This only works for Z3 when it runs in non-oracle mode
(see options \<open>old_smt_solver\<close> and \<open>old_smt_oracle\<close> above).
\<close>

declare [[ old_smt_trace_used_facts = false ]]

subsection \<open>Schematic rules for Z3 proof reconstruction\<close>

text \<open>
Several prof rules of Z3 are not very well documented.  There are two
lemma groups which can turn failing Z3 proof reconstruction attempts
into succeeding ones: the facts in \<open>z3_rule\<close> are tried prior to
any implemented reconstruction procedure for all uncertain Z3 proof
rules;  the facts in \<open>z3_simp\<close> are only fed to invocations of
the simplifier when reconstructing theory-specific proof steps.
\<close>

lemmas [old_z3_rule] =
  refl eq_commute conj_commute disj_commute simp_thms nnf_simps
  ring_distribs field_simps times_divide_eq_right times_divide_eq_left
  if_True if_False not_not

lemma [old_z3_rule]:
  "(P \<and> Q) = (\<not>(\<not>P \<or> \<not>Q))"
  "(P \<and> Q) = (\<not>(\<not>Q \<or> \<not>P))"
  "(\<not>P \<and> Q) = (\<not>(P \<or> \<not>Q))"
  "(\<not>P \<and> Q) = (\<not>(\<not>Q \<or> P))"
  "(P \<and> \<not>Q) = (\<not>(\<not>P \<or> Q))"
  "(P \<and> \<not>Q) = (\<not>(Q \<or> \<not>P))"
  "(\<not>P \<and> \<not>Q) = (\<not>(P \<or> Q))"
  "(\<not>P \<and> \<not>Q) = (\<not>(Q \<or> P))"
  by auto

lemma [old_z3_rule]:
  "(P \<longrightarrow> Q) = (Q \<or> \<not>P)"
  "(\<not>P \<longrightarrow> Q) = (P \<or> Q)"
  "(\<not>P \<longrightarrow> Q) = (Q \<or> P)"
  "(True \<longrightarrow> P) = P"
  "(P \<longrightarrow> True) = True"
  "(False \<longrightarrow> P) = True"
  "(P \<longrightarrow> P) = True"
  by auto

lemma [old_z3_rule]:
  "((P = Q) \<longrightarrow> R) = (R | (Q = (\<not>P)))"
  by auto

lemma [old_z3_rule]:
  "(\<not>True) = False"
  "(\<not>False) = True"
  "(x = x) = True"
  "(P = True) = P"
  "(True = P) = P"
  "(P = False) = (\<not>P)"
  "(False = P) = (\<not>P)"
  "((\<not>P) = P) = False"
  "(P = (\<not>P)) = False"
  "((\<not>P) = (\<not>Q)) = (P = Q)"
  "\<not>(P = (\<not>Q)) = (P = Q)"
  "\<not>((\<not>P) = Q) = (P = Q)"
  "(P \<noteq> Q) = (Q = (\<not>P))"
  "(P = Q) = ((\<not>P \<or> Q) \<and> (P \<or> \<not>Q))"
  "(P \<noteq> Q) = ((\<not>P \<or> \<not>Q) \<and> (P \<or> Q))"
  by auto

lemma [old_z3_rule]:
  "(if P then P else \<not>P) = True"
  "(if \<not>P then \<not>P else P) = True"
  "(if P then True else False) = P"
  "(if P then False else True) = (\<not>P)"
  "(if P then Q else True) = ((\<not>P) \<or> Q)"
  "(if P then Q else True) = (Q \<or> (\<not>P))"
  "(if P then Q else \<not>Q) = (P = Q)"
  "(if P then Q else \<not>Q) = (Q = P)"
  "(if P then \<not>Q else Q) = (P = (\<not>Q))"
  "(if P then \<not>Q else Q) = ((\<not>Q) = P)"
  "(if \<not>P then x else y) = (if P then y else x)"
  "(if P then (if Q then x else y) else x) = (if P \<and> (\<not>Q) then y else x)"
  "(if P then (if Q then x else y) else x) = (if (\<not>Q) \<and> P then y else x)"
  "(if P then (if Q then x else y) else y) = (if P \<and> Q then x else y)"
  "(if P then (if Q then x else y) else y) = (if Q \<and> P then x else y)"
  "(if P then x else if P then y else z) = (if P then x else z)"
  "(if P then x else if Q then x else y) = (if P \<or> Q then x else y)"
  "(if P then x else if Q then x else y) = (if Q \<or> P then x else y)"
  "(if P then x = y else x = z) = (x = (if P then y else z))"
  "(if P then x = y else y = z) = (y = (if P then x else z))"
  "(if P then x = y else z = y) = (y = (if P then x else z))"
  by auto

lemma [old_z3_rule]:
  "0 + (x::int) = x"
  "x + 0 = x"
  "x + x = 2 * x"
  "0 * x = 0"
  "1 * x = x"
  "x + y = y + x"
  by auto

lemma [old_z3_rule]:  (* for def-axiom *)
  "P = Q \<or> P \<or> Q"
  "P = Q \<or> \<not>P \<or> \<not>Q"
  "(\<not>P) = Q \<or> \<not>P \<or> Q"
  "(\<not>P) = Q \<or> P \<or> \<not>Q"
  "P = (\<not>Q) \<or> \<not>P \<or> Q"
  "P = (\<not>Q) \<or> P \<or> \<not>Q"
  "P \<noteq> Q \<or> P \<or> \<not>Q"
  "P \<noteq> Q \<or> \<not>P \<or> Q"
  "P \<noteq> (\<not>Q) \<or> P \<or> Q"
  "(\<not>P) \<noteq> Q \<or> P \<or> Q"
  "P \<or> Q \<or> P \<noteq> (\<not>Q)"
  "P \<or> Q \<or> (\<not>P) \<noteq> Q"
  "P \<or> \<not>Q \<or> P \<noteq> Q"
  "\<not>P \<or> Q \<or> P \<noteq> Q"
  "P \<or> y = (if P then x else y)"
  "P \<or> (if P then x else y) = y"
  "\<not>P \<or> x = (if P then x else y)"
  "\<not>P \<or>  (if P then x else y) = x"
  "P \<or> R \<or> \<not>(if P then Q else R)"
  "\<not>P \<or> Q \<or> \<not>(if P then Q else R)"
  "\<not>(if P then Q else R) \<or> \<not>P \<or> Q"
  "\<not>(if P then Q else R) \<or> P \<or> R"
  "(if P then Q else R) \<or> \<not>P \<or> \<not>Q"
  "(if P then Q else R) \<or> P \<or> \<not>R"
  "(if P then \<not>Q else R) \<or> \<not>P \<or> Q"
  "(if P then Q else \<not>R) \<or> P \<or> R"
  by auto

ML_file "Old_SMT/old_smt_real.ML"
ML_file "Old_SMT/old_smt_word.ML"

hide_type (open) pattern
hide_const fun_app term_true term_false z3div z3mod
hide_const (open) trigger pat nopat weight

end


(*  Title:      HOL/MicroJava/Comp/TranslCompTp.thy
    Author:     Martin Strecker
*)

theory TranslCompTp
imports Index "../BV/JVMType"
begin

(**********************************************************************)

definition comb :: "['a \<Rightarrow> 'b list \<times> 'c, 'c \<Rightarrow> 'b list \<times> 'd, 'a] \<Rightarrow> 'b list \<times> 'd" where
  "comb == (\<lambda> f1 f2 x0. let (xs1, x1) = f1 x0;
                            (xs2, x2) = f2 x1
                        in  (xs1 @ xs2, x2))"

definition comb_nil :: "'a \<Rightarrow> 'b list \<times> 'a" where
  "comb_nil a == ([], a)"

notation (xsymbols)
  comb  (infixr "\<box>" 55)

lemma comb_nil_left [simp]: "comb_nil \<box> f = f"
by (simp add: comb_def comb_nil_def split_beta)

lemma comb_nil_right [simp]: "f \<box> comb_nil = f"
by (simp add: comb_def comb_nil_def split_beta)

lemma comb_assoc [simp]: "(fa \<box> fb) \<box> fc = fa \<box> (fb \<box> fc)"
by (simp add: comb_def split_beta)

lemma comb_inv: "(xs', x') = (f1 \<box> f2) x0 \<Longrightarrow>
  \<exists> xs1 x1 xs2 x2. (xs1, x1) = (f1 x0) \<and> (xs2, x2) = f2 x1 \<and> xs'= xs1 @ xs2 \<and> x'=x2"
apply (case_tac "f1 x0")
apply (case_tac "f2 x1")
apply (simp add: comb_def split_beta)
done

(**********************************************************************)

abbreviation (input)
  mt_of :: "method_type \<times> state_type \<Rightarrow> method_type"
  where "mt_of == fst"

abbreviation (input)
  sttp_of :: "method_type \<times> state_type \<Rightarrow> state_type"
  where "sttp_of == snd"

definition nochangeST :: "state_type \<Rightarrow> method_type \<times> state_type" where
  "nochangeST sttp == ([Some sttp], sttp)"

definition pushST :: "[ty list, state_type] \<Rightarrow> method_type \<times> state_type" where
  "pushST tps == (\<lambda> (ST, LT). ([Some (ST, LT)], (tps @ ST, LT)))"

definition dupST :: "state_type \<Rightarrow> method_type \<times> state_type" where
  "dupST == (\<lambda> (ST, LT). ([Some (ST, LT)], (hd ST # ST, LT)))"

definition dup_x1ST :: "state_type \<Rightarrow> method_type \<times> state_type" where
  "dup_x1ST == (\<lambda> (ST, LT). ([Some (ST, LT)],
                             (hd ST # hd (tl ST) # hd ST # (tl (tl ST)), LT)))"

definition popST :: "[nat, state_type] \<Rightarrow> method_type \<times> state_type" where
  "popST n == (\<lambda> (ST, LT). ([Some (ST, LT)], (drop n ST, LT)))"

definition replST :: "[nat, ty, state_type] \<Rightarrow> method_type \<times> state_type" where
  "replST n tp == (\<lambda> (ST, LT). ([Some (ST, LT)], (tp # (drop n ST), LT)))"

definition storeST :: "[nat, ty, state_type] \<Rightarrow> method_type \<times> state_type" where
  "storeST i tp == (\<lambda> (ST, LT). ([Some (ST, LT)], (tl ST, LT [i:= OK tp])))"

(* Expressions *)

primrec compTpExpr :: "java_mb \<Rightarrow> java_mb prog \<Rightarrow> expr \<Rightarrow>
    state_type \<Rightarrow> method_type \<times> state_type"
  and compTpExprs :: "java_mb \<Rightarrow> java_mb prog \<Rightarrow> expr list \<Rightarrow>
    state_type \<Rightarrow> method_type \<times> state_type"
where
  "compTpExpr jmb G (NewC c) = pushST [Class c]"
| "compTpExpr jmb G (Cast c e) = (compTpExpr jmb G e) \<box> (replST 1 (Class c))"
| "compTpExpr jmb G (Lit val) = pushST [the (typeof (\<lambda>v. None) val)]"
| "compTpExpr jmb G (BinOp bo e1 e2) =
     (compTpExpr jmb G e1) \<box> (compTpExpr jmb G e2) \<box>
     (case bo of
       Eq => popST 2 \<box> pushST [PrimT Boolean] \<box> popST 1 \<box> pushST [PrimT Boolean]
     | Add => replST 2 (PrimT Integer))"
| "compTpExpr jmb G (LAcc vn) = (\<lambda> (ST, LT).
      pushST [ok_val (LT ! (index jmb vn))] (ST, LT))"
| "compTpExpr jmb G (vn::=e) =
      (compTpExpr jmb G e) \<box> dupST \<box> (popST 1)"
| "compTpExpr jmb G ( {cn}e..fn ) =
      (compTpExpr jmb G e) \<box> replST 1 (snd (the (field (G,cn) fn)))"
| "compTpExpr jmb G (FAss cn e1 fn e2 ) =
      (compTpExpr jmb G e1) \<box> (compTpExpr jmb G e2) \<box> dup_x1ST \<box> (popST 2)"
| "compTpExpr jmb G ({C}a..mn({fpTs}ps)) =
       (compTpExpr jmb G a) \<box> (compTpExprs jmb G ps) \<box>
       (replST ((length ps) + 1) (method_rT (the (method (G,C) (mn,fpTs)))))"
| "compTpExprs jmb G [] = comb_nil"
| "compTpExprs jmb G (e#es) = (compTpExpr jmb G e) \<box> (compTpExprs jmb G es)"

(* Statements *)
primrec compTpStmt :: "java_mb \<Rightarrow> java_mb prog \<Rightarrow> stmt \<Rightarrow>
    state_type \<Rightarrow> method_type \<times> state_type"
where
  "compTpStmt jmb G Skip = comb_nil"
| "compTpStmt jmb G (Expr e) =  (compTpExpr jmb G e) \<box> popST 1"
| "compTpStmt jmb G (c1;; c2) = (compTpStmt jmb G c1) \<box> (compTpStmt jmb G c2)"
| "compTpStmt jmb G (If(e) c1 Else c2) =
      (pushST [PrimT Boolean]) \<box> (compTpExpr jmb G e) \<box> popST 2 \<box>
      (compTpStmt jmb G c1) \<box> nochangeST \<box> (compTpStmt jmb G c2)"
| "compTpStmt jmb G (While(e) c) =
      (pushST [PrimT Boolean]) \<box> (compTpExpr jmb G e) \<box> popST 2 \<box>
      (compTpStmt jmb G c) \<box> nochangeST"

definition compTpInit :: "java_mb \<Rightarrow> (vname * ty)
                   \<Rightarrow> state_type \<Rightarrow> method_type \<times> state_type" where
  "compTpInit jmb == (\<lambda> (vn,ty). (pushST [ty]) \<box>  (storeST (index jmb vn) ty))"

primrec compTpInitLvars :: "[java_mb, (vname \<times> ty) list] \<Rightarrow>
    state_type \<Rightarrow> method_type \<times> state_type"
where
  "compTpInitLvars jmb [] = comb_nil"
| "compTpInitLvars jmb (lv#lvars) = (compTpInit jmb lv) \<box> (compTpInitLvars jmb lvars)"

definition start_ST :: "opstack_type" where
  "start_ST == []"

definition start_LT :: "cname \<Rightarrow> ty list \<Rightarrow> nat \<Rightarrow> locvars_type" where
  "start_LT C pTs n ==  (OK (Class C))#((map OK pTs))@(replicate n Err)"

definition compTpMethod  :: "[java_mb prog, cname, java_mb mdecl] \<Rightarrow> method_type" where
  "compTpMethod G C == \<lambda> ((mn,pTs),rT, jmb).
                         let (pns,lvars,blk,res) = jmb
                         in (mt_of
                            ((compTpInitLvars jmb lvars \<box>
                              compTpStmt jmb G blk \<box>
                              compTpExpr jmb G res \<box>
                              nochangeST)
                                (start_ST, start_LT C pTs (length lvars))))"

definition compTp :: "java_mb prog => prog_type" where
  "compTp G C sig == let (D, rT, jmb) = (the (method (G, C) sig))
                      in compTpMethod G C (sig, rT, jmb)"

(**********************************************************************)
  (* Computing the maximum stack size from the method_type *)

definition ssize_sto :: "(state_type option) \<Rightarrow> nat" where
  "ssize_sto sto ==  case sto of None \<Rightarrow> 0 | (Some (ST, LT)) \<Rightarrow> length ST"

definition max_of_list :: "nat list \<Rightarrow> nat" where
  "max_of_list xs == foldr max xs 0"

definition max_ssize :: "method_type \<Rightarrow> nat" where
  "max_ssize mt == max_of_list (map ssize_sto mt)"

end


(*  Title:      JinjaDCI/BV/BVConform.thy

    Author:     Cornelia Pusch, Gerwin Klein, Susannah Mansky
    Copyright   1999 Technische Universitaet Muenchen, 2019-20 UIUC

    Based on the Jinja theory BV/BVConform.thy by Cornelia Pusch and Gerwin Klein

The invariant for the type safety proof.
*)

section \<open> BV Type Safety Invariant \<close>

theory BVConform
imports BVSpec "../JVM/JVMExec" "../Common/Conform"
begin

subsection \<open> @{text "correct_state"} definitions \<close>

definition confT :: "'c prog \<Rightarrow> heap \<Rightarrow> val \<Rightarrow> ty err \<Rightarrow> bool"
    ("_,_ \<turnstile> _ :\<le>\<^sub>\<top> _" [51,51,51,51] 50)
where
  "P,h \<turnstile> v :\<le>\<^sub>\<top> E \<equiv> case E of Err \<Rightarrow> True | OK T \<Rightarrow> P,h \<turnstile> v :\<le> T"

notation (ASCII)
  confT  ("_,_ |- _ :<=T _" [51,51,51,51] 50)

abbreviation
  confTs :: "'c prog \<Rightarrow> heap \<Rightarrow> val list \<Rightarrow> ty\<^sub>l \<Rightarrow> bool"
      ("_,_ \<turnstile> _ [:\<le>\<^sub>\<top>] _" [51,51,51,51] 50) where
  "P,h \<turnstile> vs [:\<le>\<^sub>\<top>] Ts \<equiv> list_all2 (confT P h) vs Ts"

notation (ASCII)
  confTs  ("_,_ |- _ [:<=T] _" [51,51,51,51] 50)

fun Called_context :: "jvm_prog \<Rightarrow> cname \<Rightarrow> instr \<Rightarrow> bool" where
"Called_context P C\<^sub>0 (New C') = (C\<^sub>0=C')" |
"Called_context P C\<^sub>0 (Getstatic C F D) =  ((C\<^sub>0=D) \<and> (\<exists>t. P \<turnstile> C has F,Static:t in D))" |
"Called_context P C\<^sub>0 (Putstatic C F D) = ((C\<^sub>0=D) \<and> (\<exists>t. P \<turnstile> C has F,Static:t in D))" |
"Called_context P C\<^sub>0 (Invokestatic C M n)
   = (\<exists>Ts T m D. (C\<^sub>0=D) \<and> P \<turnstile> C sees M,Static:Ts \<rightarrow> T = m in D)" |
"Called_context P _ _ = False"

abbreviation Called_set :: "instr set" where
"Called_set \<equiv> {i. \<exists>C. i = New C} \<union> {i. \<exists>C M n. i = Invokestatic C M n}
                 \<union> {i. \<exists>C F D. i = Getstatic C F D} \<union> {i. \<exists>C F D. i = Putstatic C F D}"

lemma Called_context_Called_set:
 "Called_context P D i \<Longrightarrow> i \<in> Called_set" by(cases i, auto)

fun valid_ics :: "jvm_prog \<Rightarrow> heap \<Rightarrow> sheap \<Rightarrow> cname \<times> mname \<times> pc \<times> init_call_status \<Rightarrow> bool"
  ("_,_,_ \<turnstile>\<^sub>i _" [51,51,51,51] 50) where
"valid_ics P h sh (C,M,pc,Calling C' Cs)
 = (let ins = instrs_of P C M in Called_context P (last (C'#Cs)) (ins!pc)
    \<and> is_class P C')" |
"valid_ics P h sh (C,M,pc,Throwing Cs a)
 =(let ins = instrs_of P C M in \<exists>C1. Called_context P C1 (ins!pc)
    \<and> (\<exists>obj. h a = Some obj))" |
"valid_ics P h sh (C,M,pc,Called Cs)
 = (let ins = instrs_of P C M
    in \<exists>C1 sobj. Called_context P C1 (ins!pc) \<and> sh C1 = Some sobj)" |
"valid_ics P _ _ _ = True"

definition conf_f  :: "jvm_prog \<Rightarrow> heap \<Rightarrow> sheap \<Rightarrow> ty\<^sub>i \<Rightarrow> bytecode \<Rightarrow> frame \<Rightarrow> bool"
where
  "conf_f P h sh \<equiv> \<lambda>(ST,LT) is (stk,loc,C,M,pc,ics).
  P,h \<turnstile> stk [:\<le>] ST \<and> P,h \<turnstile> loc [:\<le>\<^sub>\<top>] LT \<and> pc < size is \<and> P,h,sh \<turnstile>\<^sub>i (C,M,pc,ics)"

lemma conf_f_def2:
  "conf_f P h sh (ST,LT) is (stk,loc,C,M,pc,ics) \<equiv>
  P,h \<turnstile> stk [:\<le>] ST \<and> P,h \<turnstile> loc [:\<le>\<^sub>\<top>] LT \<and> pc < size is \<and> P,h,sh \<turnstile>\<^sub>i (C,M,pc,ics)"
  by (simp add: conf_f_def)

primrec conf_fs :: "[jvm_prog,heap,sheap,ty\<^sub>P,cname,mname,nat,ty,frame list] \<Rightarrow> bool"
where
  "conf_fs P h sh \<Phi> C\<^sub>0 M\<^sub>0 n\<^sub>0 T\<^sub>0 [] = True"
| "conf_fs P h sh \<Phi> C\<^sub>0 M\<^sub>0 n\<^sub>0 T\<^sub>0 (f#frs) =
  (let (stk,loc,C,M,pc,ics) = f in
  (\<exists>ST LT b Ts T mxs mxl\<^sub>0 is xt.
    \<Phi> C M ! pc = Some (ST,LT) \<and>
    (P \<turnstile> C sees M,b:Ts \<rightarrow> T = (mxs,mxl\<^sub>0,is,xt) in C) \<and>
    ((\<exists>D Ts' T' m D'. M\<^sub>0 \<noteq> clinit \<and> ics = No_ics \<and>
       is!pc = Invoke M\<^sub>0 n\<^sub>0 \<and> ST!n\<^sub>0 = Class D \<and>
       P \<turnstile> D sees M\<^sub>0,NonStatic:Ts' \<rightarrow> T' = m in D' \<and> P \<turnstile> C\<^sub>0 \<preceq>\<^sup>* D' \<and> P \<turnstile> T\<^sub>0 \<le> T') \<or>
     (\<exists>D Ts' T' m. M\<^sub>0 \<noteq> clinit \<and> ics = No_ics \<and>
       is!pc = Invokestatic D M\<^sub>0 n\<^sub>0 \<and>
       P \<turnstile> D sees M\<^sub>0,Static:Ts' \<rightarrow> T' = m in C\<^sub>0 \<and> P \<turnstile> T\<^sub>0 \<le> T') \<or>
     (M\<^sub>0 = clinit \<and> (\<exists>Cs. ics = Called Cs))) \<and>
    conf_f P h sh (ST, LT) is f \<and> conf_fs P h sh \<Phi> C M (size Ts) T frs))"

fun ics_classes :: "init_call_status \<Rightarrow> cname list" where
"ics_classes (Calling C Cs) = Cs" |
"ics_classes (Throwing Cs a) = Cs" |
"ics_classes (Called Cs) = Cs" |
"ics_classes _ = []"

fun frame_clinit_classes :: "frame \<Rightarrow> cname list" where
"frame_clinit_classes (stk,loc,C,M,pc,ics) = (if M=clinit then [C] else []) @ ics_classes ics"

abbreviation clinit_classes :: "frame list \<Rightarrow> cname list" where
"clinit_classes frs \<equiv> concat (map frame_clinit_classes frs)"

definition distinct_clinit :: "frame list \<Rightarrow> bool" where
"distinct_clinit frs \<equiv> distinct (clinit_classes frs)"

definition conf_clinit :: "jvm_prog \<Rightarrow> sheap \<Rightarrow> frame list \<Rightarrow> bool" where
"conf_clinit P sh frs
   \<equiv> distinct_clinit frs \<and>
      (\<forall>C \<in> set(clinit_classes frs). is_class P C \<and> (\<exists>sfs. sh C = Some(sfs, Processing)))"

(*************************)

definition correct_state :: "[jvm_prog,ty\<^sub>P,jvm_state] \<Rightarrow> bool"  ("_,_ \<turnstile> _ \<surd>"  [61,0,0] 61)
where
  "correct_state P \<Phi> \<equiv> \<lambda>(xp,h,frs,sh).
  case xp of
     None \<Rightarrow> (case frs of
             [] \<Rightarrow> True
             | (f#fs) \<Rightarrow> P\<turnstile> h\<surd> \<and> P,h\<turnstile>\<^sub>s sh\<surd> \<and> conf_clinit P sh frs \<and>
             (let (stk,loc,C,M,pc,ics) = f
              in \<exists>b Ts T mxs mxl\<^sub>0 is xt \<tau>.
                    (P \<turnstile> C sees M,b:Ts\<rightarrow>T = (mxs,mxl\<^sub>0,is,xt) in C) \<and>
                    \<Phi> C M ! pc = Some \<tau> \<and>
                    conf_f P h sh \<tau> is f \<and> conf_fs P h sh \<Phi> C M (size Ts) T fs))
  | Some x \<Rightarrow> frs = []"

notation
  correct_state  ("_,_ |- _ [ok]"  [61,0,0] 61)

subsection \<open> Values and @{text "\<top>"} \<close>

lemma confT_Err [iff]: "P,h \<turnstile> x :\<le>\<^sub>\<top> Err"
  by (simp add: confT_def)

lemma confT_OK [iff]:  "P,h \<turnstile> x :\<le>\<^sub>\<top> OK T = (P,h \<turnstile> x :\<le> T)"
  by (simp add: confT_def)

lemma confT_cases:
  "P,h \<turnstile> x :\<le>\<^sub>\<top> X = (X = Err \<or> (\<exists>T. X = OK T \<and> P,h \<turnstile> x :\<le> T))"
  by (cases X) auto

lemma confT_hext [intro?, trans]:
  "\<lbrakk> P,h \<turnstile> x :\<le>\<^sub>\<top> T; h \<unlhd> h' \<rbrakk> \<Longrightarrow> P,h' \<turnstile> x :\<le>\<^sub>\<top> T"
  by (cases T) (blast intro: conf_hext)+

lemma confT_widen [intro?, trans]:
  "\<lbrakk> P,h \<turnstile> x :\<le>\<^sub>\<top> T; P \<turnstile> T \<le>\<^sub>\<top> T' \<rbrakk> \<Longrightarrow> P,h \<turnstile> x :\<le>\<^sub>\<top> T'"
  by (cases T', auto intro: conf_widen)

subsection \<open> Stack and Registers \<close>

lemmas confTs_Cons1 [iff] = list_all2_Cons1 [of "confT P h"] for P h

lemma confTs_confT_sup:
assumes confTs: "P,h \<turnstile> loc [:\<le>\<^sub>\<top>] LT" and n: "n < size LT" and
      LTn: "LT!n = OK T" and subtype: "P \<turnstile> T \<le> T'"
shows "P,h \<turnstile> (loc!n) :\<le> T'"
(*<*)
proof -
  have len: "n < length loc" using list_all2_lengthD[OF confTs] n
    by simp
  show ?thesis
   using list_all2_nthD[OF confTs len] conf_widen[OF _ subtype] LTn
    by simp
qed
(*>*)

lemma confTs_hext [intro?]:
  "P,h \<turnstile> loc [:\<le>\<^sub>\<top>] LT \<Longrightarrow> h \<unlhd> h' \<Longrightarrow> P,h' \<turnstile> loc [:\<le>\<^sub>\<top>] LT"
  by (fast elim: list_all2_mono confT_hext)

lemma confTs_widen [intro?, trans]:
  "P,h \<turnstile> loc [:\<le>\<^sub>\<top>] LT \<Longrightarrow> P \<turnstile> LT [\<le>\<^sub>\<top>] LT' \<Longrightarrow> P,h \<turnstile> loc [:\<le>\<^sub>\<top>] LT'"
  by (rule list_all2_trans, rule confT_widen)

lemma confTs_map [iff]:
  "\<And>vs. (P,h \<turnstile> vs [:\<le>\<^sub>\<top>] map OK Ts) = (P,h \<turnstile> vs [:\<le>] Ts)"
  by (induct Ts) (auto simp: list_all2_Cons2)

lemma reg_widen_Err [iff]:
  "\<And>LT. (P \<turnstile> replicate n Err [\<le>\<^sub>\<top>] LT) = (LT = replicate n Err)"
  by (induct n) (auto simp: list_all2_Cons1)

subsection \<open> valid @{text "init_call_status"} \<close>

lemma valid_ics_shupd:
assumes "P,h,sh \<turnstile>\<^sub>i (C, M, pc, ics)" and "distinct (C'#ics_classes ics)"
shows "P,h,sh(C' \<mapsto> (sfs, i')) \<turnstile>\<^sub>i (C, M, pc, ics)"
using assms by(cases ics; clarsimp simp: fun_upd_apply) fastforce

subsection \<open> correct-frame \<close>

lemma conf_f_Throwing:
assumes "conf_f P h sh (ST, LT) is (stk, loc, C, M, pc, Called Cs)"
  and "is_class P C'" and "h xcp = Some obj" and "sh C' = Some(sfs,Processing)"
shows "conf_f P h sh (ST, LT) is (stk, loc, C, M, pc, Throwing (C' # Cs) xcp)"
using assms by(auto simp: conf_f_def2)

lemma conf_f_shupd:
assumes "conf_f P h sh (ST,LT) ins f"
 and "i = Processing
       \<or> (distinct (C#ics_classes (ics_of f)) \<and> (curr_method f = clinit \<longrightarrow> C \<noteq> curr_class f))"
shows "conf_f P h (sh(C \<mapsto> (sfs, i))) (ST,LT) ins f"
using assms
 by(cases f, cases "ics_of f"; clarsimp simp: conf_f_def2 fun_upd_apply) fastforce+

lemma conf_f_shupd':
assumes "conf_f P h sh (ST,LT) ins f"
 and "sh C = Some(sfs,i)"
shows "conf_f P h (sh(C \<mapsto> (sfs', i))) (ST,LT) ins f"
using assms
 by(cases f, cases "ics_of f"; clarsimp simp: conf_f_def2 fun_upd_apply) fastforce+

subsection \<open> correct-frames \<close>

lemmas [simp del] = fun_upd_apply

lemma conf_fs_hext:
  "\<And>C M n T\<^sub>r.
  \<lbrakk> conf_fs P h sh \<Phi> C M n T\<^sub>r frs; h \<unlhd> h' \<rbrakk> \<Longrightarrow> conf_fs P h' sh \<Phi> C M n T\<^sub>r frs"
(*<*)
proof(induct frs)
  case (Cons fr frs)
  obtain stk ls C M pc ics where fr: "fr = (stk, ls, C, M, pc, ics)" by(cases fr) simp
  moreover obtain ST LT where \<Phi>: "\<Phi> C M ! pc = \<lfloor>(ST, LT)\<rfloor>" and
     ST: "P,h \<turnstile> stk [:\<le>] ST" and LT: "P,h \<turnstile> ls [:\<le>\<^sub>\<top>] LT"
    using Cons.prems(1) fr by(auto simp: conf_f_def)
  ultimately show ?case using Cons confs_hext[OF ST Cons(3)] confTs_hext[OF LT Cons(3)]
    by (fastforce simp: conf_f_def)
qed simp
(*>*)

lemma conf_fs_shupd:
assumes "conf_fs P h sh \<Phi> C\<^sub>0 M n T frs"
 and dist: "distinct (C#clinit_classes frs)"
shows "conf_fs P h (sh(C \<mapsto> (sfs, i))) \<Phi> C\<^sub>0 M n T frs"
using assms proof(induct frs arbitrary: C\<^sub>0 C M n T)
  case (Cons f' frs')
  then obtain stk' loc' C' M' pc' ics' where f': "f' = (stk',loc',C',M',pc',ics')" by(cases f')
  with assms Cons obtain ST LT b Ts T1 mxs mxl\<^sub>0 ins xt where
    ty: "\<Phi> C' M' ! pc' = Some (ST,LT)" and
    meth: "P \<turnstile> C' sees M',b:Ts \<rightarrow> T1 = (mxs,mxl\<^sub>0,ins,xt) in C'" and
    conf: "conf_f P h sh (ST, LT) ins f'" and
    confs: "conf_fs P h sh \<Phi> C' M' (size Ts) T1 frs'" by clarsimp

  from f' Cons.prems(2) have
   "distinct (C#ics_classes (ics_of f')) \<and> (curr_method f' = clinit \<longrightarrow> C \<noteq> curr_class f')"
     by fastforce
  with conf_f_shupd[where C=C, OF conf] have
    conf': "conf_f P h (sh(C \<mapsto> (sfs, i))) (ST, LT) ins f'" by simp

  from Cons.prems(2) have dist': "distinct (C # clinit_classes frs')"
    by(auto simp: distinct_length_2_or_more)
  from Cons.hyps[OF confs dist'] have
    confs': "conf_fs P h (sh(C \<mapsto> (sfs, i))) \<Phi> C' M' (length Ts) T1 frs'" by simp

  from conf' confs' ty meth f' Cons.prems show ?case by(fastforce dest: sees_method_fun)
qed(simp)

lemma conf_fs_shupd':
assumes "conf_fs P h sh \<Phi> C\<^sub>0 M n T frs"
 and shC: "sh C = Some(sfs,i)"
shows "conf_fs P h (sh(C \<mapsto> (sfs', i))) \<Phi> C\<^sub>0 M n T frs"
using assms proof(induct frs arbitrary: C\<^sub>0 C M n T sfs i sfs')
  case (Cons f' frs')
  then obtain stk' loc' C' M' pc' ics' where f': "f' = (stk',loc',C',M',pc',ics')" by(cases f')
  with assms Cons obtain ST LT b Ts T1 mxs mxl\<^sub>0 ins xt where
    ty: "\<Phi> C' M' ! pc' = Some (ST,LT)" and
    meth: "P \<turnstile> C' sees M',b:Ts \<rightarrow> T1 = (mxs,mxl\<^sub>0,ins,xt) in C'" and
    conf: "conf_f P h sh (ST, LT) ins f'" and
    confs: "conf_fs P h sh \<Phi> C' M' (size Ts) T1 frs'" and
    shC': "sh C = Some(sfs,i)" by clarsimp

  have conf': "conf_f P h (sh(C \<mapsto> (sfs', i))) (ST, LT) ins f'" by(rule conf_f_shupd'[OF conf shC'])

  from Cons.hyps[OF confs shC'] have
    confs': "conf_fs P h (sh(C \<mapsto> (sfs', i))) \<Phi> C' M' (length Ts) T1 frs'" by simp

  from conf' confs' ty meth f' Cons.prems show ?case by(fastforce dest: sees_method_fun)
qed(simp)

subsection \<open> correctness wrt @{term clinit} use \<close>

lemma conf_clinit_Cons:
assumes "conf_clinit P sh (f#frs)"
shows "conf_clinit P sh frs"
proof -
  from assms have dist: "distinct_clinit (f#frs)"
   by(cases "curr_method f = clinit", auto simp: conf_clinit_def)
  then have dist': "distinct_clinit frs" by(simp add: distinct_clinit_def)

  with assms show ?thesis by(cases frs; fastforce simp: conf_clinit_def)
qed

lemma conf_clinit_Cons_Cons:
 "conf_clinit P sh (f'#f#frs) \<Longrightarrow> conf_clinit P sh (f'#frs)"
 by(auto simp: conf_clinit_def distinct_clinit_def)

lemma conf_clinit_diff:
assumes "conf_clinit P sh ((stk,loc,C,M,pc,ics)#frs)"
shows "conf_clinit P sh ((stk',loc',C,M,pc',ics)#frs)"
using assms by(cases "M = clinit", simp_all add: conf_clinit_def distinct_clinit_def)

lemma conf_clinit_diff':
assumes "conf_clinit P sh ((stk,loc,C,M,pc,ics)#frs)"
shows "conf_clinit P sh ((stk',loc',C,M,pc',No_ics)#frs)"
using assms by(cases "M = clinit", simp_all add: conf_clinit_def distinct_clinit_def)

lemma conf_clinit_Called_Throwing:
 "conf_clinit P sh ((stk', loc', C', clinit, pc', ics') # (stk, loc, C, M, pc, Called Cs) # fs)
  \<Longrightarrow> conf_clinit P sh ((stk, loc, C, M, pc, Throwing (C' # Cs) xcp) # fs)"
 by(simp add: conf_clinit_def distinct_clinit_def)

lemma conf_clinit_Throwing:
 "conf_clinit P sh ((stk, loc, C, M, pc, Throwing (C'#Cs) xcp) # fs)
  \<Longrightarrow> conf_clinit P sh ((stk, loc, C, M, pc, Throwing Cs xcp) # fs)"
 by(simp add: conf_clinit_def distinct_clinit_def)

lemma conf_clinit_Called:
 "\<lbrakk> conf_clinit P sh ((stk, loc, C, M, pc, Called (C'#Cs)) # frs);
    P \<turnstile> C' sees clinit,Static: [] \<rightarrow> Void=(mxs',mxl',ins',xt') in C' \<rbrakk>
  \<Longrightarrow> conf_clinit P sh (create_init_frame P C' # (stk, loc, C, M, pc, Called Cs) # frs)"
 by(simp add: conf_clinit_def distinct_clinit_def)

lemma conf_clinit_Cons_nclinit:
assumes "conf_clinit P sh frs" and nclinit: "M \<noteq> clinit"
shows "conf_clinit P sh ((stk, loc, C, M, pc, No_ics) # frs)"
proof -
  from nclinit
  have "clinit_classes ((stk, loc, C, M, pc, No_ics) # frs) = clinit_classes frs" by simp
  with assms show ?thesis by(simp add: conf_clinit_def distinct_clinit_def)
qed

lemma conf_clinit_Invoke:
assumes "conf_clinit P sh ((stk, loc, C, M, pc, ics) # frs)" and "M' \<noteq> clinit"
shows "conf_clinit P sh ((stk', loc', C', M', pc', No_ics) # (stk, loc, C, M, pc, No_ics) # frs)"
 using assms conf_clinit_Cons_nclinit conf_clinit_diff' by auto

lemma conf_clinit_nProc_dist:
assumes "conf_clinit P sh frs"
  and "\<forall>sfs. sh C \<noteq> Some(sfs,Processing)"
shows "distinct (C # clinit_classes frs)"
using assms by(auto simp: conf_clinit_def distinct_clinit_def)

lemma conf_clinit_shupd:
assumes "conf_clinit P sh frs"
 and dist: "distinct (C#clinit_classes frs)"
shows "conf_clinit P (sh(C \<mapsto> (sfs, i))) frs"
using assms by(simp add: conf_clinit_def fun_upd_apply)

lemma conf_clinit_shupd':
assumes "conf_clinit P sh frs"
 and "sh C = Some(sfs,i)"
shows "conf_clinit P (sh(C \<mapsto> (sfs', i))) frs"
using assms by(fastforce simp: conf_clinit_def fun_upd_apply)

lemma conf_clinit_shupd_Called:
assumes "conf_clinit P sh ((stk,loc,C,M,pc,Calling C' Cs)#frs)"
 and dist: "distinct (C'#clinit_classes ((stk,loc,C,M,pc,Calling C' Cs)#frs))"
 and cls: "is_class P C'"
shows "conf_clinit P (sh(C' \<mapsto> (sfs, Processing))) ((stk,loc,C,M,pc,Called (C'#Cs))#frs)"
using assms by(clarsimp simp: conf_clinit_def fun_upd_apply distinct_clinit_def)

lemma conf_clinit_shupd_Calling:
assumes "conf_clinit P sh ((stk,loc,C,M,pc,Calling C' Cs)#frs)"
 and dist: "distinct (C'#clinit_classes ((stk,loc,C,M,pc,Calling C' Cs)#frs))"
 and cls: "is_class P C'"
shows "conf_clinit P (sh(C' \<mapsto> (sfs, Processing)))
         ((stk,loc,C,M,pc,Calling (fst(the(class P C'))) (C'#Cs))#frs)"
using assms by(clarsimp simp: conf_clinit_def fun_upd_apply distinct_clinit_def)

subsection \<open> correct state \<close>

lemma correct_state_Cons:
assumes cr: "P,\<Phi> |- (xp,h,f#frs,sh) [ok]"
shows "P,\<Phi> |- (xp,h,frs,sh) [ok]"
proof -
  from cr have dist: "conf_clinit P sh (f#frs)"
   by(simp add: correct_state_def)
  then have "conf_clinit P sh frs" by(rule conf_clinit_Cons)

  with cr show ?thesis by(cases frs; fastforce simp: correct_state_def)
qed

lemma correct_state_shupd:
assumes cs: "P,\<Phi> |- (xp,h,frs,sh) [ok]" and shC: "sh C = Some(sfs,i)"
 and dist: "distinct (C#clinit_classes frs)"
shows "P,\<Phi> |- (xp,h,frs,sh(C \<mapsto> (sfs, i'))) [ok]"
using assms
proof(cases xp)
  case None with assms show ?thesis
  proof(cases frs)
    case (Cons f' frs')
    let ?sh = "sh(C \<mapsto> (sfs, i'))"

    obtain stk' loc' C' M' pc' ics' where f': "f' = (stk',loc',C',M',pc',ics')" by(cases f')
    with cs Cons None obtain b Ts T mxs mxl\<^sub>0 ins xt ST LT where
         meth: "P \<turnstile> C' sees M',b:Ts\<rightarrow>T = (mxs,mxl\<^sub>0,ins,xt) in C'"
     and ty: "\<Phi> C' M' ! pc' = Some (ST,LT)" and conf: "conf_f P h sh (ST,LT) ins f'"
     and confs: "conf_fs P h sh \<Phi> C' M' (size Ts) T frs'"
     and confc: "conf_clinit P sh frs"
     and h_ok: "P\<turnstile> h\<surd>" and sh_ok: "P,h \<turnstile>\<^sub>s sh \<surd>"
    by(auto simp: correct_state_def)

    from Cons dist have dist': "distinct (C#clinit_classes frs')"
     by(auto simp: distinct_length_2_or_more)

    from shconf_upd_obj[OF sh_ok shconfD[OF sh_ok shC]] have sh_ok': "P,h \<turnstile>\<^sub>s ?sh \<surd>"
      by simp

    from conf f' valid_ics_shupd Cons dist have conf': "conf_f P h ?sh (ST,LT) ins f'"
     by(auto simp: conf_f_def2 fun_upd_apply)
    have confs': "conf_fs P h ?sh \<Phi> C' M' (size Ts) T frs'" by(rule conf_fs_shupd[OF confs dist'])

    have confc': "conf_clinit P ?sh frs" by(rule conf_clinit_shupd[OF confc dist])

    with h_ok sh_ok' meth ty conf' confs' f' Cons None show ?thesis
     by(fastforce simp: correct_state_def)
  qed(simp add: correct_state_def)
qed(simp add: correct_state_def)

lemma correct_state_Throwing_ex:
assumes correct: "P,\<Phi> \<turnstile> (xp,h,(stk,loc,C,M,pc,ics)#frs,sh)\<surd>"
shows "\<And>Cs a. ics = Throwing Cs a \<Longrightarrow> \<exists>obj. h a = Some obj"
using correct by(clarsimp simp: correct_state_def conf_f_def)

end


theory Proof_2_3
  imports Requirements VCTheoryLemmas
begin

theorem proof_2_3: "VC3 inv2 s0 requestButtonValue"
  apply(simp only: VC3_def inv2_def  R2_def extraInv_def)
proof
  print_state
  assume "((toEnvP s0 \<and>
      (\<forall>s1 s2 s3.
          substate s1 s2 \<and>
          substate s2 s3 \<and>
          substate s3 s0 \<and>
          toEnvP s1 \<and>
          toEnvP s2 \<and>
          toEnvP s3 \<and>
          toEnvNum s1 s2 = Ctrl \<and>
          toEnvNum s2 s3 < T2 \<and> getVarBool s1 minimalRed \<noteq> PRESSED \<and> getVarBool s2 minimalRed = PRESSED \<longrightarrow>
          getVarBool s3 minimalRed = PRESSED)) \<and>
     toEnvP s0 \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = minimalRed \<longrightarrow>
           0 < ltimeEnv s1 Ctrl \<and> ltimeEnv s1 Ctrl \<le> MINIMAL_RED_TIME_LIMIT) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = minimalRed \<longrightarrow>
           (\<exists>s2. toEnvP s2 \<and>
                 substate s2 s1 \<and>
                 toEnvNum s2 s1 = ltimeEnv s1 Ctrl \<and> getPstate s2 Ctrl = green \<and> ltimeEnv s2 Ctrl = T2) \<or>
           (\<forall>s2. toEnvP s2 \<and> substate s2 s1 \<longrightarrow> getPstate s2 Ctrl = minimalRed)) \<and>
     (\<forall>s1 s2.
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         substate s1 s2 \<and> substate s2 s0 \<and> getPstate s2 Ctrl = minimalRed \<and> toEnvNum s1 s2 < ltimeEnv s2 Ctrl \<longrightarrow>
         getPstate s1 Ctrl = minimalRed) \<and>
     (\<forall>s1 s2.
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         substate s1 s2 \<and>
         substate s2 s0 \<and> (\<forall>s3. toEnvP s3 \<and> substate s1 s3 \<and> substate s3 s2 \<longrightarrow> getPstate s3 Ctrl = minimalRed) \<longrightarrow>
         toEnvNum s1 s2 = ltimeEnv s2 Ctrl - ltimeEnv s1 Ctrl) \<and>
     (\<forall>s1. toEnvP s1 \<and>
           substate s1 s0 \<and> getPstate s1 Ctrl = redAfterMinimalRed \<and> getVarBool s1 redAfterMinimalRed = NOT_PRESSED \<longrightarrow>
           (\<exists>s2. toEnvP s2 \<and>
                 substate s2 s1 \<and>
                 getPstate s2 Ctrl = minimalRed \<and>
                 ltimeEnv s2 Ctrl = MINIMAL_RED_TIME_LIMIT \<and>
                 getVarBool s2 redAfterMinimalRed = NOT_PRESSED \<and>
                 (\<forall>s3. toEnvP s3 \<and> substate s2 s3 \<and> substate s3 s1 \<and> s2 \<noteq> s3 \<longrightarrow>
                       getPstate s3 Ctrl = redAfterMinimalRed \<and>
                       getVarBool s3 redAfterMinimalRed = NOT_PRESSED \<and> getVarBool s3 Ctrl = NOT_PRESSED))) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = redToGreen \<longrightarrow>
           0 < ltimeEnv s1 Ctrl \<and> ltimeEnv s1 Ctrl \<le> RED_TO_GREEN_TIME_LIMIT) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = redToGreen \<longrightarrow>
           (\<exists>s2. toEnvP s2 \<and>
                 substate s2 s1 \<and>
                 toEnvNum s2 s1 = ltimeEnv s1 Ctrl \<and>
                 getPstate s2 Ctrl = redAfterMinimalRed \<and>
                 (getVarBool s2 redAfterMinimalRed = PRESSED \<or> getVarBool s2 Ctrl = PRESSED))) \<and>
     (\<forall>s1 s2.
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         substate s1 s2 \<and> substate s2 s0 \<and> toEnvNum s1 s2 < ltimeEnv s2 Ctrl \<and> getPstate s2 Ctrl = redToGreen \<longrightarrow>
         getPstate s1 Ctrl = redToGreen) \<and>
     (\<forall>s1 s2.
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         substate s1 s2 \<and>
         substate s2 s0 \<and> (\<forall>s3. toEnvP s3 \<and> substate s1 s3 \<and> substate s3 s2 \<longrightarrow> getPstate s3 Ctrl = redToGreen) \<longrightarrow>
         toEnvNum s1 s2 = ltimeEnv s2 Ctrl - ltimeEnv s1 Ctrl) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = green \<longrightarrow> 0 < ltimeEnv s1 Ctrl \<and> ltimeEnv s1 Ctrl \<le> T2) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = green \<longrightarrow>
           (\<exists>s2. toEnvP s2 \<and>
                 substate s2 s1 \<and>
                 toEnvNum s2 s1 = ltimeEnv s1 Ctrl \<and>
                 getPstate s2 Ctrl = redToGreen \<and> ltimeEnv s2 Ctrl = RED_TO_GREEN_TIME_LIMIT)) \<and>
     (\<forall>s1 s2.
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         substate s1 s2 \<and> substate s2 s0 \<and> getPstate s2 Ctrl = green \<and> toEnvNum s1 s2 < ltimeEnv s2 Ctrl \<longrightarrow>
         getPstate s1 Ctrl = green) \<and>
     (\<forall>s1 s2.
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         substate s1 s2 \<and>
         substate s2 s0 \<and> (\<forall>s3. toEnvP s3 \<and> substate s1 s3 \<and> substate s3 s2 \<longrightarrow> getPstate s3 Ctrl = green) \<longrightarrow>
         toEnvNum s1 s2 = ltimeEnv s2 Ctrl - ltimeEnv s1 Ctrl) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = green \<longrightarrow> getVarBool s1 minimalRed = PRESSED) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl \<noteq> green \<longrightarrow> getVarBool s1 minimalRed = NOT_PRESSED) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<longrightarrow>
           getPstate s1 Ctrl = minimalRed \<or>
           getPstate s1 Ctrl = redAfterMinimalRed \<or> getPstate s1 Ctrl = redToGreen \<or> getPstate s1 Ctrl = green) \<and>
     (\<forall>s1 s2.
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         substate s1 s2 \<and>
         substate s2 s0 \<and>
         toEnvNum s1 s2 < ltimeEnv s2 Ctrl - Ctrl \<and>
         getPstate s2 Ctrl = minimalRed \<and> getVarBool s2 redAfterMinimalRed = NOT_PRESSED \<longrightarrow>
         getVarBool s1 Ctrl = NOT_PRESSED) \<and>
     (\<forall>s2. toEnvP s2 \<and> substate s2 s0 \<and> getPstate s2 Ctrl = minimalRed \<and> getVarBool s2 redAfterMinimalRed = PRESSED \<longrightarrow>
           (\<exists>s1. toEnvP s1 \<and>
                 substate s1 s2 \<and> toEnvNum s1 s2 < ltimeEnv s2 Ctrl - Ctrl \<and> getVarBool s1 Ctrl = PRESSED)) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = redAfterMinimalRed \<and> getVarBool s1 redAfterMinimalRed \<longrightarrow>
           (\<exists>s2. toEnvP s2 \<and>
                 substate s2 s1 \<and>
                 toEnvNum s2 s1 = Ctrl \<and>
                 getPstate s2 Ctrl = minimalRed \<and>
                 ltimeEnv s2 Ctrl = MINIMAL_RED_TIME_LIMIT \<and>
                 (getVarBool s2 redAfterMinimalRed \<or> getVarBool s1 Ctrl = PRESSED))) \<and>
     (\<forall>s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = green \<longrightarrow>
           getVarBool s1 redAfterMinimalRed = NOT_PRESSED)) \<and>
    env (setVarAny s0 requestButtonValue) requestButtonValue \<and>
    getPstate (setVarAny s0 requestButtonValue) Ctrl = minimalRed \<and>
    getVarBool (setVarAny s0 requestButtonValue) Ctrl \<and>
    \<not> MINIMAL_RED_TIME_LIMIT
       \<le> ltimeEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED) Ctrl"
  then obtain reqs0: "(toEnvP s0 \<and>
      (\<forall>s1 s2 s3.
          substate s1 s2 \<and>
          substate s2 s3 \<and>
          substate s3 s0 \<and>
          toEnvP s1 \<and>
          toEnvP s2 \<and>
          toEnvP s3 \<and>
          toEnvNum s1 s2 = Ctrl \<and>
          toEnvNum s2 s3 < T2 \<and> getVarBool s1 minimalRed \<noteq> PRESSED \<and> getVarBool s2 minimalRed = PRESSED \<longrightarrow>
          getVarBool s3 minimalRed = PRESSED))"
and ei0: "toEnvP s0"
and ei1: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = minimalRed \<longrightarrow>
 0<ltimeEnv s1 Ctrl \<and>  ltimeEnv s1 Ctrl \<le> MINIMAL_RED_TIME_LIMIT) "
and ei2: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = minimalRed \<longrightarrow>
 ((\<exists> s2. toEnvP s2 \<and> substate s2 s1 \<and> toEnvNum s2 s1 = ltimeEnv s1 Ctrl  \<and>
 getPstate s2 Ctrl = green \<and> ltimeEnv s2 Ctrl = GREEN_TIME_LIMIT) \<or>
 (\<forall> s2. toEnvP s2 \<and> substate s2 s1 \<longrightarrow> getPstate s2 Ctrl = minimalRed))) "
and ei3: "(\<forall> s1 s2. toEnvP s1 \<and> toEnvP s2 \<and> substate s1 s2 \<and> substate s2 s0 \<and> getPstate s2 Ctrl = minimalRed \<and>
 toEnvNum s1 s2 < ltimeEnv s2 Ctrl \<longrightarrow> getPstate s1 Ctrl = minimalRed) "
and ei4: "\<forall> s1 s2. toEnvP s1 \<and> toEnvP s2 \<and> substate s1 s2 \<and> substate s2 s0 \<and>
(\<forall> s3. toEnvP s3 \<and> substate s1 s3 \<and> substate s3 s2 \<longrightarrow> getPstate s3 Ctrl = minimalRed ) \<longrightarrow>
toEnvNum s1 s2 = ltimeEnv s2 Ctrl - ltimeEnv s1 Ctrl"
and ei5: "\<forall> s1 . toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = redAfterMinimalRed \<and>
 getVarBool s1 requestButtonPressed = False \<longrightarrow>
(\<exists> s2. toEnvP s2 \<and> substate s2 s1 \<and> getPstate s2 Ctrl = minimalRed \<and> ltimeEnv s2 Ctrl = MINIMAL_RED_TIME_LIMIT \<and>
getVarBool s2 requestButtonPressed = False \<and> (\<forall> s3. toEnvP s3 \<and> substate s2 s3 \<and> substate s3 s1 \<and> s2 \<noteq> s3 \<longrightarrow>
 getPstate s3 Ctrl = redAfterMinimalRed \<and>
getVarBool s3 requestButtonPressed = False \<and> getVarBool s3  requestButton = NOT_PRESSED))"
and ei6: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = redToGreen \<longrightarrow>
0< ltimeEnv s1 Ctrl \<and> ltimeEnv s1 Ctrl \<le> RED_TO_GREEN_TIME_LIMIT) "
and ei7: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = redToGreen \<longrightarrow>
(\<exists> s2. toEnvP s2  \<and> substate s2 s1 \<and>
 toEnvNum s2 s1 = ltimeEnv s1 Ctrl  \<and> getPstate s2 Ctrl = redAfterMinimalRed \<and>
(getVarBool s2 requestButtonPressed = True \<or> getVarBool s2 requestButton = PRESSED)))"
and ei8: "(\<forall> s1 s2. toEnvP s1 \<and> toEnvP s2 \<and> substate s1 s2 \<and> substate s2 s0 \<and> toEnvNum s1 s2 < ltimeEnv s2 Ctrl \<and>
 getPstate s2 Ctrl = redToGreen \<longrightarrow> getPstate s1 Ctrl = redToGreen) "
and ei9: "(\<forall> s1 s2. toEnvP s1 \<and> toEnvP s2 \<and> substate s1 s2 \<and> substate s2 s0 \<and>
(\<forall> s3. toEnvP s3 \<and> substate s1 s3 \<and> substate s3 s2 \<longrightarrow> getPstate s3 Ctrl = redToGreen) \<longrightarrow>
toEnvNum s1 s2 = ltimeEnv s2 Ctrl - ltimeEnv s1 Ctrl) "
and ei10: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = green \<longrightarrow>
0 < ltimeEnv s1 Ctrl \<and> ltimeEnv s1 Ctrl \<le> GREEN_TIME_LIMIT)"
and ei11: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = green \<longrightarrow>
(\<exists> s2. toEnvP s2 \<and> substate s2 s1 \<and> toEnvNum s2 s1 = ltimeEnv s1 Ctrl \<and>
getPstate s2 Ctrl = redToGreen \<and> ltimeEnv s2 Ctrl = RED_TO_GREEN_TIME_LIMIT)) "
and ei12: "(\<forall> s1 s2. toEnvP s1 \<and> toEnvP s2 \<and> substate s1 s2 \<and> substate s2 s0 \<and> getPstate s2 Ctrl = green \<and>
toEnvNum s1 s2 < ltimeEnv s2 Ctrl \<longrightarrow> getPstate s1 Ctrl = green)"
and ei13: "(\<forall> s1 s2. toEnvP s1 \<and> toEnvP s2 \<and> substate s1 s2 \<and> substate s2 s0 \<and>
(\<forall> s3. toEnvP s3 \<and> substate s1 s3 \<and> substate s3 s2 \<longrightarrow> getPstate s3 Ctrl = green) \<longrightarrow>
toEnvNum s1 s2 = ltimeEnv s2 Ctrl - ltimeEnv s1 Ctrl) "
and ei14: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = green \<longrightarrow> getVarBool s1 trafficLight = GREEN) "
and ei15: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl \<noteq> green \<longrightarrow> getVarBool s1 trafficLight = RED) "
and ei16: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<longrightarrow>
 getPstate s1 Ctrl = minimalRed \<or> getPstate s1 Ctrl = redAfterMinimalRed \<or>
 getPstate s1 Ctrl = redToGreen \<or> getPstate s1 Ctrl = green)"
and ei17: "(\<forall> s1 s2. toEnvP s1 \<and> toEnvP s2 \<and> substate s1 s2 \<and> substate s2 s0 \<and>
 toEnvNum s1 s2 < ltimeEnv s2 Ctrl - 1 \<and>  getPstate s2 Ctrl = minimalRed \<and>
 getVarBool s2 requestButtonPressed = False \<longrightarrow> getVarBool s1 requestButton = NOT_PRESSED)"
and ei18: "(\<forall> s2. toEnvP s2  \<and> substate s2 s0  \<and>
 getPstate s2 Ctrl = minimalRed \<and> getVarBool s2 requestButtonPressed = True \<longrightarrow>
(\<exists> s1. toEnvP s1 \<and> substate s1 s2 \<and> toEnvNum s1 s2 < ltimeEnv s2 Ctrl - 1 \<and> getVarBool s1 requestButton = PRESSED))"
and ei19: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = redAfterMinimalRed \<and> getVarBool s1 requestButtonPressed \<longrightarrow>
(\<exists> s2. toEnvP s2 \<and> substate s2 s1 \<and> toEnvNum s2 s1 = 1 \<and> getPstate s2 Ctrl = minimalRed \<and>
 ltimeEnv s2 Ctrl = MINIMAL_RED_TIME_LIMIT \<and>
 (getVarBool s2 requestButtonPressed \<or> getVarBool s1 requestButton = PRESSED)))"
and ei20: "(\<forall> s1. toEnvP s1 \<and> substate s1 s0 \<and> getPstate s1 Ctrl = green \<longrightarrow> getVarBool s1 requestButtonPressed = False)"
and vc: " env (setVarAny s0 requestButtonValue) requestButtonValue \<and>
    getPstate (setVarAny s0 requestButtonValue) Ctrl = minimalRed \<and>
    getVarBool (setVarAny s0 requestButtonValue) Ctrl \<and>
    \<not> MINIMAL_RED_TIME_LIMIT
       \<le> ltimeEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED) Ctrl"
    by fast
  show "(toEnvP (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
     (\<forall>s1 s2 s3.
         substate s1 s2 \<and>
         substate s2 s3 \<and>
         substate s3 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         toEnvP s3 \<and>
         toEnvNum s1 s2 = Ctrl \<and>
         toEnvNum s2 s3 < T2 \<and> getVarBool s1 minimalRed \<noteq> PRESSED \<and> getVarBool s2 minimalRed = PRESSED \<longrightarrow>
         getVarBool s3 minimalRed = PRESSED)) \<and>
    toEnvP (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = minimalRed \<longrightarrow>
          0 < ltimeEnv s1 Ctrl \<and> ltimeEnv s1 Ctrl \<le> MINIMAL_RED_TIME_LIMIT) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = minimalRed \<longrightarrow>
          (\<exists>s2. toEnvP s2 \<and>
                substate s2 s1 \<and>
                toEnvNum s2 s1 = ltimeEnv s1 Ctrl \<and> getPstate s2 Ctrl = green \<and> ltimeEnv s2 Ctrl = T2) \<or>
          (\<forall>s2. toEnvP s2 \<and> substate s2 s1 \<longrightarrow> getPstate s2 Ctrl = minimalRed)) \<and>
    (\<forall>s1 s2.
        toEnvP s1 \<and>
        toEnvP s2 \<and>
        substate s1 s2 \<and>
        substate s2 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
        getPstate s2 Ctrl = minimalRed \<and> toEnvNum s1 s2 < ltimeEnv s2 Ctrl \<longrightarrow>
        getPstate s1 Ctrl = minimalRed) \<and>
    (\<forall>s1 s2.
        toEnvP s1 \<and>
        toEnvP s2 \<and>
        substate s1 s2 \<and>
        substate s2 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
        (\<forall>s3. toEnvP s3 \<and> substate s1 s3 \<and> substate s3 s2 \<longrightarrow> getPstate s3 Ctrl = minimalRed) \<longrightarrow>
        toEnvNum s1 s2 = ltimeEnv s2 Ctrl - ltimeEnv s1 Ctrl) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = redAfterMinimalRed \<and> getVarBool s1 redAfterMinimalRed = NOT_PRESSED \<longrightarrow>
          (\<exists>s2. toEnvP s2 \<and>
                substate s2 s1 \<and>
                getPstate s2 Ctrl = minimalRed \<and>
                ltimeEnv s2 Ctrl = MINIMAL_RED_TIME_LIMIT \<and>
                getVarBool s2 redAfterMinimalRed = NOT_PRESSED \<and>
                (\<forall>s3. toEnvP s3 \<and> substate s2 s3 \<and> substate s3 s1 \<and> s2 \<noteq> s3 \<longrightarrow>
                      getPstate s3 Ctrl = redAfterMinimalRed \<and>
                      getVarBool s3 redAfterMinimalRed = NOT_PRESSED \<and> getVarBool s3 Ctrl = NOT_PRESSED))) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = redToGreen \<longrightarrow>
          0 < ltimeEnv s1 Ctrl \<and> ltimeEnv s1 Ctrl \<le> RED_TO_GREEN_TIME_LIMIT) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = redToGreen \<longrightarrow>
          (\<exists>s2. toEnvP s2 \<and>
                substate s2 s1 \<and>
                toEnvNum s2 s1 = ltimeEnv s1 Ctrl \<and>
                getPstate s2 Ctrl = redAfterMinimalRed \<and>
                (getVarBool s2 redAfterMinimalRed = PRESSED \<or> getVarBool s2 Ctrl = PRESSED))) \<and>
    (\<forall>s1 s2.
        toEnvP s1 \<and>
        toEnvP s2 \<and>
        substate s1 s2 \<and>
        substate s2 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
        toEnvNum s1 s2 < ltimeEnv s2 Ctrl \<and> getPstate s2 Ctrl = redToGreen \<longrightarrow>
        getPstate s1 Ctrl = redToGreen) \<and>
    (\<forall>s1 s2.
        toEnvP s1 \<and>
        toEnvP s2 \<and>
        substate s1 s2 \<and>
        substate s2 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
        (\<forall>s3. toEnvP s3 \<and> substate s1 s3 \<and> substate s3 s2 \<longrightarrow> getPstate s3 Ctrl = redToGreen) \<longrightarrow>
        toEnvNum s1 s2 = ltimeEnv s2 Ctrl - ltimeEnv s1 Ctrl) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = green \<longrightarrow>
          0 < ltimeEnv s1 Ctrl \<and> ltimeEnv s1 Ctrl \<le> T2) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = green \<longrightarrow>
          (\<exists>s2. toEnvP s2 \<and>
                substate s2 s1 \<and>
                toEnvNum s2 s1 = ltimeEnv s1 Ctrl \<and>
                getPstate s2 Ctrl = redToGreen \<and> ltimeEnv s2 Ctrl = RED_TO_GREEN_TIME_LIMIT)) \<and>
    (\<forall>s1 s2.
        toEnvP s1 \<and>
        toEnvP s2 \<and>
        substate s1 s2 \<and>
        substate s2 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
        getPstate s2 Ctrl = green \<and> toEnvNum s1 s2 < ltimeEnv s2 Ctrl \<longrightarrow>
        getPstate s1 Ctrl = green) \<and>
    (\<forall>s1 s2.
        toEnvP s1 \<and>
        toEnvP s2 \<and>
        substate s1 s2 \<and>
        substate s2 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
        (\<forall>s3. toEnvP s3 \<and> substate s1 s3 \<and> substate s3 s2 \<longrightarrow> getPstate s3 Ctrl = green) \<longrightarrow>
        toEnvNum s1 s2 = ltimeEnv s2 Ctrl - ltimeEnv s1 Ctrl) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = green \<longrightarrow>
          getVarBool s1 minimalRed = PRESSED) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl \<noteq> green \<longrightarrow>
          getVarBool s1 minimalRed = NOT_PRESSED) \<and>
    (\<forall>s1. toEnvP s1 \<and> substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<longrightarrow>
          getPstate s1 Ctrl = minimalRed \<or>
          getPstate s1 Ctrl = redAfterMinimalRed \<or> getPstate s1 Ctrl = redToGreen \<or> getPstate s1 Ctrl = green) \<and>
    (\<forall>s1 s2.
        toEnvP s1 \<and>
        toEnvP s2 \<and>
        substate s1 s2 \<and>
        substate s2 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
        toEnvNum s1 s2 < ltimeEnv s2 Ctrl - Ctrl \<and>
        getPstate s2 Ctrl = minimalRed \<and> getVarBool s2 redAfterMinimalRed = NOT_PRESSED \<longrightarrow>
        getVarBool s1 Ctrl = NOT_PRESSED) \<and>
    (\<forall>s2. toEnvP s2 \<and>
          substate s2 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s2 Ctrl = minimalRed \<and> getVarBool s2 redAfterMinimalRed = PRESSED \<longrightarrow>
          (\<exists>s1. toEnvP s1 \<and>
                substate s1 s2 \<and> toEnvNum s1 s2 < ltimeEnv s2 Ctrl - Ctrl \<and> getVarBool s1 Ctrl = PRESSED)) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = redAfterMinimalRed \<and> getVarBool s1 redAfterMinimalRed \<longrightarrow>
          (\<exists>s2. toEnvP s2 \<and>
                substate s2 s1 \<and>
                toEnvNum s2 s1 = Ctrl \<and>
                getPstate s2 Ctrl = minimalRed \<and>
                ltimeEnv s2 Ctrl = MINIMAL_RED_TIME_LIMIT \<and>
                (getVarBool s2 redAfterMinimalRed \<or> getVarBool s1 Ctrl = PRESSED))) \<and>
    (\<forall>s1. toEnvP s1 \<and>
          substate s1 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
          getPstate s1 Ctrl = green \<longrightarrow>
          getVarBool s1 redAfterMinimalRed = NOT_PRESSED)"
    apply(rule conjI)
     apply(rule conjI)
    apply(simp)
  proof(rule allI; rule allI; rule allI)
    fix s1 s2 s3
    show "substate s1 s2 \<and>
         substate s2 s3 \<and>
         substate s3 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         toEnvP s3 \<and>
         toEnvNum s1 s2 = Ctrl \<and>
         toEnvNum s2 s3 < T2 \<and> getVarBool s1 minimalRed \<noteq> PRESSED \<and> getVarBool s2 minimalRed = PRESSED \<longrightarrow>
         getVarBool s3 minimalRed = PRESSED"
    proof cases
      assume 1: "s3 =  (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED))"
      from ei2 ei0 vc substate_refl have " ((\<exists> s2. toEnvP s2 \<and> substate s2 s0
 \<and> toEnvNum s2 s0 = ltimeEnv s0 Ctrl  \<and>
 getPstate s2 Ctrl = green \<and> ltimeEnv s2 Ctrl = GREEN_TIME_LIMIT) \<or>
 (\<forall> s2. toEnvP s2 \<and> substate s2 s0 \<longrightarrow> getPstate s2 Ctrl = minimalRed))"
        by auto
      thus ?thesis
      proof
        assume "\<exists>s2. toEnvP s2 \<and>
         substate s2 s0 \<and> toEnvNum s2 s0 = ltimeEnv s0 Ctrl \<and> getPstate s2 Ctrl = green \<and> ltimeEnv s2 Ctrl = T2"
        then obtain g where 2: "toEnvP g \<and>
         substate g s0 \<and> toEnvNum g s0 = ltimeEnv s0 Ctrl \<and> getPstate g Ctrl = green \<and> ltimeEnv g Ctrl = T2" ..
        show ?thesis
        proof cases
          assume 4: "substate s2 g"
          from ei11 2 have "(\<exists> s2. toEnvP s2 \<and> substate s2 g \<and> toEnvNum s2 g = ltimeEnv g Ctrl \<and>
getPstate s2 Ctrl = redToGreen \<and> ltimeEnv s2 Ctrl = RED_TO_GREEN_TIME_LIMIT)" by blast
          then obtain rg where 3: " toEnvP rg \<and> substate rg g \<and> toEnvNum rg g = ltimeEnv g Ctrl \<and>
getPstate rg Ctrl = redToGreen \<and> ltimeEnv rg Ctrl = RED_TO_GREEN_TIME_LIMIT" ..
          show ?thesis
          proof cases
            assume 5: "substate s2 rg"
            from ei0 have "0 < ltimeEnv s0 Ctrl" by ((cases s0); auto)
            with 2 3 toEnvNum3[of rg g s0] substate_trans[of rg g s0] have 6: "toEnvNum rg s0 > T2"
              by auto
            from 2 3 substate_trans have "substate rg s0" by blast
            with 5 6 toEnvNum3[of s2 rg s0] substate_trans[of s2 rg s0] have "toEnvNum s2 s0 > T2"
              by auto
            with 1 show ?thesis by auto
          next
            assume 5: "\<not> (substate s2 rg)"
            with 3 4 substate_refl substate_total have 6: "substate rg s2 \<and> rg \<noteq> s2" by auto
            show ?thesis
            proof
              assume 7: "substate s1 s2 \<and>
         substate s2 s3 \<and>
         substate s3 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         toEnvP s3 \<and>
         toEnvNum s1 s2 = Ctrl \<and>
         toEnvNum s2 s3 < T2 \<and> getVarBool s1 minimalRed \<noteq> PRESSED \<and> getVarBool s2 minimalRed = PRESSED"
              show "getVarBool s3 minimalRed = PRESSED"
              proof cases
                assume 8: "substate s1 rg"
               from ei0 have "0 < ltimeEnv s0 Ctrl" by ((cases s0); auto)
            with 2 3 toEnvNum3[of rg g s0] substate_trans[of rg g s0] have 6: "toEnvNum rg s0 > T2"
              by auto
            from 2 3 substate_trans have "substate rg s0" by blast
            with 8 6 toEnvNum3 have 9: "toEnvNum s1 s0 > T2" by auto
            from 1 7 9 have 10: "substate s2 s0" by ((simp split: if_splits); auto)
            with 7 9 toEnvNum3 have "toEnvNum s2 s0 \<ge> T2" by auto
            with 1 10 substate_refl toEnvNum3[of s2 s0 s3] have "toEnvNum s2 s3 > T2" by auto
            with 7 show ?thesis by auto
          next
            assume 8: "\<not> substate s1 rg"
            from 4 7 substate_trans have 9: "substate s1 g" by blast
            from 2 4 substate_trans have 10: "substate s2 s0" by blast
            with 1 7 substate_refl substate_asym[of s0 s3]  have "toEnvNum s2 s0 + 1 < T2" by ((simp split: if_splits); auto)
            with 7 10 toEnvNum3 have "toEnvNum s1 s0 < T2" by auto
            with 2 9 toEnvNum3 have "toEnvNum s1 g < ltimeEnv g Ctrl" by auto
            with 2 7 9 ei12 have "getPstate s1 Ctrl = green" by blast
            with ei14 7 show ?thesis using 2 9 substate_trans by blast
          qed
        qed
      qed
    next
      assume 4: "\<not> substate s2 g"
      show ?thesis
      proof
        assume 7: "substate s1 s2 \<and>
         substate s2 s3 \<and>
         substate s3 (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
         toEnvP s1 \<and>
         toEnvP s2 \<and>
         toEnvP s3 \<and>
         toEnvNum s1 s2 = Ctrl \<and>
         toEnvNum s2 s3 < T2 \<and> getVarBool s1 minimalRed \<noteq> PRESSED \<and> getVarBool s2 minimalRed = PRESSED"
        have "getVarBool s2 minimalRed =NOT_PRESSED"
        proof cases
          assume 3: "s2 =  (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED))"
          from vc have "getPstate s0 Ctrl \<noteq> green" by auto
          with ei0 substate_refl ei15 have "getVarBool s0 trafficLight = RED" by blast
          with 3 show ?thesis by auto
        next
          assume 3: "s2 \<noteq>  (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED))"
          with 1 7 have 5: "substate s2 s0" by ((simp split: if_splits); auto)
          from 4 2 5 substate_total substate_refl have 6: "substate g s2 \<and> s2 \<noteq> g" by blast
          with 2 7 gtimeE_inj have 9: "toEnvNum emptyState g \<noteq> toEnvNum emptyState s2" by blast
           from 5 6 toEnvNum3 have "toEnvNum s2 s0 \<le> toEnvNum g s0" by auto
          from le_imp_less_or_eq[OF this]
          show ?thesis
          proof
            assume "toEnvNum s2 s0 < toEnvNum g s0"
            with 2 have 8: "toEnvNum s2 s0 < ltimeEnv s0 Ctrl" by auto
            from vc have "getPstate s0 Ctrl = minimalRed" by auto
            with ei3 7 ei0 5 substate_refl 8 have "getPstate s2 Ctrl = minimalRed" by blast
            with 5 7 ei15 show ?thesis by auto
          next
            assume "toEnvNum s2 s0 = toEnvNum g s0"
            with 9 have 10: "toEnvNum emptyState g +toEnvNum g s0 \<noteq> toEnvNum emptyState s2 +toEnvNum s2 s0"
              by auto
            from emptyState_substate 5 toEnvNum3 have 11: "toEnvNum emptyState s0 = toEnvNum emptyState s2 + toEnvNum s2 s0"
              by auto
            from emptyState_substate 5 6 substate_trans[of g s2 s0]  toEnvNum3
            have  "toEnvNum emptyState s0 = toEnvNum emptyState g + toEnvNum g s0"
              by auto
            with 10 11 show ?thesis by auto
          qed
        qed
        with 7 show " getVarBool s3 minimalRed = PRESSED" by auto
      qed
    qed
  next
    assume 2: " \<forall>s2. toEnvP s2 \<and> substate s2 s0 \<longrightarrow> getPstate s2 Ctrl = minimalRed "
    show " \<forall>s2. toEnvP s2 \<and> substate s2 s0 \<longrightarrow> getPstate s2 Ctrl = minimalRed \<Longrightarrow>
    substate s1 s2 \<and>
    substate s2 s3 \<and>
    substate s3
     (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
    toEnvP s1 \<and>
    toEnvP s2 \<and>
    toEnvP s3 \<and>
    toEnvNum s1 s2 = Ctrl \<and>
    toEnvNum s2 s3 < T2 \<and> getVarBool s1 minimalRed \<noteq> PRESSED \<and> getVarBool s2 minimalRed = PRESSED \<longrightarrow>
    getVarBool s3 minimalRed = PRESSED"
    proof cases
       assume 3: "s2 =  (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED))"
       from vc have "getPstate s0 Ctrl \<noteq> green" by auto
          with ei0 substate_refl ei15 have "getVarBool s0 trafficLight = RED" by blast
          with 3 show ?thesis by auto
        next
          assume 3: "s2 \<noteq>  (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED))"
          show ?thesis
          proof
            assume 7: "substate s1 s2 \<and>
    substate s2 s3 \<and>
    substate s3
     (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
    toEnvP s1 \<and>
    toEnvP s2 \<and>
    toEnvP s3 \<and>
    toEnvNum s1 s2 = Ctrl \<and>
    toEnvNum s2 s3 < T2 \<and> getVarBool s1 minimalRed \<noteq> PRESSED \<and> getVarBool s2 minimalRed = PRESSED"
            with 1  3 have "substate s2 s0" by ((simp split: if_splits); auto)
            with 2 7 ei15  show "  getVarBool s3 minimalRed = PRESSED" by auto
          qed
        qed
      qed
    next
      assume 1: " s3 \<noteq>
   (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED))"
      show ?thesis
      proof
        print_state
        assume 7: "substate s1 s2 \<and>
    substate s2 s3 \<and>
    substate s3
    (toEnv (setVarBool (setVarAny s0 requestButtonValue) redAfterMinimalRed PRESSED)) \<and>
    toEnvP s1 \<and>
    toEnvP s2 \<and>
    toEnvP s3 \<and>
    toEnvNum s1 s2 = Ctrl \<and>
    toEnvNum s2 s3 < T2 \<and> getVarBool s1 minimalRed \<noteq> PRESSED \<and> getVarBool s2 minimalRed = PRESSED"
        with 1 have "substate s3 s0" by ((simp split: if_splits); auto)
        with 7 reqs0         show " getVarBool s3 minimalRed = PRESSED" by blast
      qed
    qed
  next
    (*prove extraInv*)


(*  Title:      HOL/Auth/n_mutualEx_lemma_inv__3_on_rules.thy
    Author:     Yongjian Li and Kaiqiang Duan, State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
    Copyright    2016 State Key Lab of Computer Science, Institute of Software, Chinese Academy of Sciences
*)

theory n_mutualEx_lemma_inv__3_on_rules imports n_mutualEx_lemma_on_inv__3
begin
section{*All lemmas on causal relation between inv__3*}
lemma lemma_inv__3_on_rules:
  assumes b1: "r \<in> rules N" and b2: "(\<exists> p__Inv3 p__Inv4. p__Inv3\<le>N\<and>p__Inv4\<le>N\<and>p__Inv3~=p__Inv4\<and>f=inv__3  p__Inv3 p__Inv4)"
  shows "invHoldForRule Interp s f r (invariants N)"
  proof -
  have c1: "(\<exists> i. i\<le>N\<and>r=n_Try  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_Crit  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_Exit  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_Idle  i)"
  apply (cut_tac b1, auto) done
    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_Try  i)"
      have "invHoldForRule Interp s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_TryVsinv__3) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_Crit  i)"
      have "invHoldForRule Interp s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_CritVsinv__3) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_Exit  i)"
      have "invHoldForRule Interp s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_ExitVsinv__3) done
    }

    moreover {
      assume d1: "(\<exists> i. i\<le>N\<and>r=n_Idle  i)"
      have "invHoldForRule Interp s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_IdleVsinv__3) done
    }

  ultimately show "invHoldForRule Interp s f r (invariants N)"
  by satx
qed

end


(*  Title:      HOL/HOLCF/IOA/Storage/Impl.thy
    Author:     Olaf Müller
*)

section {* The implementation of a memory *}

theory Impl
imports IOA Action
begin

definition
  impl_sig :: "action signature" where
  "impl_sig = (UN l.{Free l} Un {New},
               UN l.{Loc l},
               {})"

definition
  impl_trans :: "(action, nat  * bool)transition set" where
  "impl_trans =
    {tr. let s = fst(tr); k = fst s; b = snd s;
             t = snd(snd(tr)); k' = fst t; b' = snd t
         in
         case fst(snd(tr))
         of
         New       => k' = k & b'  |
         Loc l     => b & l= k & k'= (Suc k) & ~b' |
         Free l    => k'=k & b'=b}"

definition
  impl_ioa :: "(action, nat * bool)ioa" where
  "impl_ioa = (impl_sig, {(0,False)}, impl_trans,{},{})"

lemma in_impl_asig:
  "New : actions(impl_sig) &
    Loc l : actions(impl_sig) &
    Free l : actions(impl_sig) "
  by (simp add: impl_sig_def actions_def asig_projections)

end