Theory Matrix_Relation_Algebras
section ‹Matrix Relation Algebras›
text ‹
This theory gives matrix models of Stone relation algebras and more general structures.
We consider only square matrices.
The main result is that matrices over Stone relation algebras form a Stone relation algebra.
We use the monoid structure underlying semilattices to provide finite sums, which are necessary for defining the composition of two matrices.
See \<^cite>‹"ArmstrongFosterStruthWeber2016" and "ArmstrongGomesStruthWeber2016"› for similar liftings to matrices for semirings and relation algebras.
A technical difference is that those theories are mostly based on semirings whereas our hierarchy is mostly based on lattices (and our semirings directly inherit from semilattices).
Relation algebras have both a semiring and a lattice structure such that semiring addition and lattice join coincide.
In particular, finite sums and finite suprema coincide.
Isabelle/HOL has separate theories for semirings and lattices, based on separate addition and join operations and different operations for finite sums and finite suprema.
Reusing results from both theories is beneficial for relation algebras, but not always easy to realise.
›
theory Matrix_Relation_Algebras
imports Relation_Algebras
begin
subsection ‹Finite Suprema›
text ‹
We consider finite suprema in idempotent semirings and Stone relation algebras.
We mostly use the first of the following notations, which denotes the supremum of expressions ‹t(x)› over all ‹x› from the type of ‹x›.
For finite types, this is implemented in Isabelle/HOL as the repeated application of binary suprema.
›
syntax
"_sum_sup_monoid" :: "idt ⇒ 'a::bounded_semilattice_sup_bot ⇒ 'a" ("(⨆⇩_ _)" [0,10] 10)
"_sum_sup_monoid_bounded" :: "idt ⇒ 'b set ⇒ 'a::bounded_semilattice_sup_bot ⇒ 'a" ("(⨆⇘_∈_⇙ _)" [0,51,10] 10)
translations
"⨆⇩x t" => "XCONST sup_monoid.sum (λx . t) { x . CONST True }"
"⨆⇘x∈X⇙ t" => "XCONST sup_monoid.sum (λx . t) X"
context idempotent_semiring
begin
text ‹
The following induction principles are useful for comparing two suprema.
The first principle works because types are not empty.
›
lemma one_sup_induct [case_names one sup]:
fixes f g :: "'b::finite ⇒ 'a"
assumes one: "⋀i . P (f i) (g i)"
and sup: "⋀j I . j ∉ I ⟹ P (⨆⇘i∈I⇙ f i) (⨆⇘i∈I⇙ g i) ⟹ P (f j ⊔ (⨆⇘i∈I⇙ f i)) (g j ⊔ (⨆⇘i∈I⇙ g i))"
shows "P (⨆⇩k f k) (⨆⇩k g k)"
proof -
let ?X = "{ k::'b . True }"
have "finite ?X" and "?X ≠ {}"
by auto
thus ?thesis
proof (induct rule: finite_ne_induct)
case (singleton i) thus ?case
using one by simp
next
case (insert j I) thus ?case
using sup by simp
qed
qed
lemma bot_sup_induct [case_names bot sup]:
fixes f g :: "'b::finite ⇒ 'a"
assumes bot: "P bot bot"
and sup: "⋀j I . j ∉ I ⟹ P (⨆⇘i∈I⇙ f i) (⨆⇘i∈I⇙ g i) ⟹ P (f j ⊔ (⨆⇘i∈I⇙ f i)) (g j ⊔ (⨆⇘i∈I⇙ g i))"
shows "P (⨆⇩k f k) (⨆⇩k g k)"
apply (induct rule: one_sup_induct)
using bot sup apply fastforce
using sup by blast
text ‹
Now many properties of finite suprema follow by simple applications of the above induction rules.
In particular, we show distributivity of composition, isotonicity and the upper-bound property.
›
lemma comp_right_dist_sum:
fixes f :: "'b::finite ⇒ 'a"
shows "(⨆⇩k f k * x) = (⨆⇩k f k) * x"
proof (induct rule: one_sup_induct)
case one show ?case
by simp
next
case (sup j I) thus ?case
using mult_right_dist_sup by auto
qed
lemma comp_left_dist_sum:
fixes f :: "'b::finite ⇒ 'a"
shows "(⨆⇩k x * f k) = x * (⨆⇩k f k)"
proof (induct rule: one_sup_induct)
case one show ?case
by simp
next
case (sup j I) thus ?case
by (simp add: mult_left_dist_sup)
qed
lemma leq_sum:
fixes f g :: "'b::finite ⇒ 'a"
shows "(∀k . f k ≤ g k) ⟹ (⨆⇩k f k) ≤ (⨆⇩k g k)"
proof (induct rule: one_sup_induct)
case one thus ?case
by simp
next
case (sup j I) thus ?case
using sup_mono by blast
qed
lemma ub_sum:
fixes f :: "'b::finite ⇒ 'a"
shows "f i ≤ (⨆⇩k f k)"
proof -
have "i ∈ { k . True }"
by simp
thus "f i ≤ (⨆⇩k f (k::'b))"
by (metis finite_code sup_monoid.sum.insert sup_ge1 mk_disjoint_insert)
qed
lemma lub_sum:
fixes f :: "'b::finite ⇒ 'a"
assumes "∀k . f k ≤ x"
shows "(⨆⇩k f k) ≤ x"
proof (induct rule: one_sup_induct)
case one show ?case
by (simp add: assms)
next
case (sup j I) thus ?case
using assms le_supI by blast
qed
lemma lub_sum_iff:
fixes f :: "'b::finite ⇒ 'a"
shows "(∀k . f k ≤ x) ⟷ (⨆⇩k f k) ≤ x"
using order.trans ub_sum lub_sum by blast
lemma sum_const:
"(⨆⇩k::'b::finite f) = f"
by (metis lub_sum sup.cobounded1 sup_monoid.add_0_right sup_same_context ub_sum)
end
context stone_relation_algebra
begin
text ‹
In Stone relation algebras, we can also show that converse, double complement and meet distribute over finite suprema.
›
lemma conv_dist_sum:
fixes f :: "'b::finite ⇒ 'a"
shows "(⨆⇩k (f k)⇧T) = (⨆⇩k f k)⇧T"
proof (induct rule: one_sup_induct)
case one show ?case
by simp
next
case (sup j I) thus ?case
by (simp add: conv_dist_sup)
qed
lemma pp_dist_sum:
fixes f :: "'b::finite ⇒ 'a"
shows "(⨆⇩k --f k) = --(⨆⇩k f k)"
proof (induct rule: one_sup_induct)
case one show ?case
by simp
next
case (sup j I) thus ?case
by simp
qed
lemma inf_right_dist_sum:
fixes f :: "'b::finite ⇒ 'a"
shows "(⨆⇩k f k ⊓ x) = (⨆⇩k f k) ⊓ x"
by (rule comp_inf.comp_right_dist_sum)
end
subsection ‹Square Matrices›
text ‹
Because our semiring and relation algebra type classes only work for homogeneous relations, we only look at square matrices.
›
type_synonym ('a,'b) square = "'a × 'a ⇒ 'b"
text ‹
We use standard matrix operations.
The Stone algebra structure is lifted componentwise.
Composition is matrix multiplication using given composition and supremum operations.
Its unit lifts given zero and one elements into an identity matrix.
Converse is matrix transpose with an additional componentwise transpose.
›
definition less_eq_matrix :: "('a,'b::ord) square ⇒ ('a,'b) square ⇒ bool" (infix "≼" 50) where "f ≼ g = (∀e . f e ≤ g e)"
definition less_matrix :: "('a,'b::ord) square ⇒ ('a,'b) square ⇒ bool" (infix "≺" 50) where "f ≺ g = (f ≼ g ∧ ¬ g ≼ f)"
definition sup_matrix :: "('a,'b::sup) square ⇒ ('a,'b) square ⇒ ('a,'b) square" (infixl "⊕" 65) where "f ⊕ g = (λe . f e ⊔ g e)"
definition inf_matrix :: "('a,'b::inf) square ⇒ ('a,'b) square ⇒ ('a,'b) square" (infixl "⊗" 67) where "f ⊗ g = (λe . f e ⊓ g e)"
definition minus_matrix :: "('a,'b::{uminus,inf}) square ⇒ ('a,'b) square ⇒ ('a,'b) square" (infixl "⊖" 65) where "f ⊖ g = (λe . f e ⊓ -g e)"
definition implies_matrix :: "('a,'b::implies) square ⇒ ('a,'b) square ⇒ ('a,'b) square" (infixl "⊘" 65) where "f ⊘ g = (λe . f e ↝ g e)"
definition times_matrix :: "('a,'b::{times,bounded_semilattice_sup_bot}) square ⇒ ('a,'b) square ⇒ ('a,'b) square" (infixl "⊙" 70) where "f ⊙ g = (λ(i,j) . ⨆⇩k f (i,k) * g (k,j))"
definition uminus_matrix :: "('a,'b::uminus) square ⇒ ('a,'b) square" ("⊖ _" [80] 80) where "⊖f = (λe . -f e)"
definition conv_matrix :: "('a,'b::conv) square ⇒ ('a,'b) square" ("_⇧t" [100] 100) where "f⇧t = (λ(i,j) . (f (j,i))⇧T)"
definition bot_matrix :: "('a,'b::bot) square" ("mbot") where "mbot = (λe . bot)"
definition top_matrix :: "('a,'b::top) square" ("mtop") where "mtop = (λe . top)"
definition one_matrix :: "('a,'b::{one,bot}) square" ("mone") where "mone = (λ(i,j) . if i = j then 1 else bot)"
subsection ‹Stone Algebras›
text ‹
We first lift the Stone algebra structure.
Because all operations are componentwise, this also works for infinite matrices.
›