fun is_state_cover :: "('a,'b,'c) fsm ==> ('b,'c) state_cover ==> bool"where "is_state_cover M SC = ([] ∈ SC ∧ (∀ q ∈ reachable_states M . ∃ io ∈ SC . q ∈ io_targets M io (initial M)))"
fun is_state_cover_assignment :: "('a,'b,'c) fsm ==> ('a,'b,'c) state_cover_assignment ==> bool"where "is_state_cover_assignment M f = (f (initial M) = [] ∧ (∀ q ∈ reachable_states M . q ∈ io_targets M (f q) (initial M)))"
lemma state_cover_assignment_from_state_cover : assumes"is_state_cover M SC" obtains f where"is_state_cover_assignment M f" and"∧ q . q ∈ reachable_states M ==> f q ∈ SC" proof -
define f where f: "f = (λ q . (if q = initial M then [] else (SOME io . io ∈ SC ∧ q ∈ io_targets M io (initial M))))"
have"f (initial M) = []" using f by auto moreoverhave"∧ q . q ∈ reachable_states M ==> f q ∈ SC ∧ q ∈ io_targets M (f q) (initial M)" proof - fix q assume"q ∈ reachable_states M" show"f q ∈ SC ∧ q ∈ io_targets M (f q) (initial M)" proof (cases "q = initial M") case True have"q ∈ io_targets M (f q) (FSM.initial M)" unfolding True ‹f (initial M) = []›by auto thenshow ?thesis using True assms ‹f (initial M) = []›by auto next case False thenhave"f q = (SOME io . io ∈ SC ∧ q ∈ io_targets M io (initial M))" using f by auto moreoverhave"∃ io . io ∈ SC ∧ q ∈ io_targets M io (initial M)" using assms ‹q ∈ reachable_states M› by (meson is_state_cover.simps) ultimatelyshow ?thesis by (metis (no_types, lifting) someI_ex) qed qed ultimatelyshow ?thesis using that[of f] by (meson is_state_cover_assignment.elims(3)) qed
lemma is_state_cover_assignment_language : assumes"is_state_cover_assignment M V" and"q ∈ reachable_states M" shows"V q ∈ L M" using assms io_targets_language by (metis is_state_cover_assignment.simps)
lemma is_state_cover_assignment_observable_after : assumes"observable M" and"is_state_cover_assignment M V" and"q ∈ reachable_states M" shows"after_initial M (V q) = q" proof - have"q ∈ io_targets M (V q) (initial M)" using assms(2,3) by auto thenhave"io_targets M (V q) (initial M) = {q}" using observable_io_targets[OF assms(1) io_targets_language[OF ‹q ∈ io_targets M (V q) (initial M)›]] by (metis singletonD)
thenobtain p where"path M (initial M) p"and"p_io p = V q"and"target (initial M) p = q" unfolding io_targets.simps by blast thenshow"after_initial M (V q) = q" using after_path[OF assms(1), of "initial M" p] by simp qed
lemma non_initialized_state_cover_assignment_from_non_initialized_state_cover : assumes"∧ q . q ∈ reachable_states M ==>∃ io ∈ L M ∩ SC . q ∈ io_targets M io (initial M)" obtains f where"∧ q . q ∈ reachable_states M ==> q ∈ io_targets M (f q) (initial M)" and"∧ q . q ∈ reachable_states M ==> f q ∈ L M ∩ SC" proof -
define f where f: "f = (λ q . (SOME io . io ∈ L M ∩ SC ∧ q ∈ io_targets M io (initial M)))"
have"∧ q . q ∈ reachable_states M ==> f q ∈ L M ∩ SC ∧ q ∈ io_targets M (f q) (initial M)" proof - fix q assume"q ∈ reachable_states M" show"f q ∈ L M ∩ SC ∧ q ∈ io_targets M (f q) (initial M)" proof - have"f q = (SOME io . io ∈ L M ∩ SC ∧ q ∈ io_targets M io (initial M))" using f by auto moreoverhave"∃ io . io ∈ L M ∩ SC ∧ q ∈ io_targets M io (initial M)" using assms ‹q ∈ reachable_states M› by (meson Int_iff) ultimatelyshow ?thesis by (metis (no_types, lifting) someI_ex) qed qed thenshow ?thesis using that[of f] by blast qed
lemma state_cover_assignment_inj : assumes"is_state_cover_assignment M V" and"observable M" and"q1 ∈ reachable_states M" and"q2 ∈ reachable_states M" and"q1 ≠ q2" shows"V q1 ≠ V q2" proof (rule ccontr) assume"¬ V q1 ≠ V q2"
thenhave"io_targets M (V q1) (initial M) = io_targets M (V q2) (initial M)" by auto thenhave"q1 = q2" using assms(2) proof - have f1: "∀a f. a ∉ FSM.states (f::('a, 'b, 'c) fsm) ∨ FSM.initial (FSM.from_FSM f a) = a" by (meson from_FSM_simps(1)) obtain ff :: "('a ==> ('b × 'c) list) ==> ('a, 'b, 'c) fsm ==> ('a, 'b, 'c) fsm"andpps :: "('a ==> ('b × 'c) list) ==> ('a, 'b, 'c) fsm ==> 'a ==> ('b × 'c) list"where
f2: "M = ff V M ∧ V = pps V M ∧ pps V M (FSM.initial (ff V M)) = [] ∧ (∀a. a ∉ reachable_states (ff V M) ∨ a ∈ io_targets (ff V M) (pps V M a) (FSM.initial (ff V M)))" using assms(1) by fastforce thenhave f3: "q2 ∈ FSM.states (ff V M)" by (simp add: ‹q2 ∈ reachable_states M› reachable_state_is_state) thenhave f4: "∃ps. FSM.initial (FSM.from_FSM M q2) = target (FSM.initial (ff V M)) ps ∧ path (ff V M) (FSM.initial (ff V M)) ps ∧ p_io ps = V q2" using f2 ‹q2 ∈ reachable_states M› assms(1) by auto have"q1 ∈ {target (FSM.initial M) ps |ps. path M (FSM.initial M) ps ∧ p_io ps = V q2}" by (metis (no_types) ‹io_targets M (V q1) (FSM.initial M) = io_targets M (V q2) (FSM.initial M)›‹q1 ∈ reachable_states M› assms(1) io_targets.simps is_state_cover_assignment.simps) thenhave"∃ps. FSM.initial (FSM.from_FSM M q1) = target (FSM.initial (ff V M)) ps∧ path (ff V M) (FSM.initial (ff V M)) ps ∧ p_io ps = V q2" using f2 by (simp add: ‹q1 ∈ reachable_states M› reachable_state_is_state) thenshow ?thesis using f4 f3 f2 f1 by (metis (no_types) ‹observable M›‹q1 ∈ reachable_states M› observable_path_io_target reachable_state_is_state singletonD singletonI) qed thenshow"False" using‹q1 ≠ q2›by blast qed
lemma state_cover_assignment_card : assumes"is_state_cover_assignment M V" and"observable M" shows"card (V ` reachable_states M) = card (reachable_states M)" proof - have"inj_on V (reachable_states M)" using state_cover_assignment_inj[OF assms] by (meson inj_onI)
thenhave"card (reachable_states M) ≤ card (V ` reachable_states M)" using fsm_states_finite restrict_to_reachable_states_simps(2) by (simp add: card_image) moreoverhave"card (V ` reachable_states M) ≤ card (reachable_states M)" using fsm_states_finite using card_image_le by (metis restrict_to_reachable_states_simps(2)) ultimatelyshow ?thesis by simp qed
lemma state_cover_assignment_language : assumes"is_state_cover_assignment M V" shows"V ` reachable_states M ⊆ L M" using assms unfolding is_state_cover_assignment.simps using language_io_target_append by fastforce
fun is_minimal_state_cover :: "('a,'b,'c) fsm ==> ('b,'c) state_cover ==> bool"where "is_minimal_state_cover M SC = (∃ f . (SC = f ` reachable_states M) ∧ (is_state_cover_assignment M f))"
lemma minimal_state_cover_is_state_cover : assumes"is_minimal_state_cover M SC" shows"is_state_cover M SC" proof - obtain f where"f (initial M) = []"and"(SC = f ` reachable_states M)"and"(∧ q . q ∈ reachable_states M ==> q ∈ io_targets M (f q) (initial M))" using assms by auto
show ?thesis unfolding is_state_cover.simps ‹(SC = f ` reachable_states M)› proof - have"f ` FSM.reachable_states M ⊆ L M" proof fix io assume"io ∈ f ` FSM.reachable_states M" thenobtain q where"q ∈ reachable_states M"and"io = f q" by blast thenhave"q ∈ io_targets M (f q) (initial M)" using‹(∧ q . q ∈ reachable_states M ==> q ∈ io_targets M (f q) (initial M))›by blast thenshow"io ∈ L M" unfolding‹io = f q ›by force qed
moreoverhave"∀q∈FSM.reachable_states M. ∃io∈f ` FSM.reachable_states M. q ∈ io_targets M io (FSM.initial M)" using‹(∧ q . q ∈ reachable_states M ==> q ∈ io_targets M (f q) (initial M))›by blast
ultimatelyshow"[] ∈ f ` FSM.reachable_states M ∧ (∀q∈FSM.reachable_states M. ∃io∈f ` FSM.reachable_states M. q ∈ io_targets M io (FSM.initial M))" using‹f (initial M) = []› reachable_states_initial by force qed qed
lemma state_cover_assignment_after : assumes"observable M" and"is_state_cover_assignment M V" and"q ∈ reachable_states M" shows"V q ∈ L M"and"after_initial M (V q) = q" proof - have"V q ∈ L M ∧ after_initial M (V q) = q" using assms(3) proof (induct rule: reachable_states_induct) case init have"V (FSM.initial M) = []" using assms(2) by auto thenshow ?case by auto next case (transition t) thenhave"t_target t ∈ reachable_states M" using reachable_states_next by metis thenhave"t_target t ∈ io_targets M (V (t_target t)) (FSM.initial M)" using assms(2) unfolding is_state_cover_assignment.simps by auto thenobtain p where"path M (initial M) p"and"target (initial M) p = t_target t"and"p_io p = V (t_target t)" by auto thenhave"V (t_target t) ∈ L M" by force thenshow ?case using after_path[OF assms(1) ‹path M (initial M) p›] unfolding‹p_io p = V (t_target t)›‹target (initial M) p = t_target t› by simp qed thenshow"V q ∈ L M"and"after_initial M (V q) = q" by simp+ qed
(* transitions considered covered by a state cover in the SPY and SPYH-Methods *) definition covered_transitions :: "('a,'b,'c) fsm ==> ('a,'b,'c) state_cover_assignment ==> ('b × 'c) list ==> ('a,'b,'c) transition set"where "covered_transitions M V α = (let ts = the_elem (paths_for_io M (initial M) α) in List.set (filter (λt . ((V (t_source t)) @ [(t_input t, t_output t)]) = (V (t_target t))) ts))"
subsection‹State Cover Computation›
fun reaching_paths_up_to_depth :: "('a::linorder,'b::linorder,'c::linorder) fsm ==> 'a set ==> 'a set ==> ('a ==> ('a,'b,'c) path option) ==> nat ==> ('a ==> ('a,'b,'c) path option)"where "reaching_paths_up_to_depth M nexts dones assignment 0 = assignment" | "reaching_paths_up_to_depth M nexts dones assignment (Suc k) = (let usable_transitions = filter (λ t . t_source t ∈ nexts ∧ t_target t ∉ dones ∧ t_target t ∉ nexts) (transitions_as_list M); targets = map t_target usable_transitions; transition_choice = Map.empty(targets [↦] usable_transitions); assignment' = assignment(targets [↦] (map (λq' . case transition_choice q' of Some t ==> (case assignment (t_source t) of Some p ==> p@[t])) targets)); nexts' = set targets; dones' = nexts ∪ dones in reaching_paths_up_to_depth M nexts' dones' assignment' k)"
lemma reaching_paths_up_to_depth_set : assumes"nexts = {q . (∃ p . path M (initial M) p ∧ target (initial M) p = q ∧ length p = n) ∧ (∄ p . path M (initial M) p ∧ target (initial M) p = q ∧ length p < n)}" and"dones = {q . ∃ p . path M (initial M) p ∧ target (initial M) p = q ∧ length p < n}" and"∧ q . assignment q = None = (∄p . path M (initial M) p ∧ target (initial M) p = q ∧ length p ≤ n)" and"∧ q p . assignment q = Some p ==> path M (initial M) p ∧ target (initial M) p = q ∧ length p ≤ n" and"dom assignment = nexts ∪ dones" shows"((reaching_paths_up_to_depth M nexts dones assignment k) q = None) = (∄p . path M (initial M) p ∧ target (initial M) p = q ∧ length p ≤ n+k)" and"((reaching_paths_up_to_depth M nexts dones assignment k) q = Some p) ==> path M (initial M) p ∧ target (initial M) p = q ∧ length p ≤ n+k" and"q ∈ nexts ∪ dones ==> (reaching_paths_up_to_depth M nexts dones assignment k) q = assignment q" proof - have"(((reaching_paths_up_to_depth M nexts dones assignment k) q = None) = (∄p . path M (initial M) p ∧ target (initial M) p = q ∧ length p ≤ n+k)) ∧ (((reaching_paths_up_to_depth M nexts dones assignment k) q = Some p) ⟶ path M (initial M) p ∧ target (initial M) p = q ∧ length p ≤ n+k) ∧ (q ∈ nexts ∪ dones ⟶ (reaching_paths_up_to_depth M nexts dones assignment k) q = assignment q)" using assms proof (induction k arbitrary: n q nexts dones assignment) case0
have *:"((reaching_paths_up_to_depth M nexts dones assignment 0) q) = assignment q" by auto show ?case unfolding * using"0.prems"(3,4)[of q] by simp next case (Suc k)
define usable_transitions where d1: "usable_transitions = filter (λ t . t_source t ∈nexts ∧ t_target t ∉ dones ∧ t_target t ∉ nexts) (transitions_as_list M)" moreover define targets where d2: "targets = map t_target usable_transitions" moreover define transition_choice where d3: "transition_choice = Map.empty(targets [↦] usable_transitions)" moreover define assignment' where d4: "assignment' = assignment(targets [↦] (map (λq' . case transition_choice q' of Some t ==> (case assignment (t_source t) of Some p==> p@[t])) targets))" ultimatelyhave d5: "reaching_paths_up_to_depth M nexts dones assignment (Suc k) = reaching_paths_up_to_depth M (set targets) (nexts ∪ dones) assignment' k" unfolding reaching_paths_up_to_depth.simps Let_def by force
let ?nexts' = "(set targets)" let ?dones' = "(nexts ∪ dones)"
have p1: "?nexts' = {q. (∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p = Suc n) ∧ (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < Suc n)}" (is"?nexts' = ?PS") proof - have"∧ q . q ∈ ?nexts' ==> q ∈ ?PS" proof - fix q assume"q ∈ ?nexts'" thenobtain t where"t ∈ transitions M" and"t_source t ∈ nexts" and"t_target t = q" and"t_target t ∉ dones" and"t_target t ∉ nexts" unfolding d2 d1 using transitions_as_list_set[of M] by force
obtain p where"path M (initial M) p"and"target (initial M) p = t_source t"and"length p = n" using‹t_source t ∈ nexts›unfolding Suc.prems by blast thenhave"path M (initial M) (p@[t])"and"target (initial M) (p@[t]) = q" unfolding‹t_target t = q›[symmetric] using‹t ∈ transitions M›by auto thenhave"(∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p = Suc n)" using‹length p = n›by (metis length_append_singleton) moreoverhave"(∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < Suc n)" using‹t_target t ∉ dones›‹t_target t ∉ nexts›unfolding‹t_target t = q› Suc.prems using less_antisym by blast ultimatelyshow"q ∈ ?PS" by blast qed moreoverhave"∧ q . q ∈ ?PS ==> q ∈ ?nexts'" proof - fix q assume"q ∈ ?PS" thenobtain p where"path M (initial M) p"and"target (initial M) p = q"and"length p = Suc n" by auto
let ?p = "butlast p" let ?t = "last p"
have"p = ?p@[?t]" using‹length p = Suc n› by (metis append_butlast_last_id list.size(3) nat.simps(3)) thenhave"path M (initial M) (?p@[?t])" using‹path M (initial M) p›by auto
have"path M (FSM.initial M) ?p" "?t ∈ FSM.transitions M" "t_source ?t = target (FSM.initial M) ?p" using path_append_transition_elim[OF ‹path M (initial M) (?p@[?t])›] by blast+
have"t_target ?t = q" using‹target (initial M) p = q›‹p = ?p@[?t]›unfolding target.simps visited_states.simps by (metis (no_types, lifting) last_ConsR last_map map_is_Nil_conv snoc_eq_iff_butlast) moreoverhave"t_source ?t ∈ nexts" proof - have"length ?p = n" using‹p = ?p@[?t]›‹length p = Suc n›by auto thenhave"(∃ p . path M (initial M) p ∧ target (initial M) p = t_source ?t ∧ length p = n)" using‹path M (FSM.initial M) ?p›‹t_source ?t = target (FSM.initial M) ?p› by metis moreoverhave"(∄ p . path M (initial M) p ∧ target (initial M) p = t_source ?t ∧length p < n)" proof assume"∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = t_source ?t ∧ length p < n" thenobtain p' where"path M (FSM.initial M) p'"and"target (FSM.initial M) p' = t_source ?t"and"length p' < n" by blast thenhave"path M (initial M) (p'@[?t])"and"length (p'@[?t]) < Suc n" using‹?t ∈ FSM.transitions M›by auto moreoverhave"target (initial M) (p'@[?t]) = q" using‹t_target ?t = q›by auto ultimatelyshow"False" using‹q ∈ ?PS› by (metis (mono_tags, lifting) mem_Collect_eq) qed ultimatelyshow ?thesis unfolding Suc.prems by blast qed moreoverhave"q ∉ dones"and"q ∉ nexts" unfolding Suc.prems using‹q ∈ ?PS› using less_SucI by blast+ ultimatelyhave"t_source ?t ∈ nexts ∧ t_target ?t ∉ dones ∧ t_target ?t ∉ nexts" by simp thenshow"q ∈ ?nexts'" unfolding d2 d1 using transitions_as_list_set[of M] ‹?t ∈ FSM.transitions M›‹t_target ?t = q› by auto qed ultimatelyshow ?thesis by blast qed
have p2: "?dones' = {q. ∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < Suc n}" (is"?dones' = ?PS") proof - have"∧ q . q ∈ ?dones' ==> q ∈ ?PS" unfolding Suc.prems using less_SucI by blast moreoverhave"∧ q . q ∈ ?PS ==> q ∈ ?dones'" proof - fix q assume"q ∈ ?PS" show"q ∈ ?dones'"proof (cases "∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < n") case True thenshow ?thesis unfolding Suc.prems by blast next case False
obtain p where *: "path M (FSM.initial M) p ∧ target (FSM.initial M) p = q"and"length p < Suc n" using‹q ∈ ?PS›by blast thenhave"length p = n" using False by force
thenshow ?thesis using * False unfolding Suc.prems by blast qed qed ultimatelyshow ?thesis by blast qed
have p3: "(∧q. (assignment' q = None) = (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ Suc n))" and p4: "(∧q p. assignment' q = Some p ==> path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ Suc n)" and p5: "dom assignment' = ?nexts' ∪ ?dones'" proof -
have"dom transition_choice = set targets" unfolding d3 d2 by auto
have helper: "∧ f P (n::nat) . {x . (∃ y . P x y ∧ f y = n) ∧ (∄ y . P x y ∧ f y < n)} ∪ {x . (∃ y . P x y ∧ f y < n)}= {x . (∃ y . P x y ∧ f y ≤ n)}" by force
have dom': "dom assignment' = {q. ∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ Suc n}" unfolding‹dom assignment' = ?nexts' ∪ ?dones'› p1 p2 using helper[of "λ q p . path M (FSM.initial M) p ∧ target (FSM.initial M) p = q" length "Suc n"] by force
have *: "∧ q . q ∈ ?nexts' ==>∃ p . assignment' q = Some p ∧ path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ Suc n" proof - fix q assume"q ∈ ?nexts'" thenobtain t where"transition_choice q = Some t" using‹dom transition_choice = set targets› d2 d3 by blast thenhave"t ∈ set usable_transitions" and"t_target t = q" and"q ∈ set targets" unfolding d3 d2 using map_upds_map_set_left[of t_target usable_transitions q t] by auto thenhave"t_source t ∈ nexts"and"t ∈ transitions M" unfolding d1 using transitions_as_list_set[of M] by auto thenobtain p where"assignment (t_source t) = Some p" using Suc.prems(1,3,4) by fastforce thenhave"path M (FSM.initial M) p ∧ target (FSM.initial M) p = t_source t ∧ length p ≤ n" using Suc.prems(4) by blast thenhave"path M (FSM.initial M) (p@[t]) ∧ target (FSM.initial M) (p@[t]) = q ∧ length (p@[t]) ≤ Suc n" using‹t ∈ transitions M›‹t_target t = q›by auto moreoverhave"assignment' q = Some (p@[t])" proof - have"assignment' q = [targets [↦] (map (λq' . case transition_choice q' of Some t==> (case assignment (t_source t) of Some p ==> p@[t])) targets)] q" unfolding d4 using map_upds_overwrite[OF ‹q ∈ set targets›, of "map (λq' . case transition_choice q' of Some t ==> (case assignment (t_source t) of Some p ==> p@[t])) targets" assignment] by auto alsohave"… = Some (case transition_choice q of Some t ==> case assignment (t_source t) of Some p ==> p @ [t])" using map_upds_map_set_right[OF ‹q ∈ set targets›] by auto alsohave"… = Some (p@[t])" using‹transition_choice q = Some t›‹assignment (t_source t) = Some p›by simp finallyshow ?thesis . qed ultimatelyshow"∃ p . assignment' q = Some p ∧ path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ Suc n" by simp qed
show"(∧q. (assignment' q = None) = (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ Suc n))" using dom' by blast
show"(∧q p. assignment' q = Some p ==> path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ Suc n)" proof - fix q p assume"assignment' q = Some p"
show"path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ Suc n" proof (cases "q ∈ ?nexts'") case True show ?thesis using *[OF True] ‹assignment' q = Some p› by simp next case False moreoverhave"∧ q . assignment q ≠ assignment' q ==> q ∈ ?nexts'" unfolding d4 by (metis (no_types) map_upds_apply_nontin) ultimatelyhave"assignment' q = assignment q" by force thenshow ?thesis using Suc.prems(4) ‹assignment' q = Some p› by (simp add: le_SucI) qed qed qed
have"∧ q . (reaching_paths_up_to_depth M (set targets) (nexts ∪ dones) assignment' k q = None) = (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ n + Suc k) ∧ (reaching_paths_up_to_depth M (set targets) (nexts ∪ dones) assignment' k q = Some p ⟶ path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ n + Suc k)" using Suc.IH[OF p1 p2 p3 p4 p5] by auto
moreoverhave"(q ∈ nexts ∪ dones ⟶ reaching_paths_up_to_depth M nexts dones assignment (Suc k) q = assignment q)" proof - have"∧ q . (q ∈ set targets ∪ (nexts ∪ dones) ==> reaching_paths_up_to_depth M (set targets) (nexts ∪ dones) assignment' k q = assignment' q)" using Suc.IH[OF p1 p2 p3 p4 p5] by auto moreoverhave"∧ q . assignment q ≠ assignment' q ==> q ∈ ?nexts'" unfolding d4 by (metis (no_types) map_upds_apply_nontin) ultimatelyshow ?thesis unfolding d5 by (metis (mono_tags, lifting) Un_iff mem_Collect_eq p1 p2) qed ultimatelyshow ?case unfolding d5 by blast qed
thenshow"((reaching_paths_up_to_depth M nexts dones assignment k) q = None) = (∄p . path M (initial M) p ∧ target (initial M) p = q ∧ length p ≤ n+k)" and"((reaching_paths_up_to_depth M nexts dones assignment k) q = Some p) ==> path M (initial M) p ∧ target (initial M) p = q ∧ length p ≤ n+k" and"q ∈ nexts ∪ dones ==> (reaching_paths_up_to_depth M nexts dones assignment k) q = assignment q" by blast+ qed
fun get_state_cover_assignment :: "('a::linorder,'b::linorder,'c::linorder) fsm ==> ('a,'b,'c) state_cover_assignment"where "get_state_cover_assignment M = (let path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1) in (λ q . case path_assignments q of Some p ==> p_io p | None ==> []))"
lemma get_state_cover_assignment_is_state_cover_assignment : "is_state_cover_assignment M (get_state_cover_assignment M)" unfolding is_state_cover_assignment.simps proof
define path_assignments where"path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1)" thenhave *:"∧ q . get_state_cover_assignment M q = (case path_assignments q of Some p ==> p_io p | None ==> [])" by auto
have c1: " {FSM.initial M} = {q. (∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p = 0)∧ (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < 0)}" by auto have c2: "{} = {q. ∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < 0}" by auto have c3: "(∧q. ([FSM.initial M ↦ []] q = None) = (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ 0))"byauto have c4: "(∧q p. [FSM.initial M ↦ []] q = Some p ==> path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ 0)" by (metis (no_types, lifting) c3 le_zero_eq length_0_conv map_upd_Some_unfold option.discI) have c5: "dom [FSM.initial M ↦ []] = {FSM.initial M} ∪ {}" by simp
have p1: "∧ q . (path_assignments q = None) = (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ (FSM.size M - 1))" and p2: "∧ q p . path_assignments q = Some p ==> path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ (FSM.size M - 1)" and p3: "path_assignments (initial M) = Some []" unfolding‹path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1)› using reaching_paths_up_to_depth_set[OF c1 c2 c3 c4 c5] by auto
show"get_state_cover_assignment M (FSM.initial M) = []" unfolding * p3 by auto
show"∀q∈reachable_states M. q ∈ io_targets M (get_state_cover_assignment M q) (FSM.initial M)" proof fix q assume"q ∈ reachable_states M" thenhave"q ∈ reachable_k M (FSM.initial M) (FSM.size M - 1)" using reachable_k_states by metis thenobtain p where"target (initial M) p = q"and"path M (initial M) p"and"length p ≤ size M - 1" by auto thenhave"path_assignments q ≠ None" using p1 by fastforce thenobtain p' where"get_state_cover_assignment M q = p_io p'" and"path M (FSM.initial M) p'"and"target (FSM.initial M) p' = q" using p2 unfolding * by force thenshow"q ∈ io_targets M (get_state_cover_assignment M q) (initial M)" unfolding io_targets.simps unfolding‹get_state_cover_assignment M q = p_io p'›by blast qed qed
subsection‹Computing Reachable States via State Cover Computation›
lemma restrict_to_reachable_states[code]: "restrict_to_reachable_states M = (let path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1) in filter_states M (λ q . path_assignments q ≠ None))" proof -
define path_assignments where"path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1)" thenhave *: "(let path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1) in filter_states M (λ q . path_assignments q ≠ None)) = filter_states M (λ q . path_assignments q ≠ None)" by simp
have c1: " {FSM.initial M} = {q. (∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p = 0)∧ (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < 0)}" by auto have c2: "{} = {q. ∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < 0}" by auto have c3: "(∧q. ([FSM.initial M ↦ []] q = None) = (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ 0))"byauto have c4: "(∧q p. [FSM.initial M ↦ []] q = Some p ==> path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ 0)" by (metis (no_types, lifting) c3 le_zero_eq length_0_conv map_upd_Some_unfold option.discI) have c5: "dom [FSM.initial M ↦ []] = {FSM.initial M} ∪ {}" by simp
have p1: "∧ q . (path_assignments q = None) = (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ (FSM.size M - 1))" and p2: "∧ q p . path_assignments q = Some p ==> path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ (FSM.size M - 1)" and p3: "path_assignments (initial M) = Some []" unfolding‹path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1)› using reaching_paths_up_to_depth_set[OF c1 c2 c3 c4 c5] by auto
have"∧ q . path_assignments q ≠ None ⟷ q ∈ reachable_states M" proof show"∧q. path_assignments q ≠ None ==> q ∈ reachable_states M" using p2 unfolding reachable_states_def by blast show"∧q. q ∈ reachable_states M ==> path_assignments q ≠ None" proof - fix q assume"q ∈ reachable_states M" thenhave"q ∈ reachable_k M (FSM.initial M) (FSM.size M - 1)" using reachable_k_states by metis thenobtain p where"target (initial M) p = q"and"path M (initial M) p"and"length p ≤ size M - 1" by auto thenshow"path_assignments q ≠ None" using p1 by fastforce qed qed thenshow ?thesis unfolding restrict_to_reachable_states.simps * by simp qed
lemma reachable_states_refined[code] : "reachable_states M = (let path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1) in Set.filter (λ q . path_assignments q ≠ None) (states M))" proof -
define path_assignments where"path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1)" thenhave *: "(let path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1) in Set.filter (λ q . path_assignments q ≠ None) (states M)) = Set.filter (λ q . path_assignments q ≠ None) (states M)" by simp
have c1: " {FSM.initial M} = {q. (∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p = 0)∧ (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < 0)}" by auto have c2: "{} = {q. ∃p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p < 0}" by auto have c3: "(∧q. ([FSM.initial M ↦ []] q = None) = (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ 0))"byauto have c4: "(∧q p. [FSM.initial M ↦ []] q = Some p ==> path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ 0)" by (metis (no_types, lifting) c3 le_zero_eq length_0_conv map_upd_Some_unfold option.discI) have c5: "dom [FSM.initial M ↦ []] = {FSM.initial M} ∪ {}" by simp
have p1: "∧ q . (path_assignments q = None) = (∄p. path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ (FSM.size M - 1))" and p2: "∧ q p . path_assignments q = Some p ==> path M (FSM.initial M) p ∧ target (FSM.initial M) p = q ∧ length p ≤ (FSM.size M - 1)" and p3: "path_assignments (initial M) = Some []" unfolding‹path_assignments = reaching_paths_up_to_depth M {initial M} {} [initial M ↦ []] (size M -1)› using reaching_paths_up_to_depth_set[OF c1 c2 c3 c4 c5] by auto
have"∧ q . path_assignments q ≠ None ⟷ q ∈ reachable_states M" proof show"∧q. path_assignments q ≠ None ==> q ∈ reachable_states M" using p2 unfolding reachable_states_def by blast show"∧q. q ∈ reachable_states M ==> path_assignments q ≠ None" proof - fix q assume"q ∈ reachable_states M" thenhave"q ∈ reachable_k M (FSM.initial M) (FSM.size M - 1)" using reachable_k_states by metis thenobtain p where"target (initial M) p = q"and"path M (initial M) p"and"length p ≤ size M - 1" by auto thenshow"path_assignments q ≠ None" using p1 by fastforce qed qed thenshow ?thesis unfolding * using reachable_state_is_state by force qed
lemma minimal_sequence_to_failure_from_state_cover_assignment_ob : assumes"L M ≠ L I" and"is_state_cover_assignment M V" and"(L M ∩ (V ` reachable_states M)) = (L I ∩ (V ` reachable_states M))" obtains ioT ioX where"ioT ∈ (V ` reachable_states M)" and"ioT @ ioX ∈ (L M - L I) ∪ (L I - L M)" and"∧ io q . q ∈ reachable_states M ==> (V q)@io ∈ (L M - L I) ∪ (L I - L M) ==> length ioX ≤ length io" proof -
let ?exts = "{io . ∃ q ∈ reachable_states M . (V q)@io ∈ (L M - L I) ∪ (L I - L M)}"
define exMin where exMin: "exMin = arg_min length (λ io . io ∈ ?exts)"
have"V (initial M) = []" using assms(2) by auto moreoverhave"∃ io . io ∈ (L M - L I) ∪ (L I - L M)" using assms(1) by blast ultimatelyhave"?exts ≠ {}" using reachable_states_initial by (metis (mono_tags, lifting) append_self_conv2 empty_iff mem_Collect_eq) thenhave"exMin ∈ ?exts ∧ (∀ io' . io' ∈ ?exts ⟶ length exMin ≤ length io')" using exMin arg_min_nat_lemma by (metis (no_types, lifting) all_not_in_conv) thenshow ?thesis using that by blast qed
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.