Theory Normalized_Zone_Semantics
chapter ‹Forward Analysis with DBMs and Widening›
theory Normalized_Zone_Semantics
imports DBM_Zone_Semantics Approx_Beta Simulation_Graphs_TA
begin
hide_const (open) D
no_notation infinity (‹∞›)
lemma rtranclp_backwards_invariant_iff:
assumes invariant: "⋀ y z. E⇧*⇧* x y ⟹ P z ⟹ E y z ⟹ P y"
and E': "E' = (λ x y. E x y ∧ P y)"
shows "E'⇧*⇧* x y ∧ P x ⟷ E⇧*⇧* x y ∧ P y"
unfolding E'
by (safe; induction rule: rtranclp_induct; auto dest: invariant intro: rtranclp.intros(2))
context Bisimulation_Invariant
begin
context
fixes φ :: "'a ⇒ bool" and ψ :: "'b ⇒ bool"
assumes compatible: "a ∼ b ⟹ PA a ⟹ PB b ⟹ φ a ⟷ ψ b"
begin
lemma reaches_ex_iff:
"(∃ b. A.reaches a b ∧ φ b) ⟷ (∃ b. B.reaches a' b ∧ ψ b)" if "a ∼ a'" "PA a" "PB a'"
using that by (force simp: compatible equiv'_def dest: bisim.A_B_reaches bisim.B_A_reaches)
lemma reaches_all_iff:
"(∀ b. A.reaches a b ⟶ φ b) ⟷ (∀ b. B.reaches a' b ⟶ ψ b)" if "a ∼ a'" "PA a" "PB a'"
using that by (force simp: compatible equiv'_def dest: bisim.A_B_reaches bisim.B_A_reaches)
end
end
lemma step_z_dbm_delay_loc:
"l' = l" if "A ⊢ ⟨l, D⟩ ↝⇘v,n,τ⇙ ⟨l', D'⟩"
using that by (auto elim!: step_z_dbm.cases)
lemma step_z_dbm_action_state_set1:
"l ∈ state_set A" if "A ⊢ ⟨l, D⟩ ↝⇘v,n,↿a⇙ ⟨l', D'⟩"
using that by (auto elim!: step_z_dbm.cases intro: state_setI1)
lemma step_z_dbm_action_state_set2:
"l' ∈ state_set A" if "A ⊢ ⟨l, D⟩ ↝⇘v,n,↿a⇙ ⟨l', D'⟩"
using that by (auto elim!: step_z_dbm.cases intro: state_setI2)
lemma step_delay_loc:
"l' = l" if "A ⊢ ⟨l, u⟩ →⇗d⇖ ⟨l', u'⟩"
using that by (auto elim!: step_t.cases)
lemma step_a_state_set1:
"l ∈ state_set A" if "A ⊢ ⟨l, u⟩ →⇘a⇙ ⟨l', u'⟩"
using that by (auto elim!: step_a.cases intro: state_setI1)
lemma step'_state_set1:
"l ∈ state_set A" if "A ⊢' ⟨l, u⟩ → ⟨l', u'⟩"
using that by (auto elim!: step'.cases intro: step_a_state_set1 dest: step_delay_loc)
section ‹DBM-based Semantics with Normalization›
subsection ‹Single Step›
inductive step_z_norm ::
"('a, 'c, t, 's) ta
⇒ 's ⇒ t DBM ⇒ ('s ⇒ nat ⇒ nat) ⇒ ('c ⇒ nat) ⇒ nat ⇒ 'a action ⇒ 's ⇒ t DBM ⇒ bool"
(‹_ ⊢ ⟨_, _⟩ ↝⇘_,_,_,_⇙ ⟨_, _⟩› [61,61,61,61,61,61] 61)
where step_z_norm:
"A ⊢ ⟨l,D⟩ ↝⇘v,n,a⇙ ⟨l', D'⟩ ⟹ A ⊢ ⟨l,D⟩ ↝⇘k,v,n,a⇙ ⟨l', norm (FW D' n) (k l') n⟩"
inductive step_z_norm' ::
"('a, 'c, t, 's) ta ⇒ 's ⇒ t DBM ⇒ ('s ⇒ nat ⇒ nat) ⇒ ('c ⇒ nat) ⇒ nat ⇒ 's ⇒ t DBM ⇒ bool"
(‹_ ⊢'' ⟨_, _⟩ ↝⇘_,_,_⇙ ⟨_, _⟩› [61,61,61,61,61] 61)
where
step: "A ⊢ ⟨l', Z'⟩ ↝⇘v,n,τ⇙ ⟨l'', Z''⟩
⟹ A ⊢ ⟨l'', Z''⟩ ↝⇘k,v,n,↿(a)⇙ ⟨l''', Z'''⟩
⟹ A ⊢' ⟨l', Z'⟩ ↝⇘k,v,n⇙ ⟨l''', Z'''⟩"
abbreviation steps_z_norm ::
"('a, 'c, t, 's) ta ⇒ 's ⇒ t DBM ⇒ ('s ⇒ nat ⇒ nat) ⇒ ('c ⇒ nat) ⇒ nat ⇒ 's ⇒ t DBM ⇒ bool"
(‹_ ⊢ ⟨_, _⟩ ↝⇘_,_,_⇙* ⟨_, _⟩› [61,61,61,61,61] 61) where
"A ⊢ ⟨l,D⟩ ↝⇘k,v,n⇙* ⟨l', D'⟩ ≡ (λ (l, Z) (l', Z'). A ⊢' ⟨l, Z⟩ ↝⇘k,v,n⇙ ⟨l', Z'⟩)⇧*⇧* (l, D) (l', D')"
lemma norm_empty_diag_preservation_real:
fixes k :: "nat ⇒ nat"
assumes "i ≤ n"
assumes "M i i < Le 0"
shows "norm M (real o k) n i i < Le 0"
using assms unfolding norm_def by (auto simp: Let_def norm_diag_def DBM.less)
context Regions_defs
begin
inductive valid_dbm where
"[M]⇘v,n⇙ ⊆ V ⟹ dbm_int M n ⟹ valid_dbm M"
inductive_cases valid_dbm_cases[elim]: "valid_dbm M"
declare valid_dbm.intros[intro]
end
locale Regions_common =
Regions_defs X v n for X :: "'c set" and v n +
fixes not_in_X
assumes finite: "finite X"
assumes clock_numbering: "clock_numbering' v n" "∀k≤n. k > 0 ⟶ (∃c ∈ X. v c = k)"
"∀ c ∈ X. v c ≤ n"
assumes not_in_X: "not_in_X ∉ X"
assumes non_empty: "X ≠ {}"
begin
lemma FW_zone_equiv_spec:
shows "[M]⇘v,n⇙ = [FW M n]⇘v,n⇙"
apply (rule FW_zone_equiv) using clock_numbering(2) by auto
lemma dbm_non_empty_diag:
assumes "[M]⇘v,n⇙ ≠ {}"
shows "∀ k ≤ n. M k k ≥ 0"
proof safe
fix k assume k: "k ≤ n"
have "∀k≤n. 0 < k ⟶ (∃c. v c = k)" using clock_numbering(2) by blast
from k not_empty_cyc_free[OF this assms(1)] show "0 ≤ M k k" by (simp add: cyc_free_diag_dest')
qed
lemma cn_weak: "∀k≤n. 0 < k ⟶ (∃c. v c = k)" using clock_numbering(2) by blast
lemma negative_diag_empty:
assumes "∃ k ≤ n. M k k < 0"
shows "[M]⇘v,n⇙ = {}"
using dbm_non_empty_diag assms by force
lemma non_empty_cyc_free:
assumes "[M]⇘v,n⇙ ≠ {}"
shows "cyc_free M n"
using FW_neg_cycle_detect FW_zone_equiv_spec assms negative_diag_empty by blast
lemma FW_valid_preservation:
assumes "valid_dbm M"
shows "valid_dbm (FW M n)"
proof standard
from FW_int_preservation assms show "dbm_int (FW M n) n" by blast
next
from FW_zone_equiv_spec[of M, folded neutral] assms show "[FW M n]⇘v,n⇙ ⊆ V" by fastforce
qed
end
context Regions_global
begin
sublocale Regions_common by standard (rule finite clock_numbering not_in_X non_empty)+
abbreviation "v' ≡ beta_interp.v'"
lemma apx_empty_iff'':
assumes "canonical M1 n" "[M1]⇘v,n⇙ ⊆ V" "dbm_int M1 n"
shows "[M1]⇘v,n⇙ = {} ⟷ [norm M1 (k o v') n]⇘v,n⇙ = {}"
using beta_interp.apx_norm_eq[OF assms] apx_empty_iff'[of "[M1]⇘v,n⇙"] assms
unfolding V'_def by blast
lemma norm_FW_empty:
assumes "valid_dbm M"
assumes "[M]⇘v,n⇙ = {}"
shows "[norm (FW M n) (k o v') n]⇘v,n⇙ = {}" (is "[?M]⇘v,n⇙ = {}")
proof -
from assms(2) cyc_free_not_empty clock_numbering(1) have "¬ cyc_free M n"
by metis
from FW_neg_cycle_detect[OF this] obtain i where i: "i ≤ n" "FW M n i i < 0" by auto
with norm_empty_diag_preservation_real[folded neutral] have
"?M i i < 0"
unfolding comp_def by auto
with ‹i ≤ n› show ?thesis using beta_interp.neg_diag_empty_spec by auto
qed
lemma apx_norm_eq_spec:
assumes "valid_dbm M"
and "[M]⇘v,n⇙ ≠ {}"
shows "beta_interp.Approx⇩β ([M]⇘v,n⇙) = [norm (FW M n) (k o v') n]⇘v,n⇙"
proof -
note cyc_free = non_empty_cyc_free[OF assms(2)]
from assms(1) FW_zone_equiv_spec[of M] have "[M]⇘v,n⇙ = [FW M n]⇘v,n⇙" by (auto simp: neutral)
with beta_interp.apx_norm_eq[OF fw_canonical[OF cyc_free] _ FW_int_preservation]
dbm_non_empty_diag[OF assms(2)] assms(1)
show "Approx⇩β ([M]⇘v,n⇙) = [norm (FW M n) (k o v') n]⇘v,n⇙" by auto
qed
lemma norm_FW_valid_preservation_non_empty:
assumes "valid_dbm M" "[M]⇘v,n⇙ ≠ {}"
shows "valid_dbm (norm (FW M n) (k o v') n)" (is "valid_dbm ?M")
proof -
from FW_valid_preservation[OF assms(1)] have valid: "valid_dbm (FW M n)" .
show ?thesis
proof standard
from valid beta_interp.norm_int_preservation show "dbm_int ?M n" by blast
next
from fw_canonical[OF non_empty_cyc_free] assms have "canonical (FW M n) n" by auto
from beta_interp.norm_V_preservation[OF _ this ] valid show "[?M]⇘v,n⇙ ⊆ V" by fast
qed
qed
lemma norm_int_all_preservation:
fixes M :: "real DBM"
assumes "dbm_int_all M"
shows "dbm_int_all (norm M (k o v') n)"
using assms unfolding norm_def norm_diag_def by (auto simp: Let_def)
lemma norm_FW_valid_preservation_empty:
assumes "valid_dbm M" "[M]⇘v,n⇙ = {}"
shows "valid_dbm (norm (FW M n) (k o v') n)" (is "valid_dbm ?M")
proof -
from FW_valid_preservation[OF assms(1)] have valid: "valid_dbm (FW M n)" .
show ?thesis
proof standard
from valid beta_interp.norm_int_preservation show "dbm_int ?M n" by blast
next
from norm_FW_empty[OF assms(1,2)] show "[?M]⇘v,n⇙ ⊆ V" by fast
qed
qed
lemma norm_FW_valid_preservation:
assumes "valid_dbm M"
shows "valid_dbm (norm (FW M n) (k o v') n)"
using assms norm_FW_valid_preservation_empty norm_FW_valid_preservation_non_empty by metis
lemma norm_FW_equiv:
assumes valid: "dbm_int D n" "dbm_int M n" "[D]⇘v,n⇙ ⊆ V"
and equiv: "[D]⇘v,n⇙ = [M]⇘v,n⇙"
shows "[norm (FW D n) (k o v') n]⇘v,n⇙ = [norm (FW M n) (k o v') n]⇘v,n⇙"
proof (cases "[D]⇘v,n⇙ = {}")
case False
with equiv fw_shortest[OF non_empty_cyc_free] FW_zone_equiv_spec have
"canonical (FW D n) n" "canonical (FW M n) n" "[FW D n]⇘v,n⇙ = [D]⇘v,n⇙" "[FW M n]⇘v,n⇙ = [M]⇘v,n⇙"
by blast+
with valid equiv show ?thesis
apply -
apply (subst beta_interp.apx_norm_eq[symmetric])
prefer 4
apply (subst beta_interp.apx_norm_eq[symmetric])
by (simp add: FW_int_preservation)+
next
case True
show ?thesis
apply (subst norm_FW_empty)
prefer 3
apply (subst norm_FW_empty)
using valid equiv True by blast+
qed
end
context Regions
begin
sublocale Regions_common by standard (rule finite clock_numbering not_in_X non_empty)+
definition "v' ≡ λ i. if 0 < i ∧ i ≤ n then (THE c. c ∈ X ∧ v c = i) else not_in_X"
abbreviation step_z_norm' (‹_ ⊢ ⟨_, _⟩ ↝⇘𝒩(_)⇙ ⟨_, _⟩› [61,61,61,61] 61)
where
"A ⊢ ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l', D'⟩ ≡ A ⊢ ⟨l, D⟩ ↝⇘(λ l. k l o v'),v,n,a⇙ ⟨l', D'⟩"
definition step_z_norm'' (‹_ ⊢'' ⟨_, _⟩ ↝⇘𝒩(_)⇙ ⟨_, _⟩› [61,61,61,61] 61)
where
"A ⊢' ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l'', D''⟩ ≡
∃ l' D'. A ⊢ ⟨l, D⟩ ↝⇘v,n,τ⇙ ⟨l', D'⟩ ∧ A ⊢ ⟨l', D'⟩ ↝⇘𝒩(↿a)⇙ ⟨l'', D''⟩"
abbreviation steps_z_norm' (‹_ ⊢ ⟨_, _⟩ ↝⇩𝒩* ⟨_, _⟩› [61,61,61] 61)
where
"A ⊢ ⟨l, D⟩ ↝⇩𝒩* ⟨l', D'⟩ ≡ (λ (l,D) (l',D'). ∃ a. A ⊢' ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l', D'⟩)⇧*⇧* (l,D) (l',D')"
inductive_cases step_z_norm'_elims[elim!]: "A ⊢ ⟨l, u⟩ ↝⇘𝒩(a)⇙ ⟨l',u'⟩"
declare step_z_norm.intros[intro]
lemma step_z_valid_dbm:
assumes "A ⊢ ⟨l, D⟩ ↝⇘v,n,a⇙ ⟨l', D'⟩"
and "global_clock_numbering A v n" "valid_abstraction A X k" "valid_dbm D"
shows "valid_dbm D'"
proof -
from step_z_V step_z_dbm_sound[OF assms(1,2)] step_z_dbm_preserves_int[OF assms(1,2)]
assms(3,4)
have
"dbm_int D' n" "A ⊢ ⟨l, [D]⇘v,n⇙⟩ ↝⇘a⇙ ⟨l', [D']⇘v,n⇙⟩"
by (fastforce dest!: valid_abstraction_pairsD)+
with step_z_V[OF this(2)] assms(4) show ?thesis by auto
qed
lemma step_z_norm_induct[case_names _ step_z_norm step_z_refl]:
assumes "x1 ⊢ ⟨x2, x3⟩ ↝⇘(λ l. k l o v'),v,n,a⇙ ⟨x7,x8⟩"
and step_z_norm:
"⋀A l D l' D'.
A ⊢ ⟨l, D⟩ ↝⇘v,n,a⇙ ⟨l',D'⟩ ⟹
P A l D l' (norm (FW D' n) (k l' o v') n)"
shows "P x1 x2 x3 x7 x8"
using assms by (induction rule: step_z_norm.inducts) auto
context
fixes l' :: 's
begin
interpretation regions: Regions_global _ _ _ "k l'"
by standard (rule finite clock_numbering not_in_X non_empty)+
lemma regions_v'_eq[simp]:
"regions.v' = v'"
unfolding v'_def regions.beta_interp.v'_def by simp
lemma step_z_norm_int_all_preservation:
assumes
"A ⊢ ⟨l,D⟩ ↝⇘𝒩(a)⇙ ⟨l',D'⟩" "global_clock_numbering A v n"
"∀(x, m)∈Timed_Automata.clkp_set A. m ∈ ℕ" "dbm_int_all D"
shows "dbm_int_all D'"
using assms
apply cases
apply simp
apply (rule regions.norm_int_all_preservation[simplified])
apply (rule FW_int_all_preservation)
apply (erule step_z_dbm_preserves_int_all)
by fast+
lemma step_z_norm_valid_dbm_preservation:
assumes
"A ⊢ ⟨l,D⟩ ↝⇘𝒩(a)⇙ ⟨l',D'⟩" "global_clock_numbering A v n" "valid_abstraction A X k" "valid_dbm D"
shows "valid_dbm D'"
using assms
by cases (simp; rule regions.norm_FW_valid_preservation[simplified]; erule step_z_valid_dbm; fast)
lemma norm_beta_sound:
assumes "A ⊢ ⟨l,D⟩ ↝⇘𝒩(a)⇙ ⟨l',D'⟩" "global_clock_numbering A v n" "valid_abstraction A X k"
and "valid_dbm D"
shows "A ⊢ ⟨l,[D]⇘v,n⇙⟩ ↝⇘β(a)⇙ ⟨l',[D']⇘v,n⇙⟩" using assms(2-)
apply (induction A l D l' ≡ l' D' rule: step_z_norm_induct, (subst assms(1); blast))
proof goal_cases
case step_z_norm: (1 A l D D')
from step_z_dbm_sound[OF step_z_norm(1,2)] have "A ⊢ ⟨l, [D]⇘v,n⇙⟩ ↝⇘a⇙ ⟨l',[D']⇘v,n⇙⟩" by blast
then have *: "A ⊢ ⟨l, [D]⇘v,n⇙⟩ ↝⇘β(a)⇙ ⟨l',Approx⇩β l' ([D']⇘v,n⇙)⟩" by force
show ?case
proof (cases "[D']⇘v,n⇙ = {}")
case False
from regions.apx_norm_eq_spec[OF step_z_valid_dbm[OF step_z_norm] False] *
show ?thesis by auto
next
case True
with
regions.norm_FW_empty[OF step_z_valid_dbm[OF step_z_norm] this] regions.beta_interp.apx_empty *
show ?thesis by auto
qed
qed
lemma step_z_norm_valid_dbm:
assumes
"A ⊢ ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l',D'⟩" "global_clock_numbering A v n"
"valid_abstraction A X k" "valid_dbm D"
shows "valid_dbm D'" using assms(2-)
apply (induction A l D l' ≡ l' D' rule: step_z_norm_induct, (subst assms(1); blast))
proof goal_cases
case step_z_norm: (1 A l D D')
with regions.norm_FW_valid_preservation[OF step_z_valid_dbm[OF step_z_norm]] show ?case by auto
qed
lemma norm_beta_complete:
assumes "A ⊢ ⟨l,[D]⇘v,n⇙⟩ ↝⇘β(a)⇙ ⟨l',Z⟩" "global_clock_numbering A v n" "valid_abstraction A X k"
and "valid_dbm D"
obtains D' where "A ⊢ ⟨l,D⟩ ↝⇘𝒩(a)⇙ ⟨l',D'⟩" "[D']⇘v,n⇙ = Z" "valid_dbm D'"
proof -
from assms(3) have ta_int: "∀(x, m)∈Timed_Automata.clkp_set A. m ∈ ℕ"
by (fastforce dest!: valid_abstraction_pairsD)
from assms(1) obtain Z' where Z': "A ⊢ ⟨l,[D]⇘v,n⇙⟩ ↝⇘a⇙ ⟨l',Z'⟩" "Z = Approx⇩β l' Z'" by auto
from assms(4) have "dbm_int D n" by auto
with step_z_dbm_DBM[OF Z'(1) assms(2)] step_z_dbm_preserves_int[OF _ assms(2) ta_int] obtain D'
where D': "A ⊢ ⟨l, D⟩ ↝⇘v,n,a⇙ ⟨l',D'⟩" "Z' = [D']⇘v,n⇙" "dbm_int D' n"
by auto
note valid_D' = step_z_valid_dbm[OF D'(1) assms(2,3)]
obtain D'' where D'': "D'' = norm (FW D' n) (k l' ∘ v') n" by auto
show ?thesis
proof (cases "Z' = {}")
case False
with D' have *: "[D']⇘v,n⇙ ≠ {}" by auto
from regions.apx_norm_eq_spec[OF valid_D' this] D'' D'(2) Z'(2) assms(4) have "Z = [D'']⇘v,n⇙"
by auto
with regions.norm_FW_valid_preservation[OF valid_D'] D' D'' * assms(4)
show thesis
apply -
apply (rule that[of D''])
by (drule step_z_norm.intros[where k = "λ l. k l o v'"]) simp+
next
case True
with regions.norm_FW_empty[OF valid_D'[OF assms(4)]] D'' D' Z'(2)
regions.norm_FW_valid_preservation[OF valid_D'[OF assms(4)]] regions.beta_interp.apx_empty
show thesis
apply -
apply (rule that[of D''])
apply blast
by fastforce+
qed
qed
lemma step_z_norm_mono:
assumes "A ⊢ ⟨l,D⟩ ↝⇘𝒩(a)⇙ ⟨l',D'⟩" "global_clock_numbering A v n" "valid_abstraction A X k"
and "valid_dbm D" "valid_dbm M"
and "[D]⇘v,n⇙ ⊆ [M]⇘v,n⇙"
shows "∃ M'. A ⊢ ⟨l, M⟩ ↝⇘𝒩(a)⇙ ⟨l', M'⟩ ∧ [D']⇘v,n⇙ ⊆ [M']⇘v,n⇙"
proof -
from norm_beta_sound[OF assms(1,2,3,4)] have "A ⊢ ⟨l, [D]⇘v,n⇙⟩ ↝⇘β(a)⇙ ⟨l', [D']⇘v,n⇙⟩" .
from step_z_beta_mono[OF this assms(6)] assms(5) obtain Z where
"A ⊢ ⟨l, [M]⇘v,n⇙⟩ ↝⇘β(a)⇙ ⟨l', Z⟩" "[D']⇘v,n⇙ ⊆ Z"
by auto
with norm_beta_complete[OF this(1) assms(2,3,5)] show ?thesis by metis
qed
lemma step_z_norm_equiv:
assumes step: "A ⊢ ⟨l,D⟩ ↝⇘𝒩(a)⇙ ⟨l',D'⟩"
and prems: "global_clock_numbering A v n" "valid_abstraction A X k"
and valid: "valid_dbm D" "valid_dbm M"
and equiv: "[D]⇘v,n⇙ = [M]⇘v,n⇙"
shows "∃ M'. A ⊢ ⟨l, M⟩ ↝⇘𝒩(a)⇙ ⟨l', M'⟩ ∧ [D']⇘v,n⇙ = [M']⇘v,n⇙"
using step
apply cases
apply (frule step_z_dbm_equiv[OF prems(1)])
apply (rule equiv)
apply clarify
apply (drule regions.norm_FW_equiv[rotated 3])
prefer 4
apply force
using step_z_valid_dbm[OF _ prems] valid by (simp add: valid_dbm.simps)+
end
subsection ‹Multi Step›
lemma valid_dbm_V':
assumes "valid_dbm M"
shows "[M]⇘v,n⇙ ∈ V'"
using assms unfolding V'_def by force
lemma step_z_empty:
assumes "A ⊢ ⟨l, Z⟩ ↝⇘a⇙ ⟨l', Z'⟩" "Z = {}"
shows "Z' = {}"
using assms
apply cases
unfolding zone_delay_def zone_set_def
by auto
subsection ‹Connecting with Correctness Results for Approximating Semantics›
context
fixes A :: "('a, 'c, real, 's) ta"
assumes gcn: "global_clock_numbering A v n"
and va: "valid_abstraction A X k"
begin
context
notes [intro] = step_z_valid_dbm[OF _ gcn va]
begin
lemma valid_dbm_step_z_norm'':
"valid_dbm D'" if "A ⊢' ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l', D'⟩" "valid_dbm D"
using that unfolding step_z_norm''_def by (auto intro: step_z_norm_valid_dbm[OF _ gcn va])
lemma steps_z_norm'_valid_dbm_invariant:
"valid_dbm D'" if "A ⊢ ⟨l, D⟩ ↝⇩𝒩* ⟨l', D'⟩" "valid_dbm D"
using that by (induction rule: rtranclp_induct2) (auto intro: valid_dbm_step_z_norm'')
lemma norm_beta_sound'':
assumes "A ⊢' ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l'', D''⟩"
and "valid_dbm D"
shows "A ⊢ ⟨l, [D]⇘v,n⇙⟩ ↝⇩β ⟨l'', [D'']⇘v,n⇙⟩"
proof -
from assms(1) obtain l' D' where
"A ⊢ ⟨l, D⟩ ↝⇘v,n,τ⇙ ⟨l', D'⟩" "A ⊢ ⟨l', D'⟩ ↝⇘𝒩(↿a)⇙ ⟨l'', D''⟩"
by (auto simp: step_z_norm''_def)
moreover with ‹valid_dbm D› have "valid_dbm D'"
by auto
ultimately have "A ⊢ ⟨l', [D']⇘v,n⇙⟩ ↝⇘β↿a⇙ ⟨l'', [D'']⇘v,n⇙⟩"
by - (rule norm_beta_sound[OF _ gcn va])
with step_z_dbm_sound[OF ‹A ⊢ ⟨l, D⟩ ↝⇘v,n,τ⇙ ⟨l', D'⟩› gcn] show ?thesis
unfolding step_z_beta'_def by - (frule step_z.cases[where P = "l' = l"]; force)
qed
lemma norm_beta_complete1:
assumes "A ⊢ ⟨l,[D]⇘v,n⇙⟩ ↝⇩β ⟨l'',Z''⟩"
and "valid_dbm D"
obtains a D'' where "A ⊢' ⟨l,D⟩ ↝⇘𝒩(a)⇙ ⟨l'',D''⟩" "[D'']⇘v,n⇙ = Z''" "valid_dbm D''"
proof -
from assms(1) obtain a l' Z' where steps:
"A ⊢ ⟨l, [D]⇘v,n⇙⟩ ↝⇘τ⇙ ⟨l', Z'⟩" "A ⊢ ⟨l', Z'⟩ ↝⇘β(↿a)⇙ ⟨l'', Z''⟩"
by (auto simp: step_z_beta'_def)
from step_z_dbm_DBM[OF this(1) gcn] obtain D' where D':
"A ⊢ ⟨l, D⟩ ↝⇘v,n,τ⇙ ⟨l', D'⟩" "Z' = [D']⇘v,n⇙"
by auto
with ‹valid_dbm D› have "valid_dbm D'"
by auto
from steps D' show ?thesis
by (auto
intro!: that[unfolded step_z_norm''_def]
elim!: norm_beta_complete[OF _ gcn va ‹valid_dbm D'›]
)
qed
lemma bisim:
"Bisimulation_Invariant
(λ (l, Z) (l', Z'). A ⊢ ⟨l, Z⟩ ↝⇩β ⟨l', Z'⟩ ∧ Z' ≠ {})
(λ (l, D) (l', D'). ∃ a. A ⊢' ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l', D'⟩ ∧ [D']⇘v,n⇙ ≠ {})
(λ (l, Z) (l', D). l = l' ∧ Z = [D]⇘v,n⇙)
(λ _. True) (λ (l, D). valid_dbm D)"
proof (standard, goal_cases)
case (1 a b a')
then show ?case
by (blast elim: norm_beta_complete1)
next
case (2 a a' b')
then show ?case
by (blast intro: norm_beta_sound'')
next
case (3 a b)
then show ?case
by simp
next
case (4 a b)
then show ?case
unfolding step_z_norm''_def
by (auto intro: step_z_norm_valid_dbm[OF _ gcn va])
qed
end
interpretation Bisimulation_Invariant
"λ (l, Z) (l', Z'). A ⊢ ⟨l, Z⟩ ↝⇩β ⟨l', Z'⟩ ∧ Z' ≠ {}"
"λ (l, D) (l', D'). ∃ a. A ⊢' ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l', D'⟩ ∧ [D']⇘v,n⇙ ≠ {}"
"λ (l, Z) (l', D). l = l' ∧ Z = [D]⇘v,n⇙"
"λ _. True" "λ (l, D). valid_dbm D"
by (rule bisim)
lemma step_z_norm''_non_empty:
"[D]⇘v,n⇙ ≠ {}" if "A ⊢' ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l', D'⟩" "[D']⇘v,n⇙ ≠ {}" "valid_dbm D"
proof -
from that B_A_step[of "(l, D)" "(l', D')" "(l, [D]⇘v,n⇙)"] have
"A ⊢ ⟨l, [D]⇘v,n⇙⟩ ↝⇩β ⟨l', [D']⇘v,n⇙⟩"
by auto
with ‹_ ≠ {}› show ?thesis
by (auto 4 3 dest: step_z_beta'_empty)
qed
lemma norm_steps_empty:
"A ⊢ ⟨l, D⟩ ↝⇩𝒩* ⟨l', D'⟩ ∧ [D']⇘v,n⇙ ≠ {} ⟷ B.reaches (l, D) (l', D') ∧ [D]⇘v,n⇙ ≠ {}"
if "valid_dbm D"
apply (subst rtranclp_backwards_invariant_iff[
of "λ(l, D) (l', D'). ∃ a. A ⊢' ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l', D'⟩" "(l, D)" "λ(l, D). [D]⇘v,n⇙ ≠ {}",
simplified
])
using ‹valid_dbm D›
by (auto dest!: step_z_norm''_non_empty intro: steps_z_norm'_valid_dbm_invariant)
context
fixes P Q :: "'s ⇒ bool"
begin
interpretation bisim_ψ: Bisimulation_Invariant
"λ (l, Z) (l', Z'). A ⊢ ⟨l, Z⟩ ↝⇩β ⟨l', Z'⟩ ∧ Z' ≠ {} ∧ Q l'"
"λ (l, D) (l', D'). ∃ a. A ⊢' ⟨l, D⟩ ↝⇘𝒩(a)⇙ ⟨l', D'⟩ ∧ [D']⇘v,n⇙ ≠ {} ∧ Q l'"
"λ (l, Z) (l', D). l = l' ∧ Z = [D]⇘v,n⇙"
"λ _. True" "λ (l, D). valid_dbm D"
by (rule Bisimulation_Invariant_filter[OF bisim, of "λ (l, _). Q l" "λ (l, _). Q l"]) auto
end
context
assumes finite_state_set: "finite (state_set A)"
begin
interpretation R: Regions_TA
by (standard; rule va finite_state_set)
lemma A_reaches_non_empty:
"Z' ≠ {}" if "A.reaches (l, Z) (l', Z')" "Z ≠ {}"
using that by cases auto
lemma A_reaches_start_non_empty_iff:
"(∃Z'. (∃u. u ∈ Z') ∧ A.reaches (l, Z) (l', Z')) ⟷ (∃Z'. A.reaches (l, Z) (l', Z')) ∧ Z ≠ {}"
apply safe
apply blast
subgoal
by (auto dest: step_z_beta'_empty elim: converse_rtranclpE2)
by (auto dest: A_reaches_non_empty)
lemma step_z_norm''_state_set1:
"l ∈ state_set A" if "A ⊢' ⟨l, D⟩ ↝⇘𝒩a⇙ ⟨l', D'⟩"
using that unfolding step_z_norm''_def
by (auto dest: step_z_dbm_delay_loc intro: step_z_dbm_action_state_set1)
lemma step_z_norm''_state_set2:
"l' ∈ state_set A" if "A ⊢' ⟨l, D⟩ ↝⇘𝒩a⇙ ⟨l', D'⟩"
using that unfolding step_z_norm''_def by (auto intro: step_z_dbm_action_state_set2)
theorem steps_z_norm_decides_emptiness:
assumes "valid_dbm D"
shows "(∃ D'. A ⊢ ⟨l, D⟩ ↝⇩𝒩* ⟨l',D'⟩ ∧ [D']⇘v,n⇙ ≠ {})
⟷ (∃ u ∈ [D]⇘v,n⇙. (∃ u'. A ⊢' ⟨l, u⟩ →* ⟨l', u'⟩))"
proof (cases "[D]⇘v,n⇙ = {}")
case True
then show ?thesis
unfolding norm_steps_empty[OF ‹valid_dbm D›] by auto
next
case F: False
show ?thesis
proof (cases "l ∈ state_set A")
case True
interpret Regions_TA_Start_State v n not_in_X X k A l "[D]⇘v,n⇙"
using assms F True by - (standard, auto elim!: valid_dbm_V')
show ?thesis
unfolding steps'_iff[symmetric] norm_steps_empty[OF ‹valid_dbm D›]
using
reaches_ex_iff[of "λ (l, _). l = l'" "λ (l, _). l = l'" "(l, [D]⇘v,n⇙)" "(l, D)"]
‹valid_dbm D› ta_reaches_ex_iff[of "λ (l, _). l = l'"]
by (auto simp: A_reaches_start_non_empty_iff from_R_def a⇩0_def)
next
case False
have "A ⊢ ⟨l, D⟩ ↝⇩𝒩* ⟨l',D'⟩ ⟷ (D' = D ∧ l' = l)" for D'
using False by (blast dest: step_z_norm''_state_set1 elim: converse_rtranclpE2)
moreover have "A ⊢' ⟨l, u⟩ →* ⟨l', u'⟩ ⟷ (u' = u ∧ l' = l)" for u u'
unfolding steps'_iff[symmetric] using False
by (blast dest: step'_state_set1 elim: converse_rtranclpE2)
ultimately show ?thesis
using F by auto
qed
qed
end
end
context
fixes A :: "('a, 'c, real, 's) ta"
assumes gcn: "global_clock_numbering A v n"
and va: "valid_abstraction A X k"
begin
lemmas
step_z_norm_valid_dbm' = step_z_norm_valid_dbm[OF _ gcn va]
lemmas
step_z_valid_dbm' = step_z_valid_dbm[OF _ gcn va]
lemmas norm_beta_sound' = norm_beta_sound[OF _ gcn va]
lemma v_bound:
"∀ c ∈ clk_set A. v c ≤ n"
using gcn by blast
lemmas alpha_beta_step'' = alpha_beta_step'[OF _ va v_bound]
lemmas step_z_dbm_sound' = step_z_dbm_sound[OF _ gcn]
lemmas step_z_V'' = step_z_V'[OF _ va v_bound]
end
end
section ‹Additional Useful Properties of the Normalized Semantics›
text ‹Obsolete›
lemma norm_diag_alt_def:
"norm_diag e = (if e < 0 then Lt 0 else if e = 0 then e else ∞)"
unfolding norm_diag_def DBM.neutral DBM.less ..
lemma norm_diag_preservation:
assumes "∀l≤n. M1 l l ≤ 0"
shows "∀l≤n. (norm M1 (k :: nat ⇒ nat) n) l l ≤ 0"
using assms unfolding norm_def norm_diag_alt_def by (auto simp: DBM.neutral)
section ‹Appendix: Standard Clock Numberings for Concrete Models›
locale Regions' =
fixes X and k :: "'c ⇒ nat" and v :: "'c ⇒ nat" and n :: nat and not_in_X
assumes finite: "finite X"
assumes clock_numbering': "∀ c ∈ X. v c > 0" "∀ c. c ∉ X ⟶ v c > n"
assumes bij: "bij_betw v X {1..n}"
assumes non_empty: "X ≠ {}"
assumes not_in_X: "not_in_X ∉ X"
begin
lemma inj: "inj_on v X" using bij_betw_imp_inj_on bij by simp
lemma cn_weak: "∀ c. v c > 0" using clock_numbering' by force
lemma in_X: assumes "v x ≤ n" shows "x ∈ X" using assms clock_numbering'(2) by force
end
sublocale Regions' ⊆ Regions_global
proof (unfold_locales, auto simp: finite clock_numbering' non_empty cn_weak not_in_X, goal_cases)
case (1 x y) with inj in_X show ?case unfolding inj_on_def by auto
next
case (2 k)
from bij have "v ` X = {1..n}" unfolding bij_betw_def by auto
from 2 have "k ∈ {1..n}" by simp
then obtain x where "x ∈ X" "v x = k" unfolding image_def
by (metis (no_types, lifting) ‹v ` X = {1..n}› imageE)
then show ?case by blast
next
case (3 x) with bij show ?case unfolding bij_betw_def by auto
qed
lemma standard_abstraction:
assumes
"finite (Timed_Automata.clkp_set A)" "finite (Timed_Automata.collect_clkvt (trans_of A))"
"∀(_,m::real) ∈ Timed_Automata.clkp_set A. m ∈ ℕ"
obtains k :: "'c ⇒ nat" where "Timed_Automata.valid_abstraction A (clk_set A) k"
proof -
from assms have 1: "finite (clk_set A)" by auto
have 2: "Timed_Automata.collect_clkvt (trans_of A) ⊆ clk_set A" by auto
from assms obtain L where L: "distinct L" "set L = Timed_Automata.clkp_set A"
by (meson finite_distinct_list)
let ?M = "λ c. {m . (c, m) ∈ Timed_Automata.clkp_set A}"
let ?X = "clk_set A"
let ?m = "map_of L"
let ?k = "λ x. if ?M x = {} then 0 else nat (floor (Max (?M x)) + 1)"
{ fix c m assume A: "(c, m) ∈ Timed_Automata.clkp_set A"
from assms(1) have "finite (snd ` Timed_Automata.clkp_set A)" by auto
moreover have "?M c ⊆ (snd ` Timed_Automata.clkp_set A)" by force
ultimately have fin: "finite (?M c)" by (blast intro: finite_subset)
then have "Max (?M c) ∈ {m . (c, m) ∈ Timed_Automata.clkp_set A}" using Max_in A by auto
with assms(3) have "Max (?M c) ∈ ℕ" by auto
then have "floor (Max (?M c)) = Max (?M c)" by (metis Nats_cases floor_of_nat of_int_of_nat_eq)
have *: "?k c = Max (?M c) + 1"
proof -
have "real (nat (n + 1)) = real_of_int n + 1"
if "Max {m. (c, m) ∈ Timed_Automata.clkp_set A} = real_of_int n"
for n :: int and x :: real
proof -
from that have "real_of_int (n + 1) ∈ ℕ"
using ‹Max {m. (c, m) ∈ Timed_Automata.clkp_set A} ∈ ℕ› by auto
then show ?thesis
by (metis Nats_cases ceiling_of_int nat_int of_int_1 of_int_add of_int_of_nat_eq)
qed
with A ‹floor (Max (?M c)) = Max (?M c)› show ?thesis
by auto
qed
from fin A have "Max (?M c) ≥ m" by auto
moreover from A assms(3) have "m ∈ ℕ" by auto
ultimately have "m ≤ ?k c" "m ∈ ℕ" "c ∈ clk_set A" using A * by force+
}
then have "∀(x, m) ∈ Timed_Automata.clkp_set A. m ≤ ?k x ∧ x ∈ clk_set A ∧ m ∈ ℕ" by blast
with 1 2 have "Timed_Automata.valid_abstraction A ?X ?k" by - (standard, assumption+)
then show thesis ..
qed
definition
"finite_ta A ≡
finite (Timed_Automata.clkp_set A) ∧ finite (Timed_Automata.collect_clkvt (trans_of A))
∧ (∀(_,m) ∈ Timed_Automata.clkp_set A. m ∈ ℕ) ∧ clk_set A ≠ {} ∧ -clk_set A ≠ {}"
lemma finite_ta_Regions':
fixes A :: "('a, 'c, real, 's) ta"
assumes "finite_ta A"
obtains v n x where "Regions' (clk_set A) v n x"
proof -
from assms obtain x where x: "x ∉ clk_set A" unfolding finite_ta_def by auto
from assms(1) have "finite (clk_set A)" unfolding finite_ta_def by auto
with standard_numbering[of "clk_set A"] assms obtain v and n :: nat where
"bij_betw v (clk_set A) {1..n}"
"∀c∈clk_set A. 0 < v c" "∀c. c ∉ clk_set A ⟶ n < v c"
by auto
then have "Regions' (clk_set A) v n x" using x assms unfolding finite_ta_def by - (standard, auto)
then show ?thesis ..
qed
lemma finite_ta_RegionsD:
fixes A :: "('a, 'c, t, 's) ta"
assumes "finite_ta A"
obtains k :: "'c ⇒ nat" and v n x where
"Regions' (clk_set A) v n x" "Timed_Automata.valid_abstraction A (clk_set A) k"
"global_clock_numbering A v n"
proof -
from standard_abstraction assms obtain k :: "'c ⇒ nat" where k:
"Timed_Automata.valid_abstraction A (clk_set A) k"
unfolding finite_ta_def by blast
from finite_ta_Regions'[OF assms] obtain v n x where *: "Regions' (clk_set A) v n x" .
then interpret interp: Regions' "clk_set A" k v n x .
from interp.clock_numbering have "global_clock_numbering A v n" by blast
with * k show ?thesis ..
qed
definition valid_dbm where "valid_dbm M n ≡ dbm_int M n ∧ (∀ i ≤ n. M 0 i ≤ 0)"
lemma dbm_positive:
assumes "M 0 (v c) ≤ 0" "v c ≤ n" "DBM_val_bounded v u M n"
shows "u c ≥ 0"
proof -
from assms have "dbm_entry_val u None (Some c) (M 0 (v c))" unfolding DBM_val_bounded_def by auto
with assms(1) show ?thesis
proof (cases "M 0 (v c)", goal_cases)
case 1
then show ?case unfolding less_eq neutral using order_trans by (fastforce dest!: le_dbm_le)
next
case 2
then show ?case unfolding less_eq neutral
by (auto dest!: lt_dbm_le) (meson less_trans neg_0_less_iff_less not_less)
next
case 3
then show ?case unfolding neutral less_eq dbm_le_def by auto
qed
qed
lemma valid_dbm_pos:
assumes "valid_dbm M n"
shows "[M]⇘v,n⇙ ⊆ {u. ∀ c. v c ≤ n ⟶ u c ≥ 0}"
using dbm_positive assms unfolding valid_dbm_def unfolding DBM_zone_repr_def by fast
lemma (in Regions') V_alt_def:
shows "{u. ∀ c. v c > 0 ∧ v c ≤ n ⟶ u c ≥ 0} = V"
unfolding V_def using clock_numbering by metis
end