Theory Rely_Quotient
section ‹Rely Quotient Operator \label{S:rely-quotient}›
text ‹
The rely quotient operator is used to generalise a Jones-style rely condition
to a process \<^cite>‹"jon83a"›.
It is defined in terms of the parallel operator and a process $i$
representing interference from the environment.
›
theory Rely_Quotient
imports
CRA
Conjunctive_Iteration
begin
subsection ‹Basic rely quotient›
text ‹
The rely quotient of a process $c$ and an interference process $i$
is the most general process $d$ such that $c$ is refined by $d \parallel i$.
The following locale introduces the definition of the
rely quotient $c \quotient i$ as a non-deterministic choice over
all processes $d$ such that $c$ is refined by $d \parallel i$.
›
locale rely_quotient = par_distrib + conjunction_parallel
begin
definition
rely_quotient :: "'a ⇒ 'a ⇒ 'a" (infixl "'/'/" 85)
where
"c // i ≡ ⨅{ d. (c ⊑ d ∥ i)}"
text ‹
Any process $c$ is implemented by itself if the interference is skip.
›
lemma quotient_identity: "c // skip = c"
proof -
have "c // skip = ⨅{ d. (c ⊑ d ∥ skip) }" by (metis rely_quotient_def)
then have "c // skip = ⨅{ d. (c ⊑ d) }" by (metis (mono_tags, lifting) Collect_cong par_skip)
thus ?thesis by (metis Inf_greatest Inf_lower2 dual_order.antisym dual_order.refl mem_Collect_eq)
qed
text ‹
Provided the interference process $i$ is non-aborting (i.e. it refines chaos),
any process $c$ is refined by its rely quotient with $i$ in parallel with $i$.
If interference $i$ was allowed to be aborting then,
because $(c \quotient \bot) \parallel \bot$ equals $\bot$,
it does not refine $c$ in general.
›
theorem rely_quotient:
assumes nonabort_i: "chaos ⊑ i"
shows "c ⊑ (c // i) ∥ i"
proof -
define D where "D = { d ∥ i | d. (c ⊑ d ∥ i)}"
define C where "C = {c}"
have "(∀d ∈ D. (∃ c ∈ C. c ⊑ d))" using D_def C_def CollectD singletonI by auto
then have "⨅ C ⊑ (⨅ D)" by (simp add: Inf_mono)
then have "c ⊑ ⨅{ d ∥ i | d. (c ⊑ d ∥ i)}" by (simp add: C_def D_def)
also have "... = ⨅{ d ∥ i | d. d ∈ {d. (c ⊑ d ∥ i)}}" by simp
also have "... = (⨅d ∈ {d. (c ⊑ d ∥ i)}. d ∥ i)" by (simp add: INF_Inf)
also have "... = ⨅{ d | d. (c ⊑ d ∥ i)} ∥ i"
proof (cases "{ d | d. (c ⊑ d ∥ i)} = {}")
assume "{ d | d. (c ⊑ d ∥ i)} = {}"
then show "(⨅d ∈ {d. (c ⊑ d ∥ i)}. d ∥ i) = ⨅{ d | d. (c ⊑ d ∥ i)} ∥ i"
using nonabort_i Collect_empty_eq top_greatest
nonabort_par_top par_commute by fastforce
next
assume a: "{ d | d. (c ⊑ d ∥ i)} ≠ {}"
have b: "{d. (c ⊑ d ∥ i)} ≠ {}" using a by blast
then have "(⨅d ∈ {d. (c ⊑ d ∥ i)}. d ∥ i) = ⨅{ d. (c ⊑ d ∥ i)} ∥ i"
using Inf_par_distrib by simp
then show ?thesis by auto
qed
also have "... = (c // i) ∥ i" by (metis rely_quotient_def)
finally show ?thesis .
qed
text ‹
The following theorem represents the Galois connection between
the parallel operator (upper adjoint) and the rely quotient operator
(lower adjoint). This basic relationship is used to prove the majority
of the theorems about rely quotient.
›
theorem rely_refinement:
assumes nonabort_i: "chaos ⊑ i"
shows "c // i ⊑ d ⟷ c ⊑ d ∥ i"
proof
assume a: "c // i ⊑ d"
have "c ⊑ (c // i) ∥ i" using rely_quotient nonabort_i by simp
thus "c ⊑ d ∥ i" using par_mono a
by (metis inf.absorb_iff2 inf_commute le_infI2 order_refl)
next
assume b: "c ⊑ d ∥ i"
then have "⨅{ d. (c ⊑ d ∥ i)} ⊑ d" by (simp add: Inf_lower)
thus "c // i ⊑ d" by (metis rely_quotient_def)
qed
text ‹
Refining the ``numerator'' in a quotient, refines the quotient.
›
lemma rely_mono:
assumes c_refsto_d: "c ⊑ d"
shows "(c // i) ⊑ (d // i)"
proof -
have "⋀ f. ((d ⊑ f ∥ i) ⟹ ∃ e. (c ⊑ e ∥ i) ∧ (e ⊑ f))"
using c_refsto_d order.trans by blast
then have b: "⨅{ e. (c ⊑ e ∥ i)} ⊑ ⨅{ f. (d ⊑ f ∥ i)}"
by (metis Inf_mono mem_Collect_eq)
show ?thesis using rely_quotient_def b by simp
qed
text ‹
Refining the ``denominator'' in a quotient, gives a reverse refinement
for the quotients. This corresponds to weaken rely condition law of
Jones \<^cite>‹"jon83a"›,
i.e. assuming less about the environment.
›
lemma weaken_rely:
assumes i_refsto_j: "i ⊑ j"
shows "(c // j) ⊑ (c // i)"
proof -
have "⋀ f. ((c ⊑ f ∥ i) ⟹ ∃ e. (c ⊑ e ∥ j) ∧ (e ⊑ f))"
using i_refsto_j order.trans
by (metis inf.absorb_iff2 inf_le1 inf_par_distrib inf_sup_ord(2) par_commute)
then have b: "⨅{ e. (c ⊑ e ∥ j)} ⊑ ⨅{ f. (c ⊑ f ∥ i)}"
by (metis Inf_mono mem_Collect_eq)
show ?thesis using rely_quotient_def b by simp
qed
lemma par_nonabort:
assumes nonabort_i: "chaos ⊑ i"
assumes nonabort_j: "chaos ⊑ j"
shows "chaos ⊑ i ∥ j"
by (meson chaos_par_chaos nonabort_i nonabort_j order_trans par_mono)
text ‹
Nesting rely quotients of $j$ and $i$ means the same as a single quotient
which is the parallel composition of $i$ and $j$.
›
lemma nested_rely:
assumes j_nonabort: "chaos ⊑ j"
shows "((c // j) // i) = c // (i ∥ j)"
proof (rule antisym)
show "((c // j) // i) ⊑ c // (i ∥ j)"
proof -
have "⋀ f. ((c ⊑ f ∥ i ∥ j) ⟹ ∃ e. (c ⊑ e ∥ j) ∧ (e ⊑ f ∥ i))" by blast
then have "⨅{ d. (⨅{ e. (c ⊑ e ∥ j)} ⊑ d ∥ i)} ⊑ ⨅{ f. (c ⊑ f ∥ i ∥ j)}"
by (simp add: Collect_mono Inf_lower Inf_superset_mono)
thus ?thesis using local.rely_quotient_def par_assoc by auto
qed
next
show "c // (i ∥ j) ⊑ ((c // j) // i) "
proof -
have "c ⊑ ⨅{ e. (c ⊑ e ∥ j)} ∥ j"
using j_nonabort local.rely_quotient_def rely_quotient by auto
then have "⋀ d. ⨅{ e. (c ⊑ e ∥ j)} ⊑ d ∥ i ⟹ (c ⊑ d ∥ i ∥ j)"
by (meson j_nonabort order_trans rely_refinement)
thus ?thesis
by (simp add: Collect_mono Inf_superset_mono local.rely_quotient_def par_assoc)
qed
qed
end
subsection ‹Distributed rely quotient›
locale rely_distrib = rely_quotient + conjunction_sequential
begin
text ‹
The following is a fundamental law for introducing a parallel composition
of process to refine a conjunction of specifications.
It represents an abstract view of the parallel introduction law of Jones \<^cite>‹"jon83a"›.
›
lemma introduce_parallel:
assumes nonabort_i: "chaos ⊑ i"
assumes nonabort_j: "chaos ⊑ j"
shows "c \<iinter> d ⊑ (j \<iinter> (c // i)) ∥ (i \<iinter> (d // j))"
proof -
have a: "c ⊑ (c // i) ∥ i" using nonabort_i nonabort_j rely_quotient by auto
have b: "d ⊑ j ∥ (d // j)" using rely_quotient par_commute
by (simp add: nonabort_j)
have "c \<iinter> d ⊑ ((c // i) ∥ i) \<iinter> ( j ∥ (d // j))" using a b by (metis conj_mono)
also have interchange: "c \<iinter> d ⊑ ((c // i) \<iinter> j) ∥ ( i \<iinter> (d // j))"
using parallel_interchange refine_trans calculation by blast
show ?thesis using interchange by (simp add: local.conj_commute)
qed
text ‹
Rely quotients satisfy a range of distribution properties with respect
to the other operators.
›
lemma distribute_rely_conjunction:
assumes nonabort_i: "chaos ⊑ i"
shows "(c \<iinter> d) // i ⊑ (c // i) \<iinter> (d // i)"
proof -
have "c \<iinter> d ⊑ ((c // i) ∥ i) \<iinter> ((d // i) ∥ i)" using conj_mono rely_quotient
by (simp add: nonabort_i)
then have "c \<iinter> d ⊑ ((c // i) \<iinter> (d // i)) ∥ (i \<iinter> i)"
by (metis parallel_interchange refine_trans)
then have "c \<iinter> d ⊑ ((c // i) \<iinter> (d // i)) ∥ i" by (metis conj_idem)
thus ?thesis using rely_refinement by (simp add: nonabort_i)
qed
lemma distribute_rely_choice:
assumes nonabort_i: "chaos ⊑ i"
shows "(c ⊓ d) // i ⊑ (c // i) ⊓ (d // i)"
proof -
have "c ⊓ d ⊑ ((c // i) ∥ i) ⊓ ((d // i) ∥ i)"
by (metis nonabort_i inf_mono rely_quotient)
then have "c ⊓ d ⊑ ((c // i) ⊓ (d // i)) ∥ i" by (metis inf_par_distrib)
thus ?thesis by (metis nonabort_i rely_refinement)
qed
lemma distribute_rely_parallel1:
assumes nonabort_i: "chaos ⊑ i"
assumes nonabort_j: "chaos ⊑ j"
shows "(c ∥ d) // (i ∥ j) ⊑ (c // i) ∥ (d // j)"
proof -
have "(c ∥ d) ⊑ ((c // i) ∥ i) ∥ ((d // j) ∥ j)"
using par_mono rely_quotient nonabort_i nonabort_j by simp
then have "(c ∥ d) ⊑ (c // i) ∥ (d // j) ∥ j ∥ i" by (metis par_assoc par_commute)
thus ?thesis using par_assoc par_commute rely_refinement
by (metis nonabort_i nonabort_j par_nonabort)
qed
lemma distribute_rely_parallel2:
assumes nonabort_i: "chaos ⊑ i"
assumes i_par_i: "i ∥ i ⊑ i"
shows "(c ∥ d) // i ⊑ (c // i) ∥ (d // i)"
proof -
have "(c ∥ d) // i ⊑ ((c ∥ d) // (i ∥ i))" using assms(1) using weaken_rely
by (simp add: i_par_i par_nonabort)
thus ?thesis by (metis distribute_rely_parallel1 refine_trans nonabort_i)
qed
lemma distribute_rely_sequential:
assumes nonabort_i: "chaos ⊑ i"
assumes "(∀ c. (∀ d. ((c ∥ i);(d ∥ i) ⊑ (c;d) ∥ i)))"
shows "(c;d) // i ⊑ (c // i);(d // i)"
proof -
have "c;d ⊑ ((c // i) ∥ i);((d // i) ∥ i)"
by (metis rely_quotient nonabort_i seq_mono)
then have "c;d ⊑ (c // i) ; (d // i) ∥ i" using assms(2) by (metis refine_trans)
thus ?thesis by (metis rely_refinement nonabort_i)
qed
lemma distribute_rely_sequential_event:
assumes nonabort_i: "chaos ⊑ i"
assumes nonabort_j: "chaos ⊑ j"
assumes nonabort_e: "chaos ⊑ e"
assumes "(∀ c. (∀ d. ((c ∥ i);e;(d ∥ j) ⊑ (c;e;d) ∥ (i;e;j))))"
shows "(c;e;d) // (i;e;j) ⊑ (c // i);e;(d // j)"
proof -
have "c;e;d ⊑ ((c // i) ∥ i);e;((d // j) ∥ j)"
by (metis order.refl rely_quotient nonabort_i nonabort_j seq_mono)
then have "c;e;d ⊑ ((c // i);e;(d // j)) ∥ (i;e;j)" using assms
by (metis refine_trans)
thus ?thesis using rely_refinement nonabort_i nonabort_j nonabort_e
by (simp add: Inf_lower local.rely_quotient_def)
qed
lemma introduce_parallel_with_rely:
assumes nonabort_i: "chaos ⊑ i"
assumes nonabort_j0: "chaos ⊑ j⇩0"
assumes nonabort_j1: "chaos ⊑ j⇩1"
shows "(c \<iinter> d) // i ⊑ (j⇩1 \<iinter> (c // (j⇩0 ∥ i))) ∥ (j⇩0 \<iinter> (d // (j⇩1 ∥ i)))"
proof -
have "(c \<iinter> d) // i ⊑ (c // i) \<iinter> (d // i)"
by (metis distribute_rely_conjunction nonabort_i)
then have "(c \<iinter> d) // i ⊑ (j⇩1 \<iinter> ((c // i) // j⇩0)) ∥ (j⇩0 \<iinter> ((d // i) // j⇩1))"
by (metis introduce_parallel nonabort_j0 nonabort_j1 inf_assoc inf.absorb_iff1)
thus ?thesis by (simp add: nested_rely nonabort_i)
qed
lemma introduce_parallel_with_rely_guarantee:
assumes nonabort_i: "chaos ⊑ i"
assumes nonabort_j0: "chaos ⊑ j⇩0"
assumes nonabort_j1: "chaos ⊑ j⇩1"
shows "(j⇩1 ∥ j⇩0) \<iinter> (c \<iinter> d) // i ⊑ (j⇩1 \<iinter> (c // (j⇩0 ∥ i))) ∥ (j⇩0 \<iinter> (d // (j⇩1 ∥ i)))"
proof -
have "(j⇩1 ∥ j⇩0) \<iinter> (c \<iinter> d) // i ⊑ (j⇩1 ∥ j⇩0) \<iinter> ((j⇩1 \<iinter> (c // (j⇩0 ∥ i))) ∥ (j⇩0 \<iinter> (d // (j⇩1 ∥ i))))"
by (metis introduce_parallel_with_rely nonabort_i nonabort_j0 nonabort_j1
conj_mono order.refl)
also have "... ⊑ (j⇩1 \<iinter> j⇩1 \<iinter> (c // (j⇩0 ∥ i))) ∥ (j⇩0 \<iinter> j⇩0 \<iinter> (d // (j⇩1 ∥ i)))"
by (metis conj_assoc parallel_interchange)
finally show ?thesis by (metis conj_idem)
qed
lemma wrap_rely_guar:
assumes nonabort_rg: "chaos ⊑ rg"
and skippable: "rg ⊑ skip"
shows "c ⊑ rg \<iinter> c // rg"
proof -
have "c = c // skip" by (simp add: quotient_identity)
also have "... ⊑ c // rg" by (simp add: skippable weaken_rely nonabort_rg)
also have "... ⊑ rg \<iinter> c // rg" using conjoin_non_aborting conj_commute nonabort_rg
by auto
finally show "c ⊑ rg \<iinter> c // rg" .
qed
end
locale rely_distrib_iteration = rely_distrib + iteration_finite_conjunctive
begin
lemma distribute_rely_iteration:
assumes nonabort_i: "chaos ⊑ i"
assumes "(∀ c. (∀ d. ((c ∥ i);(d ∥ i) ⊑ (c;d) ∥ i)))"
shows "(c⇧ω;d) // i ⊑ (c // i)⇧ω;(d // i)"
proof -
have "d ⊓ c ; ((c // i)⇧ω;(d // i) ∥ i) ⊑ ((d // i) ∥ i) ⊓ ((c // i) ∥ i);((c // i)⇧ω;(d // i) ∥ i)"
by (metis inf_mono order.refl rely_quotient nonabort_i seq_mono)
also have "... ⊑ ((d // i) ∥ i) ⊓ ((c // i);(c // i)⇧ω;(d // i) ∥ i )"
using assms inf_mono_right seq_assoc by fastforce
also have "... ⊑ ((d // i) ⊓ (c // i);(c // i)⇧ω;(d // i)) ∥ i"
by (simp add: inf_par_distrib)
also have "... = ((c // i)⇧ω;(d // i)) ∥ i"
by (metis iter_unfold inf_seq_distrib seq_nil_left)
finally show ?thesis by (metis rely_refinement nonabort_i iter_induct)
qed
end
end