Theory Kleene_Algebra.Conway

(* Title:      Conway Algebra
   Author:     Alasdair Armstrong, Victor B. F. Gomes, Georg Struth
   Maintainer: Georg Struth <g.struth at sheffield.ac.uk>
               Tjark Weber <tjark.weber at it.uu.se>
*)

section ‹Conway Algebras›

theory Conway
  imports Dioid
begin

text ‹
  We define a weak regular algebra which can serve as a common basis for Kleene algebra and demonic reginement algebra.
  It is closely related to an axiomatisation given by Conway~cite‹"conway71regular"›. 
›

class dagger_op =
  fixes dagger :: "'a ⇒ 'a" (‹_†› [101] 100)

subsection‹Near Conway Algebras›

class near_conway_base = near_dioid_one + dagger_op +
  assumes dagger_denest: "(x + y)† = (x† ⋅ y)† ⋅ x†"
  and dagger_prod_unfold [simp]: "1 + x ⋅ (y ⋅ x)† ⋅ y = (x ⋅ y)†"

begin

lemma dagger_unfoldl_eq [simp]: "1 + x ⋅ x† = x†"
  by (metis dagger_prod_unfold mult_1_left mult_1_right)

lemma dagger_unfoldl: "1 + x ⋅ x† ≤ x†"
  by auto

lemma dagger_unfoldr_eq [simp]: "1 + x† ⋅ x = x†"
  by (metis dagger_prod_unfold mult_1_right mult_1_left)

lemma dagger_unfoldr: "1 + x† ⋅ x ≤ x†"
  by auto

lemma dagger_unfoldl_distr [simp]: "y + x ⋅ x† ⋅ y = x† ⋅ y"
  by (metis distrib_right' mult_1_left dagger_unfoldl_eq)

lemma dagger_unfoldr_distr [simp]: "y + x† ⋅ x ⋅ y = x† ⋅ y"
  by (metis dagger_unfoldr_eq distrib_right' mult_1_left mult.assoc)

lemma dagger_refl: "1 ≤ x†"
  using dagger_unfoldl local.join.sup.bounded_iff by blast

lemma dagger_plus_one [simp]: "1 + x† = x†"
  by (simp add: dagger_refl local.join.sup_absorb2)

lemma star_1l: "x ⋅ x† ≤ x†"
  using dagger_unfoldl local.join.sup.bounded_iff by blast

lemma star_1r: "x† ⋅ x ≤ x†"
  using dagger_unfoldr local.join.sup.bounded_iff by blast

lemma dagger_ext: "x ≤ x†"
  by (metis dagger_unfoldl_distr local.join.sup.boundedE star_1r)

lemma dagger_trans_eq [simp]: "x† ⋅ x† = x†"
  by (metis dagger_unfoldr_eq local.dagger_denest local.join.sup.idem mult_assoc)

lemma dagger_subdist:  "x† ≤ (x + y)†"
  by (metis dagger_unfoldr_distr local.dagger_denest local.order_prop)

lemma dagger_subdist_var:  "x† + y† ≤ (x + y)†"
  using dagger_subdist local.join.sup_commute by fastforce

lemma dagger_iso [intro]: "x ≤ y ⟹ x† ≤ y†"
  by (metis less_eq_def dagger_subdist)

lemma star_square: "(x ⋅ x)† ≤ x†"
  by (metis dagger_plus_one dagger_subdist dagger_trans_eq dagger_unfoldr_distr dagger_denest
    distrib_right' order.eq_iff join.sup_commute less_eq_def mult_onel mult_assoc)

lemma dagger_rtc1_eq [simp]: "1 + x + x† ⋅ x† = x†"
  by (simp add: local.dagger_ext local.dagger_refl local.join.sup_absorb2)

text ‹Nitpick refutes the next lemmas.›

lemma " y + y ⋅ x† ⋅ x = y ⋅ x†"
(*nitpick [expect=genuine]*)
  oops

lemma "y ⋅ x† = y + y ⋅ x ⋅ x†"
(*nitpick [expect=genuine]*)
  oops

lemma "(x + y)† = x† ⋅ (y ⋅ x†)†"
(*nitpick [expect=genuine]*)
  oops

lemma "(x†)† = x†"
(*nitpick [expect=genuine]*)
oops

lemma "(1 + x)⋆ = x⋆"
(*nitpick [expect = genuine]*)
oops

lemma "x† ⋅ x = x ⋅ x†"
(*nitpick [expect=genuine]*)
oops

end

subsection‹Pre-Conway Algebras›

class pre_conway_base = near_conway_base + pre_dioid_one

begin

lemma dagger_subdist_var_3: "x† ⋅ y† ≤ (x + y)†"
  using local.dagger_subdist_var local.mult_isol_var by fastforce

lemma dagger_subdist_var_2: "x ⋅ y ≤ (x + y)†"
  by (meson dagger_subdist_var_3 local.dagger_ext local.mult_isol_var local.order.trans)

lemma dagger_sum_unfold [simp]: "x† + x† ⋅ y ⋅ (x + y)† = (x + y)†"
  by (metis local.dagger_denest local.dagger_unfoldl_distr mult_assoc)

end

subsection ‹Conway Algebras›

class conway_base = pre_conway_base + dioid_one

begin

lemma troeger: "(x + y)† ⋅ z = x† ⋅ (y ⋅ (x + y)† ⋅ z + z)"
proof -
  have "(x + y)† ⋅ z = x† ⋅ z + x† ⋅ y ⋅ (x + y)† ⋅ z"
    by (metis dagger_sum_unfold local.distrib_right')
  thus ?thesis
   by (metis add_commute local.distrib_left mult_assoc)
qed

lemma dagger_slide_var1: "x† ⋅ x ≤ x ⋅ x†"
  by (metis local.dagger_unfoldl_distr local.dagger_unfoldr_eq local.distrib_left order.eq_iff local.mult_1_right mult_assoc)

lemma dagger_slide_var1_eq: "x† ⋅ x = x ⋅ x†"
  by (metis local.dagger_unfoldl_distr local.dagger_unfoldr_eq local.distrib_left local.mult_1_right mult_assoc)

lemma dagger_slide_eq: "(x ⋅ y)† ⋅ x = x ⋅ (y ⋅ x)†"
proof -
  have "(x ⋅ y)† ⋅ x = x + x ⋅ (y ⋅ x)† ⋅ y ⋅ x"
    by (metis local.dagger_prod_unfold local.distrib_right' local.mult_onel)
  also have "... = x ⋅ (1 + (y ⋅ x)† ⋅ y ⋅ x)"
    using local.distrib_left local.mult_1_right mult_assoc by presburger
  finally show ?thesis
    by (simp add: mult_assoc)
qed

end

subsection ‹Conway Algebras with  Zero›

class near_conway_base_zerol = near_conway_base + near_dioid_one_zerol

begin

lemma dagger_annil [simp]: "1 + x ⋅ 0 = (x ⋅ 0)†"
  by (metis annil dagger_unfoldl_eq mult.assoc)

lemma zero_dagger [simp]: "0† = 1"
  by (metis add_0_right annil dagger_annil)

end

class pre_conway_base_zerol = near_conway_base_zerol + pre_dioid

class conway_base_zerol = pre_conway_base_zerol + dioid

subclass (in pre_conway_base_zerol) pre_conway_base ..

subclass (in conway_base_zerol) conway_base ..

context conway_base_zerol
begin

lemma "z ⋅ x ≤ y ⋅ z ⟹ z ⋅ x† ≤ y† ⋅ z"
(*nitpick [expect=genuine]*)
oops 

end

subsection ‹Conway Algebras with Simulation›

class near_conway = near_conway_base +
  assumes dagger_simr: "z ⋅ x ≤ y ⋅ z ⟹ z ⋅ x† ≤ y† ⋅ z"

begin

lemma dagger_slide_var: "x ⋅ (y ⋅ x)† ≤ (x ⋅ y)† ⋅ x"
  by (metis eq_refl dagger_simr mult.assoc)

text ‹Nitpick refutes the next lemma.›

lemma dagger_slide: "x ⋅ (y ⋅ x)† = (x ⋅ y)† ⋅ x"
(*nitpick [expect=genuine]*)
  oops

text ‹
  We say that $y$ preserves $x$ if $x \cdot y \cdot x = x \cdot y$ and $!x \cdot y \cdot !x = !x \cdot y$. This definition is taken
  from Solin~cite‹"Solin11"›. It is useful for program transformation.
›
  
lemma preservation1: "x ⋅ y ≤ x ⋅ y ⋅ x ⟹ x ⋅ y† ≤ (x ⋅ y + z)† ⋅ x"
proof -
  assume "x ⋅ y ≤ x ⋅ y ⋅ x"
  hence "x ⋅ y ≤ (x ⋅ y + z) ⋅ x"
    by (simp add: local.join.le_supI1)
  thus ?thesis
    by (simp add: local.dagger_simr)
qed

end

class near_conway_zerol = near_conway + near_dioid_one_zerol

class pre_conway = near_conway + pre_dioid_one

begin

subclass pre_conway_base ..

lemma dagger_slide: "x ⋅ (y ⋅ x)† = (x ⋅ y)† ⋅ x"
  by (metis add.commute dagger_prod_unfold join.sup_least mult_1_right mult.assoc subdistl dagger_slide_var dagger_unfoldl_distr order.antisym)

lemma dagger_denest2: "(x + y)† = x† ⋅ (y ⋅ x†)†"
  by (metis dagger_denest dagger_slide)

lemma preservation2: "y ⋅ x ≤ y ⟹ (x ⋅ y)† ⋅ x ≤ x ⋅ y†"
  by (metis dagger_slide local.dagger_iso local.mult_isol)

lemma preservation1_eq: "x ⋅ y ≤ x ⋅ y ⋅ x ⟹ y ⋅ x ≤ y ⟹ (x ⋅ y)† ⋅ x = x ⋅ y†"
  by (simp add: local.dagger_simr order.eq_iff preservation2)

end

class pre_conway_zerol = near_conway_zerol + pre_dioid_one_zerol

begin

subclass pre_conway ..

end

class conway = pre_conway + dioid_one

class conway_zerol = pre_conway + dioid_one_zerol

begin

subclass conway_base ..

text ‹Nitpick refutes the next lemmas.›

lemma "1 = 1†"
(*nitpick [expect=genuine]*)
oops

lemma "(x†)† = x†"
(*nitpick [expect=genuine]*)
oops

lemma dagger_denest_var [simp]: "(x + y)† = (x† ⋅ y†)†"
(* nitpick [expect=genuine]*)
oops

lemma star2 [simp]: "(1 + x)† = x†"
(*nitpick [expect=genuine]*)
oops

end

end