header {* \isaheader{Observable Sets of Nodes} *}
theory Observable imports "../Basic/CFG" begin
context CFG begin
inductive_set obs :: "'node => 'node set => 'node set"
for n::"'node" and S::"'node set"
where obs_elem:
"[|n -as->* n'; ∀nx ∈ set(sourcenodes as). nx ∉ S; n' ∈ S|] ==> n' ∈ obs n S"
lemma obsE:
assumes "n' ∈ obs n S"
obtains as where "n -as->* n'" and "∀nx ∈ set(sourcenodes as). nx ∉ S"
and "n' ∈ S"
proof(atomize_elim)
from `n' ∈ obs n S`
have "∃as. n -as->* n' ∧ (∀nx ∈ set(sourcenodes as). nx ∉ S) ∧ n' ∈ S"
by(auto elim:obs.cases)
thus "∃as. n -as->* n' ∧ (∀nx∈set (sourcenodes as). nx ∉ S) ∧ n' ∈ S" by blast
qed
lemma n_in_obs:
assumes "valid_node n" and "n ∈ S" shows "obs n S = {n}"
proof -
from `valid_node n` have "n -[]->* n" by(rule empty_path)
with `n ∈ S` have "n ∈ obs n S" by(fastforce elim:obs_elem simp:sourcenodes_def)
{ fix n' assume "n' ∈ obs n S"
have "n' = n"
proof(rule ccontr)
assume "n' ≠ n"
from `n' ∈ obs n S` obtain as where "n -as->* n'"
and "∀nx ∈ set(sourcenodes as). nx ∉ S"
and "n' ∈ S" by(erule obsE)
from `n -as->* n'` `∀nx ∈ set(sourcenodes as). nx ∉ S` `n' ≠ n` `n ∈ S`
show False
proof(induct rule:path.induct)
case (Cons_path n'' as n' a n)
from `∀nx∈set (sourcenodes (a#as)). nx ∉ S` `sourcenode a = n`
have "n ∉ S" by(simp add:sourcenodes_def)
with `n ∈ S` show False by simp
qed simp
qed }
with `n ∈ obs n S` show ?thesis by fastforce
qed
lemma in_obs_valid:
assumes "n' ∈ obs n S" shows "valid_node n" and "valid_node n'"
using `n' ∈ obs n S`
by(auto elim:obsE intro:path_valid_node)
lemma edge_obs_subset:
assumes"valid_edge a" and "sourcenode a ∉ S"
shows "obs (targetnode a) S ⊆ obs (sourcenode a) S"
proof
fix n assume "n ∈ obs (targetnode a) S"
then obtain as where "targetnode a -as->* n"
and all:"∀nx ∈ set(sourcenodes as). nx ∉ S" and "n ∈ S" by(erule obsE)
from `valid_edge a` `targetnode a -as->* n`
have "sourcenode a -a#as->* n" by(fastforce intro:Cons_path)
moreover
from all `sourcenode a ∉ S` have "∀nx ∈ set(sourcenodes (a#as)). nx ∉ S"
by(simp add:sourcenodes_def)
ultimately show "n ∈ obs (sourcenode a) S" using `n ∈ S`
by(rule obs_elem)
qed
lemma path_obs_subset:
"[|n -as->* n'; ∀n' ∈ set(sourcenodes as). n' ∉ S|]
==> obs n' S ⊆ obs n S"
proof(induct rule:path.induct)
case (Cons_path n'' as n' a n)
note IH = `∀n'∈set (sourcenodes as). n' ∉ S ==> obs n' S ⊆ obs n'' S`
from `∀n'∈set (sourcenodes (a#as)). n' ∉ S`
have all:"∀n'∈set (sourcenodes as). n' ∉ S" and "sourcenode a ∉ S"
by(simp_all add:sourcenodes_def)
from IH[OF all] have "obs n' S ⊆ obs n'' S" .
from `valid_edge a` `targetnode a = n''` `sourcenode a = n` `sourcenode a ∉ S`
have "obs n'' S ⊆ obs n S" by(fastforce dest:edge_obs_subset)
with `obs n' S ⊆ obs n'' S` show ?case by fastforce
qed simp
lemma path_ex_obs:
assumes "n -as->* n'" and "n' ∈ S"
obtains m where "m ∈ obs n S"
proof(atomize_elim)
show "∃m. m ∈ obs n S"
proof(cases "∀nx ∈ set(sourcenodes as). nx ∉ S")
case True
with `n -as->* n'` `n' ∈ S` have "n' ∈ obs n S" by -(rule obs_elem)
thus ?thesis by fastforce
next
case False
hence "∃nx ∈ set(sourcenodes as). nx ∈ S" by fastforce
then obtain nx ns ns' where "sourcenodes as = ns@nx#ns'"
and "nx ∈ S" and "∀n' ∈ set ns. n' ∉ S"
by(fastforce elim!:split_list_first_propE)
from `sourcenodes as = ns@nx#ns'` obtain as' a as''
where "ns = sourcenodes as'"
and "as = as'@a#as''" and "sourcenode a = nx"
by(fastforce elim:map_append_append_maps simp:sourcenodes_def)
with `n -as->* n'` have "n -as'->* nx" by(fastforce dest:path_split)
with `nx ∈ S` `∀n' ∈ set ns. n' ∉ S` `ns = sourcenodes as'` have "nx ∈ obs n S"
by(fastforce intro:obs_elem)
thus ?thesis by fastforce
qed
qed
end
end