Theory Strong_Equivalences
section ‹Strong Equivalences›
theory Strong_Equivalences
imports Labeled_Transition_Systems
begin
context lts begin
subsection ‹Trivial notions of equality›
subsubsection ‹Identity›
definition identical :: ‹'s ⇒ 's ⇒ bool›
where ‹identical p q ≡ p = q›
text ‹It's reflexive›
lemma identical_reflexive:
shows ‹identical p p›
unfolding identical_def using refl .
lemma non_identity:
assumes ‹p ≠ q›
shows ‹¬ identical p q›
using assms unfolding identical_def .
text ‹It's an equivalence.›
lemma identity_equivalence:
shows ‹equivp identical›
proof (rule equivpI)
show ‹reflp identical› unfolding reflp_def using allI identical_reflexive .
next
show ‹symp identical› unfolding symp_def
proof (rule+)
fix x y
assume ‹identical x y›
then have ‹x = y› unfolding identical_def .
with sym have ‹y = x› .
then show ‹identical y x› unfolding identical_def .
qed
next
show ‹transp identical›
unfolding transp_def identical_def by blast
qed
subsubsection ‹Universal equality›
definition universal_equal :: ‹'s ⇒ 's ⇒ bool›
where ‹universal_equal p q ≡ True›
lemma universal_equal_equivalence:
shows ‹equivp universal_equal›
unfolding equivp_def universal_equal_def by simp
subsection ‹Trace Equality›
text ‹Trace preorder as inclusion of trace sets›
definition trace_preordered :: ‹'s ⇒ 's ⇒ bool› (infix ‹≲T› 80) where
‹p ≲T q ≡ traces p ⊆ traces q›
text ‹Trace equivalence as mutual preorder›
abbreviation trace_equivalent (infix ‹≃T› 80) where
‹p ≃T q ≡ p ≲T q ∧ q ≲T p›
text ‹Trace preorder is transitive›
lemma trace_preorder_transitive:
shows ‹transp (≲T)›
unfolding trace_preordered_def
by (standard, blast)
lemma trace_equivalence_equiv:
shows ‹equivp trace_equivalent›
proof (rule equivpI)
show ‹transp trace_equivalent›
using trace_preorder_transitive
unfolding transp_def
by blast
next
show ‹reflp trace_equivalent›
unfolding reflp_def trace_preordered_def by blast
next
show ‹symp trace_equivalent›
unfolding symp_def trace_preordered_def by blast
qed
subsection ‹Isomorphism›
definition isomorphism :: ‹('s ⇒ 's) ⇒ bool›
where ‹isomorphism f ≡ bij f ∧ (∀p p' a. p ⟼ a p' ⟷ (f p) ⟼ a (f p'))›
definition is_isomorphic_to (infix ‹≃ISO› 80)
where ‹p ≃ISO q ≡ ∃f. f p = q ∧ isomorphism f›
text ‹Isomorphism yields an equivalence›
lemma iso_equivalence_equiv:
shows ‹equivp is_isomorphic_to›
proof (rule equivpI)
show ‹reflp is_isomorphic_to›
unfolding reflp_def is_isomorphic_to_def isomorphism_def by (metis bij_id id_apply)
next
show ‹symp is_isomorphic_to›
unfolding symp_def is_isomorphic_to_def isomorphism_def by (metis (no_types, opaque_lifting) bij_iff)
next
show ‹transp is_isomorphic_to›
unfolding transp_def is_isomorphic_to_def
proof safe
fix p f1 f2
assume ‹isomorphism f1› ‹isomorphism f2›
then have ‹isomorphism (f2 ∘ f1)› unfolding isomorphism_def using bij_comp by auto
then show ‹∃fb. fb p = f2 (f1 p) ∧ isomorphism fb› unfolding comp_def by auto
qed
qed
text ‹Isomorphism equivalence is closed under steps
(i.e. isomorphism equivalence is a simulation, but we have not yet defined this notion.)
›
lemma iso_sim:
assumes
‹is_isomorphic_to p q›
‹p ⟼ a p'›
shows ‹∃q'. q ⟼ a q' ∧ is_isomorphic_to p' q'›
using assms unfolding is_isomorphic_to_def isomorphism_def by blast
text ‹Isomorphic states have the same traces.›
text ‹Teaching hint: Inductive proofs›
lemma iso_implies_trace_preord:
assumes ‹is_isomorphic_to p q›
shows ‹trace_preordered p q›
unfolding trace_preordered_def
proof safe
fix tr p'
assume ‹p ⟼$tr p'›
thus ‹∃p'. q ⟼$tr p'› using assms
proof (induct tr arbitrary: p q p')
case Nil
then show ?case using empty_trace_trivial by blast
next
case (Cons a tr p q p')
from ‹p ⟼$(a # tr) p'›
obtain p'' where ‹p ⟼a p''› ‹p'' ⟼$ tr p'›
by (cases, auto)
then show ?case
using iso_sim[OF ‹is_isomorphic_to p q› ‹p ⟼a p''›]
Cons(1) sstep by blast
qed
qed
corollary iso_implies_trace_eq:
assumes ‹is_isomorphic_to p q›
shows ‹trace_equivalent p q›
using assms iso_implies_trace_preord iso_equivalence_equiv
unfolding equivp_def by simp
subsection ‹Simulation preorder and equivalence›
text ‹Two states are simulation preordered if they can be related by
a simulation relation.›
definition simulation
where ‹simulation R ≡
∀p q a p'. p ⟼ a p' ∧ R p q ⟶ (∃q'. q ⟼ a q' ∧ R p' q')›
definition simulated_by (infix ‹≲S› 80)
where ‹p ≲S q ≡ ∃R. R p q ∧ simulation R›
abbreviation similar (infix ‹≃S› 80)
where ‹p ≃S q ≡ p ≲S q ∧ q ≲S p›
lemma id_sim:
shows ‹simulation identical›
unfolding simulation_def identical_def by blast
lemma simulation_composition:
assumes
‹simulation R1›
‹simulation R2›
shows
‹simulation (λp q. ∃p'. R1 p p' ∧ R2 p' q)›
using assms unfolding simulation_def by blast
lemma simulation_union:
assumes
‹simulation R1›
‹simulation R2›
shows
‹simulation (λp q. R1 p q ∨ R2 p q)›
using assms unfolding simulation_def by blast
lemma simulation_preorder_transitive:
shows ‹transp (≲S)›
unfolding transp_def simulated_by_def
using simulation_composition
by (metis (mono_tags, lifting))
lemma iso_is_sim:
shows ‹simulation is_isomorphic_to›
using iso_sim unfolding simulated_by_def simulation_def by blast
corollary iso_implies_sim:
assumes ‹is_isomorphic_to p q›
shows ‹simulated_by p q›
using assms iso_is_sim unfolding simulated_by_def by blast
lemma sim_implies_trace_preord:
assumes ‹p ≲S q›
shows ‹p ≲T q›
unfolding trace_preordered_def
proof safe
fix tr p'
assume ‹p ⟼$tr p'›
thus ‹∃p'. q ⟼$tr p'› using assms
proof (induct tr arbitrary: p q p')
case Nil
then show ?case using empty_trace_trivial by blast
next
case (Cons a tr p q p')
from ‹p ⟼$(a # tr) p'›
obtain p'' where p''_spec: ‹p ⟼a p''› ‹p'' ⟼$ tr p'›
by (cases, auto)
then obtain R q' where ‹simulation R› ‹R p q› ‹R p'' q'›
using Cons unfolding simulated_by_def simulation_def by blast
then show ?case
using Cons step_sequence.sstep p''_spec
simulated_by_def simulation_def by metis
qed
qed
lemma sim_eq_implies_trace_eq:
assumes ‹p ≃S q›
shows ‹p ≃T q›
using assms sim_implies_trace_preord by blast
text ‹Two states are bisimilar if they can be related by a symmetric simulation.›
definition bisimilar (infix ‹≃B› 80) where
‹bisimilar p q ≡ ∃R. simulation R ∧ symp R ∧ R p q›
text ‹Bisimilarity is a simulation.›
lemma bisim_sim:
shows ‹simulation bisimilar›
unfolding bisimilar_def simulation_def by blast
lemma bisimilarity_equiv:
shows ‹equivp (≃B)›
proof (rule equivpI)
show ‹reflp (≃B)›
using id_sim DEADID.rel_symp
unfolding bisimilar_def identical_def
by (metis (mono_tags, lifting) reflpI)
next
show ‹symp (≃B)›
unfolding bisimilar_def
by (smt (verit, best) sympE sympI)
next
show ‹transp (≃B)›
unfolding transp_def bisimilar_def
proof safe
fix p p' q R1 R2
assume case_assms:
‹simulation R1› ‹symp R1› ‹R1 p p'›
‹simulation R2› ‹symp R2› ‹R2 p' q›
hence ‹simulation (λp q. (∃p'. R1 p p' ∧ R2 p' q) ∨ (∃p'. R2 p p' ∧ R1 p' q))›
using simulation_composition simulation_union by blast
moreover have
‹symp (λp q. (∃p'. R1 p p' ∧ R2 p' q) ∨ (∃p'. R2 p p' ∧ R1 p' q))›
using case_assms(2,5) unfolding symp_def by blast
ultimately show ‹∃R. simulation R ∧ symp R ∧ R p q›
using case_assms(3,6) by blast
qed
qed
text ‹Bisimilarity is a bisimulation.›
lemma bisim_bisim:
shows ‹simulation bisimilar ∧ symp bisimilar›
using bisim_sim bisimilarity_equiv equivpE by blast
lemma bisim_implies_sim:
assumes ‹p ≃B q›
shows ‹p ≃S q›
using assms bisim_bisim
unfolding simulated_by_def
by (metis sympE)
lemma iso_implies_bisim:
assumes ‹p ≃ISO q›
shows ‹p ≃B q›
using assms iso_is_sim equivpE[OF iso_equivalence_equiv] bisimilar_def by blast
end
end