Theory Matrix_Kleene_Algebras
section ‹Matrix Kleene Algebras›
text ‹
This theory gives a matrix model of Stone-Kleene relation algebras.
The main result is that matrices over Kleene algebras form Kleene algebras.
The automata-based construction is due to Conway \<^cite>‹"Conway1971"›.
An implementation of the construction in Isabelle/HOL that extends \<^cite>‹"ArmstrongGomesStruthWeber2016"› was given in \<^cite>‹"Asplund2014"› without a correctness proof.
For specifying the size of matrices, Isabelle/HOL's type system requires the use of types, not sets.
This creates two issues when trying to implement Conway's recursive construction directly.
First, the matrix size changes for recursive calls, which requires dependent types.
Second, some submatrices used in the construction are not square, which requires typed Kleene algebras \<^cite>‹"Kozen1998"›, that is, categories of Kleene algebras.
Because these instruments are not available in Isabelle/HOL, we use square matrices with a constant size given by the argument of the Kleene star operation.
Smaller, possibly rectangular submatrices are identified by two lists of indices: one for the rows to include and one for the columns to include.
Lists are used to make recursive calls deterministic; otherwise sets would be sufficient.
›
theory Matrix_Kleene_Algebras
imports Stone_Relation_Algebras.Matrix_Relation_Algebras Kleene_Relation_Algebras
begin
subsection ‹Matrix Restrictions›
text ‹
In this section we develop a calculus of matrix restrictions.
The restriction of a matrix to specific row and column indices is implemented by the following function, which keeps the size of the matrix and sets all unused entries to ‹bot›.
›
definition restrict_matrix :: "'a list ⇒ ('a,'b::bot) square ⇒ 'a list ⇒ ('a,'b) square" (‹_ ⟨_⟩ _› [90,41,90] 91)
where "restrict_matrix as f bs = (λ(i,j) . if i ∈ set as ∧ j ∈ set bs then f (i,j) else bot)"
text ‹
The following function captures Conway's automata-based construction of the Kleene star of a matrix.
An index ‹k› is chosen and ‹s› contains all other indices.
The matrix is split into four submatrices ‹a›, ‹b›, ‹c›, ‹d› including/not including row/column ‹k›.
Four matrices are computed containing the entries given by Conway's construction.
These four matrices are added to obtain the result.
All matrices involved in the function have the same size, but matrix restriction is used to set irrelevant entries to ‹bot›.
›
primrec star_matrix' :: "'a list ⇒ ('a,'b::{star,times,bounded_semilattice_sup_bot}) square ⇒ ('a,'b) square" where
"star_matrix' Nil g = mbot" |
"star_matrix' (k#s) g = (
let r = [k] in
let a = r⟨g⟩r in
let b = r⟨g⟩s in
let c = s⟨g⟩r in
let d = s⟨g⟩s in
let as = r⟨star o a⟩r in
let ds = star_matrix' s d in
let e = a ⊕ b ⊙ ds ⊙ c in
let es = r⟨star o e⟩r in
let f = d ⊕ c ⊙ as ⊙ b in
let fs = star_matrix' s f in
es ⊕ as ⊙ b ⊙ fs ⊕ ds ⊙ c ⊙ es ⊕ fs
)"
text ‹
The Kleene star of the whole matrix is obtained by taking as indices all elements of the underlying type ‹'a›.
This is conveniently supplied by the ‹enum› class.
›
fun star_matrix :: "('a::enum,'b::{star,times,bounded_semilattice_sup_bot}) square ⇒ ('a,'b) square" (‹_⇧⊙› [100] 100) where "star_matrix f = star_matrix' (enum_class.enum::'a list) f"
text ‹
The following lemmas deconstruct matrices with non-empty restrictions.
›
lemma restrict_empty_left:
"[]⟨f⟩ls = mbot"
by (unfold restrict_matrix_def bot_matrix_def) auto
lemma restrict_empty_right:
"ks⟨f⟩[] = mbot"
by (unfold restrict_matrix_def bot_matrix_def) auto
lemma restrict_nonempty_left:
fixes f :: "('a,'b::bounded_semilattice_sup_bot) square"
shows "(k#ks)⟨f⟩ls = [k]⟨f⟩ls ⊕ ks⟨f⟩ls"
by (unfold restrict_matrix_def sup_matrix_def) auto
lemma restrict_nonempty_right:
fixes f :: "('a,'b::bounded_semilattice_sup_bot) square"
shows "ks⟨f⟩(l#ls) = ks⟨f⟩[l] ⊕ ks⟨f⟩ls"
by (unfold restrict_matrix_def sup_matrix_def) auto
lemma restrict_nonempty:
fixes f :: "('a,'b::bounded_semilattice_sup_bot) square"
shows "(k#ks)⟨f⟩(l#ls) = [k]⟨f⟩[l] ⊕ [k]⟨f⟩ls ⊕ ks⟨f⟩[l] ⊕ ks⟨f⟩ls"
by (unfold restrict_matrix_def sup_matrix_def) auto
text ‹
The following predicate captures that two index sets are disjoint.
This has consequences for composition and the unit matrix.
›
abbreviation "disjoint ks ls ≡ ¬ (∃x . x ∈ set ks ∧ x ∈ set ls)"
lemma times_disjoint:
fixes f g :: "('a,'b::idempotent_semiring) square"
assumes "disjoint ls ms"
shows "ks⟨f⟩ls ⊙ ms⟨g⟩ns = mbot"
proof (rule ext, rule prod_cases)
fix i j
have "(ks⟨f⟩ls ⊙ ms⟨g⟩ns) (i,j) = (⨆⇩k (ks⟨f⟩ls) (i,k) * (ms⟨g⟩ns) (k,j))"
by (simp add: times_matrix_def)
also have "... = (⨆⇩k (if i ∈ set ks ∧ k ∈ set ls then f (i,k) else bot)
* (if k ∈ set ms ∧ j ∈ set ns then g (k,j) else bot))"
by (simp add: restrict_matrix_def)
also have "... = (⨆⇩k if k ∈ set ms ∧ j ∈ set ns then bot * g (k,j)
else (if i ∈ set ks ∧ k ∈ set ls then f (i,k) else bot) * bot)"
using assms by (auto intro: sup_monoid.sum.cong)
also have "... = (⨆⇩(k::'a) bot)"
by (simp add: sup_monoid.sum.neutral)
also have "... = bot"
by (simp add: eq_iff le_funI)
also have "... = mbot (i,j)"
by (simp add: bot_matrix_def)
finally show "(ks⟨f⟩ls ⊙ ms⟨g⟩ns) (i,j) = mbot (i,j)"
.
qed
lemma one_disjoint:
assumes "disjoint ks ls"
shows "ks⟨(mone::('a,'b::idempotent_semiring) square)⟩ls = mbot"
proof (rule ext, rule prod_cases)
let ?o = "mone::('a,'b) square"
fix i j
have "(ks⟨?o⟩ls) (i,j) = (if i ∈ set ks ∧ j ∈ set ls then if i = j then 1 else bot else bot)"
by (simp add: restrict_matrix_def one_matrix_def)
also have "... = bot"
using assms by auto
also have "... = mbot (i,j)"
by (simp add: bot_matrix_def)
finally show "(ks⟨?o⟩ls) (i,j) = mbot (i,j)"
.
qed
text ‹
The following predicate captures that an index set is a subset of another index set.
This has consequences for repeated restrictions.
›
abbreviation "is_sublist ks ls ≡ set ks ⊆ set ls"
lemma restrict_sublist:
assumes "is_sublist ls ks"
and "is_sublist ms ns"
shows "ls⟨ks⟨f⟩ns⟩ms = ls⟨f⟩ms"
proof (rule ext, rule prod_cases)
fix i j
show "(ls⟨ks⟨f⟩ns⟩ms) (i,j) = (ls⟨f⟩ms) (i,j)"
proof (cases "i ∈ set ls ∧ j ∈ set ms")
case True
with assms show ?thesis
by (auto simp add: restrict_matrix_def)
next
case False
with assms show ?thesis
by (auto simp add: restrict_matrix_def)
qed
qed
lemma restrict_superlist:
assumes "is_sublist ls ks"
and "is_sublist ms ns"
shows "ks⟨ls⟨f⟩ms⟩ns = ls⟨f⟩ms"
proof (rule ext, rule prod_cases)
fix i j
show "(ks⟨ls⟨f⟩ms⟩ns) (i,j) = (ls⟨f⟩ms) (i,j)"
proof (cases "i ∈ set ls ∧ j ∈ set ms")
case True
with assms show ?thesis
by (auto simp add: restrict_matrix_def)
next
case False
with assms show ?thesis
by (auto simp add: restrict_matrix_def)
qed
qed
text ‹
The following lemmas give the sizes of the results of some matrix operations.
›
lemma restrict_sup:
fixes f g :: "('a,'b::bounded_semilattice_sup_bot) square"
shows "ks⟨f ⊕ g⟩ls = ks⟨f⟩ls ⊕ ks⟨g⟩ls"
by (unfold restrict_matrix_def sup_matrix_def) auto
lemma restrict_times:
fixes f g :: "('a,'b::idempotent_semiring) square"
shows "ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms = ks⟨f⟩ls ⊙ ls⟨g⟩ms"
proof (rule ext, rule prod_cases)
fix i j
have "(ks⟨(ks⟨f⟩ls ⊙ ls⟨g⟩ms)⟩ms) (i,j) = (if i ∈ set ks ∧ j ∈ set ms then (⨆⇩k (ks⟨f⟩ls) (i,k) * (ls⟨g⟩ms) (k,j)) else bot)"
by (simp add: times_matrix_def restrict_matrix_def)
also have "... = (if i ∈ set ks ∧ j ∈ set ms then (⨆⇩k (if i ∈ set ks ∧ k ∈ set ls then f (i,k) else bot) * (if k ∈ set ls ∧ j ∈ set ms then g (k,j) else bot)) else bot)"
by (simp add: restrict_matrix_def)
also have "... = (if i ∈ set ks ∧ j ∈ set ms then (⨆⇩k if k ∈ set ls then f (i,k) * g (k,j) else bot) else bot)"
by (auto intro: sup_monoid.sum.cong)
also have "... = (⨆⇩k if i ∈ set ks ∧ j ∈ set ms then (if k ∈ set ls then f (i,k) * g (k,j) else bot) else bot)"
by auto
also have "... = (⨆⇩k (if i ∈ set ks ∧ k ∈ set ls then f (i,k) else bot) * (if k ∈ set ls ∧ j ∈ set ms then g (k,j) else bot))"
by (auto intro: sup_monoid.sum.cong)
also have "... = (⨆⇩k (ks⟨f⟩ls) (i,k) * (ls⟨g⟩ms) (k,j))"
by (simp add: restrict_matrix_def)
also have "... = (ks⟨f⟩ls ⊙ ls⟨g⟩ms) (i,j)"
by (simp add: times_matrix_def)
finally show "(ks⟨(ks⟨f⟩ls ⊙ ls⟨g⟩ms)⟩ms) (i,j) = (ks⟨f⟩ls ⊙ ls⟨g⟩ms) (i,j)"
.
qed
lemma restrict_star:
fixes g :: "('a,'b::kleene_algebra) square"
shows "t⟨star_matrix' t g⟩t = star_matrix' t g"
proof (induct arbitrary: g rule: list.induct)
case Nil show ?case
by (simp add: restrict_empty_left)
next
case (Cons k s)
let ?t = "k#s"
assume "⋀g::('a,'b) square . s⟨star_matrix' s g⟩s = star_matrix' s g"
then have 1: "?t⟨star_matrix' s g⟩?t = star_matrix' s g" for g :: ‹('a, 'b) square›
using restrict_superlist [of s ‹k # s› s ‹k # s› ‹star_matrix' s g›]
by auto
show "?t⟨star_matrix' ?t g⟩?t = star_matrix' ?t g"
proof -
let ?r = "[k]"
let ?a = "?r⟨g⟩?r"
let ?b = "?r⟨g⟩s"
let ?c = "s⟨g⟩?r"
let ?d = "s⟨g⟩s"
let ?as = "?r⟨star o ?a⟩?r"
let ?ds = "star_matrix' s ?d"
let ?e = "?a ⊕ ?b ⊙ ?ds ⊙ ?c"
let ?es = "?r⟨star o ?e⟩?r"
let ?f = "?d ⊕ ?c ⊙ ?as ⊙ ?b"
let ?fs = "star_matrix' s ?f"
have 2: "?t⟨?as⟩?t = ?as ∧ ?t⟨?b⟩?t = ?b ∧ ?t⟨?c⟩?t = ?c ∧ ?t⟨?es⟩?t = ?es"
by (simp add: restrict_superlist subset_eq)
have 3: "?t⟨?ds⟩?t = ?ds ∧ ?t⟨?fs⟩?t = ?fs"
using 1 by simp
have 4: "?t⟨?t⟨?as⟩?t ⊙ ?t⟨?b⟩?t ⊙ ?t⟨?fs⟩?t⟩?t = ?t⟨?as⟩?t ⊙ ?t⟨?b⟩?t ⊙ ?t⟨?fs⟩?t"
by (metis (no_types) restrict_times)
have 5: "?t⟨?t⟨?ds⟩?t ⊙ ?t⟨?c⟩?t ⊙ ?t⟨?es⟩?t⟩?t = ?t⟨?ds⟩?t ⊙ ?t⟨?c⟩?t ⊙ ?t⟨?es⟩?t"
by (metis (no_types) restrict_times)
have "?t⟨star_matrix' ?t g⟩?t = ?t⟨?es ⊕ ?as ⊙ ?b ⊙ ?fs ⊕ ?ds ⊙ ?c ⊙ ?es ⊕ ?fs⟩?t"
by (metis star_matrix'.simps(2))
also have "... = ?t⟨?es⟩?t ⊕ ?t⟨?as ⊙ ?b ⊙ ?fs⟩?t ⊕ ?t⟨?ds ⊙ ?c ⊙ ?es⟩?t ⊕ ?t⟨?fs⟩?t"
by (simp add: restrict_sup)
also have "... = ?es ⊕ ?as ⊙ ?b ⊙ ?fs ⊕ ?ds ⊙ ?c ⊙ ?es ⊕ ?fs"
using 2 3 4 5 by simp
also have "... = star_matrix' ?t g"
by (metis star_matrix'.simps(2))
finally show ?thesis
.
qed
qed
lemma restrict_one:
assumes "¬ k ∈ set ks"
shows "(k#ks)⟨(mone::('a,'b::idempotent_semiring) square)⟩(k#ks) = [k]⟨mone⟩[k] ⊕ ks⟨mone⟩ks"
by (subst restrict_nonempty) (simp add: assms one_disjoint)
lemma restrict_one_left_unit:
"ks⟨(mone::('a::finite,'b::idempotent_semiring) square)⟩ks ⊙ ks⟨f⟩ls = ks⟨f⟩ls"
proof (rule ext, rule prod_cases)
let ?o = "mone::('a,'b::idempotent_semiring) square"
fix i j
have "(ks⟨?o⟩ks ⊙ ks⟨f⟩ls) (i,j) = (⨆⇩k (ks⟨?o⟩ks) (i,k) * (ks⟨f⟩ls) (k,j))"
by (simp add: times_matrix_def)
also have "... = (⨆⇩k (if i ∈ set ks ∧ k ∈ set ks then ?o (i,k) else bot) * (if k ∈ set ks ∧ j ∈ set ls then f (k,j) else bot))"
by (simp add: restrict_matrix_def)
also have "... = (⨆⇩k (if i ∈ set ks ∧ k ∈ set ks then (if i = k then 1 else bot) else bot) * (if k ∈ set ks ∧ j ∈ set ls then f (k,j) else bot))"
by (unfold one_matrix_def) auto
also have "... = (⨆⇩k (if i = k then (if i ∈ set ks then 1 else bot) else bot) * (if k ∈ set ks ∧ j ∈ set ls then f (k,j) else bot))"
by (auto intro: sup_monoid.sum.cong)
also have "... = (⨆⇩k if i = k then (if i ∈ set ks then 1 else bot) * (if i ∈ set ks ∧ j ∈ set ls then f (i,j) else bot) else bot)"
by (rule sup_monoid.sum.cong) simp_all
also have "... = (if i ∈ set ks then 1 else bot) * (if i ∈ set ks ∧ j ∈ set ls then f (i,j) else bot)"
by simp
also have "... = (if i ∈ set ks ∧ j ∈ set ls then f (i,j) else bot)"
by simp
also have "... = (ks⟨f⟩ls) (i,j)"
by (simp add: restrict_matrix_def)
finally show "(ks⟨?o⟩ks ⊙ ks⟨f⟩ls) (i,j) = (ks⟨f⟩ls) (i,j)"
.
qed
text ‹
The following lemmas consider restrictions to singleton index sets.
›
lemma restrict_singleton:
"([k]⟨f⟩[l]) (i,j) = (if i = k ∧ j = l then f (i,j) else bot)"
by (simp add: restrict_matrix_def)
lemma restrict_singleton_list:
"([k]⟨f⟩ls) (i,j) = (if i = k ∧ j ∈ set ls then f (i,j) else bot)"
by (simp add: restrict_matrix_def)
lemma restrict_list_singleton:
"(ks⟨f⟩[l]) (i,j) = (if i ∈ set ks ∧ j = l then f (i,j) else bot)"
by (simp add: restrict_matrix_def)
lemma restrict_singleton_product:
fixes f g :: "('a::finite,'b::kleene_algebra) square"
shows "([k]⟨f⟩[l] ⊙ [m]⟨g⟩[n]) (i,j) = (if i = k ∧ l = m ∧ j = n then f (i,l) * g (m,j) else bot)"
proof -
have "([k]⟨f⟩[l] ⊙ [m]⟨g⟩[n]) (i,j) = (⨆⇩h ([k]⟨f⟩[l]) (i,h) * ([m]⟨g⟩[n]) (h,j))"
by (simp add: times_matrix_def)
also have "... = (⨆⇩h (if i = k ∧ h = l then f (i,h) else bot) * (if h = m ∧ j = n then g (h,j) else bot))"
by (simp add: restrict_singleton)
also have "... = (⨆⇩h if h = l then (if i = k then f (i,h) else bot) * (if h = m ∧ j = n then g (h,j) else bot) else bot)"
by (rule sup_monoid.sum.cong) auto
also have "... = (if i = k then f (i,l) else bot) * (if l = m ∧ j = n then g (l,j) else bot)"
by simp
also have "... = (if i = k ∧ l = m ∧ j = n then f (i,l) * g (m,j) else bot)"
by simp
finally show ?thesis
.
qed
text ‹
The Kleene star unfold law holds for matrices with a single entry on the diagonal.
›
lemma restrict_star_unfold:
"[l]⟨(mone::('a::finite,'b::kleene_algebra) square)⟩[l] ⊕ [l]⟨f⟩[l] ⊙ [l]⟨star o f⟩[l] = [l]⟨star o f⟩[l]"
proof (rule ext, rule prod_cases)
let ?o = "mone::('a,'b::kleene_algebra) square"
fix i j
have "([l]⟨?o⟩[l] ⊕ [l]⟨f⟩[l] ⊙ [l]⟨star o f⟩[l]) (i,j) = ([l]⟨?o⟩[l]) (i,j) ⊔ ([l]⟨f⟩[l] ⊙ [l]⟨star o f⟩[l]) (i,j)"
by (simp add: sup_matrix_def)
also have "... = ([l]⟨?o⟩[l]) (i,j) ⊔ (⨆⇩k ([l]⟨f⟩[l]) (i,k) * ([l]⟨star o f⟩[l]) (k,j))"
by (simp add: times_matrix_def)
also have "... = ([l]⟨?o⟩[l]) (i,j) ⊔ (⨆⇩k (if i = l ∧ k = l then f (i,k) else bot) * (if k = l ∧ j = l then (f (k,j))⇧⋆ else bot))"
by (simp add: restrict_singleton o_def)
also have "... = ([l]⟨?o⟩[l]) (i,j) ⊔ (⨆⇩k if k = l then (if i = l then f (i,k) else bot) * (if j = l then (f (k,j))⇧⋆ else bot) else bot)"
apply (rule arg_cong2[where f=sup])
apply simp
by (rule sup_monoid.sum.cong) auto
also have "... = ([l]⟨?o⟩[l]) (i,j) ⊔ (if i = l then f (i,l) else bot) * (if j = l then (f (l,j))⇧⋆ else bot)"
by simp
also have "... = (if i = l ∧ j = l then 1 ⊔ f (l,l) * (f (l,l))⇧⋆ else bot)"
by (simp add: restrict_singleton one_matrix_def)
also have "... = (if i = l ∧ j = l then (f (l,l))⇧⋆ else bot)"
by (simp add: star_left_unfold_equal)
also have "... = ([l]⟨star o f⟩[l]) (i,j)"
by (simp add: restrict_singleton o_def)
finally show "([l]⟨?o⟩[l] ⊕ [l]⟨f⟩[l] ⊙ [l]⟨star o f⟩[l]) (i,j) = ([l]⟨star o f⟩[l]) (i,j)"
.
qed
lemma restrict_all:
"enum_class.enum⟨f⟩enum_class.enum = f"
by (simp add: restrict_matrix_def enum_UNIV)
text ‹
The following shows the various components of a matrix product.
It is essentially a recursive implementation of the product.
›
lemma restrict_nonempty_product:
fixes f g :: "('a::finite,'b::idempotent_semiring) square"
assumes "¬ l ∈ set ls"
shows "(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms) = ([k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ ([k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms)"
proof -
have "(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms) = ([k]⟨f⟩[l] ⊕ [k]⟨f⟩ls ⊕ ks⟨f⟩[l] ⊕ ks⟨f⟩ls) ⊙ ([l]⟨g⟩[m] ⊕ [l]⟨g⟩ms ⊕ ls⟨g⟩[m] ⊕ ls⟨g⟩ms)"
by (metis restrict_nonempty)
also have "... = [k]⟨f⟩[l] ⊙ ([l]⟨g⟩[m] ⊕ [l]⟨g⟩ms ⊕ ls⟨g⟩[m] ⊕ ls⟨g⟩ms) ⊕ [k]⟨f⟩ls ⊙ ([l]⟨g⟩[m] ⊕ [l]⟨g⟩ms ⊕ ls⟨g⟩[m] ⊕ ls⟨g⟩ms) ⊕ ks⟨f⟩[l] ⊙ ([l]⟨g⟩[m] ⊕ [l]⟨g⟩ms ⊕ ls⟨g⟩[m] ⊕ ls⟨g⟩ms) ⊕ ks⟨f⟩ls ⊙ ([l]⟨g⟩[m] ⊕ [l]⟨g⟩ms ⊕ ls⟨g⟩[m] ⊕ ls⟨g⟩ms)"
by (simp add: matrix_idempotent_semiring.mult_right_dist_sup)
also have "... = ([k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩[l] ⊙ ls⟨g⟩[m] ⊕ [k]⟨f⟩[l] ⊙ ls⟨g⟩ms) ⊕ ([k]⟨f⟩ls ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩[l] ⊙ ls⟨g⟩[m] ⊕ ks⟨f⟩[l] ⊙ ls⟨g⟩ms) ⊕ (ks⟨f⟩ls ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms)"
by (simp add: matrix_idempotent_semiring.mult_left_dist_sup)
also have "... = ([k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms) ⊕ ([k]⟨f⟩ls ⊙ ls⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩[l] ⊙ [l]⟨g⟩ms) ⊕ (ks⟨f⟩ls ⊙ ls⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms)"
using assms by (simp add: times_disjoint)
also have "... = ([k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ ([k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms)"
by (simp add: matrix_bounded_semilattice_sup_bot.sup_monoid.add_assoc matrix_semilattice_sup.sup_left_commute)
finally show ?thesis
.
qed
text ‹
Equality of matrices is componentwise.
›
lemma restrict_nonempty_eq:
"(k#ks)⟨f⟩(l#ls) = (k#ks)⟨g⟩(l#ls) ⟷ [k]⟨f⟩[l] = [k]⟨g⟩[l] ∧ [k]⟨f⟩ls = [k]⟨g⟩ls ∧ ks⟨f⟩[l] = ks⟨g⟩[l] ∧ ks⟨f⟩ls = ks⟨g⟩ls"
proof
assume 1: "(k#ks)⟨f⟩(l#ls) = (k#ks)⟨g⟩(l#ls)"
have 2: "is_sublist [k] (k#ks) ∧ is_sublist ks (k#ks) ∧ is_sublist [l] (l#ls) ∧ is_sublist ls (l#ls)"
by auto
hence "[k]⟨f⟩[l] = [k]⟨(k#ks)⟨f⟩(l#ls)⟩[l] ∧ [k]⟨f⟩ls = [k]⟨(k#ks)⟨f⟩(l#ls)⟩ls ∧ ks⟨f⟩[l] = ks⟨(k#ks)⟨f⟩(l#ls)⟩[l] ∧ ks⟨f⟩ls = ks⟨(k#ks)⟨f⟩(l#ls)⟩ls"
by (simp add: restrict_sublist)
thus "[k]⟨f⟩[l] = [k]⟨g⟩[l] ∧ [k]⟨f⟩ls = [k]⟨g⟩ls ∧ ks⟨f⟩[l] = ks⟨g⟩[l] ∧ ks⟨f⟩ls = ks⟨g⟩ls"
using 1 2 by (simp add: restrict_sublist)
next
assume 3: "[k]⟨f⟩[l] = [k]⟨g⟩[l] ∧ [k]⟨f⟩ls = [k]⟨g⟩ls ∧ ks⟨f⟩[l] = ks⟨g⟩[l] ∧ ks⟨f⟩ls = ks⟨g⟩ls"
show "(k#ks)⟨f⟩(l#ls) = (k#ks)⟨g⟩(l#ls)"
proof (rule ext, rule prod_cases)
fix i j
have 4: "f (k,l) = g (k,l)"
using 3 by (metis restrict_singleton)
have 5: "j ∈ set ls ⟹ f (k,j) = g (k,j)"
using 3 by (metis restrict_singleton_list)
have 6: "i ∈ set ks ⟹ f (i,l) = g (i,l)"
using 3 by (metis restrict_list_singleton)
have "(ks⟨f⟩ls) (i,j) = (ks⟨g⟩ls) (i,j)"
using 3 by simp
hence 7: "i ∈ set ks ⟹ j ∈ set ls ⟹ f (i,j) = g (i,j)"
by (simp add: restrict_matrix_def)
have "((k#ks)⟨f⟩(l#ls)) (i,j) = (if (i = k ∨ i ∈ set ks) ∧ (j = l ∨ j ∈ set ls) then f (i,j) else bot)"
by (simp add: restrict_matrix_def)
also have "... = (if i = k ∧ j = l then f (i,j) else if i = k ∧ j ∈ set ls then f (i,j) else if i ∈ set ks ∧ j = l then f (i,j) else if i ∈ set ks ∧ j ∈ set ls then f (i,j) else bot)"
by auto
also have "... = (if i = k ∧ j = l then g (i,j) else if i = k ∧ j ∈ set ls then g (i,j) else if i ∈ set ks ∧ j = l then g (i,j) else if i ∈ set ks ∧ j ∈ set ls then g (i,j) else bot)"
using 4 5 6 7 by simp
also have "... = (if (i = k ∨ i ∈ set ks) ∧ (j = l ∨ j ∈ set ls) then g (i,j) else bot)"
by auto
also have "... = ((k#ks)⟨g⟩(l#ls)) (i,j)"
by (simp add: restrict_matrix_def)
finally show "((k#ks)⟨f⟩(l#ls)) (i,j) = ((k#ks)⟨g⟩(l#ls)) (i,j)"
.
qed
qed
text ‹
Inequality of matrices is componentwise.
›
lemma restrict_nonempty_less_eq:
fixes f g :: "('a,'b::idempotent_semiring) square"
shows "(k#ks)⟨f⟩(l#ls) ≼ (k#ks)⟨g⟩(l#ls) ⟷ [k]⟨f⟩[l] ≼ [k]⟨g⟩[l] ∧ [k]⟨f⟩ls ≼ [k]⟨g⟩ls ∧ ks⟨f⟩[l] ≼ ks⟨g⟩[l] ∧ ks⟨f⟩ls ≼ ks⟨g⟩ls"
by (unfold matrix_semilattice_sup.sup.order_iff) (metis (no_types, lifting) restrict_nonempty_eq restrict_sup)
text ‹
The following lemmas treat repeated restrictions to disjoint index sets.
›
lemma restrict_disjoint_left:
assumes "disjoint ks ms"
shows "ms⟨ks⟨f⟩ls⟩ns = mbot"
proof (rule ext, rule prod_cases)
fix i j
have "(ms⟨ks⟨f⟩ls⟩ns) (i,j) = (if i ∈ set ms ∧ j ∈ set ns then if i ∈ set ks ∧ j ∈ set ls then f (i,j) else bot else bot)"
by (auto simp add: restrict_matrix_def)
thus "(ms⟨ks⟨f⟩ls⟩ns) (i,j) = mbot (i,j)"
using assms by (simp add: bot_matrix_def)
qed
lemma restrict_disjoint_right:
assumes "disjoint ls ns"
shows "ms⟨ks⟨f⟩ls⟩ns = mbot"
proof (rule ext, rule prod_cases)
fix i j
have "(ms⟨ks⟨f⟩ls⟩ns) (i,j) = (if i ∈ set ms ∧ j ∈ set ns then if i ∈ set ks ∧ j ∈ set ls then f (i,j) else bot else bot)"
by (simp add: restrict_matrix_def)
thus "(ms⟨ks⟨f⟩ls⟩ns) (i,j) = mbot (i,j)"
using assms by (simp add: bot_matrix_def)
qed
text ‹
The following lemma expresses the equality of a matrix and a product of two matrices componentwise.
›
lemma restrict_nonempty_product_eq:
fixes f g h :: "('a::finite,'b::idempotent_semiring) square"
assumes "¬ k ∈ set ks"
and "¬ l ∈ set ls"
and "¬ m ∈ set ms"
shows "(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms) = (k#ks)⟨h⟩(m#ms) ⟷ [k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m] = [k]⟨h⟩[m] ∧ [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms = [k]⟨h⟩ms ∧ ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m] = ks⟨h⟩[m] ∧ ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms = ks⟨h⟩ms"
proof -
have 1: "disjoint [k] ks ∧ disjoint [m] ms"
by (auto simp add: assms(1,3))
have 2: "[k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] = [k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m]"
proof -
have "[k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] = [k]⟨([k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ ([k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms)⟩[m]"
by (metis assms(2) restrict_nonempty_product)
also have "... = [k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m] ⊕ [k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m] ⊕ [k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩[m] ⊕ [k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩ms⟩[m] ⊕ [k]⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m] ⊕ [k]⟨ks⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m] ⊕ [k]⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩[m] ⊕ [k]⟨ks⟨f⟩ls ⊙ ls⟨g⟩ms⟩[m]"
by (simp add: matrix_bounded_semilattice_sup_bot.sup_monoid.add_assoc restrict_sup)
also have "... = [k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m] ⊕ [k]⟨[k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms⟩[m] ⊕ [k]⟨[k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms⟩[m] ⊕ [k]⟨ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m]⟩[m] ⊕ [k]⟨ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m]⟩[m] ⊕ [k]⟨ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms⟩[m] ⊕ [k]⟨ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms⟩[m]"
by (simp add: restrict_times)
also have "... = [k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m]"
using 1 by (metis restrict_disjoint_left restrict_disjoint_right matrix_bounded_semilattice_sup_bot.sup_monoid.add_0_right)
finally show ?thesis
.
qed
have 3: "[k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms = [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms"
proof -
have "[k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms = [k]⟨([k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ ([k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms)⟩ms"
by (metis assms(2) restrict_nonempty_product)
also have "... = [k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩ms ⊕ [k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩[m]⟩ms ⊕ [k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms ⊕ [k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms ⊕ [k]⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩ms ⊕ [k]⟨ks⟨f⟩ls ⊙ ls⟨g⟩[m]⟩ms ⊕ [k]⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms ⊕ [k]⟨ks⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms"
by (simp add: matrix_bounded_semilattice_sup_bot.sup_monoid.add_assoc restrict_sup)
also have "... = [k]⟨[k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m]⟩ms ⊕ [k]⟨[k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m]⟩ms ⊕ [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms ⊕ [k]⟨ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m]⟩ms ⊕ [k]⟨ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m]⟩ms ⊕ [k]⟨ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms⟩ms ⊕ [k]⟨ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms⟩ms"
by (simp add: restrict_times)
also have "... = [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms"
using 1 by (metis restrict_disjoint_left restrict_disjoint_right matrix_bounded_semilattice_sup_bot.sup_monoid.add_0_right matrix_bounded_semilattice_sup_bot.sup_monoid.add_0_left)
finally show ?thesis
.
qed
have 4: "ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] = ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m]"
proof -
have "ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] = ks⟨([k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ ([k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms)⟩[m]"
by (metis assms(2) restrict_nonempty_product)
also have "... = ks⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m] ⊕ ks⟨[k]⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m] ⊕ ks⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩[m] ⊕ ks⟨[k]⟨f⟩ls ⊙ ls⟨g⟩ms⟩[m] ⊕ ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m] ⊕ ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m] ⊕ ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩[m] ⊕ ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩ms⟩[m]"
by (simp add: matrix_bounded_semilattice_sup_bot.sup_monoid.add_assoc restrict_sup)
also have "... = ks⟨[k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m]⟩[m] ⊕ ks⟨[k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m]⟩[m] ⊕ ks⟨[k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms⟩[m] ⊕ ks⟨[k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms⟩[m] ⊕ ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m] ⊕ ks⟨ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms⟩[m] ⊕ ks⟨ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms⟩[m]"
by (simp add: restrict_times)
also have "... = ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m]"
using 1 by (metis restrict_disjoint_left restrict_disjoint_right matrix_bounded_semilattice_sup_bot.sup_monoid.add_0_right matrix_bounded_semilattice_sup_bot.sup_monoid.add_0_left)
finally show ?thesis
.
qed
have 5: "ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms = ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms"
proof -
have "ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms = ks⟨([k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ ([k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m]) ⊕ (ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms)⟩ms"
by (metis assms(2) restrict_nonempty_product)
also have "... = ks⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩ms ⊕ ks⟨[k]⟨f⟩ls ⊙ ls⟨g⟩[m]⟩ms ⊕ ks⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms ⊕ ks⟨[k]⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms ⊕ ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩ms ⊕ ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩[m]⟩ms ⊕ ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms ⊕ ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms"
by (simp add: matrix_bounded_semilattice_sup_bot.sup_monoid.add_assoc restrict_sup)
also have "... = ks⟨[k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m]⟩ms ⊕ ks⟨[k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m]⟩ms ⊕ ks⟨[k]⟨[k]⟨f⟩[l] ⊙ [l]⟨g⟩ms⟩ms⟩ms ⊕ ks⟨[k]⟨[k]⟨f⟩ls ⊙ ls⟨g⟩ms⟩ms⟩ms ⊕ ks⟨ks⟨ks⟨f⟩[l] ⊙ [l]⟨g⟩[m]⟩[m]⟩ms ⊕ ks⟨ks⟨ks⟨f⟩ls ⊙ ls⟨g⟩[m]⟩[m]⟩ms ⊕ ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms"
by (simp add: restrict_times)
also have "... = ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms"
using 1 by (metis restrict_disjoint_left restrict_disjoint_right matrix_bounded_semilattice_sup_bot.sup_monoid.add_0_left)
finally show ?thesis
.
qed
have "(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms) = (k#ks)⟨h⟩(m#ms) ⟷ (k#ks)⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩(m#ms) = (k#ks)⟨h⟩(m#ms)"
by (simp add: restrict_times)
also have "... ⟷ [k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] = [k]⟨h⟩[m] ∧ [k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms = [k]⟨h⟩ms ∧ ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] = ks⟨h⟩[m] ∧ ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms = ks⟨h⟩ms"
by (meson restrict_nonempty_eq)
also have "... ⟷ [k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m] = [k]⟨h⟩[m] ∧ [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms = [k]⟨h⟩ms ∧ ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m] = ks⟨h⟩[m] ∧ ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms = ks⟨h⟩ms"
using 2 3 4 5 by simp
finally show ?thesis
by simp
qed
text ‹
The following lemma gives a componentwise characterisation of the inequality of a matrix and a product of two matrices.
›
lemma restrict_nonempty_product_less_eq:
fixes f g h :: "('a::finite,'b::idempotent_semiring) square"
assumes "¬ k ∈ set ks"
and "¬ l ∈ set ls"
and "¬ m ∈ set ms"
shows "(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms) ≼ (k#ks)⟨h⟩(m#ms) ⟷ [k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m] ≼ [k]⟨h⟩[m] ∧ [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms ≼ [k]⟨h⟩ms ∧ ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m] ≼ ks⟨h⟩[m] ∧ ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms ≼ ks⟨h⟩ms"
proof -
have 1: "[k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] = [k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m]"
by (metis assms restrict_nonempty_product_eq restrict_times)
have 2: "[k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms = [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms"
by (metis assms restrict_nonempty_product_eq restrict_times)
have 3: "ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] = ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m]"
by (metis assms restrict_nonempty_product_eq restrict_times)
have 4: "ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms = ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms"
by (metis assms restrict_nonempty_product_eq restrict_times)
have "(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms) ≼ (k#ks)⟨h⟩(m#ms) ⟷ (k#ks)⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩(m#ms) ≼ (k#ks)⟨h⟩(m#ms)"
by (simp add: restrict_times)
also have "... ⟷ [k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] ≼ [k]⟨h⟩[m] ∧ [k]⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms ≼ [k]⟨h⟩ms ∧ ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩[m] ≼ ks⟨h⟩[m] ∧ ks⟨(k#ks)⟨f⟩(l#ls) ⊙ (l#ls)⟨g⟩(m#ms)⟩ms ≼ ks⟨h⟩ms"
by (meson restrict_nonempty_less_eq)
also have "... ⟷ [k]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩[m] ≼ [k]⟨h⟩[m] ∧ [k]⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ [k]⟨f⟩ls ⊙ ls⟨g⟩ms ≼ [k]⟨h⟩ms ∧ ks⟨f⟩[l] ⊙ [l]⟨g⟩[m] ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩[m] ≼ ks⟨h⟩[m] ∧ ks⟨f⟩[l] ⊙ [l]⟨g⟩ms ⊕ ks⟨f⟩ls ⊙ ls⟨g⟩ms ≼ ks⟨h⟩ms"
using 1 2 3 4 by simp
finally show ?thesis
by simp
qed
text ‹
The Kleene star induction laws hold for matrices with a single entry on the diagonal.
The matrix ‹g› can actually contain a whole row/colum at the appropriate index.
›
lemma restrict_star_left_induct:
fixes f g :: "('a::finite,'b::kleene_algebra) square"
shows "distinct ms ⟹ [l]⟨f⟩[l] ⊙ [l]⟨g⟩ms ≼ [l]⟨g⟩ms ⟹ [l]⟨star o f⟩[l] ⊙ [l]⟨g⟩ms ≼ [l]⟨g⟩ms"
proof (induct ms)
case Nil thus ?case
by (simp add: restrict_empty_right)
next
case (Cons m ms)
assume 1: "distinct ms ⟹ [l]⟨f⟩[l] ⊙ [l]⟨g⟩ms ≼ [l]⟨g⟩ms ⟹ [l]⟨star o f⟩[l] ⊙ [l]⟨g⟩ms ≼ [l]⟨g⟩ms"
assume 2: "distinct (m#ms)"
assume 3: "[l]⟨f⟩[l] ⊙ [l]⟨g⟩(m#ms) ≼ [l]⟨g⟩(m#ms)"
have 4: "[l]⟨f⟩[l] ⊙ [l]⟨g⟩[m] ≼ [l]⟨g⟩[m] ∧ [l]⟨f⟩[l] ⊙ [l]⟨g⟩ms ≼ [l]⟨g⟩ms"
using 2 3
by (metis distinct.simps(2) distinct_singleton matrix_semilattice_sup.le_sup_iff
restrict_nonempty_product_less_eq)
hence 5: "[l]⟨star o f⟩[l] ⊙ [l]⟨g⟩ms ≼ [l]⟨g⟩ms"
using 1 2 by simp
have "f (l,l) * g (l,m) ≤ g (l,m)"
using 4 by (metis restrict_singleton_product restrict_singleton less_eq_matrix_def)
hence 6: "(f (l,l))⇧⋆ * g (l,m) ≤ g (l,m)"
by (simp add: star_left_induct_mult)
have "[l]⟨star o f⟩[l] ⊙ [l]⟨g⟩[m] ≼ [l]⟨g⟩[m]"
proof (unfold less_eq_matrix_def, rule allI, rule prod_cases)
fix i j
have "([l]⟨star o f⟩[l] ⊙ [l]⟨g⟩[m]) (i,j) = (⨆⇩k ([l]⟨star o f⟩[l]) (i,k) * ([l]⟨g⟩[m]) (k,j))"
by (simp add: times_matrix_def)
also have "... = (⨆⇩k (if i = l ∧ k = l then (f (i,k))⇧⋆ else bot) * (if k = l ∧ j = m then g (k,j) else bot))"
by (simp add: restrict_singleton o_def)
also have "... = (⨆⇩k if k = l then (if i = l then (f (i,k))⇧⋆ else bot) * (if j = m then g (k,j) else bot) else bot)"
by (rule sup_monoid.sum.cong) auto
also have "... = (if i = l then (f (i,l))⇧⋆ else bot) * (if j = m then g (l,j) else bot)"
by simp
also have "... = (if i = l ∧ j = m then (f (l,l))⇧⋆ * g (l,m) else bot)"
by simp
also have "... ≤ ([l]⟨g⟩[m]) (i,j)"
using 6 by (simp add: restrict_singleton)
finally show "([l]⟨star o f⟩[l] ⊙ [l]⟨g⟩[m]) (i,j) ≤ ([l]⟨g⟩[m]) (i,j)"
.
qed
thus "[l]⟨star o f⟩[l] ⊙ [l]⟨g⟩(m#ms) ≼ [l]⟨g⟩(m#ms)"
using 2 5 by (metis (no_types, opaque_lifting) matrix_idempotent_semiring.mult_left_dist_sup matrix_semilattice_sup.sup.mono restrict_nonempty_right)
qed
lemma restrict_star_right_induct:
fixes f g :: "('a::finite,'b::kleene_algebra) square"
shows "distinct ms ⟹ ms⟨g⟩[l] ⊙ [l]⟨f⟩[l] ≼ ms⟨g⟩[l] ⟹ ms⟨g⟩[l] ⊙ [l]⟨star o f⟩[l] ≼ ms⟨g⟩[l]"
proof (induct ms)
case Nil thus ?case
by (simp add: restrict_empty_left)
next
case (Cons m ms)
assume 1: "distinct ms ⟹ ms⟨g⟩[l] ⊙ [l]⟨f⟩[l] ≼ ms⟨g⟩[l] ⟹ ms⟨g⟩[l] ⊙ [l]⟨star o f⟩[l] ≼ ms⟨g⟩[l]"
assume 2: "distinct (m#ms)"
assume 3: "(m#ms)⟨g⟩[l] ⊙ [l]⟨f⟩[l] ≼ (m#ms)⟨g⟩[l]"
have 4: "[m]⟨g⟩[l] ⊙ [l]⟨f⟩[l] ≼ [m]⟨g⟩[l] ∧ ms⟨g⟩[l] ⊙ [l]⟨f⟩[l] ≼ ms⟨g⟩[l]"
using 2 3
by (metis distinct.simps(2) distinct_singleton matrix_semilattice_sup.le_sup_iff
restrict_nonempty_product_less_eq)
hence 5: "ms⟨g⟩[l] ⊙ [l]⟨star o f⟩[l] ≼ ms⟨g⟩[l]"
using 1 2 by simp
have "g (m,l) * f (l,l) ≤ g (m,l)"
using 4 by (metis restrict_singleton_product restrict_singleton less_eq_matrix_def)
hence 6: "g (m,l) * (f (l,l))⇧⋆ ≤ g (m,l)"
by (simp add: star_right_induct_mult)
have "[m]⟨g⟩[l] ⊙ [l]⟨star o f⟩[l] ≼ [m]⟨g⟩[l]"
proof (unfold less_eq_matrix_def, rule allI, rule prod_cases)
fix i j
have "([m]⟨g⟩[l] ⊙ [l]⟨star o f⟩[l]) (i,j) = (⨆⇩k ([m]⟨g⟩[l]) (i,k) * ([l]⟨star o f⟩[l]) (k,j))"
by (simp add: times_matrix_def)
also have "... = (⨆⇩k (if i = m ∧ k = l then g (i,k) else bot) * (if k = l ∧ j = l then (f (k,j))⇧⋆ else bot))"
by (simp add: restrict_singleton o_def)
also have "... = (⨆⇩k if k = l then (if i = m then g (i,k) else bot) * (if j = l then (f (k,j))⇧⋆ else bot) else bot)"
by (rule sup_monoid.sum.cong) auto
also have "... = (if i = m then g (i,l) else bot) * (if j = l then (f (l,j))⇧⋆ else bot)"
by simp
also have "... = (if i = m ∧ j = l then g (m,l) * (f (l,l))⇧⋆ else bot)"
by simp
also have "... ≤ ([m]⟨g⟩[l]) (i,j)"
using 6 by (simp add: restrict_singleton)
finally show "([m]⟨g⟩[l] ⊙ [l]⟨star o f⟩[l]) (i,j) ≤ ([m]⟨g⟩[l]) (i,j)"
.
qed
thus "(m#ms)⟨g⟩[l] ⊙ [l]⟨star o f⟩[l] ≼ (m#ms)⟨g⟩[l]"
using 2 5
by (metis matrix_idempotent_semiring.mult_right_dist_sup
matrix_idempotent_semiring.semiring.add_mono restrict_nonempty_left)
qed
lemma restrict_pp:
fixes f :: "('a,'b::p_algebra) square"
shows "ks⟨⊖⊖f⟩ls = ⊖⊖(ks⟨f⟩ls)"
by (unfold restrict_matrix_def uminus_matrix_def) auto
lemma pp_star_commute:
fixes f :: "('a,'b::stone_kleene_relation_algebra) square"
shows "⊖⊖(star o f) = star o ⊖⊖f"
by (simp add: uminus_matrix_def o_def pp_dist_star)
subsection ‹Matrices form a Kleene Algebra›
text ‹
Matrices over Kleene algebras form a Kleene algebra using Conway's construction.
It remains to prove one unfold and two induction axioms of the Kleene star.
Each proof is by induction over the size of the matrix represented by an index list.
›