Theory Store_Reuse_Subsumption
subsection‹Store and Reuse Subsumption›
text‹This theory provides proofs of various properties of the \emph{store and reuse} heuristic,
including the preconditions necessary for the transitions it introduces to directly subsume their
ungeneralised counterparts.›
theory Store_Reuse_Subsumption
imports Store_Reuse
begin
lemma generalisation_of_preserves:
"is_generalisation_of t' t i r ⟹
Label t = Label t' ∧
Arity t = Arity t' ∧
(Outputs t) = (Outputs t')"
apply (simp add: is_generalisation_of_def)
using remove_guard_add_update_preserves by auto
lemma is_generalisation_of_guard_subset:
"is_generalisation_of t' t i r ⟹ set (Guards t') ⊆ set (Guards t)"
by (simp add: is_generalisation_of_def remove_guard_add_update_def)
lemma is_generalisation_of_medial:
"is_generalisation_of t' t i r ⟹
can_take_transition t ip rg ⟶ can_take_transition t' ip rg"
using is_generalisation_of_guard_subset can_take_subset generalisation_of_preserves
by (metis (no_types, lifting) can_take_def can_take_transition_def)
lemma is_generalisation_of_preserves_reg:
"is_generalisation_of t' t i r ⟹
evaluate_updates t ia c $ r = c $ r"
by (simp add: is_generalisation_of_def r_not_updated_stays_the_same)
lemma apply_updates_foldr:
"apply_updates u old = foldr (λh r. r(fst h $:= aval (snd h) old)) (rev u)"
by (simp add: apply_updates_def foldr_conv_fold)
lemma is_generalisation_of_preserves_reg_2:
assumes gen: "is_generalisation_of t' t i r"
and dif: "ra ≠ r"
shows "evaluate_updates t ia c $ ra = apply_updates (Updates t') (join_ir ia c) c $ ra"
using assms
apply (simp add: apply_updates_def is_generalisation_of_def remove_guard_add_update_def del: fold.simps)
by (simp add: apply_updates_def[symmetric] apply_updates_cons)
lemma is_generalisation_of_apply_guards:
"is_generalisation_of t' t i r ⟹
apply_guards (Guards t) j ⟹
apply_guards (Guards t') j"
using is_generalisation_of_guard_subset apply_guards_subset by blast
text ‹If we drop the guard and add an update, and the updated register is undefined in the context,
c, then the generalised transition subsumes the specific one.›
lemma is_generalisation_of_subsumes_original:
"is_generalisation_of t' t i r ⟹
c $ r = None ⟹
subsumes t' c t"
apply (simp add: subsumes_def generalisation_of_preserves can_take_transition_def can_take_def posterior_separate_def)
by (metis is_generalisation_of_apply_guards is_generalisation_of_preserves_reg is_generalisation_of_preserves_reg_2)
lemma generalise_output_posterior:
"posterior (generalise_output t p r) i ra = posterior t i ra"
by (simp add: can_take_def generalise_output_preserves posterior_def)
lemma generalise_output_eq: "(Outputs t) ! r = L v ⟹
c $ p = Some v ⟹
evaluate_outputs t i c = apply_outputs (list_update (Outputs t) r (V (R p))) (join_ir i c)"
apply (rule nth_equalityI)
apply (simp add: apply_outputs_preserves_length)
subgoal for j apply (case_tac "j = r")
apply (simp add: apply_outputs_literal apply_outputs_preserves_length apply_outputs_register)
by (simp add: apply_outputs_preserves_length apply_outputs_unupdated)
done
text‹This shows that if we can guarantee that the value of a particular register is the literal
output then the generalised output subsumes the specific output.›
lemma generalise_output_subsumes_original:
"Outputs t ! r = L v ⟹
c $ p = Some v ⟹
subsumes (generalise_output t p r) c t"
by (simp add: can_take_transition_def generalise_output_def generalise_output_eq subsumes_def)
primrec stored_reused_aux_per_reg :: "transition ⇒ transition ⇒ nat ⇒ nat ⇒ (nat × nat) option" where
"stored_reused_aux_per_reg t' t 0 p = (
if is_generalised_output_of t' t 0 p then
Some (0, p)
else
None
)" |
"stored_reused_aux_per_reg t' t (Suc r) p = (
if is_generalised_output_of t' t (Suc r) p then
Some (Suc r, p)
else
stored_reused_aux_per_reg t' t r p
)"
primrec stored_reused_aux :: "transition ⇒ transition ⇒ nat ⇒ nat ⇒ (nat × nat) option" where
"stored_reused_aux t' t r 0 = stored_reused_aux_per_reg t' t r 0" |
"stored_reused_aux t' t r (Suc p) = (case stored_reused_aux_per_reg t' t r (Suc p) of
Some x ⇒ Some x |
None ⇒ stored_reused_aux t' t r p
)"
definition stored_reused :: "transition ⇒ transition ⇒ (nat × nat) option" where
"stored_reused t' t = stored_reused_aux t' t (max (Transition.total_max_reg t) (Transition.total_max_reg t')) (max (length (Outputs t)) (length (Outputs t')))"
lemma stored_reused_aux_is_generalised_output_of:
"stored_reused_aux t' t mr mp = Some (p, r) ⟹
is_generalised_output_of t' t p r"
proof(induct mr)
case 0
then show ?case
proof(induct mp)
case 0
then show ?case
apply simp
by (metis option.distinct(1) option.inject prod.inject)
next
case (Suc mp)
then show ?case
apply (case_tac "is_generalised_output_of t' t 0 (Suc mp)")
by auto
qed
next
case (Suc mr)
then show ?case
proof(induct mp)
case 0
then show ?case
apply simp
by (metis option.inject prod.inject)
next
case (Suc mp)
then show ?case
apply simp
apply (case_tac "stored_reused_aux_per_reg t' t mr (Suc mp)")
apply simp
apply (case_tac "is_generalised_output_of t' t (Suc mr) (Suc mp)")
apply simp
apply simp
apply simp
apply (case_tac "is_generalised_output_of t' t (Suc mr) (Suc mp)")
by auto
qed
qed
lemma stored_reused_is_generalised_output_of:
"stored_reused t' t = Some (p, r) ⟹
is_generalised_output_of t' t p r"
by (simp add: stored_reused_def stored_reused_aux_is_generalised_output_of)
lemma is_generalised_output_of_subsumes:
"is_generalised_output_of t' t r p ⟹
nth (Outputs t) p = L v ⟹
c $ r = Some v ⟹
subsumes t' c t"
apply (simp add: subsumes_def generalise_output_preserves can_take_transition_def can_take_def posterior_separate_def)
by (simp add: generalise_output_def generalise_output_eq is_generalised_output_of_def)
lemma lists_neq_if:
"∃i. l ! i ≠ l' ! i ⟹ l ≠ l'"
by auto
lemma is_generalised_output_of_does_not_subsume:
"is_generalised_output_of t' t r p ⟹
p < length (Outputs t) ⟹
nth (Outputs t) p = L v ⟹
c $ r ≠ Some v ⟹
∃i. can_take_transition t i c ⟹
¬subsumes t' c t"
apply (rule bad_outputs)
apply clarify
subgoal for i
apply (rule_tac x=i in exI)
apply simp
apply (rule lists_neq_if)
apply (rule_tac x=p in exI)
by (simp add: is_generalised_output_of_def generalise_output_def apply_outputs_nth join_ir_def)
done
text‹This shows that we can use the model checker to test whether the relevant register is the
correct value for direct subsumption.›
lemma generalise_output_directly_subsumes_original:
"stored_reused t' t = Some (r, p) ⟹
nth (Outputs t) p = L v ⟹
(∀c1 c2 t. obtains s c1 e1 0 <> t ∧ obtains s' c2 e2 0 <> t ⟶ c2 $ r = Some v) ⟹
directly_subsumes e1 e2 s s' t' t"
apply (simp add: directly_subsumes_def)
apply standard
by (metis is_generalised_output_of_subsumes stored_reused_aux_is_generalised_output_of stored_reused_def)
definition "generalise_output_context_check v r s1 s2 e1 e2 =
(∀c1 c2 t. obtains s1 c1 (tm e1) 0 <> t ∧ obtains s2 c2 (tm e2) 0 <> t ⟶ c2 $ r = Some v)"
lemma generalise_output_context_check_directly_subsumes_original:
"stored_reused t' t = Some (r, p) ⟹
nth (Outputs t) p = L v ⟹
generalise_output_context_check v r s s' e1 e2 ⟹
directly_subsumes (tm e1) (tm e2) s s' t' t "
by (simp add: generalise_output_context_check_def generalise_output_directly_subsumes_original)
definition generalise_output_direct_subsumption :: "transition ⇒ transition ⇒ iEFSM ⇒ iEFSM ⇒ nat ⇒ nat ⇒ bool" where
"generalise_output_direct_subsumption t' t e e' s s' = (case stored_reused t' t of
None ⇒ False |
Some (r, p) ⇒
(case nth (Outputs t) p of
L v ⇒ generalise_output_context_check v r s s' e e' |
_ ⇒ False)
)"
text‹This allows us to just run the two functions for quick subsumption.›
lemma generalise_output_directly_subsumes_original_executable:
"generalise_output_direct_subsumption t' t e e' s s' ⟹
directly_subsumes (tm e) (tm e') s s' t' t"
apply (simp add: generalise_output_direct_subsumption_def)
apply (case_tac "stored_reused t' t")
apply simp
apply simp
subgoal for a
apply (case_tac a)
apply simp
subgoal for _ b
apply (case_tac "Outputs t ! b")
apply (simp add: generalise_output_context_check_directly_subsumes_original)
by auto
done
done
lemma original_does_not_subsume_generalised_output:
"stored_reused t' t = Some (p, r) ⟹
r < length (Outputs t) ⟹
nth (Outputs t) r = L v ⟹
∃a c1 tt. obtains s c1 e1 0 <> tt ∧ obtains s' a e 0 <> tt ∧ a $ p ≠ Some v ∧ (∃i. can_take_transition t i a) ⟹
¬directly_subsumes e1 e s s' t' t"
apply (simp add: directly_subsumes_def)
apply clarify
subgoal for a c1 tt i
apply (rule_tac x=c1 in exI)
apply (rule_tac x=a in exI)
using stored_reused_is_generalised_output_of[of t' t p r]
is_generalised_output_of_does_not_subsume[of t' t p r v]
by auto
done
primrec input_i_stored_in_reg :: "transition ⇒ transition ⇒ nat ⇒ nat ⇒ (nat × nat) option" where
"input_i_stored_in_reg t' t i 0 = (if is_generalisation_of t' t i 0 then Some (i, 0) else None)" |
"input_i_stored_in_reg t' t i (Suc r) = (if is_generalisation_of t' t i (Suc r) then Some (i, (Suc r)) else input_i_stored_in_reg t' t i r)"
primrec input_stored_in_reg_aux :: "transition ⇒ transition ⇒ nat ⇒ nat ⇒ (nat × nat) option" where
"input_stored_in_reg_aux t' t 0 r = input_i_stored_in_reg t' t 0 r" |
"input_stored_in_reg_aux t' t (Suc i) r = (case input_i_stored_in_reg t' t (Suc i) r of
None ⇒ input_i_stored_in_reg t' t i r |
Some (i, r) ⇒ Some (i, r)
) "
definition input_stored_in_reg :: "transition ⇒ transition ⇒ iEFSM ⇒ (nat × nat) option" where
"input_stored_in_reg t' t e = (
case input_stored_in_reg_aux t' t (total_max_reg e) (max (Arity t) (Arity t')) of
None ⇒ None |
Some (i, r) ⇒
if length (filter (λ(r', u). r' = r) (Updates t')) = 1 then
Some (i, r)
else None
)"
definition initially_undefined_context_check :: "transition_matrix ⇒ nat ⇒ nat ⇒ bool" where
"initially_undefined_context_check e r s = (∀t a. obtains s a e 0 <> t ⟶ a $ r = None)"
lemma no_incoming_to_zero:
"∀((from, to), t)|∈|e. 0 < to ⟹
(aaa, ba) |∈| possible_steps e s d l i ⟹
aaa ≠ 0"
proof(induct e)
case empty
then show ?case
by (simp add: possible_steps_def)
next
case (insert x e)
then show ?case
apply (cases x)
subgoal for a b
apply (case_tac a)
apply (simp add: possible_steps_def ffilter_finsert)
subgoal for aa bb
apply (case_tac "aa = s ∧ Label b = l ∧ length i = Arity b ∧ apply_guards (Guards b) (join_ir i d)")
apply simp
apply blast
by simp
done
done
qed
lemma no_return_to_zero:
"∀((from, to), t)|∈|e. 0 < to ⟹
∀r n. ¬ visits 0 e (Suc n) r t"
proof(induct t)
case Nil
then show ?case
by (simp add: no_further_steps)
next
case (Cons a t)
then show ?case
apply clarify
apply (rule visits.cases)
apply simp
apply simp
defer
apply simp
apply clarify
apply simp
by (metis no_incoming_to_zero not0_implies_Suc)
qed
lemma no_accepting_return_to_zero:
"∀((from, to), t)|∈|e. to ≠ 0 ⟹
recognises (e) (a#t) ⟹
¬visits 0 (e) 0 <> (a#t)"
apply clarify
apply (rule visits.cases)
apply simp
apply simp
apply clarify
apply simp
by (metis no_incoming_to_zero no_return_to_zero old.nat.exhaust)
lemma no_return_to_zero_must_be_empty:
"∀((from, to), t)|∈|e. to ≠ 0 ⟹
obtains 0 a e s r t ⟹
t = []"
proof(induct t arbitrary: s r)
case Nil
then show ?case
by simp
next
case (Cons a t)
then show ?case
apply simp
apply (rule obtains.cases)
apply simp
apply simp
by (metis (no_types, lifting) case_prodE fBexE list.inject no_further_steps no_incoming_to_zero unobtainable_if)
qed
definition "no_illegal_updates t r = (∀u ∈ set (Updates t). fst u ≠ r)"
lemma input_stored_in_reg_aux_is_generalisation_aux:
"input_stored_in_reg_aux t' t mr mi = Some (i, r) ⟹
is_generalisation_of t' t i r"
proof(induct mi)
case 0
then show ?case
proof(induct mr)
case 0
then show ?case
apply (case_tac "is_generalisation_of t' t 0 0")
by auto
next
case (Suc mr)
then show ?case
apply simp
apply (case_tac "is_generalisation_of t' t (Suc mr) 0")
apply simp
apply simp
apply (case_tac "is_generalisation_of t' t mr 0")
by auto
qed
next
case (Suc mi)
then show ?case
proof(induct mr)
case 0
then show ?case
apply (case_tac "is_generalisation_of t' t 0 (Suc mi)")
by auto
next
case (Suc mr)
then show ?case
apply simp
apply (case_tac "is_generalisation_of t' t (Suc mr) (Suc mi)")
apply simp
apply simp
apply (case_tac "input_i_stored_in_reg t' t (Suc mr) mi")
apply simp
apply (case_tac "is_generalisation_of t' t mr (Suc mi)")
by auto
qed
qed
lemma input_stored_in_reg_is_generalisation:
"input_stored_in_reg t' t e = Some (i, r) ⟹ is_generalisation_of t' t i r"
apply (simp add: input_stored_in_reg_def)
apply (cases "input_stored_in_reg_aux t' t (total_max_reg e) (max (Arity t) (Arity t'))")
apply simp
subgoal for a
apply (case_tac a)
apply simp
subgoal for _ b
apply (case_tac "length (filter (λ(r', u). r' = b) (Updates t')) = 1")
apply (simp add: input_stored_in_reg_aux_is_generalisation_aux)
by simp
done
done
lemma generalised_directly_subsumes_original:
"input_stored_in_reg t' t e = Some (i, r) ⟹
initially_undefined_context_check (tm e) r s' ⟹
no_illegal_updates t r ⟹
directly_subsumes (tm e1) (tm e) s s' t' t"
apply (simp add: directly_subsumes_def)
apply standard
apply (meson finfun_const.rep_eq input_stored_in_reg_is_generalisation is_generalisation_of_subsumes_original)
apply (rule is_generalisation_of_subsumes_original)
using input_stored_in_reg_is_generalisation apply blast
by (simp add: initially_undefined_context_check_def)
definition drop_guard_add_update_direct_subsumption :: "transition ⇒ transition ⇒ iEFSM ⇒ nat ⇒ bool" where
"drop_guard_add_update_direct_subsumption t' t e s' = (
case input_stored_in_reg t' t e of
None ⇒ False |
Some (i, r) ⇒
if no_illegal_updates t r then
initially_undefined_context_check (tm e) r s'
else False
)"
lemma drop_guard_add_update_direct_subsumption_implies_direct_subsumption:
"drop_guard_add_update_direct_subsumption t' t e s' ⟹
directly_subsumes (tm e1) (tm e) s s' t' t"
apply (simp add: drop_guard_add_update_direct_subsumption_def)
apply (case_tac "input_stored_in_reg t' t e")
apply simp+
subgoal for a
apply (case_tac a)
apply simp
subgoal for _ b
apply (case_tac "no_illegal_updates t b")
apply (simp add: generalised_directly_subsumes_original)
by simp
done
done
lemma is_generalisation_of_constrains_input:
"is_generalisation_of t' t i r ⟹
∃v. gexp.Eq (V (vname.I i)) (L v) ∈ set (Guards t)"
by (simp add: is_generalisation_of_def)
lemma is_generalisation_of_derestricts_input:
"is_generalisation_of t' t i r ⟹
∀g ∈ set (Guards t'). ¬ gexp_constrains g (V (vname.I i))"
by (simp add: is_generalisation_of_def remove_guard_add_update_def)
lemma is_generalisation_of_same_arity:
"is_generalisation_of t' t i r ⟹ Arity t = Arity t'"
by (simp add: is_generalisation_of_def remove_guard_add_update_def)
lemma is_generalisation_of_i_lt_arity:
"is_generalisation_of t' t i r ⟹ i < Arity t"
by (simp add: is_generalisation_of_def)
lemma "∀i. ¬ can_take_transition t i r ∧ ¬ can_take_transition t' i r ⟹
Label t = Label t' ⟹
Arity t = Arity t' ⟹
subsumes t' r t"
by (simp add: subsumes_def posterior_separate_def can_take_transition_def)
lemma input_not_constrained_aval_swap_inputs:
"¬ aexp_constrains a (V (I v)) ⟹ aval a (join_ir i c) = aval a (join_ir (list_update i v x) c)"
apply(induct a rule: aexp_induct_separate_V_cases)
apply simp
apply (metis aexp_constrains.simps(2) aval.simps(2) input2state_nth input2state_out_of_bounds join_ir_def length_list_update not_le nth_list_update_neq vname.simps(5))
using join_ir_def by auto
lemma aval_unconstrained:
" ¬ aexp_constrains a (V (vname.I i)) ⟹
i < length ia ⟹
v = ia ! i ⟹
v' ≠ v ⟹
aval a (join_ir ia c) = aval a (join_ir (list_update ia i v') c)"
apply(induct a rule: aexp_induct_separate_V_cases)
using input_not_constrained_aval_swap_inputs by blast+
lemma input_not_constrained_gval_swap_inputs:
"¬ gexp_constrains a (V (I v)) ⟹
gval a (join_ir i c) = gval a (join_ir (i[v := x]) c)"
proof(induct a)
case (Bc x)
then show ?case
by (metis (full_types) gval.simps(1) gval.simps(2))
next
case (Eq x1a x2)
then show ?case
using input_not_constrained_aval_swap_inputs by auto
next
case (Gt x1a x2)
then show ?case
using input_not_constrained_aval_swap_inputs by auto
next
case (In x1a x2)
then show ?case
apply simp
apply (case_tac "join_ir i c x1a")
apply simp
apply (case_tac "join_ir (i[v := x]) c x1a")
apply simp
apply simp
apply (metis aexp.inject(2) aexp_constrains.simps(2) aval.simps(2) input_not_constrained_aval_swap_inputs option.discI)
apply (case_tac "join_ir i c x1a")
apply simp
apply (case_tac "join_ir (i[v := x]) c x1a")
apply simp
apply (metis aexp.inject(2) aexp_constrains.simps(2) aval.simps(2) input_not_constrained_aval_swap_inputs option.discI)
apply simp
by (metis (no_types, lifting) datastate(1) input2state_within_bounds join_ir_R join_ir_nth le_less_linear list_update_beyond nth_list_update option.inject vname.case(1) vname.exhaust)
qed auto
text‹If input $i$ is stored in register $r$ by transition $t$ then if we can take transition,
$t^\prime$ then for some input $ia$ then transition $t$ does not subsume $t^\prime$.›
lemma input_stored_in_reg_not_subsumed:
"input_stored_in_reg t' t e = Some (i, r) ⟹
∃ia. can_take_transition t' ia c ⟹
¬ subsumes t c t'"
using input_stored_in_reg_is_generalisation[of t' t e i r]
using is_generalisation_of_constrains_input[of t' t i r]
using is_generalisation_of_derestricts_input[of t' t i r]
apply simp
apply (rule bad_guards)
apply clarify
subgoal for ia v
apply (simp add: can_take_transition_def can_take_def)
apply clarify
apply (case_tac "v")
subgoal for x1
apply (rule_tac x="list_update ia i (Str _)" in exI)
apply simp
apply standard
apply (simp add: apply_guards_def)
apply (metis input_not_constrained_gval_swap_inputs)
apply (simp add: apply_guards_def Bex_def)
apply standard
apply (rule_tac x="Eq (V (vname.I i)) (L (Num x1))" in exI)
apply (simp add: join_ir_def input2state_nth is_generalisation_of_i_lt_arity str_not_num)
done
subgoal for x2
apply (rule_tac x="list_update ia i (Num _)" in exI)
apply simp
apply standard
apply (simp add: apply_guards_def)
apply (metis input_not_constrained_gval_swap_inputs)
apply (simp add: apply_guards_def Bex_def)
apply standard
apply (rule_tac x="Eq (V (vname.I i)) (L (value.Str x2))" in exI)
by (simp add: join_ir_def input2state_nth is_generalisation_of_i_lt_arity str_not_num)
done
done
lemma aval_updated:
"(r, u) ∈ set U ⟹
r ∉ set (map fst (removeAll (r, u) U)) ⟹
apply_updates U s c $ r = aval u s"
proof(induct U rule: rev_induct)
case (snoc a U)
then show ?case
apply (case_tac "(r, u) = a")
using apply_updates_foldr by auto
qed auto
lemma can_take_append_subset:
"set (Guards t') ⊂ set (Guards t) ⟹
can_take a (Guards t @ Guards t') ia c = can_take a (Guards t) ia c"
by (metis apply_guards_append apply_guards_subset_append can_take_def dual_order.strict_implies_order)
text‹Transitions of the form $t = \textit{select}:1[i_0=x]$ do not subsume transitions
of the form $t^\prime = select:1/r_1:=i_1$.›
lemma general_not_subsume_orig: "Arity t' = Arity t ⟹
set (Guards t') ⊂ set (Guards t) ⟹
(r, (V (I i))) ∈ set (Updates t') ⟹
r ∉ set (map fst (removeAll (r, V (I i)) (Updates t'))) ⟹
r ∉ set (map fst (Updates t)) ⟹
∃i. can_take_transition t i c ⟹
c $ r = None ⟹
i < Arity t ⟹
¬ subsumes t c t'"
apply (rule inconsistent_updates)
apply (erule_tac exE)
subgoal for ia
apply (rule_tac x="evaluate_updates t ia c" in exI)
apply (rule_tac x="apply_updates (Updates t') (join_ir ia c) c" in exI)
apply standard
apply (rule_tac x=ia in exI)
apply (metis can_take_def can_take_transition_def can_take_subset posterior_separate_def psubsetE)
apply (rule_tac x=r in exI)
apply (simp add: r_not_updated_stays_the_same)
apply (rule_tac x="λx. x = None" in exI)
by (simp add: aval_updated can_take_transition_def can_take_def)
done
lemma input_stored_in_reg_updates_reg:
"input_stored_in_reg t2 t1 a = Some (i, r) ⟹
(r, V (I i)) ∈ set (Updates t2)"
using input_stored_in_reg_is_generalisation[of t2 t1 a i r]
apply simp
by (simp add: is_generalisation_of_def remove_guard_add_update_def)
definition "diff_outputs_ctx e1 e2 s1 s2 t1 t2 =
(if Outputs t1 = Outputs t2 then False else
(∃p c1 r. obtains s1 c1 e1 0 <> p ∧
obtains s2 r e2 0 <> p ∧
(∃i. can_take_transition t1 i r ∧ can_take_transition t2 i r ∧
evaluate_outputs t1 i r ≠ evaluate_outputs t2 i r)
))"
lemma diff_outputs_direct_subsumption:
"diff_outputs_ctx e1 e2 s1 s2 t1 t2 ⟹
¬ directly_subsumes e1 e2 s1 s2 t1 t2"
apply (simp add: directly_subsumes_def diff_outputs_ctx_def)
apply (case_tac "Outputs t1 = Outputs t2")
apply simp
apply clarsimp
subgoal for _ c1 r
apply (rule_tac x=c1 in exI)
apply (rule_tac x=r in exI)
using bad_outputs by force
done
definition not_updated :: "nat ⇒ transition ⇒ bool" where
"not_updated r t = (filter (λ(r', _). r' = r) (Updates t) = [])"
lemma not_updated: assumes "not_updated r t2"
shows "apply_updates (Updates t2) s s' $ r = s' $ r"
proof-
have not_updated_aux: "⋀t2. filter (λ(r', _). r' = r) t2 = [] ⟹
apply_updates t2 s s' $ r = s' $ r"
apply (rule r_not_updated_stays_the_same)
by (metis (mono_tags, lifting) filter_empty_conv imageE prod.case_eq_if)
show ?thesis
using assms
by (simp add: not_updated_def not_updated_aux)
qed
lemma : "Label t1 = Label t2 ⟹
Arity t1 = Arity t2 ⟹
set (Guards t1) ⊆ set (Guards t2) ⟹
Outputs t1 = Outputs t2 ⟹
Updates t1 = (r, u) # Updates t2 ⟹
not_updated r t2 ⟹
c $ r = None ⟹
subsumes t1 c t2"
apply (simp add: subsumes_def posterior_separate_def can_take_transition_def can_take_def)
by (metis apply_guards_subset apply_updates_cons not_updated)
lemma :
"Label t1 = Label t2 ⟹
Arity t1 = Arity t2 ⟹
set (Guards t1) ⊆ set (Guards t2) ⟹
Outputs t1 = Outputs t2 ⟹
Updates t1 = (r, u)#(Updates t2) ⟹
not_updated r t2 ⟹
initially_undefined_context_check e2 r s2 ⟹
directly_subsumes e1 e2 s1 s2 t1 t2"
apply (simp add: directly_subsumes_def)
apply standard
apply (meson one_extra_update_subsumes finfun_const_apply)
apply (simp add: initially_undefined_context_check_def)
using obtainable_def one_extra_update_subsumes by auto
" t1 t2 s2 e2 = (
Label t1 = Label t2 ∧
Arity t1 = Arity t2 ∧
set (Guards t1) ⊆ set (Guards t2) ∧
Outputs t1 = Outputs t2 ∧
Updates t1 ≠ [] ∧
tl (Updates t1) = (Updates t2) ∧
(∃r ∈ set (map fst (Updates t1)). fst (hd (Updates t1)) = r ∧
not_updated r t2 ∧
initially_undefined_context_check e2 r s2)
)"
lemma must_be_an_update:
"U1 ≠ [] ⟹
fst (hd U1) = r ∧ tl U1 = U2 ⟹
∃u. U1 = (r, u)#(U2)"
by (metis eq_fst_iff hd_Cons_tl)
lemma :
"one_extra_update t1 t2 s2 e2 ⟹ directly_subsumes e1 e2 s1 s2 t1 t2"
apply (insert must_be_an_update[of "Updates t1" r "Updates t2"])
apply (simp add: one_extra_update_def)
by (metis eq_fst_iff hd_Cons_tl one_extra_update_directly_subsumes)
end