theory Proof_4_4
  imports Proofs_4
begin

abbreviation s where "s s0 user_value pressure_value \<equiv>
  (toEnv (setVarAny s0 user_value pressure_value))"

theorem proof_4_4: "VC4 inv4 env s0 user_value pressure_value"
  apply(simp only: VC4_def inv4_def R4_def extraInv_def)
  apply(rule impI)
  apply(rule conjI)
   apply(rule conjI)
    apply simp
  apply((rule allI)+)
    apply(rule impI)
 subgoal premises prems for s1 s2 s3
    apply(cases "s3 = s s0 user_value pressure_value")
     apply(cases "s2 = s s0 user_value pressure_value")
      using prems(2)  apply (simp split: if_splits)
      using prems(1)
        apply (smt (z3) getPstate.simps(9) substate_toEnvNum_id)
      apply(rule cut_rl[of "substate s2 s0 \<and> toEnvNum s2 s0 <DELAY'TIMEOUT"])
      using prems(1)
       apply (smt (z3) getPstate.simps(9) prems(2) substate_refl)
      using prems(2) apply (simp split: if_splits)
      apply(rule cut_rl[of "substate s3 s0"])
      using prems apply meson
      using prems(2)  by (simp split: if_splits)
	apply(simp only: extraInv_def[symmetric])
    using extra4 VC4_def by auto

end


theory flash71Bra  imports flash71Rev

  begin
lemma onInv71:

   assumes

     b1:"r \<in> rules N" and b2:"invf=inv71 "
   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 (inv71 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX1VsInv71 )
          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 (inv71 ) (NI_Local_GetX_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_GetXVsInv71 )
          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 (inv71 ) (NI_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_ReplaceVsInv71 )
          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 (inv71 ) (NI_ShWb N ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_ShWbVsInv71 )
          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 (inv71 ) (PI_Local_GetX_GetX2 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_GetX2VsInv71 )
          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 (inv71 ) (NI_Local_PutXAcksDone ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Local_PutXAcksDoneVsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX7VsInv71 )
          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 (inv71 ) (NI_Local_Get_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Nak2VsInv71 )
          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 (inv71 ) (NI_ReplaceHomeShrVld ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_ReplaceHomeShrVldVsInv71 )
          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 (inv71 ) (NI_Remote_Put  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_PutVsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX5VsInv71 )
          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 (inv71 ) (NI_Wb ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_WbVsInv71 )
          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 (inv71 ) (NI_Local_Get_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_GetVsInv71 )
          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 (inv71 ) (PI_Local_Replace ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_ReplaceVsInv71 )
          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 (inv71 ) (NI_ReplaceShrVld  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_ReplaceShrVldVsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX8VsInv71 )
          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 (inv71 ) (NI_InvAck_2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvAck_2VsInv71 )
          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 (inv71 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Nak2VsInv71 )
          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 (inv71 ) (PI_Remote_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_ReplaceVsInv71 )
          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 (inv71 ) (NI_Nak_Home ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Nak_HomeVsInv71 )
          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 (inv71 ) (NI_Local_Get_Put2  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Put2VsInv71 )
          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 (inv71 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvAck_1VsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX11VsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX6VsInv71 )
          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 (inv71 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Put2VsInv71 )
          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 (inv71 ) (PI_Local_Get_Put ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_Get_PutVsInv71 )
          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 (inv71 ) (PI_Local_GetX_PutX1 N ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX1VsInv71 )
          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 (inv71 ) (NI_InvAck_1_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvAck_1_HomeVsInv71 )
          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 (inv71 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Nak1VsInv71 )
          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 (inv71 ) (NI_Local_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Nak1VsInv71 )
          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 (inv71 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_Nak2VsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX10_homeVsInv71 )
          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 (inv71 ) (PI_Remote_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_GetVsInv71 )
          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 (inv71 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_Nak3VsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX10VsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX2VsInv71 )
          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 (inv71 ) (NI_Remote_Get_Put1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Put1VsInv71 )
          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 (inv71 ) (NI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_PutXVsInv71 )
          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 (inv71 ) (Store  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis StoreVsInv71 )
          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 (inv71 ) (NI_FAck ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_FAckVsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX3VsInv71 )
          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 (inv71 ) (PI_Local_GetX_PutX3 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX3VsInv71 )
          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 (inv71 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_PutXVsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX8_homeVsInv71 )
          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 (inv71 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Put1VsInv71 )
          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 (inv71 ) (PI_Local_GetX_GetX1 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_GetX1VsInv71 )
          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 (inv71 ) (StoreHome ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis StoreHomeVsInv71 )
          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 (inv71 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_NakVsInv71 )
          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 (inv71 ) (NI_Inv  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvVsInv71 )
          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 (inv71 ) (PI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_PutXVsInv71 )
          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 (inv71 ) (PI_Local_GetX_PutX4 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX4VsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX4VsInv71 )
          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 (inv71 ) (NI_Nak  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_NakVsInv71 )
          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 (inv71 ) (PI_Local_GetX_PutX2 N ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX2VsInv71 )
          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 (inv71 ) (NI_Local_Put ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Local_PutVsInv71 )
          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 (inv71 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_Nak1VsInv71 )
          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 (inv71 ) (NI_Nak_Clear ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Nak_ClearVsInv71 )
          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 (inv71 ) (PI_Local_PutX ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_PutXVsInv71 )
          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 (inv71 ) (NI_Local_Get_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Nak3VsInv71 )
          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 (inv71 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_Nak_HomeVsInv71 )
          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 (inv71 ) (PI_Local_Get_Get ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_Get_GetVsInv71 )
          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 (inv71 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX9VsInv71 )
          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 (inv71 ) (PI_Remote_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_GetXVsInv71 )
          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 (inv71 ) (NI_ReplaceHome ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_ReplaceHomeVsInv71 )
          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 (inv71 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_PutX_HomeVsInv71 )
          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 (inv71 ) (NI_Local_Get_Put3  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Put3VsInv71 )
          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 ExampleSimple
  imports BigStepParallel
begin

text \<open>Some common variables\<close>
definition X :: char where "X = CHR ''x''"
definition Y :: char where "Y = CHR ''y''"
definition Z :: char where "Z = CHR ''z''"

lemma vars_distinct [simp]: "X \<noteq> Y" "X \<noteq> Z" "Y \<noteq> Z" "Y \<noteq> X" "Z \<noteq> X" "Z \<noteq> Y"
  unfolding X_def Y_def Z_def by auto

subsection \<open>Big-step semantics: simple examples\<close>

text \<open>Send 1 immediately\<close>
lemma test1a: "big_step (Cm (''ch''[!](\<lambda>_. 1)))
  (\<lambda>_. 0) [OutBlock ''ch'' 1] (\<lambda>_. 0)"
  by (rule sendB1)

text \<open>Send x + 1 immediately\<close>
lemma test1b: "big_step (Cm (''ch''[!](\<lambda>s. s X + 1)))
  ((\<lambda>_. 0)(X := 1)) [OutBlock ''ch'' 2] ((\<lambda>_. 0)(X := 1))"
  apply (rule big_step_cong) apply (rule sendB1) by auto

text \<open>Send 1 after delay 2\<close>
lemma test1c: "big_step (Cm (''ch''[!](\<lambda>_. 1)))
  (\<lambda>_. 0) [WaitBlk (2::real) (\<lambda>_. State (\<lambda>_. 0)) ({''ch''}, {}),
           OutBlock ''ch'' 1] (\<lambda>_. 0)"
  by (rule sendB2, auto)

text \<open>Receive 1 immediately\<close>
lemma test2a: "big_step (Cm (''ch''[?]X))
  (\<lambda>_. 0) [InBlock ''ch'' 1] ((\<lambda>_. 0)(X := 1))"
  by (rule receiveB1)

text \<open>Receive 1 after delay 2\<close>
lemma test2b: "big_step (Cm (''ch''[?]X))
  (\<lambda>_. 0) [WaitBlk (2::real) (\<lambda>_. State (\<lambda>_. 0)) ({}, {''ch''}),
           InBlock ''ch'' 1] ((\<lambda>_. 0)(X := 1))"
  by (rule receiveB2, auto)

text \<open>Communication\<close>
lemma test3: "par_big_step (
  Parallel (Single (Cm (''ch''[!](\<lambda>_. 1)))) {''ch''}
           (Single (Cm (''ch''[?]X))))
  (ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0)))
    [IOBlock ''ch'' 1]
  (ParState (State (\<lambda>_. 0)) (State ((\<lambda>_. 0)(X := 1))))"
  apply (rule ParallelB)
    apply (rule SingleB[OF test1a])
   apply (rule SingleB[OF test2a])
  by (auto intro: combine_blocks.intros)

text \<open>Wait\<close>
lemma test4: "big_step (Wait (\<lambda>_. 2))
  (\<lambda>_. 0) [WaitBlk (2::real) (\<lambda>_. State (\<lambda>_. 0)) ({}, {})] (\<lambda>_. 0)"
  apply (rule waitB1) by auto

text \<open>Seq\<close>
lemma test5: "big_step (Wait (\<lambda>_. 2); Cm (''ch''[!](\<lambda>_. 1)))
  (\<lambda>_. 0) [WaitBlk 2 (\<lambda>_. State (\<lambda>_. 0)) ({}, {}), OutBlock ''ch'' 1] (\<lambda>_. 0)"
  apply (rule big_step_cong) apply (rule seqB[OF test4 test1a]) by auto

text \<open>Communication after delay 2\<close>
lemma test6: "par_big_step (
  Parallel (Single (Wait (\<lambda>_. 2); Cm (''ch''[!](\<lambda>_. 1)))) {''ch''}
           (Single (Cm (''ch''[?]X))))
  (ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0)))
    [WaitBlk 2 (\<lambda>_. ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0))) ({}, {''ch''}), IOBlock ''ch'' 1]
  (ParState (State (\<lambda>_. 0)) (State ((\<lambda>_. 0)(X := 1))))"
  apply (rule ParallelB)
    apply (rule SingleB[OF test5])
   apply (rule SingleB[OF test2b])
  by (auto intro!: combine_blocks.intros)

text \<open>Loop one time\<close>
lemma test7: "big_step (Rep (Assign X (\<lambda>s. s X + 1); Cm (''ch''[!](\<lambda>s. s X))))
  (\<lambda>_. 0) [OutBlock ''ch'' 1] ((\<lambda>_. 0)(X := 1))"
  apply (rule RepetitionB2)
    apply (rule seqB) apply (rule assignB) apply (rule sendB1)
  apply auto[1] apply (rule RepetitionB1)
  by auto

text \<open>Loop two times\<close>
lemma test8: "big_step (Rep (Assign X (\<lambda>s. s X + 1); Cm (''ch''[!](\<lambda>s. s X))))
  (\<lambda>_. 0) [OutBlock ''ch'' 1, OutBlock ''ch'' 2] ((\<lambda>_. 0)(X := 2))"
  apply (rule RepetitionB2)
    apply (rule seqB) apply (rule assignB) apply (rule sendB1)
   apply auto[1] apply (rule RepetitionB2)
     apply (rule seqB) apply (rule assignB) apply (rule sendB1)
    apply auto[1] apply (rule RepetitionB1)
  by auto

text \<open>External choice 1\<close>
lemma test9a: "big_step (EChoice [(''ch1''[!](\<lambda>_. 1), Wait (\<lambda>_. 1)),
                                  (''ch2''[!](\<lambda>_. 2), Wait (\<lambda>_. 2))])
  (\<lambda>_. 0) [OutBlock ''ch1'' 1, WaitBlk (1::real) (\<lambda>_. State (\<lambda>_. 0)) ({}, {})] (\<lambda>_. 0)"
  apply (rule EChoiceSendB1[where i=0])
  apply auto apply (rule waitB1) by auto

text \<open>External choice 2\<close>
lemma test9b: "big_step (EChoice [(''ch1''[!](\<lambda>_. 1), Wait (\<lambda>_. 1)),
                                  (''ch2''[!](\<lambda>_. 2), Wait (\<lambda>_. 2))])
  (\<lambda>_. 0) [OutBlock ''ch2'' 2, WaitBlk 2 (\<lambda>_. State (\<lambda>_. 0)) ({}, {})] (\<lambda>_. 0)"
  apply (rule EChoiceSendB1[where i=1])
  apply auto apply (rule waitB1) by auto

text \<open>Communication with external choice\<close>
lemma test10: "par_big_step (
  Parallel (Single (EChoice [(''ch1''[!](\<lambda>_. 1), Wait (\<lambda>_. 1)),
                             (''ch2''[!](\<lambda>_. 2), Wait (\<lambda>_. 2))])) {''ch1'', ''ch2''}
           (Single (Cm (''ch1''[?]X); Wait (\<lambda>_. 1))))
  (ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0)))
    [IOBlock ''ch1'' 1, WaitBlk (1::real) (\<lambda>_. ParState (State (\<lambda>_. 0)) (State ((\<lambda>_. 0)(X := 1)))) ({}, {})]
  (ParState (State (\<lambda>_. 0)) (State ((\<lambda>_. 0)(X := 1))))"
  apply (rule ParallelB)
    apply (rule SingleB[OF test9a])
   apply (rule SingleB)
   apply (rule seqB) apply (rule receiveB1) apply (rule waitB1)
  apply auto
  by (intro combine_blocks.intros, auto)

text \<open>ODE Example 1\<close>
lemma test11: "big_step (Cont (ODE ((\<lambda>_ _. 0)(X := (\<lambda>_. 1)))) (\<lambda>s. s X < 1))
  (\<lambda>_. 0) [WaitBlk (1::real) (\<lambda>t. State ((\<lambda>_. 0)(X := t))) ({}, {})] ((\<lambda>_. 0)(X := 1))"
  apply (rule ContB2)
      apply (auto simp add: ODEsol_def state2vec_def fun_upd_def has_vderiv_on_def)
  apply(rule exI[where x="1"])
  apply auto
  apply (rule has_vector_derivative_projI)
  by (auto intro!: derivative_intros)

subsection \<open>Big-step semantics: interrupt\<close>

text \<open>Exit through boundary\<close>
lemma test_interrupt1:
  "big_step (Interrupt (ODE ((\<lambda>_ _. 0)(X := (\<lambda>_. 1)))) (\<lambda>s. s X < 2) [(''ch''[!](\<lambda>_. 1), Assign X (\<lambda>_. 0))])
    (\<lambda>_. 0) [WaitBlk (2::real) (\<lambda>t. State ((\<lambda>_. 0)(X := t))) ({''ch''}, {})] ((\<lambda>_. 0)(X := 2))"
  apply (rule InterruptB2)
        apply (auto simp add: ODEsol_def state2vec_def fun_upd_def has_vderiv_on_def)
apply(rule exI[where x="1"])
  apply auto
  apply (rule has_vector_derivative_projI)
  by (auto intro!: derivative_intros)

text \<open>Immediate communication\<close>
lemma test_interrupt2:
  "big_step (Interrupt (ODE ((\<lambda>_ _. 0)(X := (\<lambda>_. 1)))) (\<lambda>s. s X < 2) [(''ch''[!](\<lambda>_. 1), Assign X (\<lambda>_. 3))])
    (\<lambda>_. 0) [OutBlock ''ch'' 1] ((\<lambda>_. 0)(X := 3))"
  apply (rule InterruptSendB1)
    apply (auto simp add: ODEsol_def state2vec_def fun_upd_def has_vderiv_on_def)
  apply (rule big_step_cong) apply (rule assignB) by auto

text \<open>Communication in the middle\<close>
lemma test_interrupt3:
  "big_step (Interrupt (ODE ((\<lambda>_ _. 0)(X := (\<lambda>_. 1)))) (\<lambda>s. s X < 2) [(''ch''[!](\<lambda>_. 1), Assign X (\<lambda>_. 3))])
    (\<lambda>_. 0) [WaitBlk (1::real) (\<lambda>t. State ((\<lambda>_. 0)(X := t))) ({''ch''}, {}),
             OutBlock ''ch'' 1] ((\<lambda>_. 0)(X := 3))"
  apply (rule InterruptSendB2)
  apply (auto simp add: ODEsol_def state2vec_def fun_upd_def has_vderiv_on_def)
   apply (rule exI[where x="1"])
   apply auto
   apply (rule has_vector_derivative_projI)
   apply (auto intro!: derivative_intros)
  apply (rule big_step_cong) apply (rule assignB) by auto

text \<open>Note with current definition, communication at the end is also possible\<close>
lemma test_interrupt4:
  "big_step (Interrupt (ODE ((\<lambda>_ _. 0)(X := (\<lambda>_. 1)))) (\<lambda>s. s X < 2) [(''ch''[!](\<lambda>_. 1), Assign X (\<lambda>_. 3))])
    (\<lambda>_. 0) [WaitBlk (2::real) (\<lambda>t. State ((\<lambda>_. 0)(X := t))) ({''ch''}, {}),
             OutBlock ''ch'' 1] ((\<lambda>_. 0)(X := 3))"
  apply (rule InterruptSendB2)
         apply (auto simp add: ODEsol_def state2vec_def fun_upd_def has_vderiv_on_def)
   apply (rule exI[where x="1"])
  apply auto
  apply (rule has_vector_derivative_projI)
  apply (auto intro!: derivative_intros)
  apply (rule big_step_cong) apply (rule assignB) by auto

subsection \<open>Difference between internal and external choice\<close>

text \<open>
  This example shows the difference between semantics of internal
  and external choice. We begin with the process with internal choice,
    (ch1!1 \<squnion> ch2!2)*,
  which can produce the trace (2,s,{ch2!})^(ch2!,2)^(ch1!,1).
\<close>
lemma test_internal:
  "big_step (Rep (IChoice (Cm (''ch1''[!](\<lambda>_. 1))) (Cm (''ch2''[!](\<lambda>_. 2)))))
    (\<lambda>_. 0) [WaitBlk 2 (\<lambda>_. State (\<lambda>_. 0)) ({''ch2''}, {}),
             OutBlock ''ch2'' 2,
             OutBlock ''ch1'' 1] (\<lambda>_. 0)"
  apply (rule RepetitionB2)
    apply (rule IChoiceB2)
    apply (rule sendB2[where d=2]) apply auto[1]
  apply (rule RepetitionB2)
  apply (rule IChoiceB1)
     apply (rule sendB1) apply (rule RepetitionB1)
  by auto

text \<open>
  For external choice, the process
    (ch1!1 \<rightarrow> skip $ ch2!2 \<rightarrow> skip)*
  produces the trace (2,s,{ch1!,ch2!})^(ch2!,2)^(ch1!,1).
\<close>
lemma test_external:
  "big_step (Rep (EChoice [(''ch1''[!](\<lambda>_. 1), Skip), (''ch2''[!](\<lambda>_. 2), Skip)]))
    (\<lambda>_. 0) [WaitBlk 2 (\<lambda>_. State (\<lambda>_. 0)) ({''ch1'', ''ch2''}, {}),
             OutBlock ''ch2'' 2,
             OutBlock ''ch1'' 1] (\<lambda>_. 0)"
  apply (rule RepetitionB2)
    apply (rule EChoiceSendB2[where d=2 and i=1])
       apply auto apply (rule skipB)
  apply (rule RepetitionB2)
    apply (rule EChoiceSendB1[where i=0])
      apply auto apply (rule skipB)
  by (rule RepetitionB1)

text \<open>
  The other side is the process
    (wait 1; ch1?x) || (wait 2; ch2?x),
  which can produce the trace (1,s,{})^(1,s,{ch1?})^(ch2?,2)^(ch1?,1).
\<close>
lemma test_internal_other:
  "par_big_step (Parallel (Single (Wait (\<lambda>_. 1); Cm (''ch1''[?]X))) {}
                          (Single (Wait (\<lambda>_. 2); Cm (''ch2''[?]X))))
    (ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0)))
    [WaitBlk (1::real) (\<lambda>_. ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0))) ({}, {}),
     WaitBlk (1::real) (\<lambda>_. ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0))) ({}, {''ch1''}),
     InBlock ''ch2'' 2,
     InBlock ''ch1'' 1]
    (ParState (State ((\<lambda>_. 0)(X := 1))) (State ((\<lambda>_. 0)(X := 2))))"
proof -
  have left: "big_step (Wait (\<lambda>_. 1); Cm (''ch1''[?]X)) (\<lambda>_. 0)
    [WaitBlk (1::real) (\<lambda>_. State (\<lambda>_. 0)) ({}, {}),
     WaitBlk (1::real) (\<lambda>_. State (\<lambda>_. 0)) ({}, {''ch1''}),
     InBlock ''ch1'' 1] ((\<lambda>_. 0)(X := 1))"
    apply (rule big_step_cong) apply (rule seqB) apply (rule waitB1)
    apply auto apply (rule receiveB2) by auto
  have right: "big_step (Wait (\<lambda>_. 2); Cm (''ch2''[?]X)) (\<lambda>_. 0)
    [WaitBlk 2 (\<lambda>_. State (\<lambda>_. 0)) ({}, {}),
     InBlock ''ch2'' 2] ((\<lambda>_. 0)(X := 2))"
    apply (rule big_step_cong) apply (rule seqB) apply (rule waitB1)
    apply auto by (rule receiveB1)
  show ?thesis
    apply (rule ParallelB)
      apply (rule SingleB[OF left])
     apply (rule SingleB[OF right])
    apply (rule combine_blocks_wait2) apply auto
    apply (rule combine_blocks_wait1) apply auto
     apply (rule combine_blocks_unpair2) apply auto
     apply (rule combine_blocks_unpair1) apply auto
    by (rule combine_blocks_empty)
qed

text \<open>
  The two sides can be synchronized, so the process
    (ch1!1 \<squnion> ch2!2)* || ((wait 1; ch1?x) || (wait 2; ch2?x))
  can produce the trace (1,s,{ch2!})^(1,s,{ch1?,ch2!})^(ch2,2)^(ch1,1).

  However, for the case of external choice, the two sides cannot be
  synchronized, since the test of compat_rdy fails in the time interval (1,2).
\<close>
lemma test_internal_parallel:
  "par_big_step (Parallel
    (Single (Rep (IChoice (Cm (''ch1''[!](\<lambda>_. 1))) (Cm (''ch2''[!](\<lambda>_. 2)))))) {''ch1'', ''ch2''}
    (Parallel (Single (Wait (\<lambda>_. 1); Cm (''ch1''[?]X))) {}
              (Single (Wait (\<lambda>_. 2); Cm (''ch2''[?]X)))))
    (ParState (State (\<lambda>_. 0)) (ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0))))
    [WaitBlk (1::real) (\<lambda>_. ParState (State (\<lambda>_. 0)) (ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0)))) ({''ch2''}, {}),
     WaitBlk (1::real) (\<lambda>_. ParState (State (\<lambda>_. 0)) (ParState (State (\<lambda>_. 0)) (State (\<lambda>_. 0)))) ({''ch2''}, {''ch1''}),
     IOBlock ''ch2'' 2,
     IOBlock ''ch1'' 1]
    (ParState (State (\<lambda>_. 0))
              (ParState (State ((\<lambda>_. 0)(X := 1))) (State ((\<lambda>_. 0)(X := 2)))))"
  apply (rule ParallelB)
    apply (rule SingleB[OF test_internal])
  apply (rule test_internal_other)
  apply (rule combine_blocks_wait3) apply auto
  apply (rule combine_blocks_wait1) apply auto
  apply (rule combine_blocks_pair2) apply auto
  apply (rule combine_blocks_pair2) apply auto
  by (rule combine_blocks_empty)

subsection \<open>Tests for combine_blocks\<close>

lemma test_combine1:
  "combine_blocks {''ch''} [InBlock ''ch'' v] [OutBlock ''ch'' v] [IOBlock ''ch'' v]"
  by (intro combine_blocks.intros, auto)

lemma test_combine1_unique:
  "combine_blocks {''ch''} [InBlock ''ch'' v] [OutBlock ''ch'' v] blks \<Longrightarrow>
   blks = [IOBlock ''ch'' v]"
  by (auto elim: sync_elims)

lemma test_combine2:
  "combine_blocks {} [InBlock ''ch1'' v] [OutBlock ''ch2'' w] [InBlock ''ch1'' v, OutBlock ''ch2'' w]"
  by (intro combine_blocks.intros, auto)

lemma test_combine2_unique:
  "combine_blocks {} [InBlock ''ch1'' v] [OutBlock ''ch2'' w] blks \<Longrightarrow>
   blks = [InBlock ''ch1'' v, OutBlock ''ch2'' w] \<or>
   blks = [OutBlock ''ch2'' w, InBlock ''ch1'' v]"
  apply (elim combine_blocks_unpairE2) by (auto elim: sync_elims)

subsection \<open>Examples of proofs using bare assertions\<close>

text \<open>Send 1\<close>
lemma testHL1:
  "\<Turnstile> {\<lambda>s tr. Q s (tr @ [OutBlock ''ch'' 1]) \<and>
              (\<forall>d::real>0. Q s (tr @ [WaitBlk d (\<lambda>_. State s) ({''ch''}, {}), OutBlock ''ch'' 1])) \<and>
              Q s (tr @ [WaitBlk \<infinity> (\<lambda>_. State s) ({''ch''}, {})])}
        Cm (''ch''[!](\<lambda>_. 1))
      {Q}"
  by (rule Valid_send)

text \<open>This implies the strongest postcondition form\<close>
lemma testHL2:
  "\<Turnstile> {\<lambda>s t. s = st \<and> t = tr}
        Cm (''ch''[!](\<lambda>_. 1))
      {\<lambda>s t. s = st \<and>
           (t = tr @ [OutBlock ''ch'' 1] \<or>
           (\<exists>d::real>0. t = tr @ [WaitBlk d (\<lambda>_. State st) ({''ch''}, {}), OutBlock ''ch'' 1])) \<or>
           (t = tr @ [WaitBlk \<infinity> (\<lambda>_. State st) ({''ch''}, {})])}"
  apply (rule Valid_weaken_pre)
   prefer 2
   apply (rule Valid_send)
  unfolding entails_def by auto

text \<open>Receive from ch\<close>
lemma testHL3:
  "\<Turnstile> {\<lambda>s tr.
        (\<forall>v. Q (s(X := v)) (tr @ [InBlock ''ch'' v])) \<and>
        (\<forall>d::real>0. \<forall>v. Q (s(X := v)) (tr @ [WaitBlk d (\<lambda>_. State s) ({}, {''ch''}), InBlock ''ch'' v])) \<and>
        Q s (tr @ [WaitBlk \<infinity> (\<lambda>_. State s) ({}, {''ch''})])}
       Cm (''ch''[?]X)
      {Q}"
  by (rule Valid_receive)

text \<open>Strongest postcondition form\<close>
lemma testHL4:
  "\<Turnstile> {\<lambda>s t. s = st \<and> t = tr}
       (Cm (''ch''[?]X))
      {\<lambda>s t. (\<exists>v. s = st(X := v) \<and> t = tr @ [InBlock ''ch'' v]) \<or>
             (\<exists>v. \<exists>d::real>0. s = st(X := v) \<and>
                t = tr @ [WaitBlk d (\<lambda>_. State st) ({}, {''ch''}), InBlock ''ch'' v]) \<or>
             (s = st \<and> t = tr @ [WaitBlk \<infinity> (\<lambda>_. State st) ({}, {''ch''})])}"
  apply (rule Valid_weaken_pre)
   prefer 2
   apply (rule testHL3)
  unfolding entails_def by auto

subsection \<open>Examples of proofs using simplified assertions\<close>

text \<open>Send 1\<close>
lemma testHL1s:
  "\<Turnstile> {\<lambda>s. Out\<^sub>t (State s) ''ch'' (s X) @- P s}
       Cm (''ch''[!](\<lambda>s. s X))
      {P}"
  by (rule Valid_send')

text \<open>Strongest postcondition form\<close>
lemma testHL1s':
  "\<Turnstile> {\<lambda>s. P s}
       Cm (''ch''[!](\<lambda>s. s X))
      {\<lambda>s. (P s @\<^sub>t Out\<^sub>t (State s) ''ch'' (s X))}"
  by (rule Valid_send_sp)

text \<open>Send 1, then send 2\<close>
lemma testHL2s:
  "\<Turnstile> {\<lambda>s. Out\<^sub>t (State s) ''ch'' (s X) @- Out\<^sub>t (State s) ''ch'' (s Y) @- P s}
        Cm (''ch''[!](\<lambda>s. s X)); Cm (''ch''[!](\<lambda>s. s Y))
      {P}"
  apply (rule Valid_seq)
    prefer 2 apply (rule Valid_send')
  by (rule Valid_send')

text \<open>Strongest postcondition form\<close>
lemma testHL2s':
  "\<Turnstile> {\<lambda>s. P s}
        Cm (''ch''[!](\<lambda>s. s X)); Cm (''ch''[!](\<lambda>s. s Y))
      {\<lambda>s. (P s @\<^sub>t (Out\<^sub>t (State s) ''ch'' (s X)) @\<^sub>t (Out\<^sub>t (State s) ''ch'' (s Y)))}"
  apply (rule Valid_seq)
   apply (rule Valid_send_sp)
  apply (rule Valid_strengthen_post)
   prefer 2 apply (rule Valid_send_sp)
  by (auto simp add: join_assoc)

text \<open>Receive from ch\<close>
lemma testHL3s:
  "\<Turnstile> {\<lambda>s. \<forall>\<^sub>tv. In\<^sub>t (State s) ''ch'' v @- P (s(X := v))}
        Cm (''ch''[?]X)
      {P}"
  by (rule Valid_receive')

text \<open>Strongest postcondition form\<close>
lemma testHL3s':
  "\<Turnstile> {\<lambda>s. P s}
       Cm (''ch''[?]X)
      {\<lambda>s t. \<exists>x v. (\<up>(s X = v) \<and>\<^sub>t (P(s(X := x)) @\<^sub>t In\<^sub>t (State (s(X := x))) ''ch'' v)) t}"
  by (rule Valid_receive_sp)

text \<open>Receive two values in a row\<close>
lemma testHL3a:
  "\<Turnstile> {\<lambda>s. \<forall>\<^sub>tv. In\<^sub>t (State s) ''ch'' v @- (\<forall>\<^sub>tw. In\<^sub>t (State (s(X := v))) ''ch'' w @- P (s(X := w)))}
        Cm (''ch''[?]X); Cm (''ch''[?]X)
      {P}"
  apply (rule Valid_weaken_pre) prefer 2
  apply (rule Valid_seq)
    prefer 2 apply (rule Valid_receive')
  apply (rule Valid_receive')
  by (auto simp add: entails_def)

text \<open>Strongest postcondition form\<close>
lemma testHL3a':
  "\<Turnstile> {\<lambda>s. P s}
        Cm (''ch''[?]X); Cm (''ch''[?]X)
      {\<lambda>s t. \<exists>x v w. (\<up>(s X = w) \<and>\<^sub>t (P(s(X := x)) @\<^sub>t In\<^sub>t (State (s(X := x))) ''ch'' v @\<^sub>t In\<^sub>t (State (s(X := v))) ''ch'' w)) t}"
  apply (rule Valid_seq)
   apply (rule Valid_receive_sp)
  apply (rule Valid_ex_pre) apply (rule Valid_ex_pre)
  subgoal for x v apply (rule Valid_ex_post)
    apply (rule exI[where x=x])
    apply (rule Valid_ex_post)
    apply (rule exI[where x=v])
    apply (rule Valid_strengthen_post)
     prefer 2 apply (rule Valid_receive_sp)
    apply (auto simp add: entails_def join_assoc)
    by (auto simp add: conj_assn_def pure_assn_def)
  done

text \<open>Communication\<close>
lemma testHL4s:
  "\<Turnstile>\<^sub>p
    {pair_assn (\<lambda>s. s = st1) (\<lambda>s. s = st2)}
      Parallel (Single (Cm (''ch''[!](\<lambda>s. s X)))) {''ch''}
               (Single (Cm (''ch''[?]X)))
    {left_gassn (sing_assn (\<lambda>s. s = st1)) \<and>\<^sub>g
     right_gassn (sing_assn (\<lambda>s. s = st2(X := st1 X))) \<and>\<^sub>g
     trace_gassn (IO\<^sub>t ''ch'' (st1 X))}"
  apply (rule ParValid_conseq')
    apply (rule ParValid_Parallel')
     apply (rule testHL1s')
    apply (rule testHL3s')
   apply auto[1]
  apply (auto simp add: sing_gassn_ex)
  apply (intro sync_gassn_ex_pre_right)
  subgoal for x v
    apply (auto simp add: entails_gassn_def)
    subgoal for s tr
      apply (elim sync_gassn_expand)
      subgoal for s1 s2
        apply (auto simp add: combine_assn_and_left combine_assn_and_right)
        apply (auto simp add: conj_assn_def pure_assn_def)
        apply (drule combine_assn_out_in'_tr)
        by (auto simp add: and_gassn_def trace_gassn_def)
      done
    done
  done

text \<open>Receive then send\<close>
lemma testHL5:
  "\<Turnstile> {\<lambda>s. \<forall>\<^sub>tv. In\<^sub>t (State s) ''ch1'' v @- Out\<^sub>t (State (s(X := v))) ''ch2'' (v + 1) @- Q (s(X := v))}
        Cm (''ch1''[?]X); Cm (''ch2''[!](\<lambda>s. s X + 1))
      {Q}"
  apply (rule Valid_weaken_pre)
   prefer 2 apply (rule Valid_seq)
    prefer 2 apply (rule Valid_send')
   apply (rule Valid_receive')
  by auto

text \<open>Receive then send, strongest postcondition version\<close>
lemma testHL5sp:
  "\<Turnstile>
    {\<lambda>s. P s}
      Cm (''ch1''[?]X); Cm (''ch2''[!](\<lambda>s. s X + 1))
    {\<lambda>s t. \<exists>x v. (P(s(X := x)) @\<^sub>t In\<^sub>t (State (s(X := x))) ''ch1'' v @\<^sub>t Out\<^sub>t (State s) ''ch2'' (v + 1)) t}"
  apply (rule Valid_seq)
   apply (rule Valid_receive_sp)
  apply (rule Valid_ex_pre) apply (rule Valid_ex_pre)
  subgoal for x v
    apply (rule Valid_strengthen_post)
     prefer 2 apply (rule Valid_send_sp)
    by (auto simp add: entails_def join_assoc conj_assn_def pure_assn_def)
  done

subsection \<open>Examples of proofs: internal choice\<close>

text \<open>Contrast this with the case of internal choice\<close>
lemma ichoice_test1:
  "\<Turnstile>
    {\<lambda>s. (\<forall>\<^sub>tv. In\<^sub>t (State s) ''ch1'' v @- Q (s(X := v))) \<and>\<^sub>t
         (\<forall>\<^sub>tv. In\<^sub>t (State s) ''ch2'' v @- Q (s(X := v)))}
      IChoice (Cm (''ch1''[?]X)) (Cm (''ch2''[?]X))
    {Q}"
  apply (rule Valid_weaken_pre)
   prefer 2 apply (rule Valid_ichoice)
    apply (rule Valid_receive') apply (rule Valid_receive')
  unfolding entails_def conj_assn_def by auto

text \<open>Strongest postcondition form\<close>
lemma ichoice_test1':
  "\<Turnstile>
    {\<lambda>s. P s}
      IChoice (Cm (''ch1''[?]X)) (Cm (''ch2''[?]X))
    {\<lambda>s tr. (\<exists>x v. (\<up>(s X = v) \<and>\<^sub>t (P(s(X := x)) @\<^sub>t In\<^sub>t (State (s(X := x))) ''ch1'' v)) tr) \<or>
            (\<exists>x v. (\<up>(s X = v) \<and>\<^sub>t (P(s(X := x)) @\<^sub>t In\<^sub>t (State (s(X := x))) ''ch2'' v)) tr)}"
  apply (rule Valid_strengthen_post)
   prefer 2 apply (rule Valid_ichoice_sp)
    apply (rule Valid_receive_sp)
  apply (rule Valid_receive_sp) by auto

subsection \<open>Examples of proofs: external choice\<close>

text \<open>A simple test\<close>
lemma echoice_test:
  "\<Turnstile>
    {\<lambda>s. (\<forall>\<^sub>tv. ((Inrdy\<^sub>t s ''ch1'' v ({}, {''ch1'', ''ch2''})) @- Q (s(X := v)))) \<and>\<^sub>t
         (\<forall>\<^sub>tv. ((Inrdy\<^sub>t s ''ch2'' v ({}, {''ch1'', ''ch2''})) @- Q (s(X := v))))}
      EChoice [(''ch1''[?]X, Skip), (''ch2''[?]X, Skip)]
    {Q}"
  apply (rule Valid_echoice_InIn')
   apply (rule Valid_skip)
  by (rule Valid_skip)

text \<open>Strongest postcondition form\<close>
lemma echoice_test_sp:
  "\<Turnstile>
    {\<lambda>s tr. s = st \<and> P s tr}
      EChoice [(''ch1''[?]X, Y ::= (\<lambda>s. s Y + s X)), (''ch2''[?]X, Y ::= (\<lambda>s. s Y - s X))]
    {\<lambda>s tr. (\<exists>v. s = st(X := v, Y := st Y + v) \<and> (P st @\<^sub>t Inrdy\<^sub>t st ''ch1'' v ({}, {''ch1'', ''ch2''})) tr) \<or>
            (\<exists>v. s = st(X := v, Y := st Y - v) \<and> (P st @\<^sub>t Inrdy\<^sub>t st ''ch2'' v ({}, {''ch1'', ''ch2''})) tr)}"
  apply (rule Valid_strengthen_post)
  prefer 2
   apply (rule Valid_echoice_InIn_sp)
    apply (rule Valid_assign_sp_st)
   apply (rule Valid_assign_sp_st)
  by auto

text \<open>
  Now we do a more complex example. The program is:
    (ch1?x -> y := y + x [] ch2?x -> y := y - x)*

  The loop invariant takes two arguments: the current state and
  a list of direction-value pairs, where direction is either CH1 or CH2,
  specifying from which channel is the value received.
\<close>
datatype dir = CH1 | CH2

fun echoice_ex_inv :: "state \<Rightarrow> (dir \<times> real) list \<Rightarrow> tassn" where
  "echoice_ex_inv st [] = emp\<^sub>t"
| "echoice_ex_inv st ((CH1, v) # rest) =
    Inrdy\<^sub>t st ''ch1'' v ({}, {''ch1'', ''ch2''}) @\<^sub>t echoice_ex_inv (st(X := v, Y := st Y + v)) rest"
| "echoice_ex_inv st ((CH2, v) # rest) =
    Inrdy\<^sub>t st ''ch2'' v ({}, {''ch1'', ''ch2''}) @\<^sub>t echoice_ex_inv (st(X := v, Y := st Y - v)) rest"

fun last_echoice_ex :: "state \<Rightarrow> (dir \<times> real) list \<Rightarrow> state" where
  "last_echoice_ex st [] = st"
| "last_echoice_ex st ((CH1, v) # rest) = last_echoice_ex (st(X := v, Y := st Y + v)) rest"
| "last_echoice_ex st ((CH2, v) # rest) = last_echoice_ex (st(X := v, Y := st Y - v)) rest"

lemma echoice_ex_inv_snoc [simp]:
  "echoice_ex_inv st (ins @ [(CH1, v)]) =
    echoice_ex_inv st ins @\<^sub>t Inrdy\<^sub>t (last_echoice_ex st ins) ''ch1'' v ({}, {''ch1'', ''ch2''}) \<and>
   echoice_ex_inv st (ins @ [(CH2, v)]) =
    echoice_ex_inv st ins @\<^sub>t Inrdy\<^sub>t (last_echoice_ex st ins) ''ch2'' v ({}, {''ch1'', ''ch2''})"
  apply (induct ins arbitrary: st)
  subgoal by auto
  apply auto subgoal for dir v ins st
    apply (cases dir)
    by (auto simp add: join_assoc)
  subgoal for dir v ins st
    apply (cases dir)
    by (auto simp add: join_assoc)
  done

lemma last_echoice_ex_snoc [simp]:
  "last_echoice_ex st (ins @ [(CH1, v)]) = (last_echoice_ex st ins)(X := v, Y := last_echoice_ex st ins Y + v) \<and>
   last_echoice_ex st (ins @ [(CH2, v)]) = (last_echoice_ex st ins)(X := v, Y := last_echoice_ex st ins Y - v)"
  apply (induct ins arbitrary: st)
  apply auto
  by (metis (full_types) dir.exhaust last_echoice_ex.simps(2) last_echoice_ex.simps(3))+

lemma testEChoice:
  "\<Turnstile>
    {\<lambda>s tr. s = st \<and> tr = []}
      Rep (EChoice [(''ch1''[?]X, Y ::= (\<lambda>s. s Y + s X)),
                    (''ch2''[?]X, Y ::= (\<lambda>s. s Y - s X))])
    {\<lambda>s tr. \<exists>ins. s = last_echoice_ex st ins \<and> echoice_ex_inv st ins tr}"
  apply (rule Valid_weaken_pre)
   prefer 2 apply (rule Valid_rep)
   apply (rule Valid_ex_pre)
  subgoal for ins
    apply (rule Valid_strengthen_post)
    prefer 2
     apply (rule Valid_echoice_InIn_sp)
    apply (rule Valid_assign_sp_st)
     apply (rule Valid_assign_sp_st)
    apply (auto simp add: entails_def)
    subgoal for tr v
      apply (rule exI[where x="ins@[(CH1,v)]"])
      by auto
    subgoal for tr v
      apply (rule exI[where x="ins@[(CH2,v)]"])
      by auto
    done
  apply (auto simp add: entails_def)
  apply (rule exI[where x="[]"])
  by (auto simp add: emp_assn_def)

subsection \<open>Example of loops\<close>

text \<open>First example simply counts up variable X:
  c1 ::= (x := x + 1; ch!x)*
\<close>
fun count_up_inv :: "real \<Rightarrow> nat \<Rightarrow> tassn" where
  "count_up_inv a 0 = emp\<^sub>t"
| "count_up_inv a (Suc n) = Out\<^sub>t (State ((\<lambda>_. 0)(X := a + 1))) ''ch'' (a + 1) @\<^sub>t count_up_inv (a + 1) n"

lemma count_up_inv_Suc:
  "count_up_inv a (Suc n) = count_up_inv a n @\<^sub>t Out\<^sub>t (State ((\<lambda>_. 0)(X := a + real n + 1))) ''ch'' (a + real n + 1)"
  apply (induct n arbitrary: a)
   apply (auto simp add: join_assoc)
  by (smt join_assoc)

lemma testLoop1:
  "\<Turnstile>
    {\<lambda>s tr. s = ((\<lambda>_. 0)(X := a)) \<and> emp\<^sub>t tr}
      Rep (Assign X (\<lambda>s. s X + 1); Cm (''ch''[!](\<lambda>s. s X)))
    {\<lambda>s tr. \<exists>n. s = ((\<lambda>_. 0)(X := a + n)) \<and> count_up_inv a n tr}"
  apply (rule Valid_weaken_pre)
   prefer 2 apply (rule Valid_rep)
  apply (rule Valid_ex_pre)
  subgoal for n
    apply (rule Valid_seq)
     apply (rule Valid_assign_sp)
    apply (rule Valid_ex_pre)
    subgoal for x
  apply (rule Valid_strengthen_post) prefer 2
     apply (rule Valid_send_sp)
    apply (auto simp add: entails_def)
    apply (rule exI[where x="Suc n"])
      apply (auto simp add: count_up_inv_Suc conj_assn_def pure_assn_def simp del: count_up_inv.simps)
       apply (metis add.commute add.left_commute fun_upd_idem_iff fun_upd_upd)
      by (metis fun_upd_same fun_upd_triv fun_upd_upd)
    done
  apply (auto simp add: entails_def)
  apply (rule exI[where x=0])
  by (auto simp add: emp_assn_def)

text \<open>Second example: in each iteration, increment by 1, output, then increment by 2:
  c2 ::= (x := x + 1; ch!x; x := x + 2)*
\<close>
fun count_up3_inv :: "nat \<Rightarrow> tassn" where
  "count_up3_inv 0 = emp\<^sub>t"
| "count_up3_inv (Suc n) = count_up3_inv n @\<^sub>t Out\<^sub>t (State ((\<lambda>_. 0)(X := 3 * real n + 1))) ''ch'' (3 * real n + 1)"

lemma testLoop2:
  "\<Turnstile>
    {\<lambda>s tr. s = ((\<lambda>_. 0)(X := 0)) \<and> emp\<^sub>t tr}
      Rep (Assign X (\<lambda>s. s X + 1); Cm (''ch''[!](\<lambda>s. s X)); Assign X (\<lambda>s. s X + 2))
    {\<lambda>s tr. \<exists>n. s = ((\<lambda>_. 0)(X := 3 * real n)) \<and> count_up3_inv n tr}"
  apply (rule Valid_weaken_pre)
   prefer 2 apply (rule Valid_rep)
   apply (rule Valid_ex_pre)
  subgoal for n
    apply (rule Valid_seq)
     apply (rule Valid_assign_sp)
    apply (rule Valid_ex_pre)
    subgoal for x
    apply (rule Valid_seq)
     apply (rule Valid_send_sp)
    apply (rule Valid_strengthen_post)
       prefer 2 apply (rule Valid_assign_sp)
    apply (auto simp add: entails_def)
    apply (rule exI[where x="Suc n"])
      apply (auto simp add: conj_assn_def pure_assn_def)
       apply (frule fun_upd_eqD)
      apply auto apply (metis fun_upd_idem_iff fun_upd_upd)
      apply (frule fun_upd_eqD)
      apply auto
      by (metis (full_types) fun_upd_upd)
    done
    apply (auto simp add: entails_def)
  apply (rule exI[where x=0])
  by (auto simp add: emp_assn_def)

text \<open>Third example: repeatedly receive value to variable y:
  c3 ::= (ch?y)*
\<close>

text \<open>Loop invariant, here
  - a is the starting value of y.
\<close>
fun receive_inv :: "real \<Rightarrow> real list \<Rightarrow> tassn" where
  "receive_inv a [] = emp\<^sub>t"
| "receive_inv a (x # xs) = In\<^sub>t (State ((\<lambda>_. 0)(Y := a))) ''ch'' x @\<^sub>t receive_inv x xs"

fun last_val :: "real \<Rightarrow> real list \<Rightarrow> real" where
  "last_val a [] = a"
| "last_val a (x # xs) = last_val x xs"

lemma receive_inv_snoc:
  "receive_inv a (xs @ [v]) = receive_inv a xs @\<^sub>t In\<^sub>t (State ((\<lambda>_. 0)(Y := last_val a xs))) ''ch'' v"
  apply (induct xs arbitrary: a)
  by (auto simp add: join_assoc)

lemma last_val_snoc [simp]:
  "last_val a (xs @ [v]) = v"
  by (induct xs arbitrary: a, auto)

lemma testLoop3:
  "\<Turnstile>
    {\<lambda>s tr. s = ((\<lambda>_. 0)(Y := a)) \<and> emp\<^sub>t tr}
      Rep (Cm (''ch''[?]Y))
    {\<lambda>s tr. \<exists>xs. s = ((\<lambda>_. 0)(Y := last_val a xs)) \<and> receive_inv a xs tr}"
  apply (rule Valid_weaken_pre)
   prefer 2 apply (rule Valid_rep)
  apply (rule Valid_ex_pre)
  subgoal for xs
    apply (rule Valid_strengthen_post)
     prefer 2 apply (rule Valid_receive_sp)
    apply (auto simp add: entails_def)
    subgoal for s tr x v
      apply (rule exI[where x="xs@[v]"])
      apply (auto simp add: conj_assn_def pure_assn_def receive_inv_snoc)
      by (metis fun_upd_triv fun_upd_upd)
    done
  apply (auto simp add: entails_def)
  apply (rule exI[where x="[]"])
  by (auto simp add: emp_assn_def)

text \<open>Fourth example: repeated receives and adds the input values:
  c4 ::= (ch?y; x := x + y)*
\<close>

text \<open>Loop invariant, here
  - a is the starting value of x,
  - b is the starting value of y.
\<close>
fun receive_add_inv :: "real \<Rightarrow> real \<Rightarrow> real list \<Rightarrow> tassn" where
  "receive_add_inv a b [] = emp\<^sub>t"
| "receive_add_inv a b (x # xs) = In\<^sub>t (State ((\<lambda>_. 0)(X := a, Y := b))) ''ch'' x @\<^sub>t receive_add_inv (a + x) x xs"

fun last_add_val :: "real \<Rightarrow> real list \<Rightarrow> real" where
  "last_add_val a [] = a"
| "last_add_val a (x # xs) = last_add_val (a + x) xs"

lemma receive_add_inv_snoc:
  "receive_add_inv a b (xs @ [v]) =
    receive_add_inv a b xs @\<^sub>t
    In\<^sub>t (State ((\<lambda>_. 0)(X := last_add_val a xs, Y := last_val b xs))) ''ch'' v"
  apply (induct xs arbitrary: a b)
  by (auto simp add: join_assoc)

lemma last_add_val_snoc [simp]:
  "last_add_val a (xs @ [v]) = last_add_val a xs + v"
  by (induct xs arbitrary: a, auto)

lemma testLoop4:
  "\<Turnstile>
    {\<lambda>s tr. s = ((\<lambda>_. 0)(X := a, Y := b)) \<and> emp\<^sub>t tr}
     Rep (Cm (''ch''[?]Y); X ::= (\<lambda>s. s X + s Y))
    {\<lambda>s tr. \<exists>xs. s = ((\<lambda>_. 0)(X := last_add_val a xs, Y := last_val b xs)) \<and> receive_add_inv a b xs tr}"
  apply (rule Valid_weaken_pre)
   prefer 2 apply (rule Valid_rep)
  apply (rule Valid_ex_pre)
  subgoal for xs
    apply (rule Valid_seq)
     apply (rule Valid_receive_sp)
    apply (intro Valid_ex_pre)
    subgoal for x v
      apply (rule Valid_strengthen_post)
       prefer 2
       apply (rule Valid_assign_sp)
    apply (auto simp add: entails_def)
    subgoal for s tr x'
      apply (rule exI[where x="xs@[v]"])
      apply (auto simp add: receive_add_inv_snoc conj_assn_def pure_assn_def)
      by (smt fun_upd_same fun_upd_triv fun_upd_twist fun_upd_upd)
    done
  done
  apply (auto simp add: entails_def)
  apply (rule exI[where x="[]"])
  by (auto simp add: emp_assn_def)

subsection \<open>Example of parallel\<close>

text \<open>
  We consider the parallel of c1 || c3. Recall
    c1 ::= (x := x + 1; ch!x)*
    c3 ::= (ch?y)*
\<close>
fun count_up_io_inv :: "real \<Rightarrow> nat \<Rightarrow> tassn" where
  "count_up_io_inv a 0 = emp\<^sub>t"
| "count_up_io_inv a (Suc n) = IO\<^sub>t ''ch'' (a + 1) @\<^sub>t count_up_io_inv (a + 1) n"

fun count_up_list :: "real \<Rightarrow> nat \<Rightarrow> real list" where
  "count_up_list a 0 = []"
| "count_up_list a (Suc n) = (a + 1) # count_up_list (a + 1) n"

lemma last_val_count_up_list [simp]:
  "last_val a (count_up_list a n) = a + n"
  apply (induction n arbitrary: a) by auto

lemma combine_count_up:
  "combine_assn {''ch''} (count_up_inv a n) (receive_inv b xs) \<Longrightarrow>\<^sub>t
   \<up>(xs = count_up_list a n) \<and>\<^sub>t count_up_io_inv a n"
proof (induction n arbitrary: a b xs)
  case 0
  show ?case
  proof (cases xs)
    case Nil
    then show ?thesis
      by (auto simp add: conj_assn_def pure_assn_def)
  next
    case (Cons x xs')
    then show ?thesis
      by (auto simp add: combine_assn_emp_in)
  qed
next
  case (Suc n)
  show ?case
  proof (cases xs)
    case Nil
    then show ?thesis
      by (auto simp add: combine_assn_out_emp)
  next
    case (Cons x xs')
    then show ?thesis
      apply auto
      apply (rule entails_tassn_trans)
       apply (rule combine_assn_out_in)
       apply (auto simp add: entails_tassn_def)
      using Suc[of "a + 1" "a + 1" xs']
      unfolding entails_tassn_def conj_assn_def pure_assn_def join_assn_def
      by auto
  qed
qed

lemma testLoopPar:
  "\<Turnstile>\<^sub>p
    {pair_assn (\<lambda>s. s = ((\<lambda>_. 0)(X := a))) (\<lambda>s. s = ((\<lambda>_. 0)(Y := a)))}
      Parallel (Single (Rep (Assign X (\<lambda>s. s X + 1); Cm (''ch''[!](\<lambda>s. s X))))) {''ch''}
               (Single (Rep (Cm (''ch''[?]Y))))
    {\<exists>\<^sub>gn. left_gassn (sing_assn (\<lambda>s. s = ((\<lambda>_. 0)(X := a + n)))) \<and>\<^sub>g
          right_gassn (sing_assn (\<lambda>s. s = ((\<lambda>_. 0)(Y := a + n)))) \<and>\<^sub>g
          trace_gassn (count_up_io_inv a n)}"
  apply (rule ParValid_conseq')
    apply (rule ParValid_Parallel')
     apply (rule testLoop1)
    apply (rule testLoop3)
   apply (auto simp add: sing_gassn_ex sing_gassn_split)
  apply (rule sync_gassn_ex_pre_left)
  apply (rule sync_gassn_ex_pre_right)
  subgoal for n xs
    unfolding sync_gassn_state_left sync_gassn_state_right
    apply (rule entails_ex_gassn)
    apply (rule exI[where x=n])
    apply (rule and_entails_gassn2[OF sync_gassn_traces])
    apply (rule and_entails_gassn2[OF entails_trace_gassn])
    apply (rule entails_tassn_trans)
     prefer 2 apply (rule combine_count_up)
    apply (rule combine_assn_mono)
    by (auto simp add: entails_tassn_def entails_gassn_def and_gassn_def conj_assn_def
                       trace_gassn_def pure_assn_def)
  done

end


(*  Title:      HOL/SET_Protocol/Event_SET.thy
    Author:     Giampaolo Bella
    Author:     Fabio Massacci
    Author:     Lawrence C Paulson
*)

section\<open>Theory of Events for SET\<close>

theory Event_SET
imports Message_SET
begin

text\<open>The Root Certification Authority\<close>
abbreviation "RCA == CA 0"

text\<open>Message events\<close>
datatype
  event = Says  agent agent msg
        | Gets  agent       msg
        | Notes agent       msg

text\<open>compromised agents: keys known, Notes visible\<close>
consts bad :: "agent set"

text\<open>Spy has access to his own key for spoof messages, but RCA is secure\<close>
specification (bad)
  Spy_in_bad     [iff]: "Spy \<in> bad"
  RCA_not_bad [iff]: "RCA \<notin> bad"
    by (rule exI [of _ "{Spy}"], simp)

subsection\<open>Agents' Knowledge\<close>

consts  (*Initial states of agents -- parameter of the construction*)
  initState :: "agent \<Rightarrow> msg set"

(* Message reception does not extend spy's knowledge because of
   reception invariant enforced by Reception rule in protocol definition*)
primrec knows :: "[agent, event list] \<Rightarrow> msg set"
where
  knows_Nil:
    "knows A [] = initState A"
| knows_Cons:
    "knows A (ev # evs) =
       (if A = Spy then
        (case ev of
           Says A' B X \<Rightarrow> insert X (knows Spy evs)
         | Gets A' X \<Rightarrow> knows Spy evs
         | Notes A' X  \<Rightarrow>
             if A' \<in> bad then insert X (knows Spy evs) else knows Spy evs)
        else
        (case ev of
           Says A' B X \<Rightarrow>
             if A'=A then insert X (knows A evs) else knows A evs
         | Gets A' X    \<Rightarrow>
             if A'=A then insert X (knows A evs) else knows A evs
         | Notes A' X    \<Rightarrow>
             if A'=A then insert X (knows A evs) else knows A evs))"

subsection\<open>Used Messages\<close>

primrec used :: "event list \<Rightarrow> msg set"
where
  (*Set of items that might be visible to somebody:
    complement of the set of fresh items.
    As above, message reception does extend used items *)
  used_Nil:  "used []         = (UN B. parts (initState B))"
| used_Cons: "used (ev # evs) =
                 (case ev of
                    Says A B X \<Rightarrow> parts {X} \<union> (used evs)
                  | Gets A X   \<Rightarrow> used evs
                  | Notes A X  \<Rightarrow> parts {X} \<union> (used evs))"

(* Inserted by default but later removed.  This declaration lets the file
be re-loaded. Addsimps [knows_Cons, used_Nil, *)

(** Simplifying   parts (insert X (knows Spy evs))
      = parts {X} \<union> parts (knows Spy evs) -- since general case loops*)

lemmas parts_insert_knows_A = parts_insert [of _ "knows A evs"] for A evs

text\<open>Letting the Spy see "bad" agents' notes avoids redundant case-splits
      on whether \<^term>\<open>A=Spy\<close> and whether \<^term>\<open>A\<in>bad\<close>\<close>
lemma knows_Spy_Notes [simp]:
     "knows Spy (Notes A X # evs) =
          (if A\<in>bad then insert X (knows Spy evs) else knows Spy evs)"
apply auto
done

lemma knows_Spy_Gets [simp]: "knows Spy (Gets A X # evs) = knows Spy evs"
by auto

lemma initState_subset_knows: "initState A \<subseteq> knows A evs"
apply (induct_tac "evs")
apply (auto split: event.split)
done

lemma knows_Spy_subset_knows_Spy_Says:
     "knows Spy evs \<subseteq> knows Spy (Says A B X # evs)"
by auto

lemma knows_Spy_subset_knows_Spy_Notes:
     "knows Spy evs \<subseteq> knows Spy (Notes A X # evs)"
by auto

lemma knows_Spy_subset_knows_Spy_Gets:
     "knows Spy evs \<subseteq> knows Spy (Gets A X # evs)"
by auto

(*Spy sees what is sent on the traffic*)
lemma Says_imp_knows_Spy [rule_format]:
     "Says A B X \<in> set evs \<longrightarrow> X \<in> knows Spy evs"
apply (induct_tac "evs")
apply (auto split: event.split)
done

(*Use with addSEs to derive contradictions from old Says events containing
  items known to be fresh*)
lemmas knows_Spy_partsEs =
     Says_imp_knows_Spy [THEN parts.Inj, elim_format]
     parts.Body [elim_format]

subsection\<open>The Function \<^term>\<open>used\<close>\<close>

lemma parts_knows_Spy_subset_used: "parts (knows Spy evs) \<subseteq> used evs"
apply (induct_tac "evs")
apply (auto simp add: parts_insert_knows_A split: event.split)
done

lemmas usedI = parts_knows_Spy_subset_used [THEN subsetD, intro]

lemma initState_subset_used: "parts (initState B) \<subseteq> used evs"
apply (induct_tac "evs")
apply (auto split: event.split)
done

lemmas initState_into_used = initState_subset_used [THEN subsetD]

lemma used_Says [simp]: "used (Says A B X # evs) = parts{X} \<union> used evs"
by auto

lemma used_Notes [simp]: "used (Notes A X # evs) = parts{X} \<union> used evs"
by auto

lemma used_Gets [simp]: "used (Gets A X # evs) = used evs"
by auto

lemma Notes_imp_parts_subset_used [rule_format]:
     "Notes A X \<in> set evs \<longrightarrow> parts {X} \<subseteq> used evs"
apply (induct_tac "evs")
apply (rename_tac [2] a evs')
apply (induct_tac [2] "a", auto)
done

text\<open>NOTE REMOVAL--laws above are cleaner, as they don't involve "case"\<close>
declare knows_Cons [simp del]
        used_Nil [simp del] used_Cons [simp del]

text\<open>For proving theorems of the form \<^term>\<open>X \<notin> analz (knows Spy evs) \<longrightarrow> P\<close>
  New events added by induction to "evs" are discarded.  Provided
  this information isn't needed, the proof will be much shorter, since
  it will omit complicated reasoning about \<^term>\<open>analz\<close>.\<close>

lemmas analz_mono_contra =
       knows_Spy_subset_knows_Spy_Says [THEN analz_mono, THEN contra_subsetD]
       knows_Spy_subset_knows_Spy_Notes [THEN analz_mono, THEN contra_subsetD]
       knows_Spy_subset_knows_Spy_Gets [THEN analz_mono, THEN contra_subsetD]

lemmas analz_impI = impI [where P = "Y \<notin> analz (knows Spy evs)"] for Y evs

ML
\<open>
fun analz_mono_contra_tac ctxt =
  resolve_tac ctxt @{thms analz_impI} THEN'
  REPEAT1 o (dresolve_tac ctxt @{thms analz_mono_contra})
  THEN' mp_tac ctxt
\<close>

method_setup analz_mono_contra = \<open>
    Scan.succeed (fn ctxt => SIMPLE_METHOD (REPEAT_FIRST (analz_mono_contra_tac ctxt)))\<close>
    "for proving theorems of the form X \<notin> analz (knows Spy evs) \<longrightarrow> P"

end


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

theory n_mutualEx_base2 imports paraTheory
begin

section{*Main definitions*}

subsection{* Definitions of Constants*}
definition I::"scalrValueType" where [simp]: "I\<equiv> enum ''control'' ''I''"
definition T::"scalrValueType" where [simp]: "T\<equiv> enum ''control'' ''T''"
definition C::"scalrValueType" where [simp]: "C\<equiv> enum ''control'' ''C''"
definition E::"scalrValueType" where [simp]: "E\<equiv> enum ''control'' ''E''"
definition true::"scalrValueType" where [simp]: "true\<equiv> boolV True"
definition false::"scalrValueType" where [simp]: "false\<equiv> boolV False"

subsection{*  Definitions of Parameterized Rules *}

definition n_Try::"nat \<Rightarrow> rule" where [simp]:
"n_Try  i\<equiv>
let g = (eqn (IVar (Para (Ident ''n'') i)) (Const I)) in
let s = (parallelList [(assign ((Para (Ident ''n'') i), (Const T)))]) in
guard g s"

definition n_Crit::"nat \<Rightarrow> rule" where [simp]:
"n_Crit  i\<equiv>
let g = (andForm (eqn (IVar (Para (Ident ''n'') i)) (Const T)) (eqn (IVar (Ident ''x'')) (Const true))) in
let s = (parallelList [(assign ((Para (Ident ''n'') i), (Const C))), (assign ((Ident ''x''), (Const false)))]) in
guard g s"

definition n_Exit::"nat \<Rightarrow> rule" where [simp]:
"n_Exit  i\<equiv>
let g = (eqn (IVar (Para (Ident ''n'') i)) (Const C)) in
let s = (parallelList [(assign ((Para (Ident ''n'') i), (Const E)))]) in
guard g s"

definition n_Idle::"nat \<Rightarrow> rule" where [simp]:
"n_Idle  i\<equiv>
let g = (eqn (IVar (Para (Ident ''n'') i)) (Const E)) in
let s = (parallelList [(assign ((Para (Ident ''n'') i), (Const I))), (assign ((Ident ''x''), (Const true)))]) in
guard g s"

definition n_Crit_i_3::"nat \<Rightarrow> rule" where [simp]:
"n_Crit_i_3 N \<equiv>
let g = (andForm (andForm (eqn (IVar (Ident ''x'')) (Const true)) (forallForm (down N) (\<lambda>i. (neg (eqn (IVar (Para (Ident ''n'') i)) (Const E)))))) (forallForm (down N) (\<lambda>i. (neg (eqn (IVar (Para (Ident ''n'') i)) (Const C)))))) in
let s = (parallelList [(assign ((Ident ''x''), (Const false)))]) in
guard g s"

definition n_Idle_i_3::"nat \<Rightarrow> rule" where [simp]:
"n_Idle_i_3 N \<equiv>
let g = (andForm (andForm (andForm (andForm (forallForm (down N) (\<lambda>i. (neg (eqn (IVar (Para (Ident ''n'') i)) (Const E))))) (forallForm (down N) (\<lambda>i. (neg (eqn (IVar (Para (Ident ''n'') i)) (Const C)))))) (eqn (IVar (Ident ''x'')) (Const false))) (forallForm (down N) (\<lambda>j. (neg (eqn (IVar (Para (Ident ''n'') j)) (Const E)))))) (forallForm (down N) (\<lambda>j. (neg (eqn (IVar (Para (Ident ''n'') j)) (Const C)))))) in
let s = (parallelList [(assign ((Ident ''x''), (Const true)))]) in
guard g s"

subsection{*The set of All actual Rules w.r.t. a Protocol Instance with Size $N$*}
definition rules::"nat \<Rightarrow> rule set" where [simp]:
"rules N \<equiv> {r.
(\<exists> i. i\<le>N\<and>r=n_Try  i) \<or>
(\<exists> i. i\<le>N\<and>r=n_Crit  i) \<or>
(\<exists> i. i\<le>N\<and>r=n_Exit  i) \<or>
(\<exists> i. i\<le>N\<and>r=n_Idle  i) \<or>
(r=n_Crit_i_3 N ) \<or>
(r=n_Idle_i_3 N )
}"

subsection{*Definitions of a Formally Parameterized Invariant Formulas*}

definition inv_34::"nat \<Rightarrow> nat \<Rightarrow> formula" where [simp]:
"inv_34 j i \<equiv>
(neg (implyForm (andForm (neg (eqn (IVar (Para (Ident ''n'') i)) (Const I))) (neg (eqn (IVar (Para (Ident ''n'') i)) (Const T)))) (neg (eqn (IVar (Para (Ident ''n'') j)) (Const E)))))"

definition inv_33::"nat \<Rightarrow> formula" where [simp]:
"inv_33 j \<equiv>
(neg (implyForm (eqn (IVar (Para (Ident ''n'') j)) (Const E)) (eqn (IVar (Ident ''x'')) (Const false))))"

definition inv_32::"nat \<Rightarrow> nat \<Rightarrow> formula" where [simp]:
"inv_32 j i \<equiv>
(neg (implyForm (eqn (IVar (Para (Ident ''n'') j)) (Const E)) (neg (eqn (IVar (Para (Ident ''n'') i)) (Const C)))))"

definition inv_30::"nat \<Rightarrow> formula" where [simp]:
"inv_30 i \<equiv>
(neg (implyForm (eqn (IVar (Ident ''x'')) (Const true)) (neg (eqn (IVar (Para (Ident ''n'') i)) (Const E)))))"

definition inv_26::"nat \<Rightarrow> nat \<Rightarrow> formula" where [simp]:
"inv_26 j i \<equiv>
(neg (implyForm (andForm (neg (eqn (IVar (Para (Ident ''n'') j)) (Const T))) (neg (eqn (IVar (Para (Ident ''n'') j)) (Const I)))) (neg (eqn (IVar (Para (Ident ''n'') i)) (Const E)))))"

definition inv_22::"nat \<Rightarrow> formula" where [simp]:
"inv_22 j \<equiv>
(neg (implyForm (andForm (neg (eqn (IVar (Para (Ident ''n'') j)) (Const T))) (neg (eqn (IVar (Para (Ident ''n'') j)) (Const I)))) (eqn (IVar (Ident ''x'')) (Const false))))"

definition inv_16::"nat \<Rightarrow> formula" where [simp]:
"inv_16 i \<equiv>
(neg (implyForm (eqn (IVar (Ident ''x'')) (Const true)) (neg (eqn (IVar (Para (Ident ''n'') i)) (Const C)))))"

definition inv_15::"nat \<Rightarrow> nat \<Rightarrow> formula" where [simp]:
"inv_15 j i \<equiv>
(neg (implyForm (eqn (IVar (Para (Ident ''n'') j)) (Const E)) (neg (eqn (IVar (Para (Ident ''n'') i)) (Const E)))))"

definition inv_11::"nat \<Rightarrow> nat \<Rightarrow> formula" where [simp]:
"inv_11 j i \<equiv>
(neg (implyForm (andForm (neg (eqn (IVar (Para (Ident ''n'') i)) (Const I))) (neg (eqn (IVar (Para (Ident ''n'') i)) (Const T)))) (neg (eqn (IVar (Para (Ident ''n'') j)) (Const C)))))"

definition inv_4::"nat \<Rightarrow> nat \<Rightarrow> formula" where [simp]:
"inv_4 j i \<equiv>
(neg (implyForm (andForm (neg (eqn (IVar (Para (Ident ''n'') j)) (Const T))) (neg (eqn (IVar (Para (Ident ''n'') j)) (Const I)))) (neg (eqn (IVar (Para (Ident ''n'') i)) (Const C)))))"

definition inv_1::"nat \<Rightarrow> formula" where [simp]:
"inv_1 i \<equiv>
(neg (implyForm (andForm (neg (eqn (IVar (Para (Ident ''n'') i)) (Const I))) (neg (eqn (IVar (Para (Ident ''n'') i)) (Const T)))) (eqn (IVar (Ident ''x'')) (Const false))))"

subsection{*Definitions of  the Set of Invariant Formula Instances in a $N$-protocol Instance*}
definition invariants::"nat \<Rightarrow> formula set" where [simp]:
"invariants N \<equiv> {f.
(\<exists> j i. j\<le>N\<and>i\<le>N\<and>j~=i\<and>f=inv_34  j i) \<or>
(\<exists> j. j\<le>N\<and>f=inv_33  j) \<or>
(\<exists> j i. j\<le>N\<and>i\<le>N\<and>j~=i\<and>f=inv_32  j i) \<or>
(\<exists> i. i\<le>N\<and>f=inv_30  i) \<or>
(\<exists> j i. j\<le>N\<and>i\<le>N\<and>j~=i\<and>f=inv_26  j i) \<or>
(\<exists> j. j\<le>N\<and>f=inv_22  j) \<or>
(\<exists> i. i\<le>N\<and>f=inv_16  i) \<or>
(\<exists> j i. j\<le>N\<and>i\<le>N\<and>j~=i\<and>f=inv_15  j i) \<or>
(\<exists> j i. j\<le>N\<and>i\<le>N\<and>j~=i\<and>f=inv_11  j i) \<or>
(\<exists> j i. j\<le>N\<and>i\<le>N\<and>j~=i\<and>f=inv_4  j i) \<or>
(\<exists> i. i\<le>N\<and>f=inv_1  i)
}"

subsection{*Definitions of initial states*}

lemma lemmaOnn_TryLeNc:
  assumes a1:"i\<le>NC"
  shows "trans_sim_on1 (n_Try i) (n_Try i) (set invariantsAbs) s" (is "trans_sim_on1 ?r ?r ?F s")
proof(rule ruleSimId)
  show  "∀v. v∈varOfForm (pre ?r) ⟶  v ∈(varOfFormList invariantsAbs) "
    by(cut_tac a1, auto)

next
  show  b1: "∀v a. a ∈ set (statement2Assigns (act ?r)) ⟶ v∈varOfExp ( substExpByStatement (IVar (fst a))  (act ?r))⟶v ∈varOfFormList invariantsAbs "
   proof(cut_tac a1,(rule allI)+,(rule impI)+,auto) qed

 qed
lemma lemmaOnn_Try:
  assumes   a2:"s ∈ reachableSet (set (allInitSpecs N)) (rules N)"  and
  a4:"∀f.  f ∈(set invariantsAbs) ⟶  formEval f s" and a5:"\<exists> i. i\<le>N\<and>r=n_Try  i"
  shows "∃ r'. r' ∈ rulesAbs NC∧ trans_sim_on1 r r' (set invariantsAbs) s" (is "∃r'.?P1 r' ∧ ?P2 r'")
proof -
  from a5 obtain i where d0:"i\<le>N\<and>r=n_Try  i"  by blast
  have "i\<le> NC" by auto
  moreover{
       assume a1:"i\<le> NC"
        have "∃r'. ?P1 r' ∧ ?P2 r'"
        proof(rule_tac x="(n_Try i)" in exI,rule conjI)
          show  "?P1 (n_Try i) "
           by(cut_tac a1, auto)
          next
          show  "?P2 (n_Try i) "
           using lemmaOnn_Try__i local.a1 d0 by blast
        qed
       }
  ultimately show "∃r'.?P1 r' ∧ ?P2 r'"
    by satx
qed

lemma lemmaOnn_CritGt:
  assumes a1:"i>NC" and
  a2:"s ∈ reachableSet (set (allInitSpecs N)) (rules N)"  and a3:"NC<N" and
  a4:"∀f.  f ∈(set invariantsAbs) ⟶  formEval f s"
  shows "trans_sim_on1 (n_Crit i)  (n_Crit_i_3  NC) (set invariantsAbs) s" (is "trans_sim_on1 ?r ?r' (set ?F) s")
  proof(rule ruleSimCond1)
    show " formEval (pre ?r) s ⟶formEval (pre ?r') s" (is "?A ⟶?B")
    proof(rule impI)+
      assume b0:"?A"
  from a4  have tmp:"formEval (inv_30 0)  s"
            by (force simp del:inv_30_def)
        have tmp1:"formEval (inv_30 i  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf1,force+)qed
        with b0  have c0:"formEval  (conclude (inv_30 i)) s" by auto
from a4  have tmp:"formEval (inv_16 0)  s"
            by (force simp del:inv_16_def)
        have tmp1:"formEval (inv_16 i  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf1,force+)qed
        with b0  have c1:"formEval  (conclude (inv_16 i)) s" by auto

      from b1 c0 c1 show "formEval (pre ?r') s"
       by auto
     qed
   next
	show "(∀  v. v ∈  varOfSent (act  ?r') ⟶  v ∈ varOfFormList ?F ⟶ formEval (pre ?r) s ⟶
    expEval (substExpByStatement (IVar v)  (act ?r')) s = expEval (substExpByStatement (IVar v)  (act ?r)) s)"
   proof(rule allI,(rule impI)+)
      fix  v
     assume b1:"v∈ (varOfFormList invariantsAbs)"  and b2:"formEval (pre ?r) s" and b3:"v ∈varOfSent (act ?r')"

  show "expEval (substExpByStatement (IVar v)  (act ?r')) s = expEval (substExpByStatement (IVar v)  (act ?r)) s"
       apply (cut_tac  a1 b1 b2 ,auto) done
   qed
 next
   show "∀  v. v ∈  varOfSent (act ?r) ⟶  v ∈ varOfFormList ?F ⟶ v ∈  varOfSent (act ?r')" by(cut_tac a1, auto)

 next
   show "∀ v va. v ∈ varOfSent (act ?r') ⟶va∈varOfExp ( substExpByStatement (IVar v)  (act ?r'))⟶ va ∈ (varOfFormList ?F)"
     by auto
 next
   show "∀v. v ∈ varOfForm (pre (?r')) ⟶ v ∈ varOfFormList ?F" by auto
qed
lemma lemmaOnn_CritLeNc:
  assumes a1:"i\<le>NC"
  shows "trans_sim_on1 (n_Crit i) (n_Crit i) (set invariantsAbs) s" (is "trans_sim_on1 ?r ?r ?F s")
proof(rule ruleSimId)
  show  "∀v. v∈varOfForm (pre ?r) ⟶  v ∈(varOfFormList invariantsAbs) "
    by(cut_tac a1, auto)

next
  show  b1: "∀v a. a ∈ set (statement2Assigns (act ?r)) ⟶ v∈varOfExp ( substExpByStatement (IVar (fst a))  (act ?r))⟶v ∈varOfFormList invariantsAbs "
   proof(cut_tac a1,(rule allI)+,(rule impI)+,auto) qed

 qed
lemma lemmaOnn_Crit:
  assumes   a2:"s ∈ reachableSet (set (allInitSpecs N)) (rules N)"  and
  a4:"∀f.  f ∈(set invariantsAbs) ⟶  formEval f s" and a5:"\<exists> i. i\<le>N\<and>r=n_Crit  i"
  shows "∃ r'. r' ∈ rulesAbs NC∧ trans_sim_on1 r r' (set invariantsAbs) s" (is "∃r'.?P1 r' ∧ ?P2 r'")
proof -
  from a5 obtain i where d0:"i\<le>N\<and>r=n_Crit  i"  by blast
  have "i>NC|i\<le> NC" by auto
  moreover{
       assume a1:"i>NC"
        have "∃r'. ?P1 r' ∧ ?P2 r'"
        proof(rule_tac x="(n_Crit  NC)" in exI,rule conjI)
          show  "?P1 (n_Crit  NC) "
           by(cut_tac a1, auto)
          next
          show  "?P2 (n_Crit  NC) "
           using lemmaOnn_Crit_i_ local.a1 d0 by blast
        qed
       }
moreover{
       assume a1:"i\<le> NC"
        have "∃r'. ?P1 r' ∧ ?P2 r'"
        proof(rule_tac x="(n_Crit i)" in exI,rule conjI)
          show  "?P1 (n_Crit i) "
           by(cut_tac a1, auto)
          next
          show  "?P2 (n_Crit i) "
           using lemmaOnn_Crit__i local.a1 d0 by blast
        qed
       }
  ultimately show "∃r'.?P1 r' ∧ ?P2 r'"
    by satx
qed

lemma lemmaOnn_ExitLeNc:
  assumes a1:"i\<le>NC"
  shows "trans_sim_on1 (n_Exit i) (n_Exit i) (set invariantsAbs) s" (is "trans_sim_on1 ?r ?r ?F s")
proof(rule ruleSimId)
  show  "∀v. v∈varOfForm (pre ?r) ⟶  v ∈(varOfFormList invariantsAbs) "
    by(cut_tac a1, auto)

next
  show  b1: "∀v a. a ∈ set (statement2Assigns (act ?r)) ⟶ v∈varOfExp ( substExpByStatement (IVar (fst a))  (act ?r))⟶v ∈varOfFormList invariantsAbs "
   proof(cut_tac a1,(rule allI)+,(rule impI)+,auto) qed

 qed
lemma lemmaOnn_Exit:
  assumes   a2:"s ∈ reachableSet (set (allInitSpecs N)) (rules N)"  and
  a4:"∀f.  f ∈(set invariantsAbs) ⟶  formEval f s" and a5:"\<exists> i. i\<le>N\<and>r=n_Exit  i"
  shows "∃ r'. r' ∈ rulesAbs NC∧ trans_sim_on1 r r' (set invariantsAbs) s" (is "∃r'.?P1 r' ∧ ?P2 r'")
proof -
  from a5 obtain i where d0:"i\<le>N\<and>r=n_Exit  i"  by blast
  have "i\<le> NC" by auto
  moreover{
       assume a1:"i\<le> NC"
        have "∃r'. ?P1 r' ∧ ?P2 r'"
        proof(rule_tac x="(n_Exit i)" in exI,rule conjI)
          show  "?P1 (n_Exit i) "
           by(cut_tac a1, auto)
          next
          show  "?P2 (n_Exit i) "
           using lemmaOnn_Exit__i local.a1 d0 by blast
        qed
       }
  ultimately show "∃r'.?P1 r' ∧ ?P2 r'"
    by satx
qed

lemma lemmaOnn_IdleGt:
  assumes a1:"i>NC" and
  a2:"s ∈ reachableSet (set (allInitSpecs N)) (rules N)"  and a3:"NC<N" and
  a4:"∀f.  f ∈(set invariantsAbs) ⟶  formEval f s"
  shows "trans_sim_on1 (n_Idle i)  (n_Idle_i_3  NC) (set invariantsAbs) s" (is "trans_sim_on1 ?r ?r' (set ?F) s")
  proof(rule ruleSimCond1)
    show " formEval (pre ?r) s ⟶formEval (pre ?r') s" (is "?A ⟶?B")
    proof(rule impI)+
      assume b0:"?A"
  from a4  have tmp:"formEval (inv_34 0 1)  s"
            by (force simp del:inv_34_def)
        have tmp1:"formEval (inv_34 i 0  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c0:"formEval  (conclude (inv_34 i 0)) s" by auto
from a4  have tmp:"formEval (inv_34 0 1)  s"
            by (force simp del:inv_34_def)
        have tmp1:"formEval (inv_34 i 1  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c1:"formEval  (conclude (inv_34 i 1)) s" by auto
from a4  have tmp:"formEval (inv_33 0)  s"
            by (force simp del:inv_33_def)
        have tmp1:"formEval (inv_33 i  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf1,force+)qed
        with b0  have c2:"formEval  (conclude (inv_33 i)) s" by auto
from a4  have tmp:"formEval (inv_32 0 1)  s"
            by (force simp del:inv_32_def)
        have tmp1:"formEval (inv_32 i 0  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c3:"formEval  (conclude (inv_32 i 0)) s" by auto
from a4  have tmp:"formEval (inv_32 0 1)  s"
            by (force simp del:inv_32_def)
        have tmp1:"formEval (inv_32 i 1  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c4:"formEval  (conclude (inv_32 i 1)) s" by auto
from a4  have tmp:"formEval (inv_26 0 1)  s"
            by (force simp del:inv_26_def)
        have tmp1:"formEval (inv_26 i 0  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c5:"formEval  (conclude (inv_26 i 0)) s" by auto
from a4  have tmp:"formEval (inv_26 0 1)  s"
            by (force simp del:inv_26_def)
        have tmp1:"formEval (inv_26 i 1  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c6:"formEval  (conclude (inv_26 i 1)) s" by auto
from a4  have tmp:"formEval (inv_22 0)  s"
            by (force simp del:inv_22_def)
        have tmp1:"formEval (inv_22 i  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf1,force+)qed
        with b0  have c7:"formEval  (conclude (inv_22 i)) s" by auto
from a4  have tmp:"formEval (inv_15 0 1)  s"
            by (force simp del:inv_15_def)
        have tmp1:"formEval (inv_15 i 0  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c8:"formEval  (conclude (inv_15 i 0)) s" by auto
from a4  have tmp:"formEval (inv_15 0 1)  s"
            by (force simp del:inv_15_def)
        have tmp1:"formEval (inv_15 i 1  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c9:"formEval  (conclude (inv_15 i 1)) s" by auto
from a4  have tmp:"formEval (inv_11 0 1)  s"
            by (force simp del:inv_11_def)
        have tmp1:"formEval (inv_11 i 0  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c10:"formEval  (conclude (inv_11 i 0)) s" by auto
from a4  have tmp:"formEval (inv_11 0 1)  s"
            by (force simp del:inv_11_def)
        have tmp1:"formEval (inv_11 i 1  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c11:"formEval  (conclude (inv_11 i 1)) s" by auto
from a4  have tmp:"formEval (inv_4 0 1)  s"
            by (force simp del:inv_4_def)
        have tmp1:"formEval (inv_4 i 0  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c12:"formEval  (conclude (inv_4 i 0)) s" by auto
from a4  have tmp:"formEval (inv_4 0 1)  s"
            by (force simp del:inv_4_def)
        have tmp1:"formEval (inv_4 i 1  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf2,force+)qed
        with b0  have c13:"formEval  (conclude (inv_4 i 1)) s" by auto
from a4  have tmp:"formEval (inv_1 0)  s"
            by (force simp del:inv_1_def)
        have tmp1:"formEval (inv_1 i  ) s"
        proof(cut_tac a1 a2 a3 tmp,rule axiomOnf1,force+)qed
        with b0  have c14:"formEval  (conclude (inv_1 i)) s" by auto

      from b1 c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 show "formEval (pre ?r') s"
       by auto
     qed
   next
	show "(∀  v. v ∈  varOfSent (act  ?r') ⟶  v ∈ varOfFormList ?F ⟶ formEval (pre ?r) s ⟶
    expEval (substExpByStatement (IVar v)  (act ?r')) s = expEval (substExpByStatement (IVar v)  (act ?r)) s)"
   proof(rule allI,(rule impI)+)
      fix  v
     assume b1:"v∈ (varOfFormList invariantsAbs)"  and b2:"formEval (pre ?r) s" and b3:"v ∈varOfSent (act ?r')"

  show "expEval (substExpByStatement (IVar v)  (act ?r')) s = expEval (substExpByStatement (IVar v)  (act ?r)) s"
       apply (cut_tac  a1 b1 b2 ,auto) done
   qed
 next
   show "∀  v. v ∈  varOfSent (act ?r) ⟶  v ∈ varOfFormList ?F ⟶ v ∈  varOfSent (act ?r')" by(cut_tac a1, auto)

 next
   show "∀ v va. v ∈ varOfSent (act ?r') ⟶va∈varOfExp ( substExpByStatement (IVar v)  (act ?r'))⟶ va ∈ (varOfFormList ?F)"
     by auto
 next
   show "∀v. v ∈ varOfForm (pre (?r')) ⟶ v ∈ varOfFormList ?F" by auto
qed
lemma lemmaOnn_IdleLeNc:
  assumes a1:"i\<le>NC"
  shows "trans_sim_on1 (n_Idle i) (n_Idle i) (set invariantsAbs) s" (is "trans_sim_on1 ?r ?r ?F s")
proof(rule ruleSimId)
  show  "∀v. v∈varOfForm (pre ?r) ⟶  v ∈(varOfFormList invariantsAbs) "
    by(cut_tac a1, auto)

next
  show  b1: "∀v a. a ∈ set (statement2Assigns (act ?r)) ⟶ v∈varOfExp ( substExpByStatement (IVar (fst a))  (act ?r))⟶v ∈varOfFormList invariantsAbs "
   proof(cut_tac a1,(rule allI)+,(rule impI)+,auto) qed

 qed
lemma lemmaOnn_Idle:
  assumes   a2:"s ∈ reachableSet (set (allInitSpecs N)) (rules N)"  and
  a4:"∀f.  f ∈(set invariantsAbs) ⟶  formEval f s" and a5:"\<exists> i. i\<le>N\<and>r=n_Idle  i"
  shows "∃ r'. r' ∈ rulesAbs NC∧ trans_sim_on1 r r' (set invariantsAbs) s" (is "∃r'.?P1 r' ∧ ?P2 r'")
proof -
  from a5 obtain i where d0:"i\<le>N\<and>r=n_Idle  i"  by blast
  have "i>NC|i\<le> NC" by auto
  moreover{
       assume a1:"i>NC"
        have "∃r'. ?P1 r' ∧ ?P2 r'"
        proof(rule_tac x="(n_Idle  NC)" in exI,rule conjI)
          show  "?P1 (n_Idle  NC) "
           by(cut_tac a1, auto)
          next
          show  "?P2 (n_Idle  NC) "
           using lemmaOnn_Idle_i_ local.a1 d0 by blast
        qed
       }
moreover{
       assume a1:"i\<le> NC"
        have "∃r'. ?P1 r' ∧ ?P2 r'"
        proof(rule_tac x="(n_Idle i)" in exI,rule conjI)
          show  "?P1 (n_Idle i) "
           by(cut_tac a1, auto)
          next
          show  "?P2 (n_Idle i) "
           using lemmaOnn_Idle__i local.a1 d0 by blast
        qed
       }
  ultimately show "∃r'.?P1 r' ∧ ?P2 r'"
    by satx
qed

end