theory flash113Bra  imports flash113Rev

  begin
lemma onInv113:

   assumes

     b1:"r \<in> rules N" and b2:"invf=inv113 "
   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 (inv113 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX1VsInv113 )
          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 (inv113 ) (NI_Local_GetX_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_GetXVsInv113 )
          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 (inv113 ) (NI_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_ReplaceVsInv113 )
          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 (inv113 ) (NI_ShWb N ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_ShWbVsInv113 )
          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 (inv113 ) (PI_Local_GetX_GetX2 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_GetX2VsInv113 )
          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 (inv113 ) (NI_Local_PutXAcksDone ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Local_PutXAcksDoneVsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX7VsInv113 )
          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 (inv113 ) (NI_Local_Get_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Nak2VsInv113 )
          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 (inv113 ) (NI_ReplaceHomeShrVld ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_ReplaceHomeShrVldVsInv113 )
          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 (inv113 ) (NI_Remote_Put  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_PutVsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX5VsInv113 )
          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 (inv113 ) (NI_Wb ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_WbVsInv113 )
          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 (inv113 ) (NI_Local_Get_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_GetVsInv113 )
          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 (inv113 ) (PI_Local_Replace ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_ReplaceVsInv113 )
          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 (inv113 ) (NI_ReplaceShrVld  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_ReplaceShrVldVsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX8VsInv113 )
          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 (inv113 ) (NI_InvAck_2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvAck_2VsInv113 )
          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 (inv113 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Nak2VsInv113 )
          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 (inv113 ) (PI_Remote_Replace  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_ReplaceVsInv113 )
          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 (inv113 ) (NI_Nak_Home ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Nak_HomeVsInv113 )
          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 (inv113 ) (NI_Local_Get_Put2  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Put2VsInv113 )
          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 (inv113 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvAck_1VsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX11VsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX6VsInv113 )
          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 (inv113 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Put2VsInv113 )
          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 (inv113 ) (PI_Local_Get_Put ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_Get_PutVsInv113 )
          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 (inv113 ) (PI_Local_GetX_PutX1 N ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX1VsInv113 )
          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 (inv113 ) (NI_InvAck_1_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvAck_1_HomeVsInv113 )
          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 (inv113 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Nak1VsInv113 )
          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 (inv113 ) (NI_Local_Get_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Nak1VsInv113 )
          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 (inv113 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_Nak2VsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX10_homeVsInv113 )
          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 (inv113 ) (PI_Remote_Get  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_GetVsInv113 )
          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 (inv113 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_Nak3VsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX10VsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX2VsInv113 )
          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 (inv113 ) (NI_Remote_Get_Put1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_Get_Put1VsInv113 )
          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 (inv113 ) (NI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_PutXVsInv113 )
          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 (inv113 ) (Store  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis StoreVsInv113 )
          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 (inv113 ) (NI_FAck ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_FAckVsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX3VsInv113 )
          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 (inv113 ) (PI_Local_GetX_PutX3 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX3VsInv113 )
          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 (inv113 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_PutXVsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX8_homeVsInv113 )
          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 (inv113 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Put1VsInv113 )
          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 (inv113 ) (PI_Local_GetX_GetX1 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_GetX1VsInv113 )
          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 (inv113 ) (StoreHome ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis StoreHomeVsInv113 )
          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 (inv113 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_NakVsInv113 )
          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 (inv113 ) (NI_Inv  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_InvVsInv113 )
          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 (inv113 ) (PI_Remote_PutX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_PutXVsInv113 )
          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 (inv113 ) (PI_Local_GetX_PutX4 ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX4VsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX4VsInv113 )
          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 (inv113 ) (NI_Nak  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_NakVsInv113 )
          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 (inv113 ) (PI_Local_GetX_PutX2 N ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_GetX_PutX2VsInv113 )
          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 (inv113 ) (NI_Local_Put ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Local_PutVsInv113 )
          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 (inv113 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_Nak1VsInv113 )
          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 (inv113 ) (NI_Nak_Clear ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_Nak_ClearVsInv113 )
          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 (inv113 ) (PI_Local_PutX ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_PutXVsInv113 )
          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 (inv113 ) (NI_Local_Get_Nak3  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Nak3VsInv113 )
          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 (inv113 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_Nak_HomeVsInv113 )
          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 (inv113 ) (PI_Local_Get_Get ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis PI_Local_Get_GetVsInv113 )
          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 (inv113 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_GetX_PutX9VsInv113 )
          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 (inv113 ) (PI_Remote_GetX  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis PI_Remote_GetXVsInv113 )
          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 (inv113 ) (NI_ReplaceHome ) (invariants N) "
            apply(cut_tac    b2 c2 )
            by (metis NI_ReplaceHomeVsInv113 )
          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 (inv113 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Remote_GetX_PutX_HomeVsInv113 )
          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 (inv113 ) (NI_Local_Get_Put3  iRule1 ) (invariants N) "
            apply(cut_tac  c2  )
            by (metis NI_Local_Get_Put3VsInv113 )
          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 LLVM_Memory_RS
imports
  "../basic/LLVM_Basic_Main"
  Sep_Value_RS
  Sep_Array_Block_RS
begin

  interpretation ab: array_block2 "STATIC_ERROR ''''" MEM_ERROR "vload MEM_ERROR::_ \<Rightarrow> (llvm_primval val,_,_,_) M" "vstore MEM_ERROR" "checked_gep MEM_ERROR" val_\<alpha> vpto_assn "\<lambda>v. v\<in>range val_\<alpha>"
    apply unfold_locales
    apply (rule vload_rule)
    apply (rule vstore_rule)
    apply (rule vpto_assn_notZ)
    apply auto []
    apply (simp; rule vpto_assn_this)
    apply auto []
    done

  datatype llvm_amemory = LLVM_AMEMORY (the_amemory: "(nat \<Rightarrow> (nat \<Rightarrow> llvm_primval aval) \<times> int tsa_opt)")

  instantiation llvm_amemory :: unique_zero_sep_algebra begin
    definition "sep_disj_llvm_amemory a b \<equiv> the_amemory a ## the_amemory b"
    definition "plus_llvm_amemory a b \<equiv> LLVM_AMEMORY (the_amemory a + the_amemory b)"
    definition "zero_llvm_amemory \<equiv> LLVM_AMEMORY 0"

    instance
      apply standard
      unfolding sep_disj_llvm_amemory_def plus_llvm_amemory_def zero_llvm_amemory_def
      apply (auto simp: sep_algebra_simps llvm_amemory.expand)
      done

  end

  type_synonym llvm_assn = "llvm_amemory \<Rightarrow> bool"

  definition "llvm_\<alpha> \<equiv> LLVM_AMEMORY o ab.ba.\<alpha> o llvm_memory.the_memory"
  definition "llvm_pto x p \<equiv> (ab.ba.pto (llvm_val.the_val x) (llvm_ptr.the_ptr p)) o llvm_amemory.the_amemory"
  (*definition "llvm_is_base_ptr p \<equiv> ab.is_base_ptr (llvm_ptr.the_ptr p)"*)

  definition "llvm_malloc_tag n p \<equiv> ab.ba.tag n (llvm_ptr.the_ptr p) o llvm_amemory.the_amemory"

  instantiation llvm_ptr :: addr_algebra begin
    definition "abase_llvm_ptr = abase o llvm_ptr.the_ptr"
    definition "acompat_llvm_ptr a b \<equiv> acompat (llvm_ptr.the_ptr a) (llvm_ptr.the_ptr b)"
    definition "adiff_llvm_ptr a b \<equiv> adiff (llvm_ptr.the_ptr a) (llvm_ptr.the_ptr b)"
    definition "aidx_llvm_ptr a i \<equiv> LLVM_PTR ((llvm_ptr.the_ptr a) +\<^sub>a i)"

    instance
      apply standard
      unfolding abase_llvm_ptr_def acompat_llvm_ptr_def adiff_llvm_ptr_def aidx_llvm_ptr_def
      apply (intro part_equivpI sympI transpI)
      apply (metis ab.block_ptr_imp_abase ab.is_block_ptr_simps(2) acompat_refl llvm_ptr.sel)
      apply (auto intro: acompat_sym acompat_trans simp: acompat_dom)
      done
  end

  (*
  definition "llvm_idx_ptr p i \<equiv> LLVM_PTR (ab.idx_ptr (llvm_ptr.the_ptr p) i)"
  definition "llvm_is_arr_ptr p \<equiv> ab.is_arr_ptr (llvm_ptr.the_ptr p)"

  lemma llvm_idx_ptr_add[simp]: "llvm_idx_ptr (llvm_idx_ptr p i) j = llvm_idx_ptr p (i+j)"
    by (cases p) (auto simp: llvm_idx_ptr_def)

  lemma llvm_is_arr_ptr_idx[simp]: "llvm_is_arr_ptr (llvm_idx_ptr p i) \<longleftrightarrow> llvm_is_arr_ptr p"
    by (cases p) (auto simp: llvm_idx_ptr_def llvm_is_arr_ptr_def)
  *)

  lemma xfer_htriple:
    assumes "htriple ab.ba.\<alpha> P c Q"
    assumes "P' = P o llvm_amemory.the_amemory"
    assumes "c' = llvm_zoom_base \<alpha> c"
    assumes "\<And>r. Q' (\<alpha> r) = Q r o llvm_amemory.the_amemory"
    shows "htriple llvm_\<alpha> P' c' Q'"
    using assms unfolding htriple_alt llvm_zoom_base_def llvm_\<alpha>_def wp_def
    apply (clarsimp simp: run_simps)
  proof goal_cases
    case A: (1 p s f)

    find_theorems llvm_memory.the_memory\<^sub>L

    from \<open>p##f\<close> \<open>LLVM_AMEMORY (ab.ba.\<alpha> (get' llvm_memory.the_memory\<^sub>L s)) = p + f\<close>
    have "llvm_amemory.the_amemory p ## llvm_amemory.the_amemory f"
      and "ab.ba.\<alpha> (get' llvm_memory.the_memory\<^sub>L s) = llvm_amemory.the_amemory p + llvm_amemory.the_amemory f"
      by (auto simp: sep_disj_llvm_amemory_def plus_llvm_amemory_def)

    from A(1)[rule_format] show ?case
      apply (rule mwp_cons)
      apply (intro conjI; fact)
      apply (clarsimp_all simp: run_simps)
      by (metis (full_types) assms(4) comp_apply llvm_amemory.sel plus_llvm_amemory_def sep_disj_llvm_amemory_def)

  qed

  lemma llvm_load_rule[vcg_rules]: "htriple llvm_\<alpha> (llvm_pto x p) (llvm_load p) (\<lambda>r. \<up>(r=x) ** llvm_pto x p)"
    apply (rule xfer_htriple[OF ab.ba.load_rule])
    unfolding llvm_pto_def llvm_load_def
    apply simp
    apply simp
    apply (rule ext)
    apply (auto simp: sep_algebra_simps pred_lift_extract_simps)
    done

  lemma llvm_store_unchecked_rule[vcg_rules]: "htriple llvm_\<alpha> (llvm_pto xx p) (llvm_store_unchecked x p) (\<lambda>_. llvm_pto x p)"
    apply (rule xfer_htriple[OF ab.ba.store_rule])
    unfolding llvm_pto_def llvm_store_unchecked_def
    apply simp
    apply simp
    apply (rule ext)
    apply (auto simp: sep_algebra_simps pred_lift_extract_simps)
    done

  lemma llvm_store_rule[vcg_rules]: "llvm_vstruct x = llvm_vstruct xx
    \<Longrightarrow> htriple llvm_\<alpha> (llvm_pto xx p) (llvm_store x p) (\<lambda>_. llvm_pto x p)"
    unfolding llvm_store_def
    by vcg

  lemma the_amemoryZ[simp]: "the_amemory 0 = 0" by (auto simp: zero_llvm_amemory_def)

  lemma the_amemoryZ_iff[simp]: "the_amemory x = 0 \<longleftrightarrow> x=0"
    by (auto simp: zero_llvm_amemory_def llvm_amemory.expand)

  lemma xfer_sep_conj1: "((\<lambda>x. a (the_amemory x)) ** (\<lambda>x. b (the_amemory x))) = (a**b) o the_amemory"
    apply (rule ext)
    apply (auto 3 3 simp: sep_conj_def sep_disj_llvm_amemory_def plus_llvm_amemory_def)
    by (metis (full_types) llvm_amemory.exhaust_sel llvm_amemory.sel)

  lemma xfer_sep_conj2: "((a o the_amemory) ** (b o the_amemory)) = (a**b) o the_amemory"
    using xfer_sep_conj1 unfolding comp_def .

  lemmas xfer_sep_conj = xfer_sep_conj1 xfer_sep_conj2

  lemma xfer_sep_list_conj1: "(\<And>*map (\<lambda>x. f x o the_amemory) l) = (\<And>*map f l) o the_amemory"
    apply (induction l)
    apply auto
    by (auto intro!: ext simp: sep_algebra_simps xfer_sep_conj)

  lemma xfer_sep_list_conj2: "(\<And>*map (\<lambda>x s. f x (the_amemory s)) l) = (\<And>*map f l) o the_amemory"
    using xfer_sep_list_conj1 unfolding comp_def .

  lemmas xfer_sep_list_conj = xfer_sep_list_conj1 xfer_sep_list_conj2

  lemma xfer_sep_set_img1: "(\<Union>*x\<in>I. f x o the_amemory) = (\<Union>*x\<in>I. f x) o the_amemory"
  proof (cases "finite I")
    case True then show ?thesis
      by (induction) (auto del: ext intro!: ext simp: sep_algebra_simps xfer_sep_conj)
  qed auto

  lemma xfer_sep_set_img2: "(\<Union>*x\<in>I. (\<lambda>s. f x (the_amemory s))) = (\<Union>*x\<in>I. f x) o the_amemory"
    using xfer_sep_set_img1 unfolding comp_def .

  lemmas xfer_sep_set_img = xfer_sep_set_img1 xfer_sep_set_img2

  lemma llvm_allocn_rule[vcg_rules]:
    "htriple llvm_\<alpha>
      \<box>
      (llvm_allocn v n)
      (\<lambda>r. (\<Union>*i\<in>{0..<int n}. llvm_pto v (r +\<^sub>a i))
        ** llvm_malloc_tag (int n) r ** \<up>(abase r))"
    apply (rule xfer_htriple[OF ab.ba_allocn_rule])
    unfolding llvm_pto_def llvm_allocn_def llvm_malloc_tag_def abase_llvm_ptr_def aidx_llvm_ptr_def
    apply (rule ext) apply (auto simp: sep_algebra_simps) []
    apply simp
    apply (rule ext)
    apply (auto simp: sep_algebra_simps pred_lift_extract_simps xfer_sep_set_img xfer_sep_conj)
    done

  lemma llvm_free_rule[vcg_rules]:
    "htriple llvm_\<alpha>
      ((\<Union>*i\<in>{0..<n}. EXS v. llvm_pto v (p +\<^sub>a i))
        ** llvm_malloc_tag n p)
      (llvm_free p)
      (\<lambda>_. \<box>)"
    apply (rule xfer_htriple[OF ab.ba_freen_rule[where p="llvm_ptr.the_ptr p" and n=n], where \<alpha>=id])
    apply (cases p; simp add: )

    unfolding llvm_pto_def llvm_free_def llvm_malloc_tag_def aidx_llvm_ptr_def
    apply (auto simp: sep_algebra_simps)
    apply (subst xfer_sep_set_img xfer_sep_conj)+
    apply (cases p; simp)
    by (metis llvm_val.sel)

  lemma llvm_checked_idx_ptr_rule[vcg_rules]:
    "abase p \<Longrightarrow>
      htriple llvm_\<alpha>
        (llvm_pto v (p +\<^sub>a i))
        (llvm_checked_idx_ptr p i)
        (\<lambda>r. \<up>(r= p +\<^sub>a i) ** llvm_pto v (p +\<^sub>a i))
    "

    supply R=xfer_htriple[OF ab.checked_idx_ptr_rule[where p="llvm_ptr.the_ptr p" and i=i and xx="llvm_val.the_val v"], where \<alpha>=LLVM_PTR]
    apply (rule R)
    unfolding llvm_checked_idx_ptr_def llvm_pto_def abase_llvm_ptr_def aidx_llvm_ptr_def
    apply (auto simp: xfer_sep_conj sep_algebra_simps pred_lift_extract_simps)
    done

end


theory FunctionalImplementation
imports Initialization SolveLoop
begin

(******************************************************************************)
subsection\<open>Total correctness theorem\<close>
(******************************************************************************)

theorem correctness:
shows
"(solve F0 = TRUE \<and> satisfiable F0) \<or> (solve F0 = FALSE \<and> \<not> satisfiable F0)"
proof-
  let ?istate = "initialize F0 initialState"
  let ?F0' = "filter (\<lambda> c. \<not> clauseTautology c) F0"
  have
  "InvariantConsistent (getM ?istate)"
  "InvariantUniq (getM ?istate)"
  "InvariantWatchesEl (getF ?istate) (getWatch1 ?istate) (getWatch2 ?istate)" and
  "InvariantWatchesDiffer (getF ?istate) (getWatch1 ?istate) (getWatch2 ?istate)" and
  "InvariantWatchCharacterization (getF ?istate) (getWatch1 ?istate) (getWatch2 ?istate) (getM ?istate)" and
  "InvariantWatchListsContainOnlyClausesFromF (getWatchList ?istate) (getF ?istate)" and
  "InvariantWatchListsUniq (getWatchList ?istate)" and
  "InvariantWatchListsCharacterization (getWatchList ?istate) (getWatch1 ?istate) (getWatch2 ?istate)" and
  "InvariantUniqQ (getQ ?istate)" and
  "InvariantQCharacterization (getConflictFlag ?istate) (getQ ?istate) (getF ?istate) (getM ?istate)" and
  "InvariantConflictFlagCharacterization (getConflictFlag ?istate) (getF ?istate) (getM ?istate)" and
  "InvariantNoDecisionsWhenConflict (getF ?istate) (getM ?istate) (currentLevel (getM ?istate))" and
  "InvariantNoDecisionsWhenUnit (getF ?istate) (getM ?istate) (currentLevel (getM ?istate))" and
  "InvariantGetReasonIsReason (getReason ?istate) (getF ?istate) (getM ?istate) (set (getQ ?istate))" and
  "InvariantConflictClauseCharacterization (getConflictFlag ?istate) (getConflictClause ?istate) (getF ?istate) (getM ?istate)"
  "InvariantVarsM (getM ?istate) F0 (vars F0)"
  "InvariantVarsQ (getQ ?istate) F0 (vars F0)"
  "InvariantVarsF (getF ?istate) F0 (vars F0)"
  "getSATFlag ?istate = UNDEF \<longrightarrow> InvariantEquivalentZL (getF ?istate) (getM ?istate) ?F0'" and
  "getSATFlag ?istate = FALSE \<longrightarrow> \<not> satisfiable ?F0'"
  "getSATFlag ?istate = TRUE  \<longrightarrow> satisfiable F0"
    using InvariantsAfterInitialization[of "F0"]
    using InvariantEquivalentZLAfterInitialization[of "F0"]
    unfolding InvariantVarsM_def
    unfolding InvariantVarsF_def
    unfolding InvariantVarsQ_def
    by (auto simp add: Let_def)
  moreover
  hence "solve_loop_dom ?istate (vars F0)"
    using SolveLoopTermination[of "?istate" "?F0'" "vars F0" "F0"]
    using finiteVarsFormula[of "F0"]
    using varsSubsetFormula[of "?F0'" "F0"]
    by auto
  ultimately
  show ?thesis
    using finiteVarsFormula[of "F0"]
    using SATFlagAfterSolveLoop[of "?istate" "vars F0" "?F0'" "F0"]
    using satisfiableFilterTautologies[of "F0"]
    unfolding solve_def
    using varsSubsetFormula[of "?F0'" "F0"]
    by (auto simp add: Let_def)
qed

end


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

section \<open>The (faulty) transmission channel (both directions)\<close>

theory Abschannel
imports IOA.IOA Action
begin

datatype 'a abs_action = S 'a | R 'a

definition
  ch_asig :: "'a abs_action signature" where
  "ch_asig = (UN b. {S(b)}, UN b. {R(b)}, {})"

definition
  ch_trans :: "('a abs_action, 'a multiset)transition set" where
  "ch_trans =
    {tr. let s = fst(tr);
             t = snd(snd(tr))
         in
         case fst(snd(tr))
           of S(b) => t = addm s b |
              R(b) => count s b ~= 0 & t = delm s b}"

definition
  ch_ioa :: "('a abs_action, 'a multiset)ioa" where
  "ch_ioa = (ch_asig, {{|}}, ch_trans,{},{})"

definition
  rsch_actions :: "'m action => bool abs_action option" where
  "rsch_actions (akt) =
          (case akt of
           S_msg(m) => None |
            R_msg(m) => None |
           S_pkt(packet) => None |
            R_pkt(packet) => None |
            S_ack(b) => Some(S(b)) |
            R_ack(b) => Some(R(b)) |
           C_m_s =>  None  |
           C_m_r =>  None |
           C_r_s =>  None  |
           C_r_r(m) => None)"

definition
  srch_actions :: "'m action =>(bool * 'm) abs_action option" where
  "srch_actions (akt) =
          (case akt of
           S_msg(m) => None |
            R_msg(m) => None |
           S_pkt(p) => Some(S(p)) |
            R_pkt(p) => Some(R(p)) |
            S_ack(b) => None |
            R_ack(b) => None |
           C_m_s => None |
           C_m_r => None |
           C_r_s => None |
           C_r_r(m) => None)"

definition
  srch_ioa :: "('m action, 'm packet multiset)ioa" where
  "srch_ioa = rename ch_ioa srch_actions"

definition
  rsch_ioa :: "('m action, bool multiset)ioa" where
  "rsch_ioa = rename ch_ioa rsch_actions"

definition
  srch_asig :: "'m action signature" where
  "srch_asig = asig_of(srch_ioa)"

definition
  rsch_asig :: "'m action signature" where
  "rsch_asig = asig_of(rsch_ioa)"

definition
  srch_wfair :: "('m action)set set" where
  "srch_wfair = wfair_of(srch_ioa)"
definition
  srch_sfair :: "('m action)set set" where
  "srch_sfair = sfair_of(srch_ioa)"
definition
  rsch_sfair :: "('m action)set set" where
  "rsch_sfair = sfair_of(rsch_ioa)"
definition
  rsch_wfair :: "('m action)set set" where
  "rsch_wfair = wfair_of(rsch_ioa)"

definition
  srch_trans :: "('m action, 'm packet multiset)transition set" where
  "srch_trans = trans_of(srch_ioa)"
definition
  rsch_trans :: "('m action, bool multiset)transition set" where
  "rsch_trans = trans_of(rsch_ioa)"

lemmas unfold_renaming =
  srch_asig_def rsch_asig_def rsch_ioa_def srch_ioa_def ch_ioa_def
  ch_asig_def srch_actions_def rsch_actions_def rename_def rename_set_def asig_of_def
  actions_def srch_trans_def rsch_trans_def ch_trans_def starts_of_def
  trans_of_def asig_projections

lemma in_srch_asig:
     "S_msg(m) \<notin> actions(srch_asig)        \<and>
       R_msg(m) \<notin> actions(srch_asig)        \<and>
       S_pkt(pkt) \<in> actions(srch_asig)    \<and>
       R_pkt(pkt) \<in> actions(srch_asig)    \<and>
       S_ack(b) \<notin> actions(srch_asig)     \<and>
       R_ack(b) \<notin> actions(srch_asig)     \<and>
       C_m_s \<notin> actions(srch_asig)           \<and>
       C_m_r \<notin> actions(srch_asig)           \<and>
       C_r_s \<notin> actions(srch_asig)  & C_r_r(m) \<notin> actions(srch_asig)"
  by (simp add: unfold_renaming)

lemma in_rsch_asig:
      "S_msg(m) \<notin> actions(rsch_asig)         \<and>
       R_msg(m) \<notin> actions(rsch_asig)         \<and>
       S_pkt(pkt) \<notin> actions(rsch_asig)    \<and>
       R_pkt(pkt) \<notin> actions(rsch_asig)    \<and>
       S_ack(b) \<in> actions(rsch_asig)       \<and>
       R_ack(b) \<in> actions(rsch_asig)       \<and>
       C_m_s \<notin> actions(rsch_asig)            \<and>
       C_m_r \<notin> actions(rsch_asig)            \<and>
       C_r_s \<notin> actions(rsch_asig)            \<and>
       C_r_r(m) \<notin> actions(rsch_asig)"
  by (simp add: unfold_renaming)

lemma srch_ioa_thm: "srch_ioa =
    (srch_asig, {{|}}, srch_trans,srch_wfair,srch_sfair)"
apply (simp (no_asm) add: srch_asig_def srch_trans_def asig_of_def trans_of_def wfair_of_def sfair_of_def srch_wfair_def srch_sfair_def)
apply (simp (no_asm) add: unfold_renaming)
done

lemma rsch_ioa_thm: "rsch_ioa =
     (rsch_asig, {{|}}, rsch_trans,rsch_wfair,rsch_sfair)"
apply (simp (no_asm) add: rsch_asig_def rsch_trans_def asig_of_def trans_of_def wfair_of_def sfair_of_def rsch_wfair_def rsch_sfair_def)
apply (simp (no_asm) add: unfold_renaming)
done

end


theory OG_Syntax
imports OG_Tactics Quote_Antiquote
begin

text\<open>Syntax for commands and for assertions and boolean expressions in
 commands \<open>com\<close> and annotated commands \<open>ann_com\<close>.\<close>

abbreviation Skip :: "'a com"  ("SKIP" 63)
  where "SKIP \<equiv> Basic ID"

abbreviation AnnSkip :: "'a assn \<Rightarrow> 'a ann_com"  ("_//SKIP" [90] 63)
  where "r SKIP \<equiv> AnnBasic (True, r) ID"

abbreviation AnnSkipIgnore :: "'a assn \<Rightarrow> 'a ann_com"  ("_*//SKIP" [90] 63)
  where "r* SKIP \<equiv> AnnBasic (False, r) ID"

notation
  Seq  ("_,,/ _" [55, 56] 55) and
  AnnSeq  ("_;;/ _" [60,61] 60)

abbreviation DETERM :: "('a \<Rightarrow> 'a) \<Rightarrow> ('a \<Rightarrow> 'a set)" where
  "DETERM f \<equiv> \<lambda>s. {f s}"

lemma "DETERM id = ID" by simp

syntax
  "_Assign"      :: "idt \<Rightarrow> 'b \<Rightarrow> 'a com"    ("(\<acute>_ :=/ _)" [70, 65] 61)
  "_AnnAssign"   :: "'a assn \<Rightarrow> idt \<Rightarrow> 'b \<Rightarrow> 'a com"    ("(_ \<acute>_ :=/ _)" [90,70,65] 61)
  "_AnnAssignIgnore"   :: "'a assn \<Rightarrow> idt \<Rightarrow> 'b \<Rightarrow> 'a com"    ("(_* \<acute>_ :=/ _)" [90,70,65] 61)

translations
  "\<acute>x := a" \<rightharpoonup> "CONST Basic \<guillemotleft>\<acute>(CONST DETERM (_update_name x (\<lambda>_. a)))\<guillemotright>"
  "r \<acute>x := a" \<rightharpoonup> "CONST AnnBasic (HOL.True, r) \<guillemotleft>\<acute>(CONST DETERM (_update_name x (\<lambda>_. a)))\<guillemotright>"
  "r* \<acute>x := a" \<rightharpoonup> "CONST AnnBasic (HOL.False, r) \<guillemotleft>\<acute>(CONST DETERM (_update_name x (\<lambda>_. a)))\<guillemotright>"

abbreviation
  "update_var f S s \<equiv> (\<lambda>v. f (\<lambda>_. v) s) ` S"

syntax
  "_Pick"      :: "idt \<Rightarrow> 'b \<Rightarrow> 'a com"    ("(\<acute>_ :\<in>/ _)" [70, 65] 61)
  "_AnnPick"   :: "'a assn \<Rightarrow> idt \<Rightarrow> 'b \<Rightarrow> 'a com"    ("(_ \<acute>_ :\<in>/ _)" [90,70,65] 61)
  "_AnnPickIgnore"   :: "'a assn \<Rightarrow> idt \<Rightarrow> 'b \<Rightarrow> 'a com"    ("(_* \<acute>_ :\<in>/ _)" [90,70,65] 61)

translations
  "\<acute>x :\<in> S" \<rightharpoonup> "CONST Basic \<guillemotleft>\<acute>(CONST update_var (_update_name x) S)\<guillemotright>"
  "r \<acute>x :\<in> S" \<rightharpoonup> "CONST AnnBasic (HOL.True, r) \<guillemotleft>\<acute>(CONST update_var (_update_name x) S)\<guillemotright>"
  "r* \<acute>x :\<in> S" \<rightharpoonup> "CONST AnnBasic (HOL.False, r) \<guillemotleft>\<acute>(CONST update_var (_update_name x) S)\<guillemotright>"

syntax
  "_AnnCond1"    :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a ann_com  \<Rightarrow> 'a ann_com \<Rightarrow> 'a ann_com"
                    ("_ //IF _ /THEN _ /ELSE _ /FI"  [90,0,0,0] 61)
  "_AnnCond2"    :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a ann_com \<Rightarrow> 'a ann_com"
                    ("_ //IF _ /THEN _ /FI"  [90,0,0] 61)
  "_AnnWhile"    :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a assn \<Rightarrow> 'a ann_com \<Rightarrow> 'a ann_com"
                    ("_ //WHILE _ /INV _ //DO _//OD"  [90,0,0,0] 61)
  "_AnnAwait"    :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a com \<Rightarrow> 'a ann_com"
                    ("_ //AWAIT _ /THEN /_ /END"  [90,0,0] 61)
  "_AnnAtom"     :: "'a assn  \<Rightarrow> 'a com \<Rightarrow> 'a ann_com"   ("_//\<langle>_\<rangle>" [90,0] 61)
  "_AnnWait"     :: "'a assn \<Rightarrow> 'a bexp \<Rightarrow> 'a ann_com"   ("_//WAIT _ END" [90,0] 61)

  "_AnnCond1Ig"  :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a ann_com  \<Rightarrow> 'a ann_com \<Rightarrow> 'a ann_com"
                    ("_* //IF _ /THEN _ /ELSE _ /FI"  [90,0,0,0] 61)
  "_AnnCond2Ig"  :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a ann_com \<Rightarrow> 'a ann_com"
                    ("_* //IF _ /THEN _ /FI"  [90,0,0] 61)
  "_AnnWhileIg"  :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a assn \<Rightarrow> 'a ann_com \<Rightarrow> 'a ann_com"
                    ("_* //WHILE _ /INV _ //DO _//OD"  [90,0,0,0] 61)
  "_AnnWhileIg'"  :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a assn \<Rightarrow> 'a ann_com \<Rightarrow> 'a ann_com"
                    ("_ //WHILE _ /INV _* //DO _//OD"  [90,0,0,0] 61)
  "_AnnWhileIg''"  :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a assn \<Rightarrow> 'a ann_com \<Rightarrow> 'a ann_com"
                    ("_* //WHILE _ /INV _* //DO _//OD"  [90,0,0,0] 61)
  "_AnnAwaitIg"  :: "'a assn \<Rightarrow> 'a bexp  \<Rightarrow> 'a com \<Rightarrow> 'a ann_com"
                    ("_* //AWAIT _ /THEN /_ /END"  [90,0,0] 61)
  "_AnnAtomIg"   :: "'a assn  \<Rightarrow> 'a com \<Rightarrow> 'a ann_com"   ("_*//\<langle>_\<rangle>" [90,0] 61)
  "_AnnWaitIg"   :: "'a assn \<Rightarrow> 'a bexp \<Rightarrow> 'a ann_com"   ("_*//WAIT _ END" [90,0] 61)

  "_Cond"        :: "'a bexp \<Rightarrow> 'a com \<Rightarrow> 'a com \<Rightarrow> 'a com"
                                  ("(0IF _/ THEN _/ ELSE _/ FI)" [0, 0, 0] 61)
  "_Cond2"       :: "'a bexp \<Rightarrow> 'a com \<Rightarrow> 'a com"   ("IF _ THEN _ FI" [0,0] 56)
  "_While_inv"   :: "'a bexp \<Rightarrow> 'a assn \<Rightarrow> 'a com \<Rightarrow> 'a com"
                    ("(0WHILE _/ INV _ //DO _ /OD)"  [0, 0, 0] 61)
  "_While"       :: "'a bexp \<Rightarrow> 'a com \<Rightarrow> 'a com"
                    ("(0WHILE _ //DO _ /OD)"  [0, 0] 61)

translations
  "IF b THEN c1 ELSE c2 FI" \<rightharpoonup> "CONST Cond \<lbrace>b\<rbrace> c1 c2"
  "IF b THEN c FI" \<rightleftharpoons> "IF b THEN c ELSE SKIP FI"
  "WHILE b INV i DO c OD" \<rightharpoonup> "CONST While \<lbrace>b\<rbrace> i c"
  "WHILE b DO c OD" \<rightleftharpoons> "WHILE b INV CONST undefined DO c OD"

  "r IF b THEN c1 ELSE c2 FI" \<rightharpoonup> "CONST AnnCond1 (HOL.True, r) \<lbrace>b\<rbrace> c1 c2"
  "r IF b THEN c FI" \<rightharpoonup> "CONST AnnCond2 (HOL.True, r) \<lbrace>b\<rbrace> c"
  "r WHILE b INV i DO c OD" \<rightharpoonup> "CONST AnnWhile (HOL.True, r) \<lbrace>b\<rbrace> (HOL.True, i) c"
  "r AWAIT b THEN c END" \<rightharpoonup> "CONST AnnAwait (HOL.True, r) \<lbrace>b\<rbrace> c"
  "r \<langle>c\<rangle>" \<rightleftharpoons> "r AWAIT CONST True THEN c END"
  "r WAIT b END" \<rightleftharpoons> "r AWAIT b THEN SKIP END"

  "r* IF b THEN c1 ELSE c2 FI" \<rightharpoonup> "CONST AnnCond1 (HOL.False, r) \<lbrace>b\<rbrace> c1 c2"
  "r* IF b THEN c FI" \<rightharpoonup> "CONST AnnCond2 (HOL.False, r) \<lbrace>b\<rbrace> c"
  "r* WHILE b INV i DO c OD" \<rightharpoonup> "CONST AnnWhile (HOL.False, r) \<lbrace>b\<rbrace> (HOL.True, i) c"
  "r WHILE b INV i* DO c OD" \<rightharpoonup> "CONST AnnWhile (HOL.True, r) \<lbrace>b\<rbrace> (HOL.False, i) c"
  "r* WHILE b INV i* DO c OD" \<rightharpoonup> "CONST AnnWhile (HOL.False, r) \<lbrace>b\<rbrace> (HOL.False, i) c"
  "r* AWAIT b THEN c END" \<rightharpoonup> "CONST AnnAwait (HOL.False, r) \<lbrace>b\<rbrace> c"
  "r* \<langle>c\<rangle>" \<rightleftharpoons> "r* AWAIT CONST True THEN c END"
  "r* WAIT b END" \<rightleftharpoons> "r* AWAIT b THEN SKIP END"

nonterminal prgs

syntax
  "_PAR" :: "prgs \<Rightarrow> 'a"              ("COBEGIN//_//COEND" [57] 56)
  "_prg" :: "['a, 'a] \<Rightarrow> prgs"        ("_//_" [60, 90] 57)
  "_prgs" :: "['a, 'a, prgs] \<Rightarrow> prgs"  ("_//_//\<parallel>//_" [60,90,57] 57)

  "_prg_scheme" :: "['a, 'a, 'a, 'a, 'a] \<Rightarrow> prgs"
                  ("SCHEME [_ \<le> _ < _] _// _" [0,0,0,60, 90] 57)

translations
  "_prg c q" \<rightleftharpoons> "[(CONST Some c, q)]"
  "_prgs c q ps" \<rightleftharpoons> "(CONST Some c, q) # ps"
  "_PAR ps" \<rightleftharpoons> "CONST Parallel ps"

  "_prg_scheme j i k c q" \<rightleftharpoons> "CONST map (\<lambda>i. (CONST Some c, q)) [j..<k]"

print_translation \<open>
  let
    fun quote_tr' f (t :: ts) =
          Term.list_comb (f $ Syntax_Trans.quote_tr' @{syntax_const "_antiquote"} t, ts)
      | quote_tr' _ _ = raise Match;

    fun annquote_tr' f (r :: t :: ts) =
          Term.list_comb (f $ r $ Syntax_Trans.quote_tr' @{syntax_const "_antiquote"} t, ts)
      | annquote_tr' _ _ = raise Match;

    val assert_tr' = quote_tr' (Syntax.const @{syntax_const "_Assert"});

    fun bexp_tr' name ((Const (@{const_syntax Collect}, _) $ t) :: ts) =
          quote_tr' (Syntax.const name) (t :: ts)
      | bexp_tr' _ _ = raise Match;

    fun annbexp_tr' name (r :: (Const (@{const_syntax Collect}, _) $ t) :: ts) =
          annquote_tr' (Syntax.const name) (r :: t :: ts)
      | annbexp_tr' _ _ = raise Match;

    fun assign_tr' (Abs (x, _, f $ k $ Bound 0) :: ts) =
          quote_tr' (Syntax.const @{syntax_const "_Assign"} $ Syntax_Trans.update_name_tr' f)
            (Abs (x, dummyT, Syntax_Trans.const_abs_tr' k) :: ts)
      | assign_tr' _ = raise Match;

    fun annassign_tr' (r :: Abs (x, _, f $ k $ Bound 0) :: ts) =

          quote_tr' (Syntax.const @{syntax_const "_AnnAssign"} $ r $ Syntax_Trans.update_name_tr' f)
            (Abs (x, dummyT, Syntax_Trans.const_abs_tr' k) :: ts)
      | annassign_tr' _ = raise Match;

  in
   [(@{const_syntax Collect}, K assert_tr'),
    (@{const_syntax Basic}, K assign_tr'),
    (@{const_syntax Cond}, K (bexp_tr' @{syntax_const "_Cond"})),
    (@{const_syntax While}, K (bexp_tr' @{syntax_const "_While_inv"})),
    (@{const_syntax AnnBasic}, K annassign_tr'),
    (@{const_syntax AnnWhile}, K (annbexp_tr' @{syntax_const "_AnnWhile"})),
    (@{const_syntax AnnAwait}, K (annbexp_tr' @{syntax_const "_AnnAwait"})),
    (@{const_syntax AnnCond1}, K (annbexp_tr' @{syntax_const "_AnnCond1"})),
    (@{const_syntax AnnCond2}, K (annbexp_tr' @{syntax_const "_AnnCond2"}))]
  end;
\<close>

end


theory UnionFind_Impl
imports  "../../Refine_Imperative_HOL/Sepref" UnionFind
begin

section "Union find Implementation"

subsection "MOP interface"

context
  fixes t ::  "nat \<Rightarrow> nat"
begin

  definition "mop_per_init n = SPECT [ per_init' n \<mapsto> enat (t n) ]"

  lemma progress_mop_per_init[progress_rules]: "t n > 0 \<Longrightarrow> progress (mop_per_init n)"
    unfolding mop_per_init_def by (auto intro!: progress_rules simp add:   zero_enat_def)

  lemma mop_per_init: "tt \<le> lst (SPECT [ per_init' n \<mapsto> t n]) Q \<Longrightarrow> tt
           \<le> lst (mop_per_init n) Q" unfolding mop_per_init_def by simp

  sepref_register "mop_per_init"
end

context
  fixes t ::  "('a \<times> 'a) set \<Rightarrow> nat"
begin

  definition "mop_per_compare R a b = SPECT [ per_compare R a b \<mapsto> enat (t R) ]"

  sepref_register "mop_per_compare"
end

context
  fixes t ::  "('a \<times> 'a) set \<Rightarrow> nat"
begin

  definition "mop_per_union R a b = SPECT [ per_union R a b \<mapsto> enat (t R) ]"

  sepref_register "mop_per_union"
end

subsection "Implementation Locale"

type_synonym uf = "nat array \<times> nat array"

locale UnionFind_Impl =
  fixes is_uf :: "(nat\<times>nat) set \<Rightarrow> uf \<Rightarrow> assn"
      and uf_init :: "nat \<Rightarrow> uf Heap"
      and uf_init_time :: "nat \<Rightarrow> nat"
      and uf_cmp :: "uf \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool Heap"
      and uf_cmp_time :: "nat \<Rightarrow> nat"
      and uf_union :: "uf \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> uf Heap"
      and uf_union_time :: "nat \<Rightarrow> nat"
    assumes
per_init'_sepref_rule[sepref_fr_rules]:  "\<And>t x' x. uf_init_time x' \<le> t x' \<Longrightarrow>
     hn_refine (hn_ctxt nat_assn x' x) (uf_init x)
         (hn_ctxt nat_assn x' x)
             is_uf (PR_CONST (mop_per_init t) $  x' )"

  and

per_compare_sepref_rule[sepref_fr_rules]:  "\<And>t R' R a' a b' b . uf_cmp_time (card (Domain R')) \<le> t R' \<Longrightarrow>
     hn_refine (hn_ctxt is_uf R' R * hn_ctxt nat_assn a' a * hn_ctxt nat_assn b' b) (uf_cmp R a b)
         (hn_ctxt is_uf R' R * hn_ctxt nat_assn a' a * hn_ctxt nat_assn b' b)
             bool_assn (PR_CONST (mop_per_compare t) $  R' $ a' $ b' )"

  and

per_union_sepref_rule[sepref_fr_rules]:  "\<And>t R' R a' a b' b . a' \<in> Domain R' \<Longrightarrow> b' \<in> Domain R'
  \<Longrightarrow> uf_union_time (card (Domain R')) \<le> t R' \<Longrightarrow>
     hn_refine (hn_ctxt is_uf R' R * hn_ctxt nat_assn a' a * hn_ctxt nat_assn b' b) (uf_union R a b)
         (hn_invalid is_uf R' R * hn_ctxt nat_assn a' a * hn_ctxt nat_assn b' b)
             is_uf (PR_CONST (mop_per_union t) $  R' $ a' $ b' )"

begin

thm per_init'_sepref_rule[to_hfref]
thm per_compare_sepref_rule[to_hfref]
thm per_union_sepref_rule[to_hfref]

end

end


           (*-------------------------------------------*
            |                   Test                    |
            |                                           |
            |        CSP-Prover on Isabelle2004         |
            |               August 2004                 |
            |             December 2004 (modified)      |
            |                                           |
            |        CSP-Prover on Isabelle2005         |
            |               November 2005  (modified)   |
            |                  April 2006  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2009         |
            |                   June 2009  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2016         |
            |                    May 2016  (modified)   |
            |                                           |
            |        Yoshinao Isobe (AIST JAPAN)        |
            *-------------------------------------------*)

theory Test_infinite
imports CSP_F_Main
begin

(*****************************************************************

         1. simple example for fixed point inductuction theorem
         2. Parallel, Hiding, Internal choice
         3. Refinement
         4.

 *****************************************************************)

(*********************************************************
                         event
 *********************************************************)

datatype Event = Num nat | Read nat
datatype SpcName = SPC nat
datatype ImpName = UI | VAR nat

(*********************************************************
            specification SPC and system IMP
 *********************************************************)

definition
  GTs :: "nat => nat set"
  where
  GTs_def : "GTs n == {m. n < m}"

(*** Spc ***)

primrec
  Spcfun :: "SpcName => (SpcName, Event) proc"
where
  "Spcfun   (SPC n) = Num n -> (!nat m:(GTs n) .. $(SPC m))"

overloading Set_Spcfun ==
  "PNfun :: (SpcName, Event) pnfun"
begin
(*  definition "PNfun (pn::SpcName) == Spcfun pn" *)
  definition "PNfun == Spcfun"
end

declare Set_Spcfun_def [simp]

(* Isabelle 2013
defs (overloaded)
Set_Spcfun_def [simp]: "PNfun == Spcfun"
*)

definition
  Spc :: "(SpcName, Event) proc"
  where
  Spc_def: "Spc == $(SPC 0)"

(*** Imp ***)

primrec
  Impfun :: "ImpName => (ImpName, Event) proc"
where
  "Impfun      (UI) = Read ? m -> Num m -> $UI"
 |"Impfun   (VAR n) = Read ! n -> $(VAR (Suc n))"

overloading Set_Impfun ==
  "PNfun :: (ImpName, Event) pnfun"
begin
(*  definition "PNfun (pn::ImpName) == Impfun pn" *)
  definition "PNfun == Impfun"
end

declare Set_Impfun_def [simp]

lemma "(PNfun::(ImpName, Event) pnfun) = Impfun"
by (simp)

(*
defs (overloaded)
Set_Impfun_def [simp]: "PNfun == Impfun"
*)

definition
  Imp :: "(ImpName, Event) proc"
  where
  Imp_def: "Imp == ($UI |[range Read]| $(VAR 0)) -- (range Read)"

(*********************************************************
            relation between SPC and IMP
 *********************************************************)

primrec
  Spc_to_Imp :: "SpcName => (ImpName, Event) proc"
where
  "Spc_to_Imp (SPC n) = ($UI |[range Read]| $(VAR n)) -- (range Read)"

(*********************************************************
                     small lemmas
 *********************************************************)

declare Int_commute [simp]

lemma set1[simp]: "range Read Int {(Read n)} = {(Read n)}"
by (auto)

lemma set2[simp]: "{(Read (Suc n))} Int (range Read Int {(Num n)}) Un
                    ({(Num n)} - range Read) = {(Num n)}"
by (auto)

lemma set3[simp]: "Num n ~: range Read"
by (simp add: image_def)

(*********************************************************
               guardedfun (rutine work)
 *********************************************************)

(*** To automatically unfold syntactic sugar ***)
declare csp_prefix_ss_def[simp]

lemma guardedfun_Spc_Imp[simp]:
      "guardedfun Spcfun"
      "guardedfun Impfun"
by (simp add: guardedfun_def, rule allI, induct_tac p, simp_all)+

declare inj_on_def[simp]

(*********************************************************
                   ? SPC <=F IMP ?
 *********************************************************)
(* Isabelle 2013
defs FPmode_def [simp]: "FPmode == CMSmode"
*)

overloading FPmode ==
  "FPmode :: fpmode"
begin
  definition "FPmode == CMSmode"
end

declare FPmode_def [simp]

(* it declares to use CMS approach.

   If you want to verify them by CPO approach,
   use the following mode:

defs FPmode_def [simp]: "FPmode == CPOmode"

   In this example, both modes are available,
   because Spcfun and Impfun are guarded.       *)

lemma "Spc <=F Imp"
apply (simp add: Spc_def Imp_def)

  (***** by fixed point induction *****)
apply (rule cspF_fp_induct_left[of _ "Spc_to_Imp"])

  (***** check guarded and no hiding operators *****)

apply (simp_all)
apply (simp)

  (***** by step laws (for transforming it to a hnf) *****)

apply (induct_tac p)
apply (cspF_unwind)
apply (cspF_hsf)+
apply (cspF_unwind)
apply (cspF_hsf)+
apply (auto)
apply (cspF_simp)+

  (***** instantiate a non-deterministic choice *****)

apply (rule cspF_Rep_int_choice_left)
apply (rule_tac  x="(Suc xa)" in exI)
apply (simp add: GTs_def)

apply (cspF_auto)+
done

end


theory Abstract_Rigorous_Numerics
imports
  "HOL-Library.Parallel"
  Transfer_Euclidean_Space_Vector
  "../Refinement/Enclosure_Operations"
  "../Refinement/Refine_Vector_List"
  "../Refinement/Refine_Hyperplane"
  "../Refinement/Refine_Interval"
  "../Refinement/Refine_Invar"
  "../Refinement/Refine_Unions"
  "../Refinement/Refine_Info"
begin

section \<open>misc\<close>

lemma length_listset: "xi \<in> listset xs \<Longrightarrow> length xi = length xs"
  by (induction xs arbitrary: xi) (auto simp: set_Cons_def)

lemma Nil_mem_listset[simp]: "[] \<in> listset list \<longleftrightarrow> list = []"
  by (induction list) (auto simp: set_Cons_def)

lemma sing_mem_listset_iff[simp]: "[b] \<in> listset ys \<longleftrightarrow> (\<exists>z. ys = [z] \<and> b \<in> z)"
  \<comment> \<open>TODO: generalize to Cons?\<close>
  by (cases ys) (auto simp: set_Cons_def)

no_notation (in autoref_syn) funcset (infixr "\<rightarrow>" 60)

definition cfuncset where "cfuncset l u X = funcset {l .. u} X \<inter> Collect (continuous_on {l .. u})"
lemma cfuncset_iff: "f \<in> cfuncset l u X \<longleftrightarrow> (\<forall>i\<in>{l .. u}. f i \<in> X) \<and> continuous_on {l .. u} f"
  unfolding cfuncset_def by auto

lemma cfuncset_continuous_onD: "f \<in> cfuncset 0 h X \<Longrightarrow> continuous_on {0..h} f"
  by (simp add: cfuncset_iff)

section \<open>Implementations\<close>

subsection \<open>locale for sets\<close>

definition "product_listset xs ys = (\<lambda>(x, y). x @ y) ` ((xs::real list set) \<times> (ys::real list set))"

abbreviation "rl_rel \<equiv> \<langle>rnv_rel\<rangle>list_rel"

abbreviation "slp_rel \<equiv> \<langle>Id::floatarith rel\<rangle>list_rel"
abbreviation "fas_rel \<equiv> \<langle>Id::floatarith rel\<rangle>list_rel"

type_synonym 'b reduce_argument = "'b list \<Rightarrow> nat \<Rightarrow> real list \<Rightarrow> bool" \<comment> \<open>is this too special?\<close>

record 'b numeric_options =
  precision :: nat
  adaptive_atol :: real
  adaptive_rtol :: real
  method_id :: nat
  start_stepsize :: real
  iterations :: nat
  halve_stepsizes :: nat
  widening_mod :: nat
  rk2_param :: real
  default_reduce :: "'b reduce_argument"
  printing_fun :: "bool \<Rightarrow> 'b list \<Rightarrow> unit"
  tracing_fun :: "string \<Rightarrow> 'b list option \<Rightarrow> unit"

record 'b reach_options =
  max_tdev_thres :: "real"
  pre_split_reduce :: "'b reduce_argument"
  pre_inter_granularity :: "real"
  post_inter_granularity :: "real"
  pre_collect_granularity :: real
  max_intersection_step :: real

definition "reach_options_rel TYPE('b) = (UNIV::('b reach_options \<times> unit) set)"
lemma sv_reach_options_rel[relator_props]: "single_valued (reach_options_rel TYPE('a))"
  by (auto simp: reach_options_rel_def single_valued_def)

definition "reduce_argument_rel TYPE('b) = (UNIV::('b reduce_argument \<times> unit) set)"
lemma sv_reduce_argument_rel[relator_props]: "single_valued (reduce_argument_rel TYPE('a))"
  by (auto simp: reduce_argument_rel_def single_valued_def)

definition [refine_vcg_def, simp]: "max_tdev_thres_spec (ro::unit) = SPEC (\<lambda>x::real. True)"
definition [refine_vcg_def, simp]: "max_intersection_step_spec (ro::unit) = SPEC (\<lambda>x::real. True)"
definition [refine_vcg_def, simp]: "pre_inter_granularity_spec (ro::unit) = SPEC (\<lambda>x::real. True)"
definition [refine_vcg_def, simp]: "post_inter_granularity_spec (ro::unit) = SPEC (\<lambda>x::real. True)"
definition [refine_vcg_def, simp]: "pre_collect_granularity_spec (ro::unit) = SPEC (\<lambda>x::real. True)"

lemma reach_optns_autoref[autoref_rules]:
  includes autoref_syntax
  shows
    "(\<lambda>x. RETURN (max_tdev_thres x), max_tdev_thres_spec) \<in> reach_options_rel TYPE('b) \<rightarrow> \<langle>rnv_rel\<rangle>nres_rel"
    "(\<lambda>x. RETURN (pre_inter_granularity x), pre_inter_granularity_spec) \<in> reach_options_rel TYPE('b)  \<rightarrow> \<langle>rnv_rel\<rangle>nres_rel"
    "(\<lambda>x. RETURN (post_inter_granularity x), post_inter_granularity_spec) \<in> reach_options_rel TYPE('b) \<rightarrow> \<langle>rnv_rel\<rangle>nres_rel"
    "(\<lambda>x. RETURN (pre_collect_granularity x), pre_collect_granularity_spec) \<in> reach_options_rel TYPE('b)  \<rightarrow> \<langle>rnv_rel\<rangle>nres_rel"
    "(\<lambda>x. RETURN (max_intersection_step x), max_intersection_step_spec) \<in> reach_options_rel TYPE('b)  \<rightarrow> \<langle>rnv_rel\<rangle>nres_rel"
  by (auto simp: nres_rel_def)

record 'b approximate_set_ops =
  appr_of_ivl::"real list \<Rightarrow> real list \<Rightarrow> 'b list"
  product_appr::"'b list \<Rightarrow> 'b list \<Rightarrow> 'b list"
  msum_appr::"'b list \<Rightarrow> 'b list \<Rightarrow> 'b list"
  inf_of_appr::"'b numeric_options \<Rightarrow> 'b list \<Rightarrow> real list"
  sup_of_appr::"'b numeric_options \<Rightarrow> 'b list \<Rightarrow> real list"
  split_appr::"nat \<Rightarrow> 'b list \<Rightarrow> 'b list \<times> 'b list"
  appr_inf_inner::"'b numeric_options \<Rightarrow> 'b list \<Rightarrow> real list \<Rightarrow> real"
  appr_sup_inner::"'b numeric_options \<Rightarrow> 'b list \<Rightarrow> real list \<Rightarrow> real"
  inter_appr_plane::"'b numeric_options \<Rightarrow> 'b list \<Rightarrow> real list sctn \<Rightarrow> 'b list dres"
  reduce_appr::"'b numeric_options \<Rightarrow> 'b reduce_argument \<Rightarrow> 'b list \<Rightarrow> 'b list"
  width_appr::"'b numeric_options \<Rightarrow> 'b list \<Rightarrow> real"
  approx_slp_dres::"'b numeric_options \<Rightarrow> nat \<Rightarrow> slp \<Rightarrow> 'b list \<Rightarrow> 'b list option dres"
  approx_euclarithform::"'b numeric_options \<Rightarrow> form \<Rightarrow> 'b list \<Rightarrow> bool dres"
  approx_isFDERIV::"'b numeric_options \<Rightarrow> nat \<Rightarrow> nat list \<Rightarrow> floatarith list \<Rightarrow> 'b list \<Rightarrow> bool dres"

primrec concat_appr where
  "concat_appr ops [] = []"
| "concat_appr ops (x#xs) = product_appr ops x (concat_appr ops xs)"

unbundle autoref_syntax

locale approximate_sets =
  fixes ops :: "'b approximate_set_ops"
    and set_of_appr::"'b list \<Rightarrow> real list set"
    and appr_rell :: "('b list \<times> real list set) set"
    and optns :: "'b numeric_options"
  assumes appr_rell_internal: "appr_rell \<equiv> br set_of_appr top"
  assumes transfer_operations_rl:
    "SIDE_PRECOND (list_all2 (\<le>) xrs yrs) \<Longrightarrow>
      (xri, xrs) \<in> \<langle>rnv_rel\<rangle>list_rel \<Longrightarrow>
      (yri, yrs) \<in> \<langle>rnv_rel\<rangle>list_rel \<Longrightarrow>
      (appr_of_ivl ops xri yri, lv_ivl $ xrs $ yrs) \<in> appr_rell"
    "(product_appr ops, product_listset) \<in> appr_rell \<rightarrow> appr_rell \<rightarrow> appr_rell"
    "(msum_appr ops, (\<lambda>xs ys. {List.map2 (+) x y |x y. x \<in> xs \<and> y \<in> ys})) \<in> appr_rell \<rightarrow> appr_rell \<rightarrow> appr_rell"
    "(xi, x) \<in> appr_rell \<Longrightarrow> length xi = d \<Longrightarrow>
      (RETURN (inf_of_appr ops optns xi), Inf_specs d x) \<in> \<langle>rl_rel\<rangle>nres_rel"
    "(xi, x) \<in> appr_rell \<Longrightarrow> length xi = d \<Longrightarrow>
      (RETURN (sup_of_appr ops optns xi), Sup_specs d x) \<in> \<langle>rl_rel\<rangle>nres_rel"
    "(ni, n) \<in> nat_rel \<Longrightarrow> (xi, x) \<in> appr_rell \<Longrightarrow> length xi = d \<Longrightarrow>
      (RETURN (split_appr ops ni xi), split_spec_params d n x) \<in> \<langle>appr_rell \<times>\<^sub>r appr_rell\<rangle>nres_rel"
    "(RETURN o2 appr_inf_inner ops optns, Inf_inners) \<in> appr_rell \<rightarrow> rl_rel \<rightarrow> \<langle>rnv_rel\<rangle>nres_rel"
    "(RETURN o2 appr_sup_inner ops optns, Sup_inners) \<in> appr_rell \<rightarrow> rl_rel \<rightarrow> \<langle>rnv_rel\<rangle>nres_rel"
    "(xi, x) \<in> appr_rell \<Longrightarrow> length xi = d \<Longrightarrow> length (normal si) = d \<Longrightarrow> d > 0 \<Longrightarrow> (si, s) \<in> \<langle>rl_rel\<rangle>sctn_rel \<Longrightarrow>
      (nres_of (inter_appr_plane ops optns xi si), inter_sctn_specs d x s) \<in> \<langle>appr_rell\<rangle>nres_rel"
    "(xi, x) \<in> appr_rell \<Longrightarrow> length xi = d \<Longrightarrow> (rai, ra) \<in> reduce_argument_rel TYPE('b) \<Longrightarrow>
      (RETURN (reduce_appr ops optns rai xi), reduce_specs d ra x) \<in> \<langle>appr_rell\<rangle>nres_rel"
    "(RETURN o width_appr ops optns, width_spec) \<in> appr_rell \<rightarrow> \<langle>rnv_rel\<rangle>nres_rel"
    "(nres_of o3 approx_slp_dres ops optns, approx_slp_spec fas) \<in> nat_rel \<rightarrow> slp_rel \<rightarrow> appr_rell \<rightarrow> \<langle>\<langle>appr_rell\<rangle>option_rel\<rangle>nres_rel"
assumes approx_euclarithform[unfolded comps, autoref_rules]:
  "(nres_of o2 approx_euclarithform ops optns, approx_form_spec) \<in> Id \<rightarrow> appr_rell \<rightarrow> \<langle>bool_rel\<rangle>nres_rel"
assumes approx_isFDERIV[unfolded comps, autoref_rules]:
  "(\<lambda>N xs fas vs. nres_of (approx_isFDERIV ops optns N xs fas vs), isFDERIV_spec) \<in>
  nat_rel \<rightarrow> \<langle>nat_rel\<rangle>list_rel \<rightarrow> \<langle>Id\<rangle>list_rel \<rightarrow>  appr_rell \<rightarrow> \<langle>bool_rel\<rangle>nres_rel"
assumes set_of_appr_nonempty[simp]: "set_of_appr X \<noteq> {}"
assumes length_set_of_appr: "xrs \<in> set_of_appr xs \<Longrightarrow> length xrs = length xs"
assumes set_of_appr_project: "xrs \<in> set_of_appr xs \<Longrightarrow> (\<And>i. i \<in> set is \<Longrightarrow> i < length xs) \<Longrightarrow>
    map ((!) xrs) is \<in> set_of_appr (map ((!) xs) is)"
assumes set_of_apprs_ex_Cons: "xrs \<in> set_of_appr xs \<Longrightarrow> \<exists>r. r#xrs \<in> set_of_appr (b#xs)"
assumes set_of_apprs_Nil[simp]: "xrs \<in> set_of_appr [] \<longleftrightarrow> xrs = []"
begin

abbreviation "reach_optns_rel \<equiv> reach_options_rel TYPE('b)"

definition "appr_rel = appr_rell O \<langle>lv_rel\<rangle>set_rel"
lemmas [autoref_rel_intf] = REL_INTFI[of appr_rel i_appr]

definition [simp]: "op_concat_listset xs = concat ` listset xs"

lemma [autoref_op_pat_def]: "concat ` listset xs \<equiv> OP op_concat_listset $ xs"
  by simp

lemma list_all2_replicate [simp]: "list_all2 (\<le>) xs xs" for xs::"'a::order list"
  by (auto simp: list_all2_iff in_set_zip)

lemma length_appr_of_ivl[simp]:
  "length (appr_of_ivl ops xs ys) = length xs"
  if "list_all2 (\<le>) xs ys"
  using transfer_operations_rl(1)[of xs ys xs ys] that
    apply (simp add: appr_rell_internal br_def lv_ivl_def)
  apply (auto simp: appr_rell_internal br_def list_all2_lengthD dest!: length_set_of_appr)
  using length_set_of_appr by fastforce

definition [simp]: "op_atLeastAtMost_appr = atLeastAtMost"

definition card_info::"_ set \<Rightarrow> nat nres" where [refine_vcg_def]: "card_info x = SPEC top" \<comment> \<open>\<open>op_set_wcard\<close>\<close>

definition [simp]: "set_of_coll X = X"

definition [simp]: "ivl_to_set X = X"

definition "ivls_of_sets X = do {
    XS \<leftarrow> (sets_of_coll (X:::clw_rel appr_rel) ::: \<langle>\<langle>appr_rel\<rangle>list_wset_rel\<rangle>nres_rel);
    FORWEAK XS (RETURN (op_empty_coll:::clw_rel lvivl_rel))
      (\<lambda>X. do {
        (i, s) \<leftarrow> op_ivl_rep_of_set X;
        RETURN (mk_coll (op_atLeastAtMost_ivl i s:::\<langle>lv_rel\<rangle>ivl_rel))
      })
      (\<lambda>a b. RETURN (a \<union> b))
  }"
sublocale autoref_op_pat_def ivls_of_sets .

definition "ivl_rep_of_set_coll X = do { Xs \<leftarrow> sets_of_coll (X:::clw_rel appr_rel); op_ivl_rep_of_sets Xs}"
sublocale autoref_op_pat_def ivl_rep_of_set_coll .

definition [simp]: "sets_of_ivls X = X"
sublocale autoref_op_pat_def sets_of_ivls .

definition "op_intersects X sctn = (do {
    ii \<leftarrow> Inf_inner X (normal sctn);
    si \<leftarrow> Sup_inner X (normal sctn);
    RETURN (ii \<le> pstn sctn \<and> si \<ge> pstn sctn)
  })"
sublocale autoref_op_pat_def op_intersects .

definition "sbelow_sctns_coll XS sctns = do {
    XS \<leftarrow> (sets_of_coll XS ::: \<langle>\<langle>appr_rel\<rangle>list_wset_rel\<rangle>nres_rel);
    FORWEAK XS (RETURN True) (\<lambda>X. sbelow_sctns X sctns) (\<lambda>a b. RETURN (a \<and> b))
  }"
sublocale autoref_op_pat_def sbelow_sctns_coll .

definition "below_sctn_coll XS sctn = do {
    XS \<leftarrow> (sets_of_coll XS ::: \<langle>\<langle>appr_rel\<rangle>list_wset_rel\<rangle>nres_rel);
    FORWEAK XS (RETURN True) (\<lambda>X. below_sctn X sctn) (\<lambda>a b. RETURN (a \<and> b))
  }"
sublocale autoref_op_pat_def below_sctn_coll .

definition "intersects_clw X sctn = (do {
    XS \<leftarrow> sets_of_coll (X:::clw_rel appr_rel);
    FORWEAK XS (RETURN False) (\<lambda>X. op_intersects X sctn) (\<lambda>a b. RETURN (a \<or> b))
  })"
sublocale autoref_op_pat_def intersects_clw .

definition "op_subset X ivl = do {
    (i', s') \<leftarrow> ((ivl_rep ((ivl))));
    (i, s) \<leftarrow> (op_ivl_rep_of_set ((X::'a::executable_euclidean_space set)));
    RETURN (((i' \<le> i):::bool_rel) \<and> ((s \<le> s'):::bool_rel))
  }"
sublocale autoref_op_pat_def op_subset .

definition [simp]: "subset_spec_coll X ivl = do {
    XS \<leftarrow> (sets_of_coll X:::\<langle>\<langle>appr_rel\<rangle>list_wset_rel\<rangle>nres_rel);
    FORWEAK XS (RETURN True)
      (\<lambda>X. op_subset X ivl)
      (\<lambda>x y. RETURN (x \<and> y))
  }"
sublocale autoref_op_pat_def subset_spec_coll .

definition "op_project_set X b y = inter_sctn_spec X (Sctn b y)"
sublocale autoref_op_pat_def op_project_set .

definition [simp]: "project_set_clw X b y = do {
    XS \<leftarrow> (sets_of_coll (X:::clw_rel appr_rel));
    FORWEAK XS (RETURN op_empty_coll) (\<lambda>X. do {
      P \<leftarrow> op_project_set X b y;
      RETURN (mk_coll P)
    }) (\<lambda>X Y. RETURN (Y \<union> X))
  }"
sublocale autoref_op_pat_def project_set_clw .

definition "subset_spec_ivls X Y = do {
    Ys \<leftarrow> sets_of_coll Y; FORWEAK Ys (RETURN False) (\<lambda>Y. op_subset X Y) (\<lambda>a b. RETURN (a \<or> b))
  }"
sublocale autoref_op_pat_def subset_spec_ivls .

definition "subset_spec_ivls_clw M X Y = do {
    X \<leftarrow> split_along_ivls M X Y;
    X \<leftarrow> sets_of_coll (sets_of_ivls X);
    FORWEAK X (RETURN True) (\<lambda>X. subset_spec_ivls X Y) (\<lambda>a b. RETURN (a \<and> b))
  }"
sublocale autoref_op_pat_def subset_spec_ivls_clw .

definition [simp]: "REMDUPS x = x"
sublocale autoref_op_pat_def REMDUPS .

definition "split_along_ivls2 M X Y = do {
    Xs \<leftarrow> sets_of_coll X;
    Rs \<leftarrow>FORWEAK Xs (RETURN op_empty_coll) (\<lambda>X. do {
      (I, N) \<leftarrow> split_intersecting Y (mk_coll X);
      split_along_ivls M (mk_coll X) I
    }) (\<lambda>x y. RETURN (y \<union> x));
    RETURN (REMDUPS Rs)
  }"
sublocale autoref_op_pat_def split_along_ivls2 .

definition [simp]: "op_list_of_eucl_image X = list_of_eucl ` X"
lemma [autoref_op_pat_def]: "list_of_eucl ` X \<equiv> OP op_list_of_eucl_image $ X" by simp

definition [simp]: "op_eucl_of_list_image X = (eucl_of_list ` X::'a::executable_euclidean_space set)"
lemma [autoref_op_pat_def]: "eucl_of_list ` X \<equiv> OP op_eucl_of_list_image $ X" by simp

definition [simp]: "op_take_image n X = take n ` X"
lemma [autoref_op_pat_def]: "take n ` X \<equiv> OP op_take_image $ n $ X" by simp

definition [simp]: "op_drop_image n X = drop n ` X"
lemma [autoref_op_pat_def]: "drop n ` X \<equiv> OP op_drop_image $ n $ X" by simp

definition "approx_slp_appr fas slp X = do {
    cfp \<leftarrow> approx_slp_spec fas DIM('a::executable_euclidean_space) slp X;
    (case cfp of
      Some cfp \<Rightarrow> do {
        RETURN ((eucl_of_list ` cfp::'a set):::appr_rel)
      }
      | None \<Rightarrow> do {
        SUCCEED
      }
    )
  }"
sublocale autoref_op_pat_def approx_slp_appr .

definition "mig_set D (X::'a::executable_euclidean_space set) = do {
    (i, s) \<leftarrow> op_ivl_rep_of_set (X:::appr_rel);
    let migc = mig_componentwise i s;
    ASSUME (D = DIM('a));
    let norm_fas = ([Norm (map floatarith.Var [0..<D])]:::\<langle>Id\<rangle>list_rel);
    let env = (list_of_eucl ` ({migc .. migc}:::appr_rel):::appr_rell);
    (n::real set) \<leftarrow> approx_slp_appr  norm_fas (slp_of_fas norm_fas) env;
    (ni::real) \<leftarrow> Inf_spec (n:::appr_rel);
    RETURN (rnv_of_lv ni::real)
  }"
sublocale autoref_op_pat_def mig_set .

lemma appr_rel_br: "appr_rel = br (\<lambda>xs. eucl_of_list ` (set_of_appr xs)::'a set) (\<lambda>xs. length xs = DIM('a::executable_euclidean_space))"
  unfolding appr_rel_def lv_rel_def set_rel_br
  unfolding appr_rell_internal br_chain o_def
  using length_set_of_appr
  by (auto dest!: brD intro: brI)

definition print_set::"bool \<Rightarrow> 'a set \<Rightarrow> unit" where "print_set _ _ = ()"

definition trace_set::"string\<Rightarrow>'a set option\<Rightarrow>unit" where "trace_set _ _ = ()"

definition print_msg::"string \<Rightarrow> unit" where "print_msg _ = ()"

abbreviation "CHECKs \<equiv> \<lambda>s. CHECK (\<lambda>_. print_msg s)"

definition "ncc (X::'a::executable_euclidean_space set) \<longleftrightarrow> X \<noteq> {} \<and> compact X \<and> convex X"

definition "ncc_precond TYPE('a::executable_euclidean_space) \<longleftrightarrow> (\<forall>(Xi, X::'a set) \<in> appr_rel. ncc X)"

end

lemma prod_relI': "\<lbrakk>(a,fst ab')\<in>R1; (b,snd ab')\<in>R2\<rbrakk> \<Longrightarrow> ((a,b),ab')\<in>\<langle>R1,R2\<rangle>prod_rel"
  by  (auto simp: prod_rel_def)

lemma lv_relivl_relI:
  "((xs', ys'), {eucl_of_list xs..eucl_of_list ys::'a::executable_euclidean_space}) \<in> \<langle>lv_rel\<rangle>ivl_rel"
  if [simp]: "xs' = xs" "ys' = ys" "DIM('a) = length xs" "length ys = length xs"
  by (force simp: ivl_rel_def set_of_ivl_def
      intro!:  brI lv_relI prod_relI[of _ "eucl_of_list xs" _ _ "eucl_of_list ys"])

end