Theory Drinks_Machine_LTL
section‹Temporal Properties›
text‹This theory presents some examples of temporal properties over the simple drinks machine.›
theory Drinks_Machine_LTL
imports "Drinks_Machine" "Extended_Finite_State_Machines.EFSM_LTL"
begin
declare One_nat_def [simp del]
lemma P_ltl_step_0:
assumes invalid: "P (None, [], <>)"
assumes select: "l = STR ''select'' ⟶ P (Some 1, [], <1 $:= Some (hd i), 2 $:= Some (Num 0)>)"
shows "P (ltl_step drinks (Some 0) <> (l, i))"
proof-
have length_i: "∃d. (l, i) = (STR ''select'', [d]) ⟹ length i = 1"
by (induct i, auto)
have length_i_2: "∀d. i ≠ [d] ⟹ length i ≠ 1"
by (induct i, auto)
show ?thesis
apply (case_tac "∃d. (l, i) = (STR ''select'', [d])")
apply (simp add: possible_steps_0 length_i select_def apply_updates_def)
using select apply auto[1]
by (simp add: possible_steps_0_invalid length_i_2 invalid)
qed
lemma P_ltl_step_1:
assumes invalid: "P (None, [], r)"
assumes coin: "l = STR ''coin'' ⟶ P (Some 1, [value_plus (r $ 2) (Some (hd i))], r(2 $:= value_plus (r $ 2) (Some (i ! 0))))"
assumes vend_fail: "value_gt (Some (Num 100)) (r $ 2) = trilean.true ⟶ P (Some 1, [],r)"
assumes vend: "¬? value_gt (Some (Num 100)) (r $ 2) = trilean.true ⟶ P (Some 2, [r$1], r)"
shows "P (ltl_step drinks (Some 1) r (l, i))"
proof-
have length_i: "⋀s. ∃d. (l, i) = (s, [d]) ⟹ length i = 1"
by (induct i, auto)
have length_i_2: "∀d. i ≠ [d] ⟹ length i ≠ 1"
by (induct i, auto)
show ?thesis
apply (case_tac "∃d. (l, i) = (STR ''coin'', [d])")
apply (simp add: possible_steps_1_coin length_i coin_def apply_outputs_def apply_updates_def)
using coin apply auto[1]
apply (case_tac "(l, i) = (STR ''vend'', [])")
apply (case_tac "∃n. r $ 2 = Some (Num n)")
apply clarsimp
subgoal for n
apply (case_tac "n ≥ 100")
apply (simp add: drinks_vend_sufficient vend_def apply_updates_def apply_outputs_def)
apply (metis finfun_upd_triv possible_steps_2_vend vend vend_ge_100)
apply (simp add: drinks_vend_insufficient vend_fail_def apply_updates_def apply_outputs_def)
apply (metis MaybeBoolInt.simps(1) finfun_upd_triv not_less value_gt_def vend_fail)
done
apply (simp add: drinks_vend_invalid invalid)
by (simp add: drinks_no_possible_steps_1 length_i_2 invalid)
qed
lemma LTL_r2_not_always_gt_100: "not (alw (check_exp (Gt (V (Rg 2)) (L (Num 100))))) (watch drinks i)"
using value_gt_def by auto
lemma drinks_step_2_none: "ltl_step drinks (Some 2) r e = (None, [], r)"
by (simp add: drinks_end ltl_step_none_2)
lemma one_before_two_2:
"alw (λx. statename (shd (stl x)) = Some 2 ⟶ statename (shd x) = Some 1) (make_full_observation drinks (Some 2) r [r $ 1] x2a)"
proof(coinduction)
case alw
then show ?case
apply (simp add: drinks_step_2_none)
by (metis (mono_tags, lifting) alw_mono nxt.simps once_none_nxt_always_none option.distinct(1))
qed
lemma one_before_two_aux:
assumes "∃ p r i. j = nxt (make_full_observation drinks (Some 1) r p) i"
shows "alw (λx. nxt (state_eq (Some 2)) x ⟶ state_eq (Some 1) x) j"
using assms apply(coinduct)
apply simp
apply clarify
apply standard
apply simp
apply simp
subgoal for r i
apply (case_tac "shd (stl i)")
apply (simp del: ltl_step.simps)
apply (rule P_ltl_step_1)
apply (rule disjI2)
apply (rule alw_mono[of "nxt (state_eq None)"])
apply (simp add: once_none_nxt_always_none)
apply simp
apply auto[1]
apply auto[1]
apply simp
by (simp add: one_before_two_2)
done
lemma LTL_nxt_2_means_vend:
"alw (nxt (state_eq (Some 2)) impl (state_eq (Some 1))) (watch drinks i)"
proof(coinduction)
case alw
then show ?case
apply (case_tac "shd i")
apply (simp del: ltl_step.simps)
apply (rule P_ltl_step_0)
apply simp
apply (rule disjI2)
apply (rule alw_mono[of "nxt (state_eq None)"])
apply (simp add: once_none_nxt_always_none)
using one_before_two_aux by auto
qed
lemma costsMoney_aux:
assumes "∃p r i. j = (nxt (make_full_observation drinks (Some 1) r p) i)"
shows "alw (λxs. nxt (state_eq (Some 2)) xs ⟶ check_exp (Ge (V (Rg 2)) (L (Num 100))) xs) j"
using assms apply coinduct
apply clarsimp
subgoal for r i
apply (case_tac "shd (stl i)")
apply (simp del: ltl_step.simps)
apply (rule P_ltl_step_1)
apply simp
apply (rule disjI2)
apply (rule alw_mono[of "nxt (state_eq None)"])
apply (simp add: once_none_nxt_always_none)
apply simp
apply auto[1]
apply auto[1]
apply simp
apply standard
apply (rule disjI2)
apply (rule alw_mono[of "nxt (state_eq None)"])
apply (metis (no_types, lifting) drinks_step_2_none fst_conv make_full_observation.sel(2) nxt.simps nxt_alw once_none_always_none_aux)
by simp
done
lemma LTL_costsMoney:
"(alw (nxt (state_eq (Some 2)) impl (check_exp (Ge (V (Rg 2)) (L (Num 100)))))) (watch drinks i)"
proof(coinduction)
case alw
then show ?case
apply (cases "shd i")
subgoal for l ip
apply (case_tac "l = STR ''select'' ∧ length ip = 1")
defer
apply (simp add: possible_steps_0_invalid)
apply (rule disjI2)
apply (rule alw_mono[of "nxt (state_eq None)"])
apply (simp add: once_none_nxt_always_none)
apply simp
apply (simp add: possible_steps_0 select_def)
apply (rule disjI2)
apply (simp only: nxt.simps[symmetric])
using costsMoney_aux by auto
done
qed
lemma LTL_costsMoney_aux:
"(alw (not (check_exp (Ge (V (Rg 2)) (L (Num 100)))) impl (not (nxt (state_eq (Some 2)))))) (watch drinks i)"
by (metis (no_types, lifting) LTL_costsMoney alw_mono)
lemma implode_select: "String.implode ''select'' = STR ''select''"
by (metis Literal.rep_eq String.implode_explode_eq zero_literal.rep_eq)
lemma implode_coin: "String.implode ''coin'' = STR ''coin''"
by (metis Literal.rep_eq String.implode_explode_eq zero_literal.rep_eq)
lemma implode_vend: "String.implode ''vend'' = STR ''vend''"
by (metis Literal.rep_eq String.implode_explode_eq zero_literal.rep_eq)
lemmas implode_labels = implode_select implode_coin implode_vend
lemma LTL_neverReachS2:"(((((action_eq (''select'', [Str ''coke''])))
aand
(nxt ((action_eq (''coin'', [Num 100])))))
aand
(nxt (nxt((label_eq ''vend'' aand (input_eq []))))))
impl
(nxt (nxt (nxt (state_eq (Some 2))))))
(watch drinks i)"
apply (simp add: implode_labels)
apply (cases i)
apply clarify
apply simp
apply (simp add: possible_steps_0 select_def)
apply (case_tac "shd x2", clarify)
apply (simp add: possible_steps_1_coin coin_def value_plus_def finfun_update_twist apply_updates_def)
apply (case_tac "shd (stl x2)", clarify)
by (simp add: drinks_vend_sufficient )
lemma ltl_step_not_select:
"∄i. e = (STR ''select'', [i]) ⟹
ltl_step drinks (Some 0) r e = (None, [], r)"
apply (cases e, clarify)
subgoal for a b
apply (rule ltl_step_none)
apply (simp add: possible_steps_empty drinks_def can_take_transition_def can_take_def select_def)
by (cases e, case_tac b, auto)
done
lemma ltl_step_select:
"ltl_step drinks (Some 0) <> (STR ''select'', [i]) = (Some 1, [], <1 $:= Some i, 2 $:= Some (Num 0)>)"
apply (rule ltl_step_some[of _ _ _ _ _ _ select])
apply (simp add: possible_steps_0)
apply (simp add: select_def)
by (simp add: select_def finfun_update_twist apply_updates_def)
lemma ltl_step_not_coin_or_vend:
"∄i. e = (STR ''coin'', [i]) ⟹
e ≠ (STR ''vend'', []) ⟹
ltl_step drinks (Some 1) r e = (None, [], r)"
apply (cases e)
subgoal for a b
apply (simp del: ltl_step.simps)
apply (rule ltl_step_none)
apply (simp add: possible_steps_empty drinks_def can_take_transition_def can_take_def transitions)
by (case_tac e, case_tac b, auto)
done
lemma ltl_step_coin:
"∃p r'. ltl_step drinks (Some 1) r (STR ''coin'', [i]) = (Some 1, p, r')"
by (simp add: possible_steps_1_coin)
lemma alw_tl:
"alw φ (make_full_observation e (Some 0) <> [] xs) ⟹
alw φ
(make_full_observation e (fst (ltl_step e (Some 0) <> (shd xs))) (snd (snd (ltl_step e (Some 0) <> (shd xs))))
(fst (snd (ltl_step e (Some 0) <> (shd xs)))) (stl xs))"
by auto
lemma stop_at_none:
"alw (λxs. output (shd (stl xs)) = [Some (EFSM.Str drink)] ⟶ check_exp (Ge (V (Rg 2)) (L (Num 100))) xs)
(make_full_observation drinks None r p t)"
apply (rule alw_mono[of "nxt (output_eq [])"])
apply (simp add: no_output_none_nxt)
by simp
lemma drink_costs_money_aux:
assumes "∃p r t. j = make_full_observation drinks (Some 1) r p t"
shows "alw (λxs. output (shd (stl xs)) = [Some (EFSM.Str drink)] ⟶ check_exp (Ge (V (Rg 2)) (L (Num 100))) xs) j"
using assms apply coinduct
apply clarsimp
apply (case_tac "shd t")
apply (simp del: ltl_step.simps)
apply (rule P_ltl_step_1)
apply simp
apply (rule disjI2)
apply (rule alw_mono[of "nxt (output_eq [])"])
apply (simp add: no_output_none_nxt)
apply simp
apply (simp add: Str_def value_plus_never_string)
apply auto[1]
apply auto[1]
apply simp
apply standard
apply (rule disjI2)
apply (rule alw_mono[of "nxt (output_eq [])"])
apply (simp add: drinks_step_2_none no_output_none_if_empty nxt_alw)
by simp
lemma LTL_drinks_cost_money:
"alw (nxt (output_eq [Some (Str drink)]) impl (check_exp (Ge (V (Rg 2)) (L (Num 100))))) (watch drinks t)"
proof(coinduction)
case alw
then show ?case
apply (case_tac "shd t")
apply (simp del: ltl_step.simps)
apply (rule P_ltl_step_0)
apply simp
apply (rule disjI2)
apply (rule alw_mono[of "nxt (output_eq [])"])
apply (simp add: no_output_none_nxt)
apply simp
apply simp
using drink_costs_money_aux
apply simp
by blast
qed
lemma steps_1_invalid:
"∄i. (a, b) = (STR ''coin'', [i]) ⟹
∄i. (a, b) = (STR ''vend'', []) ⟹
possible_steps drinks 1 r a b = {||}"
apply (simp add: possible_steps_empty drinks_def transitions can_take_transition_def can_take_def)
by (induct b, auto)
lemma output_vend_aux:
assumes "∃p r t. j = make_full_observation drinks (Some 1) r p t"
shows "alw (λxs. label_eq ''vend'' xs ∧ output (shd (stl xs)) = [Some d] ⟶ check_exp (Ge (V (Rg 2)) (L (Num 100))) xs) j"
using assms apply coinduct
apply clarsimp
subgoal for r t
apply (case_tac "shd t")
apply (simp add: implode_vend del: ltl_step.simps)
apply (rule P_ltl_step_1)
apply simp
apply (rule disjI2)
apply (rule alw_mono[of "nxt (output_eq [])"])
apply (simp add: no_output_none_nxt)
apply simp
apply auto[1]
apply auto[1]
apply simp
apply standard
apply (rule disjI2)
apply (rule alw_mono[of "nxt (output_eq [])"])
apply (simp add: drinks_step_2_none no_output_none_if_empty nxt_alw)
by simp
done
text_raw‹\snip{outputVend}{1}{2}{%›
lemma LTL_output_vend:
"alw (((label_eq ''vend'') aand (nxt (output_eq [Some d]))) impl
(check_exp (Ge (V (Rg 2)) (L (Num 100))))) (watch drinks t)"
text_raw‹}%endsnip›
proof(coinduction)
case alw
then show ?case
apply (simp add: implode_vend)
apply (case_tac "shd t")
apply (simp del: ltl_step.simps)
apply (rule P_ltl_step_0)
apply simp
apply (rule disjI2)
apply (rule alw_mono[of "nxt (output_eq [])"])
apply (simp add: no_output_none_nxt)
apply simp
apply simp
subgoal for a b
using output_vend_aux[of "(make_full_observation drinks (Some 1)
<1 $:= Some (hd b), 2 $:= Some (Num 0)> [] (stl t))" d]
using implode_vend by auto
done
qed
text_raw‹\snip{outputVendUnfolded}{1}{2}{%›
lemma LTL_output_vend_unfolded:
"alw (λxs. (label (shd xs) = STR ''vend'' ∧
nxt (λs. output (shd s) = [Some d]) xs) ⟶
¬? value_gt (Some (Num 100)) (datastate (shd xs) $ 2) = trilean.true)
(watch drinks t)"
text_raw‹}%endsnip›
apply (insert LTL_output_vend[of d t])
by (simp add: implode_vend)
end