(*  Title:      IL_AF_Exec_Stream.thy
    Date:       Nov 2007
    Author:     David Trachtenherz
*)

header {* \textsc{AutoFocus} message stream processing and temporal logic on intervals *}

theory IL_AF_Stream_Exec
imports Main IL_AF_Stream AF_Stream_Exec
begin

subsection {* Correlation between Pre/Post-Conditions for @{text f_Exec_Comp_Stream} and @{text f_Exec_Comp_Stream_Init} *}

thm
  i_Exec_Stream_Pre_Post1
  i_Exec_Stream_Pre_Post2
  i_Exec_Stream_Init_Pre_Post1
  i_Exec_Stream_Init_Pre_Post2
thm i_Exec_Stream_Pre_Post1
lemma i_Exec_Stream_Pre_Post1_iAll: "
  \<lbrakk> result = i_Exec_Comp_Stream trans_fun input c;
    \<forall>x_n c_n. P1 x_n \<and> P2 c_n \<longrightarrow> Q (trans_fun x_n c_n) \<rbrakk> \<Longrightarrow>
  \<box> t I. (P1 (input t) \<and> P2 (result\<^bsup>\<leftarrow> c\<^esup> t) \<longrightarrow> Q (result t))"
by (simp add: i_Exec_Stream_Pre_Post1)
text {* Direct relation between input and result after transition *}
thm i_Exec_Stream_Pre_Post2
lemma i_Exec_Stream_Pre_Post2_iAll: "
  \<lbrakk> result = i_Exec_Comp_Stream trans_fun input c;
    \<forall>x_n c_n. P c_n \<longrightarrow> Q x_n (trans_fun x_n c_n) \<rbrakk> \<Longrightarrow>
  \<box> t I. P (result\<^bsup>\<leftarrow> c\<^esup> t) \<longrightarrow> Q (input t) (result t)"
by (simp add: i_Exec_Stream_Pre_Post2)
lemma i_Exec_Stream_Pre_Post3_iAll_iNext: "
  \<lbrakk> result = i_Exec_Comp_Stream trans_fun input c;
    \<forall>x_n c_n. P c_n \<longrightarrow> Q x_n (trans_fun x_n c_n);
    \<forall>t\<in>I. inext t I' = Suc t \<rbrakk> \<Longrightarrow>
  \<box> t I. P (result t) \<longrightarrow> (\<bigcirc> t1 t I'. Q (input t1) (result t1))"
by (rule iallI, simp add: iNext_def i_Exec_Stream_Pre_Post2_Suc)

thm i_Exec_Stream_Init_Pre_Post1
lemma i_Exec_Stream_Init_Pre_Post1_iAll_iNext: "
  \<lbrakk> result = i_Exec_Comp_Stream_Init trans_fun input c;
    \<forall>x_n c_n. P1 x_n \<and> P2 c_n \<longrightarrow> Q (trans_fun x_n c_n);
    \<forall>t\<in>I. inext t I' = Suc t \<rbrakk> \<Longrightarrow>
  \<box> t I. (P1 (input t) \<and> P2 (result t) \<longrightarrow> (\<bigcirc> t1 t I'. Q (result t1)))"
by (rule iallI, simp add: iNext_def i_Exec_Stream_Init_Pre_Post1)

text {* Direct relation between input and state before transition *}
thm i_Exec_Stream_Init_Pre_Post2
lemma i_Exec_Stream_Init_Pre_Post2_iAll_iNext: "
  \<lbrakk> result = i_Exec_Comp_Stream_Init trans_fun input c;
    \<forall>x_n c_n. P x_n c_n \<longrightarrow> Q (trans_fun x_n c_n);
    \<forall>t\<in>I. inext t I' = Suc t \<rbrakk> \<Longrightarrow>
  \<box> t I. (P (input t) (result t) \<longrightarrow> (\<bigcirc> t1 t I'. Q (result t1)))"
by (rule iallI, simp add: iNext_def i_Exec_Stream_Init_Pre_Post2)

text {* Relation between input and output *}
thm i_Exec_Stream_Pre_Post3_iAll_iNext
lemma i_Exec_Stream_Init_Pre_Post3_iAll_iNext: "
  \<lbrakk> result = i_Exec_Comp_Stream_Init trans_fun input c;
    \<forall>x_n c_n. P c_n \<longrightarrow> Q x_n (trans_fun x_n c_n);
    \<forall>t\<in>I. inext t I' = Suc t \<rbrakk> \<Longrightarrow>
  \<box> t I. (P (result t) \<longrightarrow> (\<bigcirc> t1 t I'. Q (input\<^bsup>\<leftarrow> \<NoMsg>\<^esup> t1) (result t1)))"
apply (rule iallI, unfold iNext_def)
apply (simp add: ilist_Previous_Suc i_Exec_Stream_Init_nth_Suc_eq_i_Exec_Stream_nth i_Exec_Stream_Previous_i_Exec_Stream_Init)
thm i_Exec_Stream_Pre_Post2_iAll[OF refl]
apply (blast dest: i_Exec_Stream_Pre_Post2_iAll[OF refl])
done

subsection {* @{text "i_Exec_Comp_Stream_Acc_Output"} and temporal operators with bounded intervals. *}

text {* Temporal relation between uncompressed and compressed output of accelerated components. *}

thm i_shrink_eq_NoMsg_iAll_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_conv: "
  0 < k \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = \<NoMsg>) =
  (\<box> t1 [t * k\<dots>,k - Suc 0]. (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) t1 = \<NoMsg>)"
by (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_NoMsg_iAll_conv)
lemma i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_conv2: "
  0 < k \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = \<NoMsg>) =
  (\<box> t1 [\<dots>k - Suc 0] \<oplus> (t * k). (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) t1 = \<NoMsg>)"
by (simp add: iT_add i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_conv)

lemma i_Exec_Comp_Stream_Acc_Output__Init__eq_NoMsg_iAll_conv: "
  0 < k \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = \<NoMsg>) =
  (\<box> t1 [Suc (t * k)\<dots>,k - Suc 0]. (output_fun \<circ> i_Exec_Comp_Stream_Init trans_fun (input \<odot>\<^sub>i k) c) t1 = \<NoMsg>)"
apply (unfold i_Exec_Comp_Stream_Acc_Output_def)
thm i_shrink_eq_NoMsg_iAll_conv
apply (simp add: i_shrink_eq_NoMsg_iAll_conv i_Exec_Stream_Init_eq_i_Exec_Stream_Cons)
apply (rule_tac t="[Suc (t * k)\<dots>,k - Suc 0]" and s="[t * k\<dots>,k - Suc 0] \<oplus> 1" in subst)
 apply (simp add: iIN_add)
apply (simp add: iT_Plus_iAll_conv)
done

thm i_shrink_eq_Msg_iEx_iAll_cut_greater_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_iEx_iAll_cut_greater_conv: "
  \<lbrakk> 0 < k; m \<noteq> \<NoMsg>; s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) =
  (\<diamond> t1 [t * k\<dots>,k - Suc 0]. (s t1 = m \<and>
    (\<box> t2 [t * k\<dots>,k - Suc 0] \<down>> t1 . s t2 = \<NoMsg>)))"
by (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_Msg_iEx_iAll_cut_greater_conv)
thm i_shrink_eq_Msg_iEx_iAll_cut_greater_conv2
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_iEx_iAll_cut_greater_conv2: "
  \<lbrakk> 0 < k; m \<noteq> \<NoMsg>; s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) =
  (\<diamond> t1 [\<dots>k - Suc 0] \<oplus> (t * k). (s t1 = m \<and>
    (\<box> t2 ([\<dots>k - Suc 0] \<oplus> (t * k)) \<down>> t1 . s t2 = \<NoMsg>)))"
by (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_Msg_iEx_iAll_cut_greater_conv2)

thm i_shrink_eq_Msg_iSince_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_iSince_conv: "
  \<lbrakk> 0 < k; m \<noteq> \<NoMsg>; s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) =
  (s t2 = \<NoMsg>. t2 \<S> t1 [t * k\<dots>,k - Suc 0]. s t1 = m)"
by (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_Msg_iSince_conv)
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_iSince_conv2: "
  \<lbrakk> 0 < k; m \<noteq> \<NoMsg>; s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) =
  (s t2 = \<NoMsg>. t2 \<S> t1 [\<dots>k - Suc 0] \<oplus> (t * k). s t1 = m)"
by (simp add: i_Exec_Comp_Stream_Acc_Output__eq_Msg_iSince_conv iT_add)

thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_iSince_conv[OF _ _ refl]
lemma i_Exec_Comp_Stream_Acc_Output__Init__eq_Msg_iSince_conv: "
  \<lbrakk> 0 < k; m \<noteq> \<NoMsg>; s = (output_fun \<circ> i_Exec_Comp_Stream_Init trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) =
  (s t2 = \<NoMsg>. t2 \<S> t1 [Suc (t * k)\<dots>,k - Suc 0]. s t1 = m)"
apply (unfold i_Exec_Comp_Stream_Acc_Output_def)
apply (simp add: i_shrink_eq_Msg_iSince_conv i_Exec_Stream_Init_eq_i_Exec_Stream_Cons)
apply (rule_tac t="[Suc (t * k)\<dots>,k - Suc 0]" and s="[t * k\<dots>,k - Suc 0] \<oplus> 1" in subst)
 apply (simp add: iIN_add)
apply (simp add: iT_Plus_iSince_conv)
done
thm i_Exec_Comp_Stream_Acc_Output__Init__eq_Msg_iSince_conv[OF _ _ refl]

lemma i_Exec_Comp_Stream_Acc_Output__eq_iAll_iSince_conv: "
  \<lbrakk> 0 < k; s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) =
  ((m = \<NoMsg> \<longrightarrow> (\<box> t1 [t * k\<dots>,k - Suc 0]. s t1 = \<NoMsg>)) \<and>
  ((m \<noteq> \<NoMsg> \<longrightarrow> (s t2 = \<NoMsg>. t2 \<S> t1 [t * k\<dots>,k - Suc 0]. s t1 = m))))"
apply (case_tac "m = \<NoMsg>")
apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_conv)
apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_Msg_iSince_conv)
done
lemma i_Exec_Comp_Stream_Acc_Output__eq_iAll_iSince_conv2: "
  \<lbrakk> 0 < k; s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) =
  ((m = \<NoMsg> \<longrightarrow> (\<box> t1 [\<dots>k - Suc 0] \<oplus> (t * k). s t1 = \<NoMsg>)) \<and>
  ((m \<noteq> \<NoMsg> \<longrightarrow> (s t2 = \<NoMsg>. t2 \<S> t1 [\<dots>k - Suc 0] \<oplus> (t * k). s t1 = m))))"
by (simp add: i_Exec_Comp_Stream_Acc_Output__eq_iAll_iSince_conv iT_add)

subsection {* @{text "i_Exec_Comp_Stream_Acc_Output"} and temporal operators with unbounded intervals and start/finish events. *}

thm i_shrink_eq_NoMsg_iAll_start_event_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_start_event_conv: "
  \<lbrakk> 0 < k; \<And> t. event t = (t mod k = 0); t0 = t * k;
    s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk>\<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = \<NoMsg>) =
  (s t0 = \<NoMsg> \<and> (\<bigcirc> t' t0 [0\<dots>]. (s t1 = \<NoMsg>. t1 \<U> t2 [0\<dots>] \<oplus> t'. event t2)))"
by (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_NoMsg_iAll_start_event_conv)
lemma i_Exec_Comp_Stream_Acc_Output__Init__eq_NoMsg_iAll_start_event_conv: "
  \<lbrakk> 0 < k; \<And> t. event t = ((t + k - Suc 0) mod k = 0); t0 = Suc (t * k);
    s = (output_fun \<circ> i_Exec_Comp_Stream_Init trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk>\<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = \<NoMsg>) =
  (s t0 = \<NoMsg> \<and> (\<bigcirc> t' t0 [0\<dots>]. (s t1 = \<NoMsg>. t1 \<U> t2 [0\<dots>] \<oplus> t'. event t2)))"
apply (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_NoMsg_iAll_start_event_conv)
apply (simp add: iT_add iNext_def iFROM_inext iT_iff)
apply (simp add: i_Exec_Stream_Init_eq_i_Exec_Stream_Cons)
apply (rule_tac t="[Suc (Suc (t*k))\<dots>]" and s="[Suc (t*k)\<dots>] \<oplus> Suc 0" in subst)
 apply (simp add: iFROM_add)
thm iT_Plus_iUntil_conv
apply (simp add: iT_Plus_iUntil_conv)
done
lemma i_Exec_Comp_Stream_Acc_Output__Init__eq_NoMsg_iAll_start_event2_conv: "
  \<lbrakk> Suc 0 < k; \<And> t. event t = (t mod k = Suc 0); t0 = Suc (t * k);
    s = (output_fun \<circ> i_Exec_Comp_Stream_Init trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk>\<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = \<NoMsg>) =
  (s t0 = \<NoMsg> \<and> (\<bigcirc> t' t0 [0\<dots>]. (s t1 = \<NoMsg>. t1 \<U> t2 [0\<dots>] \<oplus> t'. event t2)))"
thm i_Exec_Comp_Stream_Acc_Output__Init__eq_NoMsg_iAll_start_event_conv
thm mod_eq_Suc_0_conv
by (simp add: i_Exec_Comp_Stream_Acc_Output__Init__eq_NoMsg_iAll_start_event_conv mod_eq_Suc_0_conv)

thm i_shrink_eq_Msg_iUntil_start_event_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_iUntil_start_event_conv: "
  \<lbrakk> 0 < k; m \<noteq> \<NoMsg>; \<And>t. event t = (t mod k = 0); t0 = t * k;
    s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) = (
  (s t0 = m \<and> (\<bigcirc> t' t0 [0\<dots>]. (s t1 = \<NoMsg>. t1 \<U> t2 ([0\<dots>] \<oplus> t'). event t2))) \<or>
  (\<bigcirc> t' t0 [0\<dots>]. (\<not> event t1. t1 \<U> t2 ([0\<dots>] \<oplus> t'). (
    s t2 = m \<and> \<not> event t2 \<and> (\<bigcirc> t'' t2 [0\<dots>].
      (s t3 = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t''). event t4))))))"
by (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_Msg_iUntil_start_event_conv)
lemma i_Exec_Comp_Stream_Acc_Output__Init__eq_Msg_iUntil_start_event_conv: "
  \<lbrakk> 0 < k; m \<noteq> \<NoMsg>; \<And>t. event t = ((t + k - Suc 0) mod k = 0); t0 = Suc (t * k);
    s = (output_fun \<circ> i_Exec_Comp_Stream_Init trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) = (
  (s t0 = m \<and> (\<bigcirc> t' t0 [0\<dots>]. (s t1 = \<NoMsg>. t1 \<U> t2 ([0\<dots>] \<oplus> t'). event t2))) \<or>
  (\<bigcirc> t' t0 [0\<dots>]. (\<not> event t1. t1 \<U> t2 ([0\<dots>] \<oplus> t'). (
    s t2 = m \<and> \<not> event t2 \<and> (\<bigcirc> t'' t2 [0\<dots>].
      (s t3 = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t''). event t4))))))"
apply (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_Msg_iUntil_start_event_conv)
apply (simp add: iNext_def iFROM_inext iFROM_iff iT_add)
apply (simp add: i_Exec_Stream_Init_eq_i_Exec_Stream_Cons)
apply (simp only: Suc_eq_plus1 iFROM_add[symmetric])
apply (simp add: iT_Plus_iUntil_conv)
apply (simp only: Suc_eq_plus1 iFROM_add[symmetric])
apply (simp add: iT_Plus_iUntil_conv)
done
lemma i_Exec_Comp_Stream_Acc_Output__Init__eq_Msg_iUntil_start_event2_conv: "
  \<lbrakk> Suc 0 < k; m \<noteq> \<NoMsg>; \<And>t. event t = (t mod k = Suc 0); t0 = Suc (t * k);
    s = (output_fun \<circ> i_Exec_Comp_Stream_Init trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk> \<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) = (
  (s t0 = m \<and> (\<bigcirc> t' t0 [0\<dots>]. (s t1 = \<NoMsg>. t1 \<U> t2 ([0\<dots>] \<oplus> t'). event t2))) \<or>
  (\<bigcirc> t' t0 [0\<dots>]. (\<not> event t1. t1 \<U> t2 ([0\<dots>] \<oplus> t'). (
    s t2 = m \<and> \<not> event t2 \<and> (\<bigcirc> t'' t2 [0\<dots>].
      (s t3 = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t''). event t4))))))"
by (simp add: i_Exec_Comp_Stream_Acc_Output__Init__eq_Msg_iUntil_start_event_conv mod_eq_Suc_0_conv)

thm i_shrink_eq_NoMsg_iAll_finish_event_conv
thm i_shrink_eq_Msg_iUntil_finish_event_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_finish_event_conv: "
  \<lbrakk> Suc 0 < k; \<And> t. event t = (t mod k = k - Suc 0); t0 = t * k;
    s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk>\<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = \<NoMsg>) =
  (s t0 = \<NoMsg> \<and> (\<bigcirc> t' t0 [0\<dots>]. (s t1 = \<NoMsg>. t1 \<U> t2 [0\<dots>] \<oplus> t'. event t2 \<and> s t2 = \<NoMsg>)))"
by (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_NoMsg_iAll_finish_event_conv)
lemma i_Exec_Comp_Stream_Acc_Output__Init__eq_NoMsg_iAll_finish_event_conv: "
  \<lbrakk> Suc 0 < k; \<And> t. event t = (t mod k = 0); t0 = Suc (t * k);
    s = (output_fun \<circ> i_Exec_Comp_Stream_Init trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk>\<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = \<NoMsg>) =
  (s t0 = \<NoMsg> \<and> (\<bigcirc> t' t0 [0\<dots>]. (s t1 = \<NoMsg>. t1 \<U> t2 [0\<dots>] \<oplus> t'. event t2 \<and> s t2 = \<NoMsg>)))"
apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_finish_event_conv)
apply (simp add: iNext_def iFROM_inext iFROM_iff iT_add)
apply (simp add: i_Exec_Stream_Init_eq_i_Exec_Stream_Cons)
apply (rule_tac t="[Suc (Suc (t * k))\<dots>]" and s="[Suc (t * k)\<dots>] \<oplus> 1" in subst)
 apply (simp add: iFROM_add)
thm iT_Plus_iUntil_conv
apply (simp add: iT_Plus_iUntil_conv)
apply (simp add: mod_eq_divisor_minus_Suc_0_conv)
done

thm i_shrink_eq_Msg_iUntil_finish_event_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_iUntil_finish_event_conv: "
  \<lbrakk> 0 < k; m \<noteq> \<NoMsg>; \<And> t. event t = (t mod k = k - Suc 0); t0 = t * k;
    s = (output_fun \<circ> i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk>\<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) =
  ((\<not> event t1. t1 \<U> t2 ([0\<dots>] \<oplus> t0). event t2 \<and> s t2 = m) \<or>
  (\<not> event t1. t1 \<U> t2 ([0\<dots>] \<oplus> t0). (\<not> event t2 \<and> s t2 = m \<and> (
    \<bigcirc> t' t2 [0\<dots>]. (s t3 = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t'). event t4 \<and> s t4 = \<NoMsg>)))))"
apply (case_tac "k = Suc 0")
 apply (simp add: iT_add iT_not_empty iFROM_Min)
apply (drule neq_le_trans[OF not_sym], simp)
thm i_shrink_eq_Msg_iUntil_finish_event_conv[unfolded One_nat_def]
apply (simp add: i_Exec_Comp_Stream_Acc_Output_def i_shrink_eq_Msg_iUntil_finish_event_conv)
done

lemma i_Exec_Comp_Stream_Acc_Output__Init__eq_Msg_iUntil_finish_event_conv: "
  \<lbrakk> Suc 0 < k; m \<noteq> \<NoMsg>; \<And> t. event t = (t mod k = 0); t0 = Suc (t * k);
    s = (output_fun \<circ> i_Exec_Comp_Stream_Init trans_fun (input \<odot>\<^sub>i k) c) \<rbrakk>\<Longrightarrow>
  ((i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c) t = m) =
  ((\<not> event t1. t1 \<U> t2 ([0\<dots>] \<oplus> t0). event t2 \<and> s t2 = m) \<or>
  (\<not> event t1. t1 \<U> t2 ([0\<dots>] \<oplus> t0). (\<not> event t2 \<and> s t2 = m \<and> (
    \<bigcirc> t' t2 [0\<dots>]. (s t3 = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t'). event t4 \<and> s t4 = \<NoMsg>)))))"
apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_Msg_iUntil_finish_event_conv)
apply (simp add: iNext_def iFROM_inext iT_iff)
apply (simp add: i_Exec_Stream_Init_eq_i_Exec_Stream_Cons)
apply (simp add: iT_Plus_iUntil_conv)
apply (simp add: mod_eq_divisor_minus_Suc_0_conv add_Suc[symmetric] del: add_Suc)
done

subsection {* @{text "i_Exec_Comp_Stream_Acc_Output"} and temporal operators with idle states. *}

thm
  f_expand_nth_interval_eq_nth_append_replicate_NoMsg
  f_expand_nth_interval_eq_replicate_NoMsg
  i_expand_nth_interval_eq_nth_append_replicate_NoMsg
  i_expand_nth_interval_eq_replicate_NoMsg

thm i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_conv
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_iSince_conv

thm i_Exec_Stream_Acc_Output__State_Idle_nth
lemma i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_State_Idle_conv: "
  \<lbrakk> 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = \<NoMsg>) =
  (output_fun (s t1) = \<NoMsg>. t1 \<U> t2 ([0\<dots>] \<oplus> t0). (
   output_fun (s t2) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t2))))"
apply (case_tac "k = Suc 0")
 apply (simp add: iUntil_def)
 apply (rule iffI)
  apply (rule_tac t=t in iexI)
   apply (simp add: iT_add iT_cut_less)
  apply (simp add: iT_add iT_iff)
 apply (clarify, rename_tac t1)
 apply (simp add: iT_add iT_iff iT_cut_less)
 apply (drule order_le_less[THEN iffD1])
 apply (erule disjE)
  apply (drule_tac t=t in ispec)
  apply (simp add: iT_iff)+
apply (drule order_neq_le_trans[OF not_sym Suc_leI], assumption)
thm i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_conv
apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_conv)
apply (simp add: iT_add i_Exec_Stream_nth i_Exec_Stream_Acc_LocalState_nth)
apply (simp add: i_take_Suc_conv_app_nth[of t])
apply (simp add: i_expand_i_take_mult[symmetric] f_Exec_append)
apply (subgoal_tac "\<forall>t1 \<in> [t * k\<dots>,k - Suc 0]. input \<odot>\<^sub>i k \<Down> Suc t1 \<up> (t * k) = input t # \<NoMsg>\<^bsup>t1 - t * k\<^esup>")
 prefer 2
 apply (simp add: i_expand_nth_interval_eq_nth_append_replicate_NoMsg iIN_iff)
apply (case_tac "output_fun (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> Suc (t * k)) c) \<noteq> \<NoMsg>")
 apply (subgoal_tac "
   \<not> (\<box> t1 [t * k\<dots>,k - Suc 0]. output_fun (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> Suc t1) c) = \<NoMsg>)")
  prefer 2
  apply simp
  apply (rule_tac t="t * k" in iexI, assumption)
  apply (simp add: iIN_iff)
 apply (simp add: not_iUntil del: not_iAll)
 apply (clarsimp simp: iT_iff, rename_tac t1 t2)
 apply (case_tac "t1 = t * k", simp)
 apply (drule order_le_neq_trans[OF _ not_sym], assumption)
 apply (rule_tac t="t * k" in iexI, simp)
 apply (simp add: iFROM_cut_less1 iIN_iff)

apply (case_tac "
  State_Idle localState output_fun trans_fun
    (localState ((trans_fun (input t) (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> (t * k)) c))))")
 apply (subgoal_tac "
   (\<box> t1 [t * k\<dots>,k - Suc 0]. output_fun (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> Suc t1) c) = NoMsg)")
  prefer 2
  apply (clarsimp simp: iIN_iff, rename_tac t1)
  thm subst[OF i_take_drop_append, rule_format]
  apply (rule_tac m="t * k" and n="Suc t1" in subst[OF i_take_drop_append, rule_format], simp)
  apply (drule_tac x=t1 in bspec, simp add: iT_iff)
  apply (simp add: f_Exec_append del: i_take_drop_append)
  apply (simp add: i_take_Suc_conv_app_nth f_Exec_append i_expand_nth_mult)
  thm f_Exec_State_Idle_replicate_NoMsg_output
  apply (rule f_Exec_State_Idle_replicate_NoMsg_output, assumption+)
 apply (simp add: iUntil_def)
 apply (rule_tac t="t * k" in iexI)
  apply (simp add: i_take_Suc_conv_app_nth f_Exec_append i_expand_nth_mult iFROM_cut_less)
 apply (simp add: iFROM_iff)
apply (subgoal_tac "\<forall>i < k. input \<odot>\<^sub>i k \<Up> Suc (t * k) \<Down> i = NoMsg\<^bsup>i\<^esup>")
 prefer 2
 apply (simp add: list_eq_iff i_expand_nth_if)
apply (rule iffI)
 thm State_Idle_imp_exists_state_change2
 apply (frule State_Idle_imp_exists_state_change2, assumption)
 apply (elim exE conjE, rename_tac i)
 apply (frule Suc_less_pred_conv[THEN iffD2])
 apply (simp only: iUntil_def)
 apply (rule_tac t="Suc (t * k + i)" in iexI)
  apply (rule conjI)
   apply (drule_tac t="Suc (t * k + i)" in ispec)
    apply (simp add: iIN_iff)
   apply (rule conjI, simp)
   apply (rule_tac t="Suc (Suc (t * k + i))" and s="Suc (t * k) + Suc i" in subst, simp)
   apply (subst i_take_add)
   apply (drule_tac x="Suc i" in spec)+
   apply (simp add: i_take_Suc_conv_app_nth f_Exec_append i_expand_nth_mult)
  apply (rule iallI, rename_tac t1)
  apply (drule_tac t=t1 in ispec)
   apply (drule_tac m="Suc i" in less_imp_le_pred)
   apply (clarsimp simp: iIN_iff iFROM_cut_less1)
   apply (rule order_trans, assumption)
   apply simp
  apply assumption
 apply (simp add: iFROM_iff)
apply (rule iallI)
apply (unfold iUntil_def, elim iexE conjE, rename_tac t2)
apply (case_tac "t1 < t2")
 apply (drule_tac t=t1 in ispec)
  apply (simp add: cut_less_mem_iff iT_iff)
 apply simp
apply (simp add: linorder_not_less)
apply (case_tac "t1 = t2", simp)
apply (drule le_neq_trans[OF _ not_sym], assumption)
apply (drule_tac i=t2 in less_imp_add_positive, elim exE conjE, rename_tac i)
apply (drule_tac t=t1 in sym)
apply (simp del: add_Suc add: add_Suc[symmetric] i_take_add f_Exec_append iFROM_iff)
apply (rule_tac t="input \<odot>\<^sub>i k \<Up> Suc t2 \<Down> i" and s="\<NoMsg>\<^bsup>i\<^esup>" in subst)
 apply (rule list_eq_iff[THEN iffD2])
 apply simp
 apply (intro allI impI, rename_tac i1)
 apply (simp add: i_expand_nth_if)
 apply (subst imp_conv_disj, rule disjI1)
 thm if_not_P'
 apply simp
 apply (subgoal_tac "t * k < Suc (t2 + i1) \<and> Suc (t2 + i1) < t * k + k", elim conjE)
  prefer 2
  apply (simp add: iIN_iff)
 apply (simp only: mult.commute[of _ k])
 apply (rule between_imp_mod_gr0, assumption+)
thm f_Exec_State_Idle_replicate_NoMsg_gr0_output
apply (rule f_Exec_State_Idle_replicate_NoMsg_gr0_output, assumption+)
done
thm i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_State_Idle_conv
thm i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_State_Idle_conv[OF _ _ refl refl]

lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_imp: "
  \<lbrakk> 0 < k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    t0 = t * k;
    t1 \<in> [0\<dots>, k - Suc 0] \<oplus> t0;
    State_Idle localState output_fun trans_fun (localState (s t1));
    output_fun (s t1) \<noteq> \<NoMsg> \<rbrakk> \<Longrightarrow>
  i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = output_fun (s t1)"
apply (case_tac "k = Suc 0")
 apply (simp add: iIN_0 iT_Plus_singleton)
apply (drule order_neq_le_trans[OF not_sym], rule Suc_leI, assumption)
apply (simp add: iT_add iT_iff, erule conjE)
apply (simp only: i_Exec_Stream_Acc_Output_nth i_Exec_Stream_nth)
apply (rule_tac t="Suc t1" and s="t * k + (Suc t1 - t * k)" in subst, simp)
apply (simp only: i_take_add f_Exec_append i_expand_i_take_mult)
apply (subgoal_tac "input \<odot>\<^sub>i k \<Up> (t * k) \<Down> (Suc t1 - t * k) = input t # \<NoMsg>\<^bsup>t1 - t * k\<^esup>")
 prefer 2
 apply (simp add: i_take_i_drop)
 apply (subst i_expand_nth_interval_eq_nth_append_replicate_NoMsg)
 apply (simp del: f_Exec_Comp_Stream.simps)+
apply (subgoal_tac "\<exists>i. k - Suc 0 = t1 - t * k + i")
 prefer 2
 thm le_iff_add[THEN iffD1]
 apply (rule le_iff_add[THEN iffD1])
 apply (simp add: le_diff_conv)
apply (erule exE)
apply (simp only: replicate_add)
apply (subst append_Cons[symmetric])
thm State_Idle_append_replicate_NoMsg_output_last_message
apply (subst State_Idle_append_replicate_NoMsg_output_last_message)
 apply (simp only: f_Exec_append[symmetric])
 apply (rule_tac t="input \<Down> t \<odot>\<^sub>f k @ input t # NoMsg\<^bsup>t1 - t * k\<^esup>" and s="input \<odot>\<^sub>i k \<Down> Suc t1" in subst)
  apply (subst i_expand_i_take_mult[symmetric])
  apply (drule_tac t="input t # NoMsg\<^bsup>t1 - t * k\<^esup>" in sym)
  apply (simp add: i_take_add[symmetric])
 apply assumption
apply (subgoal_tac "
  f_Exec_Comp_Stream trans_fun (input t # NoMsg\<^bsup>t1 - t * k\<^esup>)
   (f_Exec_Comp trans_fun (input \<Down> t \<odot>\<^sub>f k) c) \<noteq> []")
 prefer 2
 apply (simp add: f_Exec_Stream_not_empty_conv)
thm last_message_Msg_eq_last
apply (rule ssubst[OF last_message_Msg_eq_last])
  apply simp
 apply (subst map_last, simp)
 thm f_Exec_eq_f_Exec_Stream_last2
 apply (subst f_Exec_eq_f_Exec_Stream_last2[symmetric], simp)
 apply (subst f_Exec_append[symmetric])
 apply (rule_tac t="input \<Down> t \<odot>\<^sub>f k @ input t # NoMsg\<^bsup>t1 - t * k\<^esup>" and s="input \<odot>\<^sub>i k \<Down> Suc t1" in subst)
  apply (subst i_expand_i_take_mult[symmetric])
  apply (rule_tac t="Suc t1" and s="t * k + (Suc t1 - t * k)" in subst, simp)
  apply (subst i_take_add, simp)
 apply assumption
apply (subst map_last, simp)
apply (subst f_Exec_eq_f_Exec_Stream_last2[symmetric], simp+)
done

thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_iSince_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv2: "
  \<lbrakk> 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    t1 \<in> [0\<dots>, k - Suc 0] \<oplus> t0;
    State_Idle localState output_fun trans_fun (localState (s t1));
    output_fun (s t1) \<noteq> \<NoMsg> \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m) =
  (\<diamond> t1 [0\<dots>, k - Suc 0] \<oplus> t0. (
      (output_fun (s t1) = m \<and> State_Idle localState output_fun trans_fun (localState (s t1)))))"
apply (case_tac "k = Suc 0")
 apply (simp add: iIN_0 iT_Plus_singleton)
apply (drule order_neq_le_trans[OF not_sym], rule Suc_leI, assumption)
apply simp
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_imp
apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_imp)
apply (rule iffI)
 apply blast
apply (clarify, rename_tac t1')
apply (subgoal_tac "t1' = t1")
 prefer 2
 apply (rule ccontr)
 apply (simp add: i_Exec_Stream_nth)
 apply (subgoal_tac "
   \<And> n1 n2.
   \<lbrakk> n1 < n2; n1 \<in> [0\<dots>,k - Suc 0] \<oplus> t * k; n2 \<in> [0\<dots>,k - Suc 0] \<oplus> t * k;
     State_Idle localState output_fun trans_fun (localState (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> Suc n1) c));
     output_fun (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> Suc n2) c) \<noteq> NoMsg \<rbrakk> \<Longrightarrow>
   False")
  prefer 2
  apply (drule_tac i=n1 in less_imp_add_positive, elim exE conjE, rename_tac i)
  apply (drule_tac t=n2 in sym, simp)
  apply (simp only: add_Suc[symmetric] i_take_add f_Exec_append)
  thm i_expand_nth_interval_eq_replicate_NoMsg
  apply (subgoal_tac "input \<odot>\<^sub>i k \<Up> Suc n1 \<Down> i = \<NoMsg>\<^bsup>i\<^esup>")
   prefer 2
   apply (subst i_take_i_drop)
   apply (rule_tac t="\<NoMsg>\<^bsup>i\<^esup>" and s="\<NoMsg>\<^bsup>i + Suc n1 - Suc n1\<^esup>" in subst, simp)
   thm i_expand_nth_interval_eq_replicate_NoMsg
   apply (rule_tac t=t in i_expand_nth_interval_eq_replicate_NoMsg)
   apply (simp add: iT_add iT_iff)+
  thm f_Exec_State_Idle_replicate_NoMsg_gr0_output
  apply (frule_tac c="f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> Suc n1) c" and n=i
     in f_Exec_State_Idle_replicate_NoMsg_gr0_output)
  apply (fastforce dest: linorder_neq_iff[THEN iffD1])+
done

text {* Here the property to be checked uses only unbounded intervals suitable for LTL. *}
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv: "
  \<lbrakk> 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    t1 \<in> [0\<dots>, k - Suc 0] \<oplus> t0;
    State_Idle localState output_fun trans_fun (localState (s t1));
    output_fun (s t1) \<noteq> \<NoMsg> \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m) =
  ((\<not> State_Idle localState output_fun trans_fun (localState (s t2))). t2 \<U> t1 [0\<dots>] \<oplus> t0. (
      (output_fun (s t1) = m \<and> State_Idle localState output_fun trans_fun (localState (s t1)))))"
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv2
apply (subst i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv2, assumption+)
apply (unfold iUntil_def)
apply (rule iffI)
 apply (elim iexE conjE, rename_tac t2)
 apply (rule_tac t=t2 in iexI)
  prefer 2
  apply (simp add: iT_add iT_iff)
 apply simp
 apply (rule iallI, rename_tac t2')
 apply (rule ccontr)
 apply (simp add: cut_less_mem_iff iT_iff iT_add, elim conjE)
 apply (frule_tac n=t2' in le_imp_less_Suc)
 apply (frule_tac i=t2' in less_imp_add_positive, elim exE conjE, rename_tac i)
 apply (drule_tac t=t2 in sym)
 apply (simp only: i_Exec_Stream_nth add_Suc[symmetric] i_take_add f_Exec_append)
 apply (simp only: i_take_i_drop)
 apply (subgoal_tac "input \<odot>\<^sub>i k \<Down> (i + Suc t2') \<up> Suc t2' = \<NoMsg>\<^bsup>i\<^esup>")
  prefer 2
  thm i_expand_nth_interval_eq_replicate_NoMsg
  apply (rule_tac t="\<NoMsg>\<^bsup>i\<^esup>" and s="\<NoMsg>\<^bsup>i + Suc t2' - Suc t2'\<^esup>" in subst, simp)
  apply (rule_tac t=t in i_expand_nth_interval_eq_replicate_NoMsg)
  apply simp+
 thm f_Exec_State_Idle_replicate_NoMsg_gr0_output
 apply (drule_tac c="(f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> Suc t2') c)" and n=i
   in f_Exec_State_Idle_replicate_NoMsg_gr0_output, assumption)
 apply simp
apply (fastforce simp: iT_add iT_iff i_Exec_Stream_Acc_LocalState_nth i_Exec_Stream_nth)
done

lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp2: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    t1 \<in> [0\<dots>, k - Suc 0] \<oplus> t0;
    output_fun (s t1) = m;
    \<bigcirc> t2 t1 [0\<dots>].
     ((output_fun (s t3) = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t2).
      (output_fun (s t4) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t4))))) \<rbrakk> \<Longrightarrow>
  i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m"
apply (clarsimp simp: iUntil_def iNext_def iT_inext iT_iff, rename_tac t2)
apply (simp only: i_Exec_Stream_Acc_Output_nth i_Exec_Stream_Acc_LocalState_nth i_Exec_Stream_nth)
apply (rule last_message_conv[THEN iffD2], assumption)
apply (clarsimp simp: iT_add iT_iff simp del: f_Exec_Comp_Stream.simps)
apply (subgoal_tac "t1 - t * k < k")
 prefer 2
 apply simp
apply (rule_tac x="t1 - t * k" in exI)
apply (rule conjI, simp)
apply (rule conjI)
 apply (simp add: f_Exec_Stream_nth min_eqL del: f_Exec_Comp.simps f_Exec_Comp_Stream.simps)
 apply (simp only: f_Exec_append[symmetric])
 thm i_expand_i_take_mult_Suc
 apply (subst i_expand_i_take_mult_Suc[symmetric], assumption)
 apply simp
apply (intro allI impI)
apply (simp only: f_Exec_Stream_length length_Cons length_replicate Suc_pred
  nth_map f_Exec_Stream_nth take_Suc_Cons take_replicate min_eqL[OF less_imp_le_pred])
apply (subst f_Exec_append[symmetric])
apply (subst i_expand_i_take_mult_Suc[symmetric], assumption)
apply (case_tac "t2 \<le> t * k + j")
 prefer 2
 apply fastforce
apply (drule_tac x=t2 in order_le_less[THEN iffD1, rule_format])
apply (erule disjE)
 prefer 2
 apply simp
apply (subgoal_tac "
  State_Idle localState output_fun trans_fun
    (localState (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> (t * k + Suc j)) c))")
 prefer 2
 apply (rule_tac t="t * k + Suc j" and s="Suc t2 + (t * k + j - t2)" in subst, simp)
 apply (simp only: i_take_add f_Exec_append)
 apply (simp only: i_take_i_drop)
 apply simp
 thm i_expand_nth_interval_eq_replicate_NoMsg
 apply (rule_tac t=t in ssubst[OF i_expand_nth_interval_eq_replicate_NoMsg, rule_format], simp+)
 thm f_Exec_State_Idle_replicate_NoMsg_state
 apply (simp add: f_Exec_State_Idle_replicate_NoMsg_state)
apply (subgoal_tac "t1 div k = t \<and> t2 div k = t", elim conjE)
 prefer 2
 thm le_less_imp_div
 apply (simp add: le_less_imp_div)
apply (simp only: i_expand_i_take_Suc i_expand_i_take_mult_Suc f_Exec_append)
apply (simp add: f_Exec_append)
thm f_Exec_State_Idle_replicate_NoMsg_gr_output
apply (rule_tac m="t2 mod k" in f_Exec_State_Idle_replicate_NoMsg_gr_output, assumption)
apply (simp add: mod_div_equality')
done

lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv2: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    \<box> t1 [0\<dots>, k - Suc 0] \<oplus> t0. \<not> (
      State_Idle localState output_fun trans_fun (localState (s t1)) \<and>
      output_fun (s t1) \<noteq> \<NoMsg>) \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m) =
  (\<diamond> t1 [0\<dots>, k - Suc 0] \<oplus> t0. (
     (output_fun (s t1) = m) \<and>
     (\<bigcirc> t2 t1 [0\<dots>].
      ((output_fun (s t3) = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t2).
      (output_fun (s t4) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t4))))))))"
apply (rule iffI)
 apply (simp only: i_Exec_Stream_Acc_Output_nth i_Exec_Stream_nth)
 apply (simp only: iNext_def iFROM_iff iFROM_inext)
 thm last_message_conv
 thm last_message_conv[THEN iffD1]
 apply (frule last_message_conv[THEN iffD1], assumption)
 apply (elim exE conjE, rename_tac i)
 apply (simp add: f_Exec_Stream_nth min_eqL del: f_Exec_Comp.simps f_Exec_Comp_Stream.simps de_Morgan_conj)
 apply (subgoal_tac "
   \<box> t' ([0\<dots>] \<oplus> (Suc (t * k + i))) \<down>< (t * k + k).
   output_fun (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> Suc t') c) = \<NoMsg>")
  prefer 2
  apply (rule iallI, rename_tac t')
  apply (simp only: iT_add iT_iff cut_less_mem_iff, erule conjE)
  apply (drule_tac x="t' - t * k" in spec)
  apply (subgoal_tac "t' - t * k < k")
   prefer 2
   apply simp
  apply (simp add: f_Exec_Stream_nth min_eqL del: f_Exec_Comp_Stream.simps de_Morgan_conj)
  apply (subgoal_tac "t * k \<le> t'")
   prefer 2
   apply simp
  apply (rule_tac t="Suc t'" and s="t * k + (Suc t' - t * k)" in subst, simp)
  apply (simp only: i_take_add f_Exec_append i_expand_i_take_mult)
  apply (simp add: i_take_i_drop)
  thm i_expand_nth_interval_eq_nth_append_replicate_NoMsg
  apply (rule ssubst[OF i_expand_nth_interval_eq_nth_append_replicate_NoMsg])
  apply (simp del: f_Exec_Comp_Stream.simps de_Morgan_conj)+
 apply (rule_tac t="t * k + i" in iexI)
  prefer 2
  apply (simp add: iT_add iT_iff)
 apply (rule conjI)
  thm i_expand_i_take_mult_Suc
  apply (simp add: add_Suc_right[symmetric] i_expand_i_take_mult_Suc f_Exec_append del: add_Suc_right)
 apply (simp only: i_Exec_Stream_Acc_LocalState_nth i_expand_i_take_mult[symmetric] mult_Suc add.commute[of k])
 apply (subgoal_tac "
   \<not> State_Idle localState output_fun trans_fun
       (localState (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> (t * k + Suc i)) c))")
  prefer 2
  apply (drule_tac t="t * k + i" in ispec)
   apply (simp add: iT_add iT_iff)
  apply (simp add: add_Suc_right[symmetric] i_expand_i_take_mult_Suc f_Exec_append i_expand_i_take_mult del: add_Suc_right)
 apply (thin_tac "last_message ?x = m")
 apply (drule_tac
   a="t * k + k" and b="t * k + Suc (k - Suc 0)" and
   P="\<lambda>x. State_Idle localState output_fun trans_fun
          (localState (f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> x) c))" in back_subst, simp)
  apply (simp only: i_expand_i_take_mult_Suc f_Exec_append)
 thm State_Idle_imp_exists_state_change
 apply (frule_tac n="k - Suc 0 - i" in State_Idle_imp_exists_state_change)
  apply (simp add: f_Exec_append[symmetric] replicate_add[symmetric])
 apply (elim exE conjE, rename_tac i1)
 thm less_diff_conv[THEN iffD1, rule_format]
 apply (frule_tac i=i1 in less_diff_conv[THEN iffD1, rule_format])
 thm subst[OF add.commute, rule_format]
 apply (drule_tac a=i1 and P="\<lambda>x. (x < k - Suc 0)" in subst[OF add.commute, rule_format])
 apply (frule Suc_less_pred_conv[THEN iffD2])
 apply (simp only: iUntil_def)
 apply (rule_tac t="t * k + Suc (i + i1)" in iexI)
  prefer 2
  apply (simp add: iT_add iT_iff)
 apply (rule conjI)
  apply (drule_tac t="t * k + Suc (i + i1)" in ispec)
   apply (simp add: iT_add iT_iff cut_less_mem_iff)
  apply (subgoal_tac "Suc (t * k + Suc (i + i1)) = t * k + Suc (Suc (i + i1))")
   prefer 2
   apply simp
  thm i_expand_i_take_mult_Suc
  apply (simp only: i_expand_i_take_mult_Suc f_Exec_append)
  apply (simp add: add_Suc_right[symmetric] replicate_add f_Exec_append del: add_Suc_right replicate.simps)
 apply (clarsimp simp: cut_less_mem_iff iT_add iT_iff simp del: f_Exec_Comp_Stream.simps, rename_tac t')
 apply (subgoal_tac "\<exists>i'>i. t' = t * k + i'")
  prefer 2
  apply (rule_tac x="t' - t * k" in exI)
  apply simp
 apply (thin_tac "iAll ?I ?P")+
 apply (elim exE conjE)
 apply (subgoal_tac "i' < k")
  prefer 2
  apply simp
 apply (simp add: add_Suc_right[symmetric] i_expand_i_take_mult_Suc f_Exec_append f_Exec_Stream_nth min_eqL i_expand_i_take_mult del: add_Suc_right f_Exec_Comp_Stream.simps)
apply (elim iexE conjE, rename_tac t1)
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp2
apply (rule i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp2, assumption+)
done

text {* Here the property to be checked uses only unbounded intervals suitable for LTL. *}
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    (\<not> State_Idle localState output_fun trans_fun (localState (s t1))). t1 \<U> t2 [0\<dots>] \<oplus> t0. (
    (output_fun (s t2) = m) \<and>
    (\<bigcirc> t3 t2 [0\<dots>].
      ((output_fun (s t4) = \<NoMsg>. t4 \<U> t5 ([0\<dots>] \<oplus> t3).
       (output_fun (s t5) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t5))))))) \<rbrakk> \<Longrightarrow>
  i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m"
apply (case_tac "
  \<diamond> t1 [0\<dots>, k - Suc 0] \<oplus> t0. (
      State_Idle localState output_fun trans_fun (localState (s t1)) \<and>
      output_fun (s t1) \<noteq> \<NoMsg>)")
 apply (clarsimp, rename_tac t1)
 thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_imp[OF Suc_lessD refl refl]
 apply (frule i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_imp[OF Suc_lessD refl refl], assumption+)
 apply (simp only: iNext_def iT_inext iT_iff iUntil_def)
 apply (elim iexE conjE, rename_tac t2 t3)
 apply (subgoal_tac "t2 \<le> t1")
  prefer 2
  apply (rule ccontr)
  apply (drule_tac t=t1 in ispec)
   apply (simp add: cut_less_mem_iff iT_add iT_iff)
  apply simp
 apply (thin_tac "iAll ?I ?P")
 apply (subgoal_tac "t1 \<le> t2")
  prefer 2
  apply (rule ccontr)
  apply (subgoal_tac "t3 < t1 \<longrightarrow> output_fun (i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c t1) = \<NoMsg>")
   prefer 2
   apply (rule impI)
   apply (subgoal_tac "t * k \<le> t3")
    prefer 2
    apply (simp add: iT_add iT_iff)
   apply (subgoal_tac "t1 div k = t \<and> t3 div k = t", elim conjE)
    prefer 2
    apply (simp add: iT_add iT_iff le_less_imp_div)
   apply (simp (no_asm_simp) add: i_Exec_Stream_nth i_expand_i_take_Suc f_Exec_append)
   thm f_Exec_State_Idle_replicate_NoMsg_gr_output
   apply (rule_tac m="t3 mod k" in f_Exec_State_Idle_replicate_NoMsg_gr_output[of localState output_fun trans_fun])
    apply (simp add: i_Exec_Stream_nth i_expand_i_take_Suc f_Exec_append)
   apply (simp add: mod_div_equality')
  apply (case_tac "t1 < t3")
   apply (drule_tac t=t1 in ispec)
    apply (simp add: cut_less_mem_iff iT_add iT_iff)
   apply simp+
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv2
apply (rule ssubst[OF i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv2], simp+)
apply (simp only: iNext_def iT_inext iT_iff iUntil_def)
apply (elim iexE conjE, rename_tac t1 t2)
apply (subgoal_tac "t1 \<le> t * k + (k - Suc 0)")
 prefer 2
 apply (rule ccontr)
 apply (simp add: i_Exec_Stream_Acc_LocalState_nth i_expand_i_take_mult[symmetric] add.commute[of k])
 apply (thin_tac "iAll ?I ?P")
 apply (drule_tac t="t * k + (k - Suc 0)" in ispec)
  apply (simp add: cut_less_mem_iff iT_add iT_iff)
 apply (simp add: i_Exec_Stream_nth)
apply (rule_tac t=t1 in iexI)
 prefer 2
 apply (simp add: iT_add iT_iff)
apply simp
apply (rule_tac t=t2 in iexI)
apply simp+
done
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    \<box> t1 [0\<dots>, k - Suc 0] \<oplus> t0. \<not> (
      State_Idle localState output_fun trans_fun (localState (s t1)) \<and>
      output_fun (s t1) \<noteq> \<NoMsg>) \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m) =
  ((\<not> State_Idle localState output_fun trans_fun (localState (s t1))). t1 \<U> t2 [0\<dots>] \<oplus> t0. (
     (output_fun (s t2) = m) \<and>
     (\<bigcirc> t3 t2 [0\<dots>].
       ((output_fun (s t4) = \<NoMsg>. t4 \<U> t5 ([0\<dots>] \<oplus> t3).
        (output_fun (s t5) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t5))))))))"
apply (rule iffI)
 thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv2
 thm subst[OF i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv2, where P="\<lambda>x. x"]
 apply (frule subst[OF i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv2, where P="\<lambda>x. x"], assumption+)
 apply (simp only: iNext_def iT_inext iT_iff iUntil_def)
 apply (elim iexE conjE, rename_tac t1 t2)
 apply (rule_tac t=t1 in iexI)
  prefer 2
  apply (simp add: iT_add iT_iff)
 apply (intro conjI)
   apply simp
  apply (rule_tac t=t2 in iexI)
   prefer 2
   apply (simp add: iT_add iT_iff)
  apply simp
 apply (rule iallI, rename_tac t')
 apply (rule ccontr)
 apply (clarsimp simp: cut_less_mem_iff)
 apply (drule_tac i=t' in less_imp_add_positive)
 apply (elim exE conjE, rename_tac i)
 apply (drule_tac t=t1 in sym)
 apply (simp only: i_Exec_Stream_nth)
 apply (simp only: add_Suc[symmetric] i_take_add f_Exec_append)
 apply (simp only: i_take_i_drop)
 thm i_expand_nth_interval_eq_replicate_NoMsg
 apply (subgoal_tac "i + Suc t' \<le> t * k + k")
  prefer 2
  apply (simp add: iT_add iT_iff)
 apply (simp only: iT_add iT_iff)
 thm i_expand_nth_interval_eq_replicate_NoMsg[of k t "Suc t'", OF _ le_imp_less_Suc le_add2]
 apply (simp only: i_expand_nth_interval_eq_replicate_NoMsg[of k t, OF _ le_imp_less_Suc le_add2])
 thm f_Exec_State_Idle_replicate_NoMsg_gr0_output
 apply (drule_tac c="f_Exec_Comp trans_fun (input \<odot>\<^sub>i k \<Down> Suc t') c" and n=i in f_Exec_State_Idle_replicate_NoMsg_gr0_output)
 apply simp+
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp
apply (rule i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp, simp+)
done

thm
  i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv2
  i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv2
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m) =
  (\<diamond> t1 [0\<dots>, k - Suc 0] \<oplus> t0. (
    output_fun (s t1) = m \<and>
    (State_Idle localState output_fun trans_fun (localState (s t1)) \<or>
    (\<bigcirc> t2 t1 [0\<dots>].
      ((output_fun (s t3) = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t2).
       (output_fun (s t4) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t4)))))))))"
apply (subst conj_disj_distribL)
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv2
apply (case_tac "
  \<diamond> t1 [0\<dots>,k - Suc 0] \<oplus> t0.
    (State_Idle localState output_fun trans_fun (localState (s t1)) \<and> output_fun (s t1) \<noteq> \<NoMsg>)")
 apply (elim iexE conjE, rename_tac t1)
 apply (rule iffI)
  thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv2[THEN iffD1, OF Suc_lessD]
  apply (frule i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv2[THEN iffD1, OF Suc_lessD], assumption+)
  apply fastforce
 apply (elim iexE conjI, rename_tac t2)
 apply (erule disjE)
  thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv2
  apply (rule i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv2[THEN iffD2], simp+)
  apply (rule_tac t=t2 in iexI, simp+)
 thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp2
 apply (rule_tac ?t1.0=t2 in i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp2, simp+)
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv2[OF _ _ _ refl refl]
apply (rule ssubst[OF i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv2[OF _ _ _ refl refl]], simp+)
apply fastforce
done
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2': "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m) =
  ((\<diamond> t1 [0\<dots>, k - Suc 0] \<oplus> t0. (
      output_fun (s t1) = m \<and> State_Idle localState output_fun trans_fun (localState (s t1)))) \<or>
  (\<diamond> t1 [0\<dots>, k - Suc 0] \<oplus> t0. (
      ((output_fun (s t1) = m) \<and>
        (\<bigcirc> t2 t1 [0\<dots>].
          ((output_fun (s t3) = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t2).
           (output_fun (s t4) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t4))))))))))"
apply (subst i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2, assumption+)
apply blast
done

thm i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_State_Idle_conv
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2
lemma i_Exec_Comp_Stream_Acc_Output__eq_iAll_iUntil_State_Idle_conv2: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m) = (
  (m = \<NoMsg> \<longrightarrow>
    (output_fun (s t1) = \<NoMsg>. t1 \<U> t2 ([0\<dots>] \<oplus> t0). (
     output_fun (s t2) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t2))))) \<and>
  (m \<noteq> \<NoMsg> \<longrightarrow>
    (\<diamond> t1 [0\<dots>, k - Suc 0] \<oplus> t0. (
      output_fun (s t1) = m \<and>
      (State_Idle localState output_fun trans_fun (localState (s t1)) \<or>
      (\<bigcirc> t2 t1 [0\<dots>].
        ((output_fun (s t3) = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t2).
         (output_fun (s t4) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t4)))))))))))"
apply (case_tac "m = \<NoMsg>")
 apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_State_Idle_conv)
apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2)
done

thm
  i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv
  i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv': "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m) =
  (((\<not> State_Idle localState output_fun trans_fun (localState (s t2))). t2 \<U> t1 [0\<dots>] \<oplus> t0.
    (output_fun (s t1) = m \<and> State_Idle localState output_fun trans_fun (localState (s t1)))) \<or>
  ((\<not> State_Idle localState output_fun trans_fun (localState (s t2))). t2 \<U> t1 [0\<dots>] \<oplus> t0.
   (output_fun (s t1) = m \<and>
   (\<bigcirc> t3 t1 [0\<dots>].
     ((output_fun (s t4) = \<NoMsg>. t4 \<U> t5 ([0\<dots>] \<oplus> t3).
      (output_fun (s t5) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t5)))))))))"
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv
apply (case_tac "
  \<diamond> t1 [0\<dots>,k - Suc 0] \<oplus> t0.
    (State_Idle localState output_fun trans_fun (localState (s t1)) \<and> output_fun (s t1) \<noteq> \<NoMsg>)")
 apply (elim iexE conjE, rename_tac t1)
 apply (rule iffI)
  thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv[THEN iffD1, OF Suc_lessD]
  apply (frule i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv[THEN iffD1, OF Suc_lessD], simp+)
 apply (erule disjE)
  thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv
  apply (rule i_Exec_Comp_Stream_Acc_Output__eq_Msg_with_State_Idle_conv[THEN iffD2], simp+)
 thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp
 apply (rule_tac i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_imp, simp+)
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv[OF _ _ _ refl refl]
apply (subst i_Exec_Comp_Stream_Acc_Output__eq_Msg_before_State_Idle_conv[OF _ _ _ refl refl], simp+)
apply (rule iffI)
 apply simp
apply (unfold iUntil_def, erule disjE)
 apply (elim iexE conjE, rename_tac t1)
 apply (case_tac "t1 \<le> t * k + (k - Suc 0)")
  prefer 2
  apply (simp add: i_Exec_Stream_Acc_LocalState_nth i_Exec_Stream_nth i_expand_i_take_mult[symmetric])
  apply (thin_tac "iAll ?I ?P")
  apply (drule_tac t="t * k + (k - Suc 0)" in ispec)
   apply (simp add: cut_less_mem_iff iT_add iT_iff)
  apply (simp add: add.commute[of k])
 apply (fastforce simp: iT_add iT_iff)+
done

thm i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_State_Idle_conv
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv
lemma i_Exec_Comp_Stream_Acc_Output__eq_iUntil_State_Idle_conv: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c \<rbrakk> \<Longrightarrow>
  (i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m) = (
  (m = \<NoMsg> \<longrightarrow>
    (output_fun (s t1) = \<NoMsg>. t1 \<U> t2 ([0\<dots>] \<oplus> t0). (
     output_fun (s t2) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t2))))) \<and>
  (m \<noteq> \<NoMsg> \<longrightarrow>
    (((\<not> State_Idle localState output_fun trans_fun (localState (s t2))). t2 \<U> t1 [0\<dots>] \<oplus> t0.
      (output_fun (s t1) = m \<and>
        (State_Idle localState output_fun trans_fun (localState (s t1)) \<or>
        (\<bigcirc> t3 t1 [0\<dots>].
            ((output_fun (s t4) = \<NoMsg>. t4 \<U> t5 ([0\<dots>] \<oplus> t3).
             (output_fun (s t5) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t5))))))))))))"
apply (case_tac "m = \<NoMsg>")
 apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_State_Idle_conv)
apply (simp add: i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv)
done

text {* Sufficient conditions for output messages. *}
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2'
corollary i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_iEx_imp1: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    (\<diamond> t1 [0\<dots>, k - Suc 0] \<oplus> t0. (
       output_fun (s t1) = m \<and> State_Idle localState output_fun trans_fun (localState (s t1)))) \<rbrakk> \<Longrightarrow>
  i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m"
by (blast intro: i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2'[THEN iffD2])
corollary i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_iEx_imp2: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    \<diamond> t1 [0\<dots>, k - Suc 0] \<oplus> t0. (
          ((output_fun (s t1) = m) \<and>
            (\<bigcirc> t2 t1 [0\<dots>].
              ((output_fun (s t3) = \<NoMsg>. t3 \<U> t4 ([0\<dots>] \<oplus> t2).
               (output_fun (s t4) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t4)))))))) \<rbrakk> \<Longrightarrow>
  i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m"
by (blast intro: i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2'[THEN iffD2])

thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv'
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_iUntil_imp1: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    (\<not> State_Idle localState output_fun trans_fun (localState (s t2))). t2 \<U> t1 [0\<dots>] \<oplus> t0.
    (output_fun (s t1) = m \<and> State_Idle localState output_fun trans_fun (localState (s t1))) \<rbrakk> \<Longrightarrow>
  i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m"
by (blast intro: i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv'[THEN iffD2])
lemma i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_iUntil_imp2: "
  \<lbrakk> Suc 0 < k;
    State_Idle localState output_fun trans_fun (
      i_Exec_Comp_Stream_Acc_LocalState k localState trans_fun input c t);
    m \<noteq> \<NoMsg>;
    t0 = t * k;
    s = i_Exec_Comp_Stream trans_fun (input \<odot>\<^sub>i k) c;
    (\<not> State_Idle localState output_fun trans_fun (localState (s t2))). t2 \<U> t1 [0\<dots>] \<oplus> t0.
    (output_fun (s t1) = m \<and>
    (\<bigcirc> t3 t1 [0\<dots>].
      ((output_fun (s t4) = \<NoMsg>. t4 \<U> t5 ([0\<dots>] \<oplus> t3).
       (output_fun (s t5) = \<NoMsg> \<and> State_Idle localState output_fun trans_fun (localState (s t5))))))) \<rbrakk> \<Longrightarrow>
  i_Exec_Comp_Stream_Acc_Output k output_fun trans_fun input c t = m"
by (blast intro: i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv'[THEN iffD2])

text {* List of selected lemmas about output of accelerated components. *}
thm i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_iAll_conv
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_iEx_iAll_cut_greater_conv
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_iSince_conv
thm i_Exec_Comp_Stream_Acc_Output__eq_iAll_iSince_conv

thm i_Exec_Comp_Stream_Acc_Output__eq_NoMsg_State_Idle_conv
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv2'
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_conv'

thm i_Exec_Comp_Stream_Acc_Output__eq_iAll_iUntil_State_Idle_conv2
thm i_Exec_Comp_Stream_Acc_Output__eq_iUntil_State_Idle_conv

thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_iEx_imp1
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_iEx_imp2
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_iUntil_imp1
thm i_Exec_Comp_Stream_Acc_Output__eq_Msg_State_Idle_iUntil_imp2

end


theory LRE_R1ToR3
imports "Z_Machines.Z_Machine"
begin

notation undefined ("???")

subsection \<open> Introduction \<close>

text \<open> This theory file is to model the LRE_Beh state machine in Z Machine notations.\<close>

datatype ('s, 'e) tag =
  State (ofState: 's) | Event (ofEvent: 'e)

abbreviation "is_Event x \<equiv> \<not> is_State x"

type_synonym ('s, 'e) rctrace = "('s, 'e) tag list"

definition wf_rcstore :: "('s, 'e) rctrace \<Rightarrow> 's \<Rightarrow> 's option \<Rightarrow> bool" where
[z_defs]: "wf_rcstore tr st final =  (
     length(tr) > 0
   \<and> tr ! ((length tr) -1) = State st
   \<and> ( final \<noteq> None \<longrightarrow> (\<forall>i<length tr. tr ! i = State (the final) \<longrightarrow> i= (length tr) -1))
   \<and> (filter is_State tr) ! (length (filter is_State tr) -1) = State  st)"

subsection \<open> type definition \<close>

enumtype St = OCM | MOM | HCM | CAM | initial

definition [z_defs]: "St = {OCM, MOM, HCM, CAM, initial}"

enumtype Evt = advVel | reqHCM | reqOCM | reqMOM | endTask | reqVel

definition "Evt = {advVel, reqHCM, reqOCM, reqMOM, endTask, reqVel}"

type_synonym coord="integer\<times>integer"

record Obstacle =
  obspos :: coord
  id :: nat

consts Obsts :: " coord list"

consts Positions::"(coord) set"

consts Velocities:: "(integer\<times>integer) set"
consts ReqV:: "(integer\<times>integer) set"

consts HCMVel:: "integer"

consts MOMVel:: "integer"

consts MinSafeDist :: "integer"

consts Opez_min:: "coord"
consts Opez_max:: "coord"
consts SafeVel :: "integer"
consts ZeroVel:: "coord"

text \<open> function definition \<close>

fun inOPEZ:: "coord\<Rightarrow> bool"
  where "inOPEZ (x,y) = ( x\<ge> fst Opez_min \<and> x< fst Opez_max \<and> y\<ge>snd Opez_min \<and> y< snd Opez_max)"

fun single_dist:: " coord \<times> coord  \<Rightarrow> integer"
  where "single_dist((x,y), (m,n)) =(x-m)^2+ (y-n)^2"

fun dist:: " coord \<times> (coord list) \<Rightarrow> integer"
  where
"dist((x,y),[]) = 200^2+ 200^2" |
 " dist((x,y), g#gs) =( if  single_dist((x,y),g) \<le> dist ((x,y),gs) then single_dist((x,y),g) else dist ((x,y),gs))"

fun obst_index:: "coord  \<times> (coord list) \<Rightarrow> nat"
  where
"obst_index ((x,y), [])=100 " |
 "obst_index ((x,y), g#gs)= (if single_dist ((x,y),g) = dist ((x,y),g#gs) then 0 else  (obst_index ((x,y), gs)+1))"

fun abslt:: "integer\<Rightarrow> integer"
  where "abslt(x) = (if x\<ge>0 then x else -x)"

fun closestObs_xpos :: "coord \<times> (coord list) \<Rightarrow> integer"
  where "closestObs_xpos((xp,yp),[]) = 1000000"|
        "closestObs_xpos((xp,yp),g#gs) = fst ((g#gs) ! obst_index((xp,yp), g#gs))"

fun closestObs_ypos :: "coord \<times> (coord list) \<Rightarrow> integer"
  where "closestObs_ypos((xp,yp),[]) = 1000000"|
        "closestObs_ypos((xp,yp),g#gs) = snd ((g#gs) ! obst_index((xp,yp), g#gs))"

fun CDA :: " coord \<times> (coord list)\<times> (integer \<times> integer) \<Rightarrow> integer"
  where "CDA((xp,yp),[], (xv,yv)) = (10+MinSafeDist+5)^2" |
"CDA ((xp,yp), g#gs, (xv,yv)) =
(if xv\<noteq>0 \<and> yv=0
 then
  (if (closestObs_xpos((xp,yp),g#gs)- xp) * xv\<ge>0
   then dist((xp,yp),g#gs) -(closestObs_xpos((xp,yp),g#gs) - xp)^2
   else dist((xp,yp),g#gs)  )
else
  (if xv=0 \<and> yv\<noteq>0
   then
    (if (closestObs_ypos((xp,yp),g#gs) - yp) * yv\<ge>0
     then dist((xp,yp),g#gs)- (closestObs_ypos((xp,yp),g#gs) - yp)^2
     else dist((xp,yp),g#gs)  )
   else dist((xp,yp),g#gs)  )
)"

fun maneuv :: "integer\<times> integer \<Rightarrow> integer\<times> integer"
  where "maneuv(x,y) = (y,-x)"

fun setVel :: "(integer \<times> integer) \<times> integer   \<Rightarrow>   (integer \<times> integer) "
  where
 "setVel((xv, yv), setpoint) =
(if xv=0
  then
   (if yv>0
    then (0, setpoint)
    else  ( if yv<0 then(0, (- setpoint) )
             else (setpoint, 0) ) )
else
   (if xv>0
    then (setpoint, 0)
    else ((-setpoint), 0) )  )"

subsection \<open> State Space \<close>

zstore LRE_Beh =
  pos:: "coord"
  xvel :: "integer"
  yvel :: "integer"
  reqV::" integer\<times> integer"
  advV::" integer\<times> integer"
  st::"St"
  tr :: "(St, Evt)tag list"
  trg:: "Evt option"
  triggers:: "Evt set"
  where inv:
        "wf_rcstore tr st None"

subsection \<open> Operations \<close>

zoperation Move =
over LRE_Beh
update "[
        pos\<Zprime>=(fst(pos) + xvel, snd(pos) + yvel)
        ]"

zoperation Trigger=
params trigger \<in> "triggers"
pre "triggers \<noteq> {}"
update "[
        trg\<Zprime>= Some trigger
        ]"

zoperation InitialToOCM =
  over LRE_Beh
  pre "st= initial"
  update "[ st\<Zprime>= OCM
  		  , tr\<Zprime>=tr @ [State OCM]
        , triggers\<Zprime> = {reqMOM, reqVel}
        , trg\<Zprime> = None
          ]"

zoperation OCMToMOM =
  over LRE_Beh
  pre "st= OCM  \<and> ( xvel^2 +  yvel^2)\<le>  SafeVel^2 \<and> dist(pos,Obsts)>  (MinSafeDist+10)^2 \<and> \<not>inOPEZ(pos)"
  update "[ st\<Zprime>= MOM
  		  , tr\<Zprime>=tr  @ [Event reqMOM]  @ [Event advVel]@ [State MOM]
        , advV\<Zprime> = setVel((xvel, yvel), MOMVel)
        , (xvel,yvel)\<Zprime> = setVel((xvel, yvel), MOMVel)
        , trg\<Zprime> = None
        , triggers\<Zprime> = {endTask, reqOCM}
          ]"

zoperation MOMToOCM =
  over LRE_Beh
  pre "st= MOM"
  update "[ st\<Zprime>= OCM
  		  , tr\<Zprime>=tr @ [Event reqOCM] @ [State OCM]
        , trg\<Zprime> = None
        , triggers\<Zprime> = {reqMOM, reqVel}
          ]"

zoperation MOMToOCM_1 =
  over LRE_Beh
  pre "st= MOM \<and> inOPEZ(pos) \<and> (dist(pos,Obsts)>  (MinSafeDist+5)^2  \<or> CDA(pos,Obsts, (xvel,yvel))>  MinSafeDist^2)"
  update "[ st\<Zprime>= OCM
  		  , tr\<Zprime>=tr @ [State OCM]
        , triggers\<Zprime> = {reqMOM, reqVel}
        , trg\<Zprime> = None
          ]"

zoperation MOMToOCM_2 =
  over LRE_Beh
  pre "st= MOM "
  update "[ st\<Zprime>= OCM
  		  , tr\<Zprime>=tr @ [Event endTask] @ [Event advVel] @ [State OCM]
        , advV\<Zprime> = ZeroVel
        , (xvel,yvel)\<Zprime> = ZeroVel
        , triggers\<Zprime> = {reqMOM, reqVel}
        , trg\<Zprime> = None
          ]"

zoperation HCMToOCM =
  over LRE_Beh
  pre "st= HCM "
  update "[ st\<Zprime>= OCM
  		  , tr\<Zprime>=tr @ [Event reqOCM] @ [State OCM]
        , trg\<Zprime> = None
        , triggers\<Zprime> = {reqMOM, reqVel}
          ]"

zoperation HCMToOCM_1 =
  over LRE_Beh
  pre "st= HCM \<and> inOPEZ(pos)\<and> (dist(pos,Obsts)>  (MinSafeDist+5)^2  \<or> CDA(pos,Obsts, (xvel,yvel))>  MinSafeDist^2)"
  update "[ st\<Zprime>= OCM
  		  , tr\<Zprime>=tr @ [State OCM]
        , triggers\<Zprime> = {reqMOM, reqVel}
        , trg\<Zprime> = None
          ]"

zoperation MOMToHCM =
  over LRE_Beh
  pre "st= MOM \<and>  ( xvel^2 +  yvel^2)>  SafeVel^2 \<and>  dist(pos,Obsts)\<le>  (MinSafeDist+5)^2  \<and> CDA(pos,Obsts, (xvel,yvel))>  MinSafeDist^2"
  update "[ st\<Zprime>= HCM
  		  , tr\<Zprime>=tr @ [Event advVel] @ [State HCM]
        , advV\<Zprime> = setVel((xvel, yvel), HCMVel)
        , (xvel,yvel)\<Zprime> = setVel((xvel, yvel), HCMVel)
        , triggers\<Zprime> = {reqOCM}
        , trg\<Zprime> = None
          ]"

zoperation HCMToMOM =
  over LRE_Beh
  pre "st= HCM \<and> dist(pos,Obsts)>  (MinSafeDist+5)^2   \<and> \<not>inOPEZ(pos) "
  update "[ st\<Zprime>= MOM
  		  , tr\<Zprime>=tr @ [Event advVel] @ [State MOM]
        , advV\<Zprime> = setVel((xvel, yvel), MOMVel)
        , (xvel,yvel)\<Zprime> =  setVel((xvel, yvel), MOMVel)
        , triggers\<Zprime> = { endTask, reqOCM}
        , trg\<Zprime> = None
          ]"

zoperation OCMToOCM =
  over LRE_Beh
  params reqV_input \<in> " ReqV"
  pre "st= OCM "
  update "[ st\<Zprime>= OCM
  		  , tr\<Zprime>=tr @ [Event reqVel] @ [Event advVel] @[State OCM]
        ,reqV\<Zprime> = reqV_input
        , advV\<Zprime> = reqV_input
        , (xvel,yvel)\<Zprime> = reqV_input
        , triggers\<Zprime> = {reqMOM, reqVel}
        , trg\<Zprime> = None
  ]"

zoperation HCMToCAM =
  over LRE_Beh
  pre "st= HCM \<and> CDA(pos,Obsts, (xvel,yvel))\<le>  MinSafeDist^2 \<and>dist(pos,Obsts) \<le>  (MinSafeDist+5)^2 "
  update "[ st\<Zprime>= CAM
  		  , tr\<Zprime>=tr @ [Event advVel] @ [State CAM]
        , advV\<Zprime> = maneuv(xvel, yvel)
        , (xvel,yvel)\<Zprime> = maneuv(xvel, yvel)
        , triggers\<Zprime> = {reqOCM}
        , trg\<Zprime> = None
          ]"

zoperation HCMToCAM_1 =
  over LRE_Beh
  pre "st= HCM \<and> (-100> (fst(pos) + xvel) \<or> (fst(pos) + xvel) >100 \<or>  -100> (snd(pos) + yvel) \<or> (snd(pos) + yvel) >100)"
  update "[ st\<Zprime>= CAM
  		  , tr\<Zprime>=tr @ [Event advVel] @ [State CAM]
        , advV\<Zprime> = maneuv(xvel, yvel)
        , (xvel,yvel)\<Zprime> = maneuv(xvel, yvel)
        , triggers\<Zprime> = {reqOCM}
        , trg\<Zprime> = None
          ]"

zoperation MOMToCAM =
  over LRE_Beh
  pre "st= MOM \<and> CDA(pos,Obsts, (xvel,yvel))\<le>  MinSafeDist^2 \<and>dist(pos,Obsts)\<le> (MinSafeDist+5)^2 "
  update "[ st\<Zprime>= CAM
  		  , tr\<Zprime>=tr @ [Event advVel] @ [State CAM]
        , advV\<Zprime> = maneuv(xvel, yvel)
        , (xvel,yvel)\<Zprime> = maneuv(xvel, yvel)
        , triggers\<Zprime> = {reqOCM}
       , trg\<Zprime> = None
          ]"

zoperation MOMToCAM_1 =
  over LRE_Beh
  pre "st= MOM \<and> (-100> (fst(pos) + xvel) \<or> (fst(pos) + xvel) >100 \<or>  -100> (snd(pos) + yvel) \<or> (snd(pos) + yvel) >100)"
  update "[ st\<Zprime>= CAM
  		  , tr\<Zprime>=tr @ [Event advVel] @ [State CAM]
        , advV\<Zprime> = maneuv(xvel, yvel)
        , (xvel,yvel)\<Zprime> = maneuv(xvel, yvel)
        , triggers\<Zprime> = {reqOCM}
        , trg\<Zprime> = None
          ]"

zoperation CAMToCAM =
  over LRE_Beh
  pre "st= CAM \<and> CDA(pos,Obsts, (xvel,yvel))\<le>  MinSafeDist^2 \<and>dist(pos,Obsts)\<le>  (MinSafeDist+5)^2 "
  update "[ st\<Zprime>= CAM
  		  , tr\<Zprime>=tr @ [Event advVel] @ [State CAM]
        , advV\<Zprime> = maneuv(xvel, yvel)
        , (xvel,yvel)\<Zprime> = maneuv(xvel, yvel)
        , triggers\<Zprime> = {reqOCM}
        , trg\<Zprime> = None
          ]"

zoperation CAMToCAM_1 =
  over LRE_Beh
  pre "st= CAM \<and>  (-100> (fst(pos) + xvel) \<or> (fst(pos) + xvel) >100 \<or>  -100> (snd(pos) + yvel) \<or> (snd(pos) + yvel) >100)"
  update "[ st\<Zprime>= CAM
  		  , tr\<Zprime>=tr @ [Event advVel] @ [State CAM]
        , advV\<Zprime> = maneuv(xvel, yvel)
        , (xvel,yvel)\<Zprime> = maneuv(xvel, yvel)
        , triggers\<Zprime> = {reqOCM}
        , trg\<Zprime> = None
          ]"

zoperation CAMToOCM =
  over LRE_Beh
  pre "st= CAM \<and> CDA(pos,Obsts, (xvel,yvel))>  MinSafeDist^2"
  update "[ st\<Zprime>= OCM
  		  , tr\<Zprime>=tr @[Event advVel] @ [State OCM]
        , advV\<Zprime> = ZeroVel
        , (xvel,yvel)\<Zprime> = ZeroVel
        , triggers\<Zprime> = {reqMOM, reqVel}
        , trg\<Zprime> = None
          ]"

zoperation CAMToOCM_1 =
  over LRE_Beh
  pre "st= CAM "
  update "[ st\<Zprime>= OCM
  		  , tr\<Zprime>=tr @ [Event reqOCM] @ [State OCM]
        , trg\<Zprime> = None
        , triggers\<Zprime> = {reqMOM, reqVel}
          ]"

definition Init :: "LRE_Beh subst" where
  [z_defs]:
  "Init =
  [pos\<leadsto>(0,0),
   xvel \<leadsto> 0,
   yvel \<leadsto> 0,
   advV \<leadsto> (0,0),
reqV\<leadsto> (0,0),
   st \<leadsto> initial,
   tr  \<leadsto> [State initial],
   trg \<leadsto> None,
   triggers \<leadsto>  {reqOCM}
   ]"

def_consts Velocities = "{(0,1),(0,-2), (2,0),(-4,0)}"
declare Velocities_def [z_defs]

def_consts MinSafeDist= "2"
declare MinSafeDist_def [z_defs]

def_consts HCMVel = "3"
declare HCMVel_def [z_defs]

def_consts MOMVel = "5"
declare MOMVel_def [z_defs]

def_consts ZeroVel = "(0,0)"
declare ZeroVel_def [z_defs]

def_consts SafeVel = "3"
declare SafeVel_def [z_defs]

method zpog uses add =
  (hoare_wlp add: z_defs add; (clarify)?;
   expr_taut;
   ((clarsimp del: notI)?;
    (((erule conjE | rule conjI | erule disjE | rule impI); (clarsimp del: notI)?)+)?))
method zpog_full uses add = (zpog add: z_locale_defs add)

lemma prod_var_decomp: " get\<^bsub>x\<^esub> s= ( get\<^bsub>var_fst x\<^esub> s,  get\<^bsub>var_snd x\<^esub> s)"
  by (simp add: lens_defs)

subsection \<open> Structural Invariants \<close>

lemma Init_inv [hoare_lemmas]: "Init establishes LRE_Beh_inv"
  by (zpog_full; auto)

lemma InitialToOCM_inv [hoare_lemmas]: "InitialToOCM () preserves LRE_Beh_inv"
  by (zpog_full; auto)

lemma OCMToMOM_inv [hoare_lemmas]: "OCMToMOM() preserves LRE_Beh_inv"
  apply (zpog_full; auto)
  apply (metis add_2_eq_Suc' cancel_ab_semigroup_add_class.add_diff_cancel_left' not_add_less1 nth_Cons_0 nth_Cons_Suc nth_append numeral_2_eq_2)
  apply (metis add_2_eq_Suc' cancel_ab_semigroup_add_class.add_diff_cancel_left' not_add_less1 nth_Cons_0 nth_Cons_Suc nth_append numeral_2_eq_2)
  apply (metis add_2_eq_Suc' cancel_ab_semigroup_add_class.add_diff_cancel_left' not_add_less1 nth_Cons_0 nth_Cons_Suc nth_append numeral_2_eq_2)
  by (metis add_2_eq_Suc' cancel_ab_semigroup_add_class.add_diff_cancel_left' not_add_less1 nth_Cons_0 nth_Cons_Suc nth_append numeral_2_eq_2)

lemma MOMToOCM_inv [hoare_lemmas]: "MOMToOCM () preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (simp add: nth_append)

lemma MOMToOCM_1_inv [hoare_lemmas]: "MOMToOCM_1 () preserves LRE_Beh_inv"
   by (zpog_full; auto)

lemma MOMToOCM_2_inv [hoare_lemmas]: "MOMToOCM_2 () preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (simp add: nth_append)

lemma HCMToOCM_inv [hoare_lemmas]: "HCMToOCM () preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis One_nat_def Suc_eq_plus1 cancel_ab_semigroup_add_class.add_diff_cancel_left' not_add_less1 nth_Cons_0 nth_Cons_Suc nth_append)

lemma HCMToOCM_1_inv [hoare_lemmas]: "HCMToOCM_1() preserves LRE_Beh_inv"
  by (zpog_full; auto)

lemma MOMToHCM_inv [hoare_lemmas]: "MOMToHCM() preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis One_nat_def Suc_mono Suc_n_not_le_n diff_Suc_1 diff_diff_cancel length_greater_0_conv nth_Cons_0 nth_Cons_pos nth_append order_le_less zero_less_one)

lemma HCMToMOM_inv [hoare_lemmas]: "HCMToMOM() preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis One_nat_def Suc_eq_plus1 nth_Cons_0 nth_Cons_Suc nth_append_length_plus)

lemma OCMToOCM_inv [hoare_lemmas]: "OCMToOCM (v) preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (simp add: nth_append)

lemma HCMToCAM_inv [hoare_lemmas]: "HCMToCAM() preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis One_nat_def Suc_eq_plus1 nth_Cons_0 nth_Cons_Suc nth_append_length_plus)

lemma HCMToCAM_1_inv [hoare_lemmas]: "HCMToCAM_1() preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  apply (metis One_nat_def Suc_eq_plus1 nth_Cons_0 nth_Cons_Suc nth_append_length_plus)
  by (simp add: nth_append)

lemma MOMToCAM_inv [hoare_lemmas]: "MOMToCAM() preserves LRE_Beh_inv"
   apply (zpog_full add: prod_var_decomp)
  by (metis One_nat_def Suc_eq_plus1 nth_Cons_0 nth_Cons_Suc nth_append_length_plus)

lemma MOMToCAM_1_inv [hoare_lemmas]: "MOMToCAM_1() preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  apply (simp add: nth_append)
  by (simp add: nth_append)

lemma CAMToCAM_inv [hoare_lemmas]: "CAMToCAM () preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis One_nat_def Suc_eq_plus1 nth_Cons_0 nth_Cons_Suc nth_append_length_plus)

lemma CAMToCAM_1_inv [hoare_lemmas]: "CAMToCAM_1 () preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  apply (simp add: nth_append)
  by (simp add: nth_append)

lemma CAMToOCM_inv [hoare_lemmas]: "CAMToOCM () preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis One_nat_def Suc_eq_plus1 nth_Cons_0 nth_Cons_Suc nth_append_length_plus)

lemma CAMToOCM_1_inv [hoare_lemmas]: "CAMToOCM_1() preserves LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis append_Cons append_Nil append_assoc length_append_singleton nth_append_length)

subsection \<open> Safety Requirements \<close>

zexpr R1 is
"length (filter is_State tr) > 1 \<longrightarrow> (\<forall> i < length (filter is_State tr)-1 . (filter is_State tr) ! i= State CAM \<longrightarrow> (filter is_State tr) ! (i+1) \<in> {State OCM, State CAM})"
lemma "Init establishes R1"
  by zpog_full

lemma  "InitialToOCM () preserves R1  under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma "OCMToMOM() preserves  R1 under LRE_Beh_inv"
 apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def St.distinct_disc(5) Suc_lessI diff_Suc_1 length_greater_0_conv less_Suc0 nth_append tag.inject(1))

lemma  "MOMToOCM() preserves  R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma  "HCMToOCM () preserves R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma  "MOMToHCM() preserves  R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def St.distinct(12) diff_Suc_1 less_Suc0 not_less_eq nth_append tag.inject(1))

lemma  "MOMToOCM_1() preserves  R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  apply (simp add: nth_append)
  apply (smt (verit) Suc_lessI Suc_less_eq Suc_pred length_greater_0_conv less_Suc0)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma  "HCMToOCM_1() preserves R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  apply (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma  "HCMToMOM() preserves R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def St.distinct_disc(15) diff_Suc_1 less_Suc0 not_less_eq nth_append tag.inject(1))

lemma  "OCMToOCM (v) preserves R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma  "MOMToOCM_2() preserves R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma  "HCMToCAM() preserves R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma  "MOMToCAM() preserves  R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma  "CAMToOCM () preserves R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma  "CAMToOCM_1() preserves  R1 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (metis (no_types, lifting) Nat.lessE One_nat_def Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length)

lemma "Move() preserves R1 under LRE_Beh_inv"
  by (zpog_full; auto)

lemma  "Trigger(t) preserves R1 under LRE_Beh_inv"
  by (zpog_full; auto)

zexpr R2 is
 "length tr>1\<longrightarrow> (\<forall>i< (length tr)-1. tr ! (i+1) = State MOM \<longrightarrow> tr ! i = Event advVel ) "

lemma  "Init establishes R2 "
  by  zpog_full

lemma  "InitialToOCM () preserves R2  under LRE_Beh_inv"
  apply zpog_full
  by (smt (verit, best) St.distinct(1) St.distinct(13) Suc_pred diff_is_0_eq' less_Suc_eq less_Suc_eq_0_disj less_Suc_eq_le not_less_eq nth_append nth_append_length tag.inject(1))

lemma "OCMToMOM() preserves  R2 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (smt (verit, del_insts) Nat.lessE One_nat_def Suc_eq_plus1 add_Suc_right diff_Suc_1 less_2_cases not_less_eq nth_Cons_0 nth_Cons_Suc nth_append nth_append_length_plus numeral_2_eq_2 tag.distinct(1))

lemma  "MOMToOCM() preserves  R2 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (smt (verit, ccfv_threshold) St.distinct(2) Suc_diff_1 Suc_eq_plus1 Suc_less_SucD diff_Suc_1 gr_implies_not_zero less_SucE less_SucI less_Suc_eq_0_disj linorder_neqE_nat minus_gr_zero_iff nth_Cons_0 nth_Cons_pos nth_append nth_append_length_plus tag.distinct(1) tag.inject(1))

lemma  "MOMToOCM_1() preserves  R2 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  apply (metis (no_types, lifting) Nat.lessE One_nat_def St.distinct(2) Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length tag.inject(1))
  by (metis (no_types, lifting) Nat.lessE One_nat_def St.distinct(2) Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length tag.inject(1))

lemma  "MOMToOCM_2() preserves  R2 under LRE_Beh_inv"
  apply zpog_full
  by (smt (z3) Suc_le_eq Suc_lessI Suc_pred add_2_eq_Suc' cancel_ab_semigroup_add_class.add_diff_cancel_left' diff_Suc_1 less_2_cases less_Suc_eq less_imp_le_nat nat_arith.suc1 nat_neq_iff nth_Cons_0 nth_Cons_Suc nth_append tag.distinct(1))

lemma  "HCMToOCM () preserves R2 under LRE_Beh_inv"
  apply zpog_full
  by (smt (verit, ccfv_SIG) St.distinct(2) Suc_diff_Suc Suc_eq_plus1 bot_nat_0.extremum_strict diff_Suc_1 length_greater_0_conv less_SucE less_SucI less_diff_conv minus_gr_zero_iff nat_neq_iff nth_Cons_pos nth_append nth_append_length tag.distinct(1) tag.inject(1))

lemma  "HCMToOCM_1 () preserves R2 under LRE_Beh_inv"
  apply zpog_full
  apply (metis (no_types, lifting) Nat.lessE One_nat_def St.distinct(2) Suc_leI Suc_lessI diff_Suc_1 diff_is_0_eq' length_greater_0_conv nth_append nth_append_length tag.inject(1))
  by (metis (no_types, lifting) One_nat_def St.distinct(2) Suc_eq_plus1 Suc_lessI diff_is_0_eq gr_implies_not_zero less_diff_conv linorder_not_le nth_append nth_append_length tag.inject(1))

lemma  "MOMToHCM() preserves  R2 under LRE_Beh_inv"
  apply (zpog_full; auto)
  apply (metis Suc_lessI length_greater_0_conv less_Suc_eq less_one nth_append nth_append_length)
  by (metis One_nat_def Suc_eq_plus1 Suc_lessI less_SucE less_diff_conv nth_append nth_append_length tag.distinct(1))

lemma  "HCMToMOM() preserves  R2 under LRE_Beh_inv"
  apply zpog_full
  by (smt (verit, ccfv_SIG) Suc_leI Suc_lessI Suc_less_SucD Suc_pred diff_is_0_eq' length_greater_0_conv less_2_cases less_Suc_eq_le nth_Cons_0 nth_append numeral_2_eq_2 tag.distinct(1))

lemma  "OCMToOCM(v) preserves  R2 under LRE_Beh_inv"
  apply (zpog_full add: prod_var_decomp)
  by (smt (verit, del_insts) Nat.lessE Suc_eq_plus1 Suc_less_eq diff_Suc_1 length_greater_0_conv less_2_cases nth_Cons_0 nth_Cons_Suc nth_append nth_append_length nth_append_length_plus numeral_2_eq_2 one_add_one tag.distinct(1))

lemma  "HCMToCAM() preserves R2 under LRE_Beh_inv"
  apply zpog_full
  by (smt (verit, ccfv_SIG) Suc_leI Suc_lessI Suc_less_SucD Suc_pred diff_is_0_eq' length_greater_0_conv less_2_cases less_Suc_eq_le nth_Cons_0 nth_append numeral_2_eq_2 tag.disc(1) tag.disc(2))

lemma  "HCMToCAM_1() preserves R2 under LRE_Beh_inv"
  apply zpog_full
  apply (smt (verit, best) One_nat_def Suc_diff_Suc Suc_mono diff_Suc_1 length_greater_0_conv linorder_not_le not_less_less_Suc_eq nth_append nth_append_length tag.distinct(1) zero_le)
  by (smt (verit) One_nat_def Suc_diff_1 Suc_lessI Suc_less_SucD gr0I less_trans_Suc nth_append nth_append_length tag.distinct(1))

lemma  "MOMToCAM() preserves  R2 under LRE_Beh_inv"
  apply zpog_full
  by (smt (verit, del_insts) Suc_leI Suc_pred length_greater_0_conv less_Suc0 less_Suc_eq nat_less_le nth_append nth_append_length)

lemma  "MOMToCAM_1() preserves  R2 under LRE_Beh_inv"
  apply zpog_full
  apply (smt (verit, del_insts) Suc_pred less_Suc0 nat_neq_iff not_less_eq nth_append nth_append_length)
  by (smt (verit, ccfv_threshold) Suc_pred less_Suc0 nat_neq_iff not_less_eq nth_append nth_append_length)

lemma  "CAMToCAM() preserves R2 under LRE_Beh_inv"
  apply zpog_full
  by (smt (verit) One_nat_def Suc_eq_plus1 Suc_mono less_SucE less_diff_conv less_one linorder_neqE_nat nth_append nth_append_length tag.distinct(1))

lemma  "CAMToCAM_1() preserves R2 under LRE_Beh_inv"
  apply zpog_full
  apply (smt (verit, ccfv_SIG) Suc_leI Suc_lessI Suc_less_SucD Suc_pred diff_is_0_eq' length_greater_0_conv less_2_cases less_Suc_eq_le nth_Cons_0 nth_append numeral_2_eq_2 tag.distinct(1))
  by (metis (no_types, lifting) One_nat_def Suc_diff_1 Suc_mono length_greater_0_conv less_SucE linorder_not_le nth_append nth_append_length tag.distinct(1) zero_le)

lemma  "CAMToOCM() preserves R2 under LRE_Beh_inv"
  apply zpog_full
  by (smt (verit, ccfv_threshold) One_nat_def Suc_eq_plus1 less_Suc_eq_0_disj less_antisym less_diff_conv less_one nth_append nth_append_length tag.distinct(1))

lemma  "CAMToOCM_1() preserves R2 under LRE_Beh_inv"
  apply zpog_full
  by (smt (verit, ccfv_SIG) St.distinct(2) Suc_eq_plus1 Suc_lessI Suc_less_SucD Suc_pred cancel_ab_semigroup_add_class.add_diff_cancel_left' diff_Suc_1 length_greater_0_conv less_Suc0 less_Suc_eq nth_Cons_0 nth_Cons_Suc nth_append nth_append_length tag.disc(1) tag.disc(2) tag.inject(1))

lemma "Move() preserves R2 under LRE_Beh_inv"
  by (zpog_full; auto)

lemma  "Trigger(t) preserves R2 under LRE_Beh_inv"
  by (zpog_full; auto)

zexpr R3 is
"st\<noteq>OCM \<longrightarrow>reqOCM \<in> triggers"

lemma  "Init establishes  R3 "
  by  zpog_full

lemma  "InitialToOCM () preserves  R3 under LRE_Beh_inv"
  by  zpog_full

lemma "OCMToMOM() preserves  R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "MOMToOCM() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "MOMToOCM_1() preserves  R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "MOMToOCM_2() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "HCMToOCM () preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "HCMToOCM_1() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "MOMToHCM() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "HCMToMOM() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "OCMToOCM (v) preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "HCMToCAM() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "HCMToCAM_1() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "MOMToCAM() preserves  R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "MOMToCAM_1() preserves  R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "CAMToCAM() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "CAMToCAM_1() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "CAMToOCM () preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "CAMToOCM_1() preserves  R3 under LRE_Beh_inv"
  by  zpog_full

lemma "Move() preserves R3 under LRE_Beh_inv"
  by  zpog_full

lemma  "Trigger(t) preserves R3  under LRE_Beh_inv"
  by  zpog_full

end