theory flash89Rev imports flashPub
begin
section{*Main defintions*}
lemma NI_FAckVsInv89:
  (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_FAck ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -
  fix s

     have allCases:"formEval   (neg ( eqn ( IVar ( Global ''Dir_Dirty'') )  ( Const true )) )  s  \<or>formEval  ( eqn ( IVar ( Global ''Dir_Dirty'') )  ( Const true ))  s  "
	                      by auto

    moreover
                       {assume b1:"formEval  (neg ( eqn ( IVar ( Global ''Dir_Dirty'') )  ( Const true )) )  s"
have "?P2 s"

  apply(cut_tac  a1  a2  a3  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast
    }

    moreover
                       {assume b1:"formEval ( eqn ( IVar ( Global ''Dir_Dirty'') )  ( Const true ))  s"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''ShWbMsg_Cmd'') )  ( Const SHWB_FAck ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast
    }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_InvVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Inv  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_InvAck_1VsInv89:
    (*Rule2VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iInv2 \<le> N" and  a5:"iInv1~=iInv2  " and  a6:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_InvAck_1  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3 a4 a5 a6,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_InvAck_1_HomeVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_InvAck_1_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_InvAck_2VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_InvAck_2 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_GetX_GetXVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_GetX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_GetX_Nak1VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_GetX_Nak2VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_Nak2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_GetX_Nak3VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_Nak3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_GetX_PutX1VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX1 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX2VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX2 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX3VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX3 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX4VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX4 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX5VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX5 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX6VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX6 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX7VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX7 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX8VsInv89:
    (*Rule2VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iInv2 \<le> N" and  a5:"iInv1~=iInv2  " and  a6:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX8 N  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>iRule2=iInv2)   \<or>(iRule1=iInv1\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   \<or>(iRule1=iInv2\<and>iRule2=iInv1)   \<or>(iRule1=iInv2\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  a5  a6  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>iRule2=iInv2)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  a5  a6  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  a5  a6  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2\<and>iRule2=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

                  have "?P1 s \<or> ?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX8_homeVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX8_home N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX9VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX9 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX10VsInv89:
    (*Rule2VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iInv2 \<le> N" and  a5:"iInv1~=iInv2  " and  a6:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX10 N  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>iRule2=iInv2)   \<or>(iRule1=iInv1\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   \<or>(iRule1=iInv2\<and>iRule2=iInv1)   \<or>(iRule1=iInv2\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  a5  a6  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>iRule2=iInv2)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  a5  a6  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  a5  a6  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2\<and>iRule2=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

                  have "?P1 s \<or> ?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX10_homeVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX10_home N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_GetX_PutX11VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_GetX_PutX11 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_Get_GetVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_Get_Get  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_Get_Nak1VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_Get_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_Get_Nak2VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_Get_Nak2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_Get_Nak3VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_Get_Nak3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_Get_Put1VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_Get_Put1 N  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Local_Get_Put2VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_Get_Put2  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_Get_Put3VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_Get_Put3  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Local_PutVsInv89:
  (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_Put ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -
  fix s

      have "?P1 s"

        apply(cut_tac  a1  a2  a3 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Local_PutXAcksDoneVsInv89:
  (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Local_PutXAcksDone ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -
  fix s

      have "?P1 s"

        apply(cut_tac  a1  a2  a3 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_NakVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Nak  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_Nak_ClearVsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Nak_Clear ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Nak_HomeVsInv89:
  (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Nak_Home ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -
  fix s

      have "?P1 s"

        apply(cut_tac  a1  a2  a3 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma NI_Remote_GetX_NakVsInv89:
    (*Rule2VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iInv2 \<le> N" and  a5:"iInv1~=iInv2  " and  a6:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_GetX_Nak  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3 a4 a5 a6,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_GetX_Nak_HomeVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_GetX_Nak_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_GetX_PutXVsInv89:
    (*Rule2VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iInv2 \<le> N" and  a5:"iInv1~=iInv2  " and  a6:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_GetX_PutX  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>iRule2=iInv2)   \<or>(iRule1=iInv1\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   \<or>(iRule1=iInv2\<and>iRule2=iInv1)   \<or>(iRule1=iInv2\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  a5  a6  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>iRule2=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2\<and>iRule2=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

                  have "?P1 s \<or> ?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_GetX_PutX_HomeVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_GetX_PutX_Home  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_Get_Nak1VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_Get_Nak1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_Get_Nak2VsInv89:
    (*Rule2VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iInv2 \<le> N" and  a5:"iInv1~=iInv2  " and  a6:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_Get_Nak2  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3 a4 a5 a6,auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_Remote_Get_Put1VsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_Get_Put1  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_Get_Put2VsInv89:
    (*Rule2VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iRule2 \<le> N" and  a3:"iInv1 \<le> N" and  a4:"iInv2 \<le> N" and  a5:"iInv1~=iInv2  " and  a6:"iRule1~=iRule2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_Get_Put2  iRule1  iRule2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1\<and>iRule2=iInv2)   \<or>(iRule1=iInv1\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   \<or>(iRule1=iInv2\<and>iRule2=iInv1)   \<or>(iRule1=iInv2\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv1)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  a5  a6  , auto)
moreover
                {assume b1:"(iRule1=iInv1\<and>iRule2=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"(iRule1=iInv1\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2\<and>iRule2=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>iRule2=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 )\<and>(iRule2~=iInv1 \<and>iRule2~=iInv2 ))"

                  have "?P1 s \<or> ?P2 s"

  apply(cut_tac  a1  a2  a3  a4  a5  a6  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_PutVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_Put  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

                     have allCases:"formEval  ( eqn ( IVar ( Para ''InvMarked'' iInv2) )  ( Const true ))  s  \<or>formEval   (neg ( eqn ( IVar ( Para ''InvMarked'' iInv2) )  ( Const true )) )  s  "
	                      by auto

    moreover
                       {assume c1:"formEval ( eqn ( IVar ( Para ''InvMarked'' iInv2) )  ( Const true ))  s"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1  c1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }

    moreover
                       {assume c1:"formEval  (neg ( eqn ( IVar ( Para ''InvMarked'' iInv2) )  ( Const true )) )  s"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1  c1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast
    }
   ultimately have "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_Remote_PutXVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Remote_PutX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3  a4  b1 , simp)

        apply(rule_tac x=" (neg ( andForm ( andForm ( eqn ( IVar ( Global ''Dir_HeadPtr'') )   (Const iInv1))    ( eqn ( IVar ( Para ''UniMsg_Cmd'' iInv2) )  ( Const UNI_PutX ))  )    ( eqn ( IVar ( Para ''UniMsg_Cmd'' Home) )  ( Const UNI_Get ))  ) ) " in exI,auto)

        done

       then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma NI_ReplaceVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Replace  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_ReplaceHomeVsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_ReplaceHome ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_ReplaceHomeShrVldVsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_ReplaceHomeShrVld ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_ReplaceShrVldVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_ReplaceShrVld  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma NI_ShWbVsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_ShWb N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma NI_WbVsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (NI_Wb ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Local_GetX_GetX1VsInv89:
  (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_GetX_GetX1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -
  fix s

      have "?P1 s"

        apply(cut_tac  a1  a2  a3 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_GetX_GetX2VsInv89:
  (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_GetX_GetX2 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -
  fix s

      have "?P1 s"

        apply(cut_tac  a1  a2  a3 , auto)

        done

        then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

       by blast

 qed
lemma PI_Local_GetX_PutX1VsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_GetX_PutX1 N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Local_GetX_PutX2VsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_GetX_PutX2 N ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Local_GetX_PutX3VsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_GetX_PutX3 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Local_GetX_PutX4VsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_GetX_PutX4 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Local_Get_GetVsInv89:
  (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_Get_Get ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -
  fix s

      have "?P3 s"

        apply(   cut_tac  a1  a2  a3 , simp)

        apply(rule_tac x=" (neg ( andForm ( andForm ( eqn ( IVar ( Global ''Dir_HeadPtr'') )   (Const iInv1))    ( eqn ( IVar ( Global ''Dir_Pending'') )  ( Const false ))  )    ( eqn ( IVar ( Para ''CacheState'' iInv2) )  ( Const CACHE_E ))  ) ) " in exI,auto)

        done

       then  show "?P1 s\<or> ?P2 s\<or> ?P3 s"

        by blast

 qed
lemma PI_Local_Get_PutVsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_Get_Put ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Local_PutXVsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_PutX ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Local_ReplaceVsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Local_Replace ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  lemma PI_Remote_GetVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Remote_Get  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma PI_Remote_GetXVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Remote_GetX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma PI_Remote_PutXVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Remote_PutX  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have allCases:"(iRule1=iInv1)   \<or>(iRule1=iInv2)   \<or>((iRule1~=iInv1 \<and>iRule1~=iInv2 ))   "
	                      by( cut_tac  a1  a2  a3  a4  , auto)
moreover
                {assume b1:"(iRule1=iInv1)"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
moreover
                {assume b1:"(iRule1=iInv2)"

      have "?P1 s"

        apply(cut_tac  a1  a2  a3  a4  b1 , auto)

        done

        then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

       by blast

	                }
moreover
                {assume b1:"((iRule1~=iInv1 \<and>iRule1~=iInv2 ))"

                  have "?P2 s"

  apply(cut_tac  a1  a2  a3  a4  b1 , auto intro!:forallVars1 simp  add :invHoldForRule2'_def varsOfVar_def)

  done

  then  have "?P1 s\<or> ?P2 s \<or> ?P3 s"

        by blast

	                }
   ultimately show "?P1 s\<or> ?P2 s\<or> ?P3 s"

	                         by metis

 qed
lemma PI_Remote_ReplaceVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (PI_Remote_Replace  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma StoreVsInv89:
    (*Rule1VsPInv2*)
  assumes   a1:"iRule1 \<le> N" and  a2:"iInv1 \<le> N" and  a3:"iInv2 \<le> N" and  a4:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (Store  iRule1 ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

    by (cut_tac  a1  a2  a3  a4 , auto)
 lemma StoreHomeVsInv89:
    (*Rule0VsPInv2*)
  assumes   a1:"iInv1 \<le> N" and  a2:"iInv2 \<le> N" and  a3:"iInv1~=iInv2  "

  shows  "invHoldForRule' s (inv89  iInv1  iInv2 ) (StoreHome ) (invariants   N)" (is " ?P1 s\<or>?P2 s\<or>?P3 s")

  proof -

     have "?P2 s"

     by (cut_tac a1 a2 a3, auto  )
   then show "?P1 s\<or>?P2 s\<or>?P3 s"
      by auto
 qed
  end


theory List_Less
  imports
    "HOL-Library.List_Lexorder"
    "Isabelle_LLVM.LLVM_DS_Array_List"
    "../Setup"
    "../Separation_Logic_Solver/Methods"
    Arl_Ext
    "../Bool_Assn_Setup"
begin

partial_function (M) list_le'
  :: "(8 word, 'l::len2) array_list \<Rightarrow> (8 word, 'l) array_list \<Rightarrow> 'l word \<Rightarrow> 1 word llM"  where
  "list_le' xs ys i =
  doM {
    len_left \<leftarrow> arl_len xs;
    len_right \<leftarrow> arl_len ys;

    if i < len_right
    then if i < len_left
      then doM {
        x \<leftarrow> arl_nth xs i;
        y \<leftarrow> arl_nth ys i;
        le \<leftarrow> ll_icmp_ult x y;
        if le = 1
        then Mreturn ll_True
        else doM {
          ge \<leftarrow> ll_icmp_ult y x;
          if ge = 1
          then Mreturn ll_False
          else list_le' xs ys (i+1)
        }
      }
      else Mreturn ll_True
    else Mreturn ll_False
  }
"

abbreviation "string_assn str (stri:: (8 word, 'l::len2) array_list) \<equiv>
   \<up>(LENGTH('l) > 4) ** (EXS ws. \<upharpoonleft>arl_assn ws stri ** \<up>(length ws = length str) **
   \<up>(\<forall>i < length str. \<flat>\<^sub>punat.assn (str ! i) (ws ! i)))"

(*
abbreviation "string_assn str (stri:: (8 word, 'l::len2) array_list) \<equiv> arl_elem_assn snat.assn str stri"
*)

lemma postfix_le:
  "\<lbrakk>i < length xs; i < length ys\<rbrakk> \<Longrightarrow> drop i xs < drop i ys = (xs ! i < ys ! i \<or> xs ! i = ys ! i \<and> drop (i+1) xs < drop (i+1) ys)"
  by (auto simp add: drop_Suc_nth)

lemma arl_length_snat_bound:
  "pure_part (\<upharpoonleft>arl_assn xs (xsi :: ('a::llvm_rep, 'l::len2) array_list))
   \<Longrightarrow> length xs < 2 ^ (LENGTH('l)-1)"
  unfolding arl_assn_def dr_assn_prefix_def mk_assn_def
  unfolding arl_assn'_def mk_assn_def
  apply (cases xsi)
  apply simp
proof -
  fix li ci ai
  assume "pure_part (\<lambda>s. \<exists>c l a. (\<upharpoonleft>snat.assn l (li::'l word) \<and>*
                                    \<upharpoonleft>snat.assn c (ci::'l word) \<and>*
                                    \<upharpoonleft>narray_assn a ai \<and>*
                                    \<up>(4 < LENGTH('l) \<and> l \<le> c \<and> c = length a \<and> xs = take l a)) s)"

  then obtain c l a  where pp: "pure_part (\<upharpoonleft>snat.assn l li \<and>*
                                    \<upharpoonleft>snat.assn c ci \<and>*
                                    \<upharpoonleft>narray_assn a ai \<and>*
                                    \<up>(4 < LENGTH('l) \<and> l \<le> c \<and> c = length a \<and> xs = take l a))"
    unfolding pure_part_def
    by auto

  from pp have "xs = take l a"
    by (auto dest!: pure_part_split_conj)

  hence length_le: "length xs \<le> l" by simp

  from pp have "\<flat>\<^sub>psnat.assn l li"
    apply (auto dest!: pure_part_split_conj)
    by (simp add: snat.assn_def)
  hence "l \<in> snats LENGTH('l)"
    by (simp add: snat.assn_def)
  hence "l < 2 ^ (LENGTH('l)-1)"
    unfolding snats_def by blast

  with length_le show "length xs < 2 ^ (LENGTH('l) - Suc 0)"
    by simp
qed

lemma [simp]: "i < length xs \<Longrightarrow> [] < drop i xs" by simp

lemma list_le'_rule:
  "
  llvm_htriple
  (string_assn xs xsi ** string_assn ys ysi ** \<upharpoonleft>snat.assn i ii)
  (list_le' xsi ysi ii)
  (\<lambda>r. \<upharpoonleft>bool.assn (drop i xs < drop i ys) r ** string_assn xs xsi ** string_assn ys ysi )
"
proof(induction "min (length xs) (length ys) - i" arbitrary: i ii)
  case 0
  then show ?case
    apply (subst list_le'.simps)
    apply vcg
    subgoal by simp (*unreachable recursive path*)
     apply vcg
    done

next
  case (Suc x)
  from Suc(2) have precond: "x = min (length xs) (length ys) - (i+1)" by simp

  note Suc(1)[OF precond, vcg_rules]

  show ?case
    apply (subst list_le'.simps)
    apply vcg
    subgoal for asf x xa r ra s
      apply vcg_rl back
       apply vcg_compat
       apply (sep isep_intro: pure_pure_asm_prefixI | find_sep)+
        apply (auto simp add: SOLVE_AUTO_DEFER_def)
       apply vcg_solve
       apply vcg
       apply vcg_compat

       apply (sepE isep_intro: pure_pure_asm_prefixI | find_sep)+
             apply (auto simp add: postfix_le)
      apply vcg_solve
      apply vcg
      apply vcg_rl back
       apply vcg_compat
       apply (sepwith \<open>auto\<close> isep_intro: pure_pure_asm_prefixI)
      apply vcg_solve
      apply vcg
      apply vcg_rl
       apply vcg_compat
       apply (sepEwith simp isep_intro: pure_pure_asm_prefixI)
        apply simp_all
      subgoal
        unfolding dr_assn_pure_asm_prefix_def snat.assn_def snat_invar_def
        apply (rule conjI)
         apply simp_all
        by (smt (verit) Suc_eq_plus1 less_trans_Suc linorder_not_less msb_unat_big snat_eq_unat(1) unat_1 unat_plus_if' unsigned_less)
      apply isep_intro_ex
      apply (sepwith simp)
      apply vcg_solve+
      done
    subgoal by vcg
    subgoal by vcg
    done
qed

unbundle monad_syntax_M

partial_function (M) list_le''
  :: "(8 word, 'l::len2) array_list \<Rightarrow> (8 word, 'l) array_list \<Rightarrow> 'l word \<Rightarrow> 1 word llM"  where
  "list_le'' xs ys i =
  do {
    len_left \<leftarrow> arl_len xs;
    len_right \<leftarrow> arl_len ys;

    if i < len_right
    then if i < len_left
      then do {
        x \<leftarrow> arl_nth xs i;
        y \<leftarrow> arl_nth ys i;
        le \<leftarrow> ll_icmp_ult x y;
        if le = 1
        then return ll_True
        else do {
          ge \<leftarrow> ll_icmp_ult y x;
          if ge = 1
          then return ll_False
          else do {ip1 \<leftarrow> ll_add i 1; list_le'' xs ys ip1}
        }
      }
      else return ll_True
    else return ll_False
  }
"

lemmas list_le''.simps[llvm_code]

lemma list_le''_rule:
  "
  llvm_htriple
  (string_assn xs xsi ** string_assn ys ysi ** \<upharpoonleft>snat.assn i ii)
  (list_le'' xsi ysi ii)
  (\<lambda>r. \<upharpoonleft>bool.assn (drop i xs < drop i ys) r ** string_assn xs xsi ** string_assn ys ysi )
"
proof(induction "min (length xs) (length ys) - i" arbitrary: i ii)
  case 0
  then show ?case
    apply (subst list_le''.simps)
    apply vcg
    subgoal by simp (*unreachable recursive path*)
     apply vcg
    done
next
  case (Suc x)
  show ?case
    apply (subst list_le''.simps)
    apply vcg
    subgoal for asf x xa r ra s
      apply vcg_rl back
       apply vcg_compat
       apply (sep isep_intro: pure_pure_asm_prefixI | find_sep)+
        apply (auto simp add: SOLVE_AUTO_DEFER_def)
       apply vcg_solve
       apply vcg
       apply vcg_compat
       apply (sepE isep_intro: pure_pure_asm_prefixI | find_sep)+
             apply (auto simp add: postfix_le)
      apply vcg_solve
      apply vcg
      apply vcg_rl back
       apply vcg_compat
       apply (sepwith auto isep_intro: pure_pure_asm_prefixI)
      apply vcg_solve
      apply vcg
      supply Suc(1)[vcg_rules]
      apply vcg
      subgoal using Suc(2) by simp
      apply vcg
      done
    subgoal by vcg
    subgoal by vcg
    done
qed

definition "list_le xsi ysi \<equiv> list_le'' xsi ysi 0"

lemmas list_le_def[llvm_code, llvm_inline]

lemma list_le_rule:
  "
  llvm_htriple
  (string_assn xs xsi ** string_assn ys ysi)
  (list_le xsi ysi)
  (\<lambda>r. \<upharpoonleft>bool.assn (xs < ys) r ** string_assn xs xsi ** string_assn ys ysi )
"
  unfolding list_le_def
  supply list_le''_rule[vcg_rules]
  by vcg

end


theory PF_Predicates
  imports
  "../PF_Primitives"
  PF_Matching_Ternary
begin
fun all_match :: "('a \<Rightarrow> bool) \<Rightarrow> 'a match_expr  \<Rightarrow> bool" where
"all_match _ MatchAny = True" |
"all_match P (MatchNot m) = all_match P m" |
"all_match P (MatchAnd m1 m2) = (all_match P m1 \<and> all_match P m2)" |
"all_match P (Match m) = P m"

definition no_ipv6 :: "common_primitive match_expr \<Rightarrow> bool" where
"no_ipv6 mexpr =
all_match (\<lambda>m. (case m of
(Src (Hostspec (Address (IPv6 _)))) \<Rightarrow> False
| (Dst (Address (IPv6 _))) \<Rightarrow> False
| _ \<Rightarrow> True)) mexpr"

definition no_af :: "common_primitive match_expr \<Rightarrow> bool" where
"no_af mexpr = all_match (\<lambda>m. (case m of (Address_Family _) \<Rightarrow> False| _ \<Rightarrow> True)) mexpr"

definition no_anyhost :: "common_primitive match_expr \<Rightarrow> bool" where
"no_anyhost mexpr = all_match (\<lambda>m. (case m of (Src (Hostspec AnyHost)) \<Rightarrow> False
                                              | (Dst AnyHost) \<Rightarrow> False
                                              | _ \<Rightarrow> True)) mexpr"

definition good_match_expr :: "pfcontext \<Rightarrow> common_primitive match_expr \<Rightarrow> bool" where
"good_match_expr ctx mexpr = all_match (good_primitive ctx) mexpr"

fun all_AnchorRules_P :: "('a anchor_rule \<Rightarrow> bool) \<Rightarrow> 'a ruleset \<Rightarrow> bool" where
"all_AnchorRules_P P rs = (\<forall> l \<in> set rs. (case l of (Anchor r b) \<Rightarrow> P r \<and> all_AnchorRules_P P b | _ \<Rightarrow> True))"

fun all_AnchorRules_P' :: "('a anchor_rule \<Rightarrow> bool) \<Rightarrow> 'a ruleset \<Rightarrow> bool" where
"all_AnchorRules_P' _ [] \<longleftrightarrow> True" |
"all_AnchorRules_P' P ((PfRule r)#ls) \<longleftrightarrow> all_AnchorRules_P' P ls" |
"all_AnchorRules_P' P ((Anchor r b)#ls) \<longleftrightarrow> P r \<and> all_AnchorRules_P' P b \<and> all_AnchorRules_P' P ls"

lemma "all_AnchorRules_P P l= all_AnchorRules_P' P l"
  by (induction P l rule: all_AnchorRules_P'.induct) auto

lemma all_AnchorRules_P_append[simp]:
  "all_AnchorRules_P P (xs @ ys) \<longleftrightarrow> all_AnchorRules_P P xs \<and> all_AnchorRules_P P ys"
  by (induction P xs rule: all_AnchorRules_P.induct) auto

definition no_anchors' :: "'a ruleset \<Rightarrow> bool" where
"no_anchors' rs = all_AnchorRules_P (\<lambda>r. False) rs"

lemma no_anchors_no_anchors'_eq:
 "no_anchors rs \<longleftrightarrow> no_anchors' rs"
  unfolding no_anchors'_def
  by (induction rs) (auto split:line.splits)

definition no_unknown_anchors :: "('a,'p) match_tac \<Rightarrow> 'a ruleset \<Rightarrow> bool" where
"no_unknown_anchors \<gamma> rs = all_AnchorRules_P
 (\<lambda>r. (\<forall> p. ternary_ternary_eval (map_match_tac (fst \<gamma>) p (anchor_rule.get_match r)) \<noteq> TernaryUnknown))
 rs"

fun all_PfRules_P :: "('a pf_rule \<Rightarrow> bool) \<Rightarrow> 'a ruleset \<Rightarrow> bool" where
"all_PfRules_P P rs = (\<forall> l \<in> set rs. (case l of (PfRule r) \<Rightarrow> P r | (Anchor r b) \<Rightarrow> all_PfRules_P P b))"

fun all_PfRules_P' :: "('a pf_rule \<Rightarrow> bool) \<Rightarrow> 'a ruleset \<Rightarrow> bool" where
"all_PfRules_P' _ [] \<longleftrightarrow> True" |
"all_PfRules_P' P ((PfRule r)#ls) \<longleftrightarrow> P r \<and> all_PfRules_P' P ls" |
"all_PfRules_P' P ((Anchor r b)#ls) \<longleftrightarrow> all_PfRules_P' P b \<and> all_PfRules_P' P ls"

lemma "all_PfRules_P P l= all_PfRules_P' P l"
  by (induction P l rule: all_PfRules_P'.induct) auto

lemma all_PfRules_P_append[simp]:
  "all_PfRules_P P (xs @ ys) \<longleftrightarrow> all_PfRules_P P xs \<and> all_PfRules_P P ys"
  by (induction P xs rule: all_PfRules_P.induct) auto

definition no_match_quick :: "'a ruleset \<Rightarrow> bool" where
"no_match_quick rs = all_PfRules_P (\<lambda>r. \<not>((pf_rule.get_action r) = ActionMatch \<and> pf_rule.get_quick r)) rs"

definition wf_ruleset :: "pfcontext \<Rightarrow> common_primitive ruleset \<Rightarrow> bool" where
"wf_ruleset ctx rs = (all_PfRules_P (\<lambda>r. good_match_expr ctx (pf_rule.get_match r)) rs \<and> all_AnchorRules_P (\<lambda>a. good_match_expr ctx (anchor_rule.get_match a)) rs)"

lemma wf_ruleset_append[simp]:
"wf_ruleset ctx (xs @ ys) \<longleftrightarrow> wf_ruleset ctx xs \<and> wf_ruleset ctx ys"
  unfolding wf_ruleset_def
  using all_PfRules_P_append[of "(\<lambda>r. good_match_expr ctx (pf_rule.get_match r))" xs ys]
  all_AnchorRules_P_append[of "(\<lambda>r. good_match_expr ctx (anchor_rule.get_match r))" xs ys]
  by blast

definition no_tables :: "common_primitive match_expr \<Rightarrow> bool" where
"no_tables mexpr = all_match
                    (\<lambda>m. (case m of
                      (Src (Hostspec (Table _))) \<Rightarrow> False
                      |(Dst (Table _)) \<Rightarrow> False
                      | _ \<Rightarrow> True))
                    mexpr"

definition no_tables_rs :: "common_primitive ruleset \<Rightarrow> bool" where
"no_tables_rs = all_PfRules_P (\<lambda>r. no_tables (pf_rule.get_match r))"

definition normalized_ports :: "common_primitive match_expr \<Rightarrow> bool" where
"normalized_ports mexpr =
all_match
(\<lambda>m. (case m of
(Src_Ports (L4Ports _ (Binary bop))) \<Rightarrow> is_RangeIncl bop
| (Src_Ports (L4Ports _ (Unary _))) \<Rightarrow> False
| (Dst_Ports (L4Ports _ (Binary bop))) \<Rightarrow> is_RangeIncl bop
| (Dst_Ports (L4Ports _ (Unary _))) \<Rightarrow> False
| _ \<Rightarrow> True))
mexpr"

definition normalized_ports_rs :: "common_primitive ruleset \<Rightarrow> bool" where
"normalized_ports_rs = all_PfRules_P (\<lambda>r. normalized_ports (pf_rule.get_match r))"

definition no_ipv6_rs :: "common_primitive ruleset \<Rightarrow> bool" where
"no_ipv6_rs = all_PfRules_P (\<lambda>r. no_ipv6 (pf_rule.get_match r))"

definition no_af_rs :: "common_primitive ruleset \<Rightarrow> bool" where
"no_af_rs = all_PfRules_P (\<lambda>r. no_af (pf_rule.get_match r))"

definition no_anyhost_rs :: "common_primitive ruleset \<Rightarrow> bool" where
"no_anyhost_rs = all_PfRules_P (\<lambda>r. no_anyhost (pf_rule.get_match r))"

end


section \<open>Generic Block Allocator --- Resoning Setup\<close>
theory Sep_Block_Allocator_RS
imports Sep_Lift "../basic/LLVM_Basic_Main"
begin

  lemma list\<alpha>_at_len: "list\<alpha> \<alpha> xs (length xs) = 0"
    by (auto simp: list\<alpha>_def)

  lemma list\<alpha>_gt_len: "i\<ge>length xs \<Longrightarrow> list\<alpha> \<alpha> xs i = 0"
    by (auto simp: list\<alpha>_def)

  lemma list\<alpha>_snoc: "list\<alpha> \<alpha> (xs@[x]) = 0(length xs := \<alpha> x) + list\<alpha> \<alpha> xs"
    apply (rule ext)
    apply (auto simp: list\<alpha>_def nth_append)
    done

  lemma list\<alpha>_in_range: "list\<alpha> \<alpha> xs i \<noteq> 0 \<Longrightarrow> i<length xs"
    by (auto simp: list\<alpha>_def split: if_splits)

  lemma list\<alpha>_in_rangeD: "list\<alpha> \<alpha> xs = x \<Longrightarrow> x i \<noteq> 0 \<Longrightarrow> i<length xs"
    by (auto simp: list\<alpha>_def split: if_splits)

  lemma list\<alpha>_splitE:
    assumes "list\<alpha> \<alpha> xs = fun_upd 0 i p + fun_upd f i 0"
    assumes "p\<noteq>0"
    obtains "i<length xs" "\<alpha> (xs!i) = p"
    using assms
    by (auto simp: list\<alpha>_def fun_eq_iff split: if_splits)

  lemma option\<alpha>_splitE:
    assumes "option\<alpha> \<alpha> v = p"
    assumes "p\<noteq>0"
    obtains x where "v=Some x" "\<alpha> x = p"
    using assms by (cases v) auto

  locale block_allocator2 = block_allocator1 static_err mem_err bload bstore bcheck_addr
    for static_err :: 'err
    and mem_err :: 'err
    and bload :: "'baddr::this_addr \<Rightarrow> ('val,_,'block,'err) M"
    and bstore :: "'val \<Rightarrow> 'baddr \<Rightarrow> (unit,_,'block,'err) M"
    and bcheck_addr :: "'baddr \<Rightarrow> (unit,_,'block,'err) M"

  + fixes \<alpha>b :: "'block \<Rightarrow> 'ablock::unique_zero_sep_algebra"
      and bpto :: "'val \<Rightarrow> 'baddr \<Rightarrow> 'ablock \<Rightarrow> bool"
      and tag_of :: "'block \<Rightarrow> 'tag"
      and is_complete_tag :: "'ablock \<Rightarrow> 'tag \<Rightarrow> bool"

    assumes bload_rule: "\<And>x a. htriple \<alpha>b (bpto x a) (bload a) (\<lambda>r. \<up>(r=x) ** bpto x a)"
        and bstore_rule: "\<And>x xx a. htriple \<alpha>b (bpto xx a) (bstore x a) (\<lambda>_. bpto x a)"
        and bload_pres_tag: "\<And>s a. wlp (bload a) (\<lambda>_ s'. tag_of s' = tag_of s) s"
        and bstore_pres_tag: "\<And>s a x. wlp (bstore a x) (\<lambda>_ s'. tag_of s' = tag_of s) s"
        and complete_tag:
          "\<And>f. \<lbrakk>is_complete_tag ablock (tag_of cblock); ablock ## f; \<alpha>b cblock = ablock + f\<rbrakk> \<Longrightarrow> f=0"
        and bpto_notZ: "\<And>x a. \<not>bpto x a 0"
  begin

    definition \<alpha>tag :: "'block \<Rightarrow> 'tag tsa_opt" where "\<alpha>tag blk \<equiv> TRIV (tag_of blk)"
    definition \<alpha> :: "'block memory \<Rightarrow> nat \<Rightarrow> 'ablock \<times> 'tag tsa_opt"
      where "\<alpha> \<equiv> \<lambda>MEMORY blocks \<Rightarrow> list\<alpha> (option\<alpha> (\<lambda>x. (\<alpha>b x, \<alpha>tag x))) blocks"
    definition pto :: "'val \<Rightarrow> 'baddr addr rptr \<Rightarrow> (nat \<Rightarrow> 'ablock \<times> 'tag tsa_opt) \<Rightarrow> bool"
      where "pto x \<equiv> \<lambda>RP_ADDR (ADDR bi ba) \<Rightarrow> \<lambda>s. \<exists>ablk. s=0(bi:=(ablk,0)) \<and> bpto x ba ablk | _ \<Rightarrow> sep_false"

    definition tag :: "'tag \<Rightarrow> 'baddr addr rptr \<Rightarrow> (nat \<Rightarrow> 'ablock \<times> 'tag tsa_opt) \<Rightarrow> bool"
      where "tag t \<equiv> \<lambda>RP_ADDR (ADDR bi ba) \<Rightarrow> EXACT (0(bi:=(0,TRIV t))) ** \<up>(ba=this_addr \<and> t\<in>range tag_of) | _ \<Rightarrow> sep_false"
    definition block :: "'ablock \<Rightarrow> 'baddr addr rptr \<Rightarrow> (nat \<Rightarrow> 'ablock \<times> 'tag tsa_opt) \<Rightarrow> bool"
      where "block b \<equiv> \<lambda>RP_ADDR (ADDR bi ba) \<Rightarrow> EXACT (0(bi:=(b,0))) ** \<up>(ba=this_addr) | _ \<Rightarrow> sep_false"

    lemma alloc_rule: "htriple \<alpha> \<box> (alloc b) (\<lambda>r. block (\<alpha>b b) r ** tag (tag_of b) r)"
      apply (rule htripleI')
      apply (auto simp: alloc_def wp_def run_simps sep_algebra_simps split: option.splits)
    proof -
      fix s :: "'block memory"
      obtain blocks where [simp]: "s = MEMORY blocks" by (cases s)

      show "\<exists>p'. p' ## \<alpha> s \<and>
              \<alpha> (put' memory.the_memory\<^sub>L (get' memory.the_memory\<^sub>L s @ [Some b]) s) = p' + \<alpha> s \<and>
              (block (\<alpha>b b) (RP_ADDR (ADDR (length (get' memory.the_memory\<^sub>L s)) this_addr)) \<and>*
               tag (tag_of b) (RP_ADDR (ADDR (length (get' memory.the_memory\<^sub>L s)) this_addr)))
               p'"
        apply (rule exI[where x="0(length blocks := (\<alpha>b b, TRIV (tag_of b)))"]; intro conjI)
        apply (clarsimp_all simp: \<alpha>_def block_def tag_def \<alpha>tag_def sep_algebra_simps list\<alpha>_at_len)
        subgoal by (simp add: list\<alpha>_snoc)
        subgoal
          apply (subst EXACT_split[symmetric])
          apply (auto simp: sep_algebra_simps)
          done
        done
    qed

    lemma complete_splitE:
      assumes C: "is_complete_tag blk t"
      assumes DISJ: "f i ## (blk, TRIV t)"
      assumes AEQ: "list\<alpha> (option\<alpha> (\<lambda>x. (\<alpha>b x, \<alpha>tag x))) xs = f + fun_upd 0 i (blk, TRIV t)"
      obtains cblk where
        "i<length xs" "xs!i = Some cblk" "blk = \<alpha>b cblk" "t = tag_of cblk" "f i = 0"
    proof -
      have [simp]: "i<length xs"
        apply (rule list\<alpha>_in_rangeD[OF AEQ])
        apply (auto simp: sep_algebra_simps DISJ)
        done

      obtain fib fit where [simp]: "f i = (fib,fit)"  by (cases "f i")

      from DISJ have [simp]: "blk ## fib" "fit = 0"
        by (auto simp: sep_algebra_simps)

      obtain cblk where [simp]: "xs!i = Some cblk" "\<alpha>b cblk = blk + fib" "t = tag_of cblk"
        using fun_cong[OF AEQ, of i]
        apply (cases "xs!i")
        apply (auto simp: list\<alpha>_def sep_algebra_simps if_splits \<alpha>tag_def)
        done

      from complete_tag[OF C[simplified], of fib, simplified] have [simp]: "fib=0" .

      show ?thesis
        apply (rule that[of cblk])
        apply (auto simp: sep_algebra_simps)
        done
    qed

    lemma free_rule: "htriple \<alpha> (block blk a ** tag t a ** \<up>(is_complete_tag blk t)) (free a) (\<lambda>_. \<box>)"
      apply (rule htripleI')
      subgoal for p s f
        apply (cases s)
        apply (auto simp: free_def wp_def run_simps sep_algebra_simps split: option.splits addr.splits rptr.splits)
        apply (auto simp: block_def tag_def sep_algebra_simps pred_lift_extract_simps)
        apply (all \<open>subst (asm) EXACT_split[symmetric] sep_disj_fun_def; clarsimp simp: sep_algebra_simps\<close>)
        apply (auto simp: \<alpha>_def sep_algebra_simps merge_fun_singleton split_fun_upd_0)
        subgoal
          apply (erule (2) complete_splitE)
          by auto
        subgoal
          apply (erule (2) complete_splitE)
          by auto
        subgoal for xs i
          by (force simp: sep_algebra_simps dest: sep_disj_funD[where x=i] list\<alpha>_in_rangeD[where i=i])
        subgoal
          apply (erule (2) complete_splitE)
          by auto
        done
      done

    definition "block_lifter bi \<equiv> \<lparr>
      sep_lifter.lift = \<lambda>x. (0(bi:=(x,0))),
      sep_lifter.project = (\<lambda>f. fst (f bi)),
      sep_lifter.carve = (\<lambda>f. f(bi:=(0,snd (f bi)))),
      sep_lifter.splittable = (\<lambda>f. True),
      sep_lifter.L = lens_of_bi bi,
      sep_lifter.\<alpha>b = \<alpha>,
      sep_lifter.\<alpha>s = \<alpha>b,
      sep_lifter.tyb = \<lambda>_. (),
      sep_lifter.tys = tag_of
          \<rparr>"

    lemma block_lifter_simps[simp]:
      "sep_lifter.lift (block_lifter bi) = (\<lambda>x. (0(bi:=(x,0))))"
      "sep_lifter.project (block_lifter bi) = (\<lambda>f. fst (f bi))"
      "sep_lifter.carve (block_lifter bi) = (\<lambda>f. f(bi:=(0,snd (f bi))))"
      "sep_lifter.splittable (block_lifter bi) = (\<lambda>f. True)"
      "sep_lifter.L (block_lifter bi) = lens_of_bi bi"
      "sep_lifter.\<alpha>b (block_lifter bi) = \<alpha>"
      "sep_lifter.\<alpha>s (block_lifter bi) = \<alpha>b"
      "sep_lifter.tyb (block_lifter bi) = (\<lambda>_. ())"
      "sep_lifter.tys (block_lifter bi) = tag_of"
      unfolding block_lifter_def by auto

    sublocale block_lifter: sep_lifter "block_lifter bi"
    proof -

      have aux1[intro]: "a ## fst b \<Longrightarrow> b ## (a, 0)" for a b
        by (cases b) (auto simp: sep_algebra_simps )

      show "sep_lifter (block_lifter bi)"
        apply unfold_locales
        apply (auto simp: sep_algebra_simps sep_disj_funD[where x=bi])
        apply (auto
          simp: lens_of_bi_def \<alpha>_def list\<alpha>_def option\<alpha>_alt \<alpha>tag_def sep_algebra_simps
          split: memory.splits if_splits option.splits
          del: ext intro!: ext)
        done
    qed

    lemma pto_null_eq[simp]: "pto x RP_NULL = sep_false" by (auto simp: pto_def)

    lemma pto_addr_eq[simp]: "pto x (RP_ADDR (ADDR bi ba)) = block_lifter.lift_assn bi (bpto x ba)"
      unfolding pto_def block_lifter.lift_assn_def
      apply (rule ext)
      apply (auto simp: sep_algebra_simps)
      by (metis (no_types, hide_lams) fun_upd_same fun_upd_triv fun_upd_upd prod_Z_lower(1) surjective_pairing zero_fun_def)

    fun rptr_cases where "rptr_cases (RP_NULL) = ()" | "rptr_cases (RP_ADDR (ADDR _ _)) = ()"

    lemma load_rule: "htriple \<alpha> (pto x a) (load a) (\<lambda>r. \<up>(x=r) ** pto x a)"
      unfolding load_def
      apply (cases a rule: rptr_cases.cases; simp)
      apply (rule cons_post_rule)
      apply (rule block_lifter.lift_operation[simplified, OF _ _ bload_rule])
      apply (simp add: bpto_notZ)
      apply (rule bload_pres_tag)
      apply (auto simp: sep_algebra_simps pred_lift_extract_simps)
      done

    lemma store_rule: "htriple \<alpha> (pto xx a) (store x a) (\<lambda>_. pto x a)"
      unfolding store_def
      apply (cases a rule: rptr_cases.cases; simp)
      apply (rule cons_post_rule)
      apply (rule block_lifter.lift_operation[simplified, OF _ _ bstore_rule])
      apply (simp add: bpto_notZ)
      apply (rule bstore_pres_tag)
      apply (auto simp: sep_algebra_simps pred_lift_extract_simps)
      done

  end

subsection \<open>Address Arithmetic\<close>

  (*
    ptr ~ ptr :: bool   same base

    ptr - ptr :: int    if same base
    ptr + int :: ptr

    ~ is equivalence relation
    p ~ p
    p\<^sub>1 ~ p\<^sub>2 \<longleftrightarrow> p\<^sub>2 ~ p\<^sub>1
    p\<^sub>1~p\<^sub>2 \<and> p\<^sub>2~p\<^sub>3 \<longrightarrow> p\<^sub>1~p\<^sub>3

    p + i\<^sub>1 + i\<^sub>2 = p + (i\<^sub>1+i\<^sub>2)
    p + 0 = p
    p ~ p+i

    p\<^sub>1~p\<^sub>2 \<Longrightarrow> p\<^sub>2 + (p\<^sub>1-p\<^sub>2) = p\<^sub>1
  *)

  term "a+b"

  class addr_algebra =
    fixes abase :: "'a \<Rightarrow> bool"
      and acompat :: "'a \<Rightarrow> 'a \<Rightarrow> bool" (infix "~\<^sub>a" 50)
      and adiff :: "'a \<Rightarrow> 'a \<Rightarrow> int" (infix "-\<^sub>a" 65)
      and aidx :: "'a \<Rightarrow> int \<Rightarrow> 'a" (infixl "+\<^sub>a" 65)
    assumes
        \<comment> \<open>Compatibility is equivalence relation over base pointers\<close>
            acompat_equiv: "part_equivp acompat"
        and acompat_dom: "a\<^sub>1 ~\<^sub>a a\<^sub>2 \<Longrightarrow> abase a\<^sub>1 \<and> abase a\<^sub>2"

        \<comment> \<open>Indexing properties\<close>
        and aidx_Z[simp]: "a +\<^sub>a 0 = a" \<comment> \<open>Indexing by zero extended to non-base pointers\<close>
        and aidx_plus[simp]: "abase a \<Longrightarrow> a +\<^sub>a i\<^sub>1 +\<^sub>a i\<^sub>2 = a +\<^sub>a (i\<^sub>1 + i\<^sub>2)"
        and aidx_inj[simp]: "abase a \<Longrightarrow> a +\<^sub>a i = a +\<^sub>a j \<longleftrightarrow> i=j"
        (*and abase_idx[simp, intro!]: "abase a \<Longrightarrow> abase (a +\<^sub>a i)"*)
        and abase_idx[simp]: "abase (a +\<^sub>a i) \<longleftrightarrow> abase a"

        \<comment> \<open>Difference\<close>
        and adiff_same[simp]: "a -\<^sub>a a = 0" \<comment> \<open>Reflexive difference extended to non-base pointers\<close>
        and aidx_compat[simp]: "abase a \<Longrightarrow> a ~\<^sub>a a+\<^sub>ai"
        and adiff_idx[simp]: "a ~\<^sub>a b \<Longrightarrow> a +\<^sub>a (b -\<^sub>a a) = b"

  begin
    lemma acompat_trans[trans]: "a ~\<^sub>a b \<Longrightarrow> b ~\<^sub>a c \<Longrightarrow> a ~\<^sub>a c"
      using acompat_equiv by (meson part_equivp_transp)

    lemma acompat_sym[sym, intro]: "a ~\<^sub>a b \<Longrightarrow> b ~\<^sub>a a"
      using acompat_equiv by (meson part_equivp_symp)

    (*lemma acompat_sym_iff[simp]: "p~\<^sub>ap' \<longleftrightarrow> p'~\<^sub>ap"
      using acompat_sym by auto
    *)

    lemma acompat_refl[simp]: "a ~\<^sub>a a \<longleftrightarrow> abase a"
      using acompat_sym acompat_trans local.acompat_dom local.aidx_compat by blast

    lemma aidx_compat'[simp]:
      "abase b \<Longrightarrow> a ~\<^sub>a b +\<^sub>a i  \<longleftrightarrow> a ~\<^sub>a b"
      "abase a \<Longrightarrow> a +\<^sub>a i ~\<^sub>a b \<longleftrightarrow> a ~\<^sub>a b"
      using acompat_sym acompat_trans local.aidx_compat by blast+

    lemma diff_Z_iff_eq[simp]: "a\<^sub>1 ~\<^sub>a a\<^sub>2 \<Longrightarrow> a\<^sub>1 -\<^sub>a a\<^sub>2 = 0 \<longleftrightarrow> a\<^sub>1=a\<^sub>2"
      by (metis acompat_sym acompat_trans local.adiff_idx local.adiff_same)

    lemma diff_Z_iff_eq'[simp]: "a\<^sub>2 ~\<^sub>a a\<^sub>1 \<Longrightarrow> a\<^sub>1 -\<^sub>a a\<^sub>2 = 0 \<longleftrightarrow> a\<^sub>1=a\<^sub>2"
      by (metis acompat_sym acompat_trans local.adiff_idx local.adiff_same)

    lemma adiff_idx'[simp]: "b ~\<^sub>a a \<Longrightarrow> a +\<^sub>a (b -\<^sub>a a) = b"
      using acompat_sym local.adiff_idx by blast

    lemma idx_diff_distrib[simp]: "p~\<^sub>ap' \<Longrightarrow> (p+\<^sub>ai)-\<^sub>ap' = (p-\<^sub>ap')+i"
      by (metis acompat_dom adiff_idx' aidx_compat aidx_inj aidx_plus)
    lemma idx_diff_distrib'[simp]: "p'~\<^sub>ap \<Longrightarrow> (p+\<^sub>ai)-\<^sub>ap' = (p-\<^sub>ap')+i"
      by (metis acompat_dom adiff_idx' aidx_compat aidx_inj aidx_plus)

    lemma adiff_idx_idx[simp]:
      "p~\<^sub>ap' \<Longrightarrow> p +\<^sub>a (p' -\<^sub>a p + i) = p' +\<^sub>a i"
      "p'~\<^sub>ap \<Longrightarrow> p +\<^sub>a (p' -\<^sub>a p + i) = p' +\<^sub>a i"
      apply (metis acompat_dom adiff_idx aidx_plus)
      by (metis acompat_dom adiff_idx' aidx_plus)

    lemma acompat_dom'[simp, intro]:
      "p~\<^sub>ap' \<Longrightarrow> abase p"
      "p~\<^sub>ap' \<Longrightarrow> abase p'"
      apply (simp_all add: acompat_dom)
      done

  end

  instantiation rptr :: (addr_algebra) addr_algebra begin
    fun abase_rptr where "abase_rptr (RP_ADDR a) \<longleftrightarrow> abase a" | "abase_rptr RP_NULL \<longleftrightarrow> False"

    lemma abase_rptr_alt: "abase p \<longleftrightarrow> (case p of (RP_ADDR a) \<Rightarrow> abase a | RP_NULL \<Rightarrow> False)"
      by (cases p; simp)

    fun acompat_rptr where
      "acompat_rptr (RP_ADDR a\<^sub>1) (RP_ADDR a\<^sub>2) \<longleftrightarrow> a\<^sub>1 ~\<^sub>a a\<^sub>2"
    | "acompat_rptr _ _ \<longleftrightarrow> False"

    lemma acompat_rptr_alt: "p\<^sub>1 ~\<^sub>a p\<^sub>2 \<longleftrightarrow> (case (p\<^sub>1,p\<^sub>2) of (RP_ADDR a\<^sub>1, RP_ADDR a\<^sub>2) \<Rightarrow> a\<^sub>1 ~\<^sub>a a\<^sub>2 | _ \<Rightarrow> False)"
      by (cases p\<^sub>1; cases p\<^sub>2; simp)

    fun adiff_rptr where
      "adiff_rptr (RP_ADDR a\<^sub>1) (RP_ADDR a\<^sub>2) = (a\<^sub>1 -\<^sub>a a\<^sub>2)"
    | "adiff_rptr (RP_NULL) (RP_NULL) = 0"
    | "adiff_rptr _ _ = undefined"

    lemma adiff_rptr_alt: "p\<^sub>1 -\<^sub>a p\<^sub>2 = (case (p\<^sub>1,p\<^sub>2) of (RP_ADDR a\<^sub>1, RP_ADDR a\<^sub>2) \<Rightarrow> a\<^sub>1 -\<^sub>a a\<^sub>2 | (RP_NULL,RP_NULL) \<Rightarrow> 0 | _ \<Rightarrow> undefined)"
      by (cases p\<^sub>1; cases p\<^sub>2; simp)

    fun aidx_rptr where
      "aidx_rptr (RP_ADDR a) i = RP_ADDR (a +\<^sub>a i)"
    | "aidx_rptr RP_NULL _ = RP_NULL"

    lemma aidx_rptr_alt: "p\<^sub>1 +\<^sub>a i = (case p\<^sub>1 of RP_ADDR a\<^sub>1 \<Rightarrow> RP_ADDR (a\<^sub>1 +\<^sub>a i) | _ \<Rightarrow> RP_NULL)"
      by (cases p\<^sub>1; simp)

    lemma ptr_neq_null_conv: "p\<noteq>RP_NULL \<longleftrightarrow> (\<exists>a. p=RP_ADDR a)" by (cases p) (auto)

    instance
      apply standard
      apply (intro part_equivpI sympI transpI)
      apply (meson acompat_equiv acompat_rptr.simps(1) part_equivp_def)
      apply (auto
        simp: acompat_rptr_alt aidx_rptr_alt adiff_rptr_alt acompat_dom
        split: rptr.splits
        intro!: sympI transpI reflpI
        intro: acompat_sym acompat_trans)
      done

  end

  fun rptr_the_block_index where
    "rptr_the_block_index (RP_ADDR (ADDR bi _)) = bi" | "rptr_the_block_index _ = undefined"

  instantiation addr :: (addr_algebra) addr_algebra begin
    fun abase_addr where "abase_addr (ADDR bi ba) \<longleftrightarrow> abase ba"
    fun acompat_addr where "ADDR bi\<^sub>1 ba\<^sub>1 ~\<^sub>a ADDR bi\<^sub>2 ba\<^sub>2 \<longleftrightarrow> bi\<^sub>1=bi\<^sub>2 \<and> ba\<^sub>1~\<^sub>aba\<^sub>2"
    fun aidx_addr where "ADDR bi ba +\<^sub>a i = ADDR bi (ba +\<^sub>a i)"
    fun adiff_addr where "ADDR bi\<^sub>1 ba\<^sub>1 -\<^sub>a ADDR bi\<^sub>2 ba\<^sub>2 = ba\<^sub>1 -\<^sub>a ba\<^sub>2"

    lemma abase_addr_alt: "abase = (\<lambda>(ADDR bi ba) \<Rightarrow> abase ba)" by (intro ext) (auto split: addr.splits)
    lemma acomp_addr_alt: "(~\<^sub>a) = (\<lambda>ADDR bi\<^sub>1 ba\<^sub>1 \<Rightarrow> \<lambda>ADDR bi\<^sub>2 ba\<^sub>2 \<Rightarrow> bi\<^sub>1=bi\<^sub>2 \<and> ba\<^sub>1~\<^sub>aba\<^sub>2)" by (intro ext) (auto split: addr.splits)
    lemma aidx_addr_alt: "(+\<^sub>a) = (\<lambda>ADDR bi ba \<Rightarrow> \<lambda>i. ADDR bi (ba +\<^sub>a i))" by (intro ext) (auto split: addr.splits)
    lemma adiff_addr_alt: "(-\<^sub>a) = (\<lambda>ADDR bi\<^sub>1 ba\<^sub>1 \<Rightarrow> \<lambda>ADDR bi\<^sub>2 ba\<^sub>2 \<Rightarrow> ba\<^sub>1 -\<^sub>a ba\<^sub>2)" by (intro ext) (auto split: addr.splits)

    instance
      apply standard
      apply (intro part_equivpI sympI transpI)
      apply (meson acompat_equiv acompat_addr.simps(1) part_equivp_def)
      apply (auto
        simp: abase_addr_alt acomp_addr_alt aidx_addr_alt adiff_addr_alt acompat_dom
        split: addr.splits
        intro: acompat_sym acompat_trans)
      done

  end

end


(*
 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: GPL-2.0-only
 *)

theory Noninterference_Base_Refinement
imports Noninterference_Base
        Noninterference_Base_Alternatives
begin

(* we assume the same initial state for both systems *)
locale noninterference_refinement =
   abs?: complete_unwinding_system A s0 dom uwr policy out schedDomain +
   conc?: noninterference_system C s0 dom uwr policy out schedDomain
   for A :: "('a,'s,'e) data_type"
   and s0 :: "'s"
   and dom :: "'e \<Rightarrow> 's \<Rightarrow> 'd"
   and uwr :: "'d \<Rightarrow> ('s \<times> 's) set"
   and policy :: "('d \<times> 'd) set"
   and out :: "'d \<Rightarrow> 's \<Rightarrow> 'p"
   and schedDomain :: "'d"
   and C :: "('c,'s,'e) data_type" +
   assumes refines: "refines C A"

context noninterference_refinement begin

lemma reachable:
  "conc.reachable s \<Longrightarrow> abs.reachable s"
  apply(simp add: conc.reachable_def abs.reachable_def)
  using refines by (fastforce simp: refines_def)

lemma Step:
  "conc.Step a \<subseteq> abs.Step a"
  apply(simp add: conc.Step_def abs.Step_def)
  using refines by(fastforce simp: refines_def)

lemma confidentiality_u_refinement_closed:
  "abs.confidentiality_u \<Longrightarrow> conc.confidentiality_u"
  apply(simp add: abs.confidentiality_u_def)
  apply(subst conc.confidentiality_u_def)
  apply(blast intro: subsetD[OF Step] reachable)
  done

lemma confidentiality_u_weak_refinement_closed:
  "abs.confidentiality_u_weak \<Longrightarrow> conc.confidentiality_u_weak"
  apply(simp add: abs.confidentiality_u_weak_def)
  apply(subst conc.confidentiality_u_weak_def)
  apply(blast intro: subsetD[OF Step] reachable)
  done

lemma integrity_u_refinement_closed:
  "abs.integrity_u \<Longrightarrow> conc.integrity_u"
  apply(simp add: abs.integrity_u_def)
  apply(subst conc.integrity_u_def)
  apply(blast intro: subsetD[OF Step] reachable)
  done

lemma xources_subset:
  "abs.confidentiality_u \<Longrightarrow> abs.xources as s u \<subseteq> conc.xources as s u"
  apply(induct as arbitrary: s u)
   apply(simp add: abs.xources.xources_Nil conc.xources.xources_Nil)
  apply(simp add: abs.xources.xources_Cons conc.xources.xources_Cons)
  apply(rule conjI)
   apply(rule subsetI)
   apply(rule UnI1)
   apply(blast dest: subsetD[OF Step])
  apply(rule subsetI)
  apply(rule UnI2)
  apply(blast dest: subsetD[OF Step])
  done

lemma uwr_equiv:
  "abs.uwr_equiv s as t bs u \<Longrightarrow> conc.uwr_equiv s as t bs u"
  apply(insert refines)
  apply(fastforce simp: abs.uwr_equiv_def conc.uwr_equiv_def simp: refines_def dest: subsetD)
  done

lemma xNonleakage_gen_refinement_closed:
  "abs.xNonleakage_gen \<Longrightarrow> conc.xNonleakage_gen"
  apply(frule abs.xNonleakage_gen_confidentiality_u)
  apply(frule xources_subset)
  apply(clarsimp simp: abs.xNonleakage_gen_def conc.xNonleakage_gen_def)
  apply(drule (1) sameFor_subset_dom[OF _ xources_subset])
  apply(blast dest: reachable uwr_equiv)
  done

end

locale complete_noninterference_refinement = noninterference_refinement A s0 dom uwr policy out schedDomain C
   for A :: "('a,'s,'e) data_type"
   and s0 :: "'s"
   and dom :: "'e \<Rightarrow> 's \<Rightarrow> 'd"
   and uwr :: "'d \<Rightarrow> ('s \<times> 's) set"
   and policy :: "('d \<times> 'd) set"
   and out :: "'d \<Rightarrow> 's \<Rightarrow> 'p"
   and schedDomain :: "'d"
   and C :: "('c,'s,'e) data_type" +
   assumes Step_C: "Step_system C s0"

sublocale complete_noninterference_refinement \<subseteq> conc: complete_unwinding_system C s0 dom uwr policy out schedDomain
  apply(unfold_locales)
    using Step_C apply(fastforce simp: Step_system_def)
   using Step_C apply(fastforce simp: Step_system_def)
  apply(rule policy_refl)
  done

context complete_noninterference_refinement begin
lemma Noninfluence_strong_uwr_refinement_closed:
  "abs.Noninfluence_strong_uwr \<Longrightarrow>
    conc.Noninfluence_strong_uwr"
  apply(frule abs.Noninfluence_strong_uwr_confidentiality_u_weak)
  apply(drule abs.Noninfluence_strong_uwr_integrity_u)
  apply(drule confidentiality_u_weak_refinement_closed)
  apply(drule integrity_u_refinement_closed)
  apply(blast intro: conc.Noninfluence_strong_uwr)
  done

lemma Nonleakage_gen_refinement_closed:
  "abs.Nonleakage_gen \<Longrightarrow>
    conc.Nonleakage_gen"
  apply(simp add: abs.Nonleakage_gen_equiv_confidentiality_u conc.Nonleakage_gen_equiv_confidentiality_u)
  apply(erule confidentiality_u_refinement_closed)
  done

lemma Noninfluence_strong_quasi_refinement_closed:
  "\<lbrakk>abs.confidentiality_u_weak; abs.integrity_u;
        output_consistent\<rbrakk> \<Longrightarrow>
    conc.Noninfluence_strong"
  apply(rule conc.Noninfluence_strong)
    apply(erule confidentiality_u_weak_refinement_closed)
   apply assumption
  apply(erule integrity_u_refinement_closed)
  done

lemma Noninfluence_strong_uwr_quasi_refinement_closed:
  "\<lbrakk>abs.Noninfluence_strong_uwr;
        output_consistent\<rbrakk> \<Longrightarrow>
    conc.Noninfluence_strong"
  apply(rule conc.Noninfluence_strong)
    apply(rule confidentiality_u_weak_refinement_closed)
    apply(erule abs.Noninfluence_strong_uwr_confidentiality_u_weak)
   apply assumption
  apply(rule integrity_u_refinement_closed)
  apply(erule abs.Noninfluence_strong_uwr_integrity_u)
  done

end
end