theory flash29Bra  imports flash29Rev

  begin
lemma onInv29:

   assumes  a1:"iInv1 \<le> N" and

     b1:"r \<in> rules N" and b2:"invf=inv29  iInv1 "
   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 (inv29  iInv1 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX1VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_GetXVsInv29 )
          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 (inv29  iInv1 ) (NI_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_ReplaceVsInv29 )
          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 (inv29  iInv1 ) (NI_ShWb N ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_ShWbVsInv29 )
          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 (inv29  iInv1 ) (PI_Local_GetX_GetX2 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_GetX2VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_PutXAcksDone ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Local_PutXAcksDoneVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX7VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_Get_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Nak2VsInv29 )
          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 (inv29  iInv1 ) (NI_ReplaceHomeShrVld ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_ReplaceHomeShrVldVsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_Put  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_PutVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX5VsInv29 )
          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 (inv29  iInv1 ) (NI_Wb ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_WbVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_Get_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_GetVsInv29 )
          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 (inv29  iInv1 ) (PI_Local_Replace ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_ReplaceVsInv29 )
          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 (inv29  iInv1 ) (NI_ReplaceShrVld  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_ReplaceShrVldVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX8VsInv29 )
          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 (inv29  iInv1 ) (NI_InvAck_2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvAck_2VsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Nak2VsInv29 )
          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 (inv29  iInv1 ) (PI_Remote_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_ReplaceVsInv29 )
          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 (inv29  iInv1 ) (NI_Nak_Home ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Nak_HomeVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_Get_Put2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Put2VsInv29 )
          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 (inv29  iInv1 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvAck_1VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX11VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX6VsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Put2VsInv29 )
          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 (inv29  iInv1 ) (PI_Local_Get_Put ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_Get_PutVsInv29 )
          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 (inv29  iInv1 ) (PI_Local_GetX_PutX1 N ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX1VsInv29 )
          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 (inv29  iInv1 ) (NI_InvAck_1_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvAck_1_HomeVsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Nak1VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Nak1VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_Nak2VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX10_homeVsInv29 )
          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 (inv29  iInv1 ) (PI_Remote_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_GetVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_Nak3VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX10VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX2VsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_Get_Put1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_Get_Put1VsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_PutXVsInv29 )
          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 (inv29  iInv1 ) (Store  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis StoreVsInv29 )
          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 (inv29  iInv1 ) (NI_FAck ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_FAckVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX3VsInv29 )
          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 (inv29  iInv1 ) (PI_Local_GetX_PutX3 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX3VsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_PutXVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX8_homeVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Put1VsInv29 )
          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 (inv29  iInv1 ) (PI_Local_GetX_GetX1 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_GetX1VsInv29 )
          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 (inv29  iInv1 ) (StoreHome ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis StoreHomeVsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_NakVsInv29 )
          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 (inv29  iInv1 ) (NI_Inv  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_InvVsInv29 )
          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 (inv29  iInv1 ) (PI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_PutXVsInv29 )
          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 (inv29  iInv1 ) (PI_Local_GetX_PutX4 ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX4VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX4VsInv29 )
          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 (inv29  iInv1 ) (NI_Nak  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_NakVsInv29 )
          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 (inv29  iInv1 ) (PI_Local_GetX_PutX2 N ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_GetX_PutX2VsInv29 )
          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 (inv29  iInv1 ) (NI_Local_Put ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Local_PutVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_Nak1VsInv29 )
          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 (inv29  iInv1 ) (NI_Nak_Clear ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_Nak_ClearVsInv29 )
          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 (inv29  iInv1 ) (PI_Local_PutX ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_PutXVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_Get_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Nak3VsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_Nak_HomeVsInv29 )
          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 (inv29  iInv1 ) (PI_Local_Get_Get ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis PI_Local_Get_GetVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_GetX_PutX9VsInv29 )
          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 (inv29  iInv1 ) (PI_Remote_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis PI_Remote_GetXVsInv29 )
          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 (inv29  iInv1 ) (NI_ReplaceHome ) (invariants N) "
            apply(cut_tac   a1   b2 c2 )
            by (metis NI_ReplaceHomeVsInv29 )
          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 (inv29  iInv1 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Remote_GetX_PutX_HomeVsInv29 )
          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 (inv29  iInv1 ) (NI_Local_Get_Put3  iRule1 ) (invariants N) "
            apply(cut_tac  c2   a1 )
            by (metis NI_Local_Get_Put3VsInv29 )
          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 EdmondsKarp_Time
  imports EdmondsKarp_Impl
begin

lemma "(\<lambda>x::nat. real ((3 ))) \<in> \<Theta>(\<lambda>(x). real 1)"
  by auto2

lemma "(\<lambda>x. real ((32 ))) \<in> \<Theta>\<^sub>2(\<lambda>(V::nat,E::nat). 1)"
  apply (subst surjective_pairing) by auto2

lemma "(\<lambda>x. real ((rbt_insert_logN 1 ))) \<in> \<Theta>\<^sub>2(\<lambda>(V::nat,E::nat). 1)"
  apply (subst surjective_pairing) by auto2

lemma edka_runt: "edka_cost \<in> \<Theta>\<^sub>2(\<lambda>(V::nat,E::nat). V * E * V + V * E * E  )"
  apply (subst surjective_pairing)
  unfolding edka_cost_simp by auto2

lemma final_running_time: "edka_cost \<in> \<Theta>\<^sub>2(\<lambda>(V::nat,E::nat). (V * E) * (V + E) )"
proof -
  have *:  "\<And>E V::nat. (V * E) * (V + E) = V * E * V + V * E * E"
    by (simp add: distrib_left)
  show ?thesis unfolding * using edka_runt
    by simp
qed

end


(*  Title:      HOL/Datatype_Examples/Lift_BNF.thy
    Author:     Dmitriy Traytel, ETH Zürich
    Copyright   2015

Demonstration of the "lift_bnf" command.
*)

section \<open>Demonstration of the \textbf{lift_bnf} Command\<close>

theory Lift_BNF
imports MainRLT
begin

subsection \<open>Lifting \textbf{typedef}s\<close>

typedef 'a nonempty_list = "{xs :: 'a list. xs \<noteq> []}"
  by blast
setup_lifting type_definition_nonempty_list

lift_bnf (no_warn_wits) (neset: 'a) nonempty_list
  for map: nemap rel: nerel
  by auto

typedef ('a :: finite, 'b) fin_nonempty_list = "{(xs :: 'a set, ys :: 'b list). ys \<noteq> []}"
  by blast
setup_lifting type_definition_fin_nonempty_list

lift_bnf (no_warn_wits) (dead 'a :: finite, 'b) fin_nonempty_list
  [wits: "\<lambda>b. ({} :: 'a :: finite set, [b :: 'b])"]
  by auto

datatype 'a tree = Leaf | Node 'a "'a tree nonempty_list"

record 'a point =
  xCoord :: 'a
  yCoord :: 'a

copy_bnf (no_warn_transfer) ('a, 's) point_ext

typedef 'a it = "UNIV :: 'a set"
  by blast

setup_lifting type_definition_it

copy_bnf (plugins del: size) 'a it

typedef ('a, 'b) T_prod = "UNIV :: ('a \<times> 'b) set"
  by blast

setup_lifting type_definition_T_prod

copy_bnf ('a, 'b) T_prod

typedef ('a, 'b, 'c) T_func = "UNIV :: ('a \<Rightarrow> 'b * 'c) set"
  by blast

setup_lifting type_definition_T_func

copy_bnf ('a, 'b, 'c) T_func

typedef ('a, 'b) sum_copy = "UNIV :: ('a + 'b) set"
  by blast

setup_lifting type_definition_sum_copy

copy_bnf ('a, 'b) sum_copy

typedef ('a, 'b) T_sum = "{Inl x | x. True} :: ('a + 'b) set"
  by blast

lift_bnf (no_warn_wits, no_warn_transfer) ('a, 'b) T_sum [wits: "Inl :: 'a \<Rightarrow> 'a + 'b"]
  by (force simp: map_sum_def sum_set_defs split: sum.splits)+

typedef ('key, 'value) alist = "{xs :: ('key \<times> 'value) list. (distinct \<circ> map fst) xs}"
  morphisms impl_of Alist
proof
  show "[] \<in> {xs. (distinct o map fst) xs}"
    by simp
qed

setup_lifting type_definition_alist

lift_bnf (dead 'k, 'v) alist [wits: "Nil :: ('k \<times> 'v) list"]
  by auto

typedef 'a myopt = "{X :: 'a set. finite X \<and> card X \<le> 1}" by (rule exI[of _ "{}"]) auto
lemma myopt_type_def: "type_definition
  (\<lambda>X. if card (Rep_myopt X) = 1 then Some (the_elem (Rep_myopt X)) else None)
  (\<lambda>x. Abs_myopt (case x of Some x \<Rightarrow> {x} | _ \<Rightarrow> {}))
  (UNIV :: 'a option set)"
  apply unfold_locales
    apply (auto simp: Abs_myopt_inverse dest!: card_eq_SucD split: option.splits)
   apply (metis Rep_myopt_inverse)
  apply (metis One_nat_def Rep_myopt Rep_myopt_inverse Suc_le_mono card_0_eq le0 le_antisym mem_Collect_eq nat.exhaust)
  done

copy_bnf (no_warn_transfer) 'a myopt via myopt_type_def

typedef ('k, 'v) fmap = "{M :: ('k \<rightharpoonup> 'v). finite (dom M)}"
  by (rule exI[of _ Map.empty]) simp_all
setup_lifting type_definition_fmap

lift_bnf (dead 'k, 'v) fmap [wits: "Map.empty :: 'k \<Rightarrow> 'v option"]
  by auto

typedef ('a, 'b) tuple_dead = "UNIV :: ('a \<times> 'b) set" ..
typedef ('a, 'b) tuple_dead1 = "UNIV :: ('a \<times> 'b) set" ..
typedef ('a, 'b) tuple_dead2 = "UNIV :: ('a \<times> 'b) set" ..
typedef ('a, 'b, 'c) triple_dead = "UNIV :: ('a \<times> 'b \<times> 'c) set" ..
typedef ('a, 'b, 'c) triple_dead1 = "UNIV :: ('a \<times> 'b \<times> 'c) set" ..
typedef ('a, 'b, 'c) triple_dead2 = "UNIV :: ('a \<times> 'b \<times> 'c) set" ..
typedef ('a, 'b, 'c) triple_dead3 = "UNIV :: ('a \<times> 'b \<times> 'c) set" ..
typedef ('a, 'b, 'c) triple_dead12 = "UNIV :: ('a \<times> 'b \<times> 'c) set" ..
typedef ('a, 'b, 'c) triple_dead13 = "UNIV :: ('a \<times> 'b \<times> 'c) set" ..
typedef ('a, 'b, 'c) triple_dead23 = "UNIV :: ('a \<times> 'b \<times> 'c) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead =    "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead1 =   "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead2 =   "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead3 =   "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead4 =   "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead12 =  "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead13 =  "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead14 =  "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead23 =  "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead24 =  "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead34 =  "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead123 = "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead124 = "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead134 = "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
typedef ('a, 'b, 'c, 'd) quadruple_dead234 = "UNIV :: ('a \<times> 'b \<times> 'c \<times> 'd) set" ..
setup_lifting type_definition_tuple_dead
setup_lifting type_definition_tuple_dead1
setup_lifting type_definition_tuple_dead2
setup_lifting type_definition_triple_dead
setup_lifting type_definition_triple_dead1
setup_lifting type_definition_triple_dead2
setup_lifting type_definition_triple_dead3
setup_lifting type_definition_triple_dead12
setup_lifting type_definition_triple_dead13
setup_lifting type_definition_triple_dead23
setup_lifting type_definition_quadruple_dead
setup_lifting type_definition_quadruple_dead1
setup_lifting type_definition_quadruple_dead2
setup_lifting type_definition_quadruple_dead3
setup_lifting type_definition_quadruple_dead4
setup_lifting type_definition_quadruple_dead12
setup_lifting type_definition_quadruple_dead13
setup_lifting type_definition_quadruple_dead14
setup_lifting type_definition_quadruple_dead23
setup_lifting type_definition_quadruple_dead24
setup_lifting type_definition_quadruple_dead34
setup_lifting type_definition_quadruple_dead123
setup_lifting type_definition_quadruple_dead124
setup_lifting type_definition_quadruple_dead134
setup_lifting type_definition_quadruple_dead234

lift_bnf (no_warn_wits) (     'a,      'b) tuple_dead by auto
lift_bnf (no_warn_wits) (dead 'a,      'b) tuple_dead1 by auto
lift_bnf (no_warn_wits) (     'a, dead 'b) tuple_dead2 by auto
lift_bnf (no_warn_wits) (     'a,      'b,      'c) triple_dead by auto
lift_bnf (no_warn_wits) (dead 'a,      'b,      'c) triple_dead1 by auto
lift_bnf (no_warn_wits) (     'a, dead 'b,      'c) triple_dead2 by auto
lift_bnf (no_warn_wits) (     'a,      'b, dead 'c) triple_dead3 by auto
lift_bnf (no_warn_wits) (dead 'a, dead 'b,      'c) triple_dead12 by auto
lift_bnf (no_warn_wits) (dead 'a,      'b, dead 'c) triple_dead13 by auto
lift_bnf (no_warn_wits) (     'a, dead 'b, dead 'c) triple_dead23 by auto
lift_bnf (no_warn_wits) (     'a,      'b,      'c,      'd) quadruple_dead  by auto
lift_bnf (no_warn_wits) (dead 'a,      'b,      'c,      'd) quadruple_dead1 by auto
lift_bnf (no_warn_wits) (     'a, dead 'b,      'c,      'd) quadruple_dead2 by auto
lift_bnf (no_warn_wits) (     'a,      'b, dead 'c,      'd) quadruple_dead3 by auto
lift_bnf (no_warn_wits) (     'a,      'b,      'c, dead 'd) quadruple_dead4 by auto
lift_bnf (no_warn_wits) (dead 'a, dead 'b,      'c,      'd) quadruple_dead12  by auto
lift_bnf (no_warn_wits) (dead 'a,      'b, dead 'c,      'd) quadruple_dead13  by auto
lift_bnf (no_warn_wits) (dead 'a,      'b,      'c, dead 'd) quadruple_dead14  by auto
lift_bnf (no_warn_wits) (     'a, dead 'b, dead 'c,      'd) quadruple_dead23  by auto
lift_bnf (no_warn_wits) (     'a, dead 'b,      'c, dead 'd) quadruple_dead24  by auto
lift_bnf (no_warn_wits) (     'a,      'b, dead 'c, dead 'd) quadruple_dead34  by auto
lift_bnf (no_warn_wits) (dead 'a, dead 'b, dead 'c,      'd) quadruple_dead123 by auto
lift_bnf (no_warn_wits) (dead 'a, dead 'b,      'c, dead 'd) quadruple_dead124 by auto
lift_bnf (no_warn_wits) (dead 'a,      'b, dead 'c, dead 'd) quadruple_dead134 by auto
lift_bnf (no_warn_wits) (     'a, dead 'b, dead 'c, dead 'd) quadruple_dead234 by auto

subsection \<open>Lifting \textbf{quotient_type}s\<close>

quotient_type 'a cpy_list = "'a list" / "(=)"
  by (rule identity_equivp)

lift_bnf 'a cpy_list
  by (auto intro: list_all2_trans)

quotient_type ('a, 'b) funk = "('a \<Rightarrow> 'b)" / "\<lambda>f g. \<forall>a. f a = g a"
  unfolding equivp_def by metis

lemma funk_closure: "{(x, x'). \<forall>a. x a = x' a} `` {x. range x \<subseteq> A} = {x. range x \<subseteq> A}"
  by auto

lift_bnf (dead 'a, 'b) funk
  unfolding funk_closure rel_fun_def by (auto 0 10 split: if_splits)

lemma assumes "equivp REL"
  shows "REL OO REL OO R = REL OO R"
  using equivp_transp[OF assms] equivp_reflp[OF assms]
  by blast

inductive ignore_Inl :: "'a + 'a \<Rightarrow> 'a + 'a \<Rightarrow> bool" where
  "ignore_Inl (Inl x) (Inl y)"
| "ignore_Inl (Inr x) (Inr x)"

inductive_simps [simp]:
  "ignore_Inl (Inl x) y"
  "ignore_Inl (Inr x') y"
  "ignore_Inl y (Inl x)"
  "ignore_Inl y (Inr x')"

quotient_type 'a opt = "'a + 'a" / ignore_Inl
  apply(auto intro!: equivpI simp add: reflp_def symp_def transp_def elim!: ignore_Inl.cases)
  subgoal for x by(cases x) simp_all.

lemma ignore_Inl_map_respect:
  "(rel_fun (=) (rel_fun ignore_Inl ignore_Inl)) (\<lambda>f. map_sum f f) (\<lambda>f. map_sum f f)"
  by(auto simp add: rel_fun_def elim: ignore_Inl.cases)

lemma ignore_Inl_pos_distr:
  "A OO B \<noteq> bot \<Longrightarrow> ignore_Inl OO rel_sum A A OO ignore_Inl OO rel_sum B B OO ignore_Inl \<le>
   ignore_Inl OO rel_sum (A OO B) (A OO B) OO ignore_Inl"
  by(fastforce elim!: ignore_Inl.cases simp add: relcompp_apply fun_eq_iff intro: exI[where x="Inl _"])

lemma ignore_Inl_Inter:
  "\<lbrakk> S \<noteq> {}; \<Inter>S \<noteq> {} \<rbrakk> \<Longrightarrow> (\<Inter>A\<in>S. {(x, y). ignore_Inl x y} `` {x. Basic_BNFs.setl x \<union> Basic_BNFs.setr x \<subseteq> A}) \<subseteq> {(x, y). ignore_Inl x y} `` (\<Inter>A\<in>S. {x. Basic_BNFs.setl x \<union> Basic_BNFs.setr x \<subseteq> A})"
  apply(clarsimp; safe; clarsimp)
  subgoal for x A x'
    apply(cases x)
     apply(drule bspec[where x="Inl x'"])
      apply clarsimp
     apply simp
    apply clarsimp
    apply(drule bspec[where x="Inr _"])
     apply simp
    apply simp
    done
  done

lift_bnf 'a opt [wits: "(Inl undefined :: 'a + 'a)"]
   apply(auto simp add: rel_fun_def elim: ignore_Inl.cases)[]
  apply(fastforce simp add: rel_sum.simps)
  subgoal for Ss
    using ignore_Inl_Inter[unfolded Plus_def, of Ss]
    by blast
  apply (auto simp: Ball_def image_iff sum_set_defs elim: ignore_Inl.cases split: sum.splits) []
  done

end


theory Printing
  imports "02Typed/Typechecking" "03Debruijn/NameRemoval" "05Closure/ClosureConversion"
    "06TreeCode/TreeCodeConversion" "07TailCall/TailCallOptimization" "08FlatCode/CodeFlattening"
    "09HeapMemory/HeapConversion" "10ChainedEnvironment/Chaining" "11FlatMemory/MemoryFlattening"
    "13AssemblyCode/Assemble" "14MachineCode/Disassemble"
begin

datatype print = Number nat | Fun

primrec print_nexpr :: "nexpr \<Rightarrow> print" where
  "print_nexpr (NVar x) = undefined"
| "print_nexpr (NConst k) = Number k"
| "print_nexpr (NLam x e) = Fun"
| "print_nexpr (NApp e\<^sub>1 e\<^sub>2) = undefined"

primrec print_texpr :: "texpr \<Rightarrow> print" where
  "print_texpr (texpr.TVar x) = undefined"
| "print_texpr (texpr.TConst k) = Number k"
| "print_texpr (texpr.TLam x t e) = Fun"
| "print_texpr (texpr.TApp e\<^sub>1 e\<^sub>2) = undefined"

primrec print_dexpr :: "dexpr \<Rightarrow> print" where
  "print_dexpr (DVar x) = undefined"
| "print_dexpr (DConst k) = Number k"
| "print_dexpr (DLam t e) = Fun"
| "print_dexpr (DApp e\<^sub>1 e\<^sub>2) = undefined"

primrec print_closure :: "closure \<Rightarrow> print" where
  "print_closure (CConst k) = Number k"
| "print_closure (CLam t cs e) = Fun"

primrec print_tclosure :: "tclosure \<Rightarrow> print" where
  "print_tclosure (TConst k) = Number k"
| "print_tclosure (TLam cs cd) = Fun"

primrec print_tco_closure :: "tco_closure \<Rightarrow> print" where
  "print_tco_closure (TCOConst k) = Number k"
| "print_tco_closure (TCOLam cs cd r) = Fun"

primrec print_bclosure :: "bclosure \<Rightarrow> print" where
  "print_bclosure (BConst k) = Number k"
| "print_bclosure (BLam cs pc) = Fun"

primrec print_hclosure :: "hclosure \<Rightarrow> print" where
  "print_hclosure (HConst k) = Number k"
| "print_hclosure (HLam cs pc) = Fun"

primrec print_ceclosure :: "ceclosure \<Rightarrow> print" where
  "print_ceclosure (CEConst k) = Number k"
| "print_ceclosure (CELam cs pc) = Fun"

fun print_uval :: "(nat \<Rightarrow> nat) \<Rightarrow> nat \<Rightarrow> print" where
  "print_uval h p = (case h p of
      0 \<Rightarrow> Fun
    | Suc x \<Rightarrow> Number (h (Suc p)))"

fun print_mval :: "(nat \<Rightarrow> nat) \<Rightarrow> nat \<Rightarrow> print" where
  "print_mval m p = (case m p of
      0 \<Rightarrow> Fun
    | Suc x \<Rightarrow> Number (m (4 + p)))"

lemma [simp]: "valt e \<Longrightarrow> print_dexpr (convert e) = print_texpr e"
  by (induction e) (simp_all add: convert_def)

lemma print_eqiv_declosure [simp]: "print_closure c = print_dexpr (declosure c)"
proof (induction c)
  case (CLam t cs e)
  thus ?case by (induction cs arbitrary: e) simp_all
qed simp_all

lemma [simp]: "print_tco_closure (tco_val c) = print_tclosure c"
  by (induction c) simp_all

lemma [simp]: "print_tclosure (encode_closure c) = print_closure c"
  by (induction c) (simp_all del: print_eqiv_declosure)

lemma [simp]: "print_bclosure c = print_tco_closure (unflatten_closure cd c)"
  by (induction c) simp_all

lemma [simp]: "print_hclosure (hlookup h x) = print_bclosure (unheap_closure h x)"
  by (cases "hlookup h x") simp_all

lemma print_ce [simp]: "hcontains h x \<Longrightarrow>
    print_ceclosure (hlookup h x) = print_hclosure (hlookup (unchain_heap h env) x)"
  by (cases "hlookup h x") simp_all

lemma [simp]: "print_ceclosure (flatten_closure' c) = print_ceclosure c"
  by (induction c) simp_all

lemma print_a [simp]: "3 dvd x \<Longrightarrow> Suc x < hp \<Longrightarrow>
  print_uval (pseudoreg_map \<circ> assm_hp cd h hp) x = print_uval h x"
proof (induction "h x")
  case (Suc nat)
  hence "h x = Suc nat" by simp
  moreover from Suc have "3 dvd x" and "Suc x < hp" by simp_all
  moreover from Suc have "Suc x mod 3 = 1" by presburger
  ultimately show ?case by (simp add: assm_hp_lemma1 assm_hp_lemma2 split: nat.splits)
qed (simp_all add: assemble_heap_def)

lemma print_u [simp]: "print_uval h p = print_ceclosure (get_closure (H h hp) p)"
  by (cases "h p") simp_all

lemma print_m [simp]: "unmap_mem' p = (a, b) \<Longrightarrow>
    print_mval (unmap_mem mem) p = print_uval (pseudoreg_map \<circ> mem a) b"
  by (induction p rule: unmap_mem'.induct)
     (auto simp add: unmap_mem_def numeral_def split: nat.splits)

end


(*<*)
(*
   Title: Gateway_proof.thy  (Gateway: Verification)
   Author: Maria Spichkova <maria.spichkova at rmit.edu.au>, 2013
*)
(*>*)

(* header {*Gateway: Verification *} *)

theory Gateway_proof
imports Gateway_proof_aux
begin

subsection \<open>Properties of the Gateway\<close>

lemma Gateway_L1:
  assumes h1:"Gateway req dt a stop lose d ack i vc"
      and h2:"msg (Suc 0) req"
      and h3:"msg (Suc 0) a"
      and h4:"msg (Suc 0) stop"
      and h5:"ts lose"
      and h6:"ack t = [init_state]"
      and h7:"req (Suc t) = [init]"
      and h8:"lose (Suc t) = [False]"
      and h9:"lose (Suc (Suc t)) = [False]"
  shows "ack (Suc (Suc t)) = [connection_ok]"
proof -
  from h1 obtain i1 i2 x y
    where a1:"Sample req dt x stop lose ack i1 vc"
      and a2:"Delay y i1 d x i2"
      and a3:"Loss lose a i2 y i"
    by (simp only: Gateway_def, auto)
  from a2 and a3 and h3 have sg1:"msg (Suc 0) x"
    by (simp add: Loss_Delay_msg_a)
  from a1 and h2 and h4 and sg1 obtain st buffer where a4:
    "tiTable_SampleT req x stop lose
        (fin_inf_append [init_state] st) (fin_inf_append [[]] buffer) ack
         i1 vc st"
     by (simp add: Sample_def Sample_L_def, auto)
  from a4 and h5 and sg1 and h4 have sg2:"st t =  hd (ack t)"
    by (simp add: tiTable_ack_st_hd)
  from h6 and sg1 and sg2 and h4 have sg3:
   "(fin_inf_append [init_state] st) (Suc t) = init_state"
    by (simp add: correct_fin_inf_append1)
  from a4 and h7 and sg3 have sg4:"st (Suc t) = call"
    by (simp add: tiTable_SampleT_def)
  from sg4 have sg5:"(fin_inf_append [init_state] st) (Suc (Suc t)) = call"
    by (simp add: correct_fin_inf_append1)
  from a4 and sg5 and assms show ?thesis
    by (simp add: tiTable_SampleT_def)
qed

lemma Gateway_L2:
  assumes h1:"Gateway req dt a stop lose d ack i vc"
      and h2:"msg (Suc 0) req"
      and h3:"msg (Suc 0) a"
      and h4:"msg (Suc 0) stop"
      and h5:"ts lose"
      and h6:"ack t = [connection_ok]"
      and h7:"req (Suc t) = [send]"
      and h8:"\<forall>k\<le>Suc d. lose (t + k) = [False]"
  shows "i (Suc (t + d))  = inf_last_ti dt t"
proof -
  from h1 obtain i1 i2 x y
    where a1:"Sample req dt x stop lose ack i1 vc"
      and a2:"Delay y i1 d x i2"
      and a3:"Loss lose a i2 y i"
    by (simp only: Gateway_def, auto)
  from a2 and a3 and h3 have sg1:"msg (Suc 0) x"
    by (simp add: Loss_Delay_msg_a)
  from a1 and h2 and h4 and sg1 obtain st buffer where a4:
    "Sample_L req dt x stop lose (fin_inf_append [init_state] st)
         (fin_inf_append [[]] buffer) ack i1 vc st buffer"
    by (simp add: Sample_def, auto)
  from a4 have sg2:"buffer t = inf_last_ti dt t"
    by (simp add: Sample_L_buffer)
  from assms and a1 and a4 and sg1 and sg2 have sg3:"i1 (Suc t) =  buffer t"
    by (simp add: Sample_L_i1_buffer)
  from a2 and sg1 have sg4:"i2 ((Suc t) + d)  =  i1 (Suc t)"
    by (simp add: Delay_def)
  from a3 and h8 have sg5:"i ((Suc t) + d)  =  i2 ((Suc t) + d)"
    by (simp add: Loss_def, auto)
  from sg5 and sg4 and sg3 and sg2 show ?thesis by simp
qed

lemma Gateway_L3:
  assumes h1:"Gateway req dt a stop lose d ack i vc"
      and h2:"msg (Suc 0) req"
      and h3:"msg (Suc 0) a"
      and h4:"msg (Suc 0) stop"
      and h5:"ts lose"
      and h6:"ack t = [connection_ok]"
      and h7:"req (Suc t) = [send]"
      and h8:"\<forall>k\<le>Suc d. lose (t + k) = [False]"
  shows "ack (Suc t) = [sending_data]"
proof -
  from h1 obtain i1 i2 x y
    where a1:"Sample req dt x stop lose ack i1 vc"
      and a2:"Delay y i1 d x i2"
      and a3:"Loss lose a i2 y i"
    by (simp only: Gateway_def, auto)
  from a2 and a3 and h3 have sg1:"msg (Suc 0) x"
    by (simp add: Loss_Delay_msg_a)
  from a1 and h2 and h4 and sg1 obtain st buffer where a4:
    "tiTable_SampleT req x stop lose
        (fin_inf_append [init_state] st) (fin_inf_append [[]] buffer) ack
         i1 vc st"
     by (simp add: Sample_def Sample_L_def, auto)
  from a4 and h5 and sg1 and h4 have sg2:"st t =  hd (ack t)"
    by (simp add: tiTable_ack_st_hd)
  from sg2 and h6 have sg3:"(fin_inf_append [init_state] st) (Suc t) = connection_ok"
    by (simp add: correct_fin_inf_append1)
  from h8 have sg4:"lose (Suc t) = [False]" by auto
  from a4 and sg3 and sg4 and h7 have sg5:"st (Suc t) = sending_data"
    by (simp add: tiTable_SampleT_def)
  from a4 and h2 and sg1 and h4 and h5 have sg6:"ack (Suc t) = [st (Suc t)]"
    by (simp add: tiTable_ack_st)
  from sg5 and sg6 show ?thesis by simp
qed

lemma Gateway_L4:
  assumes h1:"Gateway req dt a stop lose d ack i vc"
      and h2:"msg (Suc 0) req"
      and h3:"msg (Suc 0) a"
      and h4:"msg (Suc 0) stop"
      and h5:"ts lose"
      and h6:"ack (t + d) = [sending_data]"
      and h7:"a (Suc t) = [sc_ack]"
      and h8:"\<forall>k\<le>Suc d. lose (t + k) = [False]"
  shows "vc (Suc (t + d)) = [vc_com]"
proof -
  from h1 obtain i1 i2 x y
    where a1:"Sample req dt x stop lose ack i1 vc"
       and a2:"Delay y i1 d x i2"
       and a3:"Loss lose a i2 y i"
    by (simp only: Gateway_def, auto)
  from a2 and a3 and h3 have sg1:"msg (Suc 0) x"
    by (simp add: Loss_Delay_msg_a)
  from a1 and h2 and h4 and sg1 obtain st buffer where a4:
    "tiTable_SampleT req x stop lose
        (fin_inf_append [init_state] st) (fin_inf_append [[]] buffer) ack
         i1 vc st"
     by (simp add: Sample_def Sample_L_def, auto)
  from a4 and h5 and sg1 and h4 have sg2:"st (t+d) =  hd (ack (t+d))"
    by (simp add: tiTable_ack_st_hd)
  from sg2 and h6 have sg3:"(fin_inf_append [init_state] st) (Suc (t+d)) = sending_data"
    by (simp add: correct_fin_inf_append1)
  from a3 and h8 have sg4:"y (Suc t)  =  a (Suc t)"
    by (simp add: Loss_def, auto)
  from a2 and sg1 have sg5:"x ((Suc t) + d)  =  y (Suc t)"
    by (simp add: Delay_def)
  from sg5 and sg4 and h7 have sg6:" x (Suc (t + d)) = [sc_ack]" by simp
  from h8 have sg7:"lose (Suc (t + d)) = [False]" by auto
  from sg6 and a4 and h2 and sg1 and h4 and h5 and sg7 and sg3 show ?thesis
    by (simp add: tiTable_SampleT_def)
qed

lemma Gateway_L5:
  assumes h1:"Gateway req dt a stop lose d ack i vc"
      and h2:"msg (Suc 0) req"
      and h3:"msg (Suc 0) a"
      and h4:"msg (Suc 0) stop"
      and h5:"ts lose"
      and h6:"ack (t + d) = [sending_data]"
      and h7:"\<forall> j \<le> Suc d. a (t+j) = []"
      and h8:"\<forall>k\<le> (d + d). lose (t + k) = [False]"
  shows "j \<le> d \<longrightarrow> ack (t+d+j) = [sending_data]"
proof -
  from h1 obtain i1 i2 x y
    where a1:"Sample req dt x stop lose ack i1 vc"
       and a2:"Delay y i1 d x i2"
       and a3:"Loss lose a i2 y i"
    by (simp only: Gateway_def, auto)
  from a2 and a3 and h3 have sg1:"msg (Suc 0) x"
    by (simp add: Loss_Delay_msg_a)
  from a1 and h2 and h4 and sg1 obtain st buffer where a4:
    "tiTable_SampleT req x stop lose
        (fin_inf_append [init_state] st) (fin_inf_append [[]] buffer) ack
         i1 vc st"
     by (simp add: Sample_def Sample_L_def, auto)
  from assms and a2 and a3 and sg1 and a4 show ?thesis
  proof (induct j)
    case 0 then show ?case by simp
  next
    case (Suc j)
    then show ?case
    proof (cases "Suc j \<le> d")
      assume "\<not> Suc j \<le> d" then show ?thesis by simp
    next
      assume a0:"Suc j \<le> d"
      then have "d + Suc j \<le> d + d"   by arith
      then have sg3:"Suc (d + j) \<le> d + d" by arith
      from a4 and h2 and sg1 and h4 and h5 have sg4:
       "st (t+d+j) =  hd (ack (t+d+j))"
        by (simp add: tiTable_ack_st_hd)
      from Suc and a0 and sg4 have sg5:
       "(fin_inf_append [init_state] st) (Suc (t+d+j)) = sending_data"
        by (simp add: correct_fin_inf_append1)
      from h7 and a0  have sg6:"\<forall>j\<le> d. a (t + Suc j) = []" by auto
      from sg6 and a3 and a0 and h5 have sg7:"y (t + (Suc j)) = []"
        by (rule Loss_L5Suc)
      from sg7 and a2 have sg8a:"x (t + d + (Suc j)) = []"
        by (simp add: Delay_def)
      then  have sg8:"x (Suc (t + d + j)) = []" by simp
      have sg9:"Suc (t + d + j) = Suc (t + (d + j))" by arith
      from a4 have sg10:
        "fin_inf_append [init_state] st (Suc (t + d + j)) = sending_data \<and>
         x (Suc (t + d + j)) = [] \<and>
         lose (Suc (t + d + j)) = [False] \<longrightarrow>
         ack (Suc (t + d + j)) = [sending_data]"
        by (simp add: tiTable_SampleT_def)
      from h8 and sg3 have sg11:"lose (t + Suc (d + j)) = [False]" by blast
      have "Suc (t + d + j) = t + Suc (d + j)"  by arith
      from this and sg11 have "lose (Suc (t + d + j)) = [False]"
        by  (simp (no_asm_simp), simp)
     from sg10 and sg5 and sg8a and this show ?thesis by simp
    qed
  qed
qed

lemma Gateway_L6_induction:
 assumes h1:"msg (Suc 0) req"
     and h2:"msg (Suc 0) x"
     and h3:"msg (Suc 0) stop"
     and h4:"ts lose"
     and h5:"\<forall>j\<le> k. lose (t + j) = [False]"
     and h6:"\<forall>m \<le> k. req (t + m) \<noteq> [send]"
     and h7:"ack t = [connection_ok]"
     and h8:"Sample req dt x1 stop lose ack i1 vc"
     and h9:"Delay x2 i1 d x1 i2"
     and h10:"Loss lose x i2 x2 i"
     and h11:"m \<le> k"
 shows "ack (t + m) = [connection_ok]"
using assms
proof (induct m)
  case 0 then show ?case  by simp
next
  case (Suc m)
  then have sg1:"msg (Suc 0) x1" by (simp add:  Loss_Delay_msg_a)
  from Suc and this obtain st buffer where
    a1:"tiTable_SampleT req x1 stop lose (fin_inf_append [init_state] st)
         (fin_inf_append [[]] buffer) ack i1 vc st"  and
    a2:"\<forall> t. buffer t = (if dt t = [] then fin_inf_append [[]] buffer t else dt t)"
    by (simp add: Sample_def Sample_L_def, auto)
  from a1 and sg1 and h3 and h4 have sg2:"st (t + m) =  hd (ack (t + m))"
    by (simp add: tiTable_ack_st_hd)
  from Suc have sg3:"ack (t + m) = [connection_ok]" by simp
  from a1 and sg2 and sg3 have sg4:
  "(fin_inf_append [init_state] st) (Suc (t + m)) = connection_ok"
    by (simp add: fin_inf_append_def)
  from Suc have sg5:"Suc m \<le> k" by simp
  from sg5 and h5 have sg6:"lose (Suc (t + m)) = [False]" by auto
  from h6 and sg5 have sg7:"req (Suc (t + m)) \<noteq> [send]" by auto
  from a1 and sg3 and sg4 and sg5 and sg6 and sg7 show ?case
    by (simp add: tiTable_SampleT_def)
qed

lemma Gateway_L6:
 assumes "Gateway req dt a stop lose d ack i vc"
     and "\<forall>m\<le>k. req (t + m) \<noteq> [send]"
     and "\<forall>j\<le>k. lose (t + j) = [False]"
     and "ack t = [connection_ok]"
     and "msg (Suc 0) req"
     and "msg (Suc 0) stop"
     and "msg (Suc 0) a"
     and "ts lose"
 shows "\<forall>m\<le>k. ack (t + m) = [connection_ok]"
using assms
by (simp add: Gateway_def, clarify, simp add: Gateway_L6_induction)

lemma Gateway_L6a:
 assumes "Gateway req dt a stop lose d ack i vc"
     and "\<forall>m\<le>k. req (t + 2 + m) \<noteq> [send]"
     and "\<forall>j\<le>k. lose (t + 2 + j) = [False]"
     and "ack (t + 2) = [connection_ok]"
     and "msg (Suc 0) req"
     and "msg (Suc 0) stop"
     and "msg (Suc 0) a"
     and "ts lose"
 shows "\<forall>m\<le>k. ack (t + 2 + m) = [connection_ok]"
using assms by (rule Gateway_L6)

lemma aux_k3req:
assumes h1:"\<forall>m<k + 3. req (t + m) \<noteq> [send]"
       and h2:"m \<le> k"
shows "req (Suc (Suc (t + m))) \<noteq> [send]"
proof -
  from h2 have "m + 2 < k + 3" by arith
  from h1 and this have "req (t + (m + 2)) \<noteq> [send]" by blast
  then show ?thesis by simp
qed

lemma aux3lose:
assumes h1:"\<forall>j\<le>k + d + 3. lose (t + j) = [False]"
       and h2:"j \<le> k"
shows "lose (Suc (Suc (t + j))) = [False]"
proof -
  from h2 have "j + 2 \<le>k + d + 3" by arith
  from h1 and this have "lose (t + (j + 2)) = [False]" by blast
  then show ?thesis by simp
qed

lemma Gateway_L7:
assumes h1:"Gateway req dt a stop lose d ack i vc"
     and h2:"ts lose"
     and h3:"msg (Suc 0) a"
     and h4:"msg (Suc 0) stop"
     and h5:"msg (Suc 0) req"
     and h6:"req (Suc t) = [init]"
     and h7:"\<forall>m < (k + 3). req (t + m) \<noteq> [send]"
     and h8:"req (t + 3 + k) = [send]"
     and h9:"ack t = [init_state]"
     and h10:"\<forall>j\<le>k + d + 3. lose (t + j) = [False]"
     and h11:"\<forall> t1 \<le> t. req t1 = []"
shows "\<forall> t2 < (t + 3 + k + d). i t2 = []"
proof -
  have "Suc 0 \<le> k + d + 3" by arith
  from h10 and this have "lose (t + Suc 0) = [False]" by blast
  then have sg1:"lose (Suc t) = [False]" by simp
  have "Suc (Suc 0)\<le> k + d + 3" by arith
  from h10 and this have "lose (t + Suc (Suc 0)) = [False]" by blast
  then have sg2:"lose (Suc (Suc t)) = [False]" by simp
  from h1 and h2 and h3 and h4 and h5 and h6 and h9 and sg1 and sg2
     have sg3:"ack (t + 2) = [connection_ok]"
    by (simp add: Gateway_L1)
  from h7 and this have sg4:"\<forall>m\<le> k. req ((t + 2) + m) \<noteq> [send]"
    by (auto, simp add: aux_k3req)
  from h10 have sg5:"\<forall>j\<le> k. lose ((t + 2) + j) = [False]"
    by (auto, simp add: aux3lose)
  from h1 and sg4 and sg5 and sg3 and h5 and h4 and h3 and h2 have sg6:
   "\<forall>m \<le>  k. ack ((t + 2) + m) = [connection_ok]"
    by (rule Gateway_L6a)
  from sg6 have sg7:"ack (t + 2 + k) = [connection_ok]"  by auto
  from h1 obtain i1 i2 x y where
    a1:"Sample req dt x stop lose ack i1 vc" and
    a2:"Delay y i1 d x i2" and
    a3:"Loss lose a i2 y i"
    by (simp add: Gateway_def, auto)
  from h3 and a2 and a3  have sg8:"msg (Suc 0) x"
    by (simp add: Loss_Delay_msg_a)
  from a1 and sg8 and h4 and h5 obtain st buffer where
    a4:"tiTable_SampleT req x stop lose (fin_inf_append [init_state] st)
         (fin_inf_append [[]] buffer) ack i1 vc st"  and
    a5:"\<forall> t. buffer t = (if dt t = [] then fin_inf_append [[]] buffer t else dt t)"
    by (simp add: Sample_def Sample_L_def, auto)
  from a4 and h2 and sg8 and h4 and h11 and h6 and h7 and sg6 and h10
    have sg9:"\<forall> t1 < (t + 3 + k). i1 t1 = []"
    by (simp add: tiTable_i1_4)
  from sg9 and a2 have sg10:"\<forall> t2 < (t + 3 + k + d). i2 t2 = []"
    by (rule Delay_L2)
  from sg10 and a3 and h2 show ?thesis by (rule Loss_L2)
qed

lemma Gateway_L8a:
  assumes h1:"Gateway req dt a stop lose d ack i vc"
      and h2:"msg (Suc 0) req"
      and h3:"msg (Suc 0) stop"
      and h4:"msg (Suc 0) a"
      and h5:"ts lose"
      and h6:"\<forall>j\<le>2 * d. lose (t + j) = [False]"
      and h7:"ack t = [sending_data]"
      and h8:"\<forall>t3 \<le> t + d. a t3 = []"
      and h9:"x \<le> d + d"
  shows "ack (t + x) = [sending_data]"
proof -
  from h1 obtain i1 i2 x y where
    a1:"Sample req dt x stop lose ack i1 vc" and
    a2:"Delay y i1 d x i2" and
    a3:"Loss lose a i2 y i"
    by (simp add: Gateway_def, auto)
  from h8 and a3 and h5 have sg1:"\<forall>t3 \<le> t + d. y t3 = []" by (rule Loss_L6)
  from sg1 and a2 have sg2:"\<forall>t4 \<le> t + d + d. x t4 = []"   by (rule Delay_L4)
  from h4 and a2 and a3 have sg3:"msg (Suc 0) x" by (simp add:  Loss_Delay_msg_a)
  from h3 and h5 and h2 and sg3 and h6 and h7 and a1 and h9 and sg2 show ?thesis
    by (simp add: Sample_sending_data)
qed

lemma Gateway_L8:
assumes "Gateway req dt a stop lose d ack i vc"
       and "msg (Suc 0) req"
       and "msg (Suc 0) stop"
       and "msg (Suc 0) a"
       and "ts lose"
       and "\<forall>j\<le>2 * d. lose (t + j) = [False]"
       and "ack t = [sending_data]"
       and "\<forall>t3 \<le> t + d. a t3 = []"
shows "\<forall>x \<le> d + d. ack (t + x) = [sending_data]"
using assms
by (simp add: Gateway_L8a)

subsection \<open>Proof of the Refinement Relation for the Gateway Requirements\<close>

lemma Gateway_L0:
 assumes "Gateway req dt a stop lose d ack i vc"
 shows     "GatewayReq req dt a stop lose d ack i vc"
using assms
by (simp add: GatewayReq_def Gateway_L1 Gateway_L2 Gateway_L3 Gateway_L4)

subsection \<open>Lemmas about Gateway Requirements\<close>

lemma GatewayReq_L1:
  assumes h1:"msg (Suc 0) req"
      and h2:"msg (Suc 0) stop"
      and h3:"msg (Suc 0) a"
      and h4:"ts lose"
      and h6:"req (t + 3 + k) = [send]"
      and h7:"\<forall>j\<le>2 * d + (4 + k). lose (t + j) = [False]"
      and h9:"\<forall>m\<le> k. ack (t + 2 + m) = [connection_ok]"
      and h10:"GatewayReq req dt a stop lose d ack i vc"
 shows "ack (t + 3 + k) = [sending_data]"
proof -
  from h9 have sg1:"ack (Suc (Suc (t + k))) = [connection_ok]" by auto
  from h7 have sg2:
   "\<forall>ka\<le>Suc d. lose (Suc (Suc (t + k + ka))) = [False]"
    by (simp add: aux_lemma_lose_1)
  from h1 and h2 and h3 and h4 and h6 and h10 and sg1 and sg2 have sg3:
   "ack (t + 2 + k) = [connection_ok] \<and>
    req (Suc (t + 2 + k)) = [send] \<and> (\<forall>k\<le>Suc d. lose (t + k) = [False]) \<longrightarrow>
    ack (Suc (t + 2 + k)) = [sending_data]"
    by (simp add: GatewayReq_def)
  have "t + 3 + k = Suc (Suc (Suc (t + k)))" by arith
  from sg3 and sg1 and h6 and h7 and this show ?thesis
    by (simp add: eval_nat_numeral)
qed

lemma GatewayReq_L2:
 assumes  h1:"msg (Suc 0) req"
      and h2:"msg (Suc 0) stop"
      and h3:"msg (Suc 0) a"
      and h4:"ts lose"
      and h5:"GatewayReq req dt a stop lose d ack i vc"
      and h6:"req (t + 3 + k) = [send]"
      and h7:"inf_last_ti dt t \<noteq> []"
      and h8:"\<forall>j\<le>2 * d + (4 + k). lose (t + j) = [False]"
      and h9:"\<forall>m\<le>k. ack (t + 2 + m) = [connection_ok]"
  shows "i (t + 3 + k + d) \<noteq> []"
proof -
  from h8 have sg1:"(\<forall> (x::nat). x \<le> (d+1) \<longrightarrow> lose (t+x) = [False])"
    by (simp add: aux_lemma_lose_2)
  from h8 have sg2:"\<forall>ka\<le>Suc d. lose (Suc (Suc (t + k + ka))) = [False]"
    by (simp add: aux_lemma_lose_1)
  from h9 have sg3:"ack (t + 2 + k) = [connection_ok]" by simp
  from h1 and h2 and h3 and h4 and h5 and h6 and sg2 and sg3 have sg4:
   "ack (t + 2 + k) = [connection_ok] \<and>
    req (Suc (t + 2 + k)) = [send] \<and> (\<forall>k\<le>Suc d. lose (t + k) = [False]) \<longrightarrow>
    i (Suc (t + 2 + k + d)) = inf_last_ti dt (t + 2 + k)"
    by (simp add: GatewayReq_def, auto)
  from h7 have sg5:"inf_last_ti dt (t + 2 + k) \<noteq> []"
    by (simp add: inf_last_ti_nonempty_k)
  have sg6:"t + 3 + k = Suc (Suc (Suc (t + k)))" by arith
  have "t + 2 + k = Suc (Suc (t + k))" by arith
  from sg1 and sg2 and sg3 and sg4 and sg5 and sg6 and this and h6 show ?thesis
    by (simp add: eval_nat_numeral)
qed

subsection \<open>Properties of the Gateway System\<close>

lemma GatewaySystem_L1aux:
assumes "msg (Suc 0) req"
       and "msg (Suc 0) stop"
       and "msg (Suc 0) a"
       and "ts lose"
       and "msg (Suc 0) req \<and> msg (Suc 0) a \<and> msg (Suc 0) stop \<and> ts lose \<longrightarrow>
        (\<forall>t. (ack t = [init_state] \<and>
          req (Suc t) = [init] \<and> lose (Suc t) = [False] \<and>
          lose (Suc (Suc t)) = [False] \<longrightarrow>
          ack (Suc (Suc t)) = [connection_ok]) \<and>
         (ack t = [connection_ok] \<and> req (Suc t) = [send] \<and>
         (\<forall>k\<le>Suc d. lose (t + k) = [False]) \<longrightarrow>
          i (Suc (t + d)) = inf_last_ti dt t \<and> ack (Suc t) = [sending_data]) \<and>
         (ack (t + d) = [sending_data] \<and> a (Suc t) = [sc_ack] \<and>
          (\<forall>k\<le>Suc d. lose (t + k) = [False]) \<longrightarrow>
          vc (Suc (t + d)) = [vc_com]))"
shows  "ack (t + 3 + k + d + d) = [sending_data] \<and>
          a (Suc (t + 3 + k + d)) = [sc_ack] \<and>
         (\<forall>ka\<le>Suc d. lose (t + 3 + k + d + ka) = [False]) \<longrightarrow>
         vc (Suc (t + 3 + k + d + d)) = [vc_com]"
using assms  by blast

lemma GatewaySystem_L3aux:
assumes "msg (Suc 0) req"
       and "msg (Suc 0) stop"
       and "msg (Suc 0) a"
       and "ts lose"
       and "msg (Suc 0) req \<and> msg (Suc 0) a \<and> msg (Suc 0) stop \<and> ts lose \<longrightarrow>
        (\<forall>t. (ack t = [init_state] \<and>
          req (Suc t) = [init] \<and> lose (Suc t) = [False] \<and>
          lose (Suc (Suc t)) = [False] \<longrightarrow>
          ack (Suc (Suc t)) = [connection_ok]) \<and>
         (ack t = [connection_ok] \<and> req (Suc t) = [send] \<and>
         (\<forall>k\<le>Suc d. lose (t + k) = [False]) \<longrightarrow>
          i (Suc (t + d)) = inf_last_ti dt t \<and> ack (Suc t) = [sending_data]) \<and>
         (ack (t + d) = [sending_data] \<and> a (Suc t) = [sc_ack] \<and>
          (\<forall>k\<le>Suc d. lose (t + k) = [False]) \<longrightarrow>
          vc (Suc (t + d)) = [vc_com]))"
shows "ack (t + 2 + k) = [connection_ok] \<and>
         req (Suc (t + 2 + k)) = [send] \<and>
         (\<forall>j\<le>Suc d. lose (t + 2 + k + j) = [False]) \<longrightarrow>
         i (Suc (t + 2 + k + d)) = inf_last_ti dt (t + 2 + k)"
using assms  by blast

lemma GatewaySystem_L1:
 assumes  h2:"ServiceCenter i a"
     and h3:"GatewayReq req dt a stop lose d ack i vc"
     and h4:"msg (Suc 0) req"
     and h5:"msg (Suc 0) stop"
     and h6:"msg (Suc 0) a"
     and h7:"ts lose"
     and h9:"\<forall>j\<le>2 * d + (4 + k). lose (t + j) = [False]"
     and h11:"i (t + 3 + k + d) \<noteq> []"
     and h14:"\<forall>x \<le> d + d. ack (t + 3 + k + x) = [sending_data]"
 shows "vc (2 * d + (t + (4 + k))) = [vc_com]"
proof -
  from h2 have "\<forall>t. a (Suc t) = (if i t = [] then [] else [sc_ack])"
    by (simp add:ServiceCenter_def)
  then have sg1:
    "a (Suc (t + 3 + k + d)) = (if i (t + 3 + k + d) = [] then [] else [sc_ack])"
     by blast
  from sg1 and h11 have sg2:"a (Suc (t + 3 + k + d)) = [sc_ack]" by auto
  from h14 have sg3:"ack (t + 3 + k + 2*d) = [sending_data]" by simp
  from h4 and h5 and h6 and h7 and h3 have sg4:
    "ack (t + 3 + k + d + d) = [sending_data] \<and> a (Suc (t + 3 + k + d)) = [sc_ack] \<and>
     (\<forall>ka\<le>Suc d. lose (t + 3 + k + d + ka) = [False]) \<longrightarrow>
     vc (Suc (t + 3 + k + d + d)) = [vc_com]"
    apply (simp only: GatewayReq_def)
    by (rule GatewaySystem_L1aux, auto)
  from h9 have sg5:"\<forall>ka\<le>Suc d. lose (d + (t + (3 + k)) + ka) = [False]"
    by (simp add: aux_lemma_lose_3)
  have sg5a:"d + (t + (3 + k)) = t + 3 + k + d" by arith
  from sg5 and sg5a have sg5b:"\<forall>ka\<le>Suc d. lose (t + 3 + k + d + ka) = [False]"
    by auto
  have sg6:"(t + 3 + k + 2 * d)  = (2 * d + (t + (3 + k)))" by arith
  have sg7:"Suc (Suc (Suc (t + k + (d + d)))) = Suc (Suc (Suc (t + k + d + d)))"
    by arith
  have "Suc (Suc (Suc (Suc (t + k + d + d)))) =
            Suc (Suc (Suc (Suc (d + d + (t + k)))))" by arith
  from sg4 and sg3 and sg2 and sg5b and sg6 and sg7 and this show ?thesis
    by (simp add: eval_nat_numeral)
qed

lemma aux4lose2:
assumes "\<forall>j\<le>2 * d + (4 + k). lose (t + j) = [False]"
       and "3 + k + d \<le> 2 * d + (4 + k)"
shows "lose (t + (3::nat) + k + d) = [False]"
proof -
  from assms have "lose (t + ((3::nat) + k + d)) = [False]" by blast
  then show ?thesis by (simp add: arith_sum1)
qed

lemma aux4req:
assumes h1:"\<forall> (m::nat) \<le> k + 2. req (t + m) \<noteq> [send]"
      and h2:"m \<le> k"
      and h3:"req (t + 2 + m) = [send]" shows "False"
proof -
  from h2 have "(2::nat) + m \<le> k + (2::nat)" by arith
  from h1 and this have "req (t + (2 + m)) \<noteq> [send]" by blast
  from this and h3 show ?thesis by simp
qed

lemma GatewaySystem_L2:
 assumes h1:"Gateway req dt a stop lose d ack i vc"
     and h2:"ServiceCenter i a"
     and h3:"GatewayReq req dt a stop lose d ack i vc"
     and h4:"msg (Suc 0) req"
     and h5:"msg (Suc 0) stop"
     and h6:"msg (Suc 0) a"
     and h7:"ts lose"
     and h8:"ack t = [init_state]"
     and h9:"req (Suc t) = [init]"
     and h10:"\<forall>t1\<le>t. req t1 = []"
     and h11:"\<forall>m \<le> k + 2. req (t + m) \<noteq> [send]"
     and h12:"req (t + 3 + k) = [send]"
     and h13:"inf_last_ti dt t \<noteq> []"
     and h14:"\<forall>j\<le>2 * d + (4 + k). lose (t + j) = [False]"
 shows "vc (2 * d + (t + (4 + k))) = [vc_com]"
proof -
  have "Suc 0 \<le> 2 * d + (4 + k)" by arith
  from h14 and this have "lose (t + Suc 0) = [False]" by blast
  then have sg1:"lose (Suc t) = [False]" by simp
  have "Suc (Suc 0) \<le> 2 * d + (4 + k)" by arith
  from h14 and this have "lose (t + Suc (Suc 0)) = [False]" by blast
  then have sg2:"lose (Suc (Suc t)) = [False]" by simp
  from h3 and h4 and h5 and h6 and h7 and h8 and h9 and sg1 and sg2 have sg3:
   "ack (t + 2) = [connection_ok]"
    by (simp add: GatewayReq_def)
  from h14 have sg4:" \<forall>j\<le>k. lose (t + 2 + j) = [False]"
    by (clarify, rule aux4lose1, simp)
  from h11 have sg5:"\<forall>m \<le> k. req (t + 2 + m) \<noteq> [send]"
    by (clarify, rule aux4req, auto)
  (* stable connection *)
  from h1 and sg5 and sg4 and sg3 and h4 and h5 and h6 and h7 have sg6:
   "\<forall>m \<le> k. ack (t + 2 + m) = [connection_ok]"
    by (rule Gateway_L6)
  (* sending data*)
  from h3 and h4 and h5 and h6 and h7 and h12 and h14 and sg6 have sg10:
   "ack (t + 3 + k) = [sending_data]"
    by (simp add: GatewayReq_L1)
  from h3 and h4 and h5 and h6 and h7 and h12 and h13 and h14 and sg6 have sg11:
   "i (t + 3 + k + d) \<noteq> []"
    by (simp add: GatewayReq_L2)
  (* waiting for sc-ack *)
  from h11 have sg12:"\<forall>m < k + 3. req (t + m) \<noteq> [send]" by auto
  from h14 have sg13:"\<forall>j\<le>k + d + 3. lose (t + j) = [False]" by auto
  from h1 and h7 and h6 and h5 and h4 and h9 and sg12
          and h12 and h8 and sg13 and h10
    have sg14:"\<forall> t2 < (t + 3 + k + d). i t2 = []"
    by (simp add: Gateway_L7)
  from sg14 and h2 have sg15:"\<forall> t3 \<le> (t + 3 + k + d). a t3 = []"
    by (simp add: ServiceCenter_L2)
  from h14 have sg18:"\<forall>j\<le>2 * d. lose ((t + 3 + k) + j) = [False]"
    by (simp add: streamValue43)
  from h14  have sg16a:"\<forall>j\<le>2 * d. lose (t + j + (4 + k)) = [False]"
    by (simp add: streamValue2)
  have sg16b:"Suc (3 + k) = (4 + k)" by arith
  from sg16a and sg16b have sg16:"\<forall>j\<le>2 * d. lose (t + j + Suc (3 + k)) = [False]"
    by (simp (no_asm_simp))
  from h1 and h4 and h5 and h6 and h7 and sg18 and sg10 and sg15 have sg19:
    "\<forall>x \<le> d + d. ack (t + 3 + k + x) = [sending_data]"
     by (simp add: Gateway_L8)
  from sg19 have sg19a:"ack (t + 3 + k + d + d) = [sending_data]" by auto
  from sg16 have sg20a:"\<forall>j\<le> d. lose (t + 3 + k + d + (Suc j)) = [False]"
    by (rule streamValue10)
  have sg20b:"3 + k + d \<le> 2 * d + (4 + k)" by arith
  from h14 and sg20b have sg20c:"lose (t + 3 + k + d) = [False]"
    by (rule aux4lose2)
  from sg20a and sg20c have sg20:"\<forall>j\<le>Suc d. lose (t + 3 + k + d + j) = [False]"
    by (rule streamValue8)
  from h4 and h5 and h6 and h7 and h3 have sg21:
     "ack (t + 3 + k + d + d) = [sending_data] \<and>
      a (Suc (t + 3 + k + d)) = [sc_ack] \<and>
      (\<forall>j\<le>Suc d. lose (t + 3 + k + d + j) = [False]) \<longrightarrow>
      vc (Suc (t + 3 + k + d + d)) = [vc_com]"
     apply (simp only: GatewayReq_def)
     by (rule GatewaySystem_L1aux, auto)
   from h2 and sg11 have sg22:"a (Suc (t + 3 + k + d)) = [sc_ack]"
     by (simp only: ServiceCenter_def, auto)
   from sg21 and sg19a and sg22 and sg20 have sg23:
     "vc (Suc (t + 3 + k + d + d)) = [vc_com]" by simp
   have "2 * d + (t + (4 + k)) = (Suc (t + 3 + k + d + d))" by arith
   from sg23 and this show ?thesis
     by (simp (no_asm_simp), simp)
qed

lemma GatewaySystem_L3:
 assumes h1:"Gateway req dt a stop lose d ack i vc"
     and h2:"ServiceCenter i a"
     and h3:"GatewayReq req dt a stop lose d ack i vc"
     and h4:"msg (Suc 0) req"
     and h5:"msg (Suc 0) stop"
     and h6:"msg (Suc 0) a"
     and h7:"ts lose"
     and h8: "dt (Suc t) \<noteq> [] \<or> dt (Suc (Suc t)) \<noteq> []"
     and h9: "ack t = [init_state]"
     and h10:"req (Suc t) = [init]"
     and h11:"\<forall>t1\<le>t. req t1 = []"
     and h12:"\<forall>m \<le> k + 2. req (t + m) \<noteq> [send]"
     and h13:"req (t + 3 + k) = [send]"
     and h14:"\<forall>j\<le>2 * d + (4 + k). lose (t + j) = [False]"
 shows "vc (2 * d + (t + (4 + k))) = [vc_com]"
proof -
  have "Suc 0 \<le> 2 * d + (4 + k)" by arith
  from h14 and this have "lose (t + Suc 0) = [False]" by blast
  then have sg1:"lose (Suc t) = [False]" by simp
  have "Suc (Suc 0) \<le> 2 * d + (4 + k)" by arith
  from h14 and this have "lose (t + Suc (Suc 0)) = [False]" by blast
  then have sg2:"lose (Suc (Suc t)) = [False]" by simp
  from h3 and h4 and h5 and h6 and h7 and h10 and h9 and sg1 and sg2 have sg3:
   "ack (t + 2) = [connection_ok]"
    by (simp add: GatewayReq_def)
  from h14 have sg4:" \<forall>j\<le>k. lose (t + 2 + j) = [False]"
    by (clarify, rule aux4lose1, simp)
  from h12 have sg5:"\<forall>m \<le> k. req (t + 2 + m) \<noteq> [send]"
    by (clarify, rule aux4req, auto)
  (* stable connection *)
  from h1 and sg5 and sg4 and sg3 and h4 and h5 and h6 and h7 have sg6:
   "\<forall>m \<le> k. ack (t + 2 + m) = [connection_ok]"
    by (rule Gateway_L6)
  from sg6 have sg6a:"ack (t + 2 + k) = [connection_ok]" by simp
  (* sending data*)
  from h3 and h4 and h5 and h6 and h7 and h13 and h14 and sg6 have sg10:
   "ack (t + 3 + k) = [sending_data]"
    by (simp add: GatewayReq_L1)
  from h3 and h4 and h5 and h6 and h7 have sg11a:
   "ack (t + 2 + k) = [connection_ok] \<and>
    req (Suc (t + 2 + k)) = [send] \<and>
    (\<forall>j\<le>Suc d. lose ((t + 2 + k) + j) = [False]) \<longrightarrow>
    i (Suc (t + (2::nat) + k + d)) = inf_last_ti dt (t + 2 + k)"
    apply (simp only: GatewayReq_def)
    by (rule GatewaySystem_L3aux, auto)
  have sg12:"Suc (t + 2 + k) = t + 3 + k" by arith
  from h13 and sg12 have sg12a:"req (Suc (t + 2 + k)) = [send]"
    by (simp add: eval_nat_numeral)
  from h14 have sg13:"\<forall>j\<le>Suc d. lose ((t + 2 + k) + j) = [False]"
    by (rule streamValue12)
  from sg11a and sg6a and h13 and sg12a and sg13 have sg14:
    "i (Suc (t + (2::nat) + k + d)) = inf_last_ti dt (t + 2 + k)" by simp
  from h8 have sg15:"inf_last_ti dt (t + 2 + k) \<noteq> []"
    by (rule inf_last_ti_Suc2)
  from sg14 and sg15 have sg16: "i (t + 3 + k + d) \<noteq> []"
    by (simp add: arith_sum4)
  (* waiting for sc-ack *)
  from h14 have sg17:"\<forall>j\<le>k + d + 3. lose (t + j) = [False]" by auto
  from h12 have sg18:"\<forall>m < (k + 3). req (t + m) \<noteq> [send]"   by auto
  from h1 and h4 and h5 and h6 and h7 and h10 and sg18 and h13 and h9 and sg17 and h11
    have sg19:"\<forall> t2 < (t + 3 + k + d). i t2 = []"
    by (simp add: Gateway_L7)
  from h2 and sg19 have sg20:"\<forall> t3 \<le> (t + 3 + k + d). a t3 = []"
    by (simp add: ServiceCenter_L2)
  from h14 have sg21:"\<forall>j\<le>2 * d. lose (t + 3 + k + j) = [False]"
    by (simp add: streamValue43)
  from h1 and h4 and h5 and h6 and h7 and sg21 and sg10 and sg20 have
    "\<forall>x \<le> d + d. ack (t + 3 + k + x) = [sending_data]"
    by (simp add: Gateway_L8)
  from h2 and h3 and h4 and h5 and h6 and h7 and h14 and sg16 and this show ?thesis
    by (simp add: GatewaySystem_L1)
qed

subsection \<open>Proof of the Refinement for the Gateway System\<close>

lemma GatewaySystem_L0:
 assumes "GatewaySystem req dt stop lose d ack vc"
 shows    "GatewaySystemReq req dt stop lose d ack vc"
proof -
  from assms obtain x i where
    a1:"Gateway req dt x stop lose d ack i vc" and
    a2:"ServiceCenter i x"
    by (simp add: GatewaySystem_def, auto)
  from a1 have sg1:"GatewayReq req dt x stop lose d ack i vc"
    by (simp add: Gateway_L0)
  from a2 have sg2:"msg (Suc 0) x"
    by (simp add: ServiceCenter_a_msg)
  from assms and a1 and a2 and sg1 and sg2 show ?thesis
    apply (simp add: GatewaySystemReq_def, auto)
    apply (simp add: GatewaySystem_L3)
    apply (simp add: GatewaySystem_L3)
    apply (simp add: GatewaySystem_L3)
    by (simp add: GatewaySystem_L2)
qed

end