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

(*header{*The n_german Protocol Case Study*}*)

theory n_german_on_inis imports n_german_on_ini
begin
lemma on_inis:
  assumes b1: "f \<in> (invariants N)" and b2: "ini \<in> {andList (allInitSpecs N)}" and b3: "formEval ini s"
  shows "formEval f s"
  proof -
  have c1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__1  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2)\<or>
    (f=inv__3  )\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__4  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__5  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__6  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__7  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__8  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__9  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__10  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__11  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__12  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__13  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__14  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__15  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__16  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__17  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__18  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__19  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__20  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__21  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__22  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv1 p__Inv2. p__Inv0\<le>N\<and>p__Inv1\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv1\<and>p__Inv0~=p__Inv2\<and>p__Inv1~=p__Inv2\<and>f=inv__23  p__Inv0 p__Inv1 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__25  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__26  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__27  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__28  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__29  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__30  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__31  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__32  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__33  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__34  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__35  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__36  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__37  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__38  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__39  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__40  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__41  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__42  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__43  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__44  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__45  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__46  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__47  p__Inv2)\<or>
    (\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__48  p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__49  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__50  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__51  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__52  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__53  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__54  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__55  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__56  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__57  p__Inv0 p__Inv2)\<or>
    (\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__58  p__Inv0 p__Inv2)"
  apply (cut_tac b1, simp) done
    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__1  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__1)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__2  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__2)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(f=inv__3  )"
      have "formEval f s"
      apply (rule iniImply_inv__3)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__4  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__4)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__5  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__5)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__6  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__6)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__7  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__7)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__8  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__8)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__9  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__9)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__10  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__10)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__11  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__11)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__12  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__12)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__13  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__13)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__14  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__14)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__15  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__15)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__16  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__16)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__17  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__17)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__18  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__18)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__19  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__19)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__20  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__20)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__21  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__21)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__22  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__22)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv1 p__Inv2. p__Inv0\<le>N\<and>p__Inv1\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv1\<and>p__Inv0~=p__Inv2\<and>p__Inv1~=p__Inv2\<and>f=inv__23  p__Inv0 p__Inv1 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__23)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__24  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__24)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__25  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__25)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__26  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__26)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__27  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__27)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__28  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__28)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__29  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__29)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__30  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__30)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__31  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__31)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__32  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__32)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__33  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__33)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__34  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__34)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__35  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__35)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__36  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__36)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__37  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__37)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__38  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__38)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__39  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__39)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__40  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__40)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__41  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__41)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__42  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__42)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__43  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__43)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__44  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__44)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__45  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__45)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__46  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__46)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__47  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__47)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__48  p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__48)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__49  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__49)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__50  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__50)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__51  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__51)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__52  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__52)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__53  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__53)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__54  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__54)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__55  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__55)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__56  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__56)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__57  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__57)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

    moreover {
      assume d1: "(\<exists> p__Inv0 p__Inv2. p__Inv0\<le>N\<and>p__Inv2\<le>N\<and>p__Inv0~=p__Inv2\<and>f=inv__58  p__Inv0 p__Inv2)"
      have "formEval f s"
      apply (rule iniImply_inv__58)
      apply (cut_tac d1, assumption)
      apply (cut_tac b2 b3, blast) done
    }

  ultimately show "formEval f s"
  by satx
qed

end


theory SuperNormEnv
  imports WTLemma
begin

definition super_norm_use_env where
  "super_norm_use_env r_s r_x = (\<lambda> x. if r_s x = OwnPerm \<and> r_x x = NoPerm then NoPerm else r_s x)"

lemma self_snorm_leq_use_env: "leq_use_env (super_norm_use_env r_s r_x) r_s"
  apply (simp add: leq_use_env_def)
  apply (simp add: super_norm_use_env_def)
  apply (auto)
   apply (case_tac "r_s x")
     apply (auto)
  apply (case_tac "r_s x")
    apply (auto)
  done

lemma rhs_snorm_leq_use_env: "\<lbrakk> leq_use_env r_x r_s; leq_use_env r_x r_ex \<rbrakk> \<Longrightarrow> leq_use_env r_x (super_norm_use_env r_s r_ex)"
  apply (simp add: leq_use_env_def)
  apply (simp add: super_norm_use_env_def)
  apply (auto)
  apply (erule_tac x="x" in allE)
  apply (erule_tac x="x" in allE)
  apply (case_tac "r_s x")
    apply (auto)
  done

lemma rhs_snorm_leq_use_env2: "\<lbrakk> leq_use_env r_x r_ex; leq_use_env r_ex r_s \<rbrakk> \<Longrightarrow> leq_use_env r_x (super_norm_use_env r_s r_ex)"
  apply (rule_tac rhs_snorm_leq_use_env)
   apply (rule_tac r_sb="r_ex" in trans_leq_use_env)
    apply (auto)
  done

lemma diff_snorm_leq_use_env: "\<lbrakk> leq_use_env r_ex r_s; leq_use_env r_x (diff_use_env r_s r_ex) \<rbrakk> \<Longrightarrow> leq_use_env (super_norm_use_env r_s r_x) (diff_use_env r_s r_ex)"
  apply (simp add: leq_use_env_def)
  apply (simp add: diff_use_env_def)
  apply (simp add: minus_use_env_def)
  apply (simp add: neg_use_env_def)
  apply (auto)
  apply (erule_tac x="x" in allE)
  apply (erule_tac x="x" in allE)
  apply (simp add: super_norm_use_env_def)
  apply (auto)
  apply (case_tac "r_s x")
    apply (auto)
   apply (case_tac "r_ex x")
     apply (auto)
  apply (case_tac "r_s x")
    apply (auto)
   apply (case_tac "r_ex x")
     apply (auto)
  apply (case_tac "r_ex x")
    apply (auto)
  apply (case_tac "r_x x")
    apply (auto)
  done

lemma dist_diff_snorm_leq_use_env: "\<lbrakk> leq_use_env r_ex r_s; leq_use_env r_xb (diff_use_env r_xa r_ex) \<rbrakk> \<Longrightarrow>
  leq_use_env (super_norm_use_env r_s r_xb) (diff_use_env (super_norm_use_env r_s r_xa) r_ex)"
  apply (simp add: leq_use_env_def)
  apply (simp add: diff_use_env_def)
  apply (simp add: minus_use_env_def)
  apply (simp add: neg_use_env_def)
  apply (auto)
  apply (erule_tac x="x" in allE)
  apply (erule_tac x="x" in allE)
  apply (simp add: super_norm_use_env_def)
  apply (auto)
      apply (case_tac "r_xb x")
        apply (auto)
     apply (case_tac "r_s x")
       apply (auto)
     apply (case_tac "r_ex x")
       apply (auto)
    apply (case_tac "r_s x")
      apply (auto)
    apply (case_tac "r_ex x")
      apply (auto)
   apply (case_tac "r_s x")
     apply (auto)
   apply (case_tac "r_ex x")
     apply (auto)
  apply (case_tac "r_s x")
    apply (auto)
   apply (case_tac "r_ex x")
     apply (auto)
  apply (case_tac "r_ex x")
    apply (auto)
  apply (case_tac "r_xb x")
    apply (auto)
   apply (case_tac "r_xa x")
     apply (auto)
  apply (case_tac "r_xa x")
    apply (auto)
  done

lemma dist_snorm_leq_use_env: "\<lbrakk> leq_use_env r_ex r_exa; leq_use_env r_ex r_exb \<rbrakk> \<Longrightarrow> leq_use_env (super_norm_use_env r_s r_ex) (super_norm_use_env (super_norm_use_env r_s r_exa) r_exb)"
  apply (simp add: leq_use_env_def)
  apply (auto)
  apply (erule_tac x="x" in allE)
  apply (erule_tac x="x" in allE)
  apply (simp add: super_norm_use_env_def)
  apply (auto)
    apply (case_tac "r_ex x")
      apply (auto)
   apply (case_tac "r_ex x")
     apply (auto)
  apply (case_tac "r_s x")
    apply (auto)
  done

lemma cancel_snorm_use_env: "\<lbrakk> leq_use_env r_xb r_xa \<rbrakk> \<Longrightarrow> super_norm_use_env (super_norm_use_env r_s r_xa) r_xb = super_norm_use_env r_s r_xb"
  apply (case_tac "\<forall> x. super_norm_use_env (super_norm_use_env r_s r_xa) r_xb x = super_norm_use_env r_s r_xb x")
   apply (auto)
  apply (simp add: leq_use_env_def)
  apply (simp add: super_norm_use_env_def)
  apply (erule_tac x="x" in allE)
  apply (case_tac "r_s x = OwnPerm \<and> r_xa x = NoPerm")
   apply (auto)
   apply (case_tac "r_xb x")
     apply (auto)
  apply (case_tac "r_s x = OwnPerm \<and> r_xa x = NoPerm")
   apply (auto)
  apply (case_tac "r_s x = OwnPerm \<and> r_xb x = NoPerm")
   apply (auto)
  done

lemma well_typed_sstr_end_perm: "\<lbrakk> well_typed env r_s1 e tau r_s2 rx \<rbrakk> \<Longrightarrow> well_typed env r_s1 e tau (super_norm_use_env r_s1 r_s2) rx"
  apply (induct e arbitrary: env r_s1 tau r_s2 rx)
       apply (auto)
    (* const + op cases *)
          apply (rule_tac self_snorm_leq_use_env)
         apply (rule_tac rhs_snorm_leq_use_env2)
          apply (auto)
        apply (rule_tac self_snorm_leq_use_env)
       apply (rule_tac rhs_snorm_leq_use_env2)
        apply (auto)
    (* var case *)
      apply (rule_tac x="r_ex" in exI)
      apply (auto)
       apply (rule_tac diff_snorm_leq_use_env)
        apply (rule_tac dist_comp_leq_use_env)
         apply (auto)
      apply (rule_tac rhs_snorm_leq_use_env2)
       apply (auto)
      apply (rule_tac r_sb="diff_use_env r_s1 (comp_use_env (ereq_use_env x1a tau_x) r_ex)" in trans_leq_use_env)
       apply (rule_tac self_diff_leq_use_env)
      apply (auto)
    (* pair case *)
     apply (rule_tac x="super_norm_use_env r_s1 r_s2a" in exI)
     apply (rule_tac x="super_norm_use_env (super_norm_use_env r_s1 r_s2a) r_s3" in exI)
     apply (rule_tac x="rx1" in exI)
     apply (auto)
     apply (rule_tac x="rx2" in exI)
     apply (auto)
        apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="super_norm_use_env r_s1 r_s2a" and e="e2" and ?r_s2.0="r_s3" in well_typed_incr_start_perm)
          apply (auto)
        apply (rule_tac rhs_snorm_leq_use_env)
         apply (rule_tac well_typed_perm_leq)
         apply (auto)
        apply (rule_tac id_leq_use_env)
       apply (rule_tac rhs_snorm_leq_use_env2)
        apply (simp)
       apply (rule_tac rhs_snorm_leq_use_env2)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
      apply (rule_tac rhs_snorm_leq_use_env2)
       apply (simp)
      apply (rule_tac rhs_snorm_leq_use_env2)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
     apply (cut_tac r_s="r_s1" and r_xa="r_s2a" and r_xb="r_s3" in cancel_snorm_use_env)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
     apply (cut_tac r_sc="r_s2" and r_sb="diff_use_env r_s3 r_ex" and r_sa="r_s1" in trans_leq_use_env)
       apply (rule_tac diff_leq_use_env)
       apply (rule_tac r_sb="r_s2a" in trans_leq_use_env)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
     apply (rule_tac x="r_ex" in exI)
     apply (auto)
      apply (rule_tac dist_diff_snorm_leq_use_env)
       apply (simp_all)
     apply (rule_tac rhs_snorm_leq_use_env2)
      apply (simp_all)
    (* if case *)
    apply (rule_tac x="rx'" in exI)
    apply (rule_tac x="super_norm_use_env r_s1 r_s2a" in exI)
    apply (auto)
    apply (rule_tac x="rx1" in exI)
    apply (auto)
     apply (rule_tac r_c="super_norm_use_env (super_norm_use_env r_s1 r_s2a) r_s2" in well_typed_decr_end_perm)
       apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="super_norm_use_env r_s1 r_s2a" and ?r_s2.0="r_s2" and e="e2" in well_typed_incr_start_perm)
         apply (auto)
       apply (rule_tac rhs_snorm_leq_use_env)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
       apply (rule_tac id_leq_use_env)
      apply (rule_tac dist_snorm_leq_use_env)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac rhs_snorm_leq_use_env2)
      apply (rule_tac well_typed_perm_leqx)
      apply (auto)
     apply (rule_tac r_sb="r_s2a" in trans_leq_use_env)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    apply (rule_tac x="rx2" in exI)
    apply (auto)
    apply (rule_tac r_c="super_norm_use_env (super_norm_use_env r_s1 r_s2a) r_s2" in well_typed_decr_end_perm)
      apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="super_norm_use_env r_s1 r_s2a" and ?r_s2.0="r_s2" and e="e3" in well_typed_incr_start_perm)
        apply (auto)
      apply (rule_tac rhs_snorm_leq_use_env)
       apply (rule_tac well_typed_perm_leq)
       apply (auto)
      apply (rule_tac id_leq_use_env)
     apply (rule_tac dist_snorm_leq_use_env)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
     apply (rule_tac id_leq_use_env)
    apply (rule_tac rhs_snorm_leq_use_env2)
     apply (rule_tac well_typed_perm_leqx)
     apply (auto)
    apply  (rule_tac r_sb="r_s2a" in trans_leq_use_env)
     apply (rule_tac well_typed_perm_leq)
     apply (auto)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
    (* lam case *)
   apply (rule_tac x="rxa" in exI)
   apply (auto)
   apply (rule_tac x="r_ex" in exI)
   apply (auto)
    apply (rule_tac diff_snorm_leq_use_env)
     apply (auto)
   apply (rule_tac rhs_snorm_leq_use_env2)
    apply (auto)
   apply (rule_tac r_sb="diff_use_env r_s1 r_ex" in trans_leq_use_env)
    apply (rule_tac self_diff_leq_use_env)
   apply (auto)
    (* app case *)
  apply (rule_tac x="t1" in exI)
  apply (rule_tac x="r" in exI)
  apply (rule_tac x="a" in exI)
  apply (rule_tac x="super_norm_use_env r_s1 r_s2a" in exI)
  apply (rule_tac x="rx1" in exI)
  apply (auto)
  apply (rule_tac x="rx2" in exI)
  apply (rule_tac x="super_norm_use_env (super_norm_use_env r_s1 r_s2a) r_s3" in exI)
  apply (auto)
   apply (cut_tac env="env" and ?r_s1.0="r_s2a" and r_c="super_norm_use_env r_s1 r_s2a" and ?r_s2.0="r_s3" and e="e2" in well_typed_incr_start_perm)
     apply (auto)
   apply (rule_tac rhs_snorm_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac id_leq_use_env)
  apply (rule_tac x="r_ex" in exI)
  apply (auto)
    apply (rule_tac r_sb="diff_use_env (super_norm_use_env r_s1 r_s3) (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)" in trans_leq_use_env)
     apply (rule_tac dist_diff_leq_use_env)
     apply (rule_tac dist_snorm_leq_use_env)
      apply (rule_tac well_typed_perm_leq)
      apply (auto)
     apply (rule_tac id_leq_use_env)
    apply (rule_tac dist_diff_snorm_leq_use_env)
     apply (rule_tac dist_comp_leq_use_env)
      apply (rule_tac r_sb="r_s3" in trans_leq_use_env)
       apply (rule_tac r_sb="r_s2a" in trans_leq_use_env)
        apply (rule_tac well_typed_perm_leq)
        apply (auto)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac rhs_snorm_leq_use_env2)
    apply (auto)
   apply (rule_tac rhs_snorm_leq_use_env2)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
   apply (rule_tac well_typed_perm_leq)
   apply (auto)
  apply (rule_tac rhs_snorm_leq_use_env2)
   apply (auto)
  apply (rule_tac r_sb="diff_use_env r_s3 (comp_use_env (comp_use_env rx1 (lift_use_env rx2 r)) r_ex)" in trans_leq_use_env)
   apply (rule_tac diff_leq_use_env)
   apply (rule_tac r_sb="r_s2a" in trans_leq_use_env)
    apply (rule_tac well_typed_perm_leq)
    apply (auto)
  apply (rule_tac well_typed_perm_leq)
  apply (auto)
  done

lemma snorm_diff_use_env: "(\<exists> r_ex. super_norm_use_env r_s r_x = diff_use_env r_s r_ex \<and> leq_use_env r_ex r_s)"
  apply (rule_tac x="\<lambda> x. if r_s x = OwnPerm \<and> r_x x = NoPerm then OwnPerm else NoPerm" in exI)
  apply (auto)
   apply (case_tac "\<forall> x. super_norm_use_env r_s r_x x = diff_use_env r_s (\<lambda>x. if r_s x = OwnPerm \<and> r_x x = NoPerm then OwnPerm else NoPerm) x")
    apply (auto)
   apply (simp add: super_norm_use_env_def)
   apply (simp add: diff_use_env_def)
   apply (simp add: minus_use_env_def)
   apply (simp add: neg_use_env_def)
   apply (case_tac "r_s x = OwnPerm \<and> r_x x = NoPerm")
    apply (auto)
    apply (case_tac "r_s x")
      apply (auto)
    apply (case_tac "r_s x")
     apply (auto)
  apply (simp add: leq_use_env_def)
  done

end


(* The state equivalence used for the unwinding proofs for the friendship confidentiality
   properties *)
theory Outer_Friend_Issuer_State_Indistinguishability
  imports Outer_Friend_Issuer_Observation_Setup
begin

subsubsection \<open>Unwinding helper definitions and lemmas\<close>

context OuterFriendIssuer
begin

fun filterUIDs :: "(apiID \<times> userID) list \<Rightarrow> (apiID \<times> userID) list" where
"filterUIDs auidl = filter (\<lambda>auid. (snd auid) \<in> UIDs (fst auid)) auidl"

fun removeUIDs :: "(apiID \<times> userID) list \<Rightarrow> (apiID \<times> userID) list" where
"removeUIDs auidl = filter (\<lambda>auid. (snd auid) \<notin> UIDs (fst auid)) auidl"

(* The notion of two (apiID \<times> userID) lists being equal on observers: *)
fun eqButUIDs :: "(apiID \<times> userID) list \<Rightarrow> (apiID \<times> userID) list \<Rightarrow> bool" where
"eqButUIDs uidl uidl1 = (filterUIDs uidl = filterUIDs uidl1)"

lemma eqButUIDs_eq[simp,intro!]: "eqButUIDs uidl uidl"
by auto

lemma eqButUIDs_sym:
assumes "eqButUIDs uidl uidl1"
shows "eqButUIDs uidl1 uidl"
using assms by auto

lemma eqButUIDs_trans:
assumes "eqButUIDs uidl uidl1" and "eqButUIDs uidl1 uidl2"
shows "eqButUIDs uidl uidl2"
using assms by auto

lemma eqButUIDs_remove1_cong:
assumes "eqButUIDs uidl uidl1"
shows "eqButUIDs (remove1 auid uidl) (remove1 auid uidl1)"
using assms by (auto simp: filter_remove1)

lemma eqButUIDs_snoc_cong:
assumes "eqButUIDs uidl uidl1"
(*and "uid' \<in>\<in> uidl \<longleftrightarrow> uid' \<in>\<in> uidl1"*)
shows "eqButUIDs (uidl ## auid') (uidl1 ## auid')"
using assms by auto

(* The notion of two functions each taking a userID being equal everywhere but on UID,
   where they are eqButUIDs. *)
definition eqButUIDf where
"eqButUIDf frds frds1 \<equiv>
  eqButUIDs (frds UID) (frds1 UID)
\<and> (\<forall>uid. uid \<noteq> UID \<longrightarrow> frds uid = frds1 uid)"

lemmas eqButUIDf_intro = eqButUIDf_def[THEN meta_eq_to_obj_eq, THEN iffD2]

lemma eqButUIDf_eeq[simp,intro!]: "eqButUIDf frds frds"
unfolding eqButUIDf_def by auto

lemma eqButUIDf_sym:
assumes "eqButUIDf frds frds1" shows "eqButUIDf frds1 frds"
using assms unfolding eqButUIDf_def
by auto

lemma eqButUIDf_trans:
assumes "eqButUIDf frds frds1" and "eqButUIDf frds1 frds2"
shows "eqButUIDf frds frds2"
using assms unfolding eqButUIDf_def by auto

lemma eqButUIDf_cong:
assumes "eqButUIDf frds frds1"
and "uid \<noteq> UID \<Longrightarrow> uu = uu1"
and "uid = UID \<Longrightarrow> eqButUIDs uu uu1"
shows "eqButUIDf (frds (uid := uu)) (frds1(uid := uu1))"
using assms unfolding eqButUIDf_def by auto

lemma eqButUIDf_not_UID:
"\<lbrakk>eqButUIDf frds frds1; uid \<noteq> UID\<rbrakk> \<Longrightarrow> frds uid = frds1 uid"
unfolding eqButUIDf_def by (auto split: if_splits)

(* The notion of two states being equal everywhere but on the friendship requests or status of users UID1 and UID2: *)
definition eqButUID :: "state \<Rightarrow> state \<Rightarrow> bool" where
"eqButUID s s1 \<equiv>
 admin s = admin s1 \<and>

 pendingUReqs s = pendingUReqs s1 \<and> userReq s = userReq s1 \<and>
 userIDs s = userIDs s1 \<and> user s = user s1 \<and> pass s = pass s1 \<and>

 pendingFReqs s = pendingFReqs s1 \<and>
 friendReq s = friendReq s1 \<and>
 friendIDs s = friendIDs s1 \<and>

 postIDs s = postIDs s1 \<and> admin s = admin s1 \<and>
 post s = post s1 \<and> vis s = vis s1 \<and>
 owner s = owner s1 \<and>

 pendingSApiReqs s = pendingSApiReqs s1 \<and> sApiReq s = sApiReq s1 \<and>
 serverApiIDs s = serverApiIDs s1 \<and> serverPass s = serverPass s1 \<and>
 outerPostIDs s = outerPostIDs s1 \<and> outerPost s = outerPost s1 \<and> outerVis s = outerVis s1 \<and>
 outerOwner s = outerOwner s1 \<and>
 eqButUIDf (sentOuterFriendIDs s) (sentOuterFriendIDs s1) \<and>
 recvOuterFriendIDs s = recvOuterFriendIDs s1 \<and>

 pendingCApiReqs s = pendingCApiReqs s1 \<and> cApiReq s = cApiReq s1 \<and>
 clientApiIDs s = clientApiIDs s1 \<and> clientPass s = clientPass s1 \<and>
 sharedWith s = sharedWith s1"

lemmas eqButUID_intro = eqButUID_def[THEN meta_eq_to_obj_eq, THEN iffD2]

lemma eqButUID_refl[simp,intro!]: "eqButUID s s"
unfolding eqButUID_def by auto

lemma eqButUID_sym[sym]:
assumes "eqButUID s s1" shows "eqButUID s1 s"
using assms eqButUIDf_sym unfolding eqButUID_def by auto

lemma eqButUID_trans[trans]:
assumes "eqButUID s s1" and "eqButUID s1 s2" shows "eqButUID s s2"
using assms eqButUIDf_trans unfolding eqButUID_def by metis

(* Implications from eqButUID, including w.r.t. auxiliary operations: *)
lemma eqButUID_stateSelectors:
assumes "eqButUID s s1"
shows "admin s = admin s1"
"pendingUReqs s = pendingUReqs s1" "userReq s = userReq s1"
"userIDs s = userIDs s1" "user s = user s1" "pass s = pass s1"
"pendingFReqs s = pendingFReqs s1"
"friendReq s = friendReq s1"
"friendIDs s = friendIDs s1"

"postIDs s = postIDs s1"
"post s = post s1" "vis s = vis s1"
"owner s = owner s1"

"pendingSApiReqs s = pendingSApiReqs s1" "sApiReq s = sApiReq s1"
"serverApiIDs s = serverApiIDs s1" "serverPass s = serverPass s1"
"outerPostIDs s = outerPostIDs s1" "outerPost s = outerPost s1" "outerVis s = outerVis s1"
"outerOwner s = outerOwner s1"
"eqButUIDf (sentOuterFriendIDs s) (sentOuterFriendIDs s1)"
"recvOuterFriendIDs s = recvOuterFriendIDs s1"

"pendingCApiReqs s = pendingCApiReqs s1" "cApiReq s = cApiReq s1"
"clientApiIDs s = clientApiIDs s1" "clientPass s = clientPass s1"
"sharedWith s = sharedWith s1"

"IDsOK s = IDsOK s1"
using assms unfolding eqButUID_def IDsOK_def[abs_def] by auto

lemmas eqButUID_eqButUIDf = eqButUID_stateSelectors(22)

lemma eqButUID_eqButUIDs:
"eqButUID s s1 \<Longrightarrow> eqButUIDs (sentOuterFriendIDs s UID) (sentOuterFriendIDs s1 UID)"
unfolding eqButUID_def eqButUIDf_def by auto

lemma eqButUID_not_UID:
"eqButUID s s1 \<Longrightarrow> uid \<noteq> UID \<Longrightarrow> sentOuterFriendIDs s uid = sentOuterFriendIDs s1 uid"
unfolding eqButUID_def eqButUIDf_def by auto

lemma eqButUID_sentOuterFriends_UIDs:
assumes "eqButUID s s1"
and "uid' \<in> UIDs aid"
shows "(aid, uid') \<in>\<in> sentOuterFriendIDs s UID \<longleftrightarrow> (aid, uid') \<in>\<in> sentOuterFriendIDs s1 UID"
proof -
  have "(aid, uid') \<in>\<in> filterUIDs (sentOuterFriendIDs s UID)
    \<longleftrightarrow> (aid, uid') \<in>\<in> filterUIDs (sentOuterFriendIDs s1 UID)"
    using assms unfolding eqButUID_def eqButUIDf_def by auto
  then show ?thesis using assms by auto
qed

lemma eqButUID_sentOuterFriendIDs_cong:
assumes "eqButUID s s1"
and "uid' \<notin> UIDs aid"
shows "eqButUID (s\<lparr>sentOuterFriendIDs := (sentOuterFriendIDs s)(UID := sentOuterFriendIDs s UID ## (aid, uid'))\<rparr>) s1"
and "eqButUID s (s1\<lparr>sentOuterFriendIDs := (sentOuterFriendIDs s1)(UID := sentOuterFriendIDs s1 UID ## (aid, uid'))\<rparr>)"
and "eqButUID s (s1\<lparr>sentOuterFriendIDs := (sentOuterFriendIDs s1)(UID := remove1 (aid, uid') (sentOuterFriendIDs s1 UID))\<rparr>)"
and "eqButUID (s\<lparr>sentOuterFriendIDs := (sentOuterFriendIDs s)(UID := remove1 (aid, uid') (sentOuterFriendIDs s UID))\<rparr>) s1"
using assms unfolding eqButUID_def eqButUIDf_def by (auto simp: filter_remove1)

lemma eqButUID_cong:
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>admin := uu1\<rparr>) (s1 \<lparr>admin := uu2\<rparr>)"

"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>pendingUReqs := uu1\<rparr>) (s1 \<lparr>pendingUReqs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>userReq := uu1\<rparr>) (s1 \<lparr>userReq := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>userIDs := uu1\<rparr>) (s1 \<lparr>userIDs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>user := uu1\<rparr>) (s1 \<lparr>user := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>pass := uu1\<rparr>) (s1 \<lparr>pass := uu2\<rparr>)"

"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>postIDs := uu1\<rparr>) (s1 \<lparr>postIDs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>owner := uu1\<rparr>) (s1 \<lparr>owner := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>post := uu1\<rparr>) (s1 \<lparr>post := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>vis := uu1\<rparr>) (s1 \<lparr>vis := uu2\<rparr>)"

"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>pendingFReqs := uu1\<rparr>) (s1 \<lparr>pendingFReqs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>friendReq := uu1\<rparr>) (s1 \<lparr>friendReq := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>friendIDs := uu1\<rparr>) (s1 \<lparr>friendIDs := uu2\<rparr>)"

"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>pendingSApiReqs := uu1\<rparr>) (s1 \<lparr>pendingSApiReqs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>sApiReq := uu1\<rparr>) (s1 \<lparr>sApiReq := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>serverApiIDs := uu1\<rparr>) (s1 \<lparr>serverApiIDs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>serverPass := uu1\<rparr>) (s1 \<lparr>serverPass := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>outerPostIDs := uu1\<rparr>) (s1 \<lparr>outerPostIDs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>outerPost := uu1\<rparr>) (s1 \<lparr>outerPost := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>outerVis := uu1\<rparr>) (s1 \<lparr>outerVis := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>outerOwner := uu1\<rparr>) (s1 \<lparr>outerOwner := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> eqButUIDf uu1 uu2 \<Longrightarrow> eqButUID (s \<lparr>sentOuterFriendIDs := uu1\<rparr>) (s1 \<lparr>sentOuterFriendIDs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>recvOuterFriendIDs := uu1\<rparr>) (s1 \<lparr>recvOuterFriendIDs := uu2\<rparr>)"

"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>pendingCApiReqs := uu1\<rparr>) (s1 \<lparr>pendingCApiReqs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>cApiReq := uu1\<rparr>) (s1 \<lparr>cApiReq := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>clientApiIDs := uu1\<rparr>) (s1 \<lparr>clientApiIDs := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>clientPass := uu1\<rparr>) (s1 \<lparr>clientPass := uu2\<rparr>)"
"\<And> uu1 uu2. eqButUID s s1 \<Longrightarrow> uu1 = uu2 \<Longrightarrow> eqButUID (s \<lparr>sharedWith := uu1\<rparr>) (s1 \<lparr>sharedWith:= uu2\<rparr>)"
unfolding eqButUID_def by auto

lemma distinct_remove1_idem: "distinct xs \<Longrightarrow> remove1 y (remove1 y xs) = remove1 y xs"
by (induction xs) (auto simp add: remove1_idem)

(* major *) lemma eqButUID_step:
assumes ss1: "eqButUID s s1"
and step: "step s a = (ou,s')"
and step1: "step s1 a = (ou1,s1')"
and rs: "reach s"
and rs1: "reach s1"
shows "eqButUID s' s1'"
proof -
  note simps = eqButUID_stateSelectors s_defs c_defs d_defs u_defs r_defs l_defs com_defs
               eqButUID_sentOuterFriends_UIDs eqButUID_not_UID
  from assms show ?thesis proof (cases a)
    case (Sact sa) with assms show ?thesis by (cases sa) (auto simp add: simps intro!: eqButUID_cong)
  next
    case (Cact ca) with assms show ?thesis by (cases ca) (auto simp add: simps intro!: eqButUID_cong)
  next
    case (Uact ua) with assms show ?thesis by (cases ua) (auto simp add: simps intro!: eqButUID_cong)
  next
    case (Ract ra) with assms show ?thesis by (cases ra) (auto simp add: simps intro!: eqButUID_cong)
  next
    case (Lact la) with assms show ?thesis by (cases la) (auto simp add: simps intro!: eqButUID_cong)
  next
    case (COMact ca)
      with assms show ?thesis proof (cases ca)
        case (comSendCreateOFriend uid p aid uid')
          then show ?thesis
            using COMact assms eqButUID_eqButUIDf[OF ss1] eqButUID_eqButUIDs[OF ss1]
            by (cases "uid = UID"; cases "uid' \<in> UIDs aid")
               (auto simp: simps intro!: eqButUID_cong eqButUIDf_cong intro: eqButUID_sentOuterFriendIDs_cong)
      next
        case (comSendDeleteOFriend uid p aid uid')
          then show ?thesis
            using COMact assms eqButUID_eqButUIDf[OF ss1] eqButUID_eqButUIDs[OF ss1]
            by (cases "uid = UID"; cases "uid' \<in> UIDs aid")
               (auto simp: simps filter_remove1 intro!: eqButUID_cong eqButUIDf_cong intro: eqButUID_sentOuterFriendIDs_cong)
      qed (auto simp: simps intro!: eqButUID_cong)
  next
    case (Dact da) with assms show ?thesis by (cases da) (auto simp add: simps intro!: eqButUID_cong)
  qed
qed

end

end


           (*-------------------------------------------*
            |        CSP-Prover on Isabelle2004         |
            |               November 2004               |
            |                   June 2005  (modified)   |
            |                   July 2005  (modified)   |
            |                                           |
            |        CSP-Prover on Isabelle2005         |
            |                October 2005  (modified)   |
            |                                           |
            |        Yoshinao Isobe (AIST JAPAN)        |
            *-------------------------------------------*)

theory Infra_common
imports Complex_Main
begin

(*****************************************************
           Convenient technique for proofs
 *****************************************************)

(*--------------------------*
 |    remove assumeption    |
 *--------------------------*)

lemma rem_asmE: "[| A ; R |] ==> R"
by simp

(*--------------------------*
 |      !!x. ==> ALL x.     |
 *--------------------------*)

lemma rev_all1E:
   "[| !!x. P x ; ALL x. P x ==> S |] ==> S"
by (auto)

lemma rev_all2E:
   "[| !!x y. P x y ; ALL x y. P x y ==> S |] ==> S"
by (auto)

lemma rev_all3E:
   "[| !!x y z. P x y z ; ALL x y z. P x y z ==> S |] ==> S"
by (auto)

lemmas rev_allE = rev_all1E rev_all2E rev_all3E

lemma rev_allI: "ALL x. P x ==> (!!x. P x)"
by (auto)

end


theory K_R_Spark_Obligation
imports K_R_Spark_User

begin

lemma goal6'1:
  assumes R1:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes R2:
  " K_R_Spark_Declaration.interfaces__unsigned_32__first'' = (0 :: int)
  "
  assumes R3:
  " K_R_Spark_Declaration.interfaces__unsigned_32__last''
    = (4294967295 :: int)
  "
  assumes R4:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__first''
    = (0 :: int)
  "
  assumes R5:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__last''
    = (4294967295 :: int)
  "
  assumes R6:
  " K_R_Spark_Declaration.interfaces__unsigned_32__modulus''
    = (4294967296 :: int)
  "
  assumes R7: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes R8: " K_R_Spark_Declaration.word__first'' = (0 :: int) "
  assumes R9:
  " K_R_Spark_Declaration.word__last'' = (4294967295 :: int)
  "
  assumes R10:
  " K_R_Spark_Declaration.word__base__first'' = (0 :: int)
  "
  assumes R11:
  " K_R_Spark_Declaration.word__base__last'' = (4294967295 :: int)
  "
  assumes R12:
  " K_R_Spark_Declaration.word__modulus'' = (4294967296 :: int)
  "
  assumes R13:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes R14:
  " K_R_Spark_Declaration.round_index__first'' = (0 :: int)
  "
  assumes R15:
  " K_R_Spark_Declaration.round_index__last'' = (79 :: int)
  "
  assumes R16:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes R17:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__first''
  "
  assumes R18:
  " K_R_Spark_Declaration.round_index__last''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H1: " (0 :: int) <= K_R_Spark_Declaration.j'' "
  assumes H2: " K_R_Spark_Declaration.j'' <= (15 :: int) "
  assumes H3:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes H4: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes H5:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes H6:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H7:
  " K_R_Spark_Declaration.round_index__base__first'' <= (0 :: int)
  "
  assumes H8:
  " (79 :: int) <= K_R_Spark_Declaration.round_index__base__last''
  "
  shows " (1352829926 :: int) = K_R_Spark_Specification.k_r' K_R_Spark_Declaration.j''
        " (is "?C1")
apply (insert assms) by (rule userlemmas)

lemma goal7'1:
  assumes R1:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes R2:
  " K_R_Spark_Declaration.interfaces__unsigned_32__first'' = (0 :: int)
  "
  assumes R3:
  " K_R_Spark_Declaration.interfaces__unsigned_32__last''
    = (4294967295 :: int)
  "
  assumes R4:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__first''
    = (0 :: int)
  "
  assumes R5:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__last''
    = (4294967295 :: int)
  "
  assumes R6:
  " K_R_Spark_Declaration.interfaces__unsigned_32__modulus''
    = (4294967296 :: int)
  "
  assumes R7: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes R8: " K_R_Spark_Declaration.word__first'' = (0 :: int) "
  assumes R9:
  " K_R_Spark_Declaration.word__last'' = (4294967295 :: int)
  "
  assumes R10:
  " K_R_Spark_Declaration.word__base__first'' = (0 :: int)
  "
  assumes R11:
  " K_R_Spark_Declaration.word__base__last'' = (4294967295 :: int)
  "
  assumes R12:
  " K_R_Spark_Declaration.word__modulus'' = (4294967296 :: int)
  "
  assumes R13:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes R14:
  " K_R_Spark_Declaration.round_index__first'' = (0 :: int)
  "
  assumes R15:
  " K_R_Spark_Declaration.round_index__last'' = (79 :: int)
  "
  assumes R16:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes R17:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__first''
  "
  assumes R18:
  " K_R_Spark_Declaration.round_index__last''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H1: " (16 :: int) <= K_R_Spark_Declaration.j'' "
  assumes H2: " K_R_Spark_Declaration.j'' <= (31 :: int) "
  assumes H3:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes H4: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes H5:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes H6:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H7:
  " K_R_Spark_Declaration.round_index__base__first'' <= (0 :: int)
  "
  assumes H8:
  " (79 :: int) <= K_R_Spark_Declaration.round_index__base__last''
  "
  shows " (1548603684 :: int) = K_R_Spark_Specification.k_r' K_R_Spark_Declaration.j''
        " (is "?C1")
apply (insert assms) by (rule userlemmas)

lemma goal8'1:
  assumes R1:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes R2:
  " K_R_Spark_Declaration.interfaces__unsigned_32__first'' = (0 :: int)
  "
  assumes R3:
  " K_R_Spark_Declaration.interfaces__unsigned_32__last''
    = (4294967295 :: int)
  "
  assumes R4:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__first''
    = (0 :: int)
  "
  assumes R5:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__last''
    = (4294967295 :: int)
  "
  assumes R6:
  " K_R_Spark_Declaration.interfaces__unsigned_32__modulus''
    = (4294967296 :: int)
  "
  assumes R7: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes R8: " K_R_Spark_Declaration.word__first'' = (0 :: int) "
  assumes R9:
  " K_R_Spark_Declaration.word__last'' = (4294967295 :: int)
  "
  assumes R10:
  " K_R_Spark_Declaration.word__base__first'' = (0 :: int)
  "
  assumes R11:
  " K_R_Spark_Declaration.word__base__last'' = (4294967295 :: int)
  "
  assumes R12:
  " K_R_Spark_Declaration.word__modulus'' = (4294967296 :: int)
  "
  assumes R13:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes R14:
  " K_R_Spark_Declaration.round_index__first'' = (0 :: int)
  "
  assumes R15:
  " K_R_Spark_Declaration.round_index__last'' = (79 :: int)
  "
  assumes R16:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes R17:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__first''
  "
  assumes R18:
  " K_R_Spark_Declaration.round_index__last''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H1: " (32 :: int) <= K_R_Spark_Declaration.j'' "
  assumes H2: " K_R_Spark_Declaration.j'' <= (47 :: int) "
  assumes H3:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes H4: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes H5:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes H6:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H7:
  " K_R_Spark_Declaration.round_index__base__first'' <= (0 :: int)
  "
  assumes H8:
  " (79 :: int) <= K_R_Spark_Declaration.round_index__base__last''
  "
  shows " (1836072691 :: int) = K_R_Spark_Specification.k_r' K_R_Spark_Declaration.j''
        " (is "?C1")
apply (insert assms) by (rule userlemmas)

lemma goal9'1:
  assumes R1:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes R2:
  " K_R_Spark_Declaration.interfaces__unsigned_32__first'' = (0 :: int)
  "
  assumes R3:
  " K_R_Spark_Declaration.interfaces__unsigned_32__last''
    = (4294967295 :: int)
  "
  assumes R4:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__first''
    = (0 :: int)
  "
  assumes R5:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__last''
    = (4294967295 :: int)
  "
  assumes R6:
  " K_R_Spark_Declaration.interfaces__unsigned_32__modulus''
    = (4294967296 :: int)
  "
  assumes R7: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes R8: " K_R_Spark_Declaration.word__first'' = (0 :: int) "
  assumes R9:
  " K_R_Spark_Declaration.word__last'' = (4294967295 :: int)
  "
  assumes R10:
  " K_R_Spark_Declaration.word__base__first'' = (0 :: int)
  "
  assumes R11:
  " K_R_Spark_Declaration.word__base__last'' = (4294967295 :: int)
  "
  assumes R12:
  " K_R_Spark_Declaration.word__modulus'' = (4294967296 :: int)
  "
  assumes R13:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes R14:
  " K_R_Spark_Declaration.round_index__first'' = (0 :: int)
  "
  assumes R15:
  " K_R_Spark_Declaration.round_index__last'' = (79 :: int)
  "
  assumes R16:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes R17:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__first''
  "
  assumes R18:
  " K_R_Spark_Declaration.round_index__last''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H1: " (48 :: int) <= K_R_Spark_Declaration.j'' "
  assumes H2: " K_R_Spark_Declaration.j'' <= (63 :: int) "
  assumes H3:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes H4: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes H5:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes H6:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H7:
  " K_R_Spark_Declaration.round_index__base__first'' <= (0 :: int)
  "
  assumes H8:
  " (79 :: int) <= K_R_Spark_Declaration.round_index__base__last''
  "
  shows " (2053994217 :: int) = K_R_Spark_Specification.k_r' K_R_Spark_Declaration.j''
        " (is "?C1")
apply (insert assms) by (rule userlemmas)

lemma goal10'1:
  assumes R1:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes R2:
  " K_R_Spark_Declaration.interfaces__unsigned_32__first'' = (0 :: int)
  "
  assumes R3:
  " K_R_Spark_Declaration.interfaces__unsigned_32__last''
    = (4294967295 :: int)
  "
  assumes R4:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__first''
    = (0 :: int)
  "
  assumes R5:
  " K_R_Spark_Declaration.interfaces__unsigned_32__base__last''
    = (4294967295 :: int)
  "
  assumes R6:
  " K_R_Spark_Declaration.interfaces__unsigned_32__modulus''
    = (4294967296 :: int)
  "
  assumes R7: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes R8: " K_R_Spark_Declaration.word__first'' = (0 :: int) "
  assumes R9:
  " K_R_Spark_Declaration.word__last'' = (4294967295 :: int)
  "
  assumes R10:
  " K_R_Spark_Declaration.word__base__first'' = (0 :: int)
  "
  assumes R11:
  " K_R_Spark_Declaration.word__base__last'' = (4294967295 :: int)
  "
  assumes R12:
  " K_R_Spark_Declaration.word__modulus'' = (4294967296 :: int)
  "
  assumes R13:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes R14:
  " K_R_Spark_Declaration.round_index__first'' = (0 :: int)
  "
  assumes R15:
  " K_R_Spark_Declaration.round_index__last'' = (79 :: int)
  "
  assumes R16:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes R17:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__first''
  "
  assumes R18:
  " K_R_Spark_Declaration.round_index__last''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H1: " (0 :: int) <= K_R_Spark_Declaration.j'' "
  assumes H2: " K_R_Spark_Declaration.j'' <= (79 :: int) "
  assumes H3: " (15 :: int) < K_R_Spark_Declaration.j'' "
  assumes H4: " (31 :: int) < K_R_Spark_Declaration.j'' "
  assumes H5: " (47 :: int) < K_R_Spark_Declaration.j'' "
  assumes H6: " (63 :: int) < K_R_Spark_Declaration.j'' "
  assumes H7:
  " (0 :: int) <= K_R_Spark_Declaration.interfaces__unsigned_32__size''
  "
  assumes H8: " (0 :: int) <= K_R_Spark_Declaration.word__size'' "
  assumes H9:
  " (0 :: int) <= K_R_Spark_Declaration.round_index__size''
  "
  assumes H10:
  " K_R_Spark_Declaration.round_index__base__first''
    <= K_R_Spark_Declaration.round_index__base__last''
  "
  assumes H11:
  " K_R_Spark_Declaration.round_index__base__first'' <= (0 :: int)
  "
  assumes H12:
  " (79 :: int) <= K_R_Spark_Declaration.round_index__base__last''
  "
  shows " (0 :: int) = K_R_Spark_Specification.k_r' K_R_Spark_Declaration.j''
        " (is "?C1")
apply (insert assms) by (rule userlemmas)
end


(*
 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
 *
 * SPDX-License-Identifier: BSD-2-Clause
 *)

theory WordSetup (* part of non-AFP Word_Lib *)
imports
  "../Distinct_Prop"
  "../Word_Lemmas_32_Internal"
begin

(* Distinct_Prop lemmas that need word lemmas: *)

lemma distinct_prop_enum:
  "\<lbrakk> \<And>x y. \<lbrakk> x \<le> stop; y \<le> stop; x \<noteq> y \<rbrakk> \<Longrightarrow> P x y \<rbrakk>
     \<Longrightarrow> distinct_prop P [0 :: 'a :: len word .e. stop]"
  apply (simp add: upto_enum_def distinct_prop_map del: upt.simps)
  apply (rule distinct_prop_distinct)
   apply simp
  apply (simp add: less_Suc_eq_le del: upt.simps)
  apply (erule_tac x="of_nat x" in meta_allE)
  apply (erule_tac x="of_nat y" in meta_allE)
  apply (frule_tac y=x in unat_le)
  apply (frule_tac y=y in unat_le)
  apply (erule word_unat.Rep_cases)+
  apply (simp add: toEnum_of_nat[OF unat_lt2p]
                   word_le_nat_alt)
  done

lemma distinct_prop_enum_step:
  "\<lbrakk> \<And>x y. \<lbrakk> x \<le> stop div step; y \<le> stop div step; x \<noteq> y \<rbrakk> \<Longrightarrow> P (x * step) (y * step) \<rbrakk>
     \<Longrightarrow> distinct_prop P [0, step .e. stop]"
  apply (simp add: upto_enum_step_def distinct_prop_map)
  apply (rule distinct_prop_enum)
  apply simp
  done

end


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

header{*The n_german Protocol Case Study*}

theory n_german_lemma_inv__12_on_rules imports n_german_lemma_on_inv__12
begin
section{*All lemmas on causal relation between inv__12*}
lemma lemma_inv__12_on_rules:
  assumes b1: "r \<in> rules N" and b2: "(\<exists> p__Inv2. p__Inv2\<le>N\<and>f=inv__12  p__Inv2)"
  shows "invHoldForRule s f r (invariants N)"
  proof -
  have c1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendReqE__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqS N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvReqE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__0  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInv__part__1  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvInvAck  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_SendGntE N i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntS  i)\<or>
    (\<exists> i. i\<le>N\<and>r=n_RecvGntE  i)"
  apply (cut_tac b1, auto) done
    moreover {
      assume d1: "(\<exists> i d. i\<le>N\<and>d\<le>N\<and>r=n_Store  i d)"
      have "invHoldForRule s f r (invariants N)"
      apply (cut_tac b2 d1, metis n_StoreVsinv__12) done
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

end


(*  Title:       CoreC++
    Author:      Daniel Wasserrab
    Maintainer:  Daniel Wasserrab <wasserra at fmi.uni-passau.de>

   Based on the Jinja theory Common/Objects.thy by Tobias Nipkow
*)

header {* \isaheader{Objects and the Heap} *}

theory Objects imports SubObj begin

section{* Objects *}

type_synonym
  subo = "(path \<times> (vname \<rightharpoonup> val))"     -- "subobjects realized on the heap"
type_synonym
  obj  = "cname \<times> subo set"            -- "mdc and subobject"

definition init_class_fieldmap :: "prog \<Rightarrow> cname \<Rightarrow> (vname \<rightharpoonup> val)" where
  "init_class_fieldmap P C \<equiv>
     map_of (map (\<lambda>(F,T).(F,default_val T)) (fst(snd(the(class P C)))) )"

inductive
  init_obj :: "prog \<Rightarrow> cname \<Rightarrow> (path \<times> (vname \<rightharpoonup> val)) \<Rightarrow> bool"
  for P :: prog and C :: cname
where
  "Subobjs P C Cs \<Longrightarrow> init_obj P C (Cs,init_class_fieldmap P (last Cs))"

lemma init_obj_nonempty: "init_obj P C (Cs,fs) \<Longrightarrow> Cs \<noteq> []"
by (fastforce elim:init_obj.cases dest:Subobjs_nonempty)

lemma init_obj_no_Ref:
"\<lbrakk>init_obj P C (Cs,fs);  fs F = Some(Ref(a',Cs'))\<rbrakk> \<Longrightarrow> False"
by (fastforce elim:init_obj.cases default_val_no_Ref
                  simp:init_class_fieldmap_def map_of_map)

lemma SubobjsSet_init_objSet:
  "{Cs. Subobjs P C Cs} = {Cs. \<exists>vmap. init_obj P C (Cs,vmap)}"
by ( fastforce intro:init_obj.intros elim:init_obj.cases)

definition obj_ty :: "obj \<Rightarrow> ty" where
  "obj_ty obj  \<equiv>  Class (fst obj)"

 -- "a new, blank object with default values in all fields:"
definition blank :: "prog \<Rightarrow> cname \<Rightarrow> obj" where
  "blank P C  \<equiv> (C, Collect (init_obj P C))"

section{* Heap *}

type_synonym heap  = "addr \<rightharpoonup> obj"

abbreviation
  cname_of :: "heap \<Rightarrow> addr \<Rightarrow> cname" where
  "cname_of hp a == fst (the (hp a))"

definition new_Addr :: "heap \<Rightarrow> addr option" where
  "new_Addr h  \<equiv>  if \<exists>a. h a = None then Some(SOME a. h a = None) else None"

lemma new_Addr_SomeD:
  "new_Addr h = Some a \<Longrightarrow> h a = None"
 by(fastforce simp add:new_Addr_def split:if_splits intro:someI)

end


(*<*)
(*
 * Knowledge-based programs.
 * (C)opyright 2011, Peter Gammie, peteg42 at gmail.com.
 * License: BSD
 *)

theory SPRViewNonDetIndInit
imports
  SPRView
  KBPsAuto
  SPRViewNonDet
begin
(*>*)

subsubsection\<open>Perfect Recall in Independently-Initialised Non-deterministic Broadcast Environments\<close>

text\<open>

\label{sec:kbps-theory-spr-non-deterministic-protocols-ind-init}

If the private and environment parts of the initial states are
independent we can simplify the construction of the previous section
and consider only sets of states rather than relations. This greatly
reduces the state space that the algorithm traverses.

We capture this independence by adding some assumptions to the @{term
"FiniteBroadcastEnvironment"} locale of
Figure~\ref{fig:kbps-theory-broadcast-envs}; the result is the @{term
"FiniteBroadcastEnvironmentIndependentInit"} locale shown in
Figure~\ref{fig:kbps-theory-broadcast-envs-ind-init}. We ask that the
initial states be the Cartesian product of possible private and
environment states; in other words there is nothing for the agents to
learn about correlations amongst the initial states. As there are
initially no public actions from the previous round, we use the @{term
"default"} class to indicate that there is a fixed but arbitrary
choice to be made here.

Again we introduce common and agent-specific abstraction functions:

\<close>

text_raw\<open>
\begin{figure}[ht]
\begin{isabellebody}%
\<close>
locale FiniteBroadcastEnvironmentIndependentInit =
  FiniteBroadcastEnvironment jkbp envInit envAction envTrans envVal envObs
                             envObsC envActionES envTransES
    for jkbp :: "('a::finite, 'p, ('pPubAct::{default,finite} \<times> 'ps::finite)) JKBP"
    and envInit :: "('a, 'ePubAct :: {default, finite}, 'es :: finite,
                     'pPubAct, 'ps) BEState list"
    and envAction :: "('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState
                   \<Rightarrow> ('ePubAct \<times> 'ePrivAct) list"
    and envTrans :: "('ePubAct \<times> 'ePrivAct)
                  \<Rightarrow> ('a \<Rightarrow> ('pPubAct \<times> 'ps))
                  \<Rightarrow> ('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState
                  \<Rightarrow> ('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState"
    and envVal :: "('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState \<Rightarrow> 'p \<Rightarrow> bool"
    and envObs :: "'a \<Rightarrow> ('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState
                \<Rightarrow> ('cobs \<times> 'ps \<times> ('ePubAct \<times> ('a \<Rightarrow> 'pPubAct)))"
    and envObsC :: "'es \<Rightarrow> 'cobs"
    and envActionES :: "'es \<Rightarrow> ('ePubAct \<times> ('a \<Rightarrow> 'pPubAct))
                            \<Rightarrow> ('ePubAct \<times> 'ePrivAct) list"
    and envTransES :: "('ePubAct \<times> 'ePrivAct) \<Rightarrow> ('a \<Rightarrow> 'pPubAct)
                    \<Rightarrow> 'es \<Rightarrow> 'es"

+ fixes agents :: "'a list"
  fixes envInitBits :: "'es list \<times> ('a \<Rightarrow> 'ps list)"
  defines envInit_def:
     "envInit \<equiv> [ \<lparr> es = esf, ps = psf, pubActs = (default, \<lambda>_. default) \<rparr>
                 . psf \<leftarrow> listToFuns (snd envInitBits) agents
                 , esf \<leftarrow> fst envInitBits ]"
  assumes agents: "set agents = UNIV" "distinct agents"

text_raw\<open>
  \end{isabellebody}%
  \caption{Finite broadcast environments with non-deterministic
  KBPs, where the initial private and environment states are
  independent.}
  \label{fig:kbps-theory-broadcast-envs-ind-init}
\end{figure}
\<close>

context FiniteBroadcastEnvironmentIndependentInit
begin

definition
  tObsC_ii_abs :: "('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState Trace
             \<Rightarrow> ('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState set"
where "tObsC_ii_abs t \<equiv>
  { tLast t' |t'. t' \<in> SPR.jkbpC \<and> tObsC t' = tObsC t }"

definition
  agent_ii_abs :: "'a \<Rightarrow> ('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState Trace
             \<Rightarrow> ('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState set"
where "agent_ii_abs a t \<equiv>
  { tLast t' |t'. t' \<in> SPR.jkbpC \<and> spr_jview a t' = spr_jview a t }"
(*<*)

lemma tObsC_ii_abs_jview_eq[dest, intro]:
  "spr_jview a t' = spr_jview a t
    \<Longrightarrow> tObsC_ii_abs t = tObsC_ii_abs t'"
  unfolding tObsC_ii_abs_def by (fastforce dest: spr_jview_tObsC)

lemma tObsC_ii_absI[intro]:
  "\<lbrakk> t' \<in> SPR.jkbpC; tObsC t' = tObsC t; v = tLast t' \<rbrakk>
    \<Longrightarrow> v \<in> tObsC_ii_abs t"
  unfolding tObsC_ii_abs_def by blast

lemma tObsC_ii_abs_conv:
  " v \<in> tObsC_ii_abs t
    \<longleftrightarrow> (\<exists>t'. t' \<in> SPR.jkbpC \<and> tObsC t' = tObsC t \<and> v = tLast t')"
  unfolding tObsC_ii_abs_def by blast

lemma agent_ii_absI[elim]:
  "\<lbrakk> t' \<in> SPR.jkbpC; spr_jview a t' = spr_jview a t; v = tLast t' \<rbrakk>
    \<Longrightarrow> v \<in> agent_ii_abs a t"
  unfolding agent_ii_abs_def by blast

lemma agent_ii_abs_tLastD[simp]:
  "v \<in> agent_ii_abs a t \<Longrightarrow> envObs a v = envObs a (tLast t)"
  unfolding agent_ii_abs_def by auto

lemma agent_ii_abs_inv[dest]:
  "v \<in> agent_ii_abs a t
    \<Longrightarrow> \<exists>t'. t' \<in> SPR.jkbpC \<and> spr_jview a t' = spr_jview a t
           \<and> v = tLast t'"
  unfolding agent_ii_abs_def by blast

(*>*)
text\<open>

The simulation is similar to the single-agent case
(\S\ref{sec:kbps-spr-single-agent}); for a given canonical trace
@{term "t"} it pairs the set of worlds that any agent considers
possible with the final state of @{term "t"}:

\<close>

type_synonym (in -) ('a, 'ePubAct, 'es, 'pPubAct, 'ps) SPRstate =
  "('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState set
 \<times> ('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState"

definition
  spr_ii_sim :: "('a, 'ePubAct, 'es, 'pPubAct, 'ps) BEState Trace
           \<Rightarrow> ('a, 'ePubAct, 'es, 'pPubAct, 'ps) SPRstate"
where "spr_ii_sim \<equiv> \<lambda>t. (tObsC_ii_abs t, tLast t)"
(*<*)

lemma spr_ii_sim_tFirst_tLast:
  "\<lbrakk> spr_ii_sim t = s; t \<in> SPR.jkbpC \<rbrakk> \<Longrightarrow> snd s \<in> fst s"
  unfolding spr_ii_sim_def by auto

(*>*)
text\<open>

The Kripke structure over simulated traces is also quite similar:

\<close>

definition
  spr_ii_simRels :: "'a \<Rightarrow> ('a, 'ePubAct, 'es, 'pPubAct, 'ps) SPRstate Relation"
where "spr_ii_simRels \<equiv> \<lambda>a.
  { (s, s') |s s'. envObs a (snd s) = envObs a (snd s') \<and> fst s = fst s' }"

definition
  spr_ii_simVal :: "('a, 'ePubAct, 'es, 'pPubAct, 'ps) SPRstate \<Rightarrow> 'p \<Rightarrow> bool"
where "spr_ii_simVal \<equiv> envVal \<circ> snd"

abbreviation
  "spr_ii_simMC \<equiv> mkKripke (spr_ii_sim ` SPR.jkbpC) spr_ii_simRels spr_ii_simVal"
(*<*)

lemma spr_ii_simVal_def2[iff]:
  "spr_ii_simVal (spr_ii_sim t) = envVal (tLast t)"
  unfolding spr_ii_sim_def spr_ii_simVal_def by simp

(* Same as for SPRViewNonDet but different base case. *)

lemma tSplice_jkbpC:
  assumes tt': "{t, t'} \<subseteq> SPR.jkbpC"
  assumes tObsC: "tObsC t = tObsC t'"
  shows "t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> t' \<in> SPR.jkbpC"
using tObsC_tLength[OF tObsC] tt' tObsC
proof(induct rule: trace_induct2)
  case (tInit s s') thus ?case
    apply clarsimp
    unfolding envInit_def sSplice_def
    apply clarsimp
    apply (rule_tac x="x(a := xa a)" in bexI)
    using listToFun_splice[OF agents]
    apply auto
    done
next
  case (tStep s s' t t')

  hence tt': "t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> t' \<in> SPR.jkbpC"
    and tLen: "tLength t' = tLength t"
    and tObsC: "tObsC (t \<leadsto> s) = tObsC (t' \<leadsto> s')"
    by auto

  hence tt'n: "t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> t' \<in> SPR.jkbpCn (tLength t)"
    by auto

  from tStep
  have ts: "t \<leadsto> s \<in> SPR.jkbpCn (Suc (tLength t))"
   and t's': "t' \<leadsto> s' \<in> SPR.jkbpCn (Suc (tLength t'))"
    apply -
     apply ((rule SPR.jkbpC_tLength_inv, simp_all)[1])+
    done

  from ts obtain eact aact
    where eact: "eact \<in> set (envAction (tLast t))"
      and aact: "\<forall>a. aact a \<in> set (jAction (SPR.mkM (SPR.jkbpCn (tLength t))) t a)"
      and trans: "envTrans eact aact (tLast t) = s"
    apply (auto iff: Let_def)
    done

  from t's' obtain eact' aact'
    where eact': "eact' \<in> set (envAction (tLast t'))"
      and aact': "\<forall>a. aact' a \<in> set (jAction (SPR.mkM (SPR.jkbpCn (tLength t'))) t' a)"
      and trans': "envTrans eact' aact' (tLast t') = s'"
    apply (auto iff: Let_def)
    done

  define aact'' where "aact'' = aact (a := aact' a)"

  from tObsC trans trans'
  have aact''_fst: "fst \<circ> aact'' = fst \<circ> aact"
    unfolding envTrans_def aact''_def
    apply -
    apply (rule ext)
    apply (auto iff: tObsC_tStep)
    apply (erule o_eq_elim)
    apply simp
    done

  from tObsC trans trans'
  have aact''_snd: "snd \<circ> aact'' = (snd \<circ> aact)(a := ps s' a)"
    unfolding envTrans_def aact''_def
    apply -
    apply (rule ext)
    apply auto
    done

  have "envTrans eact aact'' (tLast (t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> t'))
      = sSplice a (envTrans eact aact (tLast t)) s'"
    apply (simp only: envTrans_def sSplice_def)
    using tSplice_es[OF tLen[symmetric]] aact''_fst aact''_snd
    apply clarsimp
    done

  moreover

  { fix a'
    have "aact'' a' \<in> set (jAction (SPR.mkM (SPR.jkbpCn (tLength t))) (t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> t') a')"
    proof(cases "a' = a")
      case False
      with tStep have "jAction (SPR.mkM (SPR.jkbpCn (tLength t))) (t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> t') a'
                     = jAction (SPR.mkM (SPR.jkbpCn (tLength t))) t a'"
        apply -
        apply (rule S5n_jAction_eq)
         apply simp
        unfolding SPR.mkM_def
        using tSplice_spr_jview_not_a tt'
        apply auto
        done
      with False aact show ?thesis
        unfolding aact''_def by simp
    next
      case True
      with tStep have "jAction (SPR.mkM (SPR.jkbpCn (tLength t))) (t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> t') a
                     = jAction (SPR.mkM (SPR.jkbpCn (tLength t))) t' a"
        apply -
        apply (rule S5n_jAction_eq)
         apply simp
        unfolding SPR.mkM_def
        using tSplice_spr_jview_a tt'
        apply auto
        done
      with True aact' tLen show ?thesis
        unfolding aact''_def by simp
    qed }

  moreover

  from tStep have "envAction (tLast (t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> t')) = envAction (tLast t)"
    using tSplice_envAction by blast

  moreover note eact trans tt'n

  ultimately have "(t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> t') \<leadsto> sSplice a s s' \<in> SPR.jkbpCn (Suc (tLength t))"
    apply (simp add: Let_def del: split_paired_Ex)
    apply (rule exI[where x="eact"])
    apply (rule exI[where x="aact''"])
    apply simp
    done

  thus ?case
    apply (simp only: tZip.simps)
    apply blast
    done
qed

lemma spr_ii_sim_r:
  "sim_r SPR.MC spr_ii_simMC spr_ii_sim"
proof(rule sim_rI)
  fix a p q'
  assume pT: "p \<in> worlds SPR.MC"
     and fpq': "(spr_ii_sim p, q') \<in> relations spr_ii_simMC a"
  from fpq' obtain vq
    where q': "q' = (tObsC_ii_abs p, vq)"
      and vq: "envObs a (tLast p) = envObs a vq"
    unfolding mkKripke_def spr_ii_sim_def spr_ii_simRels_def
    by fastforce

  from fpq' have "q' \<in> worlds spr_ii_simMC" by simp
  with q' have "vq \<in> tObsC_ii_abs p"
    using spr_ii_sim_tFirst_tLast[where s=q']
    apply auto
    done

  then obtain t
    where tT: "t \<in> SPR.jkbpC"
      and tp: "tObsC t = tObsC p"
      and tvq: "tLast t = vq"
    by (auto iff: tObsC_ii_abs_conv)

  define q where "q = t \<^bsub>\<^esub>\<bowtie>\<^bsub>a\<^esub> p"

  from tp
  have "spr_jview a p = spr_jview a q"
    unfolding q_def by (simp add: tSplice_spr_jview_a)

  with pT tT tp
  have pt: "(p, q) \<in> relations SPR.MC a"
    unfolding SPR.mkM_def q_def by (simp add: tSplice_jkbpC)
  from q' vq tp tvq
  have ftq': "spr_ii_sim q = q'"
    unfolding spr_ii_sim_def q_def
    using tSplice_tObsC[where a=a and t=t and t'=p]
    apply clarsimp
    apply (intro conjI)
      apply (auto dest: tObsC_tLength)[2]
    unfolding tObsC_ii_abs_def (* FIXME abstract *)
    apply auto
    done
  from pt ftq'
  show "\<exists>q. (p, q) \<in> relations SPR.MC a \<and> spr_ii_sim q = q'"
    by blast
qed

(*>*)
text\<open>

The proofs that this simulation is adequate are similar to those in
the previous section. We elide the details.

\<close>

lemma spr_ii_sim: "sim SPR.MC spr_ii_simMC spr_ii_sim"
(*<*)
proof
  show "sim_range SPR.MC spr_ii_simMC spr_ii_sim"
    by (rule sim_rangeI) (simp_all add: spr_ii_sim_def)
next
  show "sim_val SPR.MC spr_ii_simMC spr_ii_sim"
    by (rule sim_valI) simp
next
  show "sim_f SPR.MC spr_ii_simMC spr_ii_sim"
    unfolding spr_ii_simRels_def spr_ii_sim_def mkKripke_def SPR.mkM_def
    by (rule sim_fI, auto simp del: split_paired_Ex)
next
  show "sim_r SPR.MC spr_ii_simMC spr_ii_sim"
    by (rule spr_ii_sim_r)
qed
(*>*)

end (* context FiniteBroadcastEnvironment *)

sublocale FiniteBroadcastEnvironmentIndependentInit
        < SPRii: SimIncrEnvironment jkbp envInit envAction envTrans envVal
                                       spr_jview envObs spr_jviewInit spr_jviewIncr
                                       spr_ii_sim spr_ii_simRels spr_ii_simVal
(*<*)
  by standard (simp add: spr_ii_sim)

end
(*>*)