theory flash50Bra  imports flash50Rev

  begin
lemma onInv50:

   assumes  a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  " and

     b1:"r \<in> rules N" and b2:"invf=inv50  iInv1  iInv2 "
   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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX1VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_GetXVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_ReplaceVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_ShWb N ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis NI_ShWbVsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_GetX_GetX2 ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_GetX_GetX2VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_PutXAcksDone ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis NI_Local_PutXAcksDoneVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX7VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_Get_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_Get_Nak2VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_ReplaceHomeShrVld ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis NI_ReplaceHomeShrVldVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_Put  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_PutVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX5VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Wb ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis NI_WbVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_Get_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_Get_GetVsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_Replace ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_ReplaceVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_ReplaceShrVld  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_ReplaceShrVldVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX8VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_InvAck_2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_InvAck_2VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_Get_Nak2VsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Remote_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis PI_Remote_ReplaceVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Nak_Home ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis NI_Nak_HomeVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_Get_Put2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_Get_Put2VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_InvAck_1VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX11VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX6VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_Get_Put2VsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_Get_Put ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_Get_PutVsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_GetX_PutX1 N ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_GetX_PutX1VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_InvAck_1_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_InvAck_1_HomeVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_Get_Nak1VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_Get_Nak1VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_Nak2VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX10_homeVsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Remote_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis PI_Remote_GetVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_Nak3VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX10VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX2VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_Get_Put1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_Get_Put1VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_PutXVsInv50 )
          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 (inv50  iInv1  iInv2 ) (Store  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis StoreVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_FAck ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis NI_FAckVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX3VsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_GetX_PutX3 ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_GetX_PutX3VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_GetX_PutXVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX8_homeVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_Get_Put1VsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_GetX_GetX1 ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_GetX_GetX1VsInv50 )
          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 (inv50  iInv1  iInv2 ) (StoreHome ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis StoreHomeVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_GetX_NakVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Inv  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_InvVsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis PI_Remote_PutXVsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_GetX_PutX4 ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_GetX_PutX4VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX4VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Nak  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_NakVsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_GetX_PutX2 N ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_GetX_PutX2VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_Put ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis NI_Local_PutVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_Nak1VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Nak_Clear ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis NI_Nak_ClearVsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_PutX ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_PutXVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_Get_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_Get_Nak3VsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_GetX_Nak_HomeVsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Local_Get_Get ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis PI_Local_Get_GetVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_GetX_PutX9VsInv50 )
          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 (inv50  iInv1  iInv2 ) (PI_Remote_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis PI_Remote_GetXVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_ReplaceHome ) (invariants N) "
            apply(cut_tac   a1  a2  a3   b2 c2 )
            by (metis NI_ReplaceHomeVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Remote_GetX_PutX_HomeVsInv50 )
          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 (inv50  iInv1  iInv2 ) (NI_Local_Get_Put3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1  a2  a3 )
            by (metis NI_Local_Get_Put3VsInv50 )
          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


(*  Title:      HOL/Auth/n_mutualExSimp_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
*)

header{*The n_mutualExSimp Protocol Case Study*}

theory n_mutualExSimp_lemma_inv__3_on_rules imports n_mutualExSimp_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 s f r (invariants N)"
  proof -
  have c1: "(\<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_Crit  i)"
      have "invHoldForRule 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 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 s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_IdleVsinv__3) done
    }

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

end


(*  Title:      HOL/Auth/n_mutualExSimp_lemma_inv__5_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
*)

header{*The n_mutualExSimp Protocol Case Study*}

theory n_mutualExSimp_lemma_inv__5_on_rules imports n_mutualExSimp_lemma_on_inv__5
begin
section{*All lemmas on causal relation between inv__5*}
lemma lemma_inv__5_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__5  p__Inv3 p__Inv4)"
  shows "invHoldForRule s f r (invariants N)"
  proof -
  have c1: "(\<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_Crit  i)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_CritVsinv__5) done
    }

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

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

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

end


(*
    This file is a part of IsarMathLib -
    a library of formalized mathematics for Isabelle/Isar.

    Copyright (C) 2008 - 2019 Slawomir Kolodynski

    This program is free software Redistribution and use in source and binary forms,
    with or without modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
   2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation and/or
   other materials provided with the distribution.
   3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES LOSS OF USE, DATA, OR PROFITS OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

*)

section \<open>Finite sets - introduction\<close>

theory Finite_ZF imports ZF1 Nat_ZF_IML ZF.Cardinal

begin

text\<open>Standard Isabelle Finite.thy contains a very useful
  notion of finite powerset: the set of finite subsets of a given set.
  The definition, however, is specific to Isabelle and based on the notion
  of "datatype", obviously not something that belongs to ZF set theory.
  This theory file devolops the notion of finite powerset similarly as
  in Finite.thy, but based on standard library's
  Cardinal.thy. This theory file is intended to
  replace IsarMathLib's \<open>Finite1\<close> and \<open>Finite_ZF_1\<close> theories
  that are currently derived from the "datatype" approach.
\<close>

subsection\<open>Definition and basic properties of finite powerset\<close>

text\<open>The goal of this section is to prove an induction theorem about
  finite powersets: if the empty set has some property and this property is
  preserved by adding a single element of a set,
  then this property is true for all finite subsets of this set.\<close>

text\<open>We defined the finite powerset \<open>FinPow(X)\<close> as those elements
  of the powerset that are finite.\<close>

definition
  "FinPow(X) \<equiv> {A \<in> Pow(X). Finite(A)}"

text\<open>The cardinality of an element of finite powerset is a natural number.\<close>

lemma card_fin_is_nat: assumes "A \<in> FinPow(X)"
  shows "|A| \<in> nat" and "A \<approx> |A|"
  using assms FinPow_def Finite_def cardinal_cong nat_into_Card
    Card_cardinal_eq by auto

text\<open>A reformulation of \<open>card_fin_is_nat\<close>: for a finit
  set $A$ there is a bijection between $|A|$ and $A$.\<close>

lemma fin_bij_card: assumes A1: "A \<in> FinPow(X)"
  shows "\<exists>b. b \<in> bij(|A|, A)"
proof -
  from A1 have "|A| \<approx> A" using card_fin_is_nat eqpoll_sym
    by blast
  then show ?thesis using eqpoll_def by auto
qed

text\<open>If a set has the same number of elements as $n \in \mathbb{N}$,
  then its cardinality is $n$. Recall that in set theory a natural number
  $n$ is a set that has $n$ elements.\<close>

lemma card_card: assumes "A \<approx> n" and "n \<in> nat"
  shows "|A| = n"
  using assms cardinal_cong nat_into_Card Card_cardinal_eq
  by auto

text\<open>If we add a point to a finite set, the cardinality
  increases by one. To understand the second assertion
  $| A \cup \{ a\}| = |A| \cup \{ |A|\} $ recall that
  the cardinality $|A|$ of $A$ is a natural number
  and for natural numbers we have $n+1 = n \cup \{ n\}$.
\<close>

lemma card_fin_add_one: assumes A1: "A \<in> FinPow(X)" and A2: "a \<in> X-A"
  shows
  "|A \<union> {a}| = succ( |A| )"
  "|A \<union> {a}| = |A| \<union> {|A|}"
proof -
  from A1 A2 have "cons(a,A) \<approx> cons( |A|, |A| )"
    using card_fin_is_nat mem_not_refl cons_eqpoll_cong
    by auto
  moreover have  "cons(a,A) = A \<union> {a}" by (rule consdef)
  moreover have "cons( |A|, |A| ) = |A| \<union> {|A|}"
    by (rule consdef)
  ultimately have "A\<union>{a} \<approx> succ( |A| )" using succ_explained
    by simp
  with A1 show
    "|A \<union> {a}| = succ( |A| )" and "|A \<union> {a}| = |A| \<union> {|A|}"
    using card_fin_is_nat card_card by auto
qed

text\<open>We can decompose the finite powerset into collection of
  sets of the same natural cardinalities.\<close>

lemma finpow_decomp:
  shows "FinPow(X) = (\<Union>n \<in> nat. {A \<in> Pow(X). A \<approx> n})"
  using Finite_def FinPow_def by auto

text\<open>Finite powerset is the union of sets of cardinality
  bounded by natural numbers.\<close>

lemma finpow_union_card_nat:
  shows "FinPow(X) = (\<Union>n \<in> nat. {A \<in> Pow(X). A \<lesssim> n})"
proof -
  have "FinPow(X) \<subseteq> (\<Union>n \<in> nat. {A \<in> Pow(X). A \<lesssim> n})"
    using finpow_decomp FinPow_def eqpoll_imp_lepoll
    by auto
  moreover have
    "(\<Union>n \<in> nat. {A \<in> Pow(X). A \<lesssim> n}) \<subseteq> FinPow(X)"
    using lepoll_nat_imp_Finite FinPow_def by auto
  ultimately show ?thesis by auto
qed

text\<open>A different form of \<open>finpow_union_card_nat\<close> (see above) -
  a subset that has not more elements than a given natural number
  is in the finite powerset.\<close>

lemma lepoll_nat_in_finpow:
  assumes "n \<in> nat"   "A \<subseteq> X"  "A \<lesssim> n"
  shows "A \<in> FinPow(X)"
  using assms finpow_union_card_nat by auto

text\<open>Natural numbers are finite subsets of the set of natural numbers.\<close>

lemma nat_finpow_nat: assumes "n \<in> nat" shows "n \<in> FinPow(nat)"
  using assms nat_into_Finite nat_subset_nat FinPow_def
  by simp

text\<open>A finite subset is a finite subset of itself.\<close>

lemma fin_finpow_self: assumes "A \<in> FinPow(X)" shows "A \<in> FinPow(A)"
  using assms FinPow_def by auto

text\<open>If we remove an element and put it back we get the set back.
\<close>

lemma rem_add_eq: assumes "a\<in>A" shows "(A-{a}) \<union> {a} = A"
  using assms by auto

text\<open>Induction for finite powerset. This is smilar to the
  standard Isabelle's \<open>Fin_induct\<close>.\<close>

theorem FinPow_induct: assumes A1: "P(0)" and
  A2: "\<forall>A \<in> FinPow(X). P(A) \<longrightarrow> (\<forall>a\<in>X. P(A \<union> {a}))" and
  A3: "B \<in> FinPow(X)"
  shows "P(B)"
proof -
  { fix n assume "n \<in> nat"
    moreover from A1 have I: "\<forall>B\<in>Pow(X). B \<lesssim> 0 \<longrightarrow> P(B)"
      using lepoll_0_is_0 by auto
    moreover have "\<forall> k \<in> nat.
      (\<forall>B \<in> Pow(X). (B \<lesssim> k \<longrightarrow> P(B))) \<longrightarrow>
      (\<forall>B \<in> Pow(X). (B \<lesssim> succ(k) \<longrightarrow> P(B)))"
    proof -
      { fix k assume A4: "k \<in> nat"
	assume A5: "\<forall> B \<in> Pow(X). (B \<lesssim> k \<longrightarrow> P(B))"
	fix B assume A6: "B \<in> Pow(X)"  "B \<lesssim> succ(k)"
	have "P(B)"
	proof -
	  have "B = 0 \<longrightarrow> P(B)"
	  proof -
	    { assume "B = 0"
	      then have "B \<lesssim> 0" using lepoll_0_iff
		by simp
	      with I A6 have "P(B)" by simp
	    } thus "B = 0 \<longrightarrow> P(B)" by simp
	  qed
	  moreover have "B\<noteq>0 \<longrightarrow> P(B)"
	  proof -
	    { assume "B \<noteq> 0"
	      then obtain a where II: "a\<in>B" by auto
	      let ?A = "B - {a}"
	      from A6 II have "?A \<subseteq> X" and "?A \<lesssim> k"
		using Diff_sing_lepoll by auto
	      with A4 A5 have "?A \<in> FinPow(X)" and "P(?A)"
		using lepoll_nat_in_finpow finpow_decomp
		by auto
	      with A2 A6 II have " P(?A \<union> {a})"
		by auto
	      moreover from II have "?A \<union> {a} = B"
		by auto
	      ultimately have "P(B)" by simp
	    } thus "B\<noteq>0 \<longrightarrow> P(B)" by simp
	  qed
	  ultimately show "P(B)" by auto
	qed
      } thus ?thesis by blast
    qed
    ultimately have "\<forall>B \<in> Pow(X). (B \<lesssim> n \<longrightarrow> P(B))"
      by (rule ind_on_nat)
  } then have "\<forall>n \<in> nat. \<forall>B \<in> Pow(X). (B \<lesssim> n \<longrightarrow> P(B))"
    by auto
  with A3 show "P(B)" using finpow_union_card_nat
    by auto
qed

text\<open>A subset of a finite subset is a finite subset.\<close>

lemma subset_finpow: assumes "A \<in> FinPow(X)" and "B \<subseteq> A"
  shows "B \<in> FinPow(X)"
  using assms FinPow_def subset_Finite by auto

text\<open>If we subtract anything from a finite set,
  the resulting set is finite.\<close>

lemma diff_finpow:
  assumes "A \<in> FinPow(X)" shows "A-B \<in> FinPow(X)"
  using assms subset_finpow by blast

text\<open>If we remove a point from a finites subset,
  we get a finite subset.\<close>

corollary fin_rem_point_fin: assumes "A \<in> FinPow(X)"
  shows "A - {a} \<in> FinPow(X)"
  using assms diff_finpow by simp

text\<open>Cardinality of a nonempty finite set is a successsor
  of some natural number.\<close>

lemma card_non_empty_succ:
  assumes A1: "A \<in> FinPow(X)" and A2: "A \<noteq> 0"
  shows "\<exists>n \<in> nat. |A| = succ(n)"
proof -
  from A2 obtain a where "a \<in> A" by auto
  let ?B = "A - {a}"
  from A1 \<open>a \<in> A\<close> have
    "?B \<in> FinPow(X)" and "a \<in> X - ?B"
    using FinPow_def fin_rem_point_fin by auto
  then have "|?B \<union> {a}| = succ( |?B| )"
    using card_fin_add_one by auto
  moreover from \<open>a \<in> A\<close> \<open>?B \<in> FinPow(X)\<close> have
    "A = ?B \<union> {a}" and "|?B| \<in> nat"
    using card_fin_is_nat by auto
  ultimately show "\<exists>n \<in> nat. |A| = succ(n)" by auto
qed

text\<open>Nonempty set has non-zero cardinality. This is probably
  true without the assumption that the set is finite, but
  I couldn't derive it from standard Isabelle theorems.
\<close>

lemma card_non_empty_non_zero:
  assumes "A \<in> FinPow(X)" and "A \<noteq> 0"
  shows "|A| \<noteq> 0"
proof -
  from assms obtain n where "|A| = succ(n)"
    using card_non_empty_succ by auto
  then show "|A| \<noteq> 0" using succ_not_0
    by simp
qed

text\<open>Another variation on the induction theme:
  If we can show something holds for the empty set and
  if it holds for all finite sets with
  at most $k$ elements then it holds for all
  finite sets with at most $k+1$
  elements, the it holds for all finite sets.\<close>

theorem FinPow_card_ind: assumes A1: "P(0)" and
  A2: "\<forall>k\<in>nat.
  (\<forall>A \<in> FinPow(X). A \<lesssim> k \<longrightarrow> P(A)) \<longrightarrow>
  (\<forall>A \<in> FinPow(X). A \<lesssim> succ(k) \<longrightarrow> P(A))"
  and A3: "A \<in>  FinPow(X)" shows "P(A)"
proof -
  from A3 have "|A| \<in> nat" and "A \<in>  FinPow(X)" and "A \<lesssim> |A|"
    using card_fin_is_nat eqpoll_imp_lepoll by auto
  moreover have "\<forall>n \<in> nat. (\<forall>A \<in> FinPow(X).
    A \<lesssim> n \<longrightarrow> P(A))"
  proof
    fix n assume "n \<in> nat"
    moreover from A1 have "\<forall>A \<in> FinPow(X). A \<lesssim> 0 \<longrightarrow> P(A)"
      using lepoll_0_is_0 by auto
    moreover note A2
    ultimately show
      "\<forall>A \<in> FinPow(X). A \<lesssim> n \<longrightarrow> P(A)"
      by (rule ind_on_nat)
  qed
  ultimately show "P(A)" by simp
qed

text\<open>Another type of induction (or, maybe recursion).
  In the induction step  we try to find a point in the set that
  if we remove it, the fact that the property holds for the
  smaller set implies that the property holds for the whole set.
\<close>

lemma FinPow_ind_rem_one: assumes A1: "P(0)" and
  A2: "\<forall> A \<in> FinPow(X). A \<noteq> 0 \<longrightarrow> (\<exists>a\<in>A. P(A-{a}) \<longrightarrow> P(A))"
  and A3: "B \<in>  FinPow(X)"
  shows "P(B)"
proof -
  note A1
  moreover have "\<forall>k\<in>nat.
  (\<forall>B \<in> FinPow(X). B \<lesssim> k \<longrightarrow> P(B)) \<longrightarrow>
  (\<forall>C \<in> FinPow(X). C \<lesssim> succ(k) \<longrightarrow> P(C))"
  proof -
    { fix k assume "k \<in> nat"
      assume A4: "\<forall>B \<in> FinPow(X). B \<lesssim> k \<longrightarrow> P(B)"
      have "\<forall>C \<in> FinPow(X). C \<lesssim> succ(k) \<longrightarrow> P(C)"
      proof -
	{ fix C assume "C \<in> FinPow(X)"
	  assume "C \<lesssim> succ(k)"
	  note A1
	  moreover
	  { assume "C \<noteq> 0"
	    with A2 \<open>C \<in> FinPow(X)\<close> obtain a where
	      "a\<in>C" and "P(C-{a}) \<longrightarrow> P(C)"
	      by auto
	    with A4 \<open>C \<in> FinPow(X)\<close> \<open>C \<lesssim> succ(k)\<close>
	    have "P(C)" using Diff_sing_lepoll fin_rem_point_fin
	      by simp }
	  ultimately have "P(C)" by auto
	} thus ?thesis by simp
      qed
    } thus ?thesis by blast
  qed
  moreover note A3
  ultimately show "P(B)" by (rule FinPow_card_ind)
qed

text\<open>Yet another induction theorem. This is similar, but
  slightly more complicated than \<open>FinPow_ind_rem_one\<close>.
  The difference is in the treatment of the empty set to allow
  to show properties that are not true for empty set.
\<close>

lemma FinPow_rem_ind: assumes A1: "\<forall>A \<in> FinPow(X).
  A = 0 \<or> (\<exists>a\<in>A. A = {a} \<or> P(A-{a}) \<longrightarrow> P(A))"
  and A2: "A \<in>  FinPow(X)" and A3: "A\<noteq>0"
  shows "P(A)"
proof -
  have "0 = 0 \<or> P(0)" by simp
  moreover have
    "\<forall>k\<in>nat.
    (\<forall>B \<in> FinPow(X). B \<lesssim> k \<longrightarrow> (B=0 \<or> P(B))) \<longrightarrow>
    (\<forall>A \<in> FinPow(X). A \<lesssim> succ(k) \<longrightarrow> (A=0 \<or> P(A)))"
  proof -
    { fix k assume "k \<in> nat"
      assume A4: "\<forall>B \<in> FinPow(X). B \<lesssim> k \<longrightarrow> (B=0 \<or> P(B))"
      have "\<forall>A \<in> FinPow(X). A \<lesssim> succ(k) \<longrightarrow> (A=0 \<or> P(A))"
      proof -
	{ fix A assume "A \<in> FinPow(X)"
	  assume "A \<lesssim> succ(k)"  "A\<noteq>0"
	  from A1 \<open>A \<in> FinPow(X)\<close> \<open>A\<noteq>0\<close> obtain a
	    where "a\<in>A" and "A = {a} \<or> P(A-{a}) \<longrightarrow> P(A)"
	    by auto
	  let ?B = "A-{a}"
	  from A4 \<open>A \<in> FinPow(X)\<close> \<open>A \<lesssim> succ(k)\<close> \<open>a\<in>A\<close>
	  have "?B = 0 \<or> P(?B)"
	    using Diff_sing_lepoll fin_rem_point_fin
	    by simp
	  with \<open>a\<in>A\<close> \<open>A = {a} \<or> P(A-{a}) \<longrightarrow> P(A)\<close>
	  have "P(A)" by auto
	} thus  ?thesis by auto
      qed
    } thus ?thesis by blast
  qed
  moreover note A2
  ultimately have "A=0 \<or> P(A)" by (rule FinPow_card_ind)
  with A3 show "P(A)" by simp
qed

text\<open>If a family of sets is closed with respect to taking intersections
  of two sets then it is closed with respect to taking intersections
  of any nonempty finite collection.\<close>

lemma inter_two_inter_fin:
  assumes A1: "\<forall>V\<in>T. \<forall>W\<in>T. V \<inter> W \<in> T" and
  A2: "N \<noteq> 0" and A3: "N \<in> FinPow(T)"
  shows "(\<Inter>N \<in> T)"
proof -
  have "0 = 0 \<or> (\<Inter>0 \<in> T)" by simp
  moreover have "\<forall>M \<in> FinPow(T). (M = 0 \<or> \<Inter>M \<in> T) \<longrightarrow>
    (\<forall>W \<in> T. M\<union>{W} = 0 \<or> \<Inter>(M \<union> {W}) \<in> T)"
  proof -
    { fix M assume "M \<in> FinPow(T)"
      assume A4: "M = 0 \<or> \<Inter>M \<in> T"
      { assume "M = 0"
	hence "\<forall>W \<in> T. M\<union>{W} = 0 \<or> \<Inter>(M \<union> {W}) \<in> T"
	  by auto }
      moreover
      { assume "M \<noteq> 0"
	with A4 have "\<Inter>M \<in> T" by simp
	{ fix W assume "W \<in> T"
	  from \<open>M \<noteq> 0\<close> have "\<Inter>(M \<union> {W}) = (\<Inter>M) \<inter> W"
	    by auto
	  with A1 \<open>\<Inter>M \<in> T\<close> \<open>W \<in> T\<close> have "\<Inter>(M \<union> {W}) \<in> T"
	    by simp
	} hence "\<forall>W \<in> T. M\<union>{W} = 0 \<or> \<Inter>(M \<union> {W}) \<in> T"
	  by simp }
      ultimately have "\<forall>W \<in> T. M\<union>{W} = 0 \<or> \<Inter>(M \<union> {W}) \<in> T"
	by blast
    } thus ?thesis by simp
  qed
  moreover note \<open>N \<in> FinPow(T)\<close>
  ultimately have "N = 0 \<or> (\<Inter>N \<in> T)"
    by (rule FinPow_induct)
  with A2 show "(\<Inter>N \<in> T)" by simp
qed

text\<open>If a family of sets contains the empty set and
  is closed with respect to taking unions
  of two sets then it is closed with respect to taking unions
  of any finite collection.\<close>

lemma union_two_union_fin:
  assumes A1: "0 \<in> C" and A2: "\<forall>A\<in>C. \<forall>B\<in>C. A\<union>B \<in> C" and
  A3: "N \<in> FinPow(C)"
  shows "\<Union>N \<in> C"
proof -
  from \<open>0 \<in> C\<close> have "\<Union>0 \<in> C" by simp
  moreover have "\<forall>M \<in> FinPow(C). \<Union>M \<in> C \<longrightarrow> (\<forall>A\<in>C. \<Union>(M \<union> {A}) \<in> C)"
  proof -
    { fix M assume "M \<in> FinPow(C)"
      assume "\<Union>M \<in> C"
      fix A assume "A\<in>C"
      have "\<Union>(M \<union> {A}) = (\<Union>M) \<union> A" by auto
      with A2 \<open>\<Union>M \<in> C\<close>  \<open>A\<in>C\<close> have  "\<Union>(M \<union> {A}) \<in> C"
	by simp
    } thus ?thesis by simp
  qed
  moreover note \<open>N \<in> FinPow(C)\<close>
  ultimately show "\<Union>N \<in> C" by (rule FinPow_induct)
qed

text\<open>Empty set is in finite power set.\<close>

lemma empty_in_finpow: shows "0 \<in> FinPow(X)"
  using FinPow_def by simp

text\<open>Singleton is in the finite powerset.\<close>

lemma singleton_in_finpow: assumes "x \<in> X"
  shows "{x} \<in> FinPow(X)" using assms FinPow_def by simp

text\<open>Union of two finite subsets is a finite subset.\<close>

lemma union_finpow: assumes "A \<in> FinPow(X)" and "B \<in> FinPow(X)"
  shows "A \<union> B \<in> FinPow(X)"
  using assms FinPow_def by auto

text\<open>Union of finite number of finite sets is finite.\<close>

lemma fin_union_finpow: assumes "M \<in> FinPow(FinPow(X))"
  shows "\<Union>M \<in> FinPow(X)"
  using assms empty_in_finpow union_finpow union_two_union_fin
  by simp

(*text{*A subset of a finites subset is a finite subset.*}

lemma subset_finpow: assumes "A \<in> FinPow(X)" and "B \<subseteq> A"
  shows "B \<in> FinPow(X)"
  using assms FinPow_def subset_Finite by auto;*)
text\<open>If a set is finite after removing one element, then it is finite.\<close>

lemma rem_point_fin_fin:
  assumes A1: "x \<in> X" and A2: "A - {x} \<in> FinPow(X)"
  shows "A \<in> FinPow(X)"
proof -
  from assms have "(A - {x}) \<union> {x} \<in> FinPow(X)"
    using singleton_in_finpow union_finpow by simp
  moreover have "A \<subseteq> (A - {x}) \<union> {x}" by auto
  ultimately show "A \<in> FinPow(X)"
    using FinPow_def subset_Finite by auto
qed

text\<open>An image of a finite set is finite.\<close>

lemma fin_image_fin: assumes "\<forall>V\<in>B. K(V)\<in>C" and "N \<in> FinPow(B)"
  shows "{K(V). V\<in>N} \<in> FinPow(C)"
proof -
  have "{K(V). V\<in>0} \<in> FinPow(C)" using FinPow_def
    by auto
  moreover have "\<forall>A \<in> FinPow(B).
    {K(V). V\<in>A} \<in> FinPow(C) \<longrightarrow> (\<forall>a\<in>B. {K(V). V \<in> (A \<union> {a})} \<in> FinPow(C))"
  proof -
    { fix A assume "A \<in> FinPow(B)"
      assume  "{K(V). V\<in>A} \<in> FinPow(C)"
      fix a assume "a\<in>B"
      have  "{K(V). V \<in> (A \<union> {a})} \<in> FinPow(C)"
      proof -
	have "{K(V). V \<in> (A \<union> {a})} = {K(V). V\<in>A} \<union> {K(a)}"
	  by auto
	moreover note \<open>{K(V). V\<in>A} \<in> FinPow(C)\<close>
	moreover from \<open>\<forall>V\<in>B. K(V) \<in> C\<close>  \<open>a\<in>B\<close> have "{K(a)} \<in>  FinPow(C)"
	  using singleton_in_finpow by simp
	ultimately show ?thesis using union_finpow by simp
      qed
    } thus ?thesis by simp
  qed
  moreover note \<open>N \<in> FinPow(B)\<close>
  ultimately show "{K(V). V\<in>N} \<in> FinPow(C)"
    by (rule FinPow_induct)
qed

text\<open>Union of a finite indexed family of finite sets is finite.\<close>

lemma union_fin_list_fin:
  assumes A1: "n \<in> nat" and A2: "\<forall>k \<in> n. N(k) \<in> FinPow(X)"
  shows
  "{N(k). k \<in> n} \<in>  FinPow(FinPow(X))" and "(\<Union>k \<in> n. N(k)) \<in> FinPow(X)"
proof -
  from A1 have "n \<in> FinPow(n)"
    using nat_finpow_nat fin_finpow_self by auto
  with A2 show "{N(k). k \<in> n} \<in>  FinPow(FinPow(X))"
    by (rule fin_image_fin)
  then show "(\<Union>k \<in> n. N(k)) \<in> FinPow(X)"
    using fin_union_finpow by simp
qed

end


theory TopoS_Helper
imports Main TopoS_Interface
  TopoS_ENF
  vertex_example_simps
begin

lemma (in SecurityInvariant_preliminaries) sinvar_valid_remove_flattened_offending_flows:
  assumes "wf_graph \<lparr>nodes = nodesG, edges = edgesG\<rparr>" (*TODO: we could get rid of this assumption*)
  shows "sinvar \<lparr>nodes = nodesG, edges = edgesG - \<Union> (set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP) \<rparr> nP"
proof -
  { fix f
    assume *: "f\<in>set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP"

    from * have 1: "sinvar \<lparr>nodes = nodesG, edges = edgesG - f \<rparr> nP"
      by (metis (hide_lams, mono_tags) SecurityInvariant_withOffendingFlows.valid_without_offending_flows delete_edges_simp2 graph.select_convs(1) graph.select_convs(2))
    from * have 2: "edgesG - \<Union> (set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP) \<subseteq> edgesG - f"
      by blast
    note 1 2
  }
  with assms show ?thesis
    by (metis (hide_lams, no_types) Diff_empty Union_empty defined_offending equals0I mono_sinvar wf_graph_remove_edges)
qed

lemma (in SecurityInvariant_preliminaries) sinvar_valid_remove_SOME_offending_flows:
  assumes "set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP \<noteq> {}"
  shows "sinvar \<lparr>nodes = nodesG, edges = edgesG - (SOME F. F \<in> set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP) \<rparr> nP"
proof -
  { fix f
    assume *: "f\<in>set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP"

    from * have 1: "sinvar \<lparr>nodes = nodesG, edges = edgesG - f \<rparr> nP"
      by (metis (hide_lams, mono_tags) SecurityInvariant_withOffendingFlows.valid_without_offending_flows delete_edges_simp2 graph.select_convs(1) graph.select_convs(2))
    from * have 2: "edgesG - \<Union> (set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP) \<subseteq> edgesG - f"
      by blast
    note 1 2
  }
  with assms show ?thesis by (simp add: some_in_eq)
qed

lemma (in SecurityInvariant_preliminaries) sinvar_valid_remove_minimalize_offending_overapprox:
  assumes "wf_graph \<lparr>nodes = nodesG, edges = edgesG\<rparr>"
      and "\<not> sinvar \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP" (*"set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP \<noteq> {}"*)
      and "set Es = edgesG" and "distinct Es"
  shows "sinvar \<lparr>nodes = nodesG, edges = edgesG -
              set (minimalize_offending_overapprox Es [] \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP) \<rparr> nP"
proof -
  from assms have off_Es: "is_offending_flows (set Es) \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP"
    by (metis (no_types, lifting) Diff_cancel
        SecurityInvariant_withOffendingFlows.valid_empty_edges_iff_exists_offending_flows defined_offending
        delete_edges_simp2 graph.select_convs(2) is_offending_flows_def sinvar_monoI)
  from minimalize_offending_overapprox_gives_back_an_offending_flow[OF assms(1) off_Es _ assms(4)] have
    in_offending: "set (minimalize_offending_overapprox Es [] \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP)
      \<in> set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP"
     using assms(3) by simp

  { fix f
    assume *: "f\<in>set_offending_flows \<lparr>nodes = nodesG, edges = edgesG\<rparr> nP"
    from * have 1: "sinvar \<lparr>nodes = nodesG, edges = edgesG - f \<rparr> nP"
      by (metis (hide_lams, mono_tags) SecurityInvariant_withOffendingFlows.valid_without_offending_flows delete_edges_simp2 graph.select_convs(1) graph.select_convs(2))
    note 1
  }
  with in_offending show ?thesis by (simp add: some_in_eq)
qed

end


subsection \<open>Instantiation for transition systems\<close>

(*<*)
theory BD_Security_TS
imports Abstract_BD_Security Filtermap Transition_System
begin
(*>*)

declare Let_def[simp]

no_notation relcomp (infixr "O" 75)

locale BD_Security_TS = Transition_System istate validTrans srcOf tgtOf
 for istate :: 'state and validTrans :: "'trans \<Rightarrow> bool"
     and srcOf :: "'trans \<Rightarrow> 'state" and tgtOf :: "'trans \<Rightarrow> 'state"
+
fixes (* value filtering and production:  *)
   \<phi> :: "'trans => bool" and f :: "'trans \<Rightarrow> 'value"
 and (* observation filtering and production: *)
   \<gamma> :: "'trans => bool" and g :: "'trans \<Rightarrow> 'obs"
 and (* declassification trigger:  *)
   T :: "'trans \<Rightarrow> bool"
 and (* declassification bound: *)
   B :: "'value list \<Rightarrow> 'value list \<Rightarrow> bool"
begin

(* The value function: *)
definition V :: "'trans list \<Rightarrow> 'value list" where "V \<equiv> filtermap \<phi> f"
(* The observation function: *)
definition O :: "'trans trace \<Rightarrow> 'obs list" where "O \<equiv> filtermap \<gamma> g"

sublocale Abstract_BD_Security
  where validSystemTrace = "validFrom istate" and V = V and O = O and B = B and TT = "never T" .

lemma O_map_filter: "O tr = map g (filter \<gamma> tr)" unfolding O_def filtermap_map_filter ..
lemma V_map_filter: "V tr = map f (filter \<phi> tr)" unfolding V_def filtermap_map_filter ..

lemma V_simps[simp]:
"V [] = []"  "\<not> \<phi> trn \<Longrightarrow> V (trn # tr) = V tr"  "\<phi> trn \<Longrightarrow> V (trn # tr) = f trn # V tr"
unfolding V_def by auto

lemma V_Cons_unfold: "V (trn # tr) = (if \<phi> trn then f trn # V tr else V tr)"
by auto

lemma O_simps[simp]:
"O [] = []"  "\<not> \<gamma> trn \<Longrightarrow> O (trn # tr) = O tr"  "\<gamma> trn \<Longrightarrow> O (trn # tr) = g trn # O tr"
unfolding O_def by auto

lemma O_Cons_unfold: "O (trn # tr) = (if \<gamma> trn then g trn # O tr else O tr)"
by auto

lemma V_append: "V (tr @ tr1) = V tr @ V tr1"
unfolding V_def using filtermap_append by auto

lemma V_snoc:
"\<not> \<phi> trn \<Longrightarrow> V (tr ## trn) = V tr"  "\<phi> trn \<Longrightarrow> V (tr ## trn) = V tr ## f trn"
unfolding V_def by auto

lemma O_snoc:
"\<not> \<gamma> trn \<Longrightarrow> O (tr ## trn) = O tr"  "\<gamma> trn \<Longrightarrow> O (tr ## trn) = O tr ## g trn"
unfolding O_def by auto

lemma V_Nil_list_ex: "V tr = [] \<longleftrightarrow> \<not> list_ex \<phi> tr"
unfolding V_def using filtermap_Nil_list_ex by auto

lemma V_Nil_never: "V tr = [] \<longleftrightarrow> never \<phi> tr"
unfolding V_def using filtermap_Nil_never by auto

lemma Nil_V_never: "[] = V tr \<longleftrightarrow> never \<phi> tr"
unfolding V_def filtermap_map_filter by (induction tr) auto

lemma list_ex_iff_length_V:
"list_ex \<phi> tr \<longleftrightarrow> length (V tr) > 0"
by (metis V_Nil_list_ex length_greater_0_conv)

lemma length_V: "length (V tr) \<le> length tr"
by (auto simp: V_def length_filtermap)

lemma V_list_all: "V tr = map f tr \<longleftrightarrow> list_all \<phi> tr"
by (auto simp: V_def length_filtermap)

lemma V_eq_Cons:
assumes "V tr = v # vl1"
shows "\<exists> trn tr2 tr1. tr = tr2 @ [trn] @ tr1 \<and> never \<phi> tr2 \<and> \<phi> trn \<and> f trn = v \<and> V tr1 = vl1"
using assms filtermap_eq_Cons unfolding V_def by auto

lemma V_eq_append:
assumes "V tr = vl1 @ vl2"
shows "\<exists> tr1 tr2. tr = tr1 @ tr2 \<and> V tr1 = vl1 \<and> V tr2 = vl2"
using assms filtermap_eq_append[of \<phi> f] unfolding V_def by auto

lemma V_eq_RCons:
assumes "V tr = vl1 ## v"
shows "\<exists> trn tr1 tr2. tr = tr1 @ [trn] @ tr2 \<and> \<phi> trn \<and> f trn = v \<and> V tr1 = vl1 \<and> never \<phi> tr2"
using assms filtermap_eq_RCons[of \<phi> f] unfolding V_def by blast

lemma V_eq_Cons_RCons:
assumes "V tr = v # vl1 ## w"
shows "\<exists> trv trnv tr1 trnw trw.
   tr = trv @ [trnv] @ tr1 @ [trnw] @ trw \<and>
   never \<phi> trv \<and> \<phi> trnv \<and> f trnv = v \<and> V tr1 = vl1 \<and> \<phi> trnw \<and> f trnw = w \<and> never \<phi> trw"
using assms filtermap_eq_Cons_RCons[of \<phi> f] unfolding V_def by blast

lemma O_append: "O (tr @ tr1) = O tr @ O tr1"
unfolding O_def using filtermap_append by auto

lemma O_Nil_list_ex: "O tr = [] \<longleftrightarrow> \<not> list_ex \<gamma> tr"
unfolding O_def using filtermap_Nil_list_ex by auto

lemma O_Nil_never: "O tr = [] \<longleftrightarrow> never \<gamma> tr"
unfolding O_def using filtermap_Nil_never by auto

lemma Nil_O_never: "[] = O tr \<longleftrightarrow> never \<gamma> tr"
unfolding O_def filtermap_map_filter by (induction tr) auto

lemma length_O: "length (O tr) \<le> length tr"
by (auto simp: O_def length_filtermap)

lemma O_list_all: "O tr = map g tr \<longleftrightarrow> list_all \<gamma> tr"
by (auto simp: O_def length_filtermap)

lemma O_eq_Cons:
assumes "O tr = obs # obsl1"
shows "\<exists> trn tr2 tr1. tr = tr2 @ [trn] @ tr1 \<and> never \<gamma> tr2 \<and> \<gamma> trn \<and> g trn = obs \<and> O tr1 = obsl1"
using assms filtermap_eq_Cons unfolding O_def by auto

lemma O_eq_append:
assumes "O tr = obsl1 @ obsl2"
shows "\<exists> tr1 tr2. tr = tr1 @ tr2 \<and> O tr1 = obsl1 \<and> O tr2 = obsl2"
using assms filtermap_eq_append[of \<gamma> g] unfolding O_def by auto

lemma O_eq_RCons:
assumes "O tr = oul1 ## ou"
shows "\<exists> trn tr1 tr2. tr = tr1 @ [trn] @ tr2 \<and> \<gamma> trn \<and> g trn = ou \<and> O tr1 = oul1 \<and> never \<gamma> tr2"
using assms filtermap_eq_RCons[of \<gamma> g] unfolding O_def by blast

lemma O_eq_Cons_RCons:
assumes "O tr0 = ou # oul1 ## ouu"
shows "\<exists> tr trn tr1 trnn trr.
   tr0 = tr @ [trn] @ tr1 @ [trnn] @ trr \<and>
   never \<gamma> tr \<and> \<gamma> trn \<and> g trn = ou \<and> O tr1 = oul1 \<and> \<gamma> trnn \<and> g trnn = ouu \<and> never \<gamma> trr"
using assms filtermap_eq_Cons_RCons[of \<gamma> g] unfolding O_def by blast

lemma O_eq_Cons_RCons_append:
assumes "O tr0 = ou # oul1 ## ouu @ oull"
shows "\<exists> tr trn tr1 trnn trr.
   tr0 = tr @ [trn] @ tr1 @ [trnn] @ trr \<and>
   never \<gamma> tr \<and> \<gamma> trn \<and> g trn = ou \<and> O tr1 = oul1 \<and> \<gamma> trnn \<and> g trnn = ouu \<and> O trr = oull"
proof-
  from O_eq_append[of tr0 "ou # oul1 ## ouu" oull] assms
  obtain tr00 trrr where 1: "tr0 = tr00 @ trrr"
  and 2: "O tr00 = ou # oul1 ## ouu" and 3: "O trrr = oull" by auto
  from O_eq_Cons_RCons[OF 2] obtain tr trn tr1 trnn trr where
  4:"tr00 = tr @ [trn] @ tr1 @ [trnn] @ trr \<and>
     never \<gamma> tr \<and>
     \<gamma> trn \<and> g trn = ou \<and> O tr1 = oul1 \<and> \<gamma> trnn \<and> g trnn = ouu \<and> never \<gamma> trr" by auto
  show ?thesis apply(rule exI[of _ tr], rule exI[of _ trn], rule exI[of _ tr1],
     rule exI[of _ trnn], rule exI[of _ "trr @ trrr"])
  using 1 3 4 by (simp add: O_append O_Nil_never)
qed

lemma O_Nil_tr_Nil: "O tr \<noteq> [] \<Longrightarrow> tr \<noteq> []"
by (induction tr) auto

lemma V_Cons_eq_append: "V (trn # tr) = V [trn] @ V tr"
by (cases "\<phi> trn") auto

lemma set_V: "set (V tr) \<subseteq> {f trn | trn . trn \<in>\<in> tr \<and> \<phi> trn}"
using set_filtermap unfolding V_def .

lemma set_O: "set (O tr) \<subseteq> {g trn | trn . trn \<in>\<in> tr \<and> \<gamma> trn}"
using set_filtermap unfolding O_def .

lemma list_ex_length_O:
assumes "list_ex \<gamma> tr"  shows "length (O tr) > 0"
by (metis assms O_Nil_list_ex length_greater_0_conv)

lemma list_ex_iff_length_O:
"list_ex \<gamma> tr \<longleftrightarrow> length (O tr) > 0"
by (metis O_Nil_list_ex length_greater_0_conv)

lemma length1_O_list_ex_iff:
"length (O tr) > 1 \<Longrightarrow> list_ex \<gamma> tr"
unfolding list_ex_iff_length_O by auto

lemma list_all_O_map: "list_all \<gamma> tr \<Longrightarrow> O tr = map g tr"
using O_list_all by auto

lemma never_O_Nil: "never \<gamma> tr \<Longrightarrow> O tr = []"
using O_Nil_never by auto

lemma list_all_V_map: "list_all \<phi> tr \<Longrightarrow> V tr = map f tr"
using V_list_all by auto

lemma never_V_Nil: "never \<phi> tr \<Longrightarrow> V tr = []"
using V_Nil_never by auto

(* Reachable states by transitions satisfying T: *)
inductive reachNT:: "'state \<Rightarrow> bool" where
Istate: "reachNT istate"
|
Step:
"\<lbrakk>reachNT (srcOf trn); validTrans trn; \<not> T trn\<rbrakk>
 \<Longrightarrow> reachNT (tgtOf trn)"

lemma reachNT_reach: assumes "reachNT s"  shows "reach s"
using assms apply induct by (auto intro: reach.intros)

lemma V_iff_non_\<phi>[simp]: "V (trn # tr) = V tr \<longleftrightarrow> \<not> \<phi> trn"
by (cases "\<phi> trn") auto

lemma V_imp_\<phi>: "V (trn # tr) = v # V tr \<Longrightarrow> \<phi> trn"
by (cases "\<phi> trn") auto

lemma V_imp_Nil: "V (trn # tr) = [] \<Longrightarrow> V tr = []"
by (cases "\<phi> trn") auto

lemma V_iff_Nil[simp]: "V (trn # tr) = [] \<longleftrightarrow> \<not> \<phi> trn \<and> V tr = []"
by (metis V_iff_non_\<phi> V_imp_Nil)

end (* locale BD_Security_TS *)

(*<*)
end
(*>*)