theory flash78Bra  imports flash78Rev

  begin
lemma onInv78:

   assumes

     b1:"r \<in> rules N" and b2:"invf=inv78 "
   shows  "invHoldForRule' s invf r (invariants   N)"
   proof -
have c1:"ex1P N (% iRule1 .  r=NI_Local_GetX_PutX1 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_GetX  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Replace  iRule1 )\<or>ex0P N (  r=NI_ShWb N )\<or>ex0P N (  r=PI_Local_GetX_GetX2 )\<or>ex0P N (  r=NI_Local_PutXAcksDone )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX7 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Nak2  iRule1 )\<or>ex0P N (  r=NI_ReplaceHomeShrVld )\<or>ex1P N (% iRule1 .  r=NI_Remote_Put  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX5 N  iRule1 )\<or>ex0P N (  r=NI_Wb )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Get  iRule1 )\<or>ex0P N (  r=PI_Local_Replace )\<or>ex1P N (% iRule1 .  r=NI_ReplaceShrVld  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Local_GetX_PutX8 N  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_InvAck_2 N  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_Get_Nak2  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=PI_Remote_Replace  iRule1 )\<or>ex0P N (  r=NI_Nak_Home )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Put2  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_InvAck_1  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX11 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX6 N  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_Get_Put2  iRule1  iRule2 )\<or>ex0P N (  r=PI_Local_Get_Put )\<or>ex0P N (  r=PI_Local_GetX_PutX1 N )\<or>ex1P N (% iRule1 .  r=NI_InvAck_1_Home  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_Get_Nak1  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Nak1  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_Nak2  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX10_home N  iRule1 )\<or>ex1P N (% iRule1 .  r=PI_Remote_Get  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_Nak3  iRule1 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Local_GetX_PutX10 N  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX2 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_Get_Put1  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_PutX  iRule1 )\<or>ex1P N (% iRule1 .  r=Store  iRule1 )\<or>ex0P N (  r=NI_FAck )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX3 N  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_PutX3 )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_GetX_PutX  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX8_home N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Put1 N  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_GetX1 )\<or>ex0P N (  r=StoreHome )\<or>ex2P N (% iRule1  iRule2 .  r=NI_Remote_GetX_Nak  iRule1  iRule2 )\<or>ex1P N (% iRule1 .  r=NI_Inv  iRule1 )\<or>ex1P N (% iRule1 .  r=PI_Remote_PutX  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_PutX4 )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX4 N  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Nak  iRule1 )\<or>ex0P N (  r=PI_Local_GetX_PutX2 N )\<or>ex0P N (  r=NI_Local_Put )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_Nak1  iRule1 )\<or>ex0P N (  r=NI_Nak_Clear )\<or>ex0P N (  r=PI_Local_PutX )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Nak3  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Remote_GetX_Nak_Home  iRule1 )\<or>ex0P N (  r=PI_Local_Get_Get )\<or>ex1P N (% iRule1 .  r=NI_Local_GetX_PutX9 N  iRule1 )\<or>ex1P N (% iRule1 .  r=PI_Remote_GetX  iRule1 )\<or>ex0P N (  r=NI_ReplaceHome )\<or>ex1P N (% iRule1 .  r=NI_Remote_GetX_PutX_Home  iRule1 )\<or>ex1P N (% iRule1 .  r=NI_Local_Get_Put3  iRule1 )"

        apply(cut_tac  b1)
        apply auto
        done      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX1 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX1 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX1VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_GetX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_GetX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_GetXVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Replace  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Replace  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_ReplaceVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_ShWb N )
"

         from c1 have c2:" r= NI_ShWb N "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (NI_ShWb N ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_ShWbVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_GetX2 )
"

         from c1 have c2:" r= PI_Local_GetX_GetX2 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_GetX_GetX2 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_GetX2VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= NI_Local_PutXAcksDone )
"

         from c1 have c2:" r= NI_Local_PutXAcksDone "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_PutXAcksDone ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Local_PutXAcksDoneVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX7 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX7 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX7VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Nak2  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Nak2  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_Get_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Nak2VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_ReplaceHomeShrVld )
"

         from c1 have c2:" r= NI_ReplaceHomeShrVld "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (NI_ReplaceHomeShrVld ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_ReplaceHomeShrVldVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_Put  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_Put  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_Put  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_PutVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX5 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX5 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX5VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_Wb )
"

         from c1 have c2:" r= NI_Wb "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (NI_Wb ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_WbVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Get  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Get  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_Get_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_GetVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_Replace )
"

         from c1 have c2:" r= PI_Local_Replace "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_Replace ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_ReplaceVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_ReplaceShrVld  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_ReplaceShrVld  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_ReplaceShrVld  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_ReplaceShrVldVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Local_GetX_PutX8 N  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Local_GetX_PutX8 N  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX8VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_InvAck_2 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_InvAck_2 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_InvAck_2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvAck_2VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_Get_Nak2  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_Get_Nak2  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Nak2VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_Replace  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_Replace  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (PI_Remote_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_ReplaceVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_Nak_Home )
"

         from c1 have c2:" r= NI_Nak_Home "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (NI_Nak_Home ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Nak_HomeVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Put2  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Put2  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_Get_Put2  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Put2VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_InvAck_1  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_InvAck_1  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv78 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvAck_1VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX11 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX11 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX11VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX6 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX6 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX6VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_Get_Put2  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_Get_Put2  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Put2VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_Get_Put )
"

         from c1 have c2:" r= PI_Local_Get_Put "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_Get_Put ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_Get_PutVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX1 N )
"

         from c1 have c2:" r= PI_Local_GetX_PutX1 N "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_GetX_PutX1 N ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX1VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_InvAck_1_Home  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_InvAck_1_Home  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_InvAck_1_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvAck_1_HomeVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_Get_Nak1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_Get_Nak1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Nak1VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Nak1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Nak1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Nak1VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_Nak2  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_Nak2  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_Nak2VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX10_home N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX10_home N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX10_homeVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_Get  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_Get  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (PI_Remote_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_GetVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_Nak3  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_Nak3  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_Nak3VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Local_GetX_PutX10 N  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Local_GetX_PutX10 N  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX10VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX2 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX2 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX2VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_Get_Put1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_Get_Put1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_Get_Put1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Put1VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_PutX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_PutX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_PutXVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= Store  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= Store  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (Store  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis StoreVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_FAck )
"

         from c1 have c2:" r= NI_FAck "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (NI_FAck ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_FAckVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX3 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX3 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX3VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX3 )
"

         from c1 have c2:" r= PI_Local_GetX_PutX3 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_GetX_PutX3 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX3VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_GetX_PutX  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_GetX_PutX  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_PutXVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX8_home N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX8_home N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX8_homeVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Put1 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Put1 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Put1VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_GetX1 )
"

         from c1 have c2:" r= PI_Local_GetX_GetX1 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_GetX_GetX1 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_GetX1VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= StoreHome )
"

         from c1 have c2:" r= StoreHome "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (StoreHome ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis StoreHomeVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex2P N (% iRule1  iRule2 .  r= NI_Remote_GetX_Nak  iRule1  iRule2 )
"

         from c1 obtain  iRule1  iRule2  where c2:"  iRule1~=iRule2    \<and>   iRule1 \<le> N \<and>   iRule2 \<le> N \<and>  r= NI_Remote_GetX_Nak  iRule1  iRule2 "
         by (auto simp add: ex2P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_NakVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Inv  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Inv  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Inv  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_PutX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_PutX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (PI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_PutXVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX4 )
"

         from c1 have c2:" r= PI_Local_GetX_PutX4 "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_GetX_PutX4 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX4VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX4 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX4 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX4VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Nak  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Nak  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Nak  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_NakVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_GetX_PutX2 N )
"

         from c1 have c2:" r= PI_Local_GetX_PutX2 N "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_GetX_PutX2 N ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX2VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= NI_Local_Put )
"

         from c1 have c2:" r= NI_Local_Put "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_Put ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Local_PutVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_Nak1  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_Nak1  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_Nak1VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_Nak_Clear )
"

         from c1 have c2:" r= NI_Nak_Clear "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (NI_Nak_Clear ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Nak_ClearVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex0P N (  r= PI_Local_PutX )
"

         from c1 have c2:" r= PI_Local_PutX "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_PutX ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_PutXVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Nak3  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Nak3  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_Get_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Nak3VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_GetX_Nak_Home  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_GetX_Nak_Home  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_Nak_HomeVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= PI_Local_Get_Get )
"

         from c1 have c2:" r= PI_Local_Get_Get "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (PI_Local_Get_Get ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_Get_GetVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_GetX_PutX9 N  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_GetX_PutX9 N  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX9VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= PI_Remote_GetX  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= PI_Remote_GetX  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (PI_Remote_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_GetXVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex0P N (  r= NI_ReplaceHome )
"

         from c1 have c2:" r= NI_ReplaceHome "
         by (auto simp add: ex0P_def)

         have "invHoldForRule' s (inv78 ) (NI_ReplaceHome ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_ReplaceHomeVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
	}      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Remote_GetX_PutX_Home  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Remote_GetX_PutX_Home  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_PutX_HomeVsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }      moreover
        {assume c1: "ex1P N (% iRule1 .  r= NI_Local_Get_Put3  iRule1 )
"

         from c1 obtain  iRule1  where c2:"  iRule1 \<le> N \<and>  r= NI_Local_Get_Put3  iRule1 "
         by (auto simp add: ex1P_def)

         have "invHoldForRule' s (inv78 ) (NI_Local_Get_Put3  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Put3VsInv78 )
          then have "invHoldForRule' s invf r (invariants N) "
            by(cut_tac c2 b2, metis)
        }ultimately show "invHoldForRule' s invf r (invariants N) "
          by blast
     qed
end


theory Capabilities_lemmas
imports Capabilities
begin

lemma leq_cap_refl[simp, intro]:
  "leq_cap CC c c"
  by (simp add: leq_cap_def)

lemma leq_cap_tag_imp[intro]:
  assumes "leq_cap CC c c'"
    and "is_tagged_method CC c"
  shows "is_tagged_method CC c'"
  using assms
  by (auto simp: leq_cap_def)

lemma leq_bounds_trans:
  assumes "leq_bounds CC c c'" and "leq_bounds CC c' c''"
  shows "leq_bounds CC c c''"
  using assms
  by (auto simp: leq_bounds_def)

lemma leq_bools_iff:
  "leq_bools bs1 bs2 \<longleftrightarrow> (\<forall>n < length bs1. bs1 ! n \<longrightarrow> bs2 ! n) \<and> length bs2 = length bs1"
  by (induction bs1 bs2 rule: leq_bools.induct) (auto simp: nth_Cons split: nat.splits)

lemma leq_bools_refl[simp, intro]:
  "leq_bools b b"
  by (auto simp: leq_bools_iff)

lemma leq_perms_refl[simp, intro]:
  "leq_perms CC c c"
  unfolding leq_perms_def
  by auto

lemma leq_bools_trans:
  "leq_bools b b' \<Longrightarrow> leq_bools b' b'' \<Longrightarrow> leq_bools b b''"
  by (auto simp: leq_bools_iff)

lemma leq_perms_trans:
  assumes "leq_perms CC c c'" and "leq_perms CC c' c''"
  shows "leq_perms CC c c''"
  using assms
  unfolding leq_perms_def
  by (metis leq_bools_trans)

lemma leq_cap_trans:
  assumes "leq_cap CC c c'" and "leq_cap CC c' c''"
  shows "leq_cap CC c c''"
  using assms
  by (auto simp: leq_cap_def elim: leq_bounds_trans leq_perms_trans)

lemma address_range_upt[simp]: "address_range start len = [start ..< start + len]"
  by (induction len) (auto simp: address_range_def)

lemma get_mem_region_base_upt_top:
  "get_mem_region CC c = {get_base_method CC c ..< get_top_method CC c}"
  by (auto simp: get_mem_region_def)

lemma leq_cap_get_mem_region_subseteq:
  assumes "leq_cap CC c c'" and "is_tagged_method CC c"
  shows "get_mem_region CC c \<subseteq> get_mem_region CC c'"
  using assms
  by (auto simp: leq_cap_def leq_bounds_def get_mem_region_base_upt_top)

locale Capabilities =
  fixes CC :: "'cap Capability_class"
  assumes is_tagged_seal[simp]: "\<And>c t. is_tagged_method CC (seal_method CC c t) = is_tagged_method CC c"
    and is_tagged_unseal[simp]: "\<And>c. is_tagged_method CC (unseal_method CC c) = is_tagged_method CC c"
    and is_tagged_clear_global[simp]: "\<And>c. is_tagged_method CC (clear_global_method CC c) = is_tagged_method CC c"
    and is_tagged_cap_of_mem_bytes[simp]: "\<And>c bytes tag. cap_of_mem_bytes_method CC bytes tag = Some c \<Longrightarrow> is_tagged_method CC c \<longleftrightarrow> tag = B1"
begin

inductive_set derivable :: "'cap set \<Rightarrow> 'cap set" for C :: "'cap set" where
  Copy: "c \<in> C \<Longrightarrow> c \<in> derivable C"
| Restrict: "c' \<in> derivable C \<Longrightarrow> leq_cap CC c c' \<Longrightarrow> c \<in> derivable C"
| Unseal:
    "\<lbrakk>c' \<in> derivable C; c'' \<in> derivable C; is_tagged_method CC c'; is_tagged_method CC c'';
      \<not>is_sealed_method CC c''; is_sealed_method CC c'; permits_unseal_method CC c'';
      get_obj_type_method CC c' = get_cursor_method CC c'';
      get_cursor_method CC c'' \<in> get_mem_region CC c''\<rbrakk> \<Longrightarrow>
     clear_global_unless CC (is_global_method CC c'') (unseal_method CC c') \<in> derivable C"
| Seal:
    "\<lbrakk>c' \<in> derivable C; c'' \<in> derivable C; is_tagged_method CC c'; is_tagged_method CC c'';
      \<not>is_sealed_method CC c''; \<not>is_sealed_method CC c';
      permits_seal_method CC c''; get_cursor_method CC c'' \<in> get_mem_region CC c''\<rbrakk> \<Longrightarrow>
     seal_method CC c' (get_cursor_method CC c'') \<in> derivable C"
| SealEntry:
    "\<lbrakk>c' \<in> derivable C; is_tagged_method CC c';
      \<not>is_sealed_method CC c';
      is_sentry_method CC (seal_method CC c' otype) \<or> is_indirect_sentry_method CC (seal_method CC c' otype)\<rbrakk> \<Longrightarrow>
     seal_method CC c' otype \<in> derivable C"

lemma derivable_mono:
  assumes "C \<subseteq> C'"
  shows "derivable C \<subseteq> derivable C'"
proof
  fix c
  assume "c \<in> derivable C"
  then show "c \<in> derivable C'" using assms by induction (auto intro: derivable.intros)
qed

lemma cap_derivable_bounded_gteq:
  assumes c: "cap_derivable_bounded CC n C c"
    and m: "m \<ge> n"
  shows "cap_derivable_bounded CC m C c"
proof -
  from m obtain k where "m = n + k" using less_iff_Suc_add[of n m] by auto
  also have "cap_derivable_bounded CC (n + k) C c" using c by (induction k) (auto)
  finally show ?thesis .
qed

lemma derivable_refl: "C \<subseteq> derivable C" by (auto intro: derivable.intros)

lemma derivable_empty: "derivable {} = {}"
proof -
  { fix c
    assume "c \<in> derivable {}"
    then have "False"
      by induction auto
  }
  then show ?thesis by auto
qed

lemma derivable_union_subseteq_absorb:
  assumes "C' \<subseteq> derivable C"
  shows "derivable (C \<union> C') = derivable C"
proof
  show "derivable (C \<union> C') \<subseteq> derivable C"
  proof
    fix c
    assume "c \<in> derivable (C \<union> C')"
    then show "c \<in> derivable C" using assms by induction (auto intro: derivable.intros)
  qed
  show "derivable C \<subseteq> derivable (C \<union> C')" by (intro derivable_mono) auto
qed

lemma derivable_minus_subseteq: "derivable (C - C') \<subseteq> derivable C"
proof
  fix c
  assume "c \<in> derivable (C - C')"
  then show "c \<in> derivable C" by induction (auto intro: derivable.intros)
qed

lemma derivable_Int1_subset:
  "derivable (A \<inter> B) \<subseteq> derivable A"
  by (intro derivable_mono) auto

lemma derivable_Int2_subset:
  "derivable (A \<inter> B) \<subseteq> derivable B"
  by (intro derivable_mono) auto

lemma cap_derivable_iff_derivable: "cap_derivable CC C c \<longleftrightarrow> c \<in> derivable C"
proof
  assume "cap_derivable CC C c"
  then obtain n where c: "cap_derivable_bounded CC n C c" by (auto simp: cap_derivable_def)
  then show "c \<in> derivable C"
    by (induction CC \<equiv> CC n C c rule: cap_derivable_bounded.induct)
       (auto intro: derivable.intros)
next
  assume c: "c \<in> derivable C"
  then have "\<exists>n. cap_derivable_bounded CC n C c"
  proof (induction rule: derivable.induct)
    case (Copy c)
    then have "cap_derivable_bounded CC 0 C c" by auto
    then show ?case by blast
  next
    case (Restrict c' c)
    then obtain n where "cap_derivable_bounded CC n C c'" by auto
    then have "cap_derivable_bounded CC (Suc n) C c" using Restrict.hyps by auto
    then show ?case by blast
  next
    case (Unseal c' c'')
    then obtain n' n''
      where "cap_derivable_bounded CC n' C c'" and "cap_derivable_bounded CC n'' C c''"
      by blast
    then have "cap_derivable_bounded CC (max n' n'') C c'"
      and "cap_derivable_bounded CC (max n' n'') C c''"
      by (auto intro: cap_derivable_bounded_gteq)
    then have "cap_derivable_bounded CC (Suc (max n' n'')) C (clear_global_unless CC (is_global_method CC c'') (unseal_method CC c'))"
      using Unseal.hyps
      by auto
    then show ?case by blast
  next
    case (Seal c' c'')
    then obtain n' n''
      where "cap_derivable_bounded CC n' C c'" and "cap_derivable_bounded CC n'' C c''"
      by blast
    then have "cap_derivable_bounded CC (max n' n'') C c'"
      and "cap_derivable_bounded CC (max n' n'') C c''"
      by (auto intro: cap_derivable_bounded_gteq)
    then have "cap_derivable_bounded CC (Suc (max n' n'')) C (seal_method CC c' (get_cursor_method CC c''))"
      using Seal.hyps
      by auto
    then show ?case by blast
  next
    case (SealEntry c' otype)
    then obtain n where "cap_derivable_bounded CC n C c'"
      by blast
    then have "cap_derivable_bounded CC (Suc n) C (seal_method CC c' otype)"
      using SealEntry.hyps
      by auto
    then show ?case by blast
  qed
  then show "cap_derivable CC C c" by (simp add: cap_derivable_def)
qed

end

locale Capabilities_Bounds_Invariants = Capabilities +
  assumes base_seal_eq: "\<And>c otype. get_base_method CC (seal_method CC c otype) = get_base_method CC c"
    and top_seal_eq: "\<And>c otype. get_top_method CC (seal_method CC c otype) = get_base_method CC c"
    and base_clear_global_eq: "\<And>c cond. get_base_method CC (clear_global_unless CC cond c) = get_base_method CC c"
    and top_clear_global_eq: "\<And>c cond. get_top_method CC (clear_global_unless CC cond c) = get_base_method CC c"
begin

lemma derivable_base_leq_top:
  assumes "\<forall>c \<in> C. is_tagged_method CC c \<longrightarrow> get_base_method CC c \<le> get_top_method CC c"
  shows "\<forall>c \<in> derivable C. is_tagged_method CC c \<longrightarrow> get_base_method CC c \<le> get_top_method CC c"
proof (intro ballI impI)
  fix c
  assume "c \<in> derivable C" and "is_tagged_method CC c"
  then show "get_base_method CC c \<le> get_top_method CC c"
    using assms
    by (induction rule: derivable.induct)
       (auto simp: leq_cap_def leq_bounds_def base_seal_eq top_seal_eq base_clear_global_eq top_clear_global_eq)
qed

end

locale Capabilities_Invariant = Capabilities CC
  for CC :: "'cap Capability_class" +
  fixes cap_invariant :: "'cap \<Rightarrow> bool"
  assumes leq_cap_invariant: "\<And>c c'. cap_invariant c \<Longrightarrow> leq_cap CC c' c \<Longrightarrow> is_tagged_method CC c \<Longrightarrow> is_tagged_method CC c' \<Longrightarrow> cap_invariant c'"
    and seal_cap_invariant: "\<And>c otype. cap_invariant c \<Longrightarrow> is_tagged_method CC c \<Longrightarrow> cap_invariant (seal_method CC c otype)"
    and unseal_cap_invariant: "\<And>c. cap_invariant c \<Longrightarrow> is_tagged_method CC c \<Longrightarrow> cap_invariant (unseal_method CC c)"
    and clear_global_cap_invariant: "\<And>c. cap_invariant c \<Longrightarrow> is_tagged_method CC c \<Longrightarrow> cap_invariant (clear_global_method CC c)"
begin

lemma derivable_cap_invariant:
  assumes "c \<in> derivable C" and "is_tagged_method CC c"
    and "\<forall>c' \<in> C. is_tagged_method CC c' \<longrightarrow> cap_invariant c'"
  shows "cap_invariant c"
  using assms
  by (induction rule: derivable.induct)
     (auto intro: leq_cap_invariant seal_cap_invariant unseal_cap_invariant clear_global_cap_invariant
           simp: clear_global_unless_def)

end

end


(*File: Logic.thy
  Author: L Beringer & M Hofmann, LMU Munich
  Date: 05/12/2008
  Purpose: Definition of axiomatic semantics, with strong
           invariants, pre- and postconditions, and local assertions.
*)
(*<*)
theory Logic imports Language begin
(*>*)

section{*Axiomatic semantics*}

subsection{*Assertion forms *}

text{*We introduce two further kinds of states. Initial states do not
contain operand stacks, terminal states lack operand stacks and local
variables, but include return values.*}

type_synonym InitState = "Store \<times> Heap"
type_synonym TermState = "Heap \<times> Val"

text{*A judgements relating to a specific program point $C.m.l$
consists of pre- and post-conditions, an invariant, and
-- optionally -- a local annotation. Local pre-conditions and
annotations relate initial states to states,
i.e.~are of type*}

type_synonym Assn = "InitState \<Rightarrow> State \<Rightarrow> bool"

text{*Post-conditions additionally depend on a terminal state*}

type_synonym Post = "InitState \<Rightarrow> State \<Rightarrow> TermState \<Rightarrow> bool"

text{*Invariants hold for the heap components of all future
(reachable) states in the current frame as well as its subframes. They
relate these heaps to the current state and the initial state of the
current frame.*}

type_synonym Inv = "InitState \<Rightarrow> State \<Rightarrow> Heap \<Rightarrow> bool"

text{*Local annotations of a method implementation are collected in a
table of type*}

type_synonym ANNO = "(Label, Assn) AssList"

text{*Implicitly, the labels are always interpreted with respect to
the current method. In addition to such a table, the behaviour of
methods is specified by a partial-correctness assertion of type*}

type_synonym MethSpec = "InitState \<Rightarrow> TermState \<Rightarrow> bool"

text{*and a method invariant of type*}

type_synonym MethInv = "InitState \<Rightarrow> Heap \<Rightarrow> bool"

text{*A method invariant is expected to be satisfied by the heap
components of all states during the execution of the method, including
states in subframes, irrespectively of the termination behaviour.*}

text{*All method specifications are collected in a table of type*}

type_synonym MSPEC = "(Class \<times> Method, MethSpec \<times> MethInv \<times> ANNO) AssList"

text{*A table of this type assigns to each method a
partial-correctness specification, a method invariant, and a table of
local annotations for the instructions in this method.*}

subsection{*Proof system \label{SectionSPJudgementProofSystem}*}

text{*The proof system derives judgements of the form $G \rhd \lbrace
A \rbrace C,m,l \lbrace B \rbrace\; I$ where $A$ is a pre-condition,
$B$ is a post-condition, $I$ is a strong invariant, $C.m.l$ represents
a program point, and $G$ is a proof context (see below). The proof
system consists of syntax-directed rules and structural rules. These
rules are formulated in such a way that assertions in the conclusions
are unconstrained, i.e.~a rule can be directly applied to derive a
judgement. In the case of the syntax-directed rules, the hypotheses
require the derivation of related statements for the control flow
successor instructions. Judgements occurring as hypotheses involve
assertions that are notationally constrained, and relate to the
conclusions' assertions via uniform constructions that resemble
strongest postconditions in Hoare-style logics.*}

text{*On pre-conditions, the operator *}

definition SP_pre::"Mbody \<Rightarrow> Label \<Rightarrow> Assn \<Rightarrow> Assn"
where "SP_pre M l A = (\<lambda> s0 r . (\<exists> s l1 n. A s0 s \<and> (M,l,s,n,l1,r):Step))"

text{*constructs an assertion that holds of a state $r$ precisely if
the argument assertion $A$ held at the predecessor state of
$r$. Similar readings explain the constructions on post-conditions*}

definition SP_post::"Mbody \<Rightarrow> Label \<Rightarrow> Post \<Rightarrow> Post"
where "SP_post M l B = (\<lambda> s0 r t . (\<forall> s l1 n. (M,l,s,n,l1,r):Step \<longrightarrow> B s0 s t))"

text{*and invariants*}

definition SP_inv::"Mbody \<Rightarrow> Label \<Rightarrow> Inv \<Rightarrow> Inv"
where "SP_inv M l I = (\<lambda> s0 r h . \<forall> s l1 n. (M,l,s,n,l1,r):Step \<longrightarrow> I s0 s h)"

text{*For the basic instructions, the appearance of the single-step
execution relation in these constructions makes the
strongest-postcondition interpretation apparent, but could easily be
eliminated by unfolding the definition of @{text Step}. In the proof
rule for static method invocations, such a direct reference to the
operational semantics is clearly undesirable. Instead, the proof rule
extracts the invoked method's specification from the specification
table. In order to simplify the formulation of the proof rule, we
introduce three operators which manipulate the extracted assertions in
a similar way as the above @{text SP}-operators.*}

definition SINV_pre::"Var list \<Rightarrow> MethSpec \<Rightarrow> Assn \<Rightarrow> Assn" where
"SINV_pre par T A =
  (\<lambda> s0 s . (\<exists> ops1 ops2 S R h k w.
               (ops1,par,R,ops2) : Frame \<and> T (R, k) (h,w) \<and>
               A s0 (ops1,S,k) \<and> s = (w#ops2,S, h)))"

definition SINV_post::"Var list \<Rightarrow> MethSpec \<Rightarrow> Post \<Rightarrow> Post" where
"SINV_post par T B =
  (\<lambda> s0 s t . \<forall> ops1 ops2 S R h k w r.
               (ops1,par,R,ops2) : Frame \<longrightarrow> T (R, k) (h,w) \<longrightarrow>
               s=(w#ops2,S,h) \<longrightarrow> r=(ops1,S,k) \<longrightarrow> B s0 r t)"

definition SINV_inv::"Var list \<Rightarrow> MethSpec \<Rightarrow> Inv \<Rightarrow> Inv" where
"SINV_inv par T I =
  (\<lambda> s0 s h' . \<forall> ops1 ops2 S R h k w.
                (ops1,par,R,ops2) : Frame \<longrightarrow> T (R,k) (h,w) \<longrightarrow>
                s=(w#ops2,S,h) \<longrightarrow> I s0 (ops1,S,k) h')"

text{*The derivation system is formulated using contexts $G$ of
proof-theoretic assumptions representing local judgements. The type of
contexts is*}

type_synonym CTXT = "(Class \<times> Method \<times> Label, Assn \<times> Post \<times> Inv) AssList"

text{*The existence of the proof context also motivates that the
hypotheses in the syntax-directed rules are formulated using an
auxiliary judgement form, $G \rhd \langle A \rangle C,m,l \langle B
\rangle\; I$. Statements for this auxiliary form can be derived by
essentially two rules. The first rule, @{text AX}, allows us to
extract assumptions from the context, while the second rule, @{text
INJECT}, converts an ordinary judgement $G \rhd \lbrace A \rbrace C,m,l
\lbrace B \rbrace\; I$ into $G \rhd \langle A \rangle C,m,l \langle B
\rangle\; I$. No rule is provided for a direct embedding in the
opposite direction. As a consequence of this formulation, contextual
assumptions cannot be used directly to justify a statement $G \rhd
\lbrace A \rbrace C,m,l \lbrace B \rbrace\; I$. Instead, the
extraction of such an assumption has to be followed by at least one
''proper'' (syntax-driven) rule. In particular, attempts to verify
jumps by assuming a judgement and immediately using it to prove the
rule's hypothesis are ruled out.  More specifically, the purpose of
this technical device will become obvious when we discharge the
context in the proof of soundness (Section
\ref{SectionContextElimination}). Here, each entry
$((C',m',l'),(A',B',I'))$ of the context will need to be justified by
a derivation $G \rhd \lbrace A' \rbrace C',m',l' \lbrace B' \rbrace\;
I'$. This justification should in principle be allowed to rely on
other entries of the context. However, an axiom rule for judgements
$G \rhd \lbrace A \rbrace C,m,l \lbrace B \rbrace\; I$ would allow a
trivial discharge of any context entry. The introduction of the
auxiliary judgement form $G \rhd \langle A \rangle C,m,l \langle B
\rangle\; I$ thus ensures that the discharge of a contextual
assumption involves at least one application of a "proper"
(i.e.~syntax-directed) rule. Rule @{text INJECT} is used to chain
together syntax-directed rules. Indeed, it allows us to discharge a
hypothesis $G \rhd \langle A \rangle C,m,l \langle B \rangle\; I$ of a
syntax-directed rule using a derivation of $G \rhd \lbrace A \rbrace
C,m,l \lbrace B \rbrace\; I$.*}

text{*The proof rules are defined relative to a fixed method
specification table $\mathit{MST}$.*}

axiomatization MST::MSPEC

text{*In Isabelle, the distinction between the two judgement forms may
for example be achieved by introducing a single judgement form that
includes a boolean flag, and definiing two pretty-printing notions.*}

inductive_set SP_Judgement ::
  "(bool \<times> CTXT \<times> Class \<times> Method \<times> Label \<times> Assn \<times> Post \<times> Inv) set"
and
 SP_Deriv :: "CTXT => Assn => Class => Method => Label =>
              Post => Inv => bool"
  ("_ \<rhd> \<lbrace> _ \<rbrace> _,_,_ \<lbrace> _ \<rbrace> _" [100,100,100,100,100,100,100] 50)
and
 SP_Assum :: "CTXT => Assn => Class => Method => Label =>
              Post => Inv => bool"
   ("_ \<rhd> \<langle> _ \<rangle> _,_,_ \<langle> _ \<rangle> _" [100,100,100,100,100,100,100] 50)
where
 "G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I == (False, G, C, m, l, A, B, I):SP_Judgement"
|
 "G \<rhd> \<langle> A \<rangle> C,m,l \<langle> B \<rangle> I == (True, G, C, m, l, A, B, I):SP_Judgement"
|
INSTR:
 "\<lbrakk> mbody_is C m M; get_ins M l = Some ins;
    lookup MST (C,m) = Some (Mspec,Minv,Anno);
    \<forall> Q . lookup Anno l = Some Q \<longrightarrow> (\<forall> s0 s . A s0 s \<longrightarrow> Q s0 s);
    \<forall> s0 s . A s0 s \<longrightarrow> I s0 s (heap s);
    ins \<in> { const c, dup, pop, swap, load x, store x, binop f, unop g,
            new d, getfield d F, putfield d F, checkcast d};
    G \<rhd> \<langle> (SP_pre M l A) \<rangle> C,m,(l+1) \<langle> (SP_post M l B) \<rangle> (SP_inv M l I) \<rbrakk>
 \<Longrightarrow> G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I"
|
GOTO:
 "\<lbrakk> mbody_is C m M; get_ins M l = Some (goto pc);
    MST\<down>(C,m) = Some (Mspec,Minv,Anno);
    \<forall> Q . Anno\<down>(l) = Some Q \<longrightarrow> (\<forall> s0 s . A s0 s \<longrightarrow> Q s0 s);
    \<forall> s0 s . A s0 s \<longrightarrow> I s0 s (heap s);
    G \<rhd> \<langle>SP_pre M l A\<rangle> C,m,pc \<langle>SP_post M l B\<rangle> (SP_inv M l I)\<rbrakk>
 \<Longrightarrow> G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I"
|
IF:
 "\<lbrakk> mbody_is C m M; get_ins M l = Some (iftrue pc);
    MST\<down>(C,m) = Some (Mspec,Minv,Anno);
    \<forall> Q . Anno\<down>(l) = Some Q \<longrightarrow> (\<forall> s0 s . A s0 s \<longrightarrow> Q s0 s);
    \<forall> s0 s . A s0 s \<longrightarrow> I s0 s (heap s);

    G \<rhd> \<langle> SP_pre M l (\<lambda> s0 s . (\<forall> ops S k . s=(TRUE#ops,S,k) \<longrightarrow> A s0 s))\<rangle>
        C,m,pc
        \<langle> SP_post M l (\<lambda> s0 s t .
           (\<forall> ops S k . s=(TRUE#ops,S,k) \<longrightarrow> B s0 s t))\<rangle>
        ( SP_inv M l (\<lambda> s0 s t .
           (\<forall> ops S k . s=(TRUE#ops,S,k) \<longrightarrow> I s0 s t)) );

    G \<rhd> \<langle> SP_pre M l (\<lambda> s0 s .
           (\<forall> ops S k v . s = (v#ops,S,k) \<longrightarrow> v \<noteq> TRUE \<longrightarrow> A s0 s))\<rangle>
         C,m,(l+1)
         \<langle> SP_post M l (\<lambda> s0 s t.
           (\<forall> ops S k v . s = (v#ops,S,k) \<longrightarrow> v \<noteq> TRUE \<longrightarrow> B s0 s t))\<rangle>
         ( SP_inv M l (\<lambda> s0 s t.
           (\<forall> ops S k v . s = (v#ops,S,k) \<longrightarrow> v \<noteq> TRUE \<longrightarrow> I s0 s t)) )\<rbrakk>
 \<Longrightarrow> G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I"
|
VRET:
 "\<lbrakk> mbody_is C m M; get_ins M l = Some vreturn;
    MST\<down>(C,m) = Some (Mspec,Minv,Anno);
    \<forall> Q . Anno\<down>(l) = Some Q \<longrightarrow> (\<forall> s0 s . A s0 s \<longrightarrow> Q s0 s);
    \<forall> s0 s . A s0 s \<longrightarrow> I s0 s (heap s);
    \<forall> s0 s . A s0 s \<longrightarrow> (\<forall> v ops S h . s = (v#ops,S,h) \<longrightarrow> B s0 s (h,v))\<rbrakk>
 \<Longrightarrow> G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I"
|
INVS:
 "\<lbrakk> mbody_is C m M; get_ins M l = Some (invokeS D m');
    MST\<down>(C,m) = Some (Mspec,Minv,Anno);
    MST\<down>(D,m') = Some (T,MI,Anno2); mbody_is D m' (par,code,l0);
    \<forall> Q . Anno\<down>(l) = Some Q \<longrightarrow> (\<forall> s0 s . A s0 s \<longrightarrow> Q s0 s);
    \<forall> s0 s . A s0 s \<longrightarrow> I s0 s (heap s);
    \<forall> s0 ops1 ops2 S R k t . (ops1,par,R,ops2) : Frame \<longrightarrow>
           A s0 (ops1,S,k) \<longrightarrow> MI (R,k) t \<longrightarrow> I s0 (ops1,S,k) t;
    G \<rhd> \<langle>SINV_pre par T A\<rangle> C,m,(l+1) \<langle>SINV_post par T B\<rangle>
        (SINV_inv par T I)\<rbrakk>
 \<Longrightarrow> G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I"
|
CONSEQ:
 "\<lbrakk> (b,G,C,m,l,AA,BB,II) \<in> SP_Judgement;
    \<forall> s0 s . A s0 s \<longrightarrow> AA s0 s; \<forall> s0 s t . BB s0 s t \<longrightarrow> B s0 s t;
    \<forall> s0 s k. II s0 s k \<longrightarrow> I s0 s k\<rbrakk>
 \<Longrightarrow> (b,G,C,m,l,A,B,I) \<in> SP_Judgement"
|
INJECT: "\<lbrakk> G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I\<rbrakk> \<Longrightarrow> G \<rhd> \<langle> A \<rangle> C,m,l \<langle> B \<rangle> I"
|
AX:
 "\<lbrakk> G\<down>(C,m,l) = Some (A,B,I); MST\<down>(C,m) = Some (Mspec,Minv,Anno);
    \<forall> Q . Anno\<down>(l) = Some Q \<longrightarrow> (\<forall> s0 s . A s0 s \<longrightarrow> Q s0 s);
    \<forall> s0 s . A s0 s \<longrightarrow> I s0 s (heap s)\<rbrakk>
 \<Longrightarrow> G \<rhd> \<langle> A \<rangle> C,m,l \<langle> B \<rangle> I"

text{*As a first consequence, we can prove by induction on the proof
system that a derivable judgement entails its strong invariant and an
annotation that may be attached to the instruction.*}

(*<*)
lemma AssertionsImplyInvariantsAux[rule_format]:
"G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I \<Longrightarrow>
  ((\<forall> s0 s t. A s0 s \<longrightarrow> I s0 s (heap s)) \<and>
   (\<forall> Mspec Minv Anno .
        MST\<down>(C,m) = Some (Mspec,Minv,Anno) \<longrightarrow>
        (\<forall> Q . Anno\<down>(l) = Some Q \<longrightarrow>
               (\<forall> s0 s . A s0 s \<longrightarrow> Q s0 s))))"
apply (erule SP_Judgement.induct)
apply clarsimp
apply clarsimp
apply clarsimp
apply clarsimp
apply clarsimp
apply clarsimp
apply clarsimp (*fast*)
apply clarsimp (*fast*)
done
(*>*)
lemma AssertionsImplyMethInvariants:
 "\<lbrakk> G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I; A s0 s\<rbrakk> \<Longrightarrow> I s0 s (heap s)"
(*<*)
by (drule AssertionsImplyInvariantsAux, fast)
(*>*)

lemma AssertionsImplyAnnoInvariants:
 "\<lbrakk> G \<rhd> \<lbrace> A \<rbrace> C,m,l \<lbrace> B \<rbrace> I; MST\<down>(C,m) = Some(Mspec,Minv,Anno);
    Anno\<down>(l) = Some Q; A s0 s\<rbrakk> \<Longrightarrow> Q s0 s"
(*<*)
by (drule AssertionsImplyInvariantsAux, fast)
(*>*)

text{*For \emph{verified} \emph{programs}, all preconditions can be
justified by proof derivations, and initial labels of all methods
(again provably) satisfy the method preconditions.*}

definition mkState::"InitState \<Rightarrow> State"
where "mkState s0 = ([],fst s0,snd s0)"

definition mkPost::"MethSpec \<Rightarrow> Post"
where "mkPost T = (\<lambda> s0 s t . s=mkState s0 \<longrightarrow> T s0 t)"

definition mkInv::"MethInv \<Rightarrow> Inv"
where "mkInv MI = (\<lambda> s0 s t . s=mkState s0 \<longrightarrow> MI s0 t)"

definition VP_G::"CTXT \<Rightarrow> bool" where
"VP_G G =
  ((\<forall> C m l A B I. G\<down>(C,m,l) = Some (A,B,I) \<longrightarrow> G \<rhd> \<lbrace>A\<rbrace> C,m,l \<lbrace>B\<rbrace> I) \<and>
  (\<forall> C m par code l0 T MI Anno.
      mbody_is C m (par,code,l0) \<longrightarrow> MST\<down>(C,m) = Some(T,MI,Anno) \<longrightarrow>
      G \<rhd> \<lbrace>(\<lambda> s0 s. s = mkState s0)\<rbrace> C,m,l0 \<lbrace>mkPost T\<rbrace> (mkInv MI)))"

definition VP::bool where "VP = (\<exists> G . VP_G G)"

(*<*)
end
(*>*)


subsection \<open>Create Consistent\label{sec:create_consistent}\<close>

theory CreateConsistent
  imports CreateAlgorithms Consistency
begin

lemma nth_visible_eff:
  assumes "nth_visible s n = Inr i"
  shows "extended_to_set i \<subseteq> I ` set s"
proof -
  have "i \<in> set (ext_ids (filter is_visible s))"
    apply (cases "n < length (ext_ids (filter is_visible s))")
    using assms by auto
  thus ?thesis
    apply (simp add: ext_ids_def)
    using extended.inject by auto
qed

lemma subset_mono:
  assumes "N \<subseteq> M"
  shows "I ` insert_messages N \<subseteq> I ` insert_messages M"
proof -
  have "insert_messages N \<subseteq> insert_messages M" using assms
    by (metis (no_types, lifting) Collect_mono_iff insert_messages_def subsetCE)
  thus ?thesis by (simp add: image_mono)
qed

lemma deps_insert:
  assumes "\<Union> (deps ` M) \<subseteq> (I ` insert_messages M)"
  assumes "deps m \<subseteq> I ` insert_messages M"
  shows "\<Union> (deps ` (M \<union> {m})) \<subseteq> (I ` insert_messages (M \<union> {m}))"
proof -
  have "deps m \<subseteq> I ` insert_messages (M \<union> {m})" using assms(2) subset_mono
    by (metis Un_upper1 order_trans)
  thus ?thesis using assms(1) apply (simp)
    by (meson rev_subsetD subsetI subset_insertI subset_mono)
qed

lemma wf_add:
  fixes m :: "('\<I>,'\<Sigma>) insert_message"
  assumes "wfP (depends_on M)"
  assumes "\<And>n. n \<in> (M \<union> {m}) \<Longrightarrow> I m \<notin> deps (Insert n)"
  assumes "m \<notin> M"
  shows "wfP (depends_on (M \<union> {m}))"
proof -
  have "\<And>Q. Q \<noteq> {} \<Longrightarrow> (\<exists>z\<in>Q. \<forall>y. (y \<in> M \<union> {m}) \<and> (z \<in> M \<union> {m}) \<and>
           I y \<in> deps (Insert z) \<longrightarrow> y \<notin> Q)"
  proof -
    fix Q :: "('\<I>,'\<Sigma>) insert_message set"
    assume b:"Q \<noteq> {}"
    show "\<exists>z\<in>Q. \<forall>y. (y \<in> M \<union> {m}) \<and> (z \<in> M \<union> {m}) \<and> I y \<in> deps (Insert z)
           \<longrightarrow> y \<notin> Q"
    proof (cases "\<exists>x. x \<in> Q - {m}")
      case True
      hence "\<exists>z\<in> Q - {m}. \<forall>y. (y \<in> M) \<and> (z \<in> M) \<and> I y \<in> deps (Insert z)
             \<longrightarrow> y \<notin> Q - {m}"
        by (metis depends_on.simps assms(1) wfP_eq_minimal)
      then show ?thesis using assms(2) DiffD2 by auto
    next
      case False
      hence "Q = {m}" using b by blast
      thus ?thesis using assms(2) by blast
    qed
  qed
  thus ?thesis by (simp add:wfP_eq_minimal, blast)
qed

lemma create_insert_p_s_ordered:
  assumes "is_associated_string N s"
  assumes "a_conditions (insert_messages N) a"
  assumes "Inr (Insert m) = create_insert s n \<sigma> new_id"
  shows "a (P m) < a (S m)"
proof -
  obtain p q where pq_def:
    "create_insert s n \<sigma> new_id = Inr (Insert (InsertMessage p new_id q \<sigma>))"
    by (metis (no_types, lifting) One_nat_def add.right_neutral add_Suc_right
        create_insert.elims sum.case_eq_if sum.simps(4) assms(3) bind_def)
  have "Inr p = nth_visible s n" using pq_def Error_Monad.bindE by fastforce
  moreover have "Inr q = nth_visible s (Suc n)"
    using pq_def Error_Monad.bindE by fastforce
  ultimately have "a p < a q"
    using assms by (metis is_associated_string_def nth_visible_inc')
  moreover have "m = InsertMessage p new_id q \<sigma>"
    using assms(3) pq_def by auto
  ultimately show ?thesis by (simp add: pq_def)
qed

lemma create_insert_consistent:
  assumes "consistent M"
  assumes "is_associated_string N s"
  assumes "N \<subseteq> M"
  assumes "Inr m = create_insert s n \<sigma> new_id"
  assumes "new_id \<notin> I ` insert_messages M"
  shows "consistent (M \<union> {m})"
proof -
  obtain p q where pq_def:
    "create_insert s n \<sigma> new_id = Inr (Insert (InsertMessage p new_id q \<sigma>))"
    by (metis (no_types, lifting) One_nat_def add.right_neutral add_Suc_right
        create_insert.elims assms(4) sum.case_eq_if sum.simps(4) bind_def)
  define m' where "m' = InsertMessage p new_id q \<sigma>"
  hence a:"m = Insert m'" using pq_def assms(4) by auto
  hence d: "create_insert s n \<sigma> new_id = Inr (Insert m')"
    using pq_def assms by simp
  have b:"I m' = new_id" using m'_def by (simp add:I_def)
  hence "inj_on I (insert_messages M \<union> {m'})" using assms(5) assms(1)
    using consistent_def by fastforce
  hence "inj_on I (insert_messages (M \<union> {m}))" using assms(4) pq_def m'_def
    by (metis Inr_inject insert_insert_message)
  moreover
  have p:"extended_to_set p \<subseteq> I ` set s" using pq_def nth_visible_eff by fastforce
  have q: "extended_to_set q \<subseteq> I ` set s"
    using pq_def apply (simp add:bind_def del:nth_visible.simps)
    apply (cases "nth_visible s n", simp)
    by (cases "nth_visible s (Suc n)", simp, simp add: nth_visible_eff)
  have "extended_to_set p \<union> extended_to_set q \<subseteq> I ` set s" using p q by simp
  hence "extended_to_set p \<union> extended_to_set q \<subseteq> I ` insert_messages N"
    by (metis assms(2) is_associated_string_def to_woot_character_keeps_i_lifted)
  hence "extended_to_set p \<union> extended_to_set q \<subseteq> I ` insert_messages M"
    using assms(3) subset_mono by blast
  hence c:"deps m \<subseteq> I ` insert_messages M" using pq_def assms(4) by auto
  hence "\<Union> (deps ` (M \<union> {m})) \<subseteq> (I ` insert_messages (M \<union> {m}))"
    by (metis consistent_def assms(1) deps_insert)
  moreover have w:
    "\<forall>n \<in> insert_messages M \<union> {m'}. deps (Insert n) \<subseteq> I ` insert_messages M"
    by (metis a c consistent_def assms(1) Sup_le_iff imageI insert_iff
        insert_is_Un insert_messages_def mem_Collect_eq sup.commute)
  hence "\<forall>n \<in> insert_messages M \<union> {m'}. I m' \<notin> deps (Insert n)"
    using b assms(5) by blast
  hence "wfP (depends_on (insert_messages M \<union> {m'}))"
    by (metis Un_insert_right insert_absorb wf_add assms(1)
        consistent_def sup_bot.right_neutral)
  moreover obtain a where a_def: "a_conditions (insert_messages M) a"
    using consistent_def  assms(1) by blast
  define a' where
    "a' = (\<lambda>i. if i = \<lbrakk> new_id \<rbrakk> then \<lbrakk>\<Psi> (a (P m'), a(S m')) new_id\<rbrakk> else a i)"
  hence "a_conditions (insert_messages (M \<union> {m})) a'"
  proof -
    have "a' \<turnstile> < a' \<stileturn>" using a'_def a_conditions_def a_def by auto
    moreover have
      "\<And>m''. m'' \<in> (insert_messages M \<union> {m'}) \<longrightarrow>
          a'(P m'') < a'(S m'')  \<and>
          a' \<lbrakk>I m''\<rbrakk> = \<lbrakk>\<Psi> (a'(P m''), a'(S m'')) (I m'')\<rbrakk>"
    proof
      fix m''
      assume e:" m'' \<in> (insert_messages M \<union> {m'})"
      show "a'(P m'') < a'(S m'') \<and> a' \<lbrakk> I m''\<rbrakk> =
            \<lbrakk>\<Psi> (a'(P m''), a'(S m'')) (I m'')\<rbrakk>"
      proof (cases "m'' \<in> insert_messages M")
        case True
        moreover have "deps (Insert m'') \<subseteq> I ` insert_messages M"
          using e w by blast
        hence "P m'' \<noteq> \<lbrakk> new_id \<rbrakk> \<and> S m'' \<noteq> \<lbrakk> new_id \<rbrakk>"
          by (meson assms(5) contra_subsetD pred_is_dep succ_is_dep)
        moreover have "I m'' \<noteq> new_id"
          using assms(5) True by blast
        ultimately show ?thesis using a_def True
          by (simp add: a_conditions_def a'_def)
      next
        case False
        moreover have "I m'' = new_id" using False b e by blast
        moreover have "deps (Insert m'') \<subseteq> I ` insert_messages M"
          using False a c e by blast
        hence "P m'' \<noteq> \<lbrakk> new_id \<rbrakk> \<and> S m'' \<noteq> \<lbrakk> new_id \<rbrakk>"
          by (meson assms(5) contra_subsetD pred_is_dep succ_is_dep)
        moreover have "a_conditions (insert_messages N) a"
          using a_def a_subset assms is_associated_string_def by blast
        hence "a (P m') < a (S m')"
          by (metis assms(2) d create_insert_p_s_ordered)
        hence "a' (P m'') < a' (S m'')" using calculation a'_def False e by auto
        ultimately show ?thesis using e a'_def by auto
      qed
    qed
    ultimately show "?thesis" using a_conditions_def
      by (metis a insert_insert_message)
  qed
  ultimately show "?thesis" using consistent_def a by (metis insert_insert_message)
qed

lemma bind_simp: "(x \<bind> (\<lambda>l. y l) = Inr r) \<Longrightarrow> (y (projr x) = Inr r)"
  using isOK_I by force

end