diff --git a/thys/Amortized_Complexity/Splay_Tree_Analysis.thy b/thys/Amortized_Complexity/Splay_Tree_Analysis.thy --- a/thys/Amortized_Complexity/Splay_Tree_Analysis.thy +++ b/thys/Amortized_Complexity/Splay_Tree_Analysis.thy @@ -1,432 +1,432 @@ subsection "Splay Tree Analysis" theory Splay_Tree_Analysis imports Splay_Tree_Analysis_Base Amortized_Framework begin subsubsection "Analysis of splay" definition A_splay :: "'a::linorder \ 'a tree \ real" where "A_splay a t = T_splay a t + \(splay a t) - \ t" text\The following lemma is an attempt to prove a generic lemma that covers both zig-zig cases. However, the lemma is not as nice as one would like. Hence it is used only once, as a demo. Ideally the lemma would involve function @{const A_splay}, but that is impossible because this involves @{const splay} and thus depends on the ordering. We would need a truly symmetric version of @{const splay} that takes the ordering as an explicit argument. Then we could define all the symmetric cases by one final equation -@{term"splay2 less t = splay2 (not o less) (mirror t)"}. +\<^prop>\splay2 less t = splay2 (\x y. Not (less x y)) (mirror t)\. This would simplify the code and the proofs.\ lemma zig_zig: fixes lx x rx lb b rb a ra u lb1 lb2 defines [simp]: "X == Node lx (x) rx" defines[simp]: "B == Node lb b rb" defines [simp]: "t == Node B a ra" defines [simp]: "A' == Node rb a ra" defines [simp]: "t' == Node lb1 u (Node lb2 b A')" assumes hyps: "lb \ \\" and IH: "T_splay x lb + \ lb1 + \ lb2 - \ lb \ 2 * \ lb - 3 * \ X + 1" and prems: "size lb = size lb1 + size lb2 + 1" "X \ subtrees lb" shows "T_splay x lb + \ t' - \ t \ 3 * (\ t - \ X)" proof - define B' where [simp]: "B' = Node lb2 b A'" have "T_splay x lb + \ t' - \ t = T_splay x lb + \ lb1 + \ lb2 - \ lb + \ B' + \ A' - \ B" using prems by(auto simp: A_splay_def size_if_splay algebra_simps in_set_tree_if split: tree.split) also have "\ \ 2 * \ lb + \ B' + \ A' - \ B - 3 * \ X + 1" using IH prems(2) by(auto simp: algebra_simps) also have "\ \ \ lb + \ B' + \ A' - 3 * \ X + 1" by(simp) also have "\ \ \ B' + 2 * \ t - 3 * \ X " using prems ld_ld_1_less[of "size1 lb" "size1 A'"] by(simp add: size_if_splay) also have "\ \ 3 * \ t - 3 * \ X" using prems by(simp add: size_if_splay) finally show ?thesis by simp qed lemma A_splay_ub: "\ bst t; Node l x r : subtrees t \ \ A_splay x t \ 3 * (\ t - \(Node l x r)) + 1" proof(induction x t rule: splay.induct) case 1 thus ?case by simp next case 2 thus ?case by (auto simp: A_splay_def) next case 4 hence False by(fastforce dest: in_set_tree_if) thus ?case .. next case 5 hence False by(fastforce dest: in_set_tree_if) thus ?case .. next case 7 hence False by(fastforce dest: in_set_tree_if) thus ?case .. next case 10 hence False by(fastforce dest: in_set_tree_if) thus ?case .. next case 12 hence False by(fastforce dest: in_set_tree_if) thus ?case .. next case 13 hence False by(fastforce dest: in_set_tree_if) thus ?case .. next case (3 x b A B CD) (* A readable proof *) let ?t = "\\A, x, B\, b, CD\" let ?t' = "\A, x, \B, b, CD\\" have *: "l = A \ r = B" using "3.prems" by(fastforce dest: in_set_tree_if) have "A_splay x ?t = 1 + \ ?t' - \ ?t" using "3.hyps" by (simp add: A_splay_def) also have "\ = 1 + \ ?t' + \ \B, b, CD\ - \ ?t - \ \A, x, B\" by(simp) also have "\ = 1 + \ \B, b, CD\ - \ \A, x, B\" by(simp) also have "\ \ 1 + \ ?t - \(Node A x B)" using log_le_cancel_iff[of 2 "size1(Node B b CD)" "size1 ?t"] by (simp) also have "\ \ 1 + 3 * (\ ?t - \(Node A x B))" using log_le_cancel_iff[of 2 "size1(Node A x B)" "size1 ?t"] by (simp) finally show ?case using * by simp next case (9 b x AB C D) (* An automatic proof *) let ?A = "\AB, b, \C, x, D\\" have "x \ set_tree AB" using "9.prems"(1) by auto with 9 show ?case using log_le_cancel_iff[of 2 "size1(Node AB b C)" "size1 ?A"] log_le_cancel_iff[of 2 "size1(Node C x D)" "size1 ?A"] by (auto simp: A_splay_def algebra_simps simp del:log_le_cancel_iff) next case (6 x a b A B C) hence *: "\l, x, r\ \ subtrees A" by(fastforce dest: in_set_tree_if) obtain A1 a' A2 where sp: "splay x A = Node A1 a' A2" using splay_not_Leaf[OF \A \ Leaf\] by blast let ?X = "Node l x r" let ?AB = "Node A a B" let ?ABC = "Node ?AB b C" let ?A' = "Node A1 a' A2" let ?BC = "Node B b C" let ?A2BC = "Node A2 a ?BC" let ?A1A2BC = "Node A1 a' ?A2BC" have 0: "\ ?A1A2BC = \ ?ABC" using sp by(simp add: size_if_splay) have 1: "\ ?A1A2BC - \ ?ABC = \ A1 + \ A2 + \ ?A2BC + \ ?BC - \ A - \ ?AB" using 0 by (simp) have "A_splay x ?ABC = T_splay x A + 1 + \ ?A1A2BC - \ ?ABC" using "6.hyps" sp by(simp add: A_splay_def) also have "\ = T_splay x A + 1 + \ A1 + \ A2 + \ ?A2BC + \ ?BC - \ A - \ ?AB" using 1 by simp also have "\ = T_splay x A + \ ?A' - \ ?A' - \ A + \ ?A2BC + \ ?BC - \ ?AB + 1" by(simp) also have "\ = A_splay x A + \ ?A2BC + \ ?BC - \ ?AB - \ ?A' + 1" using sp by(simp add: A_splay_def) also have "\ \ 3 * \ A + \ ?A2BC + \ ?BC - \ ?AB - \ ?A' - 3 * \ ?X + 2" using "6.IH" "6.prems"(1) * by(simp) also have "\ = 2 * \ A + \ ?A2BC + \ ?BC - \ ?AB - 3 * \ ?X + 2" using sp by(simp add: size_if_splay) also have "\ < \ A + \ ?A2BC + \ ?BC - 3 * \ ?X + 2" by(simp) also have "\ < \ ?A2BC + 2 * \ ?ABC - 3 * \ ?X + 1" using sp ld_ld_1_less[of "size1 A" "size1 ?BC"] by(simp add: size_if_splay) also have "\ < 3 * \ ?ABC - 3 * \ ?X + 1" using sp by(simp add: size_if_splay) finally show ?case by simp next case (8 a x b B A C) hence *: "\l, x, r\ \ subtrees B" by(fastforce dest: in_set_tree_if) obtain B1 b' B2 where sp: "splay x B = Node B1 b' B2" using splay_not_Leaf[OF \B \ Leaf\] by blast let ?X = "Node l x r" let ?AB = "Node A a B" let ?ABC = "Node ?AB b C" let ?B' = "Node B1 b' B2" let ?AB1 = "Node A a B1" let ?B2C = "Node B2 b C" let ?AB1B2C = "Node ?AB1 b' ?B2C" have 0: "\ ?AB1B2C = \ ?ABC" using sp by(simp add: size_if_splay) have 1: "\ ?AB1B2C - \ ?ABC = \ B1 + \ B2 + \ ?AB1 + \ ?B2C - \ B - \ ?AB" using 0 by (simp) have "A_splay x ?ABC = T_splay x B + 1 + \ ?AB1B2C - \ ?ABC" using "8.hyps" sp by(simp add: A_splay_def) also have "\ = T_splay x B + 1 + \ B1 + \ B2 + \ ?AB1 + \ ?B2C - \ B - \ ?AB" using 1 by simp also have "\ = T_splay x B + \ ?B' - \ ?B' - \ B + \ ?AB1 + \ ?B2C - \ ?AB + 1" by simp also have "\ = A_splay x B + \ ?AB1 + \ ?B2C - \ ?AB - \ ?B' + 1" using sp by (simp add: A_splay_def) also have "\ \ 3 * \ B + \ ?AB1 + \ ?B2C - \ ?AB - \ ?B' - 3 * \ ?X + 2" using "8.IH" "8.prems"(1) * by(simp) also have "\ = 2 * \ B + \ ?AB1 + \ ?B2C - \ ?AB - 3 * \ ?X + 2" using sp by(simp add: size_if_splay) also have "\ < \ B + \ ?AB1 + \ ?B2C - 3 * \ ?X + 2" by(simp) also have "\ < \ B + 2 * \ ?ABC - 3 * \ ?X + 1" using sp ld_ld_1_less[of "size1 ?AB1" "size1 ?B2C"] by(simp add: size_if_splay) also have "\ < 3 * \ ?ABC - 3 * \ ?X + 1" by(simp) finally show ?case by simp next case (11 b x c C A D) hence *: "\l, x, r\ \ subtrees C" by(fastforce dest: in_set_tree_if) obtain C1 c' C2 where sp: "splay x C = Node C1 c' C2" using splay_not_Leaf[OF \C \ Leaf\] by blast let ?X = "Node l x r" let ?CD = "Node C c D" let ?ACD = "Node A b ?CD" let ?C' = "Node C1 c' C2" let ?C2D = "Node C2 c D" let ?AC1 = "Node A b C1" have "A_splay x ?ACD = A_splay x C + \ ?C2D + \ ?AC1 - \ ?CD - \ ?C' + 1" using "11.hyps" sp by(auto simp: A_splay_def size_if_splay algebra_simps split: tree.split) also have "\ \ 3 * \ C + \ ?C2D + \ ?AC1 - \ ?CD - \ ?C' - 3 * \ ?X + 2" using "11.IH" "11.prems"(1) * by(auto simp: algebra_simps) also have "\ = 2 * \ C + \ ?C2D + \ ?AC1 - \ ?CD - 3 * \ ?X + 2" using sp by(simp add: size_if_splay) also have "\ \ \ C + \ ?C2D + \ ?AC1 - 3 * \ ?X + 2" by(simp) also have "\ \ \ C + 2 * \ ?ACD - 3 * \ ?X + 1" using sp ld_ld_1_less[of "size1 ?C2D" "size1 ?AC1"] by(simp add: size_if_splay algebra_simps) also have "\ \ 3 * \ ?ACD - 3 * \ ?X + 1" by(simp) finally show ?case by simp next case (14 a x b CD A B) hence 0: "x \ set_tree B \ x \ set_tree A" using "14.prems"(1) \b by(auto) hence 1: "x \ set_tree CD" using "14.prems" \b \a by (auto) obtain C c D where sp: "splay x CD = Node C c D" using splay_not_Leaf[OF \CD \ Leaf\] by blast from zig_zig[of CD x D C l r _ b B a A] 14 sp 0 show ?case by(auto simp: A_splay_def size_if_splay algebra_simps) (* The explicit version: have "A_splay x ?A = A_splay x ?R + \ ?B' + \ ?A' - \ ?B - \ ?R' + 1" using "14.prems" 1 sp by(auto simp: A_splay_def size_if_splay algebra_simps split: tree.split) also have "\ \ 3 * \ ?R + \ ?B' + \ ?A' - \ ?B - \ ?R' - 3 * \ ?X + 2" using 14 0 by(auto simp: algebra_simps) also have "\ = 2 * \ rb + \ ?B' + \ ?A' - \ ?B - 3 * \ ?X + 2" using sp by(simp add: size_if_splay) also have "\ \ \ ?R + \ ?B' + \ ?A' - 3 * \ ?X + 2" by(simp) also have "\ \ \ ?B' + 2 * \ ?A - 3 * \ ?X + 1" using sp ld_ld_1_less[of "size1 ?R" "size1 ?A'"] by(simp add: size_if_splay algebra_simps) also have "\ \ 3 * \ ?A - 3 * \ ?X + 1" using sp by(simp add: size_if_splay) finally show ?case by simp *) qed lemma A_splay_ub2: assumes "bst t" "x : set_tree t" shows "A_splay x t \ 3 * (\ t - 1) + 1" proof - from assms(2) obtain l r where N: "Node l x r : subtrees t" by (metis set_treeE) have "A_splay x t \ 3 * (\ t - \(Node l x r)) + 1" by(rule A_splay_ub[OF assms(1) N]) also have "\ \ 3 * (\ t - 1) + 1" by(simp add: field_simps) finally show ?thesis . qed lemma A_splay_ub3: assumes "bst t" shows "A_splay x t \ 3 * \ t + 1" proof cases assume "t = Leaf" thus ?thesis by(simp add: A_splay_def) next assume "t \ Leaf" from ex_in_set_tree[OF this assms] obtain x' where a': "x' \ set_tree t" "splay x' t = splay x t" "T_splay x' t = T_splay x t" by blast show ?thesis using A_splay_ub2[OF assms a'(1)] by(simp add: A_splay_def a') qed subsubsection "Analysis of insert" lemma amor_insert: assumes "bst t" shows "T_insert x t + \(Splay_Tree.insert x t) - \ t \ 4 * log 2 (size1 t) + 3" (is "?l \ ?r") proof cases assume "t = Leaf" thus ?thesis by(simp add: T_insert_def) next assume "t \ Leaf" then obtain l e r where [simp]: "splay x t = Node l e r" by (metis tree.exhaust splay_Leaf_iff) let ?t = "real(T_splay x t)" let ?Plr = "\ l + \ r" let ?Ps = "\ t" let ?slr = "real(size1 l) + real(size1 r)" let ?LR = "log 2 (1 + ?slr)" have opt: "?t + \ (splay x t) - ?Ps \ 3 * log 2 (real (size1 t)) + 1" using A_splay_ub3[OF \bst t\, simplified A_splay_def, of x] by (simp) from less_linear[of e x] show ?thesis proof (elim disjE) assume "e=x" have nneg: "log 2 (1 + real (size t)) \ 0" by simp thus ?thesis using \t \ Leaf\ opt \e=x\ apply(simp add: T_insert_def algebra_simps) using nneg by arith next let ?L = "log 2 (real(size1 l) + 1)" assume "e < x" hence "e \ x" by simp hence "?l = (?t + ?Plr - ?Ps) + ?L + ?LR + 1" using \t \ Leaf\ \e by(simp add: T_insert_def) also have "?t + ?Plr - ?Ps \ 2 * log 2 ?slr + 1" using opt size_splay[of x t,symmetric] by(simp) also have "?L \ log 2 ?slr" by(simp) also have "?LR \ log 2 ?slr + 1" proof - have "?LR \ log 2 (2 * ?slr)" by (simp add:) also have "\ \ log 2 ?slr + 1" by (simp add: log_mult del:distrib_left_numeral) finally show ?thesis . qed finally show ?thesis using size_splay[of x t,symmetric] by (simp) next let ?R = "log 2 (2 + real(size r))" assume "x < e" hence "e \ x" by simp hence "?l = (?t + ?Plr - ?Ps) + ?R + ?LR + 1" using \t \ Leaf\ \x < e\ by(simp add: T_insert_def) also have "?t + ?Plr - ?Ps \ 2 * log 2 ?slr + 1" using opt size_splay[of x t,symmetric] by(simp) also have "?R \ log 2 ?slr" by(simp) also have "?LR \ log 2 ?slr + 1" proof - have "?LR \ log 2 (2 * ?slr)" by (simp add:) also have "\ \ log 2 ?slr + 1" by (simp add: log_mult del:distrib_left_numeral) finally show ?thesis . qed finally show ?thesis using size_splay[of x t, symmetric] by simp qed qed subsubsection "Analysis of delete" definition A_splay_max :: "'a::linorder tree \ real" where "A_splay_max t = T_splay_max t + \(splay_max t) - \ t" lemma A_splay_max_ub: "t \ Leaf \ A_splay_max t \ 3 * (\ t - 1) + 1" proof(induction t rule: splay_max.induct) case 1 thus ?case by (simp) next case (2 A) thus ?case using one_le_log_cancel_iff[of 2 "size1 A + 1"] by (simp add: A_splay_max_def del: one_le_log_cancel_iff) next case (3 l b rl c rr) show ?case proof cases assume "rr = Leaf" thus ?thesis using one_le_log_cancel_iff[of 2 "1 + size1 rl"] one_le_log_cancel_iff[of 2 "1 + size1 l + size1 rl"] log_le_cancel_iff[of 2 "size1 l + size1 rl" "1 + size1 l + size1 rl"] by (auto simp: A_splay_max_def field_simps simp del: log_le_cancel_iff one_le_log_cancel_iff) next assume "rr \ Leaf" then obtain l' u r' where sp: "splay_max rr = Node l' u r'" using splay_max_Leaf_iff tree.exhaust by blast hence 1: "size rr = size l' + size r' + 1" using size_splay_max[of rr,symmetric] by(simp) let ?C = "Node rl c rr" let ?B = "Node l b ?C" let ?B' = "Node l b rl" let ?C' = "Node ?B' c l'" have "A_splay_max ?B = A_splay_max rr + \ ?B' + \ ?C' - \ rr - \ ?C + 1" using "3.prems" sp 1 by(auto simp add: A_splay_max_def) also have "\ \ 3 * (\ rr - 1) + \ ?B' + \ ?C' - \ rr - \ ?C + 2" using 3 \rr \ Leaf\ by auto also have "\ = 2 * \ rr + \ ?B' + \ ?C' - \ ?C - 1" by simp also have "\ \ \ rr + \ ?B' + \ ?C' - 1" by simp also have "\ \ 2 * \ ?B + \ ?C' - 2" using ld_ld_1_less[of "size1 ?B'" "size1 rr"] by(simp add:) also have "\ \ 3 * \ ?B - 2" using 1 by simp finally show ?case by simp qed qed lemma A_splay_max_ub3: "A_splay_max t \ 3 * \ t + 1" proof cases assume "t = Leaf" thus ?thesis by(simp add: A_splay_max_def) next assume "t \ Leaf" show ?thesis using A_splay_max_ub[OF \t \ Leaf\] by(simp) qed lemma amor_delete: assumes "bst t" shows "T_delete a t + \(Splay_Tree.delete a t) - \ t \ 6 * log 2 (size1 t) + 3" proof (cases t) case Leaf thus ?thesis by(simp add: Splay_Tree.delete_def T_delete_def) next case [simp]: (Node ls x rs) then obtain l e r where sp[simp]: "splay a (Node ls x rs) = Node l e r" by (metis tree.exhaust splay_Leaf_iff) let ?t = "real(T_splay a t)" let ?Plr = "\ l + \ r" let ?Ps = "\ t" let ?slr = "real(size1 l) + real(size1 r)" let ?LR = "log 2 (1 + ?slr)" let ?lslr = "log 2 (real (size ls) + (real (size rs) + 2))" have "?lslr \ 0" by simp have opt: "?t + \ (splay a t) - ?Ps \ 3 * log 2 (real (size1 t)) + 1" using A_splay_ub3[OF \bst t\, simplified A_splay_def, of a] by (simp add: field_simps) show ?thesis proof (cases "e=a") case False thus ?thesis using opt apply(simp add: Splay_Tree.delete_def T_delete_def field_simps) using \?lslr \ 0\ by arith next case [simp]: True show ?thesis proof (cases l) case Leaf have 1: "log 2 (real (size r) + 2) \ 0" by(simp) show ?thesis using Leaf opt apply(simp add: Splay_Tree.delete_def T_delete_def field_simps) using 1 \?lslr \ 0\ by arith next case (Node ll y lr) then obtain l' y' r' where [simp]: "splay_max (Node ll y lr) = Node l' y' r'" using splay_max_Leaf_iff tree.exhaust by blast have "bst l" using bst_splay[OF \bst t\, of a] by simp have "\ r' \ 0" apply (induction r') by (auto) have optm: "real(T_splay_max l) + \ (splay_max l) - \ l \ 3 * \ l + 1" using A_splay_max_ub3[of l, simplified A_splay_max_def] by (simp add: field_simps Node) have 1: "log 2 (2+(real(size l')+real(size r))) \ log 2 (2+(real(size l)+real(size r)))" using size_splay_max[of l] Node by simp have 2: "log 2 (2 + (real (size l') + real (size r'))) \ 0" by simp have 3: "log 2 (size1 l' + size1 r) \ log 2 (size1 l' + size1 r') + log 2 ?slr" apply simp using 1 2 by arith have 4: "log 2 (real(size ll) + (real(size lr) + 2)) \ ?lslr" using size_if_splay[OF sp] Node by simp show ?thesis using add_mono[OF opt optm] Node 3 apply(simp add: Splay_Tree.delete_def T_delete_def field_simps) using 4 \\ r' \ 0\ by arith qed qed qed subsubsection "Overall analysis" fun U where "U Empty [] = 1" | "U (Splay _) [t] = 3 * log 2 (size1 t) + 1" | "U (Insert _) [t] = 4 * log 2 (size1 t) + 3" | "U (Delete _) [t] = 6 * log 2 (size1 t) + 3" interpretation Amortized where arity = arity and exec = exec and inv = bst and cost = cost and \ = \ and U = U proof (standard, goal_cases) case (1 ss f) show ?case proof (cases f) case Empty thus ?thesis using 1 by auto next case (Splay a) then obtain t where "ss = [t]" "bst t" using 1 by auto with Splay bst_splay[OF \bst t\, of a] show ?thesis by (auto split: tree.split) next case (Insert a) then obtain t where "ss = [t]" "bst t" using 1 by auto with bst_splay[OF \bst t\, of a] Insert show ?thesis by (auto simp: splay_bstL[OF \bst t\] splay_bstR[OF \bst t\] split: tree.split) next case (Delete a) then obtain t where "ss = [t]" "bst t" using 1 by auto with 1 Delete show ?thesis by(simp add: bst_delete) qed next case (2 t) thus ?case by (induction t) auto next case (3 ss f) show ?case (is "?l \ ?r") proof(cases f) case Empty thus ?thesis using 3(2) by(simp add: A_splay_def) next case (Splay a) then obtain t where "ss = [t]" "bst t" using 3 by auto thus ?thesis using Splay A_splay_ub3[OF \bst t\] by(simp add: A_splay_def) next case [simp]: (Insert a) then obtain t where [simp]: "ss = [t]" and "bst t" using 3 by auto thus ?thesis using amor_insert[of t a] by auto next case [simp]: (Delete a) then obtain t where [simp]: "ss = [t]" and "bst t" using 3 by auto thus ?thesis using amor_delete[of t a] by auto qed qed end diff --git a/thys/BDD/General.thy b/thys/BDD/General.thy --- a/thys/BDD/General.thy +++ b/thys/BDD/General.thy @@ -1,1912 +1,1912 @@ (* Title: BDD Author: Veronika Ortner and Norbert Schirmer, 2004 Maintainer: Norbert Schirmer, norbert.schirmer at web de License: LGPL *) (* General.thy Copyright (C) 2004-2008 Veronika Ortner and Norbert Schirmer Some rights reserved, TU Muenchen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) section \General Lemmas on BDD Abstractions\ theory General imports BinDag begin definition subdag_eq:: "dag \ dag \ bool" where "subdag_eq t\<^sub>1 t\<^sub>2 = (t\<^sub>1 = t\<^sub>2 \ subdag t\<^sub>1 t\<^sub>2)" (*"subtree_eq Tip t = (if t = Tip then True else False)" "subtree_eq (Node l a r) t = (t=(Node l a r) \ subtree_eq l t \ subtree_eq r t)"*) primrec root :: "dag \ ref" where "root Tip = Null" | "root (Node l a r) = a" fun isLeaf :: "dag \ bool" where "isLeaf Tip = False" | "isLeaf (Node Tip v Tip) = True" | "isLeaf (Node (Node l v\<^sub>1 r) v\<^sub>2 Tip) = False" | "isLeaf (Node Tip v\<^sub>1 (Node l v\<^sub>2 r)) = False" datatype bdt = Zero | One | Bdt_Node bdt nat bdt fun bdt_fn :: "dag \ (ref \ nat) \ bdt option" where "bdt_fn Tip = (\bdtvar . None)" | "bdt_fn (Node Tip vref Tip) = (\bdtvar . (if (bdtvar vref = 0) then Some Zero else (if (bdtvar vref = 1) then Some One else None)))" | "bdt_fn (Node Tip vref (Node l vref1 r)) = (\bdtvar . None)" | "bdt_fn (Node (Node l vref1 r) vref Tip) = (\bdtvar . None)" | "bdt_fn (Node (Node l1 vref1 r1) vref (Node l2 vref2 r2)) = (\bdtvar . (if (bdtvar vref = 0 \ bdtvar vref = 1) then None else (case (bdt_fn (Node l1 vref1 r1) bdtvar) of None \ None |(Some b1) \ (case (bdt_fn (Node l2 vref2 r2) bdtvar) of None \ None |(Some b2) \ Some (Bdt_Node b1 (bdtvar vref) b2)))))" (* Kongruenzregeln sind das Feintuning für den Simplifier (siehe Kapitel 9 im Isabelle Tutorial). Im Fall von case wird standardmäßig nur die case bedingung nicht aber die einzelnen Fälle simplifiziert, analog dazu beim if. Dies simuliert die Auswertungsstrategie einer Programmiersprache, da wird auch zunächst nur die Bedingung vereinfacht. Will man mehr so kann man die entsprechenden Kongruenz regeln dazunehmen. *) abbreviation "bdt == bdt_fn" primrec eval :: "bdt \ bool list \ bool" where "eval Zero env = False" | "eval One env = True" | "eval (Bdt_Node l v r) env = (if (env ! v) then eval r env else eval l env)" (*A given bdt is ordered if it is a One or Zero or its value is smaller than its parents value*) fun ordered_bdt:: "bdt \ bool" where "ordered_bdt Zero = True" | "ordered_bdt One = True" | "ordered_bdt (Bdt_Node (Bdt_Node l1 v1 r1) v (Bdt_Node l2 v2 r2)) = ((v1 < v) \ (v2 < v) \ (ordered_bdt (Bdt_Node l1 v1 r1)) \ (ordered_bdt (Bdt_Node l2 v2 r2)))" | "ordered_bdt (Bdt_Node (Bdt_Node l1 v1 r1) v r) = ((v1 < v) \ (ordered_bdt (Bdt_Node l1 v1 r1)))" | "ordered_bdt (Bdt_Node l v (Bdt_Node l2 v2 r2)) = ((v2 < v) \ (ordered_bdt (Bdt_Node l2 v2 r2)))" | "ordered_bdt (Bdt_Node l v r) = True" (*In case t = (Node Tip v Tip) v should have the values 0 or 1. This is not checked by this function*) fun ordered:: "dag \ (ref\nat) \ bool" where "ordered Tip = (\ var. True)" | "ordered (Node (Node l\<^sub>1 v\<^sub>1 r\<^sub>1) v (Node l\<^sub>2 v\<^sub>2 r\<^sub>2)) = (\ var. (var v\<^sub>1 < var v \ var v\<^sub>2 < var v) \ (ordered (Node l\<^sub>1 v\<^sub>1 r\<^sub>1) var) \ (ordered (Node l\<^sub>2 v\<^sub>2 r\<^sub>2) var))" | "ordered (Node Tip v Tip) = (\ var. (True))" | "ordered (Node Tip v r) = (\ var. (var (root r) < var v) \ (ordered r var))" | "ordered (Node l v Tip) = (\ var. (var (root l) < var v) \ (ordered l var))" (*Calculates maximal value in a non ordered bdt. Does not test parents of the given bdt*) primrec max_var :: "bdt \ nat" where "max_var Zero = 0" | "max_var One = 1" | "max_var (Bdt_Node l v r) = max v (max (max_var l) (max_var r))" lemma eval_zero: "\bdt (Node l v r) var = Some x; var (root (Node l v r)) = (0::nat)\ \ x = Zero" apply (cases l) apply (cases r) apply simp apply simp apply (cases r) apply simp apply simp done lemma bdt_Some_One_iff [simp]: "(bdt t var = Some One) = (\ p. t = Node Tip p Tip \ var p = 1)" apply (induct t rule: bdt_fn.induct) apply (auto split: option.splits) (*in order to split the cases Zero and One*) done lemma bdt_Some_Zero_iff [simp]: "(bdt t var = Some Zero) = (\ p. t = Node Tip p Tip \ var p = 0)" apply (induct t rule: bdt_fn.induct) apply (auto split: option.splits) done lemma bdt_Some_Node_iff [simp]: "(bdt t var = Some (Bdt_Node bdt1 v bdt2)) = (\ p l r. t = Node l p r \ bdt l var = Some bdt1 \ bdt r var = Some bdt2 \ 1 < v \ var p = v )" apply (induct t rule: bdt_fn.induct) prefer 5 apply (fastforce split: if_splits option.splits) apply auto done lemma balanced_bdt: "\ p bdt1. \ Dag p low high t; bdt t var = Some bdt1; no \ set_of t\ \ (low no = Null) = (high no = Null)" proof (induct t) case Tip then show ?case by simp next case (Node lt a rt) note NN= this have bdt1: "bdt (Node lt a rt) var = Some bdt1" by fact have no_in_t: " no \ set_of (Node lt a rt)" by fact have p_tree: "Dag p low high (Node lt a rt)" by fact from Node.prems obtain lt: "Dag (low p) low high lt" and rt: "Dag (high p) low high rt" by auto show ?case proof (cases lt) case (Node llt l rlt) note Nlt=this show ?thesis proof (cases rt) case (Node lrt r rrt) note Nrt=this from Nlt Nrt bdt1 obtain lbdt rbdt where lbdt_def: "bdt lt var = Some lbdt" and rbdt_def: "bdt rt var = Some rbdt" and bdt1_def: "bdt1 = Bdt_Node lbdt (var a) rbdt" by (auto split: if_split_asm option.splits) from no_in_t show ?thesis proof (simp, elim disjE) assume " no = a" with p_tree Nlt Nrt show ?thesis by auto next assume "no \ set_of lt" with Node.hyps lbdt_def lt show ?thesis by simp next assume "no \ set_of rt" with Node.hyps rbdt_def rt show ?thesis by simp qed next case Tip with Nlt bdt1 show ?thesis by simp qed next case Tip note ltTip=this show ?thesis proof (cases rt) case Tip with ltTip bdt1 no_in_t p_tree show ?thesis by auto next case (Node rlt r rrt) with bdt1 ltTip show ?thesis by simp qed qed qed primrec dag_map :: "(ref \ ref) \ dag \ dag" where "dag_map f Tip = Tip" | "dag_map f (Node l a r) = (Node (dag_map f l) (f a) (dag_map f r))" definition wf_marking :: "dag \ (ref \ bool) \ (ref \ bool) \ bool \ bool" where "wf_marking t mark_old mark_new marked = (case t of Tip \ mark_new = mark_old | (Node lt p rt) \ (\ n. n \ set_of t \ mark_new n = mark_old n) \ (\ n. n \ set_of t \ mark_new n = marked))" definition dag_in_levellist:: "dag \ (ref list list) \ (ref \ nat) \ bool" where "dag_in_levellist t levellist var = (t \ Tip \ (\ st. subdag_eq t st \ root st \ set (levellist ! (var (root st)))))" lemma set_of_nn: "\ Dag p low high t; n \ set_of t\ \ n \ Null" apply (induct t) apply simp apply auto done lemma subnodes_ordered [rule_format]: "\p. n \ set_of t \ Dag p low high t \ ordered t var \ var n <= var p" apply (induct t) apply simp apply (intro allI) apply (erule_tac x="low p" in allE) apply (erule_tac x="high p" in allE) apply clarsimp apply (case_tac t1) apply (case_tac t2) apply simp apply fastforce apply (case_tac t2) apply fastforce apply fastforce done lemma ordered_set_of: "\ x. \ordered t var; x \ set_of t\ \ var x <= var (root t)" apply (induct t) apply simp apply simp apply (elim disjE) apply simp apply (case_tac t1) apply simp apply (case_tac t2) apply fastforce apply fastforce apply (case_tac t2) apply simp apply (case_tac t1) apply fastforce apply fastforce done lemma dag_setofD: "\ p low high n. \ Dag p low high t; n \ set_of t \ \ (\ nt. Dag n low high nt) \ (\ nt. Dag n low high nt \ set_of nt \ set_of t)" apply (induct t) apply simp apply auto apply fastforce apply (fastforce dest: Dag_unique) apply (fastforce dest: Dag_unique) apply blast apply blast done lemma dag_setof_exD: "\Dag p low high t; n \ set_of t\ \ \ nt. Dag n low high nt" apply (simp add: dag_setofD) done lemma dag_setof_subsetD: "\Dag p low high t; n \ set_of t; Dag n low high nt\ \ set_of nt \ set_of t" apply (simp add: dag_setofD) done -lemma subdag_parentdag_low: "not <= lt \ not <= (Node lt p rt)" +lemma subdag_parentdag_low: "not <= lt \ not <= (Node lt p rt)" for not apply (cases "not = lt") apply (cases lt) apply simp apply (cases rt) apply simp apply (simp add: le_dag_def less_dag_def) apply (simp add: le_dag_def less_dag_def) apply (simp add: le_dag_def less_dag_def) apply (simp add: le_dag_def less_dag_def) done -lemma subdag_parentdag_high: "not <= rt \ not <= (Node lt p rt)" +lemma subdag_parentdag_high: "not <= rt \ not <= (Node lt p rt)" for not apply (cases "not = rt") apply (cases lt) apply simp apply (cases rt) apply simp apply (simp add: le_dag_def less_dag_def) apply (simp add: le_dag_def less_dag_def) apply (simp add: le_dag_def less_dag_def) apply (simp add: le_dag_def less_dag_def) done lemma set_of_subdag: "\ p not no. \Dag p low high t; Dag no low high not; no \ set_of t\ \ not <= t" proof (induct t) case Tip then show ?case by simp next case (Node lt po rt) note rtNode=this from Node.prems have ppo: "p=po" by simp show ?case proof (cases "no = p") case True with ppo Node.prems have "not = (Node lt po rt)" by (simp add: Dag_unique del: Dag_Ref) with Node.prems ppo show ?thesis by (simp add: subdag_eq_def) next assume " no \ p" with Node.prems have no_in_ltorrt: "no \ set_of lt \ no \ set_of rt" by simp show ?thesis proof (cases "no \ set_of lt") case True from Node.prems ppo have "Dag (low po) low high lt" by simp with Node.prems ppo True have "not <= lt" apply - apply (rule Node.hyps) apply assumption+ done with Node.prems no_in_ltorrt show ?thesis apply - apply (rule subdag_parentdag_low) apply simp done next assume "no \ set_of lt" with no_in_ltorrt have no_in_rt: "no \ set_of rt" by simp from Node.prems ppo have "Dag (high po) low high rt" by simp with Node.prems ppo no_in_rt have "not <= rt" apply - apply (rule Node.hyps) apply assumption+ done with Node.prems no_in_rt show ?thesis apply - apply (rule subdag_parentdag_high) apply simp done qed qed qed lemma children_ordered: "\ordered (Node lt p rt) var\ \ ordered lt var \ ordered rt var" proof (cases lt) case Tip note ltTip=this assume orderedNode: "ordered (Node lt p rt) var" show ?thesis proof (cases rt) case Tip note rtTip = this with ltTip show ?thesis by simp next case (Node lrt r rrt) with orderedNode ltTip show ?thesis by simp qed next case (Node llt l rlt) note ltNode=this assume orderedNode: "ordered (Node lt p rt) var" show ?thesis proof (cases rt) case Tip note rtTip = this with orderedNode ltNode show ?thesis by simp next case (Node lrt r rrt) note rtNode = this with orderedNode ltNode show ?thesis by simp qed qed -lemma ordered_subdag: "\ordered t var; not <= t\ \ ordered not var" +lemma ordered_subdag: "\ordered t var; not <= t\ \ ordered not var" for not proof (induct t) case Tip then show ?thesis by (simp add: less_dag_def le_dag_def) next case (Node lt p rt) show ?case proof (cases "not = Node lt p rt") case True with Node.prems show ?thesis by simp next assume notnt: "not \ Node lt p rt" with Node.prems have notstltorrt: "not <= lt \ not <= rt" apply - apply (simp add: less_dag_def le_dag_def) apply fastforce done from Node.prems have ord_lt: "ordered lt var" apply - apply (drule children_ordered) apply simp done from Node.prems have ord_rt: "ordered rt var" apply - apply (drule children_ordered) apply simp done show ?thesis proof (cases "not <= lt") case True with ord_lt show ?thesis apply - apply (rule Node.hyps) apply assumption+ done next assume "\ not \ lt" with notstltorrt have notinrt: "not <= rt" by simp from Node.hyps have hyprt: "\ordered rt var; not \ rt\ \ ordered not var" by simp from notinrt ord_rt show ?thesis apply - apply (rule hyprt) apply assumption+ done qed qed qed lemma subdag_ordered: "\ not no p. \ordered t var; Dag p low high t; Dag no low high not; no \ set_of t\ \ ordered not var" proof (induct t) case Tip from Tip.prems show ?case by simp next case (Node lt po rt) note nN=this show ?case proof (cases lt) case Tip note ltTip=this show ?thesis proof (cases rt) case Tip from Node.prems have ppo: "p=po" by simp from Tip ltTip Node.prems have "no=p" by simp with ppo Node.prems have "not=(Node lt po rt)" by (simp del: Dag_Ref add: Dag_unique) with Node.prems show ?thesis by simp next case (Node lrnot rn rrnot) from Node.prems ltTip Node have ord_rt: "ordered rt var" by simp from Node.prems have ppo: "p=po" by simp from Node.prems have ponN: "po \ Null" by auto with ppo ponN ltTip Node.prems have *: "Dag (high po) low high rt" by auto show ?thesis proof (cases "no=po") case True with ppo Node.prems have "not = Node lt po rt" by (simp del: Dag_Ref add: Dag_unique) with Node.prems show ?thesis by simp next case False with Node.prems ltTip have "no \ set_of rt" by simp with ord_rt * \Dag no low high not\ show ?thesis by (rule Node.hyps) qed qed next case (Node llt l rlt) note ltNode=this show ?thesis proof (cases rt) case Tip from Node.prems Tip ltNode have ord_lt: "ordered lt var" by simp from Node.prems have ppo: "p=po" by simp from Node.prems have ponN: "po \ Null" by auto with ppo ponN Tip Node.prems ltNode have *: "Dag (low po) low high lt" by auto show ?thesis proof (cases "no=po") case True with ppo Node.prems have "not = (Node lt po rt)" by (simp del: Dag_Ref add: Dag_unique) with Node.prems show ?thesis by simp next case False with Node.prems Tip have "no \ set_of lt" by simp with ord_lt * \Dag no low high not\ show ?thesis by (rule Node.hyps) qed next case (Node lrt r rrt) from Node.prems have ppo: "p=po" by simp from Node.prems Node ltNode have ord_lt: "ordered lt var" by simp from Node.prems Node ltNode have ord_rt: "ordered rt var" by simp from Node.prems have ponN: "po \ Null" by auto with ppo ponN Node Node.prems ltNode have lt_Dag: "Dag (low po) low high lt" by auto with ppo ponN Node Node.prems ltNode have rt_Dag: "Dag (high po) low high rt" by auto show ?thesis proof (cases "no = po") case True with ppo Node.prems have "not = (Node lt po rt)" by (simp del: Dag_Ref add: Dag_unique) with Node.prems show ?thesis by simp next assume "no \ po" with Node.prems have no_in_lt_or_rt: "no \ set_of lt \ no \ set_of rt" by simp show ?thesis proof (cases "no \ set_of lt") case True with ord_lt lt_Dag Node.prems show ?thesis apply - apply (rule Node.hyps) apply assumption+ done next assume " no \ set_of lt" with no_in_lt_or_rt have no_in_rt: "no \ set_of rt" by simp from Node.hyps have hyp2: "\p no not. \ordered rt var; Dag p low high rt; Dag no low high not; no \ set_of rt\ \ ordered not var" apply - apply assumption done from no_in_rt ord_rt rt_Dag Node.prems show ?thesis apply - apply (rule hyp2) apply assumption+ done qed qed qed qed qed lemma elem_set_of: "\ x st. \x \ set_of st; set_of st \ set_of t\ \ x \ set_of t" by blast (*procedure Levellist converts a dag with root p in a ref list list (levellist) with nodes of var = i in levellist ! i. In order to convert the two datastructures a dag traversal is required using a mark on nodes. m indicates the value which is assumed for a node to be marked. (\ nt. Dag n \<^bsup>\\<^esup>low \<^bsup>\\<^esup>high nt \ {\<^bsup>\\<^esup>m} = set_of (dag_map \<^bsup>\\<^esup>mark nt))*) definition wf_ll :: "dag \ ref list list \ (ref \ nat) \ bool" where "wf_ll t levellist var = ((\p. p \ set_of t \ p \ set (levellist ! var p)) \ (\k < length levellist. \p \ set (levellist ! k). p \ set_of t \ var p = k))" definition cong_eval :: "bdt \ bdt \ bool" (infix "\" 60) where "cong_eval bdt\<^sub>1 bdt\<^sub>2 = (eval bdt\<^sub>1 = eval bdt\<^sub>2)" lemma cong_eval_sym: "l \ r = r \ l" by (auto simp add: cong_eval_def) lemma cong_eval_trans: "\ l \ r; r \ t\ \ l \ t" by (simp add: cong_eval_def) lemma cong_eval_child_high: " l \ r \ r \ (Bdt_Node l v r)" apply (simp add: cong_eval_def ) apply (rule ext) apply auto done lemma cong_eval_child_low: " l \ r \ l \ (Bdt_Node l v r)" apply (simp add: cong_eval_def ) apply (rule ext) apply auto done definition null_comp :: "(ref \ ref) \ (ref \ ref) \ (ref \ ref)" (infix "\" 60) where "null_comp a b = (\ p. (if (b p) = Null then Null else ((a \ b) p)))" lemma null_comp_not_Null [simp]: "h q \ Null \ (g \ h) q = g (h q)" by (simp add: null_comp_def) lemma id_trans: "(a \ id) (b (c p)) = (a \ b) (c p)" by (simp add: null_comp_def) definition Nodes :: "nat \ ref list list \ ref set" where "Nodes i levellist = (\k\{k. k < i} . set (levellist ! k))" inductive_set Dags :: "ref set \ (ref \ ref) \ (ref \ ref) \ dag set" for "nodes" "low" "high" where DagsI: "\ set_of t \ nodes; Dag p low high t; t \ Tip\ \ t \ Dags nodes low high" lemma empty_Dags [simp]: "Dags {} low high = {}" apply rule apply rule apply (erule Dags.cases) apply (case_tac t) apply simp apply simp apply rule done definition isLeaf_pt :: "ref \ (ref \ ref) \ (ref \ ref) \ bool" where "isLeaf_pt p low high = (low p = Null \ high p = Null)" definition repNodes_eq :: "ref \ ref \ (ref \ ref) \ (ref \ ref) \ (ref \ ref) \ bool" where "repNodes_eq p q low high rep == (rep \ high) p = (rep \ high) q \ (rep \ low) p = (rep \ low) q" definition isomorphic_dags_eq :: "dag \ dag \ (ref \ nat) \ bool" where "isomorphic_dags_eq st\<^sub>1 st\<^sub>2 var = (\bdt\<^sub>1 bdt\<^sub>2. (bdt st\<^sub>1 var = Some bdt\<^sub>1 \ bdt st\<^sub>2 var = Some bdt\<^sub>2 \ (bdt\<^sub>1 = bdt\<^sub>2)) \ st\<^sub>1 = st\<^sub>2)" lemma isomorphic_dags_eq_sym: "isomorphic_dags_eq st\<^sub>1 st\<^sub>2 var = isomorphic_dags_eq st\<^sub>2 st\<^sub>1 var" by (auto simp add: isomorphic_dags_eq_def) (*consts subdags_shared :: "dag \ dag \ (ref \ nat) \ bool" defs subdags_shared_def : "subdags_shared t1 t2 var == \ st1 st2. (st1 <= t1 \ st2 <= t2) \ shared_prop st1 st2 var" consts shared :: " dag \ dag \ (ref \ nat) \ bool" defs shared_def: "shared t1 t2 var == subdags_shared t1 t1 var \ subdags_shared t2 t2 var \ subdags_shared t1 t2 var"*) definition shared :: "dag \ (ref \ nat) \ bool" where "shared t var = (\st\<^sub>1 st\<^sub>2. (st\<^sub>1 <= t \ st\<^sub>2 <= t) \ isomorphic_dags_eq st\<^sub>1 st\<^sub>2 var)" (* shared returns True if the Dag has no different subdags which represent the same bdts. Note: The two subdags can have different references and code the same bdt nevertheless! consts shared :: "dag \ (ref \ nat) \ bool" defs shared_def: "shared t bdtvar \ \ st1 st2. (subdag t st1 \ subdag t st2 \ (bdt st1 bdtvar = bdt st2 bdtvar \ st1 = st2))" consts shared_lower_levels :: "dag \ nat \ (ref \ nat) \ bool" defs shared_lower_levels_def : "shared_lower_levels t i bdtvar == \ st1 st2. (st1 < t \ st2 < t \ bdtvar (root st1) < i \ bdtvar (root st2) < i \ (bdt st1 bdtvar = bdt st2 bdtvar \ st1 = st2))" *) fun reduced :: "dag \ bool" where "reduced Tip = True" | "reduced (Node Tip v Tip) = True" | "reduced (Node l v r) = (l \ r \ reduced l \ reduced r)" primrec reduced_bdt :: "bdt \ bool" where "reduced_bdt Zero = True" | "reduced_bdt One = True" | "reduced_bdt (Bdt_Node lbdt v rbdt) = (if lbdt = rbdt then False else (reduced_bdt lbdt \ reduced_bdt rbdt))" lemma replicate_elem: "i < n ==> (replicate n x !i) = x" apply (induct n) apply simp apply (cases i) apply auto done lemma no_in_one_ll: "\wf_ll pret levellista var; i set (levellista ! i); i\j\ \ no \ set (levellista ! j) " apply (unfold wf_ll_def) apply (erule conjE) apply (rotate_tac 5) apply (frule_tac x = i and ?R= "no \ set_of pret \ var no = i" in allE) apply (erule impE) apply simp apply (rotate_tac 6) apply (erule_tac x=no in ballE) apply assumption apply simp apply (cases "no \ set (levellista ! j)") apply assumption apply (erule_tac x=j in allE) apply (erule impE) apply assumption apply (rotate_tac 7) apply (erule_tac x=no in ballE) prefer 2 apply assumption apply (elim conjE) apply (thin_tac "\q. q \ set_of pret \ q \ set (levellista ! var q)") apply fastforce done lemma nodes_in_wf_ll: "\wf_ll pret levellista var; i < length levellista; no \ set (levellista ! i)\ \ var no = i \ no \ set_of pret" apply (simp add: wf_ll_def) done lemma subelem_set_of_low: "\ p. \ x \ set_of t; x \ Null; low x \ Null; Dag p low high t \ \ (low x) \ set_of t" proof (induct t) case Tip then show ?case by simp next case (Node lt po rt) note tNode=this then have ppo: "p=po" by simp show ?case proof (cases "x=p") case True with Node.prems have lxrootlt: "low x = root lt" proof (cases lt) case Tip with True Node.prems show ?thesis by auto next case (Node llt l rlt) with Node.prems True show ?thesis by auto qed with True Node.prems have "low x \ set_of (Node lt p rt)" proof (cases lt) case Tip with lxrootlt Node.prems show ?thesis by simp next case (Node llt l rlt) with lxrootlt Node.prems show ?thesis by simp qed with ppo show ?thesis by simp next assume xnp: " x \ p" with Node.prems have "x \ set_of lt \ x \ set_of rt" by simp show ?thesis proof (cases "x \ set_of lt") case True note xinlt=this from Node.prems have "Dag (low p) low high lt" by fastforce with Node.prems True have "low x \ set_of lt" apply - apply (rule Node.hyps) apply assumption+ done with Node.prems show ?thesis by auto next assume xnotinlt: " x \ set_of lt" with xnp Node.prems have xinrt: "x \ set_of rt" by simp from Node.prems have "Dag (high p) low high rt" by fastforce with Node.prems xinrt have "low x \ set_of rt" apply - apply (rule Node.hyps) apply assumption+ done with Node.prems show ?thesis by auto qed qed qed lemma subelem_set_of_high: "\ p. \ x \ set_of t; x \ Null; high x \ Null; Dag p low high t \ \ (high x) \ set_of t" proof (induct t) case Tip then show ?case by simp next case (Node lt po rt) note tNode=this then have ppo: "p=po" by simp show ?case proof (cases "x=p") case True with Node.prems have lxrootlt: "high x = root rt" proof (cases rt) case Tip with True Node.prems show ?thesis by auto next case (Node lrt l rrt) with Node.prems True show ?thesis by auto qed with True Node.prems have "high x \ set_of (Node lt p rt)" proof (cases rt) case Tip with lxrootlt Node.prems show ?thesis by simp next case (Node lrt l rrt) with lxrootlt Node.prems show ?thesis by simp qed with ppo show ?thesis by simp next assume xnp: " x \ p" with Node.prems have "x \ set_of lt \ x \ set_of rt" by simp show ?thesis proof (cases "x \ set_of lt") case True note xinlt=this from Node.prems have "Dag (low p) low high lt" by fastforce with Node.prems True have "high x \ set_of lt" apply - apply (rule Node.hyps) apply assumption+ done with Node.prems show ?thesis by auto next assume xnotinlt: " x \ set_of lt" with xnp Node.prems have xinrt: "x \ set_of rt" by simp from Node.prems have "Dag (high p) low high rt" by fastforce with Node.prems xinrt have "high x \ set_of rt" apply - apply (rule Node.hyps) apply assumption+ done with Node.prems show ?thesis by auto qed qed qed lemma set_split: "{k. k<(Suc n)} = {k. k {n}" apply auto done lemma Nodes_levellist_subset_t: "\wf_ll t levellist var; i<= length levellist\ \ Nodes i levellist \ set_of t" proof (induct i) case 0 show ?case by (simp add: Nodes_def) next case (Suc n) from Suc.prems Suc.hyps have Nodesn_in_t: "Nodes n levellist \ set_of t" by simp from Suc.prems have "\ x \ set (levellist ! n). x \ set_of t" apply - apply (rule ballI) apply (simp add: wf_ll_def) apply (erule conjE) apply (thin_tac " \q. q \ set_of t \ q \ set (levellist ! var q)") apply (erule_tac x=n in allE) apply (erule impE) apply simp apply fastforce done with Suc.prems have "set (levellist ! n) \ set_of t" apply blast done with Suc.prems Nodesn_in_t show ?case apply (simp add: Nodes_def) apply (simp add: set_split) done qed lemma bdt_child: "\ bdt (Node (Node llt l rlt) p (Node lrt r rrt)) var = Some bdt1\ \ \ lbdt rbdt. bdt (Node llt l rlt) var = Some lbdt \ bdt (Node lrt r rrt) var = Some rbdt" by (simp split: option.splits) lemma subbdt_ex_dag_def: "\ bdt1 p. \Dag p low high t; bdt t var = Some bdt1; Dag no low high not; -no \ set_of t\ \ \ bdt2. bdt not var = Some bdt2" +no \ set_of t\ \ \ bdt2. bdt not var = Some bdt2" for not proof (induct t) case Tip then show ?case by simp next case (Node lt po rt) note pNode=this with Node.prems have p_po: "p=po" by simp show ?case proof (cases "no = po") case True note no_eq_po=this from p_po Node.prems no_eq_po have "not = (Node lt po rt)" by (simp add: Dag_unique del: Dag_Ref) with Node.prems have "bdt not var = Some bdt1" by (simp add: le_dag_def) then show ?thesis by simp next assume "no \ po" with Node.prems have no_in_lt_or_rt: "no \ set_of lt \ no \ set_of rt" by simp show ?thesis proof (cases "no \ set_of lt") case True note no_in_lt=this from Node.prems p_po have lt_dag: "Dag (low po) low high lt" by simp from Node.prems have lbdt_def: "\ lbdt. bdt lt var = Some lbdt" proof (cases lt) case Tip with Node.prems no_in_lt show ?thesis by (simp add: le_dag_def) next case (Node llt l rlt) note lNode=this show ?thesis proof (cases rt) case Tip note rNode=this with lNode Node.prems show ?thesis by simp next case (Node lrt r rrt) note rNode=this with lNode Node.prems show ?thesis by (simp split: option.splits) qed qed then obtain lbdt where "bdt lt var = Some lbdt".. with Node.prems lt_dag no_in_lt show ?thesis apply - apply (rule Node.hyps) apply assumption+ done next assume "no \ set_of lt" with no_in_lt_or_rt have no_in_rt: "no \ set_of rt" by simp from Node.prems p_po have rt_dag: "Dag (high po) low high rt" by simp from Node.hyps have hyp2: "\ rbdt. \Dag (high po) low high rt; bdt rt var = Some rbdt; Dag no low high not; no \ set_of rt\ \ \bdt2. bdt not var = Some bdt2" by simp from Node.prems have lbdt_def: "\ rbdt. bdt rt var = Some rbdt" proof (cases rt) case Tip with Node.prems no_in_rt show ?thesis by (simp add: le_dag_def) next case (Node lrt l rrt) note rNode=this show ?thesis proof (cases lt) case Tip note lTip=this with rNode Node.prems show ?thesis by simp next case (Node llt r rlt) note lNode=this with rNode Node.prems show ?thesis by (simp split: option.splits) qed qed then obtain rbdt where "bdt rt var = Some rbdt".. with Node.prems rt_dag no_in_rt show ?thesis apply - apply (rule hyp2) apply assumption+ done qed qed qed lemma subbdt_ex: "\ bdt1. \ (Node lst stp rst) <= t; bdt t var = Some bdt1\ \ \ bdt2. bdt (Node lst stp rst) var = Some bdt2" proof (induct t) case Tip then show ?case by (simp add: le_dag_def) next case (Node lt p rt) note pNode=this show ?case proof (cases "Node lst stp rst = Node lt p rt") case True with Node.prems show ?thesis by simp next assume " Node lst stp rst \ Node lt p rt" with Node.prems have "Node lst stp rst < Node lt p rt" apply (simp add: le_dag_def) apply auto done then have in_ltrt: "Node lst stp rst <= lt \ Node lst stp rst <= rt" by (simp add: less_dag_Node) show ?thesis proof (cases "Node lst stp rst <= lt") case True note in_lt=this from Node.prems have lbdt_def: "\ lbdt. bdt lt var = Some lbdt" proof (cases lt) case Tip with Node.prems in_lt show ?thesis by (simp add: le_dag_def) next case (Node llt l rlt) note lNode=this show ?thesis proof (cases rt) case Tip note rNode=this with lNode Node.prems show ?thesis by simp next case (Node lrt r rrt) note rNode=this with lNode Node.prems show ?thesis by (simp split: option.splits) qed qed then obtain lbdt where "bdt lt var = Some lbdt".. with Node.prems in_lt show ?thesis apply - apply (rule Node.hyps) apply assumption+ done next assume " \ Node lst stp rst \ lt" with in_ltrt have in_rt: "Node lst stp rst <= rt" by simp from Node.hyps have hyp2: "\ rbdt. \Node lst stp rst <= rt; bdt rt var = Some rbdt\ \ \bdt2. bdt (Node lst stp rst) var = Some bdt2" by simp from Node.prems have rbdt_def: "\ rbdt. bdt rt var = Some rbdt" proof (cases rt) case Tip with Node.prems in_rt show ?thesis by (simp add: le_dag_def) next case (Node lrt l rrt) note rNode=this show ?thesis proof (cases lt) case Tip note lNode=this with rNode Node.prems show ?thesis by simp next case (Node lrt r rrt) note lNode=this with rNode Node.prems show ?thesis by (simp split: option.splits) qed qed then obtain rbdt where "bdt rt var = Some rbdt".. with Node.prems in_rt show ?thesis apply - apply (rule hyp2) apply assumption+ done qed qed qed lemma var_ordered_children: "\ p. \ Dag p low high t; ordered t var; no \ set_of t; low no \ Null; high no \ Null\ \ var (low no) < var no \ var (high no) < var no" proof (induct t) case Tip then show ?case by simp next case (Node lt po rt) then have ppo: "p=po" by simp show ?case proof (cases "no = po") case True note no_po=this from Node.prems have "var (low po) < var po \ var (high po) < var po" proof (cases lt) case Tip note ltTip=this with Node.prems no_po ppo show ?thesis by simp next case (Node llt l rlt) note lNode=this show ?thesis proof (cases rt) case Tip note rTip=this with Node.prems no_po ppo show ?thesis by simp next case (Node lrt r rrt) note rNode=this with Node.prems ppo no_po lNode show ?thesis by (simp del: Dag_Ref) qed qed with no_po show ?thesis by simp next assume " no \ po" with Node.prems have no_in_ltrt: "no \ set_of lt \ no \ set_of rt" by simp show ?thesis proof (cases "no \ set_of lt") case True note no_in_lt=this from Node.prems ppo have lt_dag: "Dag (low po) low high lt" by simp from Node.prems have ord_lt: "ordered lt var" apply - apply (drule children_ordered) apply simp done from no_in_lt lt_dag ord_lt Node.prems show ?thesis apply - apply (rule Node.hyps) apply assumption+ done next assume " no \ set_of lt" with no_in_ltrt have no_in_rt: "no \ set_of rt" by simp from Node.prems ppo have rt_dag: "Dag (high po) low high rt" by simp from Node.hyps have hyp2: " \Dag (high po) low high rt; ordered rt var; no \ set_of rt; low no \ Null; high no \ Null\ \ var (low no) < var no \ var (high no) < var no" by simp from Node.prems have ord_rt: "ordered rt var" apply - apply (drule children_ordered) apply simp done from rt_dag ord_rt no_in_rt Node.prems show ?thesis apply - apply (rule hyp2) apply assumption+ done qed qed qed lemma nort_null_comp: assumes pret_dag: "Dag p low high pret" and prebdt_pret: "bdt pret var = Some prebdt" and nort_dag: "Dag (repc no) (repb \ low) (repb \ high) nort" and ord_pret: "ordered pret var" and wf_llb: "wf_ll pret levellistb var" and nbsll: "nb < length levellistb" and repbc_nc: "\ nt. nt \ set (levellistb ! nb) \ repb nt = repc nt" and xsnb_in_pret: "\ x \ set_of nort. var x < nb \ x \ set_of pret" shows "\ x \ set_of nort. ((repc \ low) x = (repb \ low) x \ (repc \ high) x = (repb \ high) x)" proof (rule ballI) fix x assume x_in_nort: "x \ set_of nort" with nort_dag have xnN: "x \ Null" apply - apply (rule set_of_nn [rule_format]) apply auto done from x_in_nort xsnb_in_pret have xsnb: "var x set_of pret" by blast show " (repc \ low) x = (repb \ low) x \ (repc \ high) x = (repb \ high) x" proof (cases "(low x) \ Null") case True with pret_dag prebdt_pret x_in_pret have highnN: "(high x) \ Null" apply - apply (drule balanced_bdt) apply assumption+ apply simp done from x_in_pret ord_pret highnN True have children_var_smaller: "var (low x) < var x \ var (high x) < var x" apply - apply (rule var_ordered_children) apply (rule pret_dag) apply (rule ord_pret) apply (rule x_in_pret) apply (rule True) apply (rule highnN) done with xsnb have lowxsnb: "var (low x) < nb" by arith from children_var_smaller xsnb have highxsnb: "var (high x) < nb" by arith from x_in_pret xnN True pret_dag have lowxinpret: "(low x) \ set_of pret" apply - apply (drule subelem_set_of_low) apply assumption apply (thin_tac "x \ Null") apply assumption+ done with wf_llb have "low x \ set (levellistb ! (var (low x)))" by (simp add: wf_ll_def) with wf_llb nbsll lowxsnb have "low x \ set (levellistb ! nb)" apply - apply (rule_tac ?i="(var (low x))" and ?j=nb in no_in_one_ll) apply auto done with repbc_nc have repclow: "repc (low x) = repb (low x)" by auto from x_in_pret xnN highnN pret_dag have highxinpret: "(high x) \ set_of pret" apply - apply (drule subelem_set_of_high) apply assumption apply (thin_tac "x \ Null") apply assumption+ done with wf_llb have "high x \ set (levellistb ! (var (high x)))" by (simp add: wf_ll_def) with wf_llb nbsll highxsnb have "high x \ set (levellistb ! nb)" apply - apply (rule_tac ?i="(var (high x))" and ?j=nb in no_in_one_ll) apply auto done with repbc_nc have repchigh: "repc (high x) = repb (high x)" by auto with repclow show ?thesis by (simp add: null_comp_def) next assume " \ low x \ Null" then have lowxNull: "low x = Null" by simp with pret_dag x_in_pret prebdt_pret have highxNull: "high x =Null" apply - apply (drule balanced_bdt) apply simp apply simp apply simp done from lowxNull have repclowNull: "(repc \ low) x = Null" by (simp add: null_comp_def) from lowxNull have repblowNull: "(repb \ low) x = Null" by (simp add: null_comp_def) with repclowNull have lowxrepbc: "(repc \ low) x = (repb \ low) x" by simp from highxNull have repchighNull: "(repc \ high) x = Null" by (simp add: null_comp_def) from highxNull have "(repb \ high) x = Null" by (simp add: null_comp_def) with repchighNull have highxrepbc: "(repc \ high) x = (repb \ high) x" by simp with lowxrepbc show ?thesis by simp qed qed lemma wf_ll_Nodes_pret: "\wf_ll pret levellista var; nb < length levellista; x \ Nodes nb levellista\ \ x \ set_of pret \ var x < nb" apply (simp add: wf_ll_def Nodes_def) apply (erule conjE) apply (thin_tac " \q. q \ set_of pret \ q \ set (levellista ! var q)") apply (erule exE) apply (elim conjE) apply (erule_tac x=xa in allE) apply (erule impE) apply arith apply (erule_tac x=x in ballE) apply auto done lemma bdt_Some_var1_One: "\ x. \ bdt t var = Some x; var (root t) = 1\ \ x = One \ t = (Node Tip (root t) Tip)" proof (induct t) case Tip then show ?case by simp next case (Node lt p rt) note tNode = this show ?case proof (cases lt) case Tip note ltTip=this show ?thesis proof (cases rt) case Tip note rtTip = this with ltTip Node.prems show ?thesis by auto next case (Node lrt r rrt) note rtNode=this with Node.prems ltTip show ?thesis by auto qed next case (Node llt l rlt) note ltNode=this show ?thesis proof (cases rt) case Tip with ltNode Node.prems show ?thesis by auto next case (Node lrt r rrt) note rtNode=this with ltNode Node.prems show ?thesis by auto qed qed qed lemma bdt_Some_var0_Zero: "\ x. \ bdt t var = Some x; var (root t) = 0\ \ x = Zero \ t = (Node Tip (root t) Tip)" proof (induct t) case Tip then show ?case by simp next case (Node lt p rt) note tNode = this show ?case proof (cases lt) case Tip note ltTip=this show ?thesis proof (cases rt) case Tip note rtTip = this with ltTip Node.prems show ?thesis by auto next case (Node lrt r rrt) note rtNode=this with Node.prems ltTip show ?thesis by auto qed next case (Node llt l rlt) note ltNode=this show ?thesis proof (cases rt) case Tip with ltNode Node.prems show ?thesis by auto next case (Node lrt r rrt) note rtNode=this with ltNode Node.prems show ?thesis by auto qed qed qed lemma reduced_children_parent: "\ reduced l; l= (Node llt lp rlt); reduced r; r=(Node lrt rp rrt); lp \ rp \ \ reduced (Node l p r)" by simp (*Die allgemeine Form mit i <=j \ Nodes i levellista \ Nodes j levellista wäre schöner, aber wie beweist man das? *) lemma Nodes_subset: "Nodes i levellista \ Nodes (Suc i) levellista" apply (simp add: Nodes_def) apply (simp add: set_split) done lemma Nodes_levellist: "\ wf_ll pret levellista var; nb < length levellista; p \ Nodes nb levellista\ \ p \ set (levellista ! nb)" apply (simp add: Nodes_def) apply (erule exE) apply (rule_tac i=x and j=nb in no_in_one_ll) apply auto done lemma Nodes_var_pret: "\wf_ll pret levellista var; nb < length levellista; p \ Nodes nb levellista\ \ var p < nb \ p \ set_of pret" apply (simp add: Nodes_def wf_ll_def) apply (erule conjE) apply (thin_tac "\q. q \ set_of pret \ q \ set (levellista ! var q)") apply (erule exE) apply (erule_tac x=x in allE) apply (erule impE) apply arith apply (erule_tac x=p in ballE) apply arith apply simp done lemma Dags_root_in_Nodes: assumes t_in_DagsSucnb: "t \ Dags (Nodes (Suc nb) levellista) low high" shows "\ p . Dag p low high t \ p \ Nodes (Suc nb) levellista" proof - from t_in_DagsSucnb obtain p where t_dag: "Dag p low high t" and t_subset_Nodes: "set_of t \ Nodes (Suc nb) levellista" and t_nTip: "t\ Tip" by (fastforce elim: Dags.cases) from t_dag t_nTip have "p\Null" by (cases t) auto with t_subset_Nodes t_dag have "p \ Nodes (Suc nb) levellista" by (cases t) auto with t_dag show ?thesis by auto qed lemma subdag_dag: "\ p. \Dag p low high t; st <= t\ \ \ stp. Dag stp low high st" proof (induct t) case Tip then show ?case by (simp add: less_dag_def le_dag_def) next case (Node lt po rt) note t_Node=this with Node.prems have p_po: "p=po" by simp show ?case proof (cases "st = Node lt po rt") case True note st_t=this with Node.prems show ?thesis by auto next assume st_nt: "st \ Node lt po rt" with Node.prems p_po have st_subdag_lt_rt: "st<=lt \ st <=rt" by (auto simp add:le_dag_def less_dag_def) from Node.prems p_po obtain lp rp where lt_dag: "Dag lp low high lt" and rt_dag: "Dag rp low high rt" by auto show ?thesis proof (cases "st<=lt") case True note st_lt=this with lt_dag show ?thesis apply- apply (rule Node.hyps) apply auto done next assume "\ st \ lt" with st_subdag_lt_rt have st_rt: "st <= rt" by simp from Node.hyps have rhyp: "\Dag rp low high rt; st \ rt\ \ \stp. Dag stp low high st" by simp from st_rt rt_dag show ?thesis apply - apply (rule rhyp) apply auto done qed qed qed lemma Dags_subdags: assumes t_in_Dags: "t \ Dags nodes low high" and st_t: "st <= t" and st_nTip: "st \ Tip" shows "st \ Dags nodes low high" proof - from t_in_Dags obtain p where t_dag: "Dag p low high t" and t_subset_Nodes: "set_of t \ nodes" and t_nTip: "t\ Tip" by (fastforce elim: Dags.cases) from st_t have "set_of st \ set_of t" by (simp add: le_dag_set_of) with t_subset_Nodes have st_subset_fnctNodes: "set_of st \ nodes" by blast from st_t t_dag obtain stp where "Dag stp low high st" apply - apply (drule subdag_dag) apply auto done with st_subset_fnctNodes st_nTip show ?thesis apply - apply (rule DagsI) apply auto done qed lemma Dags_Nodes_cases: assumes P_sym: "\ t1 t2. P t1 t2 var = P t2 t1 var" and dags_in_lower_levels: "\ t1 t2. \t1 \ Dags (fnct `(Nodes n levellista)) low high; t2 \ Dags (fnct `(Nodes n levellista)) low high\ \ P t1 t2 var" and dags_in_mixed_levels: "\ t1 t2. \t1 \ Dags (fnct `(Nodes n levellista)) low high; t2 \ Dags (fnct `(Nodes (Suc n) levellista)) low high; t2 \ Dags (fnct `(Nodes n levellista)) low high\ \ P t1 t2 var" and dags_in_high_level: "\ t1 t2. \t1 \ Dags (fnct `(Nodes (Suc n) levellista)) low high; t1 \ Dags (fnct `(Nodes n levellista)) low high; t2 \ Dags (fnct `(Nodes (Suc n) levellista)) low high; t2 \ Dags (fnct `(Nodes n levellista)) low high\ \ P t1 t2 var" shows "\ t1 t2. t1 \ Dags (fnct `(Nodes (Suc n) levellista)) low high \ t2 \ Dags (fnct `(Nodes (Suc n) levellista)) low high \ P t1 t2 var" proof (intro allI impI , elim conjE) fix t1 t2 assume t1_in_higher_levels: "t1 \ Dags (fnct ` Nodes (Suc n) levellista) low high" assume t2_in_higher_levels: "t2 \ Dags (fnct ` Nodes (Suc n) levellista) low high" show "P t1 t2 var" proof (cases "t1 \ Dags (fnct ` Nodes n levellista) low high") case True note t1_in_ll = this show ?thesis proof (cases "t2 \ Dags (fnct ` Nodes n levellista) low high") case True note t2_in_ll=this with t1_in_ll dags_in_lower_levels show ?thesis by simp next assume t2_notin_ll: "t2 \ Dags (fnct ` Nodes n levellista) low high" with t1_in_ll t2_in_higher_levels dags_in_mixed_levels show ?thesis by simp qed next assume t1_notin_ll: "t1 \ Dags (fnct ` Nodes n levellista) low high" show ?thesis proof (cases "t2 \ Dags (fnct ` Nodes n levellista) low high") case True note t2_in_ll=this with dags_in_mixed_levels t1_in_higher_levels t1_notin_ll P_sym show ?thesis by auto next assume t2_notin_ll: "t2 \ Dags (fnct ` Nodes n levellista) low high" with t1_notin_ll t1_in_higher_levels t2_in_higher_levels dags_in_high_level show ?thesis by simp qed qed qed lemma Null_notin_Nodes: "\Dag p low high t; nb <= length levellista; wf_ll t levellista var\ \ Null \ Nodes nb levellista" apply (simp add: Nodes_def wf_ll_def del: Dag_Ref) apply (rule allI) apply (rule impI) apply (elim conjE) apply (thin_tac "\q. P q" for P) apply (erule_tac x=x in allE) apply (erule impE) apply simp apply (erule_tac x=Null in ballE) apply (erule conjE) apply (drule set_of_nn [rule_format]) apply auto done lemma Nodes_in_pret: "\wf_ll t levellista var; nb <= length levellista\ \ Nodes nb levellista \ set_of t" apply - apply rule apply (simp add: wf_ll_def Nodes_def) apply (erule exE) apply (elim conjE) apply (thin_tac "\q. q \ set_of t \ q \ set (levellista ! var q)") apply (erule_tac x=xa in allE) apply (erule impE) apply simp apply (erule_tac x=x in ballE) apply auto done lemma restrict_root_Node: "\t \ Dags (repc `Nodes (Suc nb) levellista) (repc \ low) (repc \ high); t \ Dags (repc `Nodes nb levellista) (repc \ low) (repc \ high); ordered t var; \ no \ Nodes (Suc nb) levellista. var (repc no) <= var no \ repc (repc no) = repc no; wf_ll pret levellista var; nb < length levellista;repc `Nodes (Suc nb) levellista \ Nodes (Suc nb) levellista\ \ \ q. Dag (repc q) (repc \ low) (repc \ high) t \ q \ set (levellista ! nb)" proof (elim Dags.cases) fix p and ta :: "dag" assume t_notin_DagsNodesnb: "t \ Dags (repc ` Nodes nb levellista) (repc \ low) (repc \ high)" assume t_ta: "t = ta" assume ta_in_repc_NodesSucnb: "set_of ta \ repc ` Nodes (Suc nb) levellista" assume ta_dag: "Dag p (repc \ low) (repc \ high) ta" assume ta_nTip: "ta \ Tip" assume ord_t: "ordered t var" assume varrep_prop: "\ no \ Nodes (Suc nb) levellista. var (repc no) <= var no \ repc (repc no) = repc no" assume wf_lla: "wf_ll pret levellista var" assume nbslla: "nb < length levellista" assume repcNodes_in_Nodes: "repc `Nodes (Suc nb) levellista \ Nodes (Suc nb) levellista" from ta_nTip ta_dag have p_nNull: "p\ Null" by auto with ta_nTip ta_dag obtain lt rt where ta_Node: " ta = Node lt p rt" by auto with ta_nTip ta_dag have p_in_ta: "p \ set_of ta" by auto with ta_in_repc_NodesSucnb have p_in_repcNodes_Sucnb: "p \ repc `Nodes (Suc nb) levellista" by auto show ?thesis proof (cases "p \ repc `(set (levellista ! nb))") case True then obtain q where p_repca: "p=repc q" and a_in_llanb: "q \ set (levellista ! nb)" by auto with ta_dag t_ta show ?thesis apply - apply (rule_tac x=q in exI) apply simp done next assume p_notin_repc_llanb: "p \ repc ` set (levellista ! nb)" with p_in_repcNodes_Sucnb have p_in_repc_Nodesnb: "p \ repc `Nodes nb levellista" apply - apply (erule imageE) apply rule apply (simp add: Nodes_def) apply (simp add: Nodes_def) apply (erule exE conjE) apply (case_tac "xa=nb") apply simp apply (rule_tac x=xa in exI) apply auto done have "t \ Dags (repc `Nodes nb levellista) (repc \ low) (repc \ high)" proof - have "set_of t \ repc `Nodes nb levellista" proof (rule) fix x :: ref assume x_in_t: "x \ set_of t" with ord_t have "var x <= var (root t)" apply - apply (rule ordered_set_of) apply auto done with t_ta ta_Node have varx_varp: "var x <= var p" by auto from p_in_repc_Nodesnb obtain k where ksnb: "k < nb" and p_in_repc_llak: "p \ repc `(set (levellista ! k))" by (auto simp add: Nodes_def ImageE) then obtain q where p_repcq: "p=repc q" and q_in_llak: "q \ set (levellista ! k)" by auto from q_in_llak wf_lla nbslla ksnb have varqk: "var q = k" by (simp add: wf_ll_def) have Nodesnb_in_NodesSucnb: "Nodes nb levellista \ Nodes (Suc nb) levellista" by (rule Nodes_subset) from q_in_llak ksnb have "q \ Nodes nb levellista" by (auto simp add: Nodes_def) with varrep_prop Nodesnb_in_NodesSucnb have "var (repc q) <= var q" by auto with varqk ksnb p_repcq have "var p < nb" by auto with varx_varp have varx_snb: "var x < nb" by auto from x_in_t t_ta ta_in_repc_NodesSucnb obtain a where x_repca: "x= repc a" and a_in_NodesSucnb: "a \ Nodes (Suc nb) levellista" by auto with varrep_prop have rx_x: "repc x = x" by auto have "x \ set_of pret" proof - from wf_lla nbslla have "Nodes (Suc nb) levellista \ set_of pret" apply - apply (rule Nodes_in_pret) apply auto done with x_in_t t_ta ta_in_repc_NodesSucnb repcNodes_in_Nodes show ?thesis by auto qed with wf_lla have "x \ set (levellista ! (var x))" by (auto simp add: wf_ll_def) with varx_snb have "x \ Nodes nb levellista" by (auto simp add: Nodes_def) with rx_x show "x \ repc `Nodes nb levellista" apply - apply rule apply (subgoal_tac "x=repc x") apply auto done qed with ta_nTip ta_dag t_ta show ?thesis apply - apply (rule DagsI) apply auto done qed with t_notin_DagsNodesnb show ?thesis by auto qed qed lemma same_bdt_var: "\bdt (Node lt1 p1 rt1) var = Some bdt1; bdt (Node lt2 p2 rt2) var = Some bdt1\ \ var p1 = var p2" proof (induct bdt1) case Zero then obtain var_p1: "var p1 = 0" and var_p2: "var p2 = 0" by simp then show ?case by simp next case One then obtain var_p1: "var p1 = 1" and var_p2: "var p2 = 1" by simp then show ?case by simp next case (Bdt_Node lbdt v rbdt) then obtain var_p1: "var p1 = v" and var_p2: "var p2 = v" by simp then show ?case by simp qed lemma bdt_Some_Leaf_var_le_1: "\Dag p low high t; bdt t var = Some x; isLeaf_pt p low high\ \ var p <= 1" proof (induct t) case Tip thus ?case by simp next case (Node lt p rt) note tNode=this from Node.prems tNode show ?case apply (simp add: isLeaf_pt_def) apply (case_tac "var p = 0") apply simp apply (case_tac "var p = Suc 0") apply simp apply simp done qed lemma subnode_dag_cons: "\ p. \Dag p low high t; no \ set_of t\ \ \ not. Dag no low high not" proof (induct t) case Tip thus ?case by simp next case (Node lt q rt) with Node.prems have q_p: "p = q" by simp from Node.prems have lt_dag: "Dag (low p) low high lt" by auto from Node.prems have rt_dag: "Dag (high p) low high rt" by auto show ?case proof (cases "no \ set_of lt") case True with Node.hyps lt_dag show ?thesis by simp next assume no_notin_lt: "no \ set_of lt" show ?thesis proof (cases "no=p") case True with Node.prems q_p show ?thesis by auto next assume no_neq_p: "no \ p" with Node.prems no_notin_lt have no_in_rt: "no \ set_of rt" by simp with rt_dag Node.hyps show ?thesis by auto qed qed qed (*theorems for the proof of share_reduce_rep_list*) lemma nodes_in_taken_in_takeSucn: "no \ set (take n nodeslist) \ no \ set (take (Suc n) nodeslist) " proof - assume no_in_taken: "no \ set (take n nodeslist)" have "set (take n nodeslist) \ set (take (Suc n) nodeslist)" apply - apply (rule set_take_subset_set_take) apply simp done with no_in_taken show ?thesis by blast qed lemma ind_in_higher_take: "\n k. \n < k; n < length xs\ \ xs ! n \ set (take k xs)" apply (induct xs) apply simp apply simp apply (case_tac n) apply simp apply (case_tac k) apply simp apply simp apply simp apply (case_tac k) apply simp apply simp done lemma take_length_set: "\n. n=length xs \ set (take n xs) = set xs" apply (induct xs) apply (auto simp add: take_Cons split: nat.splits) done lemma repNodes_eq_ext_rep: "\low no \ nodeslist! n; high no \ nodeslist ! n; low sn \ nodeslist ! n; high sn \ nodeslist ! n\ \ repNodes_eq sn no low high repa = repNodes_eq sn no low high (repa(nodeslist ! n := repa (low (nodeslist ! n))))" by (simp add: repNodes_eq_def null_comp_def) lemma filter_not_empty: "\x \ set xs; P x\ \ filter P xs \ []" by (induct xs) auto lemma "x \ set (filter P xs) \ P x" by auto lemma hd_filter_in_list: "filter P xs \ [] \ hd (filter P xs) \ set xs" by (induct xs) auto lemma hd_filter_in_filter: "filter P xs \ [] \ hd (filter P xs) \ set (filter P xs)" by (induct xs) auto lemma hd_filter_prop: assumes non_empty: "filter P xs \ []" shows "P (hd (filter P xs))" proof - from non_empty have "hd (filter P xs) \ set (filter P xs)" by (rule hd_filter_in_filter) thus ?thesis by auto qed lemma index_elem: "x \ set xs \ \i\x. P x x; \a b. P x a \ P a b \ P x b; filter (P x) xs \ []\ \ hd (filter (P (hd (filter (P x) xs))) xs) = hd (filter (P x) xs)" apply (induct xs) apply simp apply (case_tac "P x a") using [[simp_depth_limit=2]] apply (simp) apply clarsimp apply (fastforce dest: hd_filter_prop) done lemma take_Suc_not_last: "\n. \x \ set (take (Suc n) xs); x\xs!n; n < length xs\ \ x \ set (take n xs)" apply (induct xs) apply simp apply (case_tac n) apply simp using [[simp_depth_limit=2]] apply fastforce done lemma P_eq_list_filter: "\x \ set xs. P x = Q x \ filter P xs = filter Q xs" apply (induct xs) apply auto done lemma hd_filter_take_more: "\n m.\filter P (take n xs) \ []; n \ m\ \ hd (filter P (take n xs)) = hd (filter P (take m xs))" apply (induct xs) apply simp apply (case_tac n) apply simp apply (case_tac m) apply simp apply clarsimp done (* consts wf_levellist :: "dag \ ref list list \ ref list list \ (ref \ nat) \ bool" defs wf_levellist_def: "wf_levellist t levellist_old levellist_new var \ case t of Tip \ levellist_old = levellist_new | (Node lt p rt) \ (\ q. q \ set_of t \ q \ set (levellist_new ! (var q))) \ (\ i \ var p. (\ prx. (levellist_new ! i) = prx@(levellist_old ! i) \ (\ pt \ set prx. pt \ set_of t \ var pt = i))) \ (\ i. (var p) < i \ (levellist_new ! i) = (levellist_old ! i)) \ (length levellist_new = length levellist_old)" *) end diff --git a/thys/Formula_Derivatives/Presburger_Formula.thy b/thys/Formula_Derivatives/Presburger_Formula.thy --- a/thys/Formula_Derivatives/Presburger_Formula.thy +++ b/thys/Formula_Derivatives/Presburger_Formula.thy @@ -1,696 +1,705 @@ section \Concrete Atomic Presburger Formulas\ (*<*) theory Presburger_Formula imports Abstract_Formula "HOL-Library.Code_Target_Int" "List-Index.List_Index" begin (*>*) declare [[coercion "of_bool :: bool \ nat"]] declare [[coercion int]] declare [[coercion_map map]] declare [[coercion_enabled]] fun len :: "nat \ nat" where \ \FIXME yet another logarithm\ "len 0 = 0" | "len (Suc 0) = 1" | "len n = Suc (len (n div 2))" lemma len_eq0_iff: "len n = 0 \ n = 0" by (induct n rule: len.induct) auto lemma len_mult2[simp]: "len (2 * x) = (if x = 0 then 0 else Suc (len x))" proof (induct x rule: len.induct) show "len (2 * Suc 0) = (if Suc 0 = 0 then 0 else Suc (len (Suc 0)))" by (simp add: numeral_eq_Suc) qed auto lemma len_mult2'[simp]: "len (x * 2) = (if x = 0 then 0 else Suc (len x))" using len_mult2 [of x] by (simp add: ac_simps) lemma len_Suc_mult2[simp]: "len (Suc (2 * x)) = Suc (len x)" proof (induct x rule: len.induct) show "len (Suc (2 * Suc 0)) = Suc (len (Suc 0))" by (metis div_less One_nat_def div2_Suc_Suc len.simps(3) lessI mult.right_neutral numeral_2_eq_2) qed auto lemma len_le_iff: "len x \ l \ x < 2 ^ l" proof (induct x arbitrary: l rule: len.induct) fix l show "(len (Suc 0) \ l) = (Suc 0 < 2 ^ l)" proof (cases l) case Suc then show ?thesis using le_less by fastforce qed simp next fix v l assume "\l. (len (Suc (Suc v) div 2) \ l) = (Suc (Suc v) div 2 < 2 ^ l)" then show "(len (Suc (Suc v)) \ l) = (Suc (Suc v) < 2 ^ l)" by (cases l) (simp_all, linarith) qed simp lemma len_pow2[simp]: "len (2 ^ x) = Suc x" by (induct x) auto lemma len_div2[simp]: "len (x div 2) = len x - 1" by (induct x rule: len.induct) auto lemma less_pow2_len[simp]: "x < 2 ^ len x" by (induct x rule: len.induct) auto lemma len_alt: "len x = (LEAST i. x < 2 ^ i)" proof (rule antisym) show "len x \ (LEAST i. x < 2 ^ i)" unfolding len_le_iff by (rule LeastI) (rule less_pow2_len) qed (auto intro: Least_le) lemma len_mono[simp]: "x \ y \ len x \ len y" unfolding len_le_iff using less_pow2_len[of y] by linarith lemma len_div_pow2[simp]: "len (x div 2 ^ m) = len x - m" by (induct m arbitrary: x) (auto simp: div_mult2_eq) lemma len_mult_pow2[simp]: "len (x * 2 ^ m) = (if x = 0 then 0 else len x + m)" by (induct m arbitrary: x) (auto simp: div_mult2_eq mult.assoc[symmetric] mult.commute[of _ 2]) lemma map_index'_Suc[simp]: "map_index' (Suc i) f xs = map_index' i (\i. f (Suc i)) xs" by (induct xs arbitrary: i) auto abbreviation (input) "zero n \ replicate n False" abbreviation (input) "SUC \ \_::unit. Suc" definition "test_bit m n \ (m :: nat) div 2 ^ n mod 2 = 1" +lemma test_bit_eq_iff: \test_bit = bit\ + by (simp add: fun_eq_iff test_bit_def bit_iff_odd_drop_bit mod_2_eq_odd flip: drop_bit_eq_div) definition "downshift m \ (m :: nat) div 2" definition "upshift m \ (m :: nat) * 2" -definition "set_bit n m \ m + (if \ test_bit m n then 2 ^ n else (0 :: nat))" +lemma set_bit_def: "set_bit n m \ m + (if \ test_bit m n then 2 ^ n else (0 :: nat))" + apply (rule eq_reflection) + apply (rule bit_eqI) + apply (subst disjunctive_add) + apply (auto simp add: bit_simps test_bit_eq_iff) + done definition "cut_bits n m \ (m :: nat) mod 2 ^ n" typedef interp = "{(n :: nat, xs :: nat list). \x \ set xs. len x \ n}" by (force intro: exI[of _ "[]"]) setup_lifting type_definition_interp type_synonym atom = "bool list" type_synonym "value" = "nat" datatype presb = Eq (tm: "int list") (const: int) (offset: "int") derive linorder list derive linorder presb type_synonym formula = "(presb, unit) aformula" lift_definition assigns :: "nat \ interp \ unit \ value" ("_\<^bsup>_\<^esup>_" [900, 999, 999] 999) is "\n (_, I) _. if n < length I then I ! n else 0" . lift_definition nvars :: "interp \ nat" ("#\<^sub>V _" [1000] 900) is "\(_, I). length I" . lift_definition Length :: "interp \ nat" is "\(n, _). n" . lift_definition Extend :: "unit \ nat \ interp \ value \ interp" is "\_ i (n, I) m. (max n (len m), insert_nth i m I)" by (force simp: max_def dest: in_set_takeD in_set_dropD) lift_definition CONS :: "atom \ interp \ interp" is "\bs (n, I). (Suc n, map_index (\i n. 2 * n + (if bs ! i then 1 else 0)) I)" by (auto simp: set_zip) lift_definition SNOC :: "atom \ interp \ interp" is "\bs (n, I). (Suc n, map_index (\i m. m + (if bs ! i then 2 ^ n else 0)) I)" by (auto simp: all_set_conv_all_nth len_le_iff) definition extend :: "unit \ bool \ atom \ atom" where "extend _ b bs \ b # bs" abbreviation (input) size_atom :: "atom \ nat" where "size_atom \ length" definition FV0 :: "unit \ presb \ nat set" where "FV0 _ fm = (case fm of Eq is _ _ \ {n. n < length is \ is!n \ 0})" lemma FV0_code[code]: "FV0 x (Eq is i off) = Option.these (set (map_index (\i x. if x = 0 then None else Some i) is))" unfolding FV0_def by (force simp: Option.these_def image_iff) primrec wf0 :: "nat \ presb \ bool" where "wf0 idx (Eq is _ _) = (length is = idx)" fun find0 where "find0 (_::unit) n (Eq is _ _) = (is ! n \ 0)" primrec decr0 where "decr0 (_::unit) k (Eq is i d) = Eq (take k is @ drop (Suc k) is) i d" definition scalar_product :: "nat list \ int list \ int" where "scalar_product ns is = sum_list (map_index (\i b. (if i < length ns then ns ! i else 0) * b) is)" lift_definition eval_tm :: "interp \ int list \ int" is "\(_, I). scalar_product I" . primrec satisfies0 where "satisfies0 I (Eq is i d) = (eval_tm I is = i - (2 ^ Length I) * d)" inductive lformula0 where "lformula0 (Eq is i 0)" code_pred lformula0 . fun lderiv0 :: "bool list \ presb \ formula" where "lderiv0 bs (Eq is i d) = (if d \ 0 then undefined else (let v = i - scalar_product bs is in if v mod 2 = 0 then FBase (Eq is (v div 2) 0) else FBool False))" fun rderiv0 :: "bool list \ presb \ formula" where "rderiv0 bs (Eq is i d) = (let l = - sum_list [i. i \ is, i < 0]; h = - sum_list [i. i \ is, i > 0]; d' = scalar_product bs is + 2 * d in if d' \ {min h i .. max l i} then FBase (Eq is i d') else FBool False)" primrec nullable0 where "nullable0 (Eq is i off) = (i = off)" definition \ :: "nat \ atom list" where "\ n = List.n_lists n [True, False]" named_theorems Presb_simps lemma nvars_Extend[Presb_simps]: "#\<^sub>V (Extend () i \ P) = Suc (#\<^sub>V \)" by (transfer, auto) lemma Length_Extend[Presb_simps]: "Length (Extend () i \ P) = max (Length \) (len P)" by (transfer, auto) lemma Length0_inj[Presb_simps]: "Length \ = 0 \ Length \ = 0 \ #\<^sub>V \ = #\<^sub>V \ \ \ = \" by transfer (auto intro: nth_equalityI simp: all_set_conv_all_nth len_eq0_iff) lemma ex_Length0[Presb_simps]: "\\. Length \ = 0 \ #\<^sub>V \ = idx" by (transfer fixing: idx) (auto intro: exI[of _ "replicate idx 0"]) lemma Extend_commute_safe[Presb_simps]: "\j \ i; i < Suc (#\<^sub>V \)\ \ Extend k j (Extend k i \ P) Q = Extend k (Suc i) (Extend k j \ Q) P" by transfer (auto simp add: min_def take_Cons take_drop le_imp_diff_is_add split: nat.splits) lemma Extend_commute_unsafe[Presb_simps]: "k \ k' \ Extend k j (Extend k' i \ P) Q = Extend k' i (Extend k j \ Q) P" by transfer auto lemma assigns_Extend[Presb_simps]: "i < Suc (#\<^sub>V \) \ m\<^bsup>Extend k i \ P\<^esup>k' = (if k = k' then if m = i then P else dec i m\<^bsup>\\<^esup>k else m\<^bsup>\\<^esup>k')" by transfer (auto simp: nth_append dec_def min_def) lemma assigns_SNOC_zero[Presb_simps]: "m < #\<^sub>V \ \ m\<^bsup>SNOC (zero (#\<^sub>V \)) \\<^esup>k = m\<^bsup>\\<^esup>k" by transfer auto lemma Length_CONS[Presb_simps]: "Length (CONS x \) = Suc (Length \)" by transfer auto lemma Length_SNOC[Presb_simps]: "Length (SNOC x \) = Suc (Length \)" by transfer auto lemma nvars_CONS[Presb_simps]: "#\<^sub>V (CONS x \) = #\<^sub>V \" by transfer auto lemma nvars_SNOC[Presb_simps]: "#\<^sub>V (SNOC x \) = #\<^sub>V \" by transfer auto lemma Extend_CONS[Presb_simps]: "#\<^sub>V \ = length x \ Extend k 0 (CONS x \) P = CONS (extend k (test_bit P 0) x) (Extend k 0 \ (downshift P))" by transfer (auto simp: extend_def downshift_def test_bit_def, presburger+) lemma Extend_SNOC[Presb_simps]: "\#\<^sub>V \ = length x; len P \ Length (SNOC x \)\ \ Extend k 0 (SNOC x \) P = SNOC (extend k (test_bit P (Length \)) x) (Extend k 0 \ (cut_bits (Length \) P))" apply transfer apply (auto simp: cut_bits_def extend_def test_bit_def nth_Cons' max_absorb1 len_le_iff split: if_splits cong del: if_weak_cong) apply (metis add.commute mod_less mod_mult2_eq mult_numeral_1_right numeral_1_eq_Suc_0 power_commuting_commutes) apply (metis Euclidean_Division.div_eq_0_iff div_0 less_mult_imp_div_less mod_less nat_dvd_not_less semiring_normalization_rules(7)) done lemma odd_neq_even: "Suc (2 * x) = 2 * y \ False" "2 * y = Suc (2 * x) \ False" by presburger+ lemma CONS_inj[Presb_simps]: "size x = #\<^sub>V \ \ size y = #\<^sub>V \ \ #\<^sub>V \ = #\<^sub>V \ \ CONS x \ = CONS y \ \ (x = y \ \ = \)" by transfer (auto simp: list_eq_iff_nth_eq odd_neq_even split: if_splits) lemma mod_2_Suc_iff: "x mod 2 = Suc 0 \ x = Suc (2 * (x div 2))" by presburger+ lemma CONS_surj[Presb_simps]: "Length \ \ 0 \ \x \. \ = CONS x \ \ #\<^sub>V \ = #\<^sub>V \ \ size x = #\<^sub>V \" by transfer (auto simp: gr0_conv_Suc list_eq_iff_nth_eq len_le_iff split: if_splits intro!: exI[of _ "map (\n. n mod 2 \ 0) _"] exI[of _ "map (\n. n div 2) _"]; auto simp: mod_2_Suc_iff) lemma [Presb_simps]: "length (extend k b x) = Suc (length x)" "downshift (upshift P) = P" "downshift (set_bit 0 P) = downshift P" "test_bit (set_bit n P) n" "\ test_bit (upshift P) 0" "len P \ p \ \ test_bit P p" "len (cut_bits n P) \ n" "len P \ n \ cut_bits n P = P" "len (upshift P) = (case len P of 0 \ 0 | Suc n \ Suc (Suc n))" "len (downshift P) = (case len P of 0 \ 0 | Suc n \ n)" by (auto simp: extend_def set_bit_def cut_bits_def upshift_def downshift_def test_bit_def len_le_iff len_eq0_iff div_add_self2 split: nat.split) lemma Suc0_div_pow2_eq: "Suc 0 div 2 ^ i = (if i = 0 then 1 else 0)" by (induct i) (auto simp: div_mult2_eq) lemma set_unset_bit_preserves_len: assumes "x div 2 ^ m = 2 * q" "m < len x" shows "x + 2 ^ m < 2 ^ len x" using assms proof (induct m arbitrary: x) case 0 then show ?case by (auto simp: div_mult2_eq len_Suc_mult2[symmetric] simp del: len_Suc_mult2 power_Suc split: if_splits) next case (Suc m) with Suc(1)[of "x div 2"] show ?case by (cases "len x") (auto simp: div_mult2_eq) qed lemma len_set_bit[Presb_simps]: "len (set_bit m P) = max (Suc m) (len P)" proof (rule antisym) show "len (set_bit m P) \ max (Suc m) (len P)" by (auto simp: set_bit_def test_bit_def max_def Suc_le_eq not_less len_le_iff set_unset_bit_preserves_len simp del: One_nat_def) next have "P < 2 ^ len (P + 2 ^ m)" by (rule order.strict_trans2[OF less_pow2_len]) auto moreover have "m < len (P + 2 ^ m)" by (rule order.strict_trans2[OF _ len_mono[of "2 ^ m"]]) auto ultimately show "max (Suc m) (len P) \ len (set_bit m P)" by (auto simp: set_bit_def test_bit_def max_def Suc_le_eq not_less len_le_iff) qed lemma mod_pow2_div_pow2: fixes p m n :: nat shows "m < n \ p mod 2 ^ n div 2 ^ m = p div 2 ^ m mod 2 ^ (n - m)" by (induct m arbitrary: p n) (auto simp: div_mult2_eq mod_mult2_eq Suc_less_eq2) lemma irrelevant_set_bit[simp]: fixes p m n :: nat assumes "n \ m" shows "(p + 2 ^ m) mod 2 ^ n = p mod 2 ^ n" proof - from assms obtain q :: nat where "2 ^ m = q * 2 ^ n" by (metis le_add_diff_inverse mult.commute power_add) then show ?thesis by simp qed lemma mod_lemma: "\ (0::nat) < c; r < b \ \ b * (q mod c) + r < b * c" by (metis add_gr_0 div_le_mono div_mult_self1_is_m less_imp_add_positive mod_less_divisor not_less split_div) lemma relevant_set_bit[simp]: fixes p m n :: nat assumes "m < n" "p div 2 ^ m = 2 * q" shows "(p + 2 ^ m) mod 2 ^ n = p mod 2 ^ n + 2 ^ m" proof - have "p mod 2 ^ n + 2 ^ m < 2 ^ n" using assms proof (induct m arbitrary: p n) case 0 then show ?case by (auto simp: gr0_conv_Suc) (metis One_nat_def Suc_eq_plus1 lessI mod_lemma numeral_2_eq_2 zero_less_numeral zero_less_power) next case (Suc m) from Suc(1)[of "n - 1" "p div 2"] Suc(2,3) show ?case by (auto simp: div_mult2_eq mod_mult2_eq Suc_less_eq2) qed with \m < n\ show ?thesis by (subst mod_add_eq [symmetric]) auto qed lemma cut_bits_set_bit[Presb_simps]: "cut_bits n (set_bit m p) = (if n \ m then cut_bits n p else set_bit m (cut_bits n p))" unfolding cut_bits_def set_bit_def test_bit_def by (auto simp: not_le mod_pow2_div_pow2 mod_mod_cancel simp del: One_nat_def) lemma wf0_decr0[Presb_simps]: "wf0 (Suc idx) a \ l < Suc idx \ \ find0 k l a \ wf0 idx (decr0 k l a)" by (induct a) auto lemma lformula0_decr0[Presb_simps]: "lformula0 a \ lformula0 (decr0 k l a)" by (induct a) (auto elim: lformula0.cases intro: lformula0.intros) abbreviation sat0_syn (infix "\0" 65) where "sat0_syn \ satisfies0" abbreviation sat_syn (infix "\" 65) where "sat_syn \ Formula_Operations.satisfies Extend Length satisfies0" abbreviation sat_bounded_syn (infix "\\<^sub>b" 65) where "sat_bounded_syn \ Formula_Operations.satisfies_bounded Extend Length len satisfies0" lemma scalar_product_Nil[simp]: "scalar_product [] xs = 0" by (induct xs) (auto simp: scalar_product_def) lemma scalar_product_Nil2[simp]: "scalar_product xs [] = 0" by (induct xs) (auto simp: scalar_product_def) lemma scalar_product_Cons[simp]: "scalar_product xs (y # ys) = (case xs of x # xs \ x * y + scalar_product xs ys | [] \ 0)" by (cases xs) (simp, auto simp: scalar_product_def cong del: if_weak_cong) lemma scalar_product_append[simp]: "scalar_product ns (xs @ ys) = scalar_product (take (length xs) ns) xs + scalar_product (drop (length xs) ns) ys" by (induct xs arbitrary: ns) (auto split: list.splits) lemma scalar_product_trim: "scalar_product ns xs = scalar_product (take (length xs) ns) xs" by (induct xs arbitrary: ns) (auto split: list.splits) lemma Extend_satisfies0_decr0[Presb_simps]: assumes "\ find0 k i a" "i < Suc (#\<^sub>V \)" "lformula0 a \ len P \ Length \" shows "Extend k i \ P \0 a = \ \0 decr0 k i a" proof - { fix "is" :: "int list" assume "is ! i = 0" with assms(1,2) have "eval_tm (Extend k i \ P) is = eval_tm \ (take i is @ drop (Suc i) is)" by (cases a, transfer) (force intro: trans[OF scalar_product_trim] simp: min_def arg_cong2[OF refl id_take_nth_drop, of i _ scalar_product "take i xs @ _" for i x xs]) } note * = this from assms show ?thesis by (cases a) (auto dest!: * simp: Length_Extend max_def elim: lformula0.cases) qed lemma scalar_product_eq0: "\c\set ns. c = 0 \ scalar_product ns is = 0" proof (induct "is" arbitrary: "ns") case Cons then show ?case by (cases ns) (auto simp: scalar_product_def cong del: if_weak_cong) qed (simp add: scalar_product_def) lemma nullable0_satisfies0[Presb_simps]: "Length \ = 0 \ nullable0 a = \ \0 a" proof (induct a) case Eq then show ?case unfolding nullable0.simps satisfies0.simps by transfer (auto simp: len_eq0_iff scalar_product_eq0) qed lemma satisfies0_cong: "wf0 (#\<^sub>V \) a \ #\<^sub>V \ = #\<^sub>V \ \ lformula0 a \ (\m k. m < #\<^sub>V \ \ m\<^bsup>\\<^esup>k = m\<^bsup>\\<^esup>k) \ \ \0 a = \ \0 a" proof (induct a) case Eq then show ?case unfolding satisfies0.simps by transfer (auto simp: scalar_product_def intro!: arg_cong[of _ _ sum_list] map_index_cong elim!: lformula0.cases) qed lemma wf_lderiv0[Presb_simps]: "wf0 idx a \ lformula0 a \ Formula_Operations.wf (\_. Suc) wf0 idx (lderiv0 x a)" by (induct a) (auto elim: lformula0.cases simp: Formula_Operations.wf.simps Let_def) lemma lformula_lderiv0[Presb_simps]: "lformula0 a \ Formula_Operations.lformula lformula0 (lderiv0 x a)" by (induct a) (auto elim: lformula0.cases intro: lformula0.intros simp: Let_def Formula_Operations.lformula.simps) lemma wf_rderiv0[Presb_simps]: "wf0 idx a \ Formula_Operations.wf (\_. Suc) wf0 idx (rderiv0 x a)" by (induct a) (auto elim: lformula0.cases simp: Formula_Operations.wf.simps Let_def) lemma find0_FV0[Presb_simps]: "\wf0 idx a; l < idx\ \ find0 k l a = (l \ FV0 k a)" by (induct a) (auto simp: FV0_def) lemma FV0_less[Presb_simps]: "wf0 idx a \ v \ FV0 k a \ v < idx" by (induct a) (auto simp: FV0_def) lemma finite_FV0[Presb_simps]: "finite (FV0 k a)" by (induct a) (auto simp: FV0_def) lemma finite_lderiv0[Presb_simps]: assumes "lformula0 a" shows "finite {\. \xs. \ = fold (Formula_Operations.deriv extend lderiv0) xs (FBase a)}" proof - define d where "d = Formula_Operations.deriv extend lderiv0" define l where "l is = sum_list [i. i \ is, i < 0]" for "is" :: "int list" define h where "h is = sum_list [i. i \ is, i > 0]" for "is" :: "int list" define \ where "\ a = (case a of Eq is n z \ {FBase (Eq is i 0) | i . i \ {min (- h is) n .. max (- l is) n}} \ {FBool False :: formula})" for a { fix xs note Formula_Operations.fold_deriv_FBool[simp] Formula_Operations.deriv.simps[simp] \_def[simp] from \lformula0 a\ have "FBase a \ \ a" by (auto simp: elim!: lformula0.cases) moreover have "\x \. \ \ \ a \ d x \ \ \ a" proof (induct a, unfold \_def presb.case, elim UnE CollectE insertE emptyE exE conjE) fix "is" :: "int list" and bs :: "bool list" and i n :: int and \ :: formula assume "i \ {min (- h is) n..max (- l is) n}" "\ = FBase (presb.Eq is i 0)" moreover have "scalar_product bs is \ h is" proof (induct "is" arbitrary: bs) case (Cons x xs) from Cons[of "tl bs"] show ?case by (cases bs) (auto simp: h_def) qed (auto simp: h_def scalar_product_def) moreover have "l is \ scalar_product bs is" proof (induct "is" arbitrary: bs) case (Cons x xs) from Cons[of "tl bs"] show ?case by (cases bs) (auto simp: l_def) qed (auto simp: l_def scalar_product_def) ultimately show "d bs \ \ {FBase (presb.Eq is i 0) |i. i \ {min (- h is) n..max (- l is) n}} \ {FBool False}" by (auto simp: d_def Let_def) qed (auto simp: d_def) then have "\\. \ \ \ a \ fold d xs \ \ \ a" by (induct xs) auto ultimately have "fold d xs (FBase a) \ \ a" by blast } moreover have "finite (\ a)" unfolding \_def by (auto split: presb.splits) ultimately show "?thesis" unfolding d_def by (blast intro: finite_subset) qed lemma finite_rderiv0[Presb_simps]: "finite {\. \xs. \ = fold (Formula_Operations.deriv extend rderiv0) xs (FBase a)}" proof - define d where "d = Formula_Operations.deriv extend rderiv0" define l where "l is = sum_list [i. i \ is, i < 0]"for "is" :: "int list" define h where "h is = sum_list [i. i \ is, i > 0]"for "is" :: "int list" define \ where "\ a = (case a of Eq is n z \ {FBase (Eq is n i) | i . i \ {min (- h is) (min n z) .. max (- l is) (max n z)}} \ {FBool False :: formula})" for a { fix xs note Formula_Operations.fold_deriv_FBool[simp] Formula_Operations.deriv.simps[simp] \_def[simp] have "FBase a \ \ a" by (auto split: presb.splits) moreover have "\x \. \ \ \ a \ d x \ \ \ a" proof (induct a, unfold \_def presb.case, elim UnE CollectE insertE emptyE exE conjE) fix "is" :: "int list" and bs :: "bool list" and i n m :: int and \ :: formula assume "i \ {min (- h is) (min n m)..max (- l is) (max n m)}" "\ = FBase (presb.Eq is n i)" moreover have "scalar_product bs is \ h is" proof (induct "is" arbitrary: bs) case (Cons x xs) from Cons[of "tl bs"] show ?case by (cases bs) (auto simp: h_def) qed (auto simp: h_def scalar_product_def) moreover have "l is \ scalar_product bs is" proof (induct "is" arbitrary: bs) case (Cons x xs) from Cons[of "tl bs"] show ?case by (cases bs) (auto simp: l_def) qed (auto simp: l_def scalar_product_def) ultimately show "d bs \ \ {FBase (presb.Eq is n i) |i. i \ {min (- h is) (min n m)..max (- l is) (max n m)}} \ {FBool False}" by (auto 0 1 simp: d_def Let_def h_def l_def) qed (auto simp: d_def) then have "\\. \ \ \ a \ fold d xs \ \ \ a" by (induct xs) auto ultimately have "fold d xs (FBase a) \ \ a" by blast } moreover have "finite (\ a)" unfolding \_def by (auto split: presb.splits) ultimately show "?thesis" unfolding d_def by (blast intro: finite_subset) qed lemma scalar_product_CONS: "length xs = length (bs :: bool list) \ scalar_product (map_index (\i n. 2 * n + bs ! i) xs) is = scalar_product bs is + 2 * scalar_product xs is" by (induct "is" arbitrary: bs xs) (auto split: list.splits simp: algebra_simps) lemma eval_tm_CONS[simp]: "\length is \ #\<^sub>V \; #\<^sub>V \ = length x\ \ eval_tm (CONS x \) is = scalar_product x is + 2 * eval_tm \ is" by transfer (auto simp: scalar_product_CONS[symmetric] intro!: arg_cong2[of _ _ _ _ scalar_product] nth_equalityI) lemma satisfies_lderiv0[Presb_simps]: "\wf0 (#\<^sub>V \) a; #\<^sub>V \ = length x; lformula0 a\ \ \ \ lderiv0 x a \ CONS x \ \0 a" by (auto simp: Let_def Formula_Operations.satisfies_gen.simps split: if_splits elim!: lformula0.cases) lemma satisfies_bounded_lderiv0[Presb_simps]: "\wf0 (#\<^sub>V \) a; #\<^sub>V \ = length x; lformula0 a\ \ \ \\<^sub>b lderiv0 x a \ CONS x \ \0 a" by (auto simp: Let_def Formula_Operations.satisfies_gen.simps split: if_splits elim!: lformula0.cases) lemma scalar_product_SNOC: "length xs = length (bs :: bool list) \ scalar_product (map_index (\i m. m + 2 ^ a * bs ! i) xs) is = scalar_product xs is + 2 ^ a * scalar_product bs is" by (induct "is" arbitrary: bs xs) (auto split: list.splits simp: algebra_simps) lemma eval_tm_SNOC[simp]: "\length is \ #\<^sub>V \; #\<^sub>V \ = length x\ \ eval_tm (SNOC x \) is = eval_tm \ is + 2 ^ Length \ * scalar_product x is" by transfer (auto simp: scalar_product_SNOC[symmetric] intro!: arg_cong2[of _ _ _ _ scalar_product] nth_equalityI) lemma Length_eq0_eval_tm_eq0[simp]: "Length \ = 0 \ eval_tm \ is = 0" by transfer (auto simp: len_eq0_iff scalar_product_eq0) lemma less_pow2: "x < 2 ^ a \ int x < 2 ^ a" by (metis of_nat_less_iff of_nat_numeral of_nat_power [symmetric]) lemma scalar_product_upper_bound: "\x\set b. len x \ a \ scalar_product b is \ (2 ^ a - 1) * sum_list [i. i \ is, i > 0]" proof (induct "is" arbitrary: b) case (Cons i "is") then have "scalar_product (tl b) is \ (2 ^ a - 1) * sum_list [i. i \ is, i > 0]" by (auto simp: in_set_tlD) with Cons(2) show ?case by (auto 0 3 split: list.splits simp: len_le_iff mult_le_0_iff distrib_left add.commute[of _ "(2 ^ a - 1) * i"] less_pow2 intro: add_mono elim: order_trans[OF add_mono[OF order_refl]]) qed simp lemma scalar_product_lower_bound: "\x\set b. len x \ a \ scalar_product b is \ (2 ^ a - 1) * sum_list [i. i \ is, i < 0]" proof (induct "is" arbitrary: b) case (Cons i "is") then have "scalar_product (tl b) is \ (2 ^ a - 1) * sum_list [i. i \ is, i < 0]" by (auto simp: in_set_tlD) with Cons(2) show ?case by (auto 0 3 split: list.splits simp: len_le_iff mult_le_0_iff distrib_left add.commute[of _ "(2 ^ a - 1) * i"] less_pow2 intro: add_mono elim: order_trans[OF add_mono[OF order_refl]] order_trans) qed simp lemma eval_tm_upper_bound: "eval_tm \ is \ (2 ^ Length \ - 1) * sum_list [i. i \ is, i > 0]" by transfer (auto simp: scalar_product_upper_bound) lemma eval_tm_lower_bound: "eval_tm \ is \ (2 ^ Length \ - 1) * sum_list [i. i \ is, i < 0]" by transfer (auto simp: scalar_product_lower_bound) lemma satisfies_bounded_rderiv0[Presb_simps]: "\wf0 (#\<^sub>V \) a; #\<^sub>V \ = length x\ \ \ \\<^sub>b rderiv0 x a \ SNOC x \ \0 a" proof (induct a) case (Eq "is" n d) let ?l = "Length \" define d' where "d' = scalar_product x is + 2 * d" define l where "l = sum_list [i. i \ is, i < 0]" define h where "h = sum_list [i. i \ is, i > 0]" from Eq show ?case unfolding wf0.simps satisfies0.simps rderiv0.simps Let_def proof (split if_splits, simp only: Formula_Operations.satisfies_gen.simps satisfies0.simps Length_SNOC eval_tm_SNOC simp_thms(13) de_Morgan_conj not_le min_less_iff_conj max_less_iff_conj d'_def[symmetric] h_def[symmetric] l_def[symmetric], safe) assume "eval_tm \ is + 2 ^ ?l * scalar_product x is = n - 2 ^ Suc ?l * d" with eval_tm_upper_bound[of \ "is"] eval_tm_lower_bound[of \ "is"] have *: "n + h \ 2 ^ ?l * (h + d')" "2 ^ ?l * (l + d') \ n + l" by (auto simp: algebra_simps h_def l_def d'_def) assume **: "d' \ {min (- h) n..max (- l) n}" { assume "0 \ n + h" from order_trans[OF this *(1)] have "0 \ h + d'" unfolding zero_le_mult_iff using zero_less_power[of 2] by presburger } moreover { assume "n + h < 0" with *(1) have "n \ d'" by (auto dest: order_trans[OF _ mult_right_mono_neg[of 1]]) } moreover { assume "n + l < 0" from le_less_trans[OF *(2) this] have "l + d' < 0" unfolding mult_less_0_iff by auto } moreover { assume "0 \ n + l" then have "0 \ l + d'" using ** calculation(1-2) by force with *(2) have "d' \ n" by (force dest: order_trans[OF mult_right_mono[of 1], rotated]) } ultimately have "min (- h) n \ d'" "d' \ max (- l) n" by (auto simp: min_def max_def) with ** show False by auto qed (auto simp: algebra_simps d'_def) qed declare [[goals_limit = 100]] global_interpretation Presb: Formula where SUC = SUC and LESS = "\_. (<)" and Length = Length and assigns = assigns and nvars = nvars and Extend = Extend and CONS = CONS and SNOC = SNOC and extend = extend and size = size_atom and zero = zero and alphabet = \ and eval = test_bit and downshift = downshift and upshift = upshift and add = set_bit and cut = cut_bits and len = len and restrict = "\_ _. True" and Restrict = "\_ _. FBool True" and lformula0 = lformula0 and FV0 = FV0 and find0 = find0 and wf0 = wf0 and decr0 = decr0 and satisfies0 = satisfies0 and nullable0 = nullable0 and lderiv0 = lderiv0 and rderiv0 = rderiv0 and TYPEVARS = undefined defines norm = "Formula_Operations.norm find0 decr0" and nFOr = "Formula_Operations.nFOr :: formula \ _" and nFAnd = "Formula_Operations.nFAnd :: formula \ _" and nFNot = "Formula_Operations.nFNot find0 decr0 :: formula \ _" and nFEx = "Formula_Operations.nFEx find0 decr0" and nFAll = "Formula_Operations.nFAll find0 decr0" and decr = "Formula_Operations.decr decr0 :: _ \ _ \ formula \ _" and find = "Formula_Operations.find find0 :: _ \ _ \ formula \ _" and FV = "Formula_Operations.FV FV0" and RESTR = "Formula_Operations.RESTR (\_ _. FBool True) :: _ \ formula" and RESTRICT = "Formula_Operations.RESTRICT (\_ _. FBool True) FV0" and deriv = "\d0 (a :: atom) (\ :: formula). Formula_Operations.deriv extend d0 a \" and nullable = "\\ :: formula. Formula_Operations.nullable nullable0 \" and fut_default = "Formula.fut_default extend zero rderiv0" and fut = "Formula.fut extend zero find0 decr0 rderiv0" and finalize = "Formula.finalize SUC extend zero find0 decr0 rderiv0" and final = "Formula.final SUC extend zero find0 decr0 nullable0 rderiv0 :: nat \ formula \ _" and presb_wf = "Formula_Operations.wf SUC (wf0 :: nat \ presb \ _)" and presb_lformula = "Formula_Operations.lformula (lformula0 :: presb \ _) :: formula \ _" and check_eqv = "\idx. DAs.check_eqv (\ idx) (\\. norm (RESTRICT \) :: formula) (\a \. norm (deriv (lderiv0 :: _ \ _ \ formula) (a :: atom) \)) (final idx) (\\ :: formula. presb_wf idx \ \ presb_lformula \) (\ idx) (\\. norm (RESTRICT \) :: formula) (\a \. norm (deriv (lderiv0 :: _ \ _ \ formula) (a :: atom) \)) (final idx) (\\ :: formula. presb_wf idx \ \ presb_lformula \) (=)" and bounded_check_eqv = "\idx. DAs.check_eqv (\ idx) (\\. norm (RESTRICT \) :: formula) (\a \. norm (deriv (lderiv0 :: _ \ _ \ formula) (a :: atom) \)) nullable (\\ :: formula. presb_wf idx \ \ presb_lformula \) (\ idx) (\\. norm (RESTRICT \) :: formula) (\a \. norm (deriv (lderiv0 :: _ \ _ \ formula) (a :: atom) \)) nullable (\\ :: formula. presb_wf idx \ \ presb_lformula \) (=)" and automaton = "DA.automaton (\a \. norm (deriv lderiv0 (a :: atom) \ :: formula))" - by standard (auto simp: Presb_simps \_def set_n_lists distinct_n_lists + apply standard apply (auto simp: Presb_simps \_def set_n_lists distinct_n_lists Formula_Operations.lformula.simps Formula_Operations.satisfies_gen.simps Formula_Operations.wf.simps dest: satisfies0_cong split: presb.splits if_splits) + apply (simp add: downshift_def) + done (*Workaround for code generation*) lemma check_eqv_code[code]: "check_eqv idx r s = ((presb_wf idx r \ presb_lformula r) \ (presb_wf idx s \ presb_lformula s) \ (case rtrancl_while (\(p, q). final idx p = final idx q) (\(p, q). map (\a. (norm (deriv lderiv0 a p), norm (deriv lderiv0 a q))) (\ idx)) (norm (RESTRICT r), norm (RESTRICT s)) of None \ False | Some ([], x) \ True | Some (a # list, x) \ False))" unfolding check_eqv_def Presb.check_eqv_def Presb.step_alt .. definition while where [code del, code_abbrev]: "while idx \ = while_default (fut_default idx \)" declare while_default_code[of "fut_default idx \" for idx \, folded while_def, code] lemma check_eqv_sound: "\#\<^sub>V \ = idx; check_eqv idx \ \\ \ (Presb.sat \ \ \ Presb.sat \ \)" unfolding check_eqv_def by (rule Presb.check_eqv_soundness) lemma bounded_check_eqv_sound: "\#\<^sub>V \ = idx; bounded_check_eqv idx \ \\ \ (Presb.sat\<^sub>b \ \ \ Presb.sat\<^sub>b \ \)" unfolding bounded_check_eqv_def by (rule Presb.bounded_check_eqv_soundness) method_setup check_equiv = \ let fun tac ctxt = let val conv = @{computation_check terms: Trueprop "0 :: nat" "1 :: nat" "2 :: nat" "3 :: nat" Suc "plus :: nat \ _" "minus :: nat \ _" "times :: nat \ _" "divide :: nat \ _" "modulo :: nat \ _" "0 :: int" "1 :: int" "2 :: int" "3 :: int" "-1 :: int" check_eqv datatypes: formula "int list" integer bool} ctxt in CONVERSION (Conv.params_conv ~1 (K (Conv.concl_conv ~1 conv)) ctxt) THEN' resolve_tac ctxt [TrueI] end in Scan.succeed (SIMPLE_METHOD' o tac) end \ end diff --git a/thys/Isabelle_Meta_Model/meta_isabelle/Meta_Isabelle.thy b/thys/Isabelle_Meta_Model/meta_isabelle/Meta_Isabelle.thy --- a/thys/Isabelle_Meta_Model/meta_isabelle/Meta_Isabelle.thy +++ b/thys/Isabelle_Meta_Model/meta_isabelle/Meta_Isabelle.thy @@ -1,451 +1,451 @@ (****************************************************************************** * A Meta-Model for the Isabelle API * * Copyright (c) 2011-2018 Université Paris-Saclay, Univ. Paris-Sud, France * 2013-2017 IRT SystemX, France * 2011-2015 Achim D. Brucker, Germany * 2016-2018 The University of Sheffield, UK * 2016-2017 Nanyang Technological University, Singapore * 2017-2018 Virginia Tech, USA * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * * Neither the name of the copyright holders nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ******************************************************************************) section\Isabelle Meta-Model aka. AST definition of Isabelle\ theory Meta_Isabelle imports Meta_Pure Meta_SML begin subsection\Type Definition\ text\The following datatypes beginning with \verb|semi__| represent semi-concrete syntax, deliberately not minimal abstract syntax like (Pure) Term, this is for example to facilitate the pretty-printing process, or for manipulating recursively data-structures through an abstract and typed API.\ datatype semi__typ = Typ_apply semi__typ "semi__typ list" | Typ_apply_bin string \ \binop\ semi__typ semi__typ | Typ_apply_paren string \ \left\ string \ \right\ semi__typ | Typ_base string datatype "datatype" = Datatype string \ \name\ "(string \ \name\ \ semi__typ list \ \arguments\) list" \ \constructors\ datatype "type_synonym" = Type_synonym string \ \name\ "string list" \ \parametric variables\ semi__typ \ \content\ datatype semi__term = Term_rewrite semi__term \ \left\ string \ \symb rewriting\ semi__term \ \right\ | Term_basic "string list" | Term_annot semi__term semi__typ | Term_bind string \ \symbol\ semi__term \ \arg\ semi__term | Term_fun_case "semi__term \ \value\ option" \ \none: function\ "(semi__term \ \pattern\ \ semi__term \ \to return\) list" | Term_apply semi__term "semi__term list" | Term_paren string \ \left\ string \ \right\ semi__term | Term_if_then_else semi__term semi__term semi__term | Term_term "string list" \ \simulate a pre-initialized context (de bruijn variables under "lam")\ "term" \ \usual continuation of inner syntax term\ datatype "type_notation" = Type_notation string \ \name\ string \ \content\ datatype "instantiation" = Instantiation string \ \name\ string \ \name in definition\ semi__term datatype "overloading" = Overloading string \ \name consts\ semi__term string \ \name def\ semi__term \ \content\ datatype "consts" = Consts string \ \name\ semi__typ string \ \expression in 'post' mixfix\ datatype "definition" = Definition semi__term | Definition_where1 string \ \name\ "semi__term \ \syntax extension\ \ nat \ \priority\" semi__term | Definition_where2 string \ \name\ semi__term \ \syntax extension\ semi__term datatype semi__thm_attribute = Thm_thm string \ \represents a single thm\ | Thm_thms string \ \represents several thms\ | Thm_THEN semi__thm_attribute semi__thm_attribute | Thm_simplified semi__thm_attribute semi__thm_attribute | Thm_symmetric semi__thm_attribute | Thm_where semi__thm_attribute "(string \ semi__term) list" | Thm_of semi__thm_attribute "semi__term list" | Thm_OF semi__thm_attribute semi__thm_attribute datatype semi__thm = Thms_single semi__thm_attribute | Thms_mult semi__thm_attribute type_synonym semi__thm_l = "semi__thm list" datatype "lemmas" = Lemmas_simp_thm bool \ \True : simp\ string \ \name\ "semi__thm_attribute list" | Lemmas_simp_thms string \ \name\ "string \ \thms\ list" datatype semi__method_simp = Method_simp_only semi__thm_l | Method_simp_add_del_split semi__thm_l \ \add\ semi__thm_l \ \del\ semi__thm_l \ \split\ datatype semi__method = Method_rule "semi__thm_attribute option" | Method_drule semi__thm_attribute | Method_erule semi__thm_attribute | Method_intro "semi__thm_attribute list" | Method_elim semi__thm_attribute | Method_subst bool \ \asm\ "string \ \nat\ list" \ \pos\ semi__thm_attribute | Method_insert semi__thm_l | Method_plus "semi__method list" | Method_option "semi__method list" | Method_or "semi__method list" | Method_one semi__method_simp | Method_all semi__method_simp | Method_auto_simp_add_split semi__thm_l "string list" | Method_rename_tac "string list" | Method_case_tac semi__term | Method_blast "nat option" | Method_clarify | Method_metis "string list" \ \e.g. \no_types\ (\override_type_encs\)\ "semi__thm_attribute list" datatype semi__command_final = Command_done | Command_by "semi__method list" | Command_sorry datatype semi__command_state = Command_apply_end "semi__method list" \ \\<^theory_text>\apply_end (\, \)\\ datatype semi__command_proof = Command_apply "semi__method list" \ \\<^theory_text>\apply (\, \)\\ | Command_using semi__thm_l \ \\<^theory_text>\using \\\ | Command_unfolding semi__thm_l \ \\<^theory_text>\unfolding \\\ | Command_let semi__term \ \name\ semi__term | Command_have string \ \name\ bool \ \true: add \[simp]\\ semi__term semi__command_final | Command_fix_let "string list" "(semi__term \ \name\ \ semi__term) list" \ \let statements\ (* TODO merge recursively *) "( semi__term list \ \\<^theory_text>\show \ \ \ \\ \ semi__term list \ \\<^theory_text>\when \ \\\) option" \ \\None \ ?thesis\\ "semi__command_state list" \ \\<^theory_text>\qed apply_end \\\ datatype "lemma" = Lemma string \ \name\ "semi__term list" \ \specification to prove\ "semi__method list list" \ \tactics: \<^theory_text>\apply (\, \) apply \\\ semi__command_final | Lemma_assumes string \ \name\ "(string \ \name\ \ bool \ \true: add \[simp]\\ \ semi__term) list" \ \specification to prove (assms)\ semi__term \ \specification to prove (conclusion)\ "semi__command_proof list" semi__command_final datatype "axiomatization" = Axiomatization string \ \name\ semi__term datatype "section" = Section nat \ \nesting level\ string \ \content\ datatype "text" = Text string datatype "ML" = SML semi__term' datatype "setup" = Setup semi__term' datatype "thm" = Thm "semi__thm_attribute list" datatype "interpretation" = Interpretation string \ \name\ string \ \locale name\ "semi__term list" \ \locale param\ semi__command_final datatype semi__theory = Theory_datatype "datatype" | Theory_type_synonym "type_synonym" | Theory_type_notation "type_notation" | Theory_instantiation "instantiation" | Theory_overloading "overloading" | Theory_consts "consts" | Theory_definition "definition" | Theory_lemmas "lemmas" | Theory_lemma "lemma" | Theory_axiomatization "axiomatization" | Theory_section "section" | Theory_text "text" | Theory_ML "ML" | Theory_setup "setup" | Theory_thm "thm" | Theory_interpretation "interpretation" record semi__locale = HolThyLocale_name :: string HolThyLocale_header :: "( (semi__term \ \name\ \ semi__typ \ \\<^theory_text>\fix\ statement\) list \ (string \ \name\ \ semi__term \ \\<^theory_text>\assumes\ statement\) option \ \None: no \<^theory_text>\assumes\ to generate\) list" datatype semi__theories = Theories_one semi__theory | Theories_locale semi__locale "semi__theory list \ \positioning comments can occur before and after this group of commands\ list" subsection\Extending the Meta-Model\ locale T begin definition "thm = Thm_thm" definition "thms = Thm_thms" definition "THEN = Thm_THEN" definition "simplified = Thm_simplified" definition "symmetric = Thm_symmetric" definition "where = Thm_where" definition "of' = Thm_of" definition "OF = Thm_OF" definition "OF_l s l = List.fold (\x acc. Thm_OF acc x) l s" definition "simplified_l s l = List.fold (\x acc. Thm_simplified acc x) l s" end lemmas [code] = \ \def\ T.thm_def T.thms_def T.THEN_def T.simplified_def T.symmetric_def T.where_def T.of'_def T.OF_def T.OF_l_def T.simplified_l_def definition "Opt s = Typ_apply (Typ_base \option\) [Typ_base s]" definition "Raw = Typ_base" definition "Type_synonym' n = Type_synonym n []" definition "Type_synonym'' n l f = Type_synonym n l (f l)" definition "Term_annot' e s = Term_annot e (Typ_base s)" definition "Term_lambdas s = Term_bind \\\ (Term_basic s)" definition "Term_lambda x = Term_lambdas [x]" definition "Term_lambdas0 = Term_bind \\\" definition "Term_lam x f = Term_lambdas0 (Term_basic [x]) (f x)" definition "Term_some = Term_paren \\\ \\\" definition "Term_parenthesis \ \mandatory parenthesis\ = Term_paren \(\ \)\" definition "Term_warning_parenthesis \ \optional parenthesis that can be removed but a warning will be raised\ = Term_parenthesis" definition "Term_pat b = Term_basic [\?\ @@ b]" definition "Term_And x f = Term_bind \\\ (Term_basic [x]) (f x)" definition "Term_exists x f = Term_bind \\\ (Term_basic [x]) (f x)" definition "Term_binop = Term_rewrite" definition "term_binop s l = (case rev l of x # xs \ List.fold (\x. Term_binop x s) xs x)" definition "term_binop' s l = (case rev l of x # xs \ List.fold (\x. Term_parenthesis o Term_binop x s) xs x)" definition "Term_set l = (case l of [] \ Term_basic [\{}\] | _ \ Term_paren \{\ \}\ (term_binop \,\ l))" definition "Term_list l = (case l of [] \ Term_basic [\[]\] | _ \ Term_paren \[\ \]\ (term_binop \,\ l))" definition "Term_list' f l = Term_list (L.map f l)" definition "Term_pair e1 e2 = Term_parenthesis (Term_binop e1 \,\ e2)" definition "Term_pair' l = (case l of [] \ Term_basic [\()\] | _ \ Term_paren \(\ \)\ (term_binop \,\ l))" definition \Term_string s = Term_basic [S.flatten [\"\, s, \"\]]\ definition "Term_applys0 e l = Term_parenthesis (Term_apply e (L.map Term_parenthesis l))" definition "Term_applys e l = Term_applys0 (Term_parenthesis e) l" definition "Term_app e = Term_applys0 (Term_basic [e])" definition "Term_preunary e1 e2 = Term_apply e1 [e2]" \ \no parenthesis and separated with one space\ definition "Term_postunary e1 e2 = Term_apply e1 [e2]" \ \no parenthesis and separated with one space\ definition "Term_case = Term_fun_case o Some" definition "Term_function = Term_fun_case None" definition "Term_term' = Term_term []" definition "Lemmas_simp = Lemmas_simp_thm True" definition "Lemmas_nosimp = Lemmas_simp_thm False" definition "Consts_value = \(_)\" definition "Consts_raw0 s l e o_arg = Consts s l (String.replace_integers (\n. if n = 0x5F then \'_\ else \n\) e @@ (case o_arg of None \ \\ | Some arg \ let ap = \s. \'(\ @@ s @@ \')\ in ap (if arg = 0 then \\ else Consts_value @@ (S.flatten (L.map (\_. \,\ @@ Consts_value) (L.upto 2 arg))))))" definition "Ty_arrow = Typ_apply_bin \\\" definition "Ty_times = Typ_apply_bin \\\" definition "Ty_arrow' x = Ty_arrow x (Typ_base \_\)" definition "Ty_paren = Typ_apply_paren \(\ \)\" definition "Consts' s l e = Consts_raw0 s (Ty_arrow (Typ_base \'\\) l) e None" definition "Overloading' n ty = Overloading n (Term_annot (Term_basic [n]) ty)" locale M begin definition "Method_simp_add_del l_a l_d = Method_simp_add_del_split l_a l_d []" definition "Method_subst_l = Method_subst False" definition "rule' = Method_rule None" definition "rule = Method_rule o Some" definition "drule = Method_drule" definition "erule = Method_erule" definition "intro = Method_intro" definition "elim = Method_elim" definition "subst_l0 = Method_subst" definition "subst_l = Method_subst_l" definition insert where "insert = Method_insert o L.map Thms_single" definition plus where "plus = Method_plus" definition "option = Method_option" -definition "or = Method_or" +definition or where "or = Method_or" definition "meth_gen_simp = Method_simp_add_del [] []" definition "meth_gen_simp_add2 l1 l2 = Method_simp_add_del (L.flatten [ L.map Thms_mult l1 , L.map (Thms_single o Thm_thm) l2]) []" definition "meth_gen_simp_add_del l1 l2 = Method_simp_add_del (L.map (Thms_single o Thm_thm) l1) (L.map (Thms_single o Thm_thm) l2)" definition "meth_gen_simp_add_del_split l1 l2 l3 = Method_simp_add_del_split (L.map Thms_single l1) (L.map Thms_single l2) (L.map Thms_single l3)" definition "meth_gen_simp_add_split l1 l2 = Method_simp_add_del_split (L.map Thms_single l1) [] (L.map Thms_single l2)" definition "meth_gen_simp_only l = Method_simp_only (L.map Thms_single l)" definition "meth_gen_simp_only' l = Method_simp_only (L.map Thms_mult l)" definition "meth_gen_simp_add0 l = Method_simp_add_del (L.map Thms_single l) []" definition "simp = Method_one meth_gen_simp" definition "simp_add2 l1 l2 = Method_one (meth_gen_simp_add2 l1 l2)" definition "simp_add_del l1 l2 = Method_one (meth_gen_simp_add_del l1 l2)" definition "simp_add_del_split l1 l2 l3 = Method_one (meth_gen_simp_add_del_split l1 l2 l3)" definition "simp_add_split l1 l2 = Method_one (meth_gen_simp_add_split l1 l2)" definition "simp_only l = Method_one (meth_gen_simp_only l)" definition "simp_only' l = Method_one (meth_gen_simp_only' l)" definition "simp_add0 l = Method_one (meth_gen_simp_add0 l)" definition "simp_add = simp_add2 []" definition "simp_all = Method_all meth_gen_simp" definition "simp_all_add l = Method_all (meth_gen_simp_add2 [] l)" definition "simp_all_only l = Method_all (meth_gen_simp_only l)" definition "simp_all_only' l = Method_all (meth_gen_simp_only' l)" definition "auto_simp_add2 l1 l2 = Method_auto_simp_add_split (L.flatten [ L.map Thms_mult l1 , L.map (Thms_single o Thm_thm) l2]) []" definition "auto_simp_add_split l = Method_auto_simp_add_split (L.map Thms_single l)" definition "rename_tac = Method_rename_tac" definition "case_tac = Method_case_tac" definition "blast = Method_blast" definition "clarify = Method_clarify" definition "metis = Method_metis []" definition "metis0 = Method_metis" definition "subst_asm b = subst_l0 b [\0\]" definition "subst = subst_l [\0\]" definition "auto_simp_add = auto_simp_add2 []" definition "auto = auto_simp_add []" end lemmas [code] = \ \def\ M.Method_simp_add_del_def M.Method_subst_l_def M.rule'_def M.rule_def M.drule_def M.erule_def M.intro_def M.elim_def M.subst_l0_def M.subst_l_def M.insert_def M.plus_def M.option_def M.or_def M.meth_gen_simp_def M.meth_gen_simp_add2_def M.meth_gen_simp_add_del_def M.meth_gen_simp_add_del_split_def M.meth_gen_simp_add_split_def M.meth_gen_simp_only_def M.meth_gen_simp_only'_def M.meth_gen_simp_add0_def M.simp_def M.simp_add2_def M.simp_add_del_def M.simp_add_del_split_def M.simp_add_split_def M.simp_only_def M.simp_only'_def M.simp_add0_def M.simp_add_def M.simp_all_def M.simp_all_add_def M.simp_all_only_def M.simp_all_only'_def M.auto_simp_add2_def M.auto_simp_add_split_def M.rename_tac_def M.case_tac_def M.blast_def M.clarify_def M.metis_def M.metis0_def M.subst_asm_def M.subst_def M.auto_simp_add_def M.auto_def definition "ty_arrow l = (case rev l of x # xs \ List.fold Ty_arrow xs x)" locale C begin definition "done = Command_done" definition "by = Command_by" definition "sorry = Command_sorry" definition "apply_end = Command_apply_end" definition "apply = Command_apply" definition "using = Command_using o L.map Thms_single" definition "unfolding = Command_unfolding o L.map Thms_single" definition "let' = Command_let" definition "fix_let = Command_fix_let" definition "fix l = Command_fix_let l [] None []" definition "have n = Command_have n False" definition "have0 = Command_have" end lemmas [code] = \ \def\ C.done_def C.by_def C.sorry_def C.apply_end_def C.apply_def C.using_def C.unfolding_def C.let'_def C.fix_let_def C.fix_def C.have_def C.have0_def fun cross_abs_aux where "cross_abs_aux f l x = (\ (Suc n, Abs s _ t) \ f s (cross_abs_aux f (s # l) (n, t)) | (_, e) \ Term_term l e) x" definition "cross_abs f n l = cross_abs_aux f [] (n, l)" subsection\Operations of Fold, Map, ..., on the Meta-Model\ definition "map_lemma f = (\ Theory_lemma x \ Theory_lemma (f x) | x \ x)" end diff --git a/thys/Knot_Theory/Preliminaries.thy b/thys/Knot_Theory/Preliminaries.thy --- a/thys/Knot_Theory/Preliminaries.thy +++ b/thys/Knot_Theory/Preliminaries.thy @@ -1,309 +1,309 @@ section\Preliminaries: Definitions of tangles and links\ theory Preliminaries imports Main begin text\This theory contains the definition of a link. A link is defined as link diagrams upto equivalence moves. Link diagrams are defined in terms of the constituent tangles\ text\each block is a horizontal block built by putting basic link bricks next to each other. (1) vert is the straight line (2) cup is the up facing cup (3) cap is the bottom facing (4) over is the positive cross (5) under is the negative cross\ datatype brick = vert |cup |cap |over |under text\block is obtained by putting bricks next to each other\ type_synonym block = "brick list" text\wall are link diagrams obtained by placing a horizontal blocks a top each other\ datatype wall = basic block |prod block wall (infixr "*" 66) text\Concatenate gives us the block obtained by putting two blocks next to each other\ primrec concatenate :: "block => block => block" (infixr "\" 65) where concatenates_Nil: "[] \ ys = ys" | concatenates_Cons: "((x#xs)\ys) = x#(xs\ys)" lemma empty_concatenate: "xs \ Nil = xs" by (induction xs) (auto) text\Associativity properties of Conscatenation\ lemma leftright_associativity: "(x\y)\z = x\(y\z)" by (induction x) (auto) lemma left_associativity: "(x\y)\z = x\y\z" by (induction x) (auto) lemma right_associativity: "x\(y\z) =x \ y \z" by auto text\Compose gives us the wall obtained by putting a wall above another, perhaps in an invalid way. \ primrec compose :: "wall => wall => wall" (infixr "\" 66) where compose_Nil: "(basic x) \ ys = prod x ys" | compose_Cons: "((prod x xs)\ys) = prod x (xs\ys)" text\Associativity properties of composition\ lemma compose_leftassociativity: "(((x::wall) \ y) \ z) = (x\y \z)" by (induction x) (auto) lemma compose_rightassociativity: "(x::wall) \ (y \ z) = (x\y \z)" by (induction x) (auto) text\block-length of a block is the number of bricks in a given block\ primrec block_length::"block \ nat" where "block_length [] = 0"| "block_length (Cons x y) = 1 + (block_length y)" (*domain tells us the number of incoming strands*) primrec domain::"brick \ int" where "domain vert = 1"| "domain cup = 0"| "domain cap = 2"| "domain over = 2"| "domain under = 2" lemma domain_non_negative:"\x.(domain x) \ 0" proof- have "\x.(x = vert)\(x = over)\(x=under)\(x=cap)\(x=cup)" by (metis brick.exhaust) moreover have "\x.(((x = vert)\(x = over)\(x=under)\(x=cap)\(x=cup)) \ (domain x) \ 0)" using domain.simps by (metis order_refl zero_le_numeral zero_le_one) ultimately show ?thesis by auto qed (*co-domain tells us the number of outgoing strands*) primrec codomain::"brick \ int" where "codomain vert = 1"| "codomain cup = 2"| "codomain cap = 0"| "codomain over = 2"| "codomain under = 2" (*domain-block tells us the number of incoming strands of a block*) primrec domain_block::"block \ int " where "domain_block [] = 0" |"domain_block (Cons x y) = (domain x + (domain_block y))" lemma domain_block_non_negative:"domain_block xs \ 0" by (induction xs) (auto simp add:domain_non_negative) (*codomain-block tells us the number of outgoing strands of a block*) primrec codomain_block::"block \ int " where "codomain_block [] = 0" |"codomain_block (Cons x y) = (codomain x + (codomain_block y))" (*domain-wall tells us the number of incoming strands of a wall*) primrec domain_wall:: "wall \ int" where "domain_wall (basic x) = domain_block x" |"domain_wall (x*ys) = domain_block x" (*domain-wall tells us the number of incoming strands of a wall*) fun codomain_wall:: "wall \ int" where "codomain_wall (basic x) = codomain_block x" |"codomain_wall (x*ys) = codomain_wall ys" lemma domain_wall_compose: "domain_wall (xs\ys) = domain_wall xs" by (induction xs) (auto) lemma codomain_wall_compose: "codomain_wall (xs\ys) = codomain_wall ys" by (induction xs) (auto) text\this lemma tells us the number of incoming and outgoing strands of a composition of two wall\ text\absolute value\ definition abs::"int \ int" where "abs x \ if (x\0) then x else (0-x)" text\theorems about abs\ lemma abs_zero: assumes "abs x = 0" shows "x = 0" using abs_def assms eq_iff_diff_eq_0 by metis lemma abs_zero_equality: assumes "abs (x - y) = 0" shows "x = y" using assms abs_zero eq_iff_diff_eq_0 by blast lemma abs_non_negative: " abs x \ 0" using abs_def diff_0 le_cases neg_0_le_iff_le by auto lemma abs_non_negative_sum: assumes " abs x + abs y = 0" shows "abs x= 0" and "abs y = 0" using abs_def diff_0 abs_non_negative neg_0_le_iff_le add_nonneg_eq_0_iff assms apply (metis) by (metis abs_non_negative add_nonneg_eq_0_iff assms) text\The following lemmas tell us that the number of incoming and outgoing strands of every brick is a non negative integer\ lemma domain_nonnegative: "(domain x) \ 0" using domain.simps brick.exhaust le_cases not_numeral_le_zero zero_le_one by (metis) lemma codomain_nonnegative: "(codomain x) \ 0" by (cases x)(auto) text\The following lemmas tell us that the number of incoming and outgoing strands of every block is a non negative integer\ lemma domain_block_nonnegative: "domain_block x \ 0" by (induction x)(auto simp add: domain_nonnegative) lemma codomain_block_nonnegative: "(codomain_block x) \ 0" by (induction x)(auto simp add: codomain_nonnegative) text\The following lemmas tell us that if a block is appended to a block with incoming strands, then the resultant block has incoming strands\ lemma domain_positive: "((domain_block (x#Nil)) > 0) \ ((domain_block y) > 0) \ (domain_block (x#y) > 0)" proof- have "(domain_block (x#y)) = (domain x) + (domain_block y)" by auto also have " (domain x) = (domain_block (x#Nil))" by auto then have "(domain_block (x#Nil) > 0) = (domain x > 0)" by auto then have "((domain x > 0) \ (domain_block y > 0)) \ (domain x + domain_block y)>0" using domain_nonnegative add_nonneg_pos add_pos_nonneg domain_block_nonnegative by metis from this show "((domain_block(x#Nil)) > 0) \ ((domain_block y) > 0) \ (domain_block (x#y) > 0)" by auto qed lemma domain_additive: "(domain_block (x\y))= (domain_block x) + (domain_block y)" by (induction x)(auto) lemma codomain_additive: "(codomain_block (x\y))= (codomain_block x) + (codomain_block y)" by (induction x)(auto) lemma domain_zero_sum: assumes "(domain_block x) + (domain_block y) = 0" shows "domain_block x = 0" and "domain_block y = 0" using domain_block_nonnegative add_nonneg_eq_0_iff assms apply metis by (metis add_nonneg_eq_0_iff assms domain_block_nonnegative) -lemma domain_block_positive: assumes "domain_block y>0" or "domain_block y>0" +lemma domain_block_positive: fixes or assumes "domain_block y>0" or "domain_block y>0" shows "(domain_block (x\y)) > 0" apply (simp add: domain_additive) by (metis assms(1) domain_additive domain_block_nonnegative domain_zero_sum(2) less_le) -lemma codomain_block_positive: assumes "codomain_block y>0" or "codomain_block y>0" +lemma codomain_block_positive: fixes or assumes "codomain_block y>0" or "codomain_block y>0" shows "(codomain_block (x\y)) > 0" apply (simp add: codomain_additive) using assms(1) codomain_additive codomain_block_nonnegative eq_neg_iff_add_eq_0 le_less_trans less_le neg_less_0_iff_less by (metis) text\We prove that if the first count of a block is zero, then it is composed of cups and empty bricks. In order to do that we define the functions brick-is-cup and is-cup which check if a given block is composed of cups or if the blocks are composed of blocks\ primrec brick_is_cup::"brick \ bool" where "brick_is_cup vert = False"| "brick_is_cup cup = True"| "brick_is_cup cap = False"| "brick_is_cup over = False"| "brick_is_cup under = False" primrec is_cup::"block \ bool" where "is_cup [] = True"| "is_cup (x#y) = (if (x= cup) then (is_cup y) else False)" lemma brickcount_zero_implies_cup:"(domain x= 0) \ (x = cup)" by (cases x) (auto) lemma brickcount_zero_implies_brick_is_cup:"(domain x= 0) \ (brick_is_cup x)" by (cases x) (auto) lemma domain_zero_implies_is_cup:"(domain_block x= 0) \ (is_cup x)" proof(induction x) case Nil show ?case by auto next case (Cons a y) show ?case proof- have step1: "domain_block (a # y) = (domain a) + (domain_block y)" by auto with domain_zero_sum have"domain_block y = 0" by (metis (full_types) Cons.prems domain_block_nonnegative domain_positive leD neq_iff) then have step2: "(is_cup y)" using Cons.IH by (auto) with step1 and domain_zero_sum have "domain a= 0" using Cons.prems \domain_block y = 0\ by linarith then have "brick_is_cup a" using brickcount_zero_implies_brick_is_cup by auto then have "a=cup" using brick_is_cup_def by (metis \domain a = 0\ brickcount_zero_implies_cup) with step2 have "is_cup (a#y)" using is_cup_def by auto then show ?case by auto qed qed text\We need a function that checks if a wall represents a knot diagram.\ primrec is_tangle_diagram::"wall \ bool" where "is_tangle_diagram (basic x) = True" |"is_tangle_diagram (x*xs) = (if is_tangle_diagram xs then (codomain_block x = domain_wall xs) else False)" definition is_link_diagram::"wall \ bool" where "is_link_diagram x \ (if (is_tangle_diagram x) then (abs (domain_wall x) + abs(codomain_wall x) = 0) else False)" end diff --git a/thys/Monad_Normalisation/Monad_Normalisation_Test.thy b/thys/Monad_Normalisation/Monad_Normalisation_Test.thy --- a/thys/Monad_Normalisation/Monad_Normalisation_Test.thy +++ b/thys/Monad_Normalisation/Monad_Normalisation_Test.thy @@ -1,269 +1,269 @@ (* Title: Monad_Normalisation_Test.thy Author: Manuel Eberl, TU München Author: Andreas Lochbihler, ETH Zurich Author: Joshua Schneider, ETH Zurich *) theory Monad_Normalisation_Test imports Monad_Normalisation begin section \Tests and examples\ context includes monad_normalisation begin lemma assumes "f = id" shows "do {x \ B; z \ C x; d \ E z x; a \ D z x; y \ A; return_pmf (x,y)} = do {y \ A; x \ B; z \ C x; a \ D z x; d \ E z x; return_pmf (f (x,y))}" apply (simp) apply (simp add: assms) done lemma "(do {a \ E; b \ E; w \ B b a; z \ B a b; return_pmf (w,z)}) = (do {a \ E; b \ E; z \ B a b; w \ B b a; return_pmf (w,z)})" by (simp) lemma "(do {a \ E; b \ E; w \ B b a; z \ B a b; return_pmf (w,z)}) = (do {a \ E; b \ E; z \ B a b; w \ B b a; return_pmf (w,z)})" by (simp) lemma "do {y \ A; x \ A; z \ B x y y; w \ B x x y; Some (x,y)} = do {x \ A; y \ A; z \ B x x y; w \ B x y y; Some (x,y)}" by (simp) lemma "do {y \ A; x \ A; z \ B x y y; w \ B x x y; {x,y}} = do {x \ A; y \ A; z \ B x x y; w \ B x y y; {x,y}}" by (simp) lemma "do {y \ A; x \ A; z \ B x y y; w \ B x x y; return_pmf (x,y)} = do {x \ A; y \ A; z \ B x x y; w \ B x y y; return_pmf (x,y)}" by (simp) lemma "do {x \ A 0; y \ A x; w \ B y y; z \ B x y; a \ C; Predicate.single (a,a)} = do {x \ A 0; y \ A x; z \ B x y; w \ B y y; a \ C; Predicate.single (a,a)}" by (simp) lemma "do {x \ A 0; y \ A x; z \ B x y; w \ B y y; a \ C; return_pmf (a,a)} = do {x \ A 0; y \ A x; z \ B y y; w \ B x y; a \ C; return_pmf (a,a)}" by (simp) lemma "do {x \ B; z \ C x; d \ E z x; a \ D z x; y \ A; return_pmf (x,y)} = do {y \ A; x \ B; z \ C x; a \ D z x; d \ E z x; return_pmf (x,y)}" by (simp) no_adhoc_overloading Monad_Syntax.bind bind_pmf context fixes \1 :: "'a \ (('a \ 'a) \ 'b) spmf" and \2 :: "'a \ 'a \ 'b \ bool spmf" and sample_uniform :: "nat \ nat spmf" and order :: "'a \ nat" begin lemma "do { x \ sample_uniform (order \); y \ sample_uniform (order \); z \ sample_uniform (order \); b \ coin_spmf; ((msg1, msg2), \) \ \1 (f x); _ :: unit \ assert_spmf (valid_plain msg1 \ valid_plain msg2); guess \ \2 (f y, xor (f z) (if b then msg1 else msg2)) \; return_spmf (guess \ b) } = do { x \ sample_uniform (order \); y \ sample_uniform (order \); ((msg1, msg2), \) \ \1 (f x); _ :: unit \ assert_spmf (valid_plain msg1 \ valid_plain msg2); b \ coin_spmf; x \ sample_uniform (order \); guess \ \2 (f y, xor (f x) (if b then msg1 else msg2)) \; return_spmf (guess \ b) - }" + }" for xor by (simp add: split_def) lemma "do { x \ sample_uniform (order \); xa \ sample_uniform (order \); x \ \1 (f x); case x of (x, xb) \ (case x of (msg1, msg2) \ \\. do { a \ assert_spmf (valid_plain msg1 \ valid_plain msg2); x \ coin_spmf; xaa \ map_spmf f (sample_uniform (order \)); guess \ \2 (f xa, xaa) \; return_spmf (guess \ x) }) xb } = do { x \ sample_uniform (order \); xa \ sample_uniform (order \); x \ \1 (f x); case x of (x, xb) \ (case x of (msg1, msg2) \ \\. do { a \ assert_spmf (valid_plain msg1 \ valid_plain msg2); z \ map_spmf f (sample_uniform (order \)); guess \ \2 (f xa, z) \; map_spmf ((\) guess) coin_spmf }) xb }" by (simp add: map_spmf_conv_bind_spmf) lemma elgamal_step3: "do { x \ sample_uniform (order \); y \ sample_uniform (order \); b \ coin_spmf; p \ \1 (f x); _ \ assert_spmf (valid_plain (fst (fst p)) \ valid_plain (snd (fst p))); guess \ \2 (f y, xor (f (x * y)) (if b then fst (fst p) else snd (fst p))) (snd p); return_spmf (guess \ b) } = do { y \ sample_uniform (order \); b \ coin_spmf; p \ \1 (f y); _ \ assert_spmf (valid_plain (fst (fst p)) \ valid_plain (snd (fst p))); ya \ sample_uniform (order \); b' \ \2 (f ya, xor (f (y * ya)) (if b then fst (fst p) else snd (fst p))) (snd p); return_spmf (b' \ b) - }" + }" for xor by (simp) end text \Distributivity\ lemma "do { x \ A :: nat spmf; a \ B; b \ B; if a = b then do { return_spmf x } else do { y \ C; return_spmf (x + y) } } = do { a \ B; b \ B; if b = a then A else do { y \ C; x \ A; return_spmf (y + x) } }" by (simp add: add.commute cong: if_cong) lemma "do { x \ A :: nat spmf; p \ do { a \ B; b \ B; return_spmf (a, b) }; q \ coin_spmf; if q then do { return_spmf (x + fst p) } else do { y \ C; return_spmf (y + snd p) } } = do { q \ coin_spmf; if q then do { x \ A; a \ B; _ \ B; return_spmf (x + a) } else do { y \ C; a \ B; _ \ B; _ \ A; return_spmf (y + a) } }" by (simp cong: if_cong) lemma fixes f :: "nat \ nat \ nat + nat" shows "do { x \ (A::nat set); a \ B; b \ B; case f a b of Inl c \ {x} | Inr c \ do { y \ C x; {(x + y + c)} } } = do { a \ B; b \ B; case f b a of Inl c \ A | Inr c \ do { x \ A; y \ C x; {(y + c + x)} } }" by (simp add: add.commute add.left_commute cong: sum.case_cong) section \Limits\ text \ The following example shows that the combination of monad normalisation and regular ordered rewriting is not necessarily confluent. \ lemma "do {a \ A; b \ A; Some (a \ b, b)} = do {a \ A; b \ A; Some (a \ b, a)}" apply (simp add: conj_comms)? \ \no progress made\ apply (rewrite option_bind_commute) \ \force a particular binder order\ apply (simp only: conj_comms) done text \ The next example shows that even monad normalisation alone is not confluent because the term ordering prevents the reordering of \f A\ with \f B\. But if we change \A\ to \E\, then the reordering works as expected. \ lemma "do {a \ f A; b \ f B; c \ D b; d \ f C; F a c d} = do {b \ f B; c \ D b; a \ f A; d \ f C; F a c d}" for f :: "'b \ 'a option" and D :: "'a \ 'a option" apply(simp)? \ \no progress made\ apply(subst option_bind_commute, subst (2) option_bind_commute, rule refl) done lemma "do {a \ f E; b \ f B; c \ D b; d \ f C; F a c d} = do {b \ f B; c \ D b; a \ f E; d \ f C; F a c d}" for f :: "'b \ 'a option" and D :: "'a \ 'a option" by simp end end diff --git a/thys/MonoBoolTranAlgebra/Statements.thy b/thys/MonoBoolTranAlgebra/Statements.thy --- a/thys/MonoBoolTranAlgebra/Statements.thy +++ b/thys/MonoBoolTranAlgebra/Statements.thy @@ -1,445 +1,445 @@ section \Program statements, Hoare and refinement rules\ theory Statements imports Assertion_Algebra begin text \In this section we introduce assume, if, and while program statements as well as Hoare triples, and data refienment. We prove Hoare correctness rules for the program statements and we prove some theorems linking Hoare correctness statement to (data) refinement. Most of the theorems assume a monotonic boolean transformers algebra. The theorem stating the equivalence between a Hoare correctness triple and a refinement statement holds under the assumption that we have a monotonic boolean transformers algebra with post condition statement.\ definition "assume" :: "'a::mbt_algebra Assertion \ 'a" ("[\ _ ]" [0] 1000) where "[\p] = {\p} ^ o" lemma [simp]: "{\p} * \ \ [\p] = {\p}" apply (subgoal_tac "{\p} \ assertion") apply (subst (asm) assertion_def, simp add: assume_def) by simp lemma [simp]: "[\p] * x \ {\-p} * \ = [\p] * x" by (simp add: assume_def uminus_Assertion_def) lemma [simp]: "{\p} * \ \ [\-p] * x = [\-p] * x" by (simp add: assume_def uminus_Assertion_def) lemma assert_sup: "{\p \ q} = {\p} \ {\q}" by (simp add: sup_Assertion_def) lemma assert_inf: "{\p \ q} = {\p} \ {\q}" by (simp add: inf_Assertion_def) lemma assert_neg: "{\-p} = neg_assert {\p}" by (simp add: uminus_Assertion_def) lemma assert_false [simp]: "{\\} = \" by (simp add: bot_Assertion_def) lemma if_Assertion_assumption: "({\p} * x) \ ({\-p} * y) = ([\p] * x) \ ([\-p] * y)" proof - have "({\p} * x) \ {\-p} * y = ({\p} * \ \ [\p]) * x \ ({\-p} * \ \ [\-p]) * y" by simp also have "\ = ({\p} * \ \ ([\p] * x)) \ ({\-p} * \ \ ([\-p] * y))" by (unfold inf_comp, simp) also have "\ = (({\p} * \ \ ([\p] * x)) \ ({\-p} * \)) \ (({\p} * \ \ ([\p] * x)) \ ([\-p] * y))" by (simp add: sup_inf_distrib) also have "\ = (({\p} * \ \ ({\-p} * \)) \ (([\p] * x))) \ (([\-p] * y) \ (([\p] * x) \ ([\-p] * y)))" by (simp add: sup_inf_distrib2) also have "\ = ([\p] * x) \ ([\-p] * y) \ (([\p] * x) \ ([\-p] * y))" apply (simp add: sup_comp [THEN sym] ) by (simp add: assert_sup [THEN sym] inf_assoc) also have "\ = ([\p] * x) \ ([\-p] * y)" by (rule antisym, simp_all add: inf_assoc) finally show ?thesis . qed definition "wp x p = abs_wpt (x * {\p})" lemma wp_assume: "wp [\p] q = -p \ q" apply (simp add: wp_def abs_wpt_def) apply (rule assert_injective) apply simp by (simp add: assert_sup assert_neg assume_def wpt_dual_assertion_comp) lemma assert_commute: "y \ conjunctive \ y * {\p} = {\ wp y p } * y" apply (simp add: wp_def abs_wpt_def) by (rule assertion_commute, simp_all) lemma wp_assert: "wp {\p} q = p \ q" by (simp add: wp_def assertion_inf_comp_eq [THEN sym] assert_inf [THEN sym]) lemma wp_mono [simp]: "mono (wp x)" apply (simp add: le_fun_def wp_def abs_wpt_def less_eq_Assertion_def mono_def) apply (simp add: wpt_def, safe) apply (rule_tac y = " x * {\ xa } * \" in order_trans, simp_all) apply (rule le_comp_right) by (rule le_comp, simp) lemma wp_mono2: "p \ q \ wp x p \ wp x q" apply (cut_tac x = x in wp_mono) apply (unfold mono_def) by blast lemma wp_fun_mono [simp]: "mono wp" apply (simp add: le_fun_def wp_def abs_wpt_def less_eq_Assertion_def mono_def) apply (simp add: wpt_def, safe) apply (rule_tac y = " x * {\ xa } * \" in order_trans, simp_all) apply (rule le_comp_right) by (rule le_comp_right, simp) lemma wp_fun_mono2: "x \ y \ wp x p \ wp y p" apply (cut_tac wp_fun_mono) apply (unfold mono_def) apply (simp add: le_fun_def) by blast lemma wp_comp: "wp (x * y) p = wp x (wp y p)" apply (simp add: wp_def abs_wpt_def) by (unfold wpt_comp_2 [THEN sym] mult.assoc, simp) lemma wp_choice: "wp (x \ y) = wp x \ wp y" apply (simp add: fun_eq_iff wp_def inf_fun_def inf_comp inf_Assertion_def abs_wpt_def) by (simp add: wpt_choice) lemma [simp]: "wp 1 = id" apply (unfold fun_eq_iff, safe) apply (rule assert_injective) by (simp add: wp_def abs_wpt_def) lemma wp_omega_fix: "wp (x ^ \) p = wp x (wp (x ^ \) p) \ p" apply (subst omega_fix) by (simp add: wp_choice wp_comp) lemma wp_omega_least: "(wp x r) \ p \ r \ wp (x ^ \) p \ r" apply (simp add: wp_def abs_wpt_def inf_Assertion_def less_eq_Assertion_def) apply (simp add: wpt_def) apply (rule_tac y = "{\r} * \ \ 1" in order_trans) apply simp apply (rule_tac y = "x ^ \ * {\ p } * \" in order_trans, simp) apply (simp add: mult.assoc) apply (rule omega_least) apply (drule_tac z = \ in le_comp_right) apply (simp add: inf_comp mult.assoc [THEN sym]) by (simp add: assertion_prop) lemma Assertion_wp: "{\wp x p} = (x * {\p} * \) \ 1" apply (simp add: wp_def abs_wpt_def) by (simp add: wpt_def) definition "hoare p S q = (p \ wp S q)" definition "grd x = - (wp x \)" lemma grd_comp: "[\grd x] * x = x" apply (simp add: grd_def wp_def uminus_Assertion_def assume_def neg_assert_def abs_wpt_def dual_sup sup_comp) apply (simp add: wpt_def dual_inf sup_comp dual_comp bot_Assertion_def) by (rule antisym, simp_all) lemma assert_assume: "{\p} * [\p] = {\ p}" by (simp add: assume_def) lemma dual_assume: "[\p] ^ o = {\p}" by (simp add: assume_def) lemma assume_prop: "([\p] * \) \ 1 = [\p]" by (simp add: assume_def dual_assertion_prop) text\An alternative definition of a Hoare triple\ definition "hoare1 p S q = ([\ p ] * S * [\ -q ] = \)" lemma "hoare1 p S q = hoare p S q" apply (simp add: hoare1_def dual_inf dual_comp) apply (simp add: hoare_def wp_def less_eq_Assertion_def abs_wpt_def) apply (simp add: wpt_def) apply safe proof - assume A: "[\ p ] * S * [\ - q ] = \" have "{\p} \ {\p} * \" by simp also have "... \ {\p} * \ * \" by (unfold mult.assoc, simp) also have "... = {\p} * [\ p ] * S * [\ - q ] * \" by (subst A [THEN sym], simp add: mult.assoc) also have "... = {\p} * S * [\ - q ] * \" by (simp add: assert_assume) also have "... \ {\p} * S * {\ q } * \" apply (simp add: mult.assoc) apply (rule le_comp, rule le_comp) apply (simp add: assume_def uminus_Assertion_def) by (simp add: neg_assert_def dual_inf dual_comp sup_comp) also have "... \ S * {\ q } * \" by (simp add: mult.assoc) finally show "{\p} \ S * {\ q } * \" . next assume A: "{\ p } \ S * {\ q } * \" have "\ = ((S * {\q}) ^ o) * \ \ S * {\q} * \" by simp also have "\ \ [\p] * \ \ S * {\q} * \" apply (simp del: dual_neg_top) apply (rule_tac y = "[\p] * \" in order_trans, simp_all) apply (subst dual_le) apply (simp add: dual_comp dual_assume) apply (cut_tac x = "{\p}" and y = "S * {\q} * \" and z = \ in le_comp_right) apply (rule A) by (simp add: mult.assoc) also have "\ = [\p] * S * ({\q} * \)" apply (subst (2) assume_prop [THEN sym]) by (simp_all add: sup_comp mult.assoc) also have "\ \ [\p] * S * ({\q} * \ \ 1)" by (rule le_comp, simp) also have "\ = [\p] * S * [\-q]" apply (simp add: assume_def uminus_Assertion_def) by (simp add: neg_assert_def dual_inf dual_comp) finally show "[\p] * S * [\ - q] = \" by (rule_tac antisym, simp_all) qed lemma hoare_choice: "hoare p (x \ y) q = ((hoare p) x q & (hoare p y q))" apply (unfold hoare_def wp_choice inf_fun_def) by auto definition if_stm:: "'a::mbt_algebra Assertion \ 'a \ 'a \ 'a" ("(If (_)/ then (_)/ else (_))" [0, 0, 10] 10) where "if_stm b x y = (([\ b ] * x) \ ([\ -b ] * y))" lemma if_assertion: "(If p then x else y) = {\p} * x \ {\ -p} * y" by (simp add: if_stm_def if_Assertion_assumption) -lemma (in boolean_algebra) sup_neg_inf: +lemma (in Lattices.boolean_algebra) sup_neg_inf: "(p \ q \ r) = (p \ -q \ r)" apply (safe) apply(cut_tac a = p and c = "q \ r" and b = "-q" and d = "-q" in inf_mono) apply simp apply simp apply (simp add: inf_sup_distrib2) apply(cut_tac b = "p \ - q" and d = "r" and a = "q" and c = "q" in sup_mono) apply simp apply simp by (simp add: sup_inf_distrib) lemma hoare_if: "hoare p (If b then x else y) q = (hoare (p \ b) x q \ hoare (p \ -b) y q)" by (simp add: hoare_def if_stm_def wp_choice inf_fun_def wp_comp wp_assume sup_neg_inf) lemma hoare_comp: "hoare p (x * y) q = (\ r . (hoare p x r) \ (hoare r y q))" apply (simp add: hoare_def wp_comp) apply safe apply (rule_tac x = "wp y q" in exI, simp) apply (rule_tac y = "wp x r" in order_trans, simp) apply (rule_tac f = "wp x" in monoD) by simp_all lemma hoare_refinement: "hoare p S q = ({\p} * (post {\q}) \ S)" apply (simp add: hoare_def less_eq_Assertion_def Assertion_wp) proof assume A: "{\p} \ S * {\q} * \" have "{\p} * post {\q} = ({\p} * \ \ 1) * post {\q}" by (simp add: assertion_prop) also have "\ = {\p} * \ \ post {\q}" by (simp add: inf_comp) also have "\ \ S * {\q} * \ \ post {\q}" apply simp apply (rule_tac y = "{\p} * \" in order_trans, simp_all) apply (cut_tac x = "{\p}" and y = "S * {\q} * \" and z = \ in le_comp_right) by (rule A, simp) also have "\ \ S" by (simp add: post_2) finally show "{\p} * post {\q} \ S". next assume A: "{\p} * post {\q} \ S" have "{\p} = {\p} * \ \ 1" by (simp add: assertion_prop) also have "\ = {\p} * ((post {\q}) * {\q} * \) \ 1" by (simp add: post_1) also have "\ \ {\p} * ((post {\q}) * {\q} * \)" by simp also have "\ \ S * {\q} * \" apply (cut_tac x = "{\p} * post {\q}" and y = S and z = "{\q} * \" in le_comp_right) apply (simp add: A) by (simp add: mult.assoc) finally show "{\p} \ S * {\q} * \" . qed theorem hoare_fixpoint_mbt: "F x = x \ (!! (w::'a::well_founded) f . (\v. v < w \ hoare (p v) f q) \ hoare (p w) (F f) q) \ hoare (p u) x q" apply (rule less_induct1) proof - fix xa assume A: "\ w f. (\ v . v < w \ hoare (p v) f q) \ hoare (p w) (F f) q" assume B: "F x = x" assume C: "\y . y < xa \ hoare (p y) x q" have D: "hoare (p xa) (F x) q" apply (rule A) by (rule C, simp) show "hoare (p xa) x q" by (cut_tac D, simp add: B) qed lemma hoare_Sup: "hoare (Sup P) x q = (\ p \ P . hoare p x q)" apply (simp add: hoare_def) apply auto apply (rule_tac y = "Sup P" in order_trans, simp_all add: Sup_upper) apply (rule Sup_least) by simp theorem hoare_fixpoint_complete_mbt: "F x = x \ (!! w f . hoare (Sup_less p w) f q \ hoare (p w) (F f) q) \ hoare (Sup (range p)) x q" apply (simp add: hoare_Sup Sup_less_def, safe) apply (rule_tac F = F in hoare_fixpoint_mbt) by auto definition while:: "'a::mbt_algebra Assertion \ 'a \ 'a" ("(While (_)/ do (_))" [0, 10] 10) where "while p x = ([\ p] * x) ^ \ * [\ -p ]" lemma while_false: "(While \ do x) = 1" apply (unfold while_def) apply (subst omega_fix) by (simp_all add: assume_def) lemma while_true: "(While \ do 1) = \" apply (unfold while_def) by (rule antisym, simp_all add: assume_def) lemma hoare_wp [simp]: "hoare (wp x q) x q" by (simp add: hoare_def) lemma hoare_comp_wp: "hoare p (x * y) q = hoare p x (wp y q)" apply (unfold hoare_comp, safe) apply (simp add: hoare_def) apply (rule_tac y = "wp x r" in order_trans, simp) apply (rule wp_mono2, simp) by (rule_tac x = "wp y q" in exI, simp) lemma (in mbt_algebra) hoare_assume: "hoare p [\b] q = (p \ b \ q)" by (simp add: hoare_def wp_assume sup_neg_inf) lemma (in mbt_algebra) hoare_assume_comp: "hoare p ([\b] * x) q = hoare (p \ b) x q" apply (simp add: hoare_comp_wp hoare_assume) by (simp add: hoare_def) lemma hoare_while_mbt: "(\ (w::'b::well_founded) r . (\ v . v < w \ p v \ r) \ hoare ((p w) \ b) x r) \ (\ u . p u \ q) \ hoare (p w) (While b do x) (q \ -b)" apply (unfold while_def) apply (rule_tac F = "\z. [\ b ] * x * z \ [\ - b ]" in hoare_fixpoint_mbt) apply (simp add: mult.assoc [THEN sym]) apply (simp add: omega_comp_fix) apply (unfold hoare_choice) apply safe apply (subst hoare_comp_wp) apply (subst hoare_assume_comp) apply (drule_tac x = w in spec) apply (drule_tac x = "wp f (q \ - b)" in spec) apply (auto simp add: hoare_def) [1] apply (auto simp add: hoare_assume) apply (rule_tac y = "p w" in order_trans) by simp_all lemma hoare_while_complete_mbt: "(\ w::'b::well_founded . hoare ((p w) \ b) x (Sup_less p w)) \ hoare (Sup (range p)) (While b do x) ((Sup (range p)) \ -b)" apply (simp add: hoare_Sup, safe) apply (rule hoare_while_mbt) apply safe apply (drule_tac x = w in spec) apply (simp add: hoare_def) apply (rule_tac y = "wp x (Sup_less p w)" in order_trans, simp_all) apply (rule wp_mono2) apply (simp add: Sup_less_def) apply (rule Sup_least, auto) by (rule SUP_upper, simp) definition "datarefin S S1 D D1 = (D * S \ S1 * D1)" lemma "hoare p S q \ datarefin S S1 D D1 \ hoare (wp D p) S1 (wp D1 q)" apply (simp add: hoare_def datarefin_def) apply (simp add: wp_comp [THEN sym] mult.assoc [THEN sym]) apply (rule_tac y = "wp (D * S) q" in order_trans) apply (subst wp_comp) apply (rule monoD, simp_all) by (rule wp_fun_mono2, simp_all) lemma "hoare p S q \ datarefin ({\p} * S) S1 D D1 \ hoare (wp D p) S1 (wp D1 q)" apply (simp add: hoare_def datarefin_def) apply (rule_tac y = "wp (D * {\p} * S) q" in order_trans) apply (simp add: mult.assoc) apply (subst wp_comp) apply (rule monoD, simp_all) apply (subst wp_comp) apply (unfold wp_assert, simp) apply (unfold wp_comp [THEN sym]) apply (rule wp_fun_mono2) by (simp add: mult.assoc) lemma inf_pres_conj: "x \ conjunctive \ y \ conjunctive \ x \ y \ conjunctive" apply (subst conjunctive_def, safe) apply (simp add: inf_comp conjunctiveD) by (metis (opaque_lifting, no_types) inf_assoc inf_left_commute) lemma sup_pres_disj: "x \ disjunctive \ y \ disjunctive \ x \ y \ disjunctive" apply (subst disjunctive_def, safe) apply (simp add: sup_comp disjunctiveD) by (metis (opaque_lifting, no_types) sup_assoc sup_left_commute) lemma assumption_conjuncive [simp]: "[\p] \ conjunctive" by (simp add: assume_def dual_disjunctive assertion_disjunctive) lemma assumption_disjuncive [simp]: "[\p] \ disjunctive" by (simp add: assume_def dual_conjunctive assertion_conjunctive) lemma if_pres_conj: "x \ conjunctive \ y \ conjunctive \ (If p then x else y) \ conjunctive" apply (unfold if_stm_def) by (simp add: inf_pres_conj comp_pres_conj) lemma if_pres_disj: "x \ disjunctive \ y \ disjunctive \ (If p then x else y) \ disjunctive" apply (unfold if_assertion) by (simp add: sup_pres_disj comp_pres_disj assertion_disjunctive) lemma while_dual_star: "(While p do (x::'a::mbt_algebra)) = (({\ p} * x)^\ * {\ -p })" apply (simp add: while_def) apply (rule antisym) apply (rule omega_least) proof - have "([\ p] * x * (({\ p} * x)^\ * {\-p}) \ [\-p]) = ({\ p} * x * (({\ p} * x)^\ * {\-p})) \ {\-p}" apply (unfold mult.assoc) by (cut_tac p = p and x = "(x * (({\ p } * x)^\ * {\ -p }))" and y = 1 in if_Assertion_assumption, simp) also have "\ = ({\ p} * x)^\ * {\-p}" by (simp add: mult.assoc [THEN sym], simp add: dual_star_comp_fix [THEN sym]) finally show "[\ p ] * x * (({\ p } * x)^\ * {\ - p }) \ [\ - p ] \ ({\ p } * x)^\ * {\ - p }" by simp next show "({\ p } * x)^\ * {\ - p } \ ([\ p ] * x) ^ \ * [\ - p ]" apply (rule dual_star_least) proof - have "{\ p } * x * (([\ p ] * x) ^ \ * [\ - p ]) \ {\ - p } = [\ p ] * x * (([\ p ] * x) ^ \ * [\ - p ]) \ [\ - p ]" apply (unfold mult.assoc) by (cut_tac p = p and x = "(x * (([\p] * x)^\ * [\-p]))" and y = 1 in if_Assertion_assumption, simp) also have "... = ([\ p ] * x) ^ \ * [\ - p ]" apply (simp add: mult.assoc [THEN sym]) by (metis omega_comp_fix) finally show "{\ p } * x * (([\ p ] * x) ^ \ * [\ - p ]) \ {\ - p } \ ([\ p ] * x) ^ \ * [\ - p ] " by simp qed qed lemma while_pres_disj: "(x::'a::mbt_algebra) \ disjunctive \ (While p do x) \ disjunctive" apply (unfold while_dual_star) apply (rule comp_pres_disj) apply (rule dual_star_pres_disj) by (rule comp_pres_disj, simp_all add: assertion_disjunctive) lemma while_pres_conj: "(x::'a::mbt_algebra_fusion) \ conjunctive \ (While p do x) \ conjunctive" apply(unfold while_def) by (simp add: comp_pres_conj omega_pres_conj) no_notation bot ("\") and top ("\") and inf (infixl "\" 70) and sup (infixl "\" 65) and Inf ("\_" [900] 900) and Sup ("\_" [900] 900) no_syntax "_INF1" :: "pttrns \ 'b \ 'b" ("(3\_./ _)" [0, 10] 10) "_INF" :: "pttrn \ 'a set \ 'b \ 'b" ("(3\_\_./ _)" [0, 0, 10] 10) "_SUP1" :: "pttrns \ 'b \ 'b" ("(3\_./ _)" [0, 10] 10) "_SUP" :: "pttrn \ 'a set \ 'b \ 'b" ("(3\_\_./ _)" [0, 0, 10] 10) end diff --git a/thys/Order_Lattice_Props/Order_Duality.thy b/thys/Order_Lattice_Props/Order_Duality.thy --- a/thys/Order_Lattice_Props/Order_Duality.thy +++ b/thys/Order_Lattice_Props/Order_Duality.thy @@ -1,320 +1,315 @@ (* Title: Ad-Hoc Duality for Orderings and Lattices Author: Georg Struth Maintainer: Georg Struth *) section \Ad-Hoc Duality for Orderings and Lattices\ theory Order_Duality imports Sup_Lattice begin text \This component presents an "explicit" formalisation of order and lattice duality. It augments the data type based one used by Wenzel in his lattice components \cite{Wenzel}, and complements the "implicit" formalisation given by locales. It uses a functor dual, supplied within a type class, which is simply a bijection (isomorphism) between types, with the constraint that the dual of a dual object is the original object. In Wenzel's formalisation, by contrast, dual is a bijection, but not idempotent or involutive. In the past, Preoteasa has used a similar approach with Isabelle~\cite{Preoteasa11b}.\ text \Duality is such a fundamental concept in order and lattice theory that it probably deserves to be included in the type classes for these objects, as in this section.\ class dual = fixes dual :: "'a \ 'a" ("\") assumes inj_dual: "inj \" and invol_dual [simp]: "\ \ \ = id" text \This type class allows one to define a type dual. It is actually a dependent type for which dual can be instantiated.\ typedef (overloaded) 'a dual = "range (dual::'a::dual \ 'a)" by fastforce setup_lifting type_definition_dual text \At the moment I have no use for this type.\ context dual begin lemma invol_dual_var [simp]: "\ (\ x) = x" by (simp add: pointfree_idE) lemma surj_dual: "surj \" unfolding surj_def by (metis invol_dual_var) lemma bij_dual: "bij \" by (simp add: bij_def inj_dual surj_dual) lemma inj_dual_iff: "(\ x = \ y) = (x = y)" by (meson inj_dual injD) lemma dual_iff: "(\ x = y) = (x = \ y)" by auto lemma the_inv_dual: "the_inv \ = \" by (metis comp_apply id_def invol_dual_var inj_dual surj_dual surj_fun_eq the_inv_f_o_f_id) end text \In boolean algebras, duality is of course De Morgan duality and can be expressed within the language.\ -sublocale boolean_algebra \ ba_dual: dual "uminus" +sublocale Lattices.boolean_algebra \ ba_dual: dual "uminus" by (unfold_locales, simp_all add: inj_def) definition map_dual:: "('a \ 'b) \ 'a::dual \ 'b::dual" ("\\<^sub>F") where "\\<^sub>F f = \ \ f \ \" lemma map_dual_func1: "\\<^sub>F (f \ g) = \\<^sub>F f \ \\<^sub>F g" by (metis (no_types, lifting) comp_assoc comp_id invol_dual map_dual_def) lemma map_dual_func2 [simp]: "\\<^sub>F id = id" by (simp add: map_dual_def) lemma map_dual_nat_iso: "\\<^sub>F f \ \ = \ \ id f" by (simp add: comp_assoc map_dual_def) lemma map_dual_invol [simp]: "\\<^sub>F \ \\<^sub>F = id" unfolding map_dual_def comp_def fun_eq_iff by simp text \Thus map-dual is naturally isomorphic to the identify functor: The function dual is a natural transformation between map-dual and the identity functor, and, because it has a two-sided inverse --- itself, it is a natural isomorphism.\ text \The generic function set-dual provides another natural transformation (see below). Before introducing it, we introduce useful notation for a widely used function.\ abbreviation "\ \ (\x. {x})" lemma eta_inj: "inj \" by simp definition "set_dual = \ \ \" lemma set_dual_prop: "set_dual (\ x) = {x}" by (metis comp_apply dual_iff set_dual_def) text \The next four lemmas show that (functional) image and preimage are functors (on functions). This does not really belong here, but it is useful for what follows. The interaction between duality and (pre)images is needed in applications.\ lemma image_func1: "(`) (f \ g) = (`) f \ (`) g" unfolding fun_eq_iff by (simp add: image_comp) lemma image_func2: "(`) id = id" by simp lemma vimage_func1: "(-`) (f \ g) = (-`) g \ (-`) f" unfolding fun_eq_iff by (simp add: vimage_comp) lemma vimage_func2: "(-`) id = id" by simp lemma iso_image: "mono ((`) f)" by (simp add: image_mono monoI) lemma iso_preimage: "mono ((-`) f)" by (simp add: monoI vimage_mono) context dual begin lemma image_dual [simp]: "(`) \ \ (`) \ = id" by (metis image_func1 image_func2 invol_dual) lemma vimage_dual [simp]: "(-`) \ \ (-`) \ = id" by (simp add: set.comp) end text \The following natural transformation between the powerset functor (image) and the identity functor is well known.\ lemma power_set_func_nat_trans: "\ \ id f = (`) f \ \" unfolding fun_eq_iff comp_def by simp text \As an instance, set-dual is a natural transformation with built-in type coercion.\ lemma dual_singleton: "(`) \ \ \ = \ \ \" by auto lemma finite_dual [simp]: "finite \ (`) \ = finite" unfolding fun_eq_iff comp_def using inj_dual finite_vimageI inj_vimage_image_eq by fastforce lemma finite_dual_var [simp]: "finite (\ ` X) = finite X" by (metis comp_def finite_dual) lemma subset_dual: "(X = \ ` Y) = (\ ` X = Y)" by (metis image_dual pointfree_idE) lemma subset_dual1: "(X \ Y) = (\ ` X \ \ ` Y)" by (simp add: inj_dual inj_image_subset_iff) lemma dual_empty [simp]: "\ ` {} = {}" by simp lemma dual_UNIV [simp]: "\ ` UNIV = UNIV" by (simp add: surj_dual) lemma fun_dual1: "(f = g \ \) = (f \ \ = g)" by (metis comp_assoc comp_id invol_dual) lemma fun_dual2: "(f = \ \ g) = (\ \ f = g)" by (metis comp_assoc fun.map_id invol_dual) lemma fun_dual3: "(f = g \ (`) \) = (f \ (`) \ = g)" by (metis comp_id image_dual o_assoc) lemma fun_dual4: "(f = (`) \ \ g) = ((`) \ \ f = g)" by (metis comp_assoc id_comp image_dual) lemma fun_dual5: "(f = \ \ g \ \) = (\ \ f \ \ = g)" by (metis comp_assoc fun_dual1 fun_dual2) lemma fun_dual6: "(f = (`) \ \ g \ (`) \) = ((`) \ \ f \ (`) \ = g)" by (simp add: comp_assoc fun_dual3 fun_dual4) lemma fun_dual7: "(f = \ \ g \ (`) \) = (\ \ f \ (`) \ = g)" by (simp add: comp_assoc fun_dual2 fun_dual3) lemma fun_dual8: "(f = (`) \ \ g \ \) = ((`) \ \ f \ \ = g)" by (simp add: comp_assoc fun_dual1 fun_dual4) lemma map_dual_dual: "(\\<^sub>F f = g) = (\\<^sub>F g = f)" by (metis map_dual_invol pointfree_idE) text \The next facts show incrementally that the dual of a complete lattice is a complete lattice.\ class ord_with_dual = dual + ord + assumes ord_dual: "x \ y \ \ y \ \ x" begin lemma dual_dual_ord: "(\ x \ \ y) = (y \ x)" by (metis dual_iff ord_dual) end lemma ord_pres_dual: fixes f :: "'a::ord_with_dual \ 'b::ord_with_dual" shows "ord_pres f \ ord_pres (\\<^sub>F f)" by (simp add: dual_dual_ord map_dual_def ord_pres_def) lemma map_dual_anti: "(f::'a::ord_with_dual \ 'b::ord_with_dual) \ g \ \\<^sub>F g \ \\<^sub>F f" by (simp add: le_fun_def map_dual_def ord_dual) class preorder_with_dual = ord_with_dual + preorder begin lemma less_dual_def_var: "(\ y < \ x) = (x < y)" by (simp add: dual_dual_ord less_le_not_le) end class order_with_dual = preorder_with_dual + order lemma iso_map_dual: fixes f :: "'a::order_with_dual \ 'b::order_with_dual" shows "mono f \ mono (\\<^sub>F f)" by (simp add: ord_pres_dual ord_pres_mono) class lattice_with_dual = lattice + dual + assumes sup_dual_def: "\ (x \ y) = \ x \ \ y" begin subclass order_with_dual by (unfold_locales, metis inf.absorb_iff2 sup_absorb1 sup_commute sup_dual_def) lemma inf_dual: "\ (x \ y) = \ x \ \ y" by (metis invol_dual_var sup_dual_def) lemma inf_to_sup: "x \ y = \ (\ x \ \ y)" using inf_dual dual_iff by fastforce lemma sup_to_inf: "x \ y = \ (\ x \ \ y)" by (simp add: inf_dual) end class bounded_lattice_with_dual = lattice_with_dual + bounded_lattice begin lemma bot_dual: "\ \ = \" by (metis dual_dual_ord dual_iff le_bot top_greatest) lemma top_dual: "\ \ = \" using bot_dual dual_iff by force end class boolean_algebra_with_dual = lattice_with_dual + boolean_algebra -sublocale boolean_algebra \ badual: boolean_algebra_with_dual _ _ _ _ _ _ _ _ uminus +sublocale Lattices.boolean_algebra \ badual: boolean_algebra_with_dual _ _ _ _ _ _ _ _ uminus by unfold_locales simp_all class Sup_lattice_with_dual = Sup_lattice + dual + assumes Sups_dual_def: "\ \ Sup = Infs \ (`) \" class Inf_lattice_with_dual = Inf_lattice + dual + assumes Sups_dual_def: "\ \ Supi = Inf \ (`) \" class complete_lattice_with_dual = complete_lattice + dual + assumes Sups_dual_def: "\ \ Sup = Inf \ (`) \" sublocale Sup_lattice_with_dual \ sclatd: complete_lattice_with_dual Infs Sup infs "(\)" le sups bots tops "\" by (unfold_locales, simp add: Sups_dual_def) sublocale Inf_lattice_with_dual \ iclatd: complete_lattice_with_dual Inf Supi infi "(\)" le supi boti topi "\" by (unfold_locales, simp add: Sups_dual_def) context complete_lattice_with_dual begin lemma Inf_dual: "\ \ Inf = Sup \ (`) \" by (metis comp_assoc comp_id fun.map_id Sups_dual_def image_dual invol_dual) lemma Inf_dual_var: "\ (\X) = \(\ ` X)" using comp_eq_dest Inf_dual by fastforce lemma Inf_to_Sup: "Inf = \ \ Sup \ (`) \" by (auto simp add: Sups_dual_def image_comp) lemma Inf_to_Sup_var: "\X = \ (\(\ ` X))" using Inf_dual_var dual_iff by fastforce lemma Sup_to_Inf: "Sup = \ \ Inf \ (`) \" by (auto simp add: Inf_dual image_comp) lemma Sup_to_Inf_var: "\X = \ (\(\ ` X))" using Sup_to_Inf by force lemma Sup_dual_def_var: "\ (\X) = \ (\ ` X)" using comp_eq_dest Sups_dual_def by fastforce lemma bot_dual_def: "\ \ = \" by (smt Inf_UNIV Sup_UNIV Sups_dual_def surj_dual o_eq_dest) lemma top_dual_def: "\ \ = \" using bot_dual_def dual_iff by blast lemma inf_dual2: "\ (x \ y) = \ x \ \ y" by (smt comp_eq_elim Inf_dual Inf_empty Inf_insert SUP_insert inf_top.right_neutral) lemma sup_dual: "\ (x \ y) = \ x \ \ y" by (metis inf_dual2 dual_iff) subclass lattice_with_dual by (unfold_locales, auto simp: inf_dual sup_dual) subclass bounded_lattice_with_dual.. end end - - - - - diff --git a/thys/Order_Lattice_Props/Order_Lattice_Props.thy b/thys/Order_Lattice_Props/Order_Lattice_Props.thy --- a/thys/Order_Lattice_Props/Order_Lattice_Props.thy +++ b/thys/Order_Lattice_Props/Order_Lattice_Props.thy @@ -1,1269 +1,1269 @@ (* Title: Properties of Orderings and Lattices Author: Georg Struth Maintainer: Georg Struth *) section \Properties of Orderings and Lattices\ theory Order_Lattice_Props imports Order_Duality begin subsection \Basic Definitions for Orderings and Lattices\ text \The first definition is for order morphisms --- isotone (order-preserving, monotone) functions. An order isomorphism is an order-preserving bijection. This should be defined in the class ord, but mono requires order.\ definition ord_homset :: "('a::order \ 'b::order) set" where "ord_homset = {f::'a::order \ 'b::order. mono f}" definition ord_embed :: "('a::order \ 'b::order) \ bool" where "ord_embed f = (\x y. f x \ f y \ x \ y)" definition ord_iso :: "('a::order \ 'b::order) \ bool" where "ord_iso = bij \ mono \ (mono \ the_inv)" lemma ord_embed_alt: "ord_embed f = (mono f \ (\x y. f x \ f y \ x \ y))" using mono_def ord_embed_def by auto lemma ord_embed_homset: "ord_embed f \ f \ ord_homset" by (simp add: mono_def ord_embed_def ord_homset_def) lemma ord_embed_inj: "ord_embed f \ inj f" unfolding ord_embed_def inj_def by (simp add: eq_iff) lemma ord_iso_ord_embed: "ord_iso f \ ord_embed f" unfolding ord_iso_def ord_embed_def bij_def inj_def mono_def by (clarsimp, metis inj_def the_inv_f_f) lemma ord_iso_alt: "ord_iso f = (ord_embed f \ surj f)" unfolding ord_iso_def ord_embed_def surj_def bij_def inj_def mono_def apply safe by simp_all (metis eq_iff inj_def the_inv_f_f)+ lemma ord_iso_the_inv: "ord_iso f \ mono (the_inv f)" by (simp add: ord_iso_def) lemma ord_iso_inv1: "ord_iso f \ (the_inv f) \ f = id" using ord_embed_inj ord_iso_ord_embed the_inv_into_f_f by fastforce lemma ord_iso_inv2: "ord_iso f \ f \ (the_inv f) = id" using f_the_inv_into_f ord_embed_inj ord_iso_alt by fastforce typedef (overloaded) ('a,'b) ord_homset = "ord_homset::('a::order \ 'b::order) set" by (force simp: ord_homset_def mono_def) setup_lifting type_definition_ord_homset text \The next definition is for the set of fixpoints of a given function. It is important in the context of orders, for instance for proving Tarski's fixpoint theorem, but does not really belong here.\ definition Fix :: "('a \ 'a) \ 'a set" where "Fix f = {x. f x = x}" lemma retraction_prop: "f \ f = f \ f x = x \ x \ range f" by (metis comp_apply f_inv_into_f rangeI) lemma retraction_prop_fix: "f \ f = f \ range f = Fix f" unfolding Fix_def using retraction_prop by fastforce lemma Fix_map_dual: "Fix \ \\<^sub>F = (`) \ \ Fix" unfolding Fix_def map_dual_def comp_def fun_eq_iff by (smt Collect_cong invol_dual pointfree_idE setcompr_eq_image) lemma Fix_map_dual_var: "Fix (\\<^sub>F f) = \ ` (Fix f)" by (metis Fix_map_dual o_def) lemma gfp_dual: "(\::'a::complete_lattice_with_dual \ 'a) \ gfp = lfp \ \\<^sub>F" proof- {fix f:: "'a \ 'a" have "\ (gfp f) = \ (\{u. u \ f u})" by (simp add: gfp_def) also have "... = \(\ ` {u. u \ f u})" by (simp add: Sup_dual_def_var) also have "... = \{\ u |u. u \ f u}" by (simp add: setcompr_eq_image) also have "... = \{u |u. (\\<^sub>F f) u \ u}" by (metis (no_types, opaque_lifting) dual_dual_ord dual_iff map_dual_def o_def) finally have "\ (gfp f) = lfp (\\<^sub>F f)" by (metis lfp_def)} thus ?thesis by auto qed lemma gfp_dual_var: fixes f :: "'a::complete_lattice_with_dual \ 'a" shows "\ (gfp f) = lfp (\\<^sub>F f)" using comp_eq_elim gfp_dual by blast lemma gfp_to_lfp: "gfp = (\::'a::complete_lattice_with_dual \ 'a) \ lfp \ \\<^sub>F" by (simp add: comp_assoc fun_dual2 gfp_dual) lemma gfp_to_lfp_var: fixes f :: "'a::complete_lattice_with_dual \ 'a" shows "gfp f = \ (lfp (\\<^sub>F f))" by (metis gfp_dual_var invol_dual_var) lemma lfp_dual: "(\::'a::complete_lattice_with_dual \ 'a) \ lfp = gfp \ \\<^sub>F" by (simp add: comp_assoc gfp_to_lfp map_dual_invol) lemma lfp_dual_var: fixes f :: "'a::complete_lattice_with_dual \ 'a" shows "\ (lfp f) = gfp (map_dual f)" using comp_eq_dest_lhs lfp_dual by fastforce lemma lfp_to_gfp: "lfp = (\::'a::complete_lattice_with_dual \ 'a) \ gfp \ \\<^sub>F" by (simp add: comp_assoc gfp_dual map_dual_invol) lemma lfp_to_gfp_var: fixes f :: "'a::complete_lattice_with_dual \ 'a" shows "lfp f = \ (gfp (\\<^sub>F f))" by (metis invol_dual_var lfp_dual_var) lemma lfp_in_Fix: fixes f :: "'a::complete_lattice \ 'a" shows "mono f \ lfp f \ Fix f" by (metis (mono_tags, lifting) Fix_def lfp_unfold mem_Collect_eq) lemma gfp_in_Fix: fixes f :: "'a::complete_lattice \ 'a" shows "mono f \ gfp f \ Fix f" by (metis (mono_tags, lifting) Fix_def gfp_unfold mem_Collect_eq) lemma nonempty_Fix: fixes f :: "'a::complete_lattice \ 'a" shows "mono f \ Fix f \ {}" using lfp_in_Fix by fastforce text \Next the minimal and maximal elements of an ordering are defined.\ context ord begin definition min_set :: "'a set \ 'a set" where "min_set X = {y \ X. \x \ X. x \ y \ x = y}" definition max_set :: "'a set \ 'a set" where "max_set X = {x \ X. \y \ X. x \ y \ x = y}" end context ord_with_dual begin lemma min_max_set_dual: "(`) \ \ min_set = max_set \ (`) \" unfolding max_set_def min_set_def fun_eq_iff comp_def apply safe using dual_dual_ord inj_dual_iff by auto lemma min_max_set_dual_var: "\ ` (min_set X) = max_set (\ ` X)" using comp_eq_dest min_max_set_dual by fastforce lemma max_min_set_dual: "(`) \ \ max_set = min_set \ (`) \" by (metis (no_types, opaque_lifting) comp_id fun.map_comp id_comp image_dual min_max_set_dual) lemma min_to_max_set: "min_set = (`) \ \ max_set \ (`) \" by (metis comp_id image_dual max_min_set_dual o_assoc) lemma max_min_set_dual_var: "\ ` (max_set X) = min_set (\ ` X)" using comp_eq_dest max_min_set_dual by fastforce lemma min_to_max_set_var: "min_set X = \ ` (max_set (\ ` X))" by (simp add: max_min_set_dual_var pointfree_idE) end text \Next, directed and filtered sets, upsets, downsets, filters and ideals in posets are defined.\ context ord begin definition directed :: "'a set \ bool" where "directed X = (\Y. finite Y \ Y \ X \ (\x \ X. \y \ Y. y \ x))" definition filtered :: "'a set \ bool" where "filtered X = (\Y. finite Y \ Y \ X \ (\x \ X. \y \ Y. x \ y))" definition downset_set :: "'a set \ 'a set" ("\") where "\X = {y. \x \ X. y \ x}" definition upset_set :: "'a set \ 'a set" ("\") where "\X = {y. \x \ X. x \ y}" definition downset :: "'a \ 'a set" ("\") where "\ = \ \ \" definition upset :: "'a \ 'a set" ("\") where "\ = \ \ \" definition downsets :: "'a set set" where "downsets = Fix \" definition upsets :: "'a set set" where "upsets = Fix \" definition "downclosed_set X = (X \ downsets)" definition "upclosed_set X = (X \ upsets)" definition ideals :: "'a set set" where "ideals = {X. X \ {} \ downclosed_set X \ directed X}" definition filters :: "'a set set" where "filters = {X. X \ {} \ upclosed_set X \ filtered X}" abbreviation "idealp X \ X \ ideals" abbreviation "filterp X \ X \ filters" end text \These notions are pair-wise dual.\ text \Filtered and directed sets are dual.\ context ord_with_dual begin lemma filtered_directed_dual: "filtered \ (`) \ = directed" unfolding filtered_def directed_def fun_eq_iff comp_def apply clarsimp apply safe apply (meson finite_imageI imageI image_mono dual_dual_ord) by (smt finite_subset_image imageE ord_dual) lemma directed_filtered_dual: "directed \ (`) \ = filtered" using filtered_directed_dual by (metis comp_id image_dual o_assoc) lemma filtered_to_directed: "filtered X = directed (\ ` X)" by (metis comp_apply directed_filtered_dual) text \Upsets and downsets are dual.\ lemma downset_set_upset_set_dual: "(`) \ \ \ = \ \ (`) \" unfolding downset_set_def upset_set_def fun_eq_iff comp_def apply safe apply (meson image_eqI ord_dual) by (clarsimp, metis (mono_tags, lifting) dual_iff image_iff mem_Collect_eq ord_dual) lemma upset_set_downset_set_dual: "(`) \ \ \ = \ \ (`) \" using downset_set_upset_set_dual by (metis (no_types, opaque_lifting) comp_id id_comp image_dual o_assoc) lemma upset_set_to_downset_set: "\ = (`) \ \ \ \ (`) \" by (simp add: comp_assoc downset_set_upset_set_dual) lemma upset_set_to_downset_set2: "\ X = \ ` (\ (\ ` X))" by (simp add: upset_set_to_downset_set) lemma downset_upset_dual: "(`) \ \ \ = \ \ \" using downset_def upset_def upset_set_to_downset_set by fastforce lemma upset_to_downset: "(`) \ \ \ = \ \ \" by (metis comp_assoc id_apply ord.downset_def ord.upset_def power_set_func_nat_trans upset_set_downset_set_dual) lemma upset_to_downset2: "\ = (`) \ \ \ \ \" by (simp add: comp_assoc downset_upset_dual) lemma upset_to_downset3: "\ x = \ ` (\ (\ x))" by (simp add: upset_to_downset2) lemma downsets_upsets_dual: "(X \ downsets) = (\ ` X \ upsets)" unfolding downsets_def upsets_def Fix_def by (smt comp_eq_dest downset_set_upset_set_dual image_inv_f_f inj_dual mem_Collect_eq) lemma downset_setp_upset_setp_dual: "upclosed_set \ (`) \ = downclosed_set" unfolding downclosed_set_def upclosed_set_def using downsets_upsets_dual by fastforce lemma upsets_to_downsets: "(X \ upsets) = (\ ` X \ downsets)" by (simp add: downsets_upsets_dual image_comp) lemma upset_setp_downset_setp_dual: "downclosed_set \ (`) \ = upclosed_set" by (metis comp_id downset_setp_upset_setp_dual image_dual o_assoc) text \Filters and ideals are dual.\ lemma ideals_filters_dual: "(X \ ideals) = ((\ ` X) \ filters)" by (smt comp_eq_dest_lhs directed_filtered_dual image_inv_f_f image_is_empty inv_unique_comp filters_def ideals_def inj_dual invol_dual mem_Collect_eq upset_setp_downset_setp_dual) lemma idealp_filterp_dual: "idealp = filterp \ (`) \" unfolding fun_eq_iff by (simp add: ideals_filters_dual) lemma filters_to_ideals: "(X \ filters) = ((\ ` X) \ ideals)" by (simp add: ideals_filters_dual image_comp) lemma filterp_idealp_dual: "filterp = idealp \ (`) \" unfolding fun_eq_iff by (simp add: filters_to_ideals) end subsection \Properties of Orderings\ context ord begin lemma directed_nonempty: "directed X \ X \ {}" unfolding directed_def by fastforce lemma directed_ub: "directed X \ (\x \ X. \y \ X. \z \ X. x \ z \ y \ z)" by (meson empty_subsetI directed_def finite.emptyI finite_insert insert_subset order_refl) lemma downset_set_prop: "\ = Union \ (`) \" unfolding downset_set_def downset_def fun_eq_iff by fastforce lemma downset_set_prop_var: "\X = (\x \ X. \x)" by (simp add: downset_set_prop) lemma downset_prop: "\x = {y. y \ x}" unfolding downset_def downset_set_def fun_eq_iff by fastforce lemma downset_prop2: "y \ x \ y \ \x" by (simp add: downset_prop) lemma ideals_downsets: "X \ ideals \ X \ downsets" by (simp add: downclosed_set_def ideals_def) lemma ideals_directed: "X \ ideals \ directed X" by (simp add: ideals_def) end context preorder begin lemma directed_prop: "X \ {} \ (\x \ X. \y \ X. \z \ X. x \ z \ y \ z) \ directed X" proof- assume h1: "X \ {}" and h2: "\x \ X. \y \ X. \z \ X. x \ z \ y \ z" {fix Y have "finite Y \ Y \ X \ (\x \ X. \y \ Y. y \ x)" proof (induct rule: finite_induct) case empty then show ?case using h1 by blast next case (insert x F) then show ?case by (metis h2 insert_iff insert_subset order_trans) qed} thus ?thesis by (simp add: directed_def) qed lemma directed_alt: "directed X = (X \ {} \ (\x \ X. \y \ X. \z \ X. x \ z \ y \ z))" by (metis directed_prop directed_nonempty directed_ub) lemma downset_set_prop_var2: "x \ \X \ y \ x \ y \ \X" unfolding downset_set_def using order_trans by blast lemma downclosed_set_iff: "downclosed_set X = (\x \ X. \y. y \ x \ y \ X)" unfolding downclosed_set_def downsets_def Fix_def downset_set_def by auto lemma downclosed_downset_set: "downclosed_set (\X)" by (simp add: downclosed_set_iff downset_set_prop_var2 downset_def) lemma downclosed_downset: "downclosed_set (\x)" by (simp add: downclosed_downset_set downset_def) lemma downset_set_ext: "id \ \" unfolding le_fun_def id_def downset_set_def by auto lemma downset_set_iso: "mono \" unfolding mono_def downset_set_def by blast lemma downset_set_idem [simp]: "\ \ \ = \" unfolding fun_eq_iff downset_set_def using order_trans by auto lemma downset_faithful: "\x \ \y \ x \ y" by (simp add: downset_prop subset_eq) lemma downset_iso_iff: "(\x \ \y) = (x \ y)" using atMost_iff downset_prop order_trans by blast text \The following proof uses the Axiom of Choice.\ lemma downset_directed_downset_var [simp]: "directed (\X) = directed X" proof assume h1: "directed X" {fix Y assume h2: "finite Y" and h3: "Y \ \X" hence "\y. \x. y \ Y \ x \ X \ y \ x" by (force simp: downset_set_def) hence "\f. \y. y \ Y \ f y \ X \ y \ f y" by (rule choice) hence "\f. finite (f ` Y) \ f ` Y \ X \ (\y \ Y. y \ f y)" by (metis finite_imageI h2 image_subsetI) hence "\Z. finite Z \ Z \ X \ (\y \ Y. \ z \ Z. y \ z)" by fastforce hence "\Z. finite Z \ Z \ X \ (\y \ Y. \ z \ Z. y \ z) \ (\x \ X. \ z \ Z. z \ x)" by (metis directed_def h1) hence "\x \ X. \y \ Y. y \ x" by (meson order_trans)} thus "directed (\X)" unfolding directed_def downset_set_def by fastforce next assume "directed (\X)" thus "directed X" unfolding directed_def downset_set_def apply clarsimp by (smt Ball_Collect order_refl order_trans subsetCE) qed lemma downset_directed_downset [simp]: "directed \ \ = directed" unfolding fun_eq_iff by simp lemma directed_downset_ideals: "directed (\X) = (\X \ ideals)" by (metis (mono_tags, lifting) CollectI Fix_def directed_alt downset_set_idem downclosed_set_def downsets_def ideals_def o_def ord.ideals_directed) lemma downclosed_Fix: "downclosed_set X = (\X = X)" by (metis (mono_tags, lifting) CollectD Fix_def downclosed_downset_set downclosed_set_def downsets_def) end lemma downset_iso: "mono (\::'a::order \ 'a set)" by (simp add: downset_iso_iff mono_def) lemma mono_downclosed: fixes f :: "'a::order \ 'b::order" assumes "mono f" shows "\Y. downclosed_set Y \ downclosed_set (f -` Y)" by (simp add: assms downclosed_set_iff monoD) lemma fixes f :: "'a::order \ 'b::order" assumes "mono f" shows "\Y. downclosed_set X \ downclosed_set (f ` X)" (*nitpick*) oops lemma downclosed_mono: fixes f :: "'a::order \ 'b::order" assumes "\Y. downclosed_set Y \ downclosed_set (f -` Y)" shows "mono f" proof- {fix x y :: "'a::order" assume h: "x \ y" have "downclosed_set (\ (f y))" unfolding downclosed_set_def downsets_def Fix_def downset_set_def downset_def by auto hence "downclosed_set (f -` (\ (f y)))" by (simp add: assms) hence "downclosed_set {z. f z \ f y}" unfolding vimage_def downset_def downset_set_def by auto hence "\z w. (f z \ f y \ w \ z) \ f w \ f y" unfolding downclosed_set_def downclosed_set_def downsets_def Fix_def downset_set_def by force hence "f x \ f y" using h by blast} thus ?thesis.. qed lemma mono_downclosed_iff: "mono f = (\Y. downclosed_set Y \ downclosed_set (f -` Y))" using mono_downclosed downclosed_mono by auto context order begin lemma downset_inj: "inj \" by (metis injI downset_iso_iff order.eq_iff) lemma "(X \ Y) = (\X \ \Y)" (*nitpick*) oops end context lattice begin lemma lat_ideals: "X \ ideals = (X \ {} \ X \ downsets \ (\x \ X. \ y \ X. x \ y \ X))" unfolding ideals_def directed_alt downsets_def Fix_def downset_set_def downclosed_set_def by (clarsimp, smt sup.cobounded1 sup.orderE sup.orderI sup_absorb2 sup_left_commute mem_Collect_eq) end context bounded_lattice begin lemma bot_ideal: "X \ ideals \ \ \ X" unfolding ideals_def downclosed_set_def downsets_def Fix_def downset_set_def by fastforce end context complete_lattice begin lemma Sup_downset_id [simp]: "Sup \ \ = id" using Sup_atMost atMost_def downset_prop by fastforce lemma downset_Sup_id: "id \ \ \ Sup" by (simp add: Sup_upper downset_prop le_funI subsetI) lemma Inf_Sup_var: "\(\x \ X. \x) = \X" unfolding downset_prop by (simp add: Collect_ball_eq Inf_eq_Sup) lemma Inf_pres_downset_var: "(\x \ X. \x) = \(\X)" unfolding downset_prop by (safe, simp_all add: le_Inf_iff) end subsection \Dual Properties of Orderings\ context ord_with_dual begin lemma filtered_nonempty: "filtered X \ X \ {}" using filtered_to_directed ord.directed_nonempty by auto lemma filtered_lb: "filtered X \ (\x \ X. \y \ X. \z \ X. z \ x \ z \ y)" using filtered_to_directed directed_ub dual_dual_ord by fastforce lemma upset_set_prop_var: "\X = (\x \ X. \x)" by (simp add: image_Union downset_set_prop_var upset_set_to_downset_set2 upset_to_downset2) lemma upset_set_prop: "\ = Union \ (`) \" unfolding fun_eq_iff by (simp add: upset_set_prop_var) lemma upset_prop: "\x = {y. x \ y}" unfolding upset_to_downset3 downset_prop image_def using dual_dual_ord by fastforce lemma upset_prop2: "x \ y \ y \ \x" by (simp add: upset_prop) lemma filters_upsets: "X \ filters \ X \ upsets" by (simp add: upclosed_set_def filters_def) lemma filters_filtered: "X \ filters \ filtered X" by (simp add: filters_def) end context preorder_with_dual begin lemma filtered_prop: "X \ {} \ (\x \ X. \y \ X. \z \ X. z \ x \ z \ y) \ filtered X" unfolding filtered_to_directed by (rule directed_prop, blast, metis (full_types) image_iff ord_dual) lemma filtered_alt: "filtered X = (X \ {} \ (\x \ X. \y \ X. \z \ X. z \ x \ z \ y))" by (metis image_empty directed_alt filtered_to_directed filtered_lb filtered_prop) lemma up_set_prop_var2: "x \ \X \ x \ y \ y \ \X" using downset_set_prop_var2 dual_iff ord_dual upset_set_to_downset_set2 by fastforce lemma upclosed_set_iff: "upclosed_set X = (\x \ X. \y. x \ y \ y \ X)" unfolding upclosed_set_def upsets_def Fix_def upset_set_def by auto lemma upclosed_upset_set: "upclosed_set (\X)" using up_set_prop_var2 upclosed_set_iff by blast lemma upclosed_upset: "upclosed_set (\x)" by (simp add: upset_def upclosed_upset_set) lemma upset_set_ext: "id \ \" by (smt comp_def comp_id image_mono le_fun_def downset_set_ext image_dual upset_set_to_downset_set2) lemma upset_set_anti: "mono \" by (metis image_mono downset_set_iso upset_set_to_downset_set2 mono_def) lemma up_set_idem [simp]: "\ \ \ = \" by (metis comp_assoc downset_set_idem upset_set_downset_set_dual upset_set_to_downset_set) lemma upset_faithful: "\x \ \y \ y \ x" by (metis inj_image_subset_iff downset_faithful dual_dual_ord inj_dual upset_to_downset3) lemma upset_anti_iff: "(\y \ \x) = (x \ y)" by (metis downset_iso_iff ord_dual upset_to_downset3 subset_image_iff upset_faithful) lemma upset_filtered_upset [simp]: "filtered \ \ = filtered" by (metis comp_assoc directed_filtered_dual downset_directed_downset upset_set_downset_set_dual) lemma filtered_upset_filters: "filtered (\X) = (\X \ filters)" by (metis comp_apply directed_downset_ideals filtered_to_directed filterp_idealp_dual upset_set_downset_set_dual) lemma upclosed_Fix: "upclosed_set X = (\X = X)" by (simp add: Fix_def upclosed_set_def upsets_def) end lemma upset_anti: "antimono (\::'a::order_with_dual \ 'a set)" by (simp add: antimono_def upset_anti_iff) lemma mono_upclosed: fixes f :: "'a::order_with_dual \ 'b::order_with_dual" assumes "mono f" shows "\Y. upclosed_set Y \ upclosed_set (f -` Y)" by (simp add: assms monoD upclosed_set_iff) lemma mono_upclosed: fixes f :: "'a::order_with_dual \ 'b::order_with_dual" assumes "mono f" shows "\Y. upclosed_set X \ upclosed_set (f ` X)" (*nitpick*) oops lemma upclosed_mono: fixes f :: "'a::order_with_dual \ 'b::order_with_dual" assumes "\Y. upclosed_set Y \ upclosed_set (f -` Y)" shows "mono f" by (metis (mono_tags, lifting) assms dual_order.refl mem_Collect_eq monoI order.trans upclosed_set_iff vimageE vimageI2) lemma mono_upclosed_iff: fixes f :: "'a::order_with_dual \ 'b::order_with_dual" shows "mono f = (\Y. upclosed_set Y \ upclosed_set (f -` Y))" using mono_upclosed upclosed_mono by auto context order_with_dual begin lemma upset_inj: "inj \" by (metis inj_compose inj_on_imageI2 downset_inj inj_dual upset_to_downset) lemma "(X \ Y) = (\Y \ \X)" (*nitpick*) oops end context lattice_with_dual begin lemma lat_filters: "X \ filters = (X \ {} \ X \ upsets \ (\x \ X. \ y \ X. x \ y \ X))" unfolding filters_to_ideals upsets_to_downsets inf_to_sup lat_ideals by (smt image_iff image_inv_f_f image_is_empty inj_image_mem_iff inv_unique_comp inj_dual invol_dual) end context bounded_lattice_with_dual begin lemma top_filter: "X \ filters \ \ \ X" using bot_ideal inj_image_mem_iff inj_dual filters_to_ideals top_dual by fastforce end context complete_lattice_with_dual begin lemma Inf_upset_id [simp]: "Inf \ \ = id" by (metis comp_assoc comp_id Sup_downset_id Sups_dual_def downset_upset_dual invol_dual) lemma upset_Inf_id: "id \ \ \ Inf" by (simp add: Inf_lower le_funI subsetI upset_prop) lemma Sup_Inf_var: " \(\x \ X. \x) = \X" unfolding upset_prop by (simp add: Collect_ball_eq Sup_eq_Inf) lemma Sup_dual_upset_var: "(\x \ X. \x) = \(\X)" unfolding upset_prop by (safe, simp_all add: Sup_le_iff) end subsection \Shunting Laws\ text \The first set of laws supplies so-called shunting laws for boolean algebras. Such laws rather belong into Isabelle Main.\ -context boolean_algebra +context Lattices.boolean_algebra begin lemma shunt1: "(x \ y \ z) = (x \ -y \ z)" proof standard assume "x \ y \ z" hence "-y \ (x \ y) \ -y \ z" using sup.mono by blast hence "-y \ x \ -y \ z" by (simp add: sup_inf_distrib1) thus "x \ -y \ z" by simp next assume "x \ -y \ z" hence "x \ y \ (-y \ z) \ y" using inf_mono by auto thus "x \ y \ z" using inf.boundedE inf_sup_distrib2 by auto qed lemma shunt2: "(x \ -y \ z) = (x \ y \ z)" by (simp add: shunt1) lemma meet_shunt: "(x \ y = \) = (x \ -y)" by (simp add: order.eq_iff shunt1) lemma join_shunt: "(x \ y = \) = (-x \ y)" by (metis compl_sup compl_top_eq double_compl meet_shunt) lemma meet_shunt_var: "(x - y = \) = (x \ y)" by (simp add: diff_eq meet_shunt) lemma join_shunt_var: "(x \ y = \) = (x \ y)" by simp end subsection \Properties of Complete Lattices\ definition "Inf_closed_set X = (\Y \ X. \Y \ X)" definition "Sup_closed_set X = (\Y \ X. \Y \ X)" definition "inf_closed_set X = (\x \ X. \y \ X. x \ y \ X)" definition "sup_closed_set X = (\x \ X. \y \ X. x \ y \ X)" text \The following facts about complete lattices add to those in the Isabelle libraries.\ context complete_lattice begin text \The translation between sup and Sup could be improved. The sup-theorems should be direct consequences of Sup-ones. In addition, duality between sup and inf is currently not exploited.\ lemma sup_Sup: "x \ y = \{x,y}" by simp lemma inf_Inf: "x \ y = \{x,y}" by simp text \The next two lemmas are about Sups and Infs of indexed families. These are interesting for iterations and fixpoints.\ lemma fSup_unfold: "(f::nat \ 'a) 0 \ (\n. f (Suc n)) = (\n. f n)" apply (intro order.antisym sup_least) apply (rule Sup_upper, force) apply (rule Sup_mono, force) apply (safe intro!: Sup_least) by (case_tac n, simp_all add: Sup_upper le_supI2) lemma fInf_unfold: "(f::nat \ 'a) 0 \ (\n. f (Suc n)) = (\n. f n)" apply (intro order.antisym inf_greatest) apply (rule Inf_greatest, safe) apply (case_tac n) apply simp_all using Inf_lower inf.coboundedI2 apply force apply (simp add: Inf_lower) by (auto intro: Inf_mono) end lemma Sup_sup_closed: "Sup_closed_set (X::'a::complete_lattice set) \ sup_closed_set X" by (metis Sup_closed_set_def empty_subsetI insert_subsetI sup_Sup sup_closed_set_def) lemma Inf_inf_closed: "Inf_closed_set (X::'a::complete_lattice set) \ inf_closed_set X" by (metis Inf_closed_set_def empty_subsetI inf_Inf inf_closed_set_def insert_subset) subsection \Sup- and Inf-Preservation\ text \Next, important notation for morphism between posets and lattices is introduced: sup-preservation, inf-preservation and related properties.\ abbreviation Sup_pres :: "('a::Sup \ 'b::Sup) \ bool" where "Sup_pres f \ f \ Sup = Sup \ (`) f" abbreviation Inf_pres :: "('a::Inf \ 'b::Inf) \ bool" where "Inf_pres f \ f \ Inf = Inf \ (`) f" abbreviation sup_pres :: "('a::sup \ 'b::sup) \ bool" where "sup_pres f \ (\x y. f (x \ y) = f x \ f y)" abbreviation inf_pres :: "('a::inf \ 'b::inf) \ bool" where "inf_pres f \ (\x y. f (x \ y) = f x \ f y)" abbreviation bot_pres :: "('a::bot \ 'b::bot) \ bool" where "bot_pres f \ f \ = \" abbreviation top_pres :: "('a::top \ 'b::top) \ bool" where "top_pres f \ f \ = \" abbreviation Sup_dual :: "('a::Sup \ 'b::Inf) \ bool" where "Sup_dual f \ f \ Sup = Inf \ (`) f" abbreviation Inf_dual :: "('a::Inf \ 'b::Sup) \ bool" where "Inf_dual f \ f \ Inf = Sup \ (`) f" abbreviation sup_dual :: "('a::sup \ 'b::inf) \ bool" where "sup_dual f \ (\x y. f (x \ y) = f x \ f y)" abbreviation inf_dual :: "('a::inf \ 'b::sup) \ bool" where "inf_dual f \ (\x y. f (x \ y) = f x \ f y)" abbreviation bot_dual :: "('a::bot \ 'b::top) \ bool" where "bot_dual f \ f \ = \" abbreviation top_dual :: "('a::top \ 'b::bot) \ bool" where "top_dual f \ f \ = \" text \Inf-preservation and sup-preservation relate with duality.\ lemma Inf_pres_map_dual_var: "Inf_pres f = Sup_pres (\\<^sub>F f)" for f :: "'a::complete_lattice_with_dual \ 'b::complete_lattice_with_dual" proof - { fix x :: "'a set" assume "\ (f (\ (\ ` x))) = (\y\x. \ (f (\ y)))" for x then have "\ (f ` \ ` A) = f (\ (\ A))" for A by (metis (no_types) Sup_dual_def_var image_image invol_dual_var subset_dual) then have "\ (f ` x) = f (\ x)" by (metis Sup_dual_def_var subset_dual) } then show ?thesis by (auto simp add: map_dual_def fun_eq_iff Inf_dual_var Sup_dual_def_var image_comp) qed lemma Inf_pres_map_dual: "Inf_pres = Sup_pres \ (\\<^sub>F::('a::complete_lattice_with_dual \ 'b::complete_lattice_with_dual) \ 'a \ 'b)" proof- {fix f::"'a \ 'b" have "Inf_pres f = (Sup_pres \ \\<^sub>F) f" by (simp add: Inf_pres_map_dual_var)} thus ?thesis by force qed lemma Sup_pres_map_dual_var: fixes f :: "'a::complete_lattice_with_dual \ 'b::complete_lattice_with_dual" shows "Sup_pres f = Inf_pres (\\<^sub>F f)" by (metis Inf_pres_map_dual_var fun_dual5 map_dual_def) lemma Sup_pres_map_dual: "Sup_pres = Inf_pres \ (\\<^sub>F::('a::complete_lattice_with_dual \ 'b::complete_lattice_with_dual) \ 'a \ 'b)" by (simp add: Inf_pres_map_dual comp_assoc map_dual_invol) text \The following lemmas relate isotonicity of functions between complete lattices with weak (left) preservation properties of sups and infs.\ lemma fun_isol: "mono f \ mono ((\) f)" by (simp add: le_fun_def mono_def) lemma fun_isor: "mono f \ mono (\x. x \ f)" by (simp add: le_fun_def mono_def) lemma Sup_sup_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Sup_pres f \ sup_pres f" by (metis (no_types, opaque_lifting) Sup_empty Sup_insert comp_apply image_insert sup_bot.right_neutral) lemma Inf_inf_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows"Inf_pres f \ inf_pres f" by (smt INF_insert Inf_empty Inf_insert comp_eq_elim inf_top.right_neutral) lemma Sup_bot_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Sup_pres f \ bot_pres f" by (metis SUP_empty Sup_empty comp_eq_elim) lemma Inf_top_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Inf_pres f \ top_pres f" by (metis INF_empty Inf_empty comp_eq_elim) lemma Sup_sup_dual: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Sup_dual f \ sup_dual f" by (smt comp_eq_elim image_empty image_insert inf_Inf sup_Sup) lemma Inf_inf_dual: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Inf_dual f \ inf_dual f" by (smt comp_eq_elim image_empty image_insert inf_Inf sup_Sup) lemma Sup_bot_dual: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Sup_dual f \ bot_dual f" by (metis INF_empty Sup_empty comp_eq_elim) lemma Inf_top_dual: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Inf_dual f \ top_dual f" by (metis Inf_empty SUP_empty comp_eq_elim) text \However, Inf-preservation does not imply top-preservation and Sup-preservation does not imply bottom-preservation.\ lemma fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Sup_pres f \ top_pres f" (*nitpick*) oops lemma fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Inf_pres f \ bot_pres f" (*nitpick*) oops context complete_lattice begin lemma iso_Inf_subdistl: fixes f :: "'a \ 'b::complete_lattice" shows "mono f \f \ Inf \ Inf \ (`) f" by (simp add: complete_lattice_class.le_Inf_iff le_funI Inf_lower monoD) lemma iso_Sup_supdistl: fixes f :: "'a \ 'b::complete_lattice" shows "mono f \ Sup \ (`) f \ f \ Sup" by (simp add: complete_lattice_class.Sup_le_iff le_funI Sup_upper monoD) lemma Inf_subdistl_iso: fixes f :: "'a \ 'b::complete_lattice" shows "f \ Inf \ Inf \ (`) f \ mono f" unfolding mono_def le_fun_def comp_def by (metis complete_lattice_class.le_INF_iff Inf_atLeast atLeast_iff) lemma Sup_supdistl_iso: fixes f :: "'a \ 'b::complete_lattice" shows "Sup \ (`) f \ f \ Sup \ mono f" unfolding mono_def le_fun_def comp_def by (metis complete_lattice_class.SUP_le_iff Sup_atMost atMost_iff) lemma supdistl_iso: fixes f :: "'a \ 'b::complete_lattice" shows "(Sup \ (`) f \ f \ Sup) = mono f" using Sup_supdistl_iso iso_Sup_supdistl by force lemma subdistl_iso: fixes f :: "'a \ 'b::complete_lattice" shows "(f \ Inf \ Inf \ (`) f) = mono f" using Inf_subdistl_iso iso_Inf_subdistl by force end lemma ord_iso_Inf_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "ord_iso f \ Inf \ (`) f = f \ Inf" proof- let ?g = "the_inv f" assume h: "ord_iso f" hence a: "mono ?g" by (simp add: ord_iso_the_inv) {fix X :: "'a::complete_lattice set" {fix y :: "'b::complete_lattice" have "(y \ f (\X)) = (?g y \ \X)" by (metis (mono_tags, lifting) UNIV_I f_the_inv_into_f h monoD ord_embed_alt ord_embed_inj ord_iso_alt) also have "... = (\x \ X. ?g y \ x)" by (simp add: le_Inf_iff) also have "... = (\x \ X. y \ f x)" by (metis (mono_tags, lifting) UNIV_I f_the_inv_into_f h monoD ord_embed_alt ord_embed_inj ord_iso_alt) also have "... = (y \ \ (f ` X))" by (simp add: le_INF_iff) finally have "(y \ f (\X)) = (y \ \ (f ` X))".} hence "f (\X) = \ (f ` X)" by (meson dual_order.antisym order_refl)} thus ?thesis unfolding fun_eq_iff by simp qed lemma ord_iso_Sup_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "ord_iso f \ Sup \ (`) f = f \ Sup" proof- let ?g = "the_inv f" assume h: "ord_iso f" hence a: "mono ?g" by (simp add: ord_iso_the_inv) {fix X :: "'a::complete_lattice set" {fix y :: "'b::complete_lattice" have "(f (\X) \ y) = (\X \ ?g y)" by (metis (mono_tags, lifting) UNIV_I f_the_inv_into_f h monoD ord_embed_alt ord_embed_inj ord_iso_alt) also have "... = (\x \ X. x \ ?g y)" by (simp add: Sup_le_iff) also have "... = (\x \ X. f x \ y)" by (metis (mono_tags, lifting) UNIV_I f_the_inv_into_f h monoD ord_embed_alt ord_embed_inj ord_iso_alt) also have "... = (\ (f ` X) \ y)" by (simp add: SUP_le_iff) finally have "(f (\X) \ y) = (\ (f ` X) \ y)".} hence "f (\X) = \ (f ` X)" by (meson dual_order.antisym order_refl)} thus ?thesis unfolding fun_eq_iff by simp qed text \Right preservation of sups and infs is trivial.\ lemma fSup_distr: "Sup_pres (\x. x \ f)" unfolding fun_eq_iff by (simp add: image_comp) lemma fSup_distr_var: "\F \ g = (\f \ F. f \ g)" unfolding fun_eq_iff by (simp add: image_comp) lemma fInf_distr: "Inf_pres (\x. x \ f)" unfolding fun_eq_iff comp_def by (smt INF_apply Inf_fun_def Sup.SUP_cong) lemma fInf_distr_var: "\F \ g = (\f \ F. f \ g)" unfolding fun_eq_iff comp_def by (smt INF_apply INF_cong INF_image Inf_apply image_comp image_def image_image) text \The next set of lemma revisits the preservation properties in the function space.\ lemma fSup_subdistl: assumes "mono (f::'a::complete_lattice \ 'b::complete_lattice)" shows "Sup \ (`) ((\) f) \ (\) f \ Sup" using assms by (simp add: fun_isol supdistl_iso) lemma fSup_subdistl_var: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "mono f \ (\g \ G. f \ g) \ f \ \G" by (simp add: fun_isol mono_Sup) lemma fInf_subdistl: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "mono f \ (\) f \ Inf \ Inf \ (`) ((\) f)" by (simp add: fun_isol subdistl_iso) lemma fInf_subdistl_var: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "mono f \ f \ \G \ (\g \ G. f \ g)" by (simp add: fun_isol mono_Inf) lemma fSup_distl: "Sup_pres f \ Sup_pres ((\) f)" unfolding fun_eq_iff by (simp add: image_comp) lemma fSup_distl_var: "Sup_pres f \ f \ \G = (\g \ G. f \ g)" unfolding fun_eq_iff by (simp add: image_comp) lemma fInf_distl: "Inf_pres f \ Inf_pres ((\) f)" unfolding fun_eq_iff by (simp add: image_comp) lemma fInf_distl_var: "Inf_pres f \ f \ \G = (\g \ G. f \ g)" unfolding fun_eq_iff by (simp add: image_comp) text \Downsets preserve infs whereas upsets preserve sups.\ lemma Inf_pres_downset: "Inf_pres (\::'a::complete_lattice_with_dual \ 'a set)" unfolding downset_prop fun_eq_iff by (safe, simp_all add: le_Inf_iff) lemma Sup_dual_upset: "Sup_dual (\::'a::complete_lattice_with_dual \ 'a set)" unfolding upset_prop fun_eq_iff by (safe, simp_all add: Sup_le_iff) text \Images of Sup-morphisms are closed under Sups and images of Inf-morphisms are closed under Infs.\ lemma Sup_pres_Sup_closed: "Sup_pres f \ Sup_closed_set (range f)" by (metis (mono_tags, lifting) Sup_closed_set_def comp_eq_elim range_eqI subset_image_iff) lemma Inf_pres_Inf_closed: "Inf_pres f \ Inf_closed_set (range f)" by (metis (mono_tags, lifting) Inf_closed_set_def comp_eq_elim range_eqI subset_image_iff) text \It is well known that functions into complete lattices form complete lattices. Here, such results are shown for the subclasses of isotone functions, where additional closure conditions must be respected.\ typedef (overloaded) 'a iso = "{f::'a::order \ 'a::order. mono f}" by (metis Abs_ord_homset_cases ord_homset_def) setup_lifting type_definition_iso instantiation iso :: (complete_lattice) complete_lattice begin lift_definition Inf_iso :: "'a::complete_lattice iso set \ 'a iso" is Sup by (metis (mono_tags, lifting) SUP_subset_mono Sup_apply mono_def subsetI) lift_definition Sup_iso :: "'a::complete_lattice iso set \ 'a iso" is Inf by (smt INF_lower2 Inf_apply le_INF_iff mono_def) lift_definition bot_iso :: "'a::complete_lattice iso" is "\" by (simp add: monoI) lift_definition sup_iso :: "'a::complete_lattice iso \ 'a iso \ 'a iso" is inf by (smt inf_apply inf_mono monoD monoI) lift_definition top_iso :: "'a::complete_lattice iso" is "\" by (simp add: mono_def) lift_definition inf_iso :: "'a::complete_lattice iso \ 'a iso \ 'a iso" is sup by (smt mono_def sup.mono sup_apply) lift_definition less_eq_iso :: "'a::complete_lattice iso \ 'a iso \ bool" is "(\)". lift_definition less_iso :: "'a::complete_lattice iso \ 'a iso \ bool" is "(>)". instance by (intro_classes; transfer, simp_all add: less_fun_def Sup_upper Sup_least Inf_lower Inf_greatest) end text \Duality has been baked into this result because of its relevance for predicate transformers. A proof where Sups are mapped to Sups and Infs to Infs is certainly possible, but two instantiation of the same type and the same classes are unfortunately impossible. Interpretations could be used instead. A corresponding result for Inf-preseving functions and Sup-lattices, is proved in components on transformers, as more advanced properties about Inf-preserving functions are needed.\ subsection \Alternative Definitions for Complete Boolean Algebras\ text \The current definitions of complete boolean algebras deviates from that in most textbooks in that a distributive law with infinite sups and infinite infs is used. There are interesting applications, for instance in topology, where weaker laws are needed --- for instance for frames and locales.\ class complete_heyting_algebra = complete_lattice + assumes ch_dist: "x \ \Y = (\y \ Y. x \ y)" text \Complete Heyting algebras are also known as frames or locales (they differ with respect to their morphisms).\ class complete_co_heyting_algebra = complete_lattice + assumes co_ch_dist: "x \ \Y = (\y \ Y. x \ y)" class complete_boolean_algebra_alt = complete_lattice + boolean_algebra instance set :: (type) complete_boolean_algebra_alt.. context complete_boolean_algebra_alt begin subclass complete_heyting_algebra proof fix x Y {fix t have "(x \ \Y \ t) = (\Y \ -x \ t)" by (simp add: inf.commute shunt1[symmetric]) also have "... = (\y \ Y. y \ -x \ t)" using Sup_le_iff by blast also have "... = (\y \ Y. x \ y \ t)" by (simp add: inf.commute shunt1) finally have "(x \ \Y \ t) = ((\y\Y. x \ y) \ t)" by (simp add: local.SUP_le_iff)} thus "x \ \Y = (\y\Y. x \ y)" using order.eq_iff by blast qed subclass complete_co_heyting_algebra apply unfold_locales apply (rule order.antisym) apply (simp add: INF_greatest Inf_lower2) by (meson eq_refl le_INF_iff le_Inf_iff shunt2) lemma de_morgan1: "-(\X) = (\x \ X. -x)" proof- {fix y have "(y \ -(\X)) = (\X \ -y)" using compl_le_swap1 by blast also have "... = (\x \ X. x \ -y)" by (simp add: Sup_le_iff) also have "... = (\x \ X. y \ -x)" using compl_le_swap1 by blast also have "... = (y \ (\x \ X. -x))" using le_INF_iff by force finally have "(y \ -(\X)) = (y \(\x \ X. -x))".} thus ?thesis using order.antisym by blast qed lemma de_morgan2: "-(\X) = (\x \ X. -x)" by (metis de_morgan1 ba_dual.dual_iff ba_dual.image_dual pointfree_idE) end class complete_boolean_algebra_alt_with_dual = complete_lattice_with_dual + complete_boolean_algebra_alt instantiation set :: (type) complete_boolean_algebra_alt_with_dual begin definition dual_set :: "'a set \ 'a set" where "dual_set = uminus" instance by intro_classes (simp_all add: ba_dual.inj_dual dual_set_def comp_def uminus_Sup id_def) end context complete_boolean_algebra_alt begin sublocale cba_dual: complete_boolean_algebra_alt_with_dual _ _ _ _ _ _ _ _ uminus _ _ by unfold_locales (auto simp: de_morgan2 de_morgan1) end subsection \Atomic Boolean Algebras\ text \Next, atomic boolean algebras are defined.\ context bounded_lattice begin text \Atoms are covers of bottom.\ definition "atom x = (x \ \ \ \(\y. \ < y \ y < x))" definition "atom_map x = {y. atom y \ y \ x}" lemma atom_map_def_var: "atom_map x = \x \ Collect atom" unfolding atom_map_def downset_def downset_set_def comp_def atom_def by fastforce lemma atom_map_atoms: "\(range atom_map) = Collect atom" unfolding atom_map_def atom_def by auto end typedef (overloaded) 'a atoms = "range (atom_map::'a::bounded_lattice \ 'a set)" by blast setup_lifting type_definition_atoms definition at_map :: "'a::bounded_lattice \ 'a atoms" where "at_map = Abs_atoms \ atom_map" class atomic_boolean_algebra = boolean_algebra + assumes atomicity: "x \ \ \ (\y. atom y \ y \ x)" class complete_atomic_boolean_algebra = complete_lattice + atomic_boolean_algebra begin subclass complete_boolean_algebra_alt.. end text \Here are two equivalent definitions for atoms; first in boolean algebras, and then in complete boolean algebras.\ -context boolean_algebra +context Lattices.boolean_algebra begin text \The following two conditions are taken from Koppelberg's book~\cite{Koppelberg89}.\ lemma atom_neg: "atom x \ x \ \ \ (\y z. x \ y \ x \ -y)" by (metis atom_def dual_order.order_iff_strict inf.cobounded1 inf.commute meet_shunt) lemma atom_sup: "(\y. x \ y \ x \ -y) \ (\y z. (x \ y \ x \ z) = (x \ y \ z))" by (metis inf.orderE le_supI1 shunt2) lemma sup_atom: "x \ \ \ (\y z. (x \ y \ x \ z) = (x \ y \ z)) \ atom x" unfolding atom_def apply clarsimp by (metis bot_less inf.absorb2 less_le_not_le meet_shunt sup_compl_top) lemma atom_sup_iff: "atom x = (x \ \ \ (\y z. (x \ y \ x \ z) = (x \ y \ z)))" by (standard, auto simp add: atom_neg atom_sup sup_atom) lemma atom_neg_iff: "atom x = (x \ \ \ (\y z. x \ y \ x \ -y))" by (standard, auto simp add: atom_neg atom_sup sup_atom) lemma atom_map_bot_pres: "atom_map \ = {}" using atom_def atom_map_def le_bot by auto lemma atom_map_top_pres: "atom_map \ = Collect atom" using atom_map_def by auto end context complete_boolean_algebra_alt begin lemma atom_Sup: "\Y. x \ \ \ (\y. x \ y \ x \ -y) \ ((\y \ Y. x \ y) = (x \ \Y))" by (metis Sup_least Sup_upper2 compl_le_swap1 le_iff_inf meet_shunt) lemma Sup_atom: "x \ \ \ (\Y. (\y \ Y. x \ y) = (x \ \Y)) \ atom x" proof- assume h1: "x \ \" and h2: "\Y. (\y \ Y. x \ y) = (x \ \Y)" hence "\y z. (x \ y \ x \ z) = (x \ y \ z)" by (smt insert_iff sup_Sup sup_bot.right_neutral) thus "atom x" by (simp add: h1 sup_atom) qed lemma atom_Sup_iff: "atom x = (x \ \ \ (\Y. (\y \ Y. x \ y) = (x \ \Y)))" by standard (auto simp: atom_neg atom_Sup Sup_atom) end end diff --git a/thys/Order_Lattice_Props/Order_Lattice_Props_Loc.thy b/thys/Order_Lattice_Props/Order_Lattice_Props_Loc.thy --- a/thys/Order_Lattice_Props/Order_Lattice_Props_Loc.thy +++ b/thys/Order_Lattice_Props/Order_Lattice_Props_Loc.thy @@ -1,575 +1,575 @@ (* Title: Locale-Based Duality Author: Georg Struth Maintainer:Georg Struth *) section \Locale-Based Duality\ theory Order_Lattice_Props_Loc imports Main "HOL-Library.Lattice_Syntax" begin text \This section explores order and lattice duality based on locales. Used within the context of a class or locale, this is very effective, though more opaque than the previous approach. Outside of such a context, however, it apparently cannot be used for dualising theorems. Examples are properties of functions between orderings or lattices.\ definition Fix :: "('a \ 'a) \ 'a set" where "Fix f = {x. f x = x}" context ord begin definition min_set :: "'a set \ 'a set" where "min_set X = {y \ X. \x \ X. x \ y \ x = y}" definition max_set :: "'a set \ 'a set" where "max_set X = {x \ X. \y \ X. x \ y \ x = y}" definition directed :: "'a set \ bool" where "directed X = (\Y. finite Y \ Y \ X \ (\x \ X. \y \ Y. y \ x))" definition filtered :: "'a set \ bool" where "filtered X = (\Y. finite Y \ Y \ X \ (\x \ X. \y \ Y. x \ y))" definition downset_set :: "'a set \ 'a set" ("\") where "\X = {y. \x \ X. y \ x}" definition upset_set :: "'a set \ 'a set" ("\") where "\X = {y. \x \ X. x \ y}" definition downset :: "'a \ 'a set" ("\") where "\ = \ \ (\x. {x})" definition upset :: "'a \ 'a set" ("\") where "\ = \ \ (\x. {x})" definition downsets :: "'a set set" where "downsets = Fix \" definition upsets :: "'a set set" where "upsets = Fix \" abbreviation "downset_setp X \ X \ downsets" abbreviation "upset_setp X \ X \ upsets" definition ideals :: "'a set set" where "ideals = {X. X \ {} \ downset_setp X \ directed X}" definition filters :: "'a set set" where "filters = {X. X \ {} \ upset_setp X \ filtered X}" abbreviation "idealp X \ X \ ideals" abbreviation "filterp X \ X \ filters" end abbreviation Sup_pres :: "('a::Sup \ 'b::Sup) \ bool" where "Sup_pres f \ f \ Sup = Sup \ (`) f" abbreviation Inf_pres :: "('a::Inf \ 'b::Inf) \ bool" where "Inf_pres f \ f \ Inf = Inf \ (`) f" abbreviation sup_pres :: "('a::sup \ 'b::sup) \ bool" where "sup_pres f \ (\x y. f (x \ y) = f x \ f y)" abbreviation inf_pres :: "('a::inf \ 'b::inf) \ bool" where "inf_pres f \ (\x y. f (x \ y) = f x \ f y)" abbreviation bot_pres :: "('a::bot \ 'b::bot) \ bool" where "bot_pres f \ f \ = \" abbreviation top_pres :: "('a::top \ 'b::top) \ bool" where "top_pres f \ f \ = \" abbreviation Sup_dual :: "('a::Sup \ 'b::Inf) \ bool" where "Sup_dual f \ f \ Sup = Inf \ (`) f" abbreviation Inf_dual :: "('a::Inf \ 'b::Sup) \ bool" where "Inf_dual f \ f \ Inf = Sup \ (`) f" abbreviation sup_dual :: "('a::sup \ 'b::inf) \ bool" where "sup_dual f \ (\x y. f (x \ y) = f x \ f y)" abbreviation inf_dual :: "('a::inf \ 'b::sup) \ bool" where "inf_dual f \ (\x y. f (x \ y) = f x \ f y)" abbreviation bot_dual :: "('a::bot \ 'b::top) \ bool" where "bot_dual f \ f \ = \" abbreviation top_dual :: "('a::top \ 'b::bot) \ bool" where "top_dual f \ f \ = \" subsection \Duality via Locales\ sublocale ord \ dual_ord: ord "(\)" "(>)" rewrites dual_max_set: "max_set = dual_ord.min_set" and dual_filtered: "filtered = dual_ord.directed" and dual_upset_set: "upset_set = dual_ord.downset_set" and dual_upset: "upset = dual_ord.downset" and dual_upsets: "upsets = dual_ord.downsets" and dual_filters: "filters = dual_ord.ideals" apply unfold_locales unfolding max_set_def ord.min_set_def fun_eq_iff apply blast unfolding filtered_def ord.directed_def apply simp unfolding upset_set_def ord.downset_set_def apply simp apply (simp add: ord.downset_def ord.downset_set_def ord.upset_def ord.upset_set_def) unfolding upsets_def ord.downsets_def apply (metis ord.downset_set_def upset_set_def) unfolding filters_def ord.ideals_def Fix_def ord.downsets_def upsets_def ord.downset_set_def upset_set_def ord.directed_def filtered_def by simp sublocale preorder \ dual_preorder: preorder "(\)" "(>)" apply unfold_locales apply (simp add: less_le_not_le) apply simp using order_trans by blast sublocale order \ dual_order: order "(\)" "(>)" by (unfold_locales, simp) sublocale lattice \ dual_lattice: lattice sup "(\)" "(>)" inf by (unfold_locales, simp_all) sublocale bounded_lattice \ dual_bounded_lattice: bounded_lattice sup "(\)" "(>)" inf \ \ by (unfold_locales, simp_all) -sublocale boolean_algebra \ dual_boolean_algebra: boolean_algebra "\x y. x \ -y" uminus sup "(\)" "(>)" inf \ \ +sublocale Lattices.boolean_algebra \ dual_boolean_algebra: Lattices.boolean_algebra "\x y. x \ -y" uminus sup "(\)" "(>)" inf \ \ by (unfold_locales, simp_all add: inf_sup_distrib1) sublocale complete_lattice \ dual_complete_lattice: complete_lattice Sup Inf sup "(\)" "(>)" inf \ \ rewrites dual_gfp: "gfp = dual_complete_lattice.lfp" proof- show "class.complete_lattice Sup Inf sup (\) (>) inf \ \" by (unfold_locales, simp_all add: Sup_upper Sup_least Inf_lower Inf_greatest) then interpret dual_complete_lattice: complete_lattice Sup Inf sup "(\)" "(>)" inf \ \. show "gfp = dual_complete_lattice.lfp" unfolding gfp_def dual_complete_lattice.lfp_def fun_eq_iff by simp qed context ord begin lemma dual_min_set: "min_set = dual_ord.max_set" by (simp add: dual_ord.dual_max_set) lemma dual_directed: "directed = dual_ord.filtered" by (simp add:dual_ord.dual_filtered) lemma dual_downset: "downset = dual_ord.upset" by (simp add: dual_ord.dual_upset) lemma dual_downset_set: "downset_set = dual_ord.upset_set" by (simp add: dual_ord.dual_upset_set) lemma dual_downsets: "downsets = dual_ord.upsets" by (simp add: dual_ord.dual_upsets) lemma dual_ideals: "ideals = dual_ord.filters" by (simp add: dual_ord.dual_filters) end context complete_lattice begin lemma dual_lfp: "lfp = dual_complete_lattice.gfp" by (simp add: dual_complete_lattice.dual_gfp) end subsection \Properties of Orderings, Again\ context ord begin lemma directed_nonempty: "directed X \ X \ {}" unfolding directed_def by fastforce lemma directed_ub: "directed X \ (\x \ X. \y \ X. \z \ X. x \ z \ y \ z)" by (meson empty_subsetI directed_def finite.emptyI finite_insert insert_subset order_refl) lemma downset_set_prop: "\ = Union \ (`) \" unfolding downset_set_def downset_def fun_eq_iff by fastforce lemma downset_set_prop_var: "\X = (\x \ X. \x)" by (simp add: downset_set_prop) lemma downset_prop: "\x = {y. y \ x}" unfolding downset_def downset_set_def fun_eq_iff comp_def by fastforce end context preorder begin lemma directed_prop: "X \ {} \ (\x \ X. \y \ X. \z \ X. x \ z \ y \ z) \ directed X" proof- assume h1: "X \ {}" and h2: "\x \ X. \y \ X. \z \ X. x \ z \ y \ z" {fix Y have "finite Y \ Y \ X \ (\x \ X. \y \ Y. y \ x)" proof (induct rule: finite_induct) case empty then show ?case using h1 by blast next case (insert x F) then show ?case by (metis h2 insert_iff insert_subset order_trans) qed} thus ?thesis by (simp add: directed_def) qed lemma directed_alt: "directed X = (X \ {} \ (\x \ X. \y \ X. \z \ X. x \ z \ y \ z))" by (metis directed_prop directed_nonempty directed_ub) lemma downset_set_ext: "id \ \" unfolding le_fun_def id_def downset_set_def by auto lemma downset_set_iso: "mono \" unfolding mono_def downset_set_def by blast lemma downset_set_idem [simp]: "\ \ \ = \" unfolding fun_eq_iff downset_set_def comp_def using order_trans by auto lemma downset_faithful: "\x \ \y \ x \ y" by (simp add: downset_prop subset_eq) lemma downset_iso_iff: "(\x \ \y) = (x \ y)" using atMost_iff downset_prop order_trans by blast lemma downset_directed_downset_var [simp]: "directed (\X) = directed X" proof assume h1: "directed X" {fix Y assume h2: "finite Y" and h3: "Y \ \X" hence "\y. \x. y \ Y \ x \ X \ y \ x" by (force simp: downset_set_def) hence "\f. \y. y \ Y \ f y \ X \ y \ f y" by (rule choice) hence "\f. finite (f ` Y) \ f ` Y \ X \ (\y \ Y. y \ f y)" by (metis finite_imageI h2 image_subsetI) hence "\Z. finite Z \ Z \ X \ (\y \ Y. \ z \ Z. y \ z)" by fastforce hence "\Z. finite Z \ Z \ X \ (\y \ Y. \ z \ Z. y \ z) \ (\x \ X. \ z \ Z. z \ x)" by (metis directed_def h1) hence "\x \ X. \y \ Y. y \ x" by (meson order_trans)} thus "directed (\X)" unfolding directed_def downset_set_def by fastforce next assume "directed (\X)" thus "directed X" unfolding directed_def downset_set_def apply clarsimp by (smt Ball_Collect order_refl order_trans subsetCE) qed lemma downset_directed_downset [simp]: "directed \ \ = directed" unfolding fun_eq_iff comp_def by simp lemma directed_downset_ideals: "directed (\X) = (\X \ ideals)" by (metis (mono_tags, lifting) Fix_def comp_apply directed_alt downset_set_idem downsets_def ideals_def mem_Collect_eq) end lemma downset_iso: "mono (\::'a::order \ 'a set)" by (simp add: downset_iso_iff mono_def) context order begin lemma downset_inj: "inj \" by (metis injI downset_iso_iff order.eq_iff) end context lattice begin lemma lat_ideals: "X \ ideals = (X \ {} \ X \ downsets \ (\x \ X. \ y \ X. x \ y \ X))" unfolding ideals_def directed_alt downsets_def Fix_def downset_set_def by (clarsimp, smt sup.cobounded1 sup.orderE sup.orderI sup_absorb2 sup_left_commute mem_Collect_eq) end context bounded_lattice begin lemma bot_ideal: "X \ ideals \ \ \ X" unfolding ideals_def downsets_def Fix_def downset_set_def by fastforce end context complete_lattice begin lemma Sup_downset_id [simp]: "Sup \ \ = id" using Sup_atMost atMost_def downset_prop by fastforce lemma downset_Sup_id: "id \ \ \ Sup" by (simp add: Sup_upper downset_prop le_funI subsetI) lemma Inf_Sup_var: "\(\x \ X. \x) = \X" unfolding downset_prop by (simp add: Collect_ball_eq Inf_eq_Sup) lemma Inf_pres_downset_var: "(\x \ X. \x) = \(\X)" unfolding downset_prop by (safe, simp_all add: le_Inf_iff) end lemma lfp_in_Fix: fixes f :: "'a::complete_lattice \ 'a" shows "mono f \ lfp f \ Fix f" using Fix_def lfp_unfold by fastforce lemma gfp_in_Fix: fixes f :: "'a::complete_lattice \ 'a" shows "mono f \ gfp f \ Fix f" using Fix_def gfp_unfold by fastforce lemma nonempty_Fix: fixes f :: "'a::complete_lattice \ 'a" shows "mono f \ Fix f \ {}" using lfp_in_Fix by fastforce subsection \Dual Properties of Orderings from Locales\ text \These properties can be proved very smoothly overall. But only within the context of a class or locale!\ context ord begin lemma filtered_nonempty: "filtered X \ X \ {}" by (simp add: dual_filtered dual_ord.directed_nonempty) lemma filtered_lb: "filtered X \ (\x \ X. \y \ X. \z \ X. z \ x \ z \ y)" by (simp add: dual_filtered dual_ord.directed_ub) lemma upset_set_prop: "\ = Union \ (`) \" by (simp add: dual_ord.downset_set_prop dual_upset dual_upset_set) lemma upset_set_prop_var: "\X = (\x \ X. \x)" by (simp add: dual_ord.downset_set_prop_var dual_upset dual_upset_set) lemma upset_prop: "\x = {y. x \ y}" by (simp add: dual_ord.downset_prop dual_upset) end context preorder begin lemma filtered_prop: "X \ {} \ (\x \ X. \y \ X. \z \ X. z \ x \ z \ y) \ filtered X" by (simp add: dual_filtered dual_preorder.directed_prop) lemma filtered_alt: "filtered X = (X \ {} \ (\x \ X. \y \ X. \z \ X. z \ x \ z \ y))" by (simp add: dual_filtered dual_preorder.directed_alt) lemma upset_set_ext: "id \ \" by (simp add: dual_preorder.downset_set_ext dual_upset_set) lemma upset_set_anti: "mono \" by (simp add: dual_preorder.downset_set_iso dual_upset_set) lemma up_set_idem [simp]: "\ \ \ = \" by (simp add: dual_upset_set) lemma upset_faithful: "\x \ \y \ y \ x" by (metis dual_preorder.downset_faithful dual_upset) lemma upset_anti_iff: "(\y \ \x) = (x \ y)" by (simp add: dual_preorder.downset_iso_iff dual_upset) lemma upset_filtered_upset [simp]: "filtered \ \ = filtered" by (simp add: dual_filtered dual_upset_set) lemma filtered_upset_filters: "filtered (\X) = (\X \ filters)" using dual_filtered dual_preorder.directed_downset_ideals dual_upset_set ord.dual_filters by fastforce end context order begin lemma upset_inj: "inj \" by (simp add: dual_order.downset_inj dual_upset) end context lattice begin lemma lat_filters: "X \ filters = (X \ {} \ X \ upsets \ (\x \ X. \ y \ X. x \ y \ X))" by (simp add: dual_filters dual_lattice.lat_ideals dual_ord.downsets_def dual_upset_set upsets_def) end context bounded_lattice begin lemma top_filter: "X \ filters \ \ \ X" by (simp add: dual_bounded_lattice.bot_ideal dual_filters) end context complete_lattice begin lemma Inf_upset_id [simp]: "Inf \ \ = id" by (simp add: dual_upset) lemma upset_Inf_id: "id \ \ \ Inf" by (simp add: dual_complete_lattice.downset_Sup_id dual_upset) lemma Sup_Inf_var: " \(\x \ X. \x) = \X" by (simp add: dual_complete_lattice.Inf_Sup_var dual_upset) lemma Sup_dual_upset_var: "(\x \ X. \x) = \(\X)" by (simp add: dual_complete_lattice.Inf_pres_downset_var dual_upset) end subsection \Examples that Do Not Dualise\ lemma upset_anti: "antimono (\::'a::order \ 'a set)" by (simp add: antimono_def upset_anti_iff) context complete_lattice begin lemma fSup_unfold: "(f::nat \ 'a) 0 \ (\n. f (Suc n)) = (\n. f n)" apply (intro order.antisym sup_least) apply (rule Sup_upper, force) apply (rule Sup_mono, force) apply (safe intro!: Sup_least) by (case_tac n, simp_all add: Sup_upper le_supI2) lemma fInf_unfold: "(f::nat \ 'a) 0 \ (\n. f (Suc n)) = (\n. f n)" apply (intro order.antisym inf_greatest) apply (rule Inf_greatest, safe) apply (case_tac n) apply simp_all using Inf_lower inf.coboundedI2 apply force apply (simp add: Inf_lower) by (auto intro: Inf_mono) end lemma fun_isol: "mono f \ mono ((\) f)" by (simp add: le_fun_def mono_def) lemma fun_isor: "mono f \ mono (\x. x \ f)" by (simp add: le_fun_def mono_def) lemma Sup_sup_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Sup_pres f \ sup_pres f" by (metis (no_types, opaque_lifting) Sup_empty Sup_insert comp_apply image_insert sup_bot.right_neutral) lemma Inf_inf_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows"Inf_pres f \ inf_pres f" by (smt INF_insert comp_eq_elim dual_complete_lattice.Sup_empty dual_complete_lattice.Sup_insert inf_top.right_neutral) lemma Sup_bot_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Sup_pres f \ bot_pres f" by (metis SUP_empty Sup_empty comp_eq_elim) lemma Inf_top_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "Inf_pres f \ top_pres f" by (metis INF_empty comp_eq_elim dual_complete_lattice.Sup_empty) context complete_lattice begin lemma iso_Inf_subdistl: assumes "mono (f::'a \ 'b::complete_lattice)" shows "f \ Inf \ Inf \ (`) f" by (simp add: assms complete_lattice_class.le_Inf_iff le_funI Inf_lower monoD) lemma iso_Sup_supdistl: assumes "mono (f::'a \ 'b::complete_lattice)" shows "Sup \ (`) f \ f \ Sup" by (simp add: assms complete_lattice_class.SUP_le_iff le_funI dual_complete_lattice.Inf_lower monoD) lemma Inf_subdistl_iso: fixes f :: "'a \ 'b::complete_lattice" shows "f \ Inf \ Inf \ (`) f \ mono f" unfolding mono_def le_fun_def comp_def by (metis complete_lattice_class.le_INF_iff Inf_atLeast atLeast_iff) lemma Sup_supdistl_iso: fixes f :: "'a \ 'b::complete_lattice" shows "Sup \ (`) f \ f \ Sup \ mono f" unfolding mono_def le_fun_def comp_def by (metis complete_lattice_class.SUP_le_iff Sup_atMost atMost_iff) lemma supdistl_iso: fixes f :: "'a \ 'b::complete_lattice" shows "(Sup \ (`) f \ f \ Sup) = mono f" using Sup_supdistl_iso iso_Sup_supdistl by force lemma subdistl_iso: fixes f :: "'a \ 'b::complete_lattice" shows "(f \ Inf \ Inf \ (`) f) = mono f" using Inf_subdistl_iso iso_Inf_subdistl by force end lemma fSup_distr: "Sup_pres (\x. x \ f)" unfolding fun_eq_iff comp_def by (smt Inf.INF_cong SUP_apply Sup_apply) lemma fSup_distr_var: "\F \ g = (\f \ F. f \ g)" unfolding fun_eq_iff comp_def by (smt Inf.INF_cong SUP_apply Sup_apply) lemma fInf_distr: "Inf_pres (\x. x \ f)" unfolding fun_eq_iff comp_def by (smt INF_apply Inf.INF_cong Inf_apply) lemma fInf_distr_var: "\F \ g = (\f \ F. f \ g)" unfolding fun_eq_iff comp_def by (smt INF_apply Inf.INF_cong Inf_apply) lemma fSup_subdistl: assumes "mono (f::'a::complete_lattice \ 'b::complete_lattice)" shows "Sup \ (`) ((\) f) \ (\) f \ Sup" using assms by (simp add: SUP_least Sup_upper le_fun_def monoD image_comp) lemma fSup_subdistl_var: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "mono f \ (\g \ G. f \ g) \ f \ \G" by (simp add: SUP_least Sup_upper le_fun_def monoD image_comp) lemma fInf_subdistl: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "mono f \ (\) f \ Inf \ Inf \ (`) ((\) f)" by (simp add: INF_greatest Inf_lower le_fun_def monoD image_comp) lemma fInf_subdistl_var: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "mono f \ f \ \G \ (\g \ G. f \ g)" by (simp add: INF_greatest Inf_lower le_fun_def monoD image_comp) lemma Inf_pres_downset: "Inf_pres (\::'a::complete_lattice \ 'a set)" unfolding downset_prop fun_eq_iff comp_def by (safe, simp_all add: le_Inf_iff) lemma Sup_dual_upset: "Sup_dual (\::'a::complete_lattice \ 'a set)" unfolding upset_prop fun_eq_iff comp_def by (safe, simp_all add: Sup_le_iff) text \This approach could probably be combined with the explicit functor-based one. This may be good for proofs, but seems conceptually rather ugly.\ end \ No newline at end of file diff --git a/thys/Order_Lattice_Props/Order_Lattice_Props_Wenzel.thy b/thys/Order_Lattice_Props/Order_Lattice_Props_Wenzel.thy --- a/thys/Order_Lattice_Props/Order_Lattice_Props_Wenzel.thy +++ b/thys/Order_Lattice_Props/Order_Lattice_Props_Wenzel.thy @@ -1,289 +1,280 @@ (* Title: Duality Based on a Data Type Author: Georg Struth Maintainer:Georg Struth *) section \Duality Based on a Data Type\ theory Order_Lattice_Props_Wenzel imports Main "HOL-Library.Lattice_Syntax" begin subsection \Wenzel's Approach Revisited\ text \This approach is similar to, but inferior to the explicit class-based one. The main caveat is that duality is not involutive with this approach, and this allows dualising less theorems.\ text \I copy Wenzel's development \cite{Wenzel} in this subsection and extend it with additional properties. I show only the most important properties.\ datatype 'a dual = dual (un_dual: 'a) ("\") notation un_dual ("\\<^sup>-") lemma dual_inj: "inj \" using injI by fastforce lemma dual_surj: "surj \" using dual.exhaust_sel by blast lemma dual_bij: "bij \" by (simp add: bijI dual_inj dual_surj) text \Dual is not idempotent, and I see no way of imposing this condition. Yet at least an inverse exists --- namely un-dual..\ lemma dual_inv1 [simp]: "\\<^sup>- \ \ = id" by fastforce lemma dual_inv2 [simp]: "\ \ \\<^sup>- = id" by fastforce lemma dual_inv_inj: "inj \\<^sup>-" by (simp add: dual.expand injI) lemma dual_inv_surj: "surj \\<^sup>-" by (metis dual.sel surj_def) lemma dual_inv_bij: "bij \\<^sup>-" by (simp add: bij_def dual_inv_inj dual_inv_surj) lemma dual_iff: "(\ x = y) \ (x = \\<^sup>- y)" by fastforce text \Isabelle data types come with a number of generic functions.\ text \The functor map-dual lifts functions to dual types. Isabelle's generic definition is not straightforward to understand and use. Yet conceptually it can be explained as follows.\ lemma map_dual_def_var [simp]: "(map_dual::('a \ 'b) \ 'a dual \ 'b dual) f = \ \ f \ \\<^sup>-" unfolding fun_eq_iff comp_def by (metis dual.map_sel dual_iff) lemma map_dual_def_var2: "\\<^sup>- \ map_dual f = f \ \\<^sup>-" by (simp add: rewriteL_comp_comp) lemma map_dual_func1: "map_dual (f \ g) = map_dual f \ map_dual g" unfolding fun_eq_iff comp_def by (metis dual.exhaust dual.map) lemma map_dual_func2 : "map_dual id = id" by simp text \The functor map-dual has an inverse functor as well.\ definition map_dual_inv :: "('a dual \ 'b dual) => ('a => 'b)" where "map_dual_inv f = \\<^sup>- \ f \ \" lemma map_dual_inv_func1: "map_dual_inv id = id" by (simp add: map_dual_inv_def) lemma map_dual_inv_func2: "map_dual_inv (f \ g) = map_dual_inv f \ map_dual_inv g" unfolding fun_eq_iff comp_def map_dual_inv_def by (metis dual_iff) lemma map_dual_inv1: "map_dual \ map_dual_inv = id" unfolding fun_eq_iff map_dual_def_var map_dual_inv_def comp_def id_def by (metis dual_iff) lemma map_dual_inv2: "map_dual_inv \ map_dual = id" unfolding fun_eq_iff map_dual_def_var map_dual_inv_def comp_def id_def by (metis dual_iff) text \Hence dual is an isomorphism between categories.\ lemma subset_dual: "(\ ` X = Y) \ (X = \\<^sup>- ` Y)" by (metis dual_inj image_comp image_inv_f_f inv_o_cancel dual_inv2) lemma subset_dual1: "(X \ Y) \ (\ ` X \ \ ` Y)" by (simp add: dual_inj inj_image_subset_iff) lemma dual_ball: "(\x \ X. P (\ x)) \ (\y \ \ ` X. P y)" by simp lemma dual_inv_ball: "(\x \ X. P (\\<^sup>- x)) \ (\y \ \\<^sup>- ` X. P y)" by simp lemma dual_all: "(\x. P (\ x)) \ (\y. P y)" by (metis dual.collapse) lemma dual_inv_all: "(\x. P (\\<^sup>- x)) \ (\y. P y)" by (metis dual_inv_surj surj_def) lemma dual_ex: "(\x. P (\ x)) \ (\y. P y)" by (metis UNIV_I bex_imageD dual_surj) lemma dual_inv_ex: "(\x. P (\\<^sup>- x)) \ (\y. P y)" by (metis dual.sel) lemma dual_Collect: "{\ x |x. P (\ x)} = {y. P y}" by (metis dual.exhaust) lemma dual_inv_Collect: "{\\<^sup>- x |x. P (\\<^sup>- x)} = {y. P y}" by (metis dual.collapse dual.inject) lemma fun_dual1: "(f \ \ = g) \ (f = g \ \\<^sup>-)" by auto lemma fun_dual2: "(\ \ f = g) \ (f = \\<^sup>- \ g)" by auto lemma fun_dual3: "(f \ (`) \ = g) \ (f = g \ (`) \\<^sup>-)" unfolding fun_eq_iff comp_def by (metis subset_dual) lemma fun_dual4: "(f = \\<^sup>- \ g \ (`) \) \ (\ \ f \ (`) \\<^sup>- = g)" by (metis fun_dual2 fun_dual3 o_assoc) text \The next facts show incrementally that the dual of a complete lattice is a complete lattice. This follows once again Wenzel.\ instantiation dual :: (ord) ord begin definition less_eq_dual_def: "(\) = rel_dual (\)" definition less_dual_def: "(<) = rel_dual (>)" instance.. end lemma less_eq_dual_def_var: "(x \ y) = (\\<^sup>- y \ \\<^sup>- x)" apply (rule antisym) apply (simp add: dual.rel_sel less_eq_dual_def) by (simp add: dual.rel_sel less_eq_dual_def) lemma less_dual_def_var: "(x < y) = (\\<^sup>- y < \\<^sup>- x)" by (simp add: dual.rel_sel less_dual_def) instance dual :: (preorder) preorder apply standard apply (simp add: less_dual_def_var less_eq_dual_def_var less_le_not_le) apply (simp add: less_eq_dual_def_var) by (meson less_eq_dual_def_var order_trans) instance dual :: (order) order by (standard, simp add: dual.expand less_eq_dual_def_var) lemma dual_anti: "x \ y \ \ y \ \ x" by (simp add: dual_inj less_eq_dual_def the_inv_f_f) lemma dual_anti_iff: "(x \ y) = (\ y \ \ x)" by (simp add: dual_inj less_eq_dual_def the_inv_f_f) text \map-dual does not map isotone functions to antitone ones. It simply lifts the type!\ lemma "mono f \ mono (map_dual f)" unfolding map_dual_def_var mono_def by (metis comp_apply dual_anti less_eq_dual_def_var) instantiation dual :: (lattice) lattice begin definition inf_dual_def: "x \ y = \ (\\<^sup>- x \ \\<^sup>- y)" definition sup_dual_def: "x \ y = \ (\\<^sup>- x \ \\<^sup>- y)" instance by (standard, simp_all add: dual_inj inf_dual_def sup_dual_def less_eq_dual_def_var the_inv_f_f) end instantiation dual :: (complete_lattice) complete_lattice begin definition Inf_dual_def: "Inf = \ \ Sup \ (`) \\<^sup>-" definition Sup_dual_def: "Sup = \ \ Inf \ (`) \\<^sup>-" definition bot_dual_def: "\ = \ \" definition top_dual_def: "\ = \ \" instance by (standard, simp_all add: Inf_dual_def top_dual_def Sup_dual_def bot_dual_def dual_inj le_INF_iff SUP_le_iff INF_lower SUP_upper less_eq_dual_def_var the_inv_f_f) end text \Next, directed and filtered sets, upsets, downsets, filters and ideals in posets are defined.\ context ord begin definition directed :: "'a set \ bool" where "directed X = (\Y. finite Y \ Y \ X \ (\x \ X. \y \ Y. y \ x))" definition filtered :: "'a set \ bool" where "filtered X = (\Y. finite Y \ Y \ X \ (\x \ X. \y \ Y. x \ y))" definition downset_set :: "'a set \ 'a set" ("\") where "\X = {y. \x \ X. y \ x}" definition upset_set :: "'a set \ 'a set" ("\") where "\X = {y. \x \ X. x \ y}" end subsection \Examples that Do Not Dualise\ text \Filtered and directed sets are dual.\ text \Proofs could be simplified if dual was idempotent.\ lemma filtered_directed_dual: "filtered \ (`) \ = directed" proof- {fix X::"'a set" have "(filtered \ (`) \) X = (\Y. finite (\\<^sup>- ` Y) \ \\<^sup>- ` Y \ X \ (\x \ X.\y \ (\\<^sup>- ` Y). \ x \ \ y))" unfolding filtered_def comp_def by (simp, metis dual_iff finite_subset_image subset_dual subset_dual1) also have "... = (\Y. finite Y \ Y \ X \ (\x \ X.\y \ Y. y \ x))" by (metis dual_anti_iff dual_inv_surj finite_subset_image top.extremum) finally have "(filtered \ (`) \) X = directed X" using directed_def by auto} thus ?thesis unfolding fun_eq_iff by simp qed lemma directed_filtered_dual: "directed \ (`) \ = filtered" proof- {fix X::"'a set" have "(directed \ (`) \) X = (\Y. finite (\\<^sup>- ` Y) \ \\<^sup>- ` Y \ X \ (\x \ X.\y \ (\\<^sup>- ` Y). \ y \ \ x))" unfolding directed_def comp_def by (simp, metis dual_iff finite_subset_image subset_dual subset_dual1) also have "... = (\Y. finite Y \ Y \ X \ (\x \ X.\y \ Y. x \ y))" unfolding dual_anti_iff[symmetric] by (metis dual_inv_surj finite_subset_image top_greatest) finally have "(directed \ (`) \) X = filtered X" using filtered_def by auto} thus ?thesis unfolding fun_eq_iff by simp qed text \This example illustrates the deficiency of the approach. In the class-based approach the second proof is trivial.\ text \The next example shows that this is a systematic problem.\ lemma downset_set_upset_set_dual: "(`) \ \ \ = \ \ (`) \" proof- {fix X::"'a set" have "((`) \ \ \) X = {\ y |y. \x \ X. y \ x}" by (simp add: downset_set_def setcompr_eq_image) also have "... = {\ y |y. \x \ X. \ x \ \ y}" by (meson dual_anti_iff) also have "... = {y. \x \ \ ` X. x \ y}" by (metis (mono_tags, opaque_lifting) dual.exhaust image_iff) finally have "((`) \ \ \) X = (\ \ (`) \) X" by (simp add: upset_set_def)} thus ?thesis unfolding fun_eq_iff by simp qed lemma upset_set_downset_set_dual: "(`) \ \ \ = \ \ (`) \" unfolding downset_set_def upset_set_def fun_eq_iff comp_def apply (safe, force simp: dual_anti) by (metis (mono_tags, lifting) dual.exhaust dual_anti_iff mem_Collect_eq rev_image_eqI) end - - - - - - - - - diff --git a/thys/Order_Lattice_Props/Representations.thy b/thys/Order_Lattice_Props/Representations.thy --- a/thys/Order_Lattice_Props/Representations.thy +++ b/thys/Order_Lattice_Props/Representations.thy @@ -1,625 +1,620 @@ (* Title: Representation Theorems for Orderings and Lattices Author: Georg Struth Maintainer: Georg Struth *) section \Representation Theorems for Orderings and Lattices\ theory Representations imports Order_Lattice_Props begin subsection \Representation of Posets\ text \The isomorphism between partial orders and downsets with set inclusion is well known. It forms the basis of Priestley and Stone duality. I show it not only for objects, but also order morphisms, hence establish equivalences and isomorphisms between categories.\ typedef (overloaded) 'a downset = "range (\::'a::ord \ 'a set)" by fastforce setup_lifting type_definition_downset text \The map ds yields the isomorphism between the set and the powerset level if its range is restricted to downsets.\ definition ds :: "'a::ord \ 'a downset" where "ds = Abs_downset \ \" text \In a complete lattice, its inverse is Sup.\ definition SSup :: "'a::complete_lattice downset \ 'a" where "SSup = Sup \ Rep_downset" lemma ds_SSup_inv: "ds \ SSup = (id::'a::complete_lattice downset \ 'a downset)" unfolding ds_def SSup_def by (smt Rep_downset Rep_downset_inverse cSup_atMost eq_id_iff imageE o_def ord_class.atMost_def ord_class.downset_prop) lemma SSup_ds_inv: "SSup \ ds = (id::'a::complete_lattice \ 'a)" unfolding ds_def SSup_def fun_eq_iff id_def comp_def by (simp add: Abs_downset_inverse pointfree_idE) instantiation downset :: (ord) order begin lift_definition less_eq_downset :: "'a downset \ 'a downset \ bool" is "(\X Y. Rep_downset X \ Rep_downset Y)" . lift_definition less_downset :: "'a downset \ 'a downset \ bool" is "(\X Y. Rep_downset X \ Rep_downset Y)" . instance by (intro_classes, transfer, auto simp: Rep_downset_inject less_eq_downset_def) end lemma ds_iso: "mono ds" unfolding mono_def ds_def fun_eq_iff comp_def by (metis Abs_downset_inverse downset_iso_iff less_eq_downset.rep_eq rangeI) lemma ds_faithful: "ds x \ ds y \ x \ (y::'a::order)" by (simp add: Abs_downset_inverse downset_faithful ds_def less_eq_downset.rep_eq) lemma ds_inj: "inj (ds::'a::order \ 'a downset)" by (simp add: ds_faithful dual_order.antisym injI) lemma ds_surj: "surj ds" by (metis (no_types, opaque_lifting) Rep_downset Rep_downset_inverse ds_def image_iff o_apply surj_def) lemma ds_bij: "bij (ds::'a::order \ 'a downset)" by (simp add: bijI ds_inj ds_surj) lemma ds_ord_iso: "ord_iso ds" unfolding ord_iso_def comp_def inf_bool_def by (smt UNIV_I ds_bij ds_faithful ds_inj ds_iso ds_surj f_the_inv_into_f inf1I mono_def) text \The morphishms between orderings and downsets are isotone functions. One can define functors mapping back and forth between these.\ definition map_ds :: "('a::complete_lattice \ 'b::complete_lattice) \ ('a downset \ 'b downset)" where "map_ds f = ds \ f \ SSup" text \This definition is actually contrived. We have shown that a function f between posets P and Q is isotone if and only if the inverse image of f maps downclosed sets in Q to downclosed sets in P. There is the following duality: ds is a natural transformation between the identity functor and the preimage functor as a contravariant functor from P to Q. Hence orderings with isotone maps and downsets with downset-preserving maps are dual, which is a first step towards Stone duality. I don't see a way of proving this with Isabelle, as the types of the preimage of f are the wrong way and I don't see how I could capture opposition with what I have.\ (*lemma "mono (f::'a::complete_lattice \ 'b::complete_lattimap_ds f = Abs_downset \ (-`) f \ Rep_downset" doesn't work! *) lemma map_ds_prop: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "map_ds f \ ds = ds \ f" unfolding map_ds_def by (simp add: SSup_ds_inv comp_assoc) lemma map_ds_prop2: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "map_ds f \ ds = ds \ id f" unfolding map_ds_def by (simp add: SSup_ds_inv comp_assoc) text \This is part of showing that map-ds is naturally isomorphic to the identity functor, ds being the natural isomorphism.\ definition map_SSup :: "('a downset \ 'b downset) \ ('a::complete_lattice \ 'b::complete_lattice)" where "map_SSup F = SSup \ F \ ds" lemma map_ds_iso_pres: fixes f :: "'a::complete_lattice \ 'b::complete_lattice" shows "mono f \ mono (map_ds f)" unfolding fun_eq_iff mono_def map_ds_def ds_def SSup_def comp_def by (metis Abs_downset_inverse Sup_subset_mono downset_iso_iff less_eq_downset.rep_eq rangeI) lemma map_SSup_iso_pres: fixes F :: "'a::complete_lattice downset \ 'b::complete_lattice downset" shows "mono F \ mono (map_SSup F)" unfolding fun_eq_iff mono_def map_SSup_def ds_def SSup_def comp_def by (metis Abs_downset_inverse Sup_subset_mono downset_iso_iff less_eq_downset.rep_eq rangeI) lemma map_SSup_prop: fixes F :: "'a::complete_lattice downset \ 'b::complete_lattice downset" shows "ds \ map_SSup F = F \ ds" unfolding map_SSup_def by (metis ds_SSup_inv fun.map_id0 id_def rewriteL_comp_comp) lemma map_SSup_prop2: fixes F :: "'a::complete_lattice downset \ 'b::complete_lattice downset" shows "ds \ map_SSup F = id F \ ds" by (simp add: map_SSup_prop) lemma map_ds_func1: "map_ds id = (id::'a::complete_lattice downset\ 'a downset)" by (simp add: ds_SSup_inv map_ds_def) lemma map_ds_func2: fixes g :: "'a::complete_lattice \ 'b::complete_lattice" shows "map_ds (f \ g) = map_ds f \ map_ds g" unfolding map_ds_def fun_eq_iff comp_def ds_def SSup_def by (metis Abs_downset_inverse Sup_atMost atMost_def downset_prop rangeI) lemma map_SSup_func1: "map_SSup (id::'a::complete_lattice downset\ 'a downset) = id" by (simp add: SSup_ds_inv map_SSup_def) lemma map_SSup_func2: fixes F :: "'c::complete_lattice downset \ 'b::complete_lattice downset" and G :: "'a::complete_lattice downset \ 'c downset" shows "map_SSup (F \ G) = map_SSup F \ map_SSup G" unfolding map_SSup_def fun_eq_iff comp_def id_def ds_def by (metis comp_apply ds_SSup_inv ds_def id_apply) lemma map_SSup_map_ds_inv: "map_SSup \ map_ds = (id::('a::complete_lattice \ 'b::complete_lattice) \ ('a \ 'b))" by (metis (no_types, opaque_lifting) SSup_ds_inv comp_def eq_id_iff fun.map_comp fun.map_id0 id_apply map_SSup_prop map_ds_prop) lemma map_ds_map_SSup_inv: "map_ds \ map_SSup = (id::('a::complete_lattice downset \ 'b::complete_lattice downset) \ ('a downset \ 'b downset))" unfolding map_SSup_def map_ds_def SSup_def ds_def id_def comp_def fun_eq_iff by (metis (no_types, lifting) Rep_downset Rep_downset_inverse Sup_downset_id image_iff pointfree_idE) lemma inj_map_ds: "inj (map_ds::('a::complete_lattice \ 'b::complete_lattice) \ ('a downset \ 'b downset))" by (metis (no_types, lifting) SSup_ds_inv fun.map_id0 id_comp inj_def map_ds_prop rewriteR_comp_comp2) lemma inj_map_SSup: "inj (map_SSup::('a::complete_lattice downset \ 'b::complete_lattice downset) \ ('a \ 'b))" by (metis inj_on_id inj_on_imageI2 map_ds_map_SSup_inv) lemma map_ds_map_SSup_iff: fixes g :: "'a::complete_lattice \ 'b::complete_lattice" shows "(f = map_ds g) = (map_SSup f = g)" by (metis inj_eq inj_map_ds map_ds_map_SSup_inv pointfree_idE) text \This gives an isomorphism between categories.\ lemma surj_map_ds: "surj (map_ds::('a::complete_lattice \ 'b::complete_lattice) \ ('a downset \ 'b downset))" by (simp add: map_ds_map_SSup_iff surj_def) lemma surj_map_SSup: "surj (map_SSup::('a::complete_lattice_with_dual downset \ 'b::complete_lattice_with_dual downset) \ ('a \ 'b))" by (metis map_ds_map_SSup_iff surjI) text \There is of course a dual result for upsets with the reverse inclusion ordering. Once again, it seems impossible to capture the "real" duality that uses the inverse image functor.\ typedef (overloaded) 'a upset = "range (\::'a::ord \ 'a set)" by fastforce setup_lifting type_definition_upset definition us :: "'a::ord \ 'a upset" where "us = Abs_upset \ \" definition IInf :: "'a::complete_lattice upset \ 'a" where "IInf = Inf \ Rep_upset" lemma us_ds: "us = Abs_upset \ (`) \ \ Rep_downset \ ds \ (\::'a::ord_with_dual \ 'a)" unfolding us_def ds_def fun_eq_iff comp_def by (simp add: Abs_downset_inverse upset_to_downset2) lemma IInf_SSup: "IInf = \ \ SSup \ Abs_downset \ (`) (\::'a::complete_lattice_with_dual \ 'a) \ Rep_upset" unfolding IInf_def SSup_def fun_eq_iff comp_def by (metis (no_types, opaque_lifting) Abs_downset_inverse Rep_upset Sup_dual_def_var image_iff rangeI subset_dual upset_to_downset3) lemma us_IInf_inv: "us \ IInf = (id::'a::complete_lattice_with_dual upset \ 'a upset)" unfolding us_def IInf_def fun_eq_iff id_def comp_def by (metis (no_types, lifting) Inf_upset_id Rep_upset Rep_upset_inverse f_the_inv_into_f pointfree_idE upset_inj) lemma IInf_us_inv: "IInf \ us = (id::'a::complete_lattice_with_dual \ 'a)" unfolding us_def IInf_def fun_eq_iff id_def comp_def by (metis Abs_upset_inverse Sup_Inf_var Sup_atLeastAtMost Sup_dual_upset_var order_refl rangeI) instantiation upset :: (ord) order begin lift_definition less_eq_upset :: "'a upset \ 'a upset \ bool" is "(\X Y. Rep_upset X \ Rep_upset Y)" . lift_definition less_upset :: "'a upset \ 'a upset \ bool" is "(\X Y. Rep_upset X \ Rep_upset Y)" . instance by (intro_classes, transfer, simp_all add: less_le_not_le less_eq_upset.rep_eq Rep_upset_inject) end lemma us_iso: "x \ y \ us x \ us (y::'a::order_with_dual)" by (simp add: Abs_upset_inverse less_eq_upset.rep_eq upset_anti_iff us_def) lemma us_faithful: "us x \ us y \ x \ (y::'a::order_with_dual)" by (simp add: Abs_upset_inverse upset_faithful us_def less_eq_upset.rep_eq) lemma us_inj: "inj (us::'a::order_with_dual \ 'a upset)" unfolding inj_def by (simp add: us_faithful dual_order.antisym) lemma us_surj: "surj (us::'a::order_with_dual \ 'a upset)" unfolding surj_def by (metis Rep_upset Rep_upset_inverse comp_def image_iff us_def) lemma us_bij: "bij (us::'a::order_with_dual \ 'a upset)" by (simp add: bij_def us_surj us_inj) lemma us_ord_iso: "ord_iso (us::'a::order_with_dual \ 'a upset)" unfolding ord_iso_def by (simp, metis (no_types, lifting) UNIV_I f_the_inv_into_f monoI us_iso us_bij us_faithful us_inj us_surj) definition map_us :: "('a::complete_lattice \ 'b::complete_lattice) \ ('a upset \ 'b upset)" where "map_us f = us \ f \ IInf" lemma map_us_prop: "map_us f \ (us::'a::complete_lattice_with_dual \ 'a upset) = us \ id f" unfolding map_us_def by (simp add: IInf_us_inv comp_assoc) definition map_IInf :: "('a upset \ 'b upset) \ ('a::complete_lattice \ 'b::complete_lattice)" where "map_IInf F = IInf \ F \ us" lemma map_IInf_prop: "(us::'a::complete_lattice_with_dual \ 'a upset) \ map_IInf F = id F \ us" proof- have "us \ map_IInf F = (us \ IInf) \ F \ us" by (simp add: fun.map_comp map_IInf_def) thus ?thesis by (simp add: us_IInf_inv) qed lemma map_us_func1: "map_us id = (id::'a::complete_lattice_with_dual upset \ 'a upset)" unfolding map_us_def fun_eq_iff comp_def us_def id_def IInf_def by (metis (no_types, lifting) Inf_upset_id Rep_upset Rep_upset_inverse image_iff pointfree_idE) lemma map_us_func2: fixes f :: "'c::complete_lattice_with_dual \ 'b::complete_lattice_with_dual" and g :: "'a::complete_lattice_with_dual \ 'c" shows "map_us (f \ g) = map_us f \ map_us g" unfolding map_us_def fun_eq_iff comp_def us_def IInf_def by (metis Abs_upset_inverse Sup_Inf_var Sup_atLeastAtMost Sup_dual_upset_var order_refl rangeI) lemma map_IInf_func1: "map_IInf id = (id::'a::complete_lattice_with_dual \ 'a)" unfolding map_IInf_def fun_eq_iff comp_def id_def us_def IInf_def by (simp add: Abs_upset_inverse pointfree_idE) lemma map_IInf_func2: fixes F :: "'c::complete_lattice_with_dual upset \ 'b::complete_lattice_with_dual upset" and G :: "'a::complete_lattice_with_dual upset \ 'c upset" shows "map_IInf (F \ G) = map_IInf F \ map_IInf G" unfolding map_IInf_def fun_eq_iff comp_def id_def us_def by (metis comp_apply id_apply us_IInf_inv us_def) lemma map_IInf_map_us_inv: "map_IInf \ map_us = (id::('a::complete_lattice_with_dual \ 'b::complete_lattice_with_dual) \ ('a \ 'b))" unfolding map_IInf_def map_us_def IInf_def us_def id_def comp_def fun_eq_iff by (simp add: Abs_upset_inverse pointfree_idE) lemma map_us_map_IInf_inv: "map_us \ map_IInf = (id::('a::complete_lattice_with_dual upset \ 'b::complete_lattice_with_dual upset) \ ('a upset \ 'b upset))" unfolding map_IInf_def map_us_def IInf_def us_def id_def comp_def fun_eq_iff by (metis (no_types, lifting) Inf_upset_id Rep_upset Rep_upset_inverse image_iff pointfree_idE) lemma inj_map_us: "inj (map_us::('a::complete_lattice_with_dual \ 'b::complete_lattice_with_dual) \ ('a upset \ 'b upset))" unfolding map_us_def us_def IInf_def inj_def comp_def fun_eq_iff by (metis (no_types, opaque_lifting) Abs_upset_inverse Inf_upset_id pointfree_idE rangeI) lemma inj_map_IInf: "inj (map_IInf::('a::complete_lattice_with_dual upset \ 'b::complete_lattice_with_dual upset) \ ('a \ 'b))" unfolding map_IInf_def fun_eq_iff inj_def comp_def IInf_def us_def by (metis (no_types, opaque_lifting) Inf_upset_id Rep_upset Rep_upset_inverse image_iff pointfree_idE) lemma map_us_map_IInf_iff: fixes g :: "'a::complete_lattice_with_dual \ 'b::complete_lattice_with_dual" shows "(f = map_us g) = (map_IInf f = g)" by (metis inj_eq inj_map_us map_us_map_IInf_inv pointfree_idE) lemma map_us_mono_pres: fixes f :: "'a::complete_lattice_with_dual \ 'b::complete_lattice_with_dual" shows "mono f \ mono (map_us f)" unfolding mono_def map_us_def comp_def us_def IInf_def by (metis Abs_upset_inverse Inf_superset_mono less_eq_upset.rep_eq rangeI upset_anti_iff) lemma map_IInf_mono_pres: fixes F :: "'a::complete_lattice_with_dual upset \ 'b::complete_lattice_with_dual upset" shows "mono F \ mono (map_IInf F)" unfolding mono_def map_IInf_def comp_def us_def IInf_def oops lemma surj_map_us: "surj (map_us::('a::complete_lattice_with_dual \ 'b::complete_lattice_with_dual) \ ('a upset \ 'b upset))" by (simp add: map_us_map_IInf_iff surj_def) lemma surj_map_IInf: "surj (map_IInf::('a::complete_lattice_with_dual upset \ 'b::complete_lattice_with_dual upset) \ ('a \ 'b))" by (metis map_us_map_IInf_iff surjI) text \Hence we have again an isomorphism --- or rather equivalence --- between categories. Here, however, duality is not consistently picked up.\ subsection \Stone's Theorem in the Presence of Atoms\ text \Atom-map is a boolean algebra morphism.\ -context boolean_algebra +context Lattices.boolean_algebra begin lemma atom_map_compl_pres: "atom_map (-x) = Collect atom - atom_map x" proof- {fix y have "(y \ atom_map (-x)) = (atom y \ y \ -x)" by (simp add: atom_map_def) also have "... = (atom y \ \(y \ x))" by (metis atom_sup_iff inf.orderE meet_shunt sup_compl_top top.ordering_top_axioms ordering_top.extremum) also have "... = (y \ Collect atom - atom_map x)" using atom_map_def by auto finally have "(y \ atom_map (-x)) = (y \ Collect atom - atom_map x)".} thus ?thesis by blast qed lemma atom_map_sup_pres: "atom_map (x \ y) = atom_map x \ atom_map y" proof- {fix z have "(z \ atom_map (x \ y)) = (atom z \ z \ x \ y)" by (simp add: atom_map_def) also have "... = (atom z \ (z \ x \ z \ y))" using atom_sup_iff by auto also have "... = (z \ atom_map x \ atom_map y)" using atom_map_def by auto finally have "(z \ atom_map (x \ y)) = (z \ atom_map x \ atom_map y)" by blast} thus ?thesis by blast qed lemma atom_map_inf_pres: "atom_map (x \ y) = atom_map x \ atom_map y" by (smt Diff_Un atom_map_compl_pres atom_map_sup_pres compl_inf double_compl) lemma atom_map_minus_pres: "atom_map (x - y) = atom_map x - atom_map y" using atom_map_compl_pres atom_map_def diff_eq by auto end text \The homomorphic images of boolean algebras under atom-map are boolean algebras --- in fact powerset boolean algebras.\ -instantiation atoms :: (boolean_algebra) boolean_algebra +instantiation atoms :: (Lattices.boolean_algebra) Lattices.boolean_algebra begin lift_definition minus_atoms :: "'a atoms \ 'a atoms \ 'a atoms" is "\x y. Abs_atoms (Rep_atoms x - Rep_atoms y)". lift_definition uminus_atoms :: "'a atoms \ 'a atoms" is "\x. Abs_atoms (Collect atom - Rep_atoms x)". lift_definition bot_atoms :: "'a atoms" is "Abs_atoms {}". lift_definition sup_atoms :: "'a atoms \ 'a atoms \ 'a atoms" is "\x y. Abs_atoms (Rep_atoms x \ Rep_atoms y)". lift_definition top_atoms :: "'a atoms" is "Abs_atoms (Collect atom)". lift_definition inf_atoms :: "'a atoms \ 'a atoms \ 'a atoms" is "\x y. Abs_atoms (Rep_atoms x \ Rep_atoms y)". lift_definition less_eq_atoms :: "'a atoms \ 'a atoms \ bool" is "(\x y. Rep_atoms x \ Rep_atoms y)". lift_definition less_atoms :: "'a atoms \ 'a atoms \ bool" is "(\x y. Rep_atoms x \ Rep_atoms y)". instance apply intro_classes apply (transfer, simp add: less_le_not_le) apply (transfer, simp) apply (transfer, blast) apply (simp add: Rep_atoms_inject less_eq_atoms.abs_eq) apply (transfer, smt Abs_atoms_inverse Rep_atoms atom_map_inf_pres image_iff inf_le1 rangeI) apply (transfer, smt Abs_atoms_inverse Rep_atoms atom_map_inf_pres image_iff inf_le2 rangeI) apply (transfer, smt Abs_atoms_inverse Rep_atoms atom_map_inf_pres image_iff le_iff_sup rangeI sup_inf_distrib1) apply (transfer, smt Abs_atoms_inverse Rep_atoms atom_map_sup_pres image_iff image_iff inf.orderE inf_sup_aci(6) le_iff_sup order_refl rangeI rangeI) apply (transfer, smt Abs_atoms_inverse Rep_atoms atom_map_sup_pres image_iff inf_sup_aci(6) le_iff_sup rangeI sup.left_commute sup.right_idem) apply (transfer, subst Abs_atoms_inverse, metis (no_types, lifting) Rep_atoms atom_map_sup_pres image_iff rangeI, simp) apply transfer using Abs_atoms_inverse atom_map_bot_pres apply blast apply (transfer, metis Abs_atoms_inverse Rep_atoms atom_map_compl_pres atom_map_top_pres diff_eq double_compl inf_le1 rangeE rangeI) apply (transfer, smt Abs_atoms_inverse Rep_atoms atom_map_inf_pres atom_map_sup_pres image_iff rangeI sup_inf_distrib1) apply (transfer, metis (no_types, opaque_lifting) Abs_atoms_inverse Diff_disjoint Rep_atoms atom_map_compl_pres rangeE rangeI) apply (transfer, smt Abs_atoms_inverse uminus_atoms.abs_eq Rep_atoms Un_Diff_cancel atom_map_compl_pres atom_map_inf_pres atom_map_minus_pres atom_map_sup_pres atom_map_top_pres diff_eq double_compl inf_compl_bot_right rangeE rangeI sup_commute sup_compl_top) by transfer (smt Abs_atoms_inverse Rep_atoms atom_map_compl_pres atom_map_inf_pres atom_map_minus_pres diff_eq rangeE rangeI) end text \The homomorphism atom-map can then be restricted in its output type to the powerset boolean algebra.\ lemma at_map_bot_pres: "at_map \ = \" by (simp add: at_map_def atom_map_bot_pres bot_atoms.transfer) lemma at_map_top_pres: "at_map \ = \" by (simp add: at_map_def atom_map_top_pres top_atoms.transfer) lemma at_map_compl_pres: "at_map \ uminus = uminus \ at_map" unfolding fun_eq_iff by (simp add: Abs_atoms_inverse at_map_def atom_map_compl_pres uminus_atoms.abs_eq) lemma at_map_sup_pres: "at_map (x \ y) = at_map x \ at_map y" unfolding at_map_def comp_def by (metis (mono_tags, lifting) Abs_atoms_inverse atom_map_sup_pres rangeI sup_atoms.transfer) lemma at_map_inf_pres: "at_map (x \ y) = at_map x \ at_map y" unfolding at_map_def comp_def by (metis (mono_tags, lifting) Abs_atoms_inverse atom_map_inf_pres inf_atoms.transfer rangeI) lemma at_map_minus_pres: "at_map (x - y) = at_map x - at_map y" unfolding at_map_def comp_def by (simp add: Abs_atoms_inverse atom_map_minus_pres minus_atoms.abs_eq) context atomic_boolean_algebra begin text \In atomic boolean algebras, atom-map is an embedding that maps atoms of the boolean algebra to those of the powerset boolean algebra. Analogous properties hold for at-map.\ lemma inj_atom_map: "inj atom_map" proof- {fix x y ::'a assume "x \ y" hence "x \ -y \ \ \ -x \ y \ \" by (auto simp: meet_shunt) hence "\z. atom z \ (z \ x \ -y \ z \ -x \ y)" using atomicity by blast hence "\z. atom z \ ((z \ atom_map x \ \(z \ atom_map y)) \ (\(z \ atom_map x) \ z \ atom_map y))" unfolding atom_def atom_map_def by (clarsimp, metis diff_eq inf.orderE meet_shunt_var) hence "atom_map x \ atom_map y" by blast} thus ?thesis by (meson injI) qed lemma atom_map_atom_pres: "atom x \ atom_map x = {x}" unfolding atom_def atom_map_def by (auto simp: bot_less dual_order.order_iff_strict) lemma atom_map_atom_pres2: "atom x \ atom (atom_map x)" proof- assume "atom x" hence "atom_map x = {x}" by (simp add: atom_map_atom_pres) thus "atom (atom_map x)" using bounded_lattice_class.atom_def by auto qed end lemma inj_at_map: "inj (at_map::'a::atomic_boolean_algebra \ 'a atoms)" unfolding at_map_def comp_def by (metis (no_types, lifting) Abs_atoms_inverse inj_atom_map inj_def rangeI) lemma at_map_atom_pres: "atom (x::'a::atomic_boolean_algebra) \ at_map x = Abs_atoms {x}" unfolding at_map_def comp_def by (simp add: atom_map_atom_pres) lemma at_map_atom_pres2: "atom (x::'a::atomic_boolean_algebra) \ atom (at_map x)" unfolding at_map_def comp_def by (metis Abs_atoms_inverse atom_def atom_map_atom_pres2 atom_map_bot_pres bot_atoms.abs_eq less_atoms.abs_eq rangeI) text \Homomorphic images of atomic boolean algebras under atom-map are therefore atomic (rather obviously).\ instance atoms :: (atomic_boolean_algebra) atomic_boolean_algebra proof intro_classes fix x::"'a atoms" assume "x \ \" hence "\y. x = at_map y \ x \ \" unfolding at_map_def comp_def by (metis Abs_atoms_cases rangeE) hence "\y. x = at_map y \ (\z. atom z \ z \ y)" using at_map_bot_pres atomicity by force hence "\y. x = at_map y \ (\z. atom (at_map z) \ at_map z \ at_map y)" by (metis at_map_atom_pres2 at_map_sup_pres sup.orderE sup_ge2) thus "\y. atom y \ y \ x" by fastforce qed context complete_boolean_algebra_alt begin text \In complete boolean algebras, atom-map is surjective; more precisely it is the left inverse of Sup, at least for sets of atoms. Below, this statement is made more explicit for at-map.\ lemma surj_atom_map: "Y \ Collect atom \ Y = atom_map (\Y)" proof assume "Y \ Collect atom" thus "Y \ atom_map (\Y)" using Sup_upper atom_map_def by force next assume "Y \ Collect atom" hence a: "\y. y \ Y \ atom y" by blast {fix z assume h: "z \ Collect atom - Y" hence "\y \ Y. y \ z = \" by (metis DiffE a h atom_def dual_order.not_eq_order_implies_strict inf.absorb_iff2 inf_le2 meet_shunt mem_Collect_eq) hence "\Y \ z = \" using Sup_least meet_shunt by simp hence "z \ atom_map (\Y)" using atom_map_bot_pres atom_map_def by force} thus "atom_map (\Y) \ Y" using atom_map_def by force qed text \In this setting, atom-map is a complete boolean algebra morphism.\ lemma atom_map_Sup_pres: "atom_map (\X) = (\x \ X. atom_map x)" proof- {fix z have "(z \ atom_map (\X)) = (atom z \ z \ \X)" by (simp add: atom_map_def) also have "... = (atom z \ (\x \ X. z \ x))" using atom_Sup_iff by auto also have "... = (z \ (\x \ X. atom_map x))" using atom_map_def by auto finally have "(z \ atom_map (\X)) = (z \ (\x \ X. atom_map x))" by blast} thus ?thesis by blast qed lemma atom_map_Sup_pres_var: "atom_map \ Sup = Sup \ (`) atom_map" unfolding fun_eq_iff comp_def by (simp add: atom_map_Sup_pres) text \For Inf-preservation, it is important that Infs are restricted to homomorphic images; hence they need to be pushed into the set of all atoms.\ lemma atom_map_Inf_pres: "atom_map (\X) = Collect atom \ (\x \ X. atom_map x)" proof- have "atom_map (\X) = atom_map (-(\x \ X. -x))" by (smt Collect_cong SUP_le_iff atom_map_def compl_le_compl_iff compl_le_swap1 le_Inf_iff) also have "... = Collect atom - atom_map (\x \ X. -x)" using atom_map_compl_pres by blast also have "... = Collect atom - (\x \ X. atom_map (-x))" by (simp add: atom_map_Sup_pres) also have "... = Collect atom - (\x \ X. Collect atom - atom_map (x))" using atom_map_compl_pres by blast also have "... = Collect atom \ (\x \ X. atom_map x)" by blast finally show ?thesis. qed end text \It follows that homomorphic images of complete boolean algebras under atom-map form complete boolean algebras.\ instantiation atoms :: (complete_boolean_algebra_alt) complete_boolean_algebra_alt begin lift_definition Inf_atoms :: "'a::complete_boolean_algebra_alt atoms set \ 'a::complete_boolean_algebra_alt atoms" is "\X. Abs_atoms (Collect atom \ Inter ((`) Rep_atoms X))". lift_definition Sup_atoms :: "'a::complete_boolean_algebra_alt atoms set \ 'a::complete_boolean_algebra_alt atoms" is "\X. Abs_atoms (Union ((`) Rep_atoms X))". instance apply (intro_classes; transfer) apply (metis (no_types, opaque_lifting) Abs_atoms_inverse image_iff inf_le1 le_Inf_iff le_infI2 order_refl rangeI surj_atom_map) apply (metis (no_types, lifting) Abs_atoms_inverse Int_subset_iff Rep_atoms Sup_upper atom_map_atoms inf_le1 le_INF_iff rangeI surj_atom_map) apply (metis Abs_atoms_inverse Rep_atoms SUP_least SUP_upper Sup_upper atom_map_atoms rangeI surj_atom_map) apply (metis Abs_atoms_inverse Rep_atoms SUP_least Sup_upper atom_map_atoms rangeI surj_atom_map) by simp_all end text \Once more, properties proved above can now be restricted to at-map.\ lemma surj_at_map_var: "at_map \ Sup \ Rep_atoms = (id::'a::complete_boolean_algebra_alt atoms \ 'a atoms)" unfolding at_map_def comp_def fun_eq_iff id_def by (metis Rep_atoms Rep_atoms_inverse Sup_upper atom_map_atoms surj_atom_map) lemma surj_at_map: "surj (at_map::'a::complete_boolean_algebra_alt \ 'a atoms)" unfolding surj_def at_map_def comp_def by (metis Rep_atoms Rep_atoms_inverse image_iff) lemma at_map_Sup_pres: "at_map \ Sup = Sup \ (`) (at_map::'a::complete_boolean_algebra_alt \ 'a atoms)" unfolding fun_eq_iff at_map_def comp_def atom_map_Sup_pres by (smt Abs_atoms_inverse Sup.SUP_cong Sup_atoms.transfer UN_extend_simps(10) rangeI) lemma at_map_Sup_pres_var: "at_map (\X) = (\(x::'a::complete_boolean_algebra_alt) \ X. (at_map x))" using at_map_Sup_pres comp_eq_elim by blast lemma at_map_Inf_pres: "at_map (\X) = Abs_atoms (Collect atom \ (\x \ X. (Rep_atoms (at_map (x::'a::complete_boolean_algebra_alt)))))" unfolding at_map_def comp_def by (metis (no_types, lifting) Abs_atoms_inverse Sup.SUP_cong atom_map_Inf_pres rangeI) lemma at_map_Inf_pres_var: "at_map \ Inf = Inf \ (`) (at_map::'a::complete_boolean_algebra_alt \ 'a atoms)" unfolding fun_eq_iff comp_def by (metis Inf_atoms.abs_eq at_map_Inf_pres image_image) text \Finally, on complete atomic boolean algebras (CABAs), at-map is an isomorphism, that is, a bijection that preserves the complete boolean algebra operations. Thus every CABA is isomorphic to a powerset boolean algebra and every powerset boolean algebra is a CABA. The bijective pair is given by at-map and Sup (defined on the powerset algebra). This theorem is a little version of Stone's theorem. In the general case, ultrafilters play the role of atoms.\ lemma "Sup \ atom_map = (id::'a::complete_atomic_boolean_algebra \ 'a)" unfolding fun_eq_iff comp_def id_def by (metis Union_upper atom_map_atoms inj_atom_map inj_def rangeI surj_atom_map) lemma inj_at_map_var: "Sup \ Rep_atoms \ at_map = (id ::'a::complete_atomic_boolean_algebra \ 'a)" unfolding at_map_def comp_def fun_eq_iff id_def by (metis Abs_atoms_inverse Union_upper atom_map_atoms inj_atom_map inj_def rangeI surj_atom_map) lemma bij_at_map: "bij (at_map::'a::complete_atomic_boolean_algebra \ 'a atoms)" unfolding bij_def by (simp add: inj_at_map surj_at_map) instance atoms :: (complete_atomic_boolean_algebra) complete_atomic_boolean_algebra.. text \A full consideration of Stone duality is left for future work.\ (* Failed attempt to prove Tarski's fixpoint theorem: The problem is that we want to use mono, but this has two type parameters. It doesn't work inside of the one-type-parameter typedef. Yet isotonicity is needed to prove inhabitance of the type. I could develop a theory of isotone endos and prove the existence of lfps and gfps, duplicating the more general facts for mono. But that's not the point. Because of this I see no direct way of proving Tarski's fixpoint theorem. Any way out? class complete_lattice_with_iso = complete_lattice + fixes f :: "'a \ 'a" (* assumes isof: "x \ y \ f x \ f y"*) typedef (overloaded) 'a Fix = "Fix (f::'a::complete_lattice_with_iso \ 'a)" setup_lifting type_definition_Fix *) end - - - - - diff --git a/thys/Relation_Algebra/More_Boolean_Algebra.thy b/thys/Relation_Algebra/More_Boolean_Algebra.thy --- a/thys/Relation_Algebra/More_Boolean_Algebra.thy +++ b/thys/Relation_Algebra/More_Boolean_Algebra.thy @@ -1,293 +1,293 @@ (* Title: Relation Algebra Author: Alasdair Armstrong, Simon Foster, Georg Struth, Tjark Weber Maintainer: Georg Struth Tjark Weber *) section \(More) Boolean Algebra\ theory More_Boolean_Algebra imports Main begin subsection \Laws of Boolean Algebra\ text \The following laws of Boolean algebra support relational proofs. We might add laws for the binary minus since that would make certain theorems look more nicely. These are currently not so well supported.\ -context boolean_algebra +context Lattices.boolean_algebra begin no_notation times (infixl "\" 70) and plus (infixl "+" 65) and Groups.zero_class.zero ("0") and Groups.one_class.one ("1") notation inf (infixl "\" 70) and sup (infixl "+" 65) and bot ("0") and top ("1") lemma meet_assoc: "x \ (y \ z) = (x \ y) \ z" by (metis inf_assoc) lemma aux4 [simp]: "x \ y + x \ -y = x" by (metis inf_sup_distrib1 inf_top_right sup_compl_top) lemma aux4_comm [simp]: "x \ -y + x \ y = x" by (metis aux4 sup.commute) lemma aux6 [simp]: "(x + y) \ -x = y \ -x" by (metis inf_compl_bot inf_sup_distrib2 sup_bot_left) lemma aux6_var [simp]: "(-x + y) \ x = x \ y" by (metis compl_inf_bot inf_commute inf_sup_distrib2 sup_bot_left) lemma aux9 [simp]: "x + -x \ y = x + y" by (metis aux4 aux6 inf.commute inf_sup_absorb) lemma join_iso: "x \ y \ x + z \ y + z" by (metis eq_refl sup_mono) lemma join_isol: "x \ y \ z + x \ z + y" by (metis join_iso sup.commute) lemma join_double_iso: "x \ y \ w + x + z \ w + y + z" by (metis le_iff_inf sup_inf_distrib1 sup_inf_distrib2) lemma comp_anti: "x \ y \ -y \ -x" by (metis compl_le_swap2 double_compl) lemma meet_iso: "x \ y \ x \ z \ y \ z" by (metis eq_refl inf_mono) lemma meet_isor: "x \ y \ z \ x \ z \ y" by (metis inf.commute meet_iso) lemma meet_double_iso: "x \ y \ w \ x \ z \ w \ y \ z" by (metis meet_iso meet_isor) lemma de_morgan_3 [simp]: "-(-x \ -y) = x + y" by (metis compl_sup double_compl) lemma subdist_2_var: "x + y \ z \ x + y" by (metis eq_refl inf_le1 sup_mono) lemma dist_alt: "\x + z = y + z; x \ z = y \ z\ \ x = y" by (metis aux4 aux6 sup.commute) text \Finally we prove the Galois connections for complementation.\ lemma galois_aux: "x \ y = 0 \ x \ -y" by (metis aux6 compl_sup double_compl inf.commute le_iff_inf sup_bot_right sup_compl_top) lemma galois_aux2: "x \ -y = 0 \ x \ y" by (metis double_compl galois_aux) lemma galois_1: "x \ -y \ z \ x \ y + z" apply (rule iffI) apply (metis inf_le2 join_iso le_iff_sup le_supE join_isol aux4) apply (metis meet_iso aux6 le_infE) done lemma galois_2: "x \ y + -z \ x \ z \ y" apply (rule iffI) apply (metis compl_sup double_compl galois_1 inf.commute) apply (metis inf.commute order_trans subdist_2_var aux4 join_iso) done lemma galois_aux3: "x + y = 1 \ -x \ y" by (metis galois_1 inf_top_left top_unique) lemma galois_aux4: "-x + y = 1 \ x \ y" by (metis double_compl galois_aux3) subsection \Boolean Algebras with Operators\ text \We follow J\'onsson and Tarski to define pairs of conjugate functions on Boolean algebras. We also consider material from Maddux's article. This gives rise to a Galois connection and the notion of Boolean algebras with operators. We do not explicitly define families of functions over Boolean algebras as a type class. This development should certainly be expanded do deal with complete Boolean algebras one the one hand and other lattices on the other hand. Boolean algebras with operators and their variants can be applied in various ways. The prime example are relation algebras. The modular laws, for instance, can be derived by instantiation. Other applications are antidomain semirings where modal operators satisfy conjugations and Galois connections, and algebras of predicate transformers.\ text\We define conjugation as a predicate which holds if a pair of functions are conjugates.\ definition is_conjugation :: "('a \ 'a) \ ('a \ 'a) \ bool" where "is_conjugation f g \ (\x y . f x \ y = 0 \ x \ g y = 0)" text \We now prove the standard lemmas. First we show that conjugation is symmetric and that conjugates are uniqely defined.\ lemma is_conjugation_sym: "is_conjugation f g \ is_conjugation g f" by (metis inf.commute is_conjugation_def) lemma is_conjugation_unique: "\is_conjugation f g; is_conjugation f h\ \ g = h" by (metis galois_aux inf.commute double_compl order.eq_iff ext is_conjugation_def) text \Next we show that conjugates give rise to adjoints in a Galois connection.\ lemma conj_galois_1: assumes "is_conjugation f g" shows "f x \ y \ x \ -g (-y)" by (metis assms is_conjugation_def double_compl galois_aux) lemma conj_galois_2: assumes "is_conjugation f g" shows "g x \ y \ x \ -f (-y)" by (metis assms is_conjugation_sym conj_galois_1) text \Now we prove some of the standard properties of adjoints and conjugates. In fact, conjugate functions even distribute over all existing suprema. We display the next proof in detail because it is elegant.\ lemma f_pre_additive: assumes "is_conjugation f g" shows "f (x + y) \ z \ f x + f y \ z" proof - have "f (x + y) \ z \ x + y \ -g (-z)" by (metis assms conj_galois_1) also have "... \ x \ -g (-z) \ y \ -g (-z)" by (metis le_sup_iff) also have "... \ f x \ z \ f y \ z" by (metis assms conj_galois_1) thus ?thesis by (metis le_sup_iff calculation) qed lemma f_additive: assumes "is_conjugation f g" shows "f (sup x y) = sup (f x) (f y)" by (metis assms order.eq_iff f_pre_additive) lemma g_pre_additive: assumes "is_conjugation f g" shows "g (sup x y) \ z \ sup (g x) (g y) \ z" by (metis assms is_conjugation_sym f_pre_additive) lemma g_additive: assumes "is_conjugation f g" shows "g (sup x y) = sup (g x) (g y)" by (metis assms is_conjugation_sym f_additive) text \Additivity of adjoints obviously implies their isotonicity.\ lemma f_iso: assumes "is_conjugation f g" shows "x \ y \ f x \ f y" by (metis assms f_additive le_iff_sup) lemma g_iso: assumes "is_conjugation f g" shows "x \ y \ g x \ g y" by (metis assms is_conjugation_sym f_iso) lemma f_subdist: assumes "is_conjugation f g" shows "f (x \ y) \ f x" by (metis assms f_iso inf_le1) lemma g_subdist: assumes "is_conjugation f g" shows "g (x \ y) \ g x" by (metis assms g_iso inf_le1) text \Next we prove cancellation and strictness laws.\ lemma cancellation_1: assumes "is_conjugation f g" shows "f (-g x) \ -x" by (metis assms conj_galois_1 double_compl eq_refl) lemma cancellation_2: assumes "is_conjugation f g" shows "g (-f x) \ -x" by (metis assms is_conjugation_sym cancellation_1) lemma f_strict: assumes "is_conjugation f g" shows "f 0 = 0" by (metis assms inf.idem inf_bot_left is_conjugation_def) lemma g_strict: assumes "is_conjugation f g" shows "g 0 = 0" by (metis assms is_conjugation_sym f_strict) text \The following variants of modular laws have more concrete counterparts in relation algebra.\ lemma modular_1_aux: assumes "is_conjugation f g" shows "f (x \ -g y) \ y = 0" by (metis assms galois_aux inf_le2 is_conjugation_def) lemma modular_2_aux: assumes "is_conjugation f g" shows "g (x \ -f y) \ y = 0" by (metis assms is_conjugation_sym modular_1_aux) lemma modular_1: assumes "is_conjugation f g" shows "f x \ y = f (x \ g y) \ y" proof - have "f x \ y = f (x \ g y + x \ -g y) \ y" by (metis aux4) hence "f x \ y = (f (x \ g y) + f (x \ -g y)) \ y" by (metis assms f_additive) hence "f x \ y = f (x \ g y) \ y + f (x \ -g y) \ y" by (metis inf.commute inf_sup_distrib1) thus ?thesis by (metis assms modular_1_aux sup_bot_right) qed lemma modular_2: assumes "is_conjugation f g" shows "g x \ y = g (x \ f y) \ y" by (metis assms is_conjugation_sym modular_1) lemma conjugate_eq_aux: "is_conjugation f g \ f (x \ -g y) \ f x \ -y" by (metis f_subdist galois_aux le_inf_iff modular_1_aux) lemma conjugate_eq: "is_conjugation f g \ (\x y. f (x \ -g y) \ f x \ -y \ g (y \ -f x) \ g y \ -x)" (is "?l \ ?r") proof assume ?l thus ?r by (metis is_conjugation_sym conjugate_eq_aux) next assume r: ?r have "\x y. f x \ y = 0 \ x \ g y = 0" by (metis aux4 inf.left_commute inf_absorb1 inf_compl_bot inf_left_idem sup_bot_left r) hence "\x y. x \ g y = 0 \ f x \ y = 0" by (metis aux4 inf.commute inf.left_commute inf_absorb1 inf_compl_bot sup_commute sup_inf_absorb r) thus "is_conjugation f g" by (metis is_conjugation_def) qed lemma conjugation_prop1: "is_conjugation f g \ f y \ z \ f (y \ g z)" by (metis le_infE modular_1 order_refl) lemma conjugation_prop2: "is_conjugation f g \ g z \ y \ g (z \ f y)" by (metis is_conjugation_sym conjugation_prop1) end (* boolean_algebra *) end diff --git a/thys/Relation_Algebra/Relation_Algebra_Models.thy b/thys/Relation_Algebra/Relation_Algebra_Models.thy --- a/thys/Relation_Algebra/Relation_Algebra_Models.thy +++ b/thys/Relation_Algebra/Relation_Algebra_Models.thy @@ -1,149 +1,149 @@ (* Title: Relation Algebra Author: Alasdair Armstrong, Simon Foster, Georg Struth, Tjark Weber Maintainer: Georg Struth Tjark Weber *) section \Models of Relation Algebra\ theory Relation_Algebra_Models imports Relation_Algebra Kleene_Algebra.Inf_Matrix begin text \We formalise two models. First we show the obvious: binary relations form a relation algebra. Then we show that infinite matrices (which we formalised originally for Kleene algebras) form models of relation algebra if we restrict their element type to @{typ bool}.\ subsection \Binary Relations\ text \Since Isabelle's libraries for binary relations are very well developed, the proof for this model is entirely trivial.\ interpretation rel_relation_algebra: relation_algebra "(-)" uminus "(\)" "(\)" "(\)" "(\)" "{}" UNIV "(O)" Relation.converse Id by unfold_locales auto subsection \Infinite Boolean Matrices\ text \Next we consider infinite Boolean matrices. We define the maximal Boolean matrix (all of its entries are @{const True}), the converse or transpose of a matrix, the intersection of two Boolean matrices and the complement of a Boolean matrix.\ definition mat_top :: "('a, 'b, bool) matrix" ("\") where "\ i j \ True" definition mat_transpose :: "('a, 'b, 'c) matrix \ ('b, 'a, 'c) matrix" ("_\<^sup>\" [101] 100) where "f\<^sup>\ \ (\i j. f j i)" definition mat_inter :: "('a, 'b, bool) matrix \ ('a, 'b, bool) matrix \ ('a, 'b, bool) matrix" (infixl "\" 70) where "f \ g \ (\i j. f i j \ g i j)" definition mat_complement :: "('a, 'b, bool) matrix \ ('a, 'b, bool) matrix" ("_\<^sup>c" [101] 100) where "f\<^sup>c = (\i j. - f i j)" text \Next we show that the Booleans form a dioid. We state this as an \emph{instantiation} result. The Kleene algebra files contain an \emph{interpretation} proof, which is not sufficient for our purposes.\ instantiation bool :: dioid_one_zero begin definition zero_bool_def: "zero_bool \ False" definition one_bool_def: "one_bool \ True" definition times_bool_def: "times_bool \ (\)" definition plus_bool_def: "plus_bool \ (\)" instance by standard (auto simp: plus_bool_def times_bool_def one_bool_def zero_bool_def) end text \We now show that infinite Boolean matrices form a Boolean algebra.\ lemma le_funI2: "(\i j. f i j \ g i j) \ f \ g" by (metis le_funI) -interpretation matrix_ba: boolean_algebra "\f g. f \ g\<^sup>c" mat_complement "(\)" "(\)" "(<)" mat_add mat_zero mat_top +interpretation matrix_ba: Lattices.boolean_algebra "\f g. f \ g\<^sup>c" mat_complement "(\)" "(\)" "(<)" mat_add mat_zero mat_top by standard (force intro!: le_funI simp: mat_inter_def plus_bool_def mat_add_def mat_zero_def zero_bool_def mat_top_def mat_complement_def)+ text \We continue working towards the main result of this section, that infinite Boolean matrices form a relation algebra.\ lemma mat_mult_var: "(f \ g) = (\i j. \ {(f i k) * (g k j) | k. k \ UNIV})" by (rule ext)+ (simp add: mat_mult_def) text \The following fact is related to proving the last relation algebra axiom in the matrix model. It is more complicated than necessary since finite infima are not well developed in Isabelle. Instead we translate properties of finite infima into properties of finite suprema by using Boolean algebra. For finite suprema we have developed special-purpose theorems in the Kleene algebra files.\ lemma mat_res_pointwise: fixes i j :: "'a::finite" and x :: "('a, 'a, bool) matrix" shows "(x\<^sup>\ \ (x \ y)\<^sup>c) i j \ (y\<^sup>c) i j" proof - have "\{(x\<^sup>\) i k \ ((x \ y)\<^sup>c) k j |k. k \ UNIV} \ (y\<^sup>c) i j \ (\k. ((x\<^sup>\) i k \ ((x \ y)\<^sup>c) k j) \ (y\<^sup>c) i j)" by (subst sum_sup) auto also have "\ \ (\k. ((x\<^sup>\) i k \ - (x \ y) k j) \ (y\<^sup>c) i j)" by (simp only: mat_complement_def) also have "\ \ (\k. (x\<^sup>\) i k \ ((y\<^sup>c) i j \ (x \ y) k j))" by auto also have "\ \ (\k. (x\<^sup>\) i k \ (- y i j \ (x \ y) k j))" by (simp only: mat_complement_def) also have "\ \ (\k. ((x\<^sup>\) i k \ y i j) \ (x \ y) k j)" by auto also have "\ \ (\k. (x k i \ y i j) \ (x \ y) k j)" by (simp add: mat_transpose_def) also have "\ \ (\k. (x k i \ y i j) \ \{x k l \ y l j |l. l \ UNIV})" by (simp add: mat_mult_def times_bool_def) also have "\ \ (\k. \{x k i \ y i j} \ \{x k l \ y l j |l. l \ UNIV})" by simp also have "\ \ True" by (intro iffI TrueI allI sum_intro[rule_format]) auto moreover have "(x\<^sup>\ \ (x \ y)\<^sup>c) i j = \{(x\<^sup>\) i k \ ((x \ y)\<^sup>c) k j |k. k \ UNIV}" by (subst mat_mult_def) (simp add: times_bool_def) ultimately show ?thesis by auto qed text \Finally the main result of this section.\ interpretation matrix_ra: relation_algebra "\f g. f \ g\<^sup>c" mat_complement "(\)" "(\)" "(<)" "(\)" "\i j. False" \ "(\)" mat_transpose \ proof fix x y z :: "'a::finite \ 'a \ bool" show "(\(i::'a) j::'a. False) \ x" by (metis predicate2I) show "x \ x\<^sup>c = (\i j. False)" by (metis matrix_ba.bot.extremum matrix_ba.inf_compl_bot rev_predicate2D) show "x \ x\<^sup>c = \" by (fact matrix_ba.sup_compl_top) show "x \ y\<^sup>c = x \ y\<^sup>c" by (fact refl) show "x \ y \ z = x \ (y \ z)" by (metis mat_mult_assoc) show "x \ \ = x" by (fact mat_oner) show "x \ y \ z = (x \ z) \ (y \ z)" by (fact mat_distr) show "(x\<^sup>\)\<^sup>\ = x" by (simp add: mat_transpose_def) show "(x \ y)\<^sup>\ = x\<^sup>\ \ y\<^sup>\" by (simp add: mat_transpose_def mat_add_def) show "(x \ y)\<^sup>\ = y\<^sup>\ \ x\<^sup>\" by (simp add: mat_transpose_def mat_mult_var times_bool_def conj_commute) show "x\<^sup>\ \ (x \ y)\<^sup>c \ y\<^sup>c" by (metis le_funI2 mat_res_pointwise) qed end diff --git a/thys/Residuated_Lattices/Residuated_Boolean_Algebras.thy b/thys/Residuated_Lattices/Residuated_Boolean_Algebras.thy --- a/thys/Residuated_Lattices/Residuated_Boolean_Algebras.thy +++ b/thys/Residuated_Lattices/Residuated_Boolean_Algebras.thy @@ -1,665 +1,665 @@ (* Title: Residuated Boolean Algebras Author: Victor Gomes Maintainer: Georg Struth *) section \Residuated Boolean Algebras\ theory Residuated_Boolean_Algebras imports Residuated_Lattices begin subsection \Conjugation on Boolean Algebras\ text \ Similarly, as in the previous section, we define the conjugation for arbitrary residuated functions on boolean algebras. \ -context boolean_algebra +context Lattices.boolean_algebra begin lemma inf_bot_iff_le: "x \ y = \ \ x \ -y" by (metis le_iff_inf inf_sup_distrib1 inf_top_right sup_bot.left_neutral sup_compl_top compl_inf_bot inf.assoc inf_bot_right) lemma le_iff_inf_bot: "x \ y \ x \ -y = \" by (metis inf_bot_iff_le compl_le_compl_iff inf_commute) lemma indirect_eq: "(\z. x \ z \ y \ z) \ x = y" by (metis order.eq_iff) text \ Let $B$ be a boolean algebra. The maps $f$ and $g$ on $B$ are a pair of conjugates if and only if for all $x, y \in B$, $f(x) \sqcap y = \bot \Leftrightarrow x \sqcap g(t) = \bot$. \ definition conjugation_pair :: "('a \ 'a) \ ('a \ 'a) \ bool" where "conjugation_pair f g \ \x y. f(x) \ y = \ \ x \ g(y) = \" lemma conjugation_pair_commute: "conjugation_pair f g \ conjugation_pair g f" by (auto simp: conjugation_pair_def inf_commute) lemma conjugate_iff_residuated: "conjugation_pair f g = residuated_pair f (\x. -g(-x))" apply (clarsimp simp: conjugation_pair_def residuated_pair_def inf_bot_iff_le) by (metis double_compl) lemma conjugate_residuated: "conjugation_pair f g \ residuated_pair f (\x. -g(-x))" by (metis conjugate_iff_residuated) lemma residuated_iff_conjugate: "residuated_pair f g = conjugation_pair f (\x. -g(-x))" apply (clarsimp simp: conjugation_pair_def residuated_pair_def inf_bot_iff_le) by (metis double_compl) text \ A map $f$ has a conjugate pair if and only if it is residuated. \ lemma conj_residuatedI1: "\g. conjugation_pair f g \ residuated f" by (metis conjugate_iff_residuated residuated_def) lemma conj_residuatedI2: "\g. conjugation_pair g f \ residuated f" by (metis conj_residuatedI1 conjugation_pair_commute) lemma exist_conjugateI[intro]: "residuated f \ \g. conjugation_pair f g" by (metis residuated_def residuated_iff_conjugate) lemma exist_conjugateI2[intro]: "residuated f \ \g. conjugation_pair g f" by (metis exist_conjugateI conjugation_pair_commute) text \ The conjugate of a residuated function $f$ is unique. \ lemma unique_conjugate[intro]: "residuated f \ \!g. conjugation_pair f g" proof - { fix g h x assume "conjugation_pair f g" and "conjugation_pair f h" hence "g = h" apply (unfold conjugation_pair_def) apply (rule ext) apply (rule order.antisym) by (metis le_iff_inf_bot inf_commute inf_compl_bot)+ } moreover assume "residuated f" ultimately show ?thesis by force qed lemma unique_conjugate2[intro]: "residuated f \ \!g. conjugation_pair g f" by (metis unique_conjugate conjugation_pair_commute) text \ Since the conjugate of a residuated map is unique, we define a conjugate operation. \ definition conjugate :: "('a \ 'a) \ ('a \ 'a)" where "conjugate f \ THE g. conjugation_pair g f" lemma conjugate_iff_def: "residuated f \ f(x) \ y = \ \ x \ conjugate f y = \" apply (clarsimp simp: conjugate_def dest!: unique_conjugate) apply (subgoal_tac "(THE g. conjugation_pair g f) = g") apply (clarsimp simp add: conjugation_pair_def) apply (rule the1_equality) by (auto intro: conjugation_pair_commute) lemma conjugateI1: "residuated f \ f(x) \ y = \ \ x \ conjugate f y = \" by (metis conjugate_iff_def) lemma conjugateI2: "residuated f \ x \ conjugate f y = \ \ f(x) \ y = \" by (metis conjugate_iff_def) text \ Few more lemmas about conjugation follow. \ lemma residuated_conj1: "residuated f \ conjugation_pair f (conjugate f)" using conjugateI1 conjugateI2 conjugation_pair_def by auto lemma residuated_conj2: "residuated f \ conjugation_pair (conjugate f) f" using conjugateI1 conjugateI2 conjugation_pair_def inf_commute by auto lemma conj_residuated: "residuated f \ residuated (conjugate f)" by (force dest!: residuated_conj2 intro: conj_residuatedI1) lemma conj_involution: "residuated f \ conjugate (conjugate f) = f" by (metis conj_residuated residuated_conj1 residuated_conj2 unique_conjugate) lemma residual_conj_eq: "residuated f \ residual (conjugate f) = (\x. -f(-x))" apply (unfold residual_def) apply (rule the1_equality) apply (rule residual_unique) apply (auto intro: conj_residuated conjugate_residuated residuated_conj2) done lemma residual_conj_eq_ext: "residuated f \ residual (conjugate f) x = -f(-x)" by (metis residual_conj_eq) lemma conj_iso: "residuated f \ x \ y \ conjugate f x \ conjugate f y" by (metis conj_residuated res_iso) lemma conjugate_strict: "residuated f \ conjugate f \ = \" by (metis conj_residuated residuated_strict) lemma conjugate_sup: "residuated f \ conjugate f (x \ y) = conjugate f x \ conjugate f y" by (metis conj_residuated residuated_sup) lemma conjugate_subinf: "residuated f \ conjugate f (x \ y) \ conjugate f x \ conjugate f y" by (auto simp: conj_iso) text \ Next we prove some lemmas from Maddux's article. Similar lemmas have been proved in AFP entry for relation algebras. They should be consolidated in the future. \ lemma maddux1: "residuated f \ f(x \ - conjugate f(y)) \ f(x) \ -y" proof - assume assm: "residuated f" hence "f(x \ - conjugate f(y)) \ f x" by (metis inf_le1 res_iso) moreover have "f(x \ - conjugate f (y)) \ y = \" by (metis assm conjugateI2 inf_bot_iff_le inf_le2) ultimately show ?thesis by (metis inf_bot_iff_le le_inf_iff) qed lemma maddux1': "residuated f \ conjugate f(x \ -f(y)) \ conjugate f(x) \ -y" by (metis conj_involution conj_residuated maddux1) lemma maddux2: "residuated f \ f(x) \ y \ f(x \ conjugate f y)" proof - assume resf: "residuated f" obtain z where z_def: "z = f(x \ conjugate f y)" by auto hence "f(x \ conjugate f y) \ -z = \" by (metis inf_compl_bot) hence "x \ conjugate f y \ conjugate f (-z) = \" by (metis conjugate_iff_def resf) hence "x \ conjugate f (y \ -z) = \" apply (subgoal_tac "conjugate f (y \ -z) \ conjugate f y \ conjugate f (-z)") apply (metis (no_types, opaque_lifting) dual_order.trans inf.commute inf_bot_iff_le inf_left_commute) by (metis conj_iso inf_le2 inf_top.left_neutral le_inf_iff resf) hence "f(x) \ y \ -z = \" by (metis conjugateI2 inf.assoc resf) thus ?thesis by (metis double_compl inf_bot_iff_le z_def) qed lemma maddux2': "residuated f \ conjugate f(x) \ y \ conjugate f(x \ f y)" by (metis conj_involution conj_residuated maddux2) lemma residuated_conjugate_ineq: "residuated f \ conjugate f x \ y \ x \ -f(-y)" by (metis conj_residuated residual_galois residual_conj_eq) lemma residuated_comp_closed: "residuated f \ residuated g \ residuated (f o g)" by (auto simp add: residuated_def residuated_pair_def) lemma conjugate_comp: "residuated f \ residuated g \ conjugate (f o g) = conjugate g o conjugate f" proof (rule ext, rule indirect_eq) fix x y assume assms: "residuated f" "residuated g" have "conjugate (f o g) x \ y \ x \ -f(g(-y))" apply (subst residuated_conjugate_ineq) using assms by (auto intro!: residuated_comp_closed) also have "... \ conjugate g (conjugate f x) \ y" using assms by (simp add: residuated_conjugate_ineq) finally show "(conjugate (f \ g) x \ y) = ((conjugate g \ conjugate f) x \ y)" by auto qed lemma conjugate_comp_ext: "residuated f \ residuated g \ conjugate (\x. f (g x)) x = conjugate g (conjugate f x)" using conjugate_comp by (simp add: comp_def) end (* boolean_algebra *) context complete_boolean_algebra begin text \ On a complete boolean algebra, it is possible to give an explicit definition of conjugation. \ lemma conjugate_eq: "residuated f \ conjugate f y = \{x. y \ -f(-x)}" proof - assume assm: "residuated f" obtain g where g_def: "g = conjugate f" by auto have "g y = \{x. x \ g y}" by (auto intro!: order.antisym Inf_lower Inf_greatest) also have "... = \{x. -x \ g y = \}" by (simp add: inf_bot_iff_le) also have "... = \{x. f(-x) \ y = \}" by (metis conjugate_iff_def assm g_def) finally show ?thesis by (simp add: g_def le_iff_inf_bot inf_commute) qed end (* complete_boolean_algebra *) subsection \Residuated Boolean Structures\ text \ In this section, we present various residuated structures based on boolean algebras. The left and right conjugation of the multiplicative operation is defined, and a number of facts is derived. \ class residuated_boolean_algebra = boolean_algebra + residuated_pogroupoid begin subclass residuated_lgroupoid .. definition conjugate_l :: "'a \ 'a \ 'a" (infixl "\" 60) where "x \ y \ -(-x \ y)" definition conjugate_r :: "'a \ 'a \ 'a" (infixl "\" 60) where "x \ y \ -(x \ -y)" lemma residual_conjugate_r: "x \ y = -(x \ -y)" by (metis conjugate_r_def double_compl) lemma residual_conjugate_l: "x \ y = -(-x \ y)" by (metis conjugate_l_def double_compl) lemma conjugation_multl: "x\y \ z = \ \ x \ (z \ y) = \" by (metis conjugate_l_def double_compl le_iff_inf_bot resl_galois) lemma conjugation_multr: "x\y \ z = \ \ y \ (x \ z) = \" by (metis conjugate_r_def inf_bot_iff_le le_iff_inf_bot resr_galois) lemma conjugation_conj: "(x \ y) \ z = \ \ y \ (z \ x) = \" by (metis inf_commute conjugation_multr conjugation_multl) lemma conjugation_pair_multl [simp]: "conjugation_pair (\x. x\y) (\x. x \ y)" by (simp add: conjugation_pair_def conjugation_multl) lemma conjugation_pair_multr [simp]: "conjugation_pair (\x. y\x) (\x. y \ x)" by (simp add: conjugation_pair_def conjugation_multr) lemma conjugation_pair_conj [simp]: "conjugation_pair (\x. y \ x) (\x. x \ y)" by (simp add: conjugation_pair_def conjugation_conj) lemma residuated_conjl1 [simp]: "residuated (\x. x \ y)" by (metis conj_residuatedI2 conjugation_pair_multl) lemma residuated_conjl2 [simp]: "residuated (\x. y \ x)" by (metis conj_residuatedI1 conjugation_pair_conj) lemma residuated_conjr1 [simp]: "residuated (\x. y \ x)" by (metis conj_residuatedI2 conjugation_pair_multr) lemma residuated_conjr2 [simp]: "residuated (\x. x \ y)" by (metis conj_residuatedI2 conjugation_pair_conj) lemma conjugate_multr [simp]: "conjugate (\x. y\x) = (\x. y \ x)" by (metis conjugation_pair_multr residuated_conj1 residuated_multr unique_conjugate) lemma conjugate_conjr1 [simp]: "conjugate (\x. y \ x) = (\x. y\x)" by (metis conjugate_multr conj_involution residuated_multr) lemma conjugate_multl [simp]: "conjugate (\x. x\y) = (\x. x \ y)" by (metis conjugation_pair_multl residuated_conj1 residuated_multl unique_conjugate) lemma conjugate_conjl1 [simp]: "conjugate (\x. x \ y) = (\x. x\y)" proof - have "conjugate (conjugate (\x. x\y)) = conjugate (\x. x \ y)" by simp thus ?thesis by (metis conj_involution[OF residuated_multl]) qed lemma conjugate_conjl2[simp]: "conjugate (\x. y \ x) = (\x. x \ y)" by (metis conjugation_pair_conj unique_conjugate residuated_conj1 residuated_conjl2) lemma conjugate_conjr2[simp]: "conjugate (\x. x \ y) = (\x. y \ x)" proof - have "conjugate (conjugate (\x. y \ x)) = conjugate (\x. x \ y)" by simp thus ?thesis by (metis conj_involution[OF residuated_conjl2]) qed lemma conjl1_iso: "x \ y \ x \ z \ y \ z" by (metis conjugate_l_def compl_mono resl_iso) lemma conjl2_iso: "x \ y \ z \ x \ z \ y" by (metis res_iso residuated_conjl2) lemma conjr1_iso: "x \ y \ z \ x \ z \ y" by (metis res_iso residuated_conjr1) lemma conjr2_iso: "x \ y \ x \ z \ y \ z" by (metis conjugate_r_def compl_mono resr_antitonel) lemma conjl1_sup: "z \ (x \ y) = (z \ x) \ (z \ y)" by (metis conjugate_l_def compl_inf resl_distr) lemma conjl2_sup: "(x \ y) \ z = (x \ z) \ (y \ z)" by (metis (poly_guards_query) residuated_sup residuated_conjl1) lemma conjr1_sup: "z \ (x \ y) = (z \ x) \ (z \ y)" by (metis residuated_sup residuated_conjr1) lemma conjr2_sup: "(x \ y) \ z = (x \ z) \ (y \ z)" by (metis conjugate_r_def compl_inf resr_distl) lemma conjl1_strict: "\ \ x = \" by (metis residuated_strict residuated_conjl1) lemma conjl2_strict: "x \ \ = \" by (metis residuated_strict residuated_conjl2) lemma conjr1_strict: "\ \ x = \" by (metis residuated_strict residuated_conjr2) lemma conjr2_strict: "x \ \ = \" by (metis residuated_strict residuated_conjr1) lemma conjl1_iff: "x \ y \ z \ x \ -(-z\y)" by (metis conjugate_l_def compl_le_swap1 compl_le_swap2 resl_galois) lemma conjl2_iff: "x \ y \ z \ y \ -(-z \ x)" by (metis conjl1_iff conjugate_r_def compl_le_swap2 double_compl resr_galois) lemma conjr1_iff: "x \ y \ z \ y \ -(x\-z)" by (metis conjugate_r_def compl_le_swap1 double_compl resr_galois) lemma conjr2_iff: "x \ y \ z \ x \ -(y \ -z)" by (metis conjugation_conj double_compl inf.commute le_iff_inf_bot) text \ We apply Maddux's lemmas regarding conjugation of an arbitrary residuated function for each of the 6 functions. \ lemma maddux1a: "a\(x \ -(a \ y)) \ a\x" by (insert maddux1 [of "\x. a\x"]) simp lemma maddux1a': "a\(x \ -(a \ y)) \ -y" by (insert maddux1 [of "\x. a\x"]) simp lemma maddux1b: "(x \ -(y \ a))\a \ x\a" by (insert maddux1 [of "\x. x\a"]) simp lemma maddux1b': "(x \ -(y \ a))\a \ -y" by (insert maddux1 [of "\x. x\a"]) simp lemma maddux1c: " a \ x \ -(y \ a) \ a \ x" by (insert maddux1 [of "\x. a \ x"]) simp lemma maddux1c': "a \ x \ -(y \ a) \ -y" by (insert maddux1 [of "\x. a \ x"]) simp lemma maddux1d: "a \ x \ -(a\y) \ a \ x" by (insert maddux1 [of "\x. a \ x"]) simp lemma maddux1d': "a \ x \ -(a\y) \ -y" by (insert maddux1 [of "\x. a \ x"]) simp lemma maddux1e: "x \ -(y\a) \ a \ x \ a" by (insert maddux1 [of "\x. x \ a"]) simp lemma maddux1e': "x \ -(y\a) \ a \ -y" by (insert maddux1 [of "\x. x \ a"]) simp lemma maddux1f: "x \ -(a \ y) \ a \ x \ a" by (insert maddux1 [of "\x. x \ a"]) simp lemma maddux1f': "x \ -(a \ y) \ a \ -y" by (insert maddux1 [of "\x. x \ a"]) simp lemma maddux2a: "a\x \ y \ a\(x \ (a \ y))" by (insert maddux2 [of "\x. a\x"]) simp lemma maddux2b: "x\a \ y \ (x \ (y \ a))\a" by (insert maddux2 [of "\x. x\a"]) simp lemma maddux2c: "(a \ x) \ y \ a \ (x \ (y \ a))" by (insert maddux2 [of "\x. a \ x"]) simp lemma maddux2d: "(a \ x) \ y \ a \ (x \ a\y)" by (insert maddux2 [of "\x. a \ x"]) simp lemma maddux2e: "(x \ a) \ y \ (x \ y\a) \ a" by (insert maddux2 [of "\x. x \ a"]) simp lemma maddux2f: "(x \ a) \ y \ (x \ (a \ y)) \ a" by (insert maddux2 [of "\x. x \ a"]) simp text \ The multiplicative operation $\cdot$ on a residuated boolean algebra is generally not associative. We prove some equivalences related to associativity. \ lemma res_assoc_iff1: "(\x y z. x\(y\z) = (x\y)\z) \ (\x y z. x \ (y \ z) = y\x \ z)" proof safe fix x y z assume "\x y z. x\(y\z) = (x\y)\z" thus "x \ (y \ z) = y \ x \ z" using conjugate_comp_ext[of "\z. y\z" "\z. x\z"] by auto next fix x y z assume "\x y z. x \ (y \ z) = y\x \ z" thus "x\(y\z) = (x\y)\z" using conjugate_comp_ext[of "\z. y \ z" "\z. x \ z"] by auto qed lemma res_assoc_iff2: "(\x y z. x\(y\z) = (x\y)\z) \ (\x y z. x \ (y \ z) = (x \ z) \ y)" proof safe fix x y z assume "\x y z. x\(y\z) = (x\y)\z" hence "\x y z. (x\y)\z = x\(y\z)" by simp thus "x \ (y \ z) = (x \ z) \ y" using conjugate_comp_ext[of "\x. x\z" "\x. x\y"] by auto next fix x y z assume "\x y z. x \ (y \ z) = (x \ z) \ y" hence "\x y z. (x \ z) \ y = x \ (y \ z)" by simp thus "x\(y\z) = (x\y)\z" using conjugate_comp_ext[of "\z. z \ y" "\x. x \ z"] by auto qed lemma res_assoc_iff3: "(\x y z. x\(y\z) = (x\y)\z) \ (\x y z. (x \ y) \ z = x \ (y \ z))" proof safe fix x y z assume "\x y z. x\(y\z) = (x\y)\z" thus "(x \ y) \ z = x \ (y \ z)" using conjugate_comp_ext[of "\u. x\u" "\u. u\z"] and conjugate_comp_ext[of "\u. u\z" "\u. x\u", symmetric] by auto next fix x y z assume "\x y z. (x \ y) \ z = x \ (y \ z)" thus "x\(y\z) = (x\y)\z" using conjugate_comp_ext[of "\u. x \ u" "\u. u \ z"] and conjugate_comp_ext[of "\u. u \ z" "\u. x \ u", symmetric] by auto qed end (* residuated_boolean_algebra *) class unital_residuated_boolean = residuated_boolean_algebra + one + assumes mult_onel [simp]: "x\1 = x" and mult_oner [simp]: "1\x = x" begin text \ The following equivalences are taken from J{\'o}sson and Tsinakis. \ lemma jonsson1a: "(\f. \x y. x \ y = f(x)\y) \ (\x y. x \ y = (x \ 1)\y)" apply standard apply force apply (rule_tac x="\x. x \ 1" in exI) apply force done lemma jonsson1b: "(\x y. x \ y = (x \ 1)\y) \ (\x y. x\y = (x \ 1) \ y)" proof safe fix x y assume "\x y. x \ y = (x \ 1)\y" hence "conjugate (\y. x \ y) = conjugate (\y. (x \ 1)\y)" by metis thus "x\y = (x \ 1) \ y" by simp next fix x y assume "\x y. x \ y = x \ 1 \ y" thus "x \ y = (x \ 1) \ y" by (metis mult_onel) qed lemma jonsson1c: "(\x y. x \ y = (x \ 1)\y) \ (\x y. y \ x = 1 \ (x \ y))" proof safe fix x y assume "\x y. x \ y = (x \ 1)\y" hence "(\x. x \ y) = (\x. (x \ 1)\y)" by metis hence "(\x. x \ y) = (\x. x\y) o (\x. x \ 1)" by force hence "conjugate (\x. y \ x) = (\x. x\y) o conjugate (\x. 1 \ x)" by simp hence "conjugate (conjugate (\x. y \ x)) = conjugate ((\x. x\y) o conjugate (\x. 1 \ x))" by simp hence "(\x. y \ x) = conjugate ((\x. x\y) o conjugate (\x. 1 \ x))" by simp also have "... = conjugate (conjugate (\x. 1 \ x)) o conjugate (\x. x\y)" by (subst conjugate_comp[symmetric]) simp_all finally show "y \ x = 1 \ (x \ y)" by simp next fix x y assume "\x y. y \ x = 1 \ (x \ y)" hence "(\x. y \ x) = (\x. 1 \ (x \ y))" by metis hence "(\x. y \ x) = (\x. 1 \ x) o conjugate (\x. x\y)" by force hence "conjugate (\x. y \ x) = conjugate ((\x. 1 \ x) o conjugate (\x. x\y))" by metis also have "... = conjugate (conjugate (\x. x\y)) o conjugate (\x. 1 \ x)" by (subst conjugate_comp[symmetric]) simp_all finally have "(\x. x \ y) = (\x. x\y) o (\x. x \ 1)" by simp hence "(\x. x \ y) = (\x. (x \ 1) \ y)" by (simp add: comp_def) thus "x \ y = (x \ 1) \ y" by metis qed lemma jonsson2a: "(\g. \x y. x \ y = x\g(y)) \ (\x y. x \ y = x\(1 \ y))" apply standard apply force apply (rule_tac x="\x. 1 \ x" in exI) apply force done lemma jonsson2b: "(\x y. x \ y = x\(1 \ y)) \ (\x y. x\y = x \ (1 \ y))" proof safe fix x y assume "\x y. x \ y = x\(1 \ y)" hence "conjugate (\x. x \ y) = conjugate (\x. x\(1 \ y))" by metis thus "x\y = x \ (1 \ y)" by simp metis next fix x y assume "\x y. x\y = x \ (1 \ y)" hence "(\x. x\y) = (\x. x \ (1 \ y))" by metis hence "conjugate (\x. x\y) = conjugate (\x. x \ (1 \ y))" by metis thus "x \ y = x \ (1 \ y)" by simp metis qed lemma jonsson2c: "(\x y. x \ y = x\(1 \ y)) \ (\x y. y \ x = (x \ y) \ 1)" proof safe fix x y assume "\x y. x \ y = x\(1 \ y)" hence "(\y. x \ y) = (\y. x\(1 \ y))" by metis hence "(\y. x \ y) = (\y. x\y) o (\y. 1 \ y)" by force hence "conjugate (\y. y \ x) = (\y. x\y) o conjugate (\y. y \ 1)" by force hence "conjugate (conjugate (\y. y \ x)) = conjugate ((\y. x\y) o conjugate (\y. y \ 1))" by metis hence "(\y. y \ x) = conjugate ((\y. x\y) o conjugate (\y. y \ 1))" by simp also have "... = conjugate (conjugate (\y. y \ 1)) o conjugate (\y. x\y)" by (subst conjugate_comp[symmetric]) simp_all finally have "(\y. y \ x) = (\y. x \ y \ 1)" by (simp add: comp_def) thus "y \ x = x \ y \ 1" by metis next fix x y assume "\x y. y \ x = x \ y \ 1" hence "(\y. y \ x) = (\y. x \ y \ 1)" by force hence "(\y. y \ x) = (\y. y \ 1) o conjugate (\y. x\y)" by force hence "conjugate (\y. y \ x) = conjugate ((\y. y \ 1) o conjugate (\y. x\y))" by metis also have "... = conjugate (conjugate (\y. x\y)) o conjugate (\y. y \ 1)" by (subst conjugate_comp[symmetric]) simp_all finally have "(\y. x \ y) = (\y. x\y) o (\y. 1 \ y)" by (metis conjugate_conjr1 conjugate_conjr2 conjugate_multr) thus "x \ y = x \ (1 \ y)" by (simp add: comp_def) qed lemma jonsson3a: "(\x. (x \ 1) \ 1 = x) \ (\x. 1 \ (1 \ x) = x)" proof safe fix x assume "\x. x \ 1 \ 1 = x" thus "1 \ (1 \ x) = x" by (metis compl_le_swap1 compl_le_swap2 conjr2_iff order.eq_iff) next fix x assume "\x. 1 \ (1 \ x) = x" thus "x \ 1 \ 1 = x" by (metis conjugate_l_def conjugate_r_def double_compl jipsen2r) qed lemma jonsson3b: "(\x. (x \ 1) \ 1 = x) \ (x \ y) \ 1 = (x \ 1) \ (y \ 1)" proof (rule order.antisym, auto simp: conjr2_iso) assume assm: "\x. (x \ 1) \ 1 = x" hence "(x \ 1) \ (y \ 1) \ 1 = x \ (((x \ 1) \ (y \ 1) \ 1) \ y)" by (metis (no_types) conjr2_iso inf.cobounded2 inf.commute inf.orderE) hence "(x \ 1) \ (y \ 1) \ 1 \ x \ y" using inf.orderI inf_left_commute by presburger thus "(x \ 1) \ (y \ 1) \ x \ y \ 1" using assm by (metis (no_types) conjr2_iso) qed lemma jonsson3c: "\x. (x \ 1) \ 1 = x \ x \ 1 = 1 \ x" proof (rule indirect_eq) fix z assume assms: "\x. (x \ 1) \ 1 = x" hence "(x \ 1) \ -z = \ \ ((x \ 1) \ -z) \ 1 = \" by (metis compl_sup conjugation_conj double_compl inf_bot_right sup_bot.left_neutral) also have "... \ -z\x \ 1 = \" by (metis assms jonsson3b conjugation_multr) finally have "(x \ 1) \ -z = \ \ (1 \ x) \ -z = \" by (metis conjugation_multl inf.commute) thus "(x \ 1 \ z) \ (1 \ x \ z)" by (metis le_iff_inf_bot) qed end (* unital_residuated_boolean *) class residuated_boolean_semigroup = residuated_boolean_algebra + semigroup_mult begin subclass residuated_boolean_algebra .. text \ The following lemmas hold trivially, since they are equivalent to associativity. \ lemma res_assoc1: "x \ (y \ z) = y\x \ z" by (metis res_assoc_iff1 mult_assoc) lemma res_assoc2: "x \ (y \ z) = (x \ z) \ y" by (metis res_assoc_iff2 mult_assoc) lemma res_assoc3: "(x \ y) \ z = x \ (y \ z)" by (metis res_assoc_iff3 mult_assoc) end (*residuated_boolean_semigroup *) class residuated_boolean_monoid = residuated_boolean_algebra + monoid_mult begin subclass unital_residuated_boolean by standard auto subclass residuated_lmonoid .. lemma jonsson4: "(\x y. x \ y = x\(1 \ y)) \ (\x y. x \ y = (x \ 1)\y)" proof safe fix x y assume assms: "\x y. x \ y = x\(1 \ y)" have "x \ y = (y \ x) \ 1" by (metis assms jonsson2c) also have "... = (y \ ((x \ 1) \ 1)) \ 1" by (metis assms jonsson2b jonsson3a mult_oner) also have "... = (((x \ 1)\y) \ 1) \ 1" by (metis conjugate_r_def double_compl resr3) also have "... = (x \ 1)\y" by (metis assms jonsson2b jonsson3a mult_oner) finally show "x \ y = (x \ 1)\y" . next fix x y assume assms: "\x y. x \ y = (x \ 1)\y" have "y \ x = 1 \ (x \ y)" by (metis assms jonsson1c) also have "... = 1 \ ((1 \ (1 \ x)) \ y)" by (metis assms conjugate_l_def double_compl jonsson1c mult_1_right resl3) also have "... = 1 \ (1 \ (y\(1 \ x)))" by (metis conjugate_l_def double_compl resl3) also have "... = y\(1 \ x)" by (metis assms jonsson1b jonsson1c jonsson3c mult_onel) finally show "y \ x = y\(1 \ x)". qed end (* residuated_boolean_monoid *) end diff --git a/thys/Residuated_Lattices/Residuated_Relation_Algebra.thy b/thys/Residuated_Lattices/Residuated_Relation_Algebra.thy --- a/thys/Residuated_Lattices/Residuated_Relation_Algebra.thy +++ b/thys/Residuated_Lattices/Residuated_Relation_Algebra.thy @@ -1,118 +1,118 @@ (* Title: Residuated Relation Algebras Author: Victor Gomes Maintainer: Georg Struth *) section \Residuated Relation Algebras\ theory Residuated_Relation_Algebra imports Residuated_Boolean_Algebras Relation_Algebra.Relation_Algebra begin -context boolean_algebra begin +context Lattices.boolean_algebra begin text \ The notation used in the relation algebra AFP entry differs a little from ours. \ notation times (infixl "\" 70) and plus (infixl "+" 65) and Groups.zero_class.zero ("0") and Groups.one_class.one ("1") no_notation inf (infixl "\" 70) and sup (infixl "+" 65) and bot ("0") and top ("1") end text \ We prove that a unital residuated boolean algebra enriched with two simple equalities form a non-associative relation algebra, that is, a relation algebra where the associativity law does not hold. \ class nra = unital_residuated_boolean + assumes conv1: "x \ y = (x \ 1)\y" and conv2: "x \ y = x\(1 \ y)" begin text \ When the converse operation is set to be $\lambda x.\ x \rhd 1$, a unital residuated boolean algebra forms a non associative relation algebra. \ lemma conv_invol: "x \ 1 \ 1 = x" by (metis local.conv1 local.jonsson1b local.mult_onel) lemma conv_add: "x \ y \ 1 = (x \ 1) \ (y \ 1)" by (metis local.conjr2_sup) lemma conv_contrav: "x\y \ 1 = (y \ 1)\(x \ 1)" by (metis local.conv1 local.conv2 local.jonsson1b local.jonsson2c) lemma conv_res: "(x \ 1)\- (x\y) \ - y" by (metis local.comp_anti local.conjugate_r_def local.conv1 local.double_compl local.res_rc1) text \ Similarly, for $x^\smile = 1 \lhd x$, since $x \rhd 1 = 1 \lhd x$ when $x \rhd 1 \rhd 1 = x$ holds. \ lemma conv_invol': "1 \ (1 \ x) = x" by (metis local.conv_invol local.jonsson3c) lemma conv_add': "1 \ (x \ y) = (1 \ x) \ (1 \ y)" by (metis local.conjl1_sup) lemma conv_contrav': "1 \ x\y = (1 \ y)\(1 \ x)" by (metis local.conv_contrav local.conv_invol local.jonsson3c) lemma conv_res': "(1 \ x)\- (x\y) \ - y" by (metis conv_res local.conv_invol local.jonsson3c) end (* nra *) text \ Since the previous axioms are equivalent when multiplication is associative in a residuated boolean monoid, one of them are sufficient to derive a relation algebra. \ class residuated_ra = residuated_boolean_monoid + assumes conv: "x \ y = (x \ 1)\y" begin subclass nra proof (standard, fact conv) fix x y show "x \ y = x\(1 \ y)" by (metis conv jonsson4) qed sublocale relation_algebra where composition = "(\)" and unit = 1 and converse = "\x. x \ 1" proof fix x y z show "x\y\z = x\(y\z)" by (metis local.mult_assoc) show "x\1 = x" by (metis local.mult_onel) show "(x \ y)\z = x\z \ y\z" by (metis local.distr) show "x \ 1 \ 1 = x" by (metis local.conv_invol) show "x \ y \ 1 = (x \ 1) \ (y \ 1)" by (metis local.conv_add) show "x\y \ 1 = (y \ 1)\(x \ 1)" by (metis local.conv_contrav) show "(x \ 1)\- (x\y) \ - y" by (metis local.conv_res) qed end (* residuated_ra *) end diff --git a/thys/Robbins-Conjecture/Robbins_Conjecture.thy b/thys/Robbins-Conjecture/Robbins_Conjecture.thy --- a/thys/Robbins-Conjecture/Robbins_Conjecture.thy +++ b/thys/Robbins-Conjecture/Robbins_Conjecture.thy @@ -1,985 +1,985 @@ section \Robbins Conjecture\ theory Robbins_Conjecture imports Main begin text \The document gives a formalization of the proof of the Robbins conjecture, following A. Mann, \emph{A Complete Proof of the Robbins Conjecture}, 2003, DOI 10.1.1.6.7838\ section \Axiom Systems\ text \The following presents several axiom systems that shall be under study. The first axiom sets common systems that underly all of the systems we shall be looking at. The second system is a reformulation of Boolean algebra. We shall follow pages 7--8 in S. Koppelberg. \emph{General Theory of Boolean Algebras}, Volume 1 of \emph{Handbook of Boolean Algebras}. North Holland, 1989. Note that our formulation deviates slightly from this, as we only provide one distribution axiom, as the dual is redundant. The third system is Huntington's algebra and the fourth system is Robbins' algebra. Apart from the common system, all of these systems are demonstrated to be equivalent to the library formulation of Boolean algebra, under appropriate interpretation.\ subsection \Common Algebras\ class common_algebra = uminus + fixes inf :: "'a \ 'a \ 'a" (infixl "\" 70) fixes sup :: "'a \ 'a \ 'a" (infixl "\" 65) fixes bot :: "'a" ("\") fixes top :: "'a" ("\") assumes sup_assoc: "x \ (y \ z) = (x \ y) \ z" assumes sup_comm: "x \ y = y \ x" context common_algebra begin definition less_eq :: "'a \ 'a \ bool" (infix "\" 50) where "x \ y = (x \ y = y)" definition less :: "'a \ 'a \ bool" (infix "\" 50) where "x \ y = (x \ y \ \ y \ x)" definition minus :: "'a \ 'a \ 'a" (infixl "-" 65) where "minus x y = (x \ - y)" (* We shall need some object in order to define falsum and verum *) definition secret_object1 :: "'a" ("\") where "\ = (SOME x. True)" end class ext_common_algebra = common_algebra + assumes inf_eq: "x \ y = -(- x \ - y)" assumes top_eq: "\ = \ \ - \" assumes bot_eq: "\ = -(\ \ - \)" subsection \Boolean Algebra\ class boolean_algebra_II = common_algebra + assumes inf_comm: "x \ y = y \ x" assumes inf_assoc: "x \ (y \ z) = (x \ y) \ z" assumes sup_absorb: "x \ (x \ y) = x" assumes inf_absorb: "x \ (x \ y) = x" assumes sup_inf_distrib1: "x \ y \ z = (x \ y) \ (x \ z)" assumes sup_compl: "x \ - x = \" assumes inf_compl: "x \ - x = \" subsection \Huntington's Algebra\ class huntington_algebra = ext_common_algebra + assumes huntington: "- (-x \ -y) \ - (-x \ y) = x" subsection \Robbins' Algebra\ class robbins_algebra = ext_common_algebra + assumes robbins: "- (- (x \ y) \ - (x \ -y)) = x" section \Equivalence\ text \With our axiom systems defined, we turn to providing equivalence results between them. We shall begin by illustrating equivalence for our formulation and the library formulation of Boolean algebra.\ subsection \Boolean Algebra\ text \The following provides the canonical definitions for order and relative complementation for Boolean algebras. These are necessary since the Boolean algebras presented in the Isabelle/HOL library have a lot of structure, while our formulation is considerably simpler. Since our formulation of Boolean algebras is considerably simple, it is easy to show that the library instantiates our axioms.\ context boolean_algebra_II begin lemma boolean_II_is_boolean: "class.boolean_algebra minus uminus (\) (\) (\) (\) \ \" apply unfold_locales apply (metis inf_absorb inf_assoc inf_comm inf_compl less_def less_eq_def minus_def sup_absorb sup_assoc sup_comm sup_compl sup_inf_distrib1 sup_absorb inf_comm)+ done end -context boolean_algebra begin +context Lattices.boolean_algebra begin lemma boolean_is_boolean_II: "class.boolean_algebra_II uminus inf sup bot top" apply unfold_locales apply (metis sup_assoc sup_commute sup_inf_absorb sup_compl_top inf_assoc inf_commute inf_sup_absorb inf_compl_bot sup_inf_distrib1)+ done end subsection \Huntington Algebra\ text \We shall illustrate here that all Boolean algebra using our formulation are Huntington algebras, and illustrate that every Huntington algebra may be interpreted as a Boolean algebra. Since the Isabelle/HOL library has good automation, it is convenient to first show that the library instances Huntington algebras to exploit previous results, and then use our previously derived correspondence.\ -context boolean_algebra begin +context Lattices.boolean_algebra begin lemma boolean_is_huntington: "class.huntington_algebra uminus inf sup bot top" apply unfold_locales apply (metis double_compl inf_sup_distrib1 inf_top_right compl_inf inf_commute inf_compl_bot compl_sup sup_commute sup_compl_top sup_compl_top sup_assoc)+ done end context boolean_algebra_II begin lemma boolean_II_is_huntington: "class.huntington_algebra uminus (\) (\) \ \" proof - interpret boolean: - boolean_algebra minus uminus "(\)" "(\)" "(\)" "(\)" \ \ + Lattices.boolean_algebra minus uminus "(\)" "(\)" "(\)" "(\)" \ \ by (fact boolean_II_is_boolean) show ?thesis by (simp add: boolean.boolean_is_huntington) qed end context huntington_algebra begin lemma huntington_id: "x \ -x = -x \ -(-x)" proof - from huntington have "x \ -x = -(-x \ -(-(-x))) \ -(-x \ -(-x)) \ (-(-(-x) \ -(-(-x))) \ -(-(-x) \ -(-x)))" by simp also from sup_comm have "\ = -(-(-x) \ -(-x)) \ -(-(-x) \ -(-(-x))) \ (-(-(-x) \ -x) \ -(-(-(-x)) \ -x))" by simp also from sup_assoc have "\ = -(-(-x) \ -(-x)) \ (-(-(-x) \ -(-(-x))) \ -(-(-x) \ -x)) \ -(-(-(-x)) \ -x)" by simp also from sup_comm have "\ = -(-(-x) \ -(-x)) \ (-(-(-x) \ -x) \ -(-(-x) \ -(-(-x)))) \ -(-(-(-x)) \ -x)" by simp also from sup_assoc have "\ = -(-(-x) \ -(-x)) \ -(-(-x) \ -x) \ (-(-(-x) \ -(-(-x))) \ -(-(-(-x)) \ -x))" by simp also from sup_comm have "\ = -(-(-x) \ -(-x)) \ -(-(-x) \ -x) \ (-(-(-(-x)) \ -(-x)) \ -(-(-(-x)) \ -x))" by simp also from huntington have "\ = -x \ -(-x)" by simp finally show ?thesis by simp qed lemma dbl_neg: "- (-x) = x" apply (metis huntington huntington_id sup_comm) done lemma towards_sup_compl: "x \ -x = y \ -y" proof - from huntington have "x \ -x = -(-x \ -(-y)) \ -(-x \ -y) \ (-(-(-x) \ -(-y)) \ -(-(-x) \ -y))" by simp also from sup_comm have "\ = -(-(-y) \ -x) \ -(-y \ -x) \ (-(-y \ -(-x)) \ -(-(-y) \ -(-x)))" by simp also from sup_assoc have "\ = -(-(-y) \ -x) \ (-(-y \ -x) \ -(-y \ -(-x))) \ -(-(-y) \ -(-x))" by simp also from sup_comm have "\ = -(-y \ -(-x)) \ -(-y \ -x) \ -(-(-y) \ -x) \ -(-(-y) \ -(-x))" by simp also from sup_assoc have "\ = -(-y \ -(-x)) \ -(-y \ -x) \ (-(-(-y) \ -x) \ -(-(-y) \ -(-x)))" by simp also from sup_comm have "\ = -(-y \ -(-x)) \ -(-y \ -x) \ (-(-(-y) \ -(-x)) \ -(-(-y) \ -x))" by simp also from huntington have "y \ -y = \" by simp finally show ?thesis by simp qed lemma sup_compl: "x \ -x = \" by (simp add: top_eq towards_sup_compl) lemma towards_inf_compl: "x \ -x = y \ -y" by (metis dbl_neg inf_eq sup_comm sup_compl) lemma inf_compl: "x \ -x = \" by (metis dbl_neg sup_comm bot_eq towards_inf_compl inf_eq) lemma towards_idem: "\ = \ \ \" by (metis dbl_neg huntington inf_compl inf_eq sup_assoc sup_comm sup_compl) lemma sup_ident: "x \ \ = x" by (metis dbl_neg huntington inf_compl inf_eq sup_assoc sup_comm sup_compl towards_idem) lemma inf_ident: "x \ \ = x" by (metis dbl_neg inf_compl inf_eq sup_ident sup_comm sup_compl) lemma sup_idem: "x \ x = x" by (metis dbl_neg huntington inf_compl inf_eq sup_ident sup_comm sup_compl) lemma inf_idem: "x \ x = x" by (metis dbl_neg inf_eq sup_idem) lemma sup_nil: "x \ \ = \" by (metis sup_idem sup_assoc sup_comm sup_compl) lemma inf_nil: "x \ \ = \" by (metis dbl_neg inf_compl inf_eq sup_nil sup_comm sup_compl) lemma sup_absorb: "x \ x \ y = x" by (metis huntington inf_eq sup_idem sup_assoc sup_comm) lemma inf_absorb: "x \ (x \ y) = x" by (metis dbl_neg inf_eq sup_absorb) lemma partition: "x \ y \ x \ -y = x" by (metis dbl_neg huntington inf_eq sup_comm) lemma demorgans1: "-(x \ y) = -x \ -y" by (metis dbl_neg inf_eq) lemma demorgans2: "-(x \ y) = -x \ -y" by (metis dbl_neg inf_eq) lemma inf_comm: "x \ y = y \ x" by (metis inf_eq sup_comm) lemma inf_assoc: "x \ (y \ z) = x \ y \ z" by (metis dbl_neg inf_eq sup_assoc) lemma inf_sup_distrib1: "x \ (y \ z) = (x \ y) \ (x \ z)" proof - from partition have "x \ (y \ z) = x \ (y \ z) \ y \ x \ (y \ z) \ -y" .. also from inf_assoc have "\ = x \ ((y \ z) \ y) \ x \ (y \ z) \ -y" by simp also from inf_comm have "\ = x \ (y \ (y \ z)) \ x \ (y \ z) \ -y" by simp also from inf_absorb have "\ = (x \ y) \ (x \ (y \ z) \ -y)" by simp also from partition have "\ = ((x \ y \ z) \ (x \ y \ -z)) \ ((x \ (y \ z) \ -y \ z) \ (x \ (y \ z) \ -y \ -z))" by simp also from inf_assoc have "\ = ((x \ y \ z) \ (x \ y \ -z)) \ ((x \ ((y \ z) \ (-y \ z))) \ (x \ ((y \ z) \ (-y \ -z))))" by simp also from demorgans2 have "\ = ((x \ y \ z) \ (x \ y \ -z)) \ ((x \ ((y \ z) \ (-y \ z))) \ (x \ ((y \ z) \ -(y \ z))))" by simp also from inf_compl have "\ = ((x \ y \ z) \ (x \ y \ -z)) \ ((x \ ((y \ z) \ (-y \ z))) \ (x \ \))" by simp also from inf_nil have "\ = ((x \ y \ z) \ (x \ y \ -z)) \ ((x \ ((y \ z) \ (-y \ z))) \ \)" by simp also from sup_idem have "\ = ((x \ y \ z) \ (x \ y \ z) \ (x \ y \ -z)) \ ((x \ ((y \ z) \ (-y \ z))) \ \)" by simp also from sup_ident have "\ = ((x \ y \ z) \ (x \ y \ z) \ (x \ y \ -z)) \ (x \ ((y \ z) \ (-y \ z)))" by simp also from inf_comm have "\ = ((x \ y \ z) \ (x \ y \ z) \ (x \ y \ -z)) \ (x \ ((-y \ z) \ (y \ z)))" by simp also from sup_comm have "\ = ((x \ y \ z) \ (x \ y \ z) \ (x \ y \ -z)) \ (x \ ((-y \ z) \ (z \ y)))" by simp also from inf_assoc have "\ = ((x \ y \ z) \ (x \ (y \ z)) \ (x \ y \ -z)) \ (x \ (-y \ (z \ (z \ y))))" by simp also from inf_absorb have "\ = ((x \ y \ z) \ (x \ (y \ z)) \ (x \ y \ -z)) \ (x \ (-y \ z))" by simp also from inf_comm have "\ = ((x \ y \ z) \ (x \ (z \ y)) \ (x \ y \ -z)) \ (x \ (z \ -y))" by simp also from sup_assoc have "\ = ((x \ y \ z) \ ((x \ (z \ y)) \ (x \ y \ -z))) \ (x \ (z \ -y))" by simp also from sup_comm have "\ = ((x \ y \ z) \ ((x \ y \ -z) \ (x \ (z \ y)))) \ (x \ (z \ -y))" by simp also from sup_assoc have "\ = ((x \ y \ z) \ (x \ y \ -z)) \ ((x \ (z \ y)) \ (x \ (z \ -y)))" by simp also from inf_assoc have "\ = ((x \ y \ z) \ (x \ y \ -z)) \ ((x \ z \ y) \ (x \ z \ -y))" by simp also from partition have "\ = (x \ y) \ (x \ z)" by simp finally show ?thesis by simp qed lemma sup_inf_distrib1: "x \ (y \ z) = (x \ y) \ (x \ z)" proof - from dbl_neg have "x \ (y \ z) = -(-(-(-x) \ (y \ z)))" by simp also from inf_eq have "\ = -(-x \ (-y \ -z))" by simp also from inf_sup_distrib1 have "\ = -((-x \ -y) \ (-x \ -z))" by simp also from demorgans2 have "\ = -(-x \ -y) \ -(-x \ -z)" by simp also from demorgans1 have "\ = (-(-x) \ -(-y)) \ (-(-x) \ -(-z))" by simp also from dbl_neg have "\ = (x \ y) \ (x \ z)" by simp finally show ?thesis by simp qed lemma huntington_is_boolean_II: "class.boolean_algebra_II uminus (\) (\) \ \" apply unfold_locales apply (metis inf_comm inf_assoc sup_absorb inf_absorb sup_inf_distrib1 sup_compl inf_compl)+ done lemma huntington_is_boolean: "class.boolean_algebra minus uminus (\) (\) (\) (\) \ \" proof - interpret boolean_II: boolean_algebra_II uminus "(\)" "(\)" \ \ by (fact huntington_is_boolean_II) show ?thesis by (simp add: boolean_II.boolean_II_is_boolean) qed end subsection \Robbins' Algebra\ -context boolean_algebra begin +context Lattices.boolean_algebra begin lemma boolean_is_robbins: "class.robbins_algebra uminus inf sup bot top" apply unfold_locales apply (metis sup_assoc sup_commute compl_inf double_compl sup_compl_top inf_compl_bot diff_eq sup_bot_right sup_inf_distrib1)+ done end context boolean_algebra_II begin lemma boolean_II_is_robbins: "class.robbins_algebra uminus inf sup bot top" proof - interpret boolean: - boolean_algebra minus uminus "(\)" "(\)" "(\)" "(\)" \ \ + Lattices.boolean_algebra minus uminus "(\)" "(\)" "(\)" "(\)" \ \ by (fact boolean_II_is_boolean) show ?thesis by (simp add: boolean.boolean_is_robbins) qed end context huntington_algebra begin lemma huntington_is_robbins: "class.robbins_algebra uminus inf sup bot top" proof - interpret boolean: - boolean_algebra minus uminus "(\)" "(\)" "(\)" "(\)" \ \ + Lattices.boolean_algebra minus uminus "(\)" "(\)" "(\)" "(\)" \ \ by (fact huntington_is_boolean) show ?thesis by (simp add: boolean.boolean_is_robbins) qed end text \Before diving into the proof that the Robbins algebra is Boolean, we shall present some shorthand machinery\ context common_algebra begin (* Iteration Machinery/Shorthand *) primrec copyp :: "nat \ 'a \ 'a" (infix "\" 80) where copyp_0: "0 \ x = x" | copyp_Suc: "(Suc k) \ x = (k \ x) \ x" no_notation Product_Type.Times (infixr "\" 80) primrec copy :: "nat \ 'a \ 'a" (infix "\" 85) where "0 \ x = x" | "(Suc k) \ x = k \ x" (* Theorems for translating shorthand into syntax *) lemma one: "1 \ x = x" proof - have "1 = Suc(0)" by arith hence "1 \ x = Suc(0) \ x" by metis also have "\ = x" by simp finally show ?thesis by simp qed lemma two: "2 \ x = x \ x" proof - have "2 = Suc(Suc(0))" by arith hence "2 \ x = Suc(Suc(0)) \ x" by metis also have "\ = x \ x" by simp finally show ?thesis by simp qed lemma three: "3 \ x = x \ x \ x" proof - have "3 = Suc(Suc(Suc(0)))" by arith hence "3 \ x = Suc(Suc(Suc(0))) \ x" by metis also have "\ = x \ x \ x" by simp finally show ?thesis by simp qed lemma four: "4 \ x = x \ x \ x \ x" proof - have "4 = Suc(Suc(Suc(Suc(0))))" by arith hence "4 \ x = Suc(Suc(Suc(Suc(0)))) \ x" by metis also have "\ = x \ x \ x \ x" by simp finally show ?thesis by simp qed lemma five: "5 \ x = x \ x \ x \ x \ x" proof - have "5 = Suc(Suc(Suc(Suc(Suc(0)))))" by arith hence "5 \ x = Suc(Suc(Suc(Suc(Suc(0))))) \ x" by metis also have "\ = x \ x \ x \ x \ x" by simp finally show ?thesis by simp qed lemma six: "6 \ x = x \ x \ x \ x \ x \ x" proof - have "6 = Suc(Suc(Suc(Suc(Suc(Suc(0))))))" by arith hence "6 \ x = Suc(Suc(Suc(Suc(Suc(Suc(0)))))) \ x" by metis also have "\ = x \ x \ x \ x \ x \ x" by simp finally show ?thesis by simp qed (* Distribution Laws *) lemma copyp_distrib: "k \ (x \ y) = (k \ x) \ (k \ y)" proof (induct k) case 0 show ?case by simp case Suc thus ?case by (simp, metis sup_assoc sup_comm) qed corollary copy_distrib: "k \ (x \ y) = (k \ x) \ (k \ y)" by (induct k, (simp add: sup_assoc sup_comm copyp_distrib)+) lemma copyp_arith: "(k + l + 1) \ x = (k \ x) \ (l \ x)" proof (induct l) case 0 have "k + 0 + 1 = Suc(k)" by arith thus ?case by simp case (Suc l) note ind_hyp = this have "k + Suc(l) + 1 = Suc(k + l + 1)" by arith+ hence "(k + Suc(l) + 1) \ x = (k + l + 1) \ x \ x" by (simp add: ind_hyp) also from ind_hyp have "\ = (k \ x) \ (l \ x) \ x" by simp also note sup_assoc finally show ?case by simp qed lemma copy_arith: assumes "k \ 0" and "l \ 0" shows "(k + l) \ x = (k \ x) \ (l \ x)" using assms proof - from assms have "\ k'. Suc(k') = k" and "\ l'. Suc(l') = l" by arith+ from this obtain k' l' where A: "Suc(k') = k" and B: "Suc(l') = l" by fast+ from this have A1: "k \ x = k' \ x" and B1: "l \ x = l' \ x" by fastforce+ from A B have "k + l = Suc(k' + l' + 1)" by arith hence "(k + l) \ x = (k' + l' + 1) \ x" by simp also from copyp_arith have "\ = k' \ x \ l' \ x" by fast also from A1 B1 have "\ = k \ x \ l \ x" by fastforce finally show ?thesis by simp qed end text \The theorem asserting all Robbins algebras are Boolean comes in 6 movements. First: The Winker identity is proved. Second: Idempotence for a particular object is proved. Note that falsum is defined in terms of this object. Third: An identity law for falsum is derived. Fourth: Idempotence for supremum is derived. Fifth: The double negation law is proven Sixth: Robbin's algebras are proven to be Huntington Algebras.\ context robbins_algebra begin definition secret_object2 :: "'a" ("\") where "\ = -(-(\ \ \ \ \) \ \)" definition secret_object3 :: "'a" ("\") where "\ = \ \ \" definition secret_object4 :: "'a" ("\") where "\ = \ \ (-(\ \ -\) \ -(\ \ -\))" definition secret_object5 :: "'a" ("\") where "\ = \ \ -(\ \ -\)" definition winker_object :: "'a" ("\") where "\ = \ \ \ \ \" definition fake_bot :: "'a" ("\\") where "\\ = -(\ \ -\)" (* Towards Winker's Identity *) (* These lemmas are due to Alan Mann *) lemma robbins2: "y = -(-(-x \ y) \ -(x \ y))" by (metis robbins sup_comm) lemma mann0: "-(x \ y) = -(-(-(x \ y) \ -x \ y) \ y)" by (metis robbins sup_comm sup_assoc) lemma mann1: "-(-x \ y) = -(-(-(-x \ y) \ x \ y) \ y)" by (metis robbins sup_comm sup_assoc) lemma mann2: "y = -(-(-(-x \ y) \ x \ y \ y) \ -(-x \ y))" by (metis mann1 robbins sup_comm sup_assoc) lemma mann3: "z = -(-(-(-(-x \ y) \ x \ y \ y) \ -(-x \ y) \ z) \ -(y \ z))" proof - let ?w = "-(-(-x \ y) \ x \ y \ y) \ -(-x \ y)" from robbins[where x="z" and y="?w"] sup_comm mann2 have "z = -(-(y \ z) \ -(?w \ z))" by metis thus ?thesis by (metis sup_comm) qed lemma mann4: "-(y \ z) = -(-(-(-(-x \ y) \ x \ y \ y) \ -(-x \ y) \ -(y \ z) \ z) \ z)" proof - from robbins2[where x="-(-(-x \ y) \ x \ y \ y) \ -(-x \ y) \ z" and y="-(y \ z)"] mann3[where x="x" and y="y" and z="z"] have "-(y \ z) = -(z \ -(-(-(-x \ y) \ x \ y \ y) \ -(-x \ y) \ z \ -(y \ z)))" by metis with sup_comm sup_assoc show ?thesis by metis qed lemma mann5: "u = -(-(-(-(-(-x \ y) \ x \ y \ y) \ -(-x \ y) \ - (y \ z) \ z) \ z \ u) \ -(-(y \ z) \ u))" using robbins2[where x="-(-(-(-x \ y) \ x \ y \ y) \ -(-x \ y) \ -(y \ z) \ z) \ z" and y="u"] mann4[where x=x and y=y and z=z] sup_comm by metis lemma mann6: "-(- 3\x \ x) = -(-(-(- 3\x \ x) \ - 3\x) \ -(-(- 3\x \ x) \ 5\x))" proof - have "3+2=(5::nat)" and "3\(0::nat)" and "2\(0::nat)" by arith+ with copy_arith have \: "3\x \ 2\x = 5\x" by metis let ?p = "-(- 3\x \ x)" { fix q from sup_comm have "-(q \ 5\x) = -(5\x \ q)" by metis also from \ mann0[where x="3\x" and y="q \ 2\x"] sup_assoc sup_comm have "\ = -(-(-(3\x \ (q \ 2\x)) \ - 3\x \ (q \ 2\x)) \ (q \ 2\x))" by metis also from sup_assoc have "\ = -(-(-((3\x \ q) \ 2\x) \ - 3\x \ (q \ 2\x)) \ (q \ 2\x))" by metis also from sup_comm have "\ = -(-(-((q \ 3\x) \ 2\x) \ - 3\x \ (q \ 2\x)) \ (q \ 2\x))" by metis also from sup_assoc have "\ = -(-(-(q \ (3\x \ 2\x)) \ - 3\x \ (q \ 2\x)) \ (q \ 2\x))" by metis also from \ have "\ = -(-(-(q \ 5\x) \ - 3\x \ (q \ 2\x)) \ (q \ 2\x))" by metis also from sup_assoc have "\ = -(-(-(q \ 5\x) \ (- 3\x \ q) \ 2\x) \ (q \ 2\x))" by metis also from sup_comm have "\ = -(-(-(q \ 5\x) \ (q \ - 3\x) \ 2\x) \ (2\x \ q))" by metis also from sup_assoc have "\ = -(-(-(q \ 5\x) \ q \ - 3\x \ 2\x) \ 2\x \ q)" by metis finally have "-(q \ 5\x) = -(-(-(q \ 5\x) \ q \ - 3\x \ 2\x) \ 2\x \ q)" by simp } hence \: "-(?p \ 5\x) = -(-(-(?p \ 5\x) \ ?p \ - 3\x \ 2\x) \ 2\x \ ?p)" by simp from mann5[where x="3\x" and y="x" and z="2\x" and u="?p"] sup_assoc three[where x=x] five[where x=x] have "?p = -(-(-(-(?p \ 5\x) \ ?p \ -(x \ 2\x) \ 2\x) \ 2\x \ ?p) \ -(-(x \ 2\x) \ ?p))" by metis also from sup_comm have "\ = -(-(-(-(?p \ 5\x) \ ?p \ -(2\x \ x) \ 2\x) \ 2\x \ ?p) \ -(-(2\x \ x) \ ?p))" by metis also from two[where x=x] three[where x=x] have "\ = -(-(-(-(?p \ 5\x) \ ?p \ - 3\x \ 2\x) \ 2\x \ ?p) \ -(- 3\x \ ?p))" by metis also from \ have "\ = -(-(?p \ 5\x) \ -(- 3\x \ ?p))" by simp also from sup_comm have "\ = -(-(?p \ 5\x) \ -(?p \ - 3\x))" by simp also from sup_comm have "\ = -(-(?p \ - 3\x) \ -(?p \ 5\x))" by simp finally show ?thesis . qed lemma mann7: "- 3\x = -(-(- 3\x \ x) \ 5\x)" proof - let ?p = "-(- 3\x \ x)" let ?q = "?p \ - 3\x" let ?r = "-(?p \ 5\x)" from robbins2[where x="?q" and y="?r"] mann6[where x=x] have "?r = - (?p \ - (?q \ ?r))" by simp also from sup_comm have "\ = - (- (?q \ ?r) \ ?p)" by simp also from sup_comm have "\ = - (- (?r \ ?q) \ ?p)" by simp finally have \: "?r = - (- (?r \ ?q) \ ?p)" . from mann3[where x="3\x" and y="x" and z="- 3\x"] sup_comm have "- 3\x = -(-(-(?p \ 3\x \ x \ x) \ ?p \ - 3\x) \ ?p)" by metis also from sup_assoc have "\ = -(-(-(?p \ (3\x \ x \ x)) \ ?q) \ ?p)" by metis also from three[where x=x] five[where x=x] have "\ = -(-(?r \ ?q) \ ?p)" by metis finally have "- 3\x = -(-(?r \ ?q) \ ?p)" by metis with \ show ?thesis by simp qed lemma mann8: "-(- 3\x \ x) \ 2\x = -(-(-(- 3\x \ x) \ - 3\x \ 2\x) \ - 3\x)" (is "?lhs = ?rhs") proof - let ?p = "-(- 3\x \ x)" let ?q = "?p \ 2\x" let ?r = "3\x" have "3+2=(5::nat)" and "3\(0::nat)" and "2\(0::nat)" by arith+ with copy_arith have \: "3\x \ 2\x = 5\x" by metis from robbins2[where x="?r" and y="?q"] and sup_assoc have "?q = -(-(- 3\x \ ?q) \ -(3\x \ ?p \ 2\x))" by metis also from sup_comm have "\ = -(-(?q \ - 3\x) \ -(?p \ 3\x \ 2\x))" by metis also from \ sup_assoc have "\ = -(-(?q \ - 3\x) \ -(?p \ 5\x))" by metis also from mann7[where x=x] have "\ = -(-(?q \ - 3\x) \ - 3\x)" by metis also from sup_assoc have "\ = -(-(?p \ (2\x \ - 3\x)) \ - 3\x)" by metis also from sup_comm have "\ = -(-(?p \ (- 3\x \ 2\x)) \ - 3\x)" by metis also from sup_assoc have "\ = ?rhs" by metis finally show ?thesis by simp qed lemma mann9: "x = -(-(- 3\x \ x) \ - 3\x )" proof - let ?p = "-(- 3\x \ x)" let ?q = "?p \ 4\x" have "4+1=(5::nat)" and "1\(0::nat)" and "4\(0::nat)" by arith+ with copy_arith one have \: "4\x \ x = 5\x" by metis with sup_assoc robbins2[where y=x and x="?q"] have "x = -(-(-?q \ x) \ -(?p \ 5\x))" by metis with mann7 have "x = -(-(-?q \ x) \ - 3\x)" by metis moreover have "3+1=(4::nat)" and "1\(0::nat)" and "3\(0::nat)" by arith+ with copy_arith one have \: "3\x \ x = 4\x" by metis with mann1[where x="3\x" and y="x"] sup_assoc have "-(-?q \ x) = ?p" by metis ultimately show ?thesis by simp qed lemma mann10: "y = -(-(-(- 3\x \ x) \ - 3\x \ y) \ -(x \ y))" using robbins2[where x="-(- 3\x \ x) \ - 3\x" and y=y] mann9[where x=x] sup_comm by metis theorem mann: "2\x = -(- 3\x \ x) \ 2\x" using mann10[where x=x and y="2\x"] mann8[where x=x] two[where x=x] three[where x=x] sup_comm by metis corollary winkerr: "\ \ \ = \" using mann secret_object2_def secret_object3_def two three by metis corollary winker: "\ \ \ = \" by (metis winkerr sup_comm) corollary multi_winkerp: "\ \ k \ \ = \" by (induct k, (simp add: winker sup_comm sup_assoc)+) corollary multi_winker: "\ \ k \ \ = \" by (induct k, (simp add: multi_winkerp winker sup_comm sup_assoc)+) (* Towards Idempotence *) lemma less_eq_introp: "-(x \ -(y \ z)) = -(x \ y \ -z) \ y \ x" by (metis robbins sup_assoc less_eq_def sup_comm[where x=x and y=y]) corollary less_eq_intro: "-(x \ -(y \ z)) = -(x \ y \ -z) \ x \ y = x" by (metis less_eq_introp less_eq_def sup_comm) lemma eq_intro: "-(x \ -(y \ z)) = -(y \ -(x \ z)) \ x = y" by (metis robbins sup_assoc sup_comm) lemma copyp0: assumes "-(x \ -y) = z" shows "-(x \ -(y \ k \ (x \ z))) = z" using assms proof (induct k) case 0 show ?case by (simp, metis assms robbins sup_assoc sup_comm) case Suc note ind_hyp = this show ?case by (simp, metis ind_hyp robbins sup_assoc sup_comm) qed lemma copyp1: assumes "-(-(x \ -y) \ -y) = x" shows "-(y \ k \ (x \ -(x \ -y))) = -y" using assms proof - let ?z = "-(x \ - y)" let ?ky = "y \ k \ (x \ ?z)" have "-(x \ -?ky) = ?z" by (simp add: copyp0) hence "-(-?ky \ -(-y \ ?z)) = ?z" by (metis assms sup_comm) also have "-(?z \ -?ky) = x" by (metis assms copyp0 sup_comm) hence "?z = -(-y \ -(-?ky \ ?z))" by (metis sup_comm) finally show ?thesis by (metis eq_intro) qed corollary copyp2: assumes "-(x \ y) = -y" shows "-(y \ k \ (x \ -(x \ -y))) = -y" by (metis assms robbins sup_comm copyp1) lemma two_threep: assumes "-(2 \ x \ y) = -y" and "-(3 \ x \ y) = -y" shows "2 \ x \ y = 3 \ x \ y" using assms proof - from assms two three have A: "-(x \ x \ y) = -y" and B: "-(x \ x \ x \ y) = -y" by simp+ with sup_assoc copyp2[where x="x" and y="x \ x \ y" and k="0"] have "-(x \ x \ y \ x \ -(x \ -y)) = -y" by simp moreover from sup_comm sup_assoc A B copyp2[where x="x \ x" and y="y" and k="0"] have "-(y \ x \ x \ -(x \ x \ -y)) = -y" by fastforce with sup_comm sup_assoc have "-(x \ x \ y \ -(x \ (x \ -y))) = -y" by metis ultimately have "-(x \ x \ y \ -(x \ (x \ -y))) = -(x \ x \ y \ x \ -(x \ -y))" by simp with less_eq_intro have "x \ x \ y = x \ x \ y \ x" by metis with sup_comm sup_assoc two three show ?thesis by metis qed lemma two_three: assumes "-(x \ y) = -y \ -(-(x \ -y) \ -y) = x" shows "y \ 2 \ (x \ -(x \ -y)) = y \ 3 \ (x \ -(x \ -y))" (is "y \ ?z2 = y \ ?z3") using assms proof assume "-(x \ y) = -y" with copyp2[where k="Suc(0)"] copyp2[where k="Suc(Suc(0))"] two three have "-(y \ ?z2) = -y" and "-(y \ ?z3) = -y" by simp+ with two_threep sup_comm show ?thesis by metis next assume "-(-(x \ -y) \ -y) = x" with copyp1[where k="Suc(0)"] copyp1[where k="Suc(Suc(0))"] two three have "-(y \ ?z2) = -y" and "-(y \ ?z3) = -y" by simp+ with two_threep sup_comm show ?thesis by metis qed lemma sup_idem: "\ \ \ = \" proof - from winkerr two copyp2[where x="\" and y="\" and k="Suc(0)"] have "-\ = -(\ \ 2 \ (\ \ -(\ \ -\)))" by simp also from copy_distrib sup_assoc have "\ = -(\ \ 2 \ \ \ 2 \ (-(\ \ -\)))" by simp also from sup_assoc secret_object4_def two multi_winker[where k="2"] have "\ = -\" by metis finally have "-\ = -\" by simp with secret_object4_def sup_assoc three have "\ \ -(\ \ -\) = \ \ 3 \ (-(\ \ -\))" by simp also from copy_distrib[where k="3"] multi_winker[where k="3"] sup_assoc have "\ = \ \ 3 \ (\ \ -(\ \ -\))" by metis also from winker sup_comm two_three[where x="\" and y="\"] have "\ = \ \ 2 \ (\ \ -(\ \ -\))" by fastforce also from copy_distrib[where k="2"] multi_winker[where k="2"] sup_assoc two secret_object4_def have "\ = \" by metis finally have \: "\ \ -(\ \ -\) = \" by simp from secret_object4_def winkerr sup_assoc have "\ \ \ = \" by metis hence "\ \ \ = \" by (metis sup_comm) hence "-(-(\ \ -\) \ -\) = -(-(\ \ (\ \ -\)) \ -\)" by (metis sup_assoc) also from \ have "\ = -(-(\ \ (\ \ -\)) \ -(\ \ -(\ \ -\)))" by metis also from robbins have "\ = \" by metis finally have "-(-(\ \ -\) \ -\) = \" by simp with two_three[where x="\" and y="\"] secret_object5_def sup_comm have "3 \ \ \ \ = 2 \ \ \ \" by fastforce with secret_object5_def sup_assoc sup_comm have "3 \ \ \ \ = 2 \ \ \ \" by fastforce with two three four five six have "6 \ \ = 3 \ \" by simp moreover have "3 + 3 = (6::nat)" and "3 \ (0::nat)" by arith+ moreover note copy_arith[where k="3" and l="3" and x="\"] winker_object_def three ultimately show ?thesis by simp qed (* Idempotence implies the identity law *) lemma sup_ident: "x \ \\ = x" proof - have I: "\ = -(-\ \ \\)" by (metis fake_bot_def inf_eq robbins sup_comm sup_idem) { fix x have "x = -(-(x \ -\ \ \\) \ -(x \ \))" by (metis I robbins sup_assoc) } note II = this have III: "-\ = -(-(\ \ -\ \ -\) \ \)" by (metis robbins[where x="-\" and y="\ \ -\"] I sup_comm fake_bot_def) hence "\ = -(-(\ \ -\ \ -\) \ -\)" by (metis robbins[where x="\" and y="\ \ -\ \ -\"] sup_comm[where x="\" and y="-(\ \ -\ \ -\)"] sup_assoc sup_idem) hence "-(\ \ -\ \ -\) = \\" by (metis robbins[where x="-(\ \ -\ \ -\)" and y="\"] III sup_comm fake_bot_def) hence "-\ = -(\ \ \\)" by (metis III sup_comm) hence "\ = -(-(\ \ \\) \ -(\ \ \\ \ -\))" by (metis II sup_idem sup_comm sup_assoc) moreover have "\ \ \\ = -(-(\ \ \\) \ -(\ \ \\ \ -\))" by (metis robbins[where x="\ \ \\" and y="\"] sup_comm[where y="\"] sup_assoc sup_idem) ultimately have "\ = \ \ \\" by auto hence "x \ \\ = -(-(x \ \) \ -(x \ \\ \ -\))" by (metis robbins[where x="x \ \\" and y=\] sup_comm[where x="\\" and y=\] sup_assoc) thus ?thesis by (metis sup_assoc sup_comm II) qed (* The identity law implies double negation *) lemma dbl_neg: "- (-x) = x" proof - { fix x have "\\ = -(-x \ -(-x))" by (metis robbins sup_comm sup_ident) } note I = this { fix x have "-x = -(-(-x \ -(-(-x))))" by (metis I robbins sup_comm sup_ident) } note II = this { fix x have "-(-(-x)) = -(-(-x \ -(-(-x))))" by (metis I II robbins sup_assoc sup_comm sup_ident) } note III = this show ?thesis by (metis II III robbins) qed (* Double negation implies Huntington's axiom, hence Boolean*) theorem robbins_is_huntington: "class.huntington_algebra uminus (\) (\) \ \" apply unfold_locales apply (metis dbl_neg robbins sup_comm) done theorem robbins_is_boolean_II: "class.boolean_algebra_II uminus (\) (\) \ \" proof - interpret huntington: huntington_algebra uminus "(\)" "(\)" \ \ by (fact robbins_is_huntington) show ?thesis by (simp add: huntington.huntington_is_boolean_II) qed theorem robbins_is_boolean: "class.boolean_algebra minus uminus (\) (\) (\) (\) \ \" proof - interpret huntington: huntington_algebra uminus "(\)" "(\)" \ \ by (fact robbins_is_huntington) show ?thesis by (simp add: huntington.huntington_is_boolean) qed end no_notation secret_object1 ("\") and secret_object2 ("\") and secret_object3 ("\") and secret_object4 ("\") and secret_object5 ("\") and winker_object ("\") and less_eq (infix "\" 50) and less (infix "\" 50) and inf (infixl "\" 70) and sup (infixl "\" 65) and top ("\") and bot ("\") and copyp (infix "\" 80) and copy (infix "\" 85) notation Product_Type.Times (infixr "\" 80) end diff --git a/thys/Statecharts/Expr.thy b/thys/Statecharts/Expr.thy --- a/thys/Statecharts/Expr.thy +++ b/thys/Statecharts/Expr.thy @@ -1,229 +1,231 @@ (* Title: statecharts/SA/Expr.thy Author: Steffen Helke, Software Engineering Group Copyright 2010 Technische Universitaet Berlin *) section \Label Expressions\ theory Expr imports Update begin +no_notation not ("NOT") + datatype ('s,'e)expr = true | In 's | En 'e | NOT "('s,'e)expr" | And "('s,'e)expr" "('s,'e)expr" | Or "('s,'e)expr" "('s,'e)expr" type_synonym 'd guard = "('d data) => bool" type_synonym ('e,'d)action = "('e set * 'd pupdate)" type_synonym ('s,'e,'d)label = "(('s,'e)expr * 'd guard * ('e,'d)action)" type_synonym ('s,'e,'d)trans = "('s * ('s,'e,'d)label * 's)" primrec eval_expr :: "[('s set * 'e set), ('s,'e)expr] \ bool" where "eval_expr sc true = True" | "eval_expr sc (En ev) = (ev \ snd sc)" | "eval_expr sc (In st) = (st \ fst sc)" | "eval_expr sc (NOT e1) = (\ (eval_expr sc e1))" | "eval_expr sc (And e1 e2) = ((eval_expr sc e1) \ (eval_expr sc e2))" | "eval_expr sc (Or e1 e2) = ((eval_expr sc e1) \ (eval_expr sc e2))" primrec ExprEvents :: "('s,'e)expr \ 'e set" where "ExprEvents true = {}" | "ExprEvents (En ev) = {ev}" | "ExprEvents (In st) = {}" | "ExprEvents (NOT e) = (ExprEvents e)" | "ExprEvents (And e1 e2) = ((ExprEvents e1) \ (ExprEvents e2))" | "ExprEvents (Or e1 e2) = ((ExprEvents e1) \ (ExprEvents e2))" (* atomar propositions for Sequential Automata, will be necessary for CTL-interpretation *) datatype ('s, 'e, dead 'd)atomar = TRUE | FALSE | IN 's | EN 'e | VAL "'d data => bool" definition source :: "('s,'e,'d)trans => 's" where "source t = fst t" definition Source :: "('s,'e,'d)trans set => 's set" where "Source T == source ` T" definition target :: "('s,'e,'d)trans => 's" where "target t = snd(snd t)" definition Target :: "('s,'e,'d)trans set => 's set" where "Target T = target ` T" definition label :: "('s,'e,'d)trans => ('s,'e,'d)label" where "label t = fst (snd t)" definition Label :: "('s,'e,'d)trans set => ('s,'e,'d)label set" where "Label T = label ` T" definition expr :: "('s,'e,'d)label => ('s,'e)expr" where "expr = fst" definition action :: "('s,'e,'d)label => ('e,'d)action" where "action = snd o snd" definition Action :: "('s,'e,'d)label set => ('e,'d)action set" where "Action L = action ` L" definition pupdate :: "('s,'e,'d)label => 'd pupdate" where "pupdate = snd o action" definition PUpdate :: "('s,'e,'d)label set => ('d pupdate) set" where "PUpdate L = pupdate ` L" definition actevent :: "('s,'e,'d)label => 'e set" where "actevent = fst o action" definition Actevent :: "('s,'e,'d)label set => ('e set) set" where "Actevent L = actevent ` L" definition guard :: "('s,'e,'d)label => 'd guard" where "guard = fst o snd" definition Guard :: "('s,'e,'d)label set => ('d guard) set" where "Guard L = guard ` L" definition defaultexpr :: "('s,'e)expr" where "defaultexpr = true" definition defaultaction :: "('e,'d)action" where "defaultaction = ({},DefaultPUpdate)" definition defaultguard :: "('d guard)" where "defaultguard = (\ d. True)" definition defaultlabel :: "('s,'e,'d)label" where "defaultlabel = (defaultexpr, defaultguard, defaultaction)" definition eval :: "[('s set * 'e set * 'd data), ('s,'e,'d)label] => bool" ("_ |= _" [91,90]90) where "eval scd l = (let (s,e,d) = scd in ((eval_expr (s,e) (expr l)) \ ((guard l) d)))" lemma Source_EmptySet [simp]: "Source {} = {}" by (unfold Source_def, auto) lemma Target_EmptySet [simp]: "Target {} = {}" by (unfold Target_def, auto) lemma Label_EmptySet [simp]: "Label {} = {}" by (unfold Label_def, auto) lemma Action_EmptySet [simp]: "Action {} = {}" by (unfold Action_def, auto) lemma PUpdate_EmptySet [simp]: "PUpdate {} = {}" by (unfold PUpdate_def, auto) lemma Actevent_EmptySet [simp]: "Actevent {} = {}" by (unfold Actevent_def, auto) lemma Union_Actevent_subset: "\ m \ M; ((\ (Actevent (Label (Union M)))) \ (N::'a set)) \ \ ((\ (Actevent (Label m))) \ N)" by (unfold Actevent_def Label_def, auto) lemma action_select [simp]: "action (a,b,c) = c" by (unfold action_def, auto) lemma label_select [simp]: "label (a,b,c) = b" by (unfold label_def, auto) lemma target_select [simp]: "target (a,b,c) = c" by (unfold target_def, auto) lemma actevent_select [simp]: "actevent (a,b,(c,d)) = c" by (unfold actevent_def, auto) lemma pupdate_select [simp]: "pupdate (a,b,c,d) = d" by (unfold pupdate_def, auto) lemma source_select [simp]: "source (a,b) = a" by (unfold source_def, auto) lemma finite_PUpdate [simp]: "finite S \ finite(PUpdate S)" by (unfold PUpdate_def, auto) lemma finite_Label [simp]: "finite S \ finite(Label S)" by (unfold Label_def, auto) lemma fst_defaultaction [simp]: "fst defaultaction = {}" by (unfold defaultaction_def, auto) lemma action_defaultlabel [simp]: "(action defaultlabel) = defaultaction" by (unfold defaultlabel_def action_def, auto) lemma fst_defaultlabel [simp]: "(fst defaultlabel) = defaultexpr" by (unfold defaultlabel_def, auto) lemma ExprEvents_defaultexpr [simp]: "(ExprEvents defaultexpr) = {}" by (unfold defaultexpr_def, auto) lemma defaultlabel_defaultexpr [simp]: "expr defaultlabel = defaultexpr" by (unfold defaultlabel_def expr_def, auto) lemma target_Target [simp]: "t \ T \ target t \ Target T" by (unfold Target_def, auto) lemma Source_union : "Source s \ Source t = Source (s \ t)" apply (unfold Source_def) apply auto done lemma Target_union : "Target s \ Target t = Target (s \ t)" apply (unfold Target_def) apply auto done end diff --git a/thys/Stone_Algebras/Lattice_Basics.thy b/thys/Stone_Algebras/Lattice_Basics.thy --- a/thys/Stone_Algebras/Lattice_Basics.thy +++ b/thys/Stone_Algebras/Lattice_Basics.thy @@ -1,561 +1,561 @@ (* Title: Lattice Basics Author: Walter Guttmann Maintainer: Walter Guttmann *) section \Lattice Basics\ text \ This theory provides notations, basic definitions and facts of lattice-related structures used throughout the subsequent development. \ theory Lattice_Basics imports Main begin subsection \General Facts and Notations\ text \ The following results extend basic Isabelle/HOL facts. \ lemma imp_as_conj: assumes "P x \ Q x" shows "P x \ Q x \ P x" using assms by auto lemma if_distrib_2: "f (if c then x else y) (if c then z else w) = (if c then f x z else f y w)" by simp lemma left_invertible_inj: "(\x . g (f x) = x) \ inj f" by (metis injI) lemma invertible_bij: assumes "\x . g (f x) = x" and "\y . f (g y) = y" shows "bij f" by (metis assms bijI') lemma finite_ne_subset_induct [consumes 3, case_names singleton insert]: assumes "finite F" and "F \ {}" and "F \ S" and singleton: "\x . P {x}" and insert: "\x F . finite F \ F \ {} \ F \ S \ x \ S \ x \ F \ P F \ P (insert x F)" shows "P F" using assms(1-3) apply (induct rule: finite_ne_induct) apply (simp add: singleton) by (simp add: insert) lemma finite_set_of_finite_funs_pred: assumes "finite { x::'a . True }" and "finite { y::'b . P y }" shows "finite { f . (\x::'a . P (f x)) }" using assms finite_set_of_finite_funs by force text \ We use the following notations for the join, meet and complement operations. Changing the precedence of the unary complement allows us to write terms like \--x\ instead of \-(-x)\. \ context sup begin notation sup (infixl "\" 65) definition additive :: "('a \ 'a) \ bool" where "additive f \ \x y . f (x \ y) = f x \ f y" end context inf begin notation inf (infixl "\" 67) end context uminus begin no_notation uminus ("- _" [81] 80) notation uminus ("- _" [80] 80) end subsection \Orders\ text \ We use the following definition of monotonicity for operations defined in classes. The standard \mono\ places a sort constraint on the target type. We also give basic properties of Galois connections and lift orders to functions. \ context ord begin definition isotone :: "('a \ 'a) \ bool" where "isotone f \ \x y . x \ y \ f x \ f y" definition galois :: "('a \ 'a) \ ('a \ 'a) \ bool" where "galois l u \ \x y . l x \ y \ x \ u y" definition lifted_less_eq :: "('a \ 'a) \ ('a \ 'a) \ bool" ("(_ \\ _)" [51, 51] 50) where "f \\ g \ \x . f x \ g x" end context order begin lemma order_lesseq_imp: "(\z . x \ z \ y \ z) \ y \ x" using order_trans by blast lemma galois_char: "galois l u \ (\x . x \ u (l x)) \ (\x . l (u x) \ x) \ isotone l \ isotone u" apply (rule iffI) apply (metis (full_types) galois_def isotone_def order_refl order_trans) using galois_def isotone_def order_trans by blast lemma galois_closure: "galois l u \ l x = l (u (l x)) \ u x = u (l (u x))" by (simp add: galois_char isotone_def order.antisym) lemma lifted_reflexive: "f = g \ f \\ g" by (simp add: lifted_less_eq_def) lemma lifted_transitive: "f \\ g \ g \\ h \ f \\ h" using lifted_less_eq_def order_trans by blast lemma lifted_antisymmetric: "f \\ g \ g \\ f \ f = g" by (rule ext, rule order.antisym) (simp_all add: lifted_less_eq_def) text \ If the image of a finite non-empty set under \f\ is a totally ordered, there is an element that minimises the value of \f\. \ lemma finite_set_minimal: assumes "finite s" and "s \ {}" and "\x\s . \y\s . f x \ f y \ f y \ f x" shows "\m\s . \z\s . f m \ f z" apply (rule finite_ne_subset_induct[where S=s]) apply (rule assms(1)) apply (rule assms(2)) apply simp apply simp by (metis assms(3) insert_iff order_trans subsetD) end subsection \Semilattices\ text \ The following are basic facts in semilattices. \ context semilattice_sup begin lemma sup_left_isotone: "x \ y \ x \ z \ y \ z" using sup.mono by blast lemma sup_right_isotone: "x \ y \ z \ x \ z \ y" using sup.mono by blast lemma sup_left_divisibility: "x \ y \ (\z . x \ z = y)" using sup.absorb2 sup.cobounded1 by blast lemma sup_right_divisibility: "x \ y \ (\z . z \ x = y)" by (metis sup.cobounded2 sup.orderE) lemma sup_same_context: "x \ y \ z \ y \ x \ z \ x \ z = y \ z" by (simp add: le_iff_sup sup_left_commute) lemma sup_relative_same_increasing: "x \ y \ x \ z = x \ w \ y \ z = y \ w" using sup.assoc sup_right_divisibility by auto end text \ Every bounded semilattice is a commutative monoid. Finite sums defined in commutative monoids are available via the following sublocale. \ context bounded_semilattice_sup_bot begin sublocale sup_monoid: comm_monoid_add where plus = sup and zero = bot apply unfold_locales apply (simp add: sup_assoc) apply (simp add: sup_commute) by simp end context semilattice_inf begin lemma inf_same_context: "x \ y \ z \ y \ x \ z \ x \ z = y \ z" using order.antisym by auto end text \ The following class requires only the existence of upper bounds, which is a property common to bounded semilattices and (not necessarily bounded) lattices. We use it in our development of filters. \ class directed_semilattice_inf = semilattice_inf + assumes ub: "\z . x \ z \ y \ z" text \ We extend the \inf\ sublocale, which dualises the order in semilattices, to bounded semilattices. \ context bounded_semilattice_inf_top begin subclass directed_semilattice_inf apply unfold_locales using top_greatest by blast sublocale inf: bounded_semilattice_sup_bot where sup = inf and less_eq = greater_eq and less = greater and bot = top by unfold_locales (simp_all add: less_le_not_le) end subsection \Lattices\ context lattice begin subclass directed_semilattice_inf apply unfold_locales using sup_ge1 sup_ge2 by blast definition dual_additive :: "('a \ 'a) \ bool" where "dual_additive f \ \x y . f (x \ y) = f x \ f y" end text \ Not every bounded lattice has complements, but two elements might still be complements of each other as captured in the following definition. In this situation we can apply, for example, the shunting property shown below. We introduce most definitions using the \abbreviation\ command. \ context bounded_lattice begin abbreviation "complement x y \ x \ y = top \ x \ y = bot" lemma complement_symmetric: "complement x y \ complement y x" by (simp add: inf.commute sup.commute) definition conjugate :: "('a \ 'a) \ ('a \ 'a) \ bool" where "conjugate f g \ \x y . f x \ y = bot \ x \ g y = bot" end class dense_lattice = bounded_lattice + assumes bot_meet_irreducible: "x \ y = bot \ x = bot \ y = bot" context distrib_lattice begin lemma relative_equality: "x \ z = y \ z \ x \ z = y \ z \ x = y" by (metis inf.commute inf_sup_absorb inf_sup_distrib2) end text \ Distributive lattices with a greatest element are widely used in the construction theorem for Stone algebras. \ class distrib_lattice_bot = bounded_lattice_bot + distrib_lattice class distrib_lattice_top = bounded_lattice_top + distrib_lattice class bounded_distrib_lattice = bounded_lattice + distrib_lattice begin subclass distrib_lattice_bot .. subclass distrib_lattice_top .. lemma complement_shunting: assumes "complement z w" shows "z \ x \ y \ x \ w \ y" proof assume 1: "z \ x \ y" have "x = (z \ w) \ x" by (simp add: assms) also have "... \ y \ (w \ x)" using 1 sup.commute sup.left_commute inf_sup_distrib2 sup_right_divisibility by fastforce also have "... \ w \ y" by (simp add: inf.coboundedI1) finally show "x \ w \ y" . next assume "x \ w \ y" hence "z \ x \ z \ (w \ y)" using inf.sup_right_isotone by auto also have "... = z \ y" by (simp add: assms inf_sup_distrib1) also have "... \ y" by simp finally show "z \ x \ y" . qed end subsection \Linear Orders\ text \ We next consider lattices with a linear order structure. In such lattices, join and meet are selective operations, which give the maximum and the minimum of two elements, respectively. Moreover, the lattice is automatically distributive. \ class bounded_linorder = linorder + order_bot + order_top class linear_lattice = lattice + linorder begin lemma max_sup: "max x y = x \ y" by (metis max.boundedI max.cobounded1 max.cobounded2 sup_unique) lemma min_inf: "min x y = x \ y" by (simp add: inf.absorb1 inf.absorb2 min_def) lemma sup_inf_selective: "(x \ y = x \ x \ y = y) \ (x \ y = y \ x \ y = x)" by (meson inf.absorb1 inf.absorb2 le_cases sup.absorb1 sup.absorb2) lemma sup_selective: "x \ y = x \ x \ y = y" using sup_inf_selective by blast lemma inf_selective: "x \ y = x \ x \ y = y" using sup_inf_selective by blast subclass distrib_lattice apply standard apply (rule order.antisym) apply (auto simp add: le_supI2) apply (metis inf_selective inf.coboundedI1 inf.coboundedI2 order.eq_iff) done lemma sup_less_eq: "x \ y \ z \ x \ y \ x \ z" by (metis le_supI1 le_supI2 sup_selective) lemma inf_less_eq: "x \ y \ z \ x \ z \ y \ z" by (metis inf.coboundedI1 inf.coboundedI2 inf_selective) lemma sup_inf_sup: "x \ y = (x \ y) \ (x \ y)" by (metis sup_commute sup_inf_absorb sup_left_commute) end text \ The following class derives additional properties if the linear order of the lattice has a least and a greatest element. \ class linear_bounded_lattice = bounded_lattice + linorder begin subclass linear_lattice .. subclass bounded_linorder .. subclass bounded_distrib_lattice .. lemma sup_dense: "x \ top \ y \ top \ x \ y \ top" by (metis sup_selective) lemma inf_dense: "x \ bot \ y \ bot \ x \ y \ bot" by (metis inf_selective) lemma sup_not_bot: "x \ bot \ x \ y \ bot" by simp lemma inf_not_top: "x \ top \ x \ y \ top" by simp subclass dense_lattice apply unfold_locales using inf_dense by blast end text \ Every bounded linear order can be expanded to a bounded lattice. Join and meet are maximum and minimum, respectively. \ class linorder_lattice_expansion = bounded_linorder + sup + inf + assumes sup_def [simp]: "x \ y = max x y" assumes inf_def [simp]: "x \ y = min x y" begin subclass linear_bounded_lattice apply unfold_locales by auto end subsection \Non-trivial Algebras\ text \ Some results, such as the existence of certain filters, require that the algebras are not trivial. This is not an assumption of the order and lattice classes that come with Isabelle/HOL; for example, \bot = top\ may hold in bounded lattices. \ class non_trivial = assumes consistent: "\x y . x \ y" class non_trivial_order = non_trivial + order class non_trivial_order_bot = non_trivial_order + order_bot class non_trivial_bounded_order = non_trivial_order_bot + order_top begin lemma bot_not_top: "bot \ top" proof - from consistent obtain x y :: 'a where "x \ y" by auto thus ?thesis by (metis bot_less top.extremum_strict) qed end subsection \Homomorphisms\ text \ This section gives definitions of lattice homomorphisms and isomorphisms and basic properties. \ class sup_inf_top_bot_uminus = sup + inf + top + bot + uminus class sup_inf_top_bot_uminus_ord = sup_inf_top_bot_uminus + ord -context boolean_algebra +context Lattices.boolean_algebra begin subclass sup_inf_top_bot_uminus_ord . end abbreviation sup_homomorphism :: "('a::sup \ 'b::sup) \ bool" where "sup_homomorphism f \ \x y . f (x \ y) = f x \ f y" abbreviation inf_homomorphism :: "('a::inf \ 'b::inf) \ bool" where "inf_homomorphism f \ \x y . f (x \ y) = f x \ f y" abbreviation bot_homomorphism :: "('a::bot \ 'b::bot) \ bool" where "bot_homomorphism f \ f bot = bot" abbreviation top_homomorphism :: "('a::top \ 'b::top) \ bool" where "top_homomorphism f \ f top = top" abbreviation minus_homomorphism :: "('a::minus \ 'b::minus) \ bool" where "minus_homomorphism f \ \x y . f (x - y) = f x - f y" abbreviation uminus_homomorphism :: "('a::uminus \ 'b::uminus) \ bool" where "uminus_homomorphism f \ \x . f (-x) = -f x" abbreviation sup_inf_homomorphism :: "('a::{sup,inf} \ 'b::{sup,inf}) \ bool" where "sup_inf_homomorphism f \ sup_homomorphism f \ inf_homomorphism f" abbreviation sup_inf_top_homomorphism :: "('a::{sup,inf,top} \ 'b::{sup,inf,top}) \ bool" where "sup_inf_top_homomorphism f \ sup_inf_homomorphism f \ top_homomorphism f" abbreviation sup_inf_top_bot_homomorphism :: "('a::{sup,inf,top,bot} \ 'b::{sup,inf,top,bot}) \ bool" where "sup_inf_top_bot_homomorphism f \ sup_inf_top_homomorphism f \ bot_homomorphism f" abbreviation bounded_lattice_homomorphism :: "('a::bounded_lattice \ 'b::bounded_lattice) \ bool" where "bounded_lattice_homomorphism f \ sup_inf_top_bot_homomorphism f" abbreviation sup_inf_top_bot_uminus_homomorphism :: "('a::sup_inf_top_bot_uminus \ 'b::sup_inf_top_bot_uminus) \ bool" where "sup_inf_top_bot_uminus_homomorphism f \ sup_inf_top_bot_homomorphism f \ uminus_homomorphism f" abbreviation sup_inf_top_bot_uminus_ord_homomorphism :: "('a::sup_inf_top_bot_uminus_ord \ 'b::sup_inf_top_bot_uminus_ord) \ bool" where "sup_inf_top_bot_uminus_ord_homomorphism f \ sup_inf_top_bot_uminus_homomorphism f \ (\x y . x \ y \ f x \ f y)" abbreviation sup_inf_top_isomorphism :: "('a::{sup,inf,top} \ 'b::{sup,inf,top}) \ bool" where "sup_inf_top_isomorphism f \ sup_inf_top_homomorphism f \ bij f" abbreviation bounded_lattice_top_isomorphism :: "('a::bounded_lattice_top \ 'b::bounded_lattice_top) \ bool" where "bounded_lattice_top_isomorphism f \ sup_inf_top_isomorphism f" abbreviation sup_inf_top_bot_uminus_isomorphism :: "('a::sup_inf_top_bot_uminus \ 'b::sup_inf_top_bot_uminus) \ bool" where "sup_inf_top_bot_uminus_isomorphism f \ sup_inf_top_bot_uminus_homomorphism f \ bij f" abbreviation boolean_algebra_isomorphism :: "('a::boolean_algebra \ 'b::boolean_algebra) \ bool" where "boolean_algebra_isomorphism f \ sup_inf_top_bot_uminus_isomorphism f \ minus_homomorphism f" lemma sup_homomorphism_mono: "sup_homomorphism (f::'a::semilattice_sup \ 'b::semilattice_sup) \ mono f" by (metis le_iff_sup monoI) lemma sup_isomorphism_ord_isomorphism: assumes "sup_homomorphism (f::'a::semilattice_sup \ 'b::semilattice_sup)" and "bij f" shows "x \ y \ f x \ f y" proof assume "x \ y" thus "f x \ f y" by (metis assms(1) le_iff_sup) next assume "f x \ f y" hence "f (x \ y) = f y" by (simp add: assms(1) le_iff_sup) hence "x \ y = y" by (metis injD bij_is_inj assms(2)) thus "x \ y" by (simp add: le_iff_sup) qed lemma minus_homomorphism_default: assumes "\x y::'a::{inf,minus,uminus} . x - y = x \ -y" and "\x y::'b::{inf,minus,uminus} . x - y = x \ -y" and "inf_homomorphism (f::'a \ 'b)" and "uminus_homomorphism f" shows "minus_homomorphism f" by (simp add: assms) end diff --git a/thys/Stone_Algebras/P_Algebras.thy b/thys/Stone_Algebras/P_Algebras.thy --- a/thys/Stone_Algebras/P_Algebras.thy +++ b/thys/Stone_Algebras/P_Algebras.thy @@ -1,1328 +1,1328 @@ (* Title: Pseudocomplemented Algebras Author: Walter Guttmann Maintainer: Walter Guttmann *) section \Pseudocomplemented Algebras\ text \ This theory expands lattices with a pseudocomplement operation. In particular, we consider the following algebraic structures: \begin{itemize} \item pseudocomplemented lattices (p-algebras) \item pseudocomplemented distributive lattices (distributive p-algebras) \item Stone algebras \item Heyting semilattices \item Heyting lattices \item Heyting algebras \item Heyting-Stone algebras \item Brouwer algebras \item Boolean algebras \end{itemize} Most of these structures and many results in this theory are discussed in \cite{BalbesDwinger1974,Birkhoff1967,Blyth2005,Curry1977,Graetzer1971,Maddux1996}. \ theory P_Algebras imports Lattice_Basics begin subsection \P-Algebras\ text \ In this section we add a pseudocomplement operation to lattices and to distributive lattices. \ subsubsection \Pseudocomplemented Lattices\ text \ The pseudocomplement of an element \y\ is the greatest element whose meet with \y\ is the least element of the lattice. \ class p_algebra = bounded_lattice + uminus + assumes pseudo_complement: "x \ y = bot \ x \ -y" begin subclass sup_inf_top_bot_uminus_ord . text \ Regular elements and dense elements are frequently used in pseudocomplemented algebras. \ abbreviation "regular x \ x = --x" abbreviation "dense x \ -x = bot" abbreviation "complemented x \ \y . x \ y = bot \ x \ y = top" abbreviation "in_p_image x \ \y . x = -y" abbreviation "selection s x \ s = --s \ x" abbreviation "dense_elements \ { x . dense x }" abbreviation "regular_elements \ { x . in_p_image x }" lemma p_bot [simp]: "-bot = top" using inf_top.left_neutral pseudo_complement top_unique by blast lemma p_top [simp]: "-top = bot" by (metis eq_refl inf_top.comm_neutral pseudo_complement) text \ The pseudocomplement satisfies the following half of the requirements of a complement. \ lemma inf_p [simp]: "x \ -x = bot" using inf.commute pseudo_complement by fastforce lemma p_inf [simp]: "-x \ x = bot" by (simp add: inf_commute) lemma pp_inf_p: "--x \ -x = bot" by simp text \ The double complement is a closure operation. \ lemma pp_increasing: "x \ --x" using inf_p pseudo_complement by blast lemma ppp [simp]: "---x = -x" by (metis order.antisym inf.commute order_trans pseudo_complement pp_increasing) lemma pp_idempotent: "----x = --x" by simp lemma regular_in_p_image_iff: "regular x \ in_p_image x" by auto lemma pseudo_complement_pp: "x \ y = bot \ --x \ -y" by (metis inf_commute pseudo_complement ppp) lemma p_antitone: "x \ y \ -y \ -x" by (metis inf_commute order_trans pseudo_complement pp_increasing) lemma p_antitone_sup: "-(x \ y) \ -x" by (simp add: p_antitone) lemma p_antitone_inf: "-x \ -(x \ y)" by (simp add: p_antitone) lemma p_antitone_iff: "x \ -y \ y \ -x" using order_lesseq_imp p_antitone pp_increasing by blast lemma pp_isotone: "x \ y \ --x \ --y" by (simp add: p_antitone) lemma pp_isotone_sup: "--x \ --(x \ y)" by (simp add: p_antitone) lemma pp_isotone_inf: "--(x \ y) \ --x" by (simp add: p_antitone) text \ One of De Morgan's laws holds in pseudocomplemented lattices. \ lemma p_dist_sup [simp]: "-(x \ y) = -x \ -y" apply (rule order.antisym) apply (simp add: p_antitone) using inf_le1 inf_le2 le_sup_iff p_antitone_iff by blast lemma p_supdist_inf: "-x \ -y \ -(x \ y)" by (simp add: p_antitone) lemma pp_dist_pp_sup [simp]: "--(--x \ --y) = --(x \ y)" by simp lemma p_sup_p [simp]: "-(x \ -x) = bot" by simp lemma pp_sup_p [simp]: "--(x \ -x) = top" by simp lemma dense_pp: "dense x \ --x = top" by (metis p_bot p_top ppp) lemma dense_sup_p: "dense (x \ -x)" by simp lemma regular_char: "regular x \ (\y . x = -y)" by auto lemma pp_inf_bot_iff: "x \ y = bot \ --x \ y = bot" by (simp add: pseudo_complement_pp) text \ Weak forms of the shunting property hold. Most require a pseudocomplemented element on the right-hand side. \ lemma p_shunting_swap: "x \ y \ -z \ x \ z \ -y" by (metis inf_assoc inf_commute pseudo_complement) lemma pp_inf_below_iff: "x \ y \ -z \ --x \ y \ -z" by (simp add: inf_commute p_shunting_swap) lemma p_inf_pp [simp]: "-(x \ --y) = -(x \ y)" apply (rule order.antisym) apply (simp add: inf.coboundedI2 p_antitone pp_increasing) using inf_commute p_antitone_iff pp_inf_below_iff by auto lemma p_inf_pp_pp [simp]: "-(--x \ --y) = -(x \ y)" by (simp add: inf_commute) lemma regular_closed_inf: "regular x \ regular y \ regular (x \ y)" by (metis p_dist_sup ppp) lemma regular_closed_p: "regular (-x)" by simp lemma regular_closed_pp: "regular (--x)" by simp lemma regular_closed_bot: "regular bot" by simp lemma regular_closed_top: "regular top" by simp lemma pp_dist_inf [simp]: "--(x \ y) = --x \ --y" by (metis p_dist_sup p_inf_pp_pp ppp) lemma inf_import_p [simp]: "x \ -(x \ y) = x \ -y" apply (rule order.antisym) using p_shunting_swap apply fastforce using inf.sup_right_isotone p_antitone by auto text \ Pseudocomplements are unique. \ lemma p_unique: "(\x . x \ y = bot \ x \ z) \ z = -y" using inf.order_eq_iff pseudo_complement by auto lemma maddux_3_5: "x \ x = x \ -(y \ -y)" by simp lemma shunting_1_pp: "x \ --y \ x \ -y = bot" by (simp add: pseudo_complement) lemma pp_pp_inf_bot_iff: "x \ y = bot \ --x \ --y = bot" by (simp add: pseudo_complement_pp) lemma inf_pp_semi_commute: "x \ --y \ --(x \ y)" using inf.eq_refl p_antitone_iff p_inf_pp by presburger lemma inf_pp_commute: "--(--x \ y) = --x \ --y" by simp lemma sup_pp_semi_commute: "x \ --y \ --(x \ y)" by (simp add: p_antitone_iff) lemma regular_sup: "regular z \ (x \ z \ y \ z \ --(x \ y) \ z)" apply (rule iffI) apply (metis le_supI pp_isotone) using dual_order.trans sup_ge2 pp_increasing pp_isotone_sup by blast lemma dense_closed_inf: "dense x \ dense y \ dense (x \ y)" by (simp add: dense_pp) lemma dense_closed_sup: "dense x \ dense y \ dense (x \ y)" by simp lemma dense_closed_pp: "dense x \ dense (--x)" by simp lemma dense_closed_top: "dense top" by simp lemma dense_up_closed: "dense x \ x \ y \ dense y" using dense_pp top_le pp_isotone by auto lemma regular_dense_top: "regular x \ dense x \ x = top" using p_bot by blast lemma selection_char: "selection s x \ (\y . s = -y \ x)" by (metis inf_import_p inf_commute regular_closed_p) lemma selection_closed_inf: "selection s x \ selection t x \ selection (s \ t) x" by (metis inf_assoc inf_commute inf_idem pp_dist_inf) lemma selection_closed_pp: "regular x \ selection s x \ selection (--s) x" by (metis pp_dist_inf) lemma selection_closed_bot: "selection bot x" by simp lemma selection_closed_id: "selection x x" using inf.le_iff_sup pp_increasing by auto text \ Conjugates are usually studied for Boolean algebras, however, some of their properties generalise to pseudocomplemented algebras. \ lemma conjugate_unique_p: assumes "conjugate f g" and "conjugate f h" shows "uminus \ g = uminus \ h" proof - have "\x y . x \ g y = bot \ x \ h y = bot" using assms conjugate_def inf.commute by simp hence "\x y . x \ -(g y) \ x \ -(h y)" using inf.commute pseudo_complement by simp hence "\y . -(g y) = -(h y)" using order.eq_iff by blast thus ?thesis by auto qed lemma conjugate_symmetric: "conjugate f g \ conjugate g f" by (simp add: conjugate_def inf_commute) lemma additive_isotone: "additive f \ isotone f" by (metis additive_def isotone_def le_iff_sup) lemma dual_additive_antitone: assumes "dual_additive f" shows "isotone (uminus \ f)" proof - have "\x y . f (x \ y) \ f x" using assms dual_additive_def by simp hence "\x y . x \ y \ f y \ f x" by (metis sup_absorb2) hence "\x y . x \ y \ -(f x) \ -(f y)" by (simp add: p_antitone) thus ?thesis by (simp add: isotone_def) qed lemma conjugate_dual_additive: assumes "conjugate f g" shows "dual_additive (uminus \ f)" proof - have 1: "\x y z . -z \ -(f (x \ y)) \ -z \ -(f x) \ -z \ -(f y)" proof (intro allI) fix x y z have "(-z \ -(f (x \ y))) = (f (x \ y) \ -z = bot)" by (simp add: p_antitone_iff pseudo_complement) also have "... = ((x \ y) \ g(-z) = bot)" using assms conjugate_def by auto also have "... = (x \ y \ -(g(-z)))" by (simp add: pseudo_complement) also have "... = (x \ -(g(-z)) \ y \ -(g(-z)))" by (simp add: le_sup_iff) also have "... = (x \ g(-z) = bot \ y \ g(-z) = bot)" by (simp add: pseudo_complement) also have "... = (f x \ -z = bot \ f y \ -z = bot)" using assms conjugate_def by auto also have "... = (-z \ -(f x) \ -z \ -(f y))" by (simp add: p_antitone_iff pseudo_complement) finally show "-z \ -(f (x \ y)) \ -z \ -(f x) \ -z \ -(f y)" by simp qed have "\x y . -(f (x \ y)) = -(f x) \ -(f y)" proof (intro allI) fix x y have "-(f x) \ -(f y) = --(-(f x) \ -(f y))" by simp hence "-(f x) \ -(f y) \ -(f (x \ y))" using 1 by (metis inf_le1 inf_le2) thus "-(f (x \ y)) = -(f x) \ -(f y)" using 1 order.antisym by fastforce qed thus ?thesis using dual_additive_def by simp qed lemma conjugate_isotone_pp: "conjugate f g \ isotone (uminus \ uminus \ f)" by (simp add: comp_assoc conjugate_dual_additive dual_additive_antitone) lemma conjugate_char_1_pp: "conjugate f g \ (\x y . f(x \ -(g y)) \ --f x \ -y \ g(y \ -(f x)) \ --g y \ -x)" proof assume 1: "conjugate f g" show "\x y . f(x \ -(g y)) \ --f x \ -y \ g(y \ -(f x)) \ --g y \ -x" proof (intro allI) fix x y have 2: "f(x \ -(g y)) \ -y" using 1 by (simp add: conjugate_def pseudo_complement) have "f(x \ -(g y)) \ --f(x \ -(g y))" by (simp add: pp_increasing) also have "... \ --f x" using 1 conjugate_isotone_pp isotone_def by simp finally have 3: "f(x \ -(g y)) \ --f x \ -y" using 2 by simp have 4: "isotone (uminus \ uminus \ g)" using 1 conjugate_isotone_pp conjugate_symmetric by auto have 5: "g(y \ -(f x)) \ -x" using 1 by (metis conjugate_def inf.cobounded2 inf_commute pseudo_complement) have "g(y \ -(f x)) \ --g(y \ -(f x))" by (simp add: pp_increasing) also have "... \ --g y" using 4 isotone_def by auto finally have "g(y \ -(f x)) \ --g y \ -x" using 5 by simp thus "f(x \ -(g y)) \ --f x \ -y \ g(y \ -(f x)) \ --g y \ -x" using 3 by simp qed next assume 6: "\x y . f(x \ -(g y)) \ --f x \ -y \ g(y \ -(f x)) \ --g y \ -x" hence 7: "\x y . f x \ y = bot \ x \ g y = bot" by (metis inf.le_iff_sup inf.le_sup_iff inf_commute pseudo_complement) have "\x y . x \ g y = bot \ f x \ y = bot" using 6 by (metis inf.le_iff_sup inf.le_sup_iff inf_commute pseudo_complement) thus "conjugate f g" using 7 conjugate_def by auto qed lemma conjugate_char_1_isotone: "conjugate f g \ isotone f \ isotone g \ f(x \ -(g y)) \ f x \ -y \ g(y \ -(f x)) \ g y \ -x" by (simp add: conjugate_char_1_pp ord.isotone_def) lemma dense_lattice_char_1: "(\x y . x \ y = bot \ x = bot \ y = bot) \ (\x . x \ bot \ dense x)" by (metis inf_top.left_neutral p_bot p_inf pp_inf_bot_iff) lemma dense_lattice_char_2: "(\x y . x \ y = bot \ x = bot \ y = bot) \ (\x . regular x \ x = bot \ x = top)" by (metis dense_lattice_char_1 inf_top.left_neutral p_inf regular_closed_p regular_closed_top) lemma restrict_below_Rep_eq: "x \ --y \ z \ x \ y = x \ z \ y" by (metis inf.absorb2 inf.commute inf.left_commute pp_increasing) (* lemma p_inf_sup_below: "-x \ (x \ y) \ y" nitpick [expect=genuine] oops lemma complement_p: "x \ y = bot \ x \ y = top \ -x = y" nitpick [expect=genuine] oops lemma complemented_regular: "complemented x \ regular x" nitpick [expect=genuine] oops *) end text \ The following class gives equational axioms for the pseudocomplement operation. \ class p_algebra_eq = bounded_lattice + uminus + assumes p_bot_eq: "-bot = top" and p_top_eq: "-top = bot" and inf_import_p_eq: "x \ -(x \ y) = x \ -y" begin lemma inf_p_eq: "x \ -x = bot" by (metis inf_bot_right inf_import_p_eq inf_top_right p_top_eq) subclass p_algebra apply unfold_locales apply (rule iffI) apply (metis inf.orderI inf_import_p_eq inf_top.right_neutral p_bot_eq) by (metis (full_types) inf.left_commute inf.orderE inf_bot_right inf_commute inf_p_eq) end subsubsection \Pseudocomplemented Distributive Lattices\ text \ We obtain further properties if we assume that the lattice operations are distributive. \ class pd_algebra = p_algebra + bounded_distrib_lattice begin lemma p_inf_sup_below: "-x \ (x \ y) \ y" by (simp add: inf_sup_distrib1) lemma pp_inf_sup_p [simp]: "--x \ (x \ -x) = x" using inf.absorb2 inf_sup_distrib1 pp_increasing by auto lemma complement_p: "x \ y = bot \ x \ y = top \ -x = y" by (metis pseudo_complement inf.commute inf_top.left_neutral sup.absorb_iff1 sup.commute sup_bot.right_neutral sup_inf_distrib2 p_inf) lemma complemented_regular: "complemented x \ regular x" using complement_p inf.commute sup.commute by fastforce lemma regular_inf_dense: "\y z . regular y \ dense z \ x = y \ z" by (metis pp_inf_sup_p dense_sup_p ppp) lemma maddux_3_12 [simp]: "(x \ -y) \ (x \ y) = x" by (metis p_inf sup_bot_right sup_inf_distrib1) lemma maddux_3_13 [simp]: "(x \ y) \ -x = y \ -x" by (simp add: inf_sup_distrib2) lemma maddux_3_20: "((v \ w) \ (-v \ x)) \ -((v \ y) \ (-v \ z)) = (v \ w \ -y) \ (-v \ x \ -z)" proof - have "v \ w \ -(v \ y) \ -(-v \ z) = v \ w \ -(v \ y)" by (meson inf.cobounded1 inf_absorb1 le_infI1 p_antitone_iff) also have "... = v \ w \ -y" using inf.sup_relative_same_increasing inf_import_p inf_le1 by blast finally have 1: "v \ w \ -(v \ y) \ -(-v \ z) = v \ w \ -y" . have "-v \ x \ -(v \ y) \ -(-v \ z) = -v \ x \ -(-v \ z)" by (simp add: inf.absorb1 le_infI1 p_antitone_inf) also have "... = -v \ x \ -z" by (simp add: inf.assoc inf_left_commute) finally have 2: "-v \ x \ -(v \ y) \ -(-v \ z) = -v \ x \ -z" . have "((v \ w) \ (-v \ x)) \ -((v \ y) \ (-v \ z)) = (v \ w \ -(v \ y) \ -(-v \ z)) \ (-v \ x \ -(v \ y) \ -(-v \ z))" by (simp add: inf_assoc inf_sup_distrib2) also have "... = (v \ w \ -y) \ (-v \ x \ -z)" using 1 2 by simp finally show ?thesis . qed lemma order_char_1: "x \ y \ x \ y \ -x" by (metis inf.sup_left_isotone inf_sup_absorb le_supI1 maddux_3_12 sup_commute) lemma order_char_2: "x \ y \ x \ -x \ y \ -x" using order_char_1 by auto lemma half_shunting: "x \ y \ z \ x \ -z \ y" by (metis inf.sup_right_isotone inf_commute inf_sup_distrib1 sup.boundedE maddux_3_12) (* lemma pp_dist_sup [simp]: "--(x \ y) = --x \ --y" nitpick [expect=genuine] oops lemma regular_closed_sup: "regular x \ regular y \ regular (x \ y)" nitpick [expect=genuine] oops lemma regular_complemented_iff: "regular x \ complemented x" nitpick [expect=genuine] oops lemma selection_closed_sup: "selection s x \ selection t x \ selection (s \ t) x" nitpick [expect=genuine] oops lemma stone [simp]: "-x \ --x = top" nitpick [expect=genuine] oops *) end subsection \Stone Algebras\ text \ A Stone algebra is a distributive lattice with a pseudocomplement that satisfies the following equation. We thus obtain the other half of the requirements of a complement at least for the regular elements. \ class stone_algebra = pd_algebra + assumes stone [simp]: "-x \ --x = top" begin text \ As a consequence, we obtain both De Morgan's laws for all elements. \ lemma p_dist_inf [simp]: "-(x \ y) = -x \ -y" proof (rule p_unique[THEN sym], rule allI, rule iffI) fix w assume "w \ (x \ y) = bot" hence "w \ --x \ y = bot" using inf_commute inf_left_commute pseudo_complement by auto hence 1: "w \ --x \ -y" by (simp add: pseudo_complement) have "w = (w \ -x) \ (w \ --x)" using distrib_imp2 sup_inf_distrib1 by auto thus "w \ -x \ -y" using 1 by (metis inf_le2 sup.mono) next fix w assume "w \ -x \ -y" thus "w \ (x \ y) = bot" using order_trans p_supdist_inf pseudo_complement by blast qed lemma pp_dist_sup [simp]: "--(x \ y) = --x \ --y" by simp lemma regular_closed_sup: "regular x \ regular y \ regular (x \ y)" by simp text \ The regular elements are precisely the ones having a complement. \ lemma regular_complemented_iff: "regular x \ complemented x" by (metis inf_p stone complemented_regular) lemma selection_closed_sup: "selection s x \ selection t x \ selection (s \ t) x" by (simp add: inf_sup_distrib2) lemma huntington_3_pp [simp]: "-(-x \ -y) \ -(-x \ y) = --x" by (metis p_dist_inf p_inf sup.commute sup_bot_left sup_inf_distrib1) lemma maddux_3_3 [simp]: "-(x \ y) \ -(x \ -y) = -x" by (simp add: sup_commute sup_inf_distrib1) lemma maddux_3_11_pp: "(x \ -y) \ (x \ --y) = x" by (metis inf_sup_distrib1 inf_top_right stone) lemma maddux_3_19_pp: "(-x \ y) \ (--x \ z) = (--x \ y) \ (-x \ z)" proof - have "(--x \ y) \ (-x \ z) = (--x \ z) \ (y \ -x) \ (y \ z)" by (simp add: inf.commute inf_sup_distrib1 sup.assoc) also have "... = (--x \ z) \ (y \ -x) \ (y \ z \ (-x \ --x))" by simp also have "... = (--x \ z) \ ((y \ -x) \ (y \ -x \ z)) \ (y \ z \ --x)" using inf_sup_distrib1 sup_assoc inf_commute inf_assoc by presburger also have "... = (--x \ z) \ (y \ -x) \ (y \ z \ --x)" by simp also have "... = ((--x \ z) \ (--x \ z \ y)) \ (y \ -x)" by (simp add: inf_assoc inf_commute sup.left_commute sup_commute) also have "... = (--x \ z) \ (y \ -x)" by simp finally show ?thesis by (simp add: inf_commute sup_commute) qed lemma compl_inter_eq_pp: "--x \ y = --x \ z \ -x \ y = -x \ z \ y = z" by (metis inf_commute inf_p inf_sup_distrib1 inf_top.right_neutral p_bot p_dist_inf) lemma maddux_3_21_pp [simp]: "--x \ (-x \ y) = --x \ y" by (simp add: sup.commute sup_inf_distrib1) lemma shunting_2_pp: "x \ --y \ -x \ --y = top" by (metis inf_top_left p_bot p_dist_inf pseudo_complement) lemma shunting_p: "x \ y \ -z \ x \ -z \ -y" by (metis inf.assoc p_dist_inf p_shunting_swap pseudo_complement) text \ The following weak shunting property is interesting as it does not require the element \z\ on the right-hand side to be regular. \ lemma shunting_var_p: "x \ -y \ z \ x \ z \ --y" proof assume "x \ -y \ z" hence "z \ --y = --y \ (z \ x \ -y)" by (simp add: sup.absorb1 sup.commute) thus "x \ z \ --y" by (metis inf_commute maddux_3_21_pp sup.commute sup.left_commute sup_left_divisibility) next assume "x \ z \ --y" thus "x \ -y \ z" by (metis inf.mono maddux_3_12 sup_ge2) qed (* Whether conjugate_char_2_pp can be proved in pd_algebra or in p_algebra is unknown. *) lemma conjugate_char_2_pp: "conjugate f g \ f bot = bot \ g bot = bot \ (\x y . f x \ y \ --(f(x \ --(g y))) \ g y \ x \ --(g(y \ --(f x))))" proof assume 1: "conjugate f g" hence 2: "dual_additive (uminus \ g)" using conjugate_symmetric conjugate_dual_additive by auto show "f bot = bot \ g bot = bot \ (\x y . f x \ y \ --(f(x \ --(g y))) \ g y \ x \ --(g(y \ --(f x))))" proof (intro conjI) show "f bot = bot" using 1 by (metis conjugate_def inf_idem inf_bot_left) next show "g bot = bot" using 1 by (metis conjugate_def inf_idem inf_bot_right) next show "\x y . f x \ y \ --(f(x \ --(g y))) \ g y \ x \ --(g(y \ --(f x)))" proof (intro allI) fix x y have 3: "y \ -(f(x \ -(g y)))" using 1 by (simp add: conjugate_def pseudo_complement inf_commute) have 4: "x \ -(g(y \ -(f x)))" using 1 conjugate_def inf.commute pseudo_complement by fastforce have "y \ -(f(x \ --(g y))) = y \ -(f(x \ -(g y))) \ -(f(x \ --(g y)))" using 3 by (simp add: inf.le_iff_sup inf_commute) also have "... = y \ -(f((x \ -(g y)) \ (x \ --(g y))))" using 1 conjugate_dual_additive dual_additive_def inf_assoc by auto also have "... = y \ -(f x)" by (simp add: maddux_3_11_pp) also have "... \ -(f x)" by simp finally have 5: "f x \ y \ --(f(x \ --(g y)))" by (simp add: inf_commute p_shunting_swap) have "x \ -(g(y \ --(f x))) = x \ -(g(y \ -(f x))) \ -(g(y \ --(f x)))" using 4 by (simp add: inf.le_iff_sup inf_commute) also have "... = x \ -(g((y \ -(f x)) \ (y \ --(f x))))" using 2 by (simp add: dual_additive_def inf_assoc) also have "... = x \ -(g y)" by (simp add: maddux_3_11_pp) also have "... \ -(g y)" by simp finally have "g y \ x \ --(g(y \ --(f x)))" by (simp add: inf_commute p_shunting_swap) thus "f x \ y \ --(f(x \ --(g y))) \ g y \ x \ --(g(y \ --(f x)))" using 5 by simp qed qed next assume "f bot = bot \ g bot = bot \ (\x y . f x \ y \ --(f(x \ --(g y))) \ g y \ x \ --(g(y \ --(f x))))" thus "conjugate f g" by (unfold conjugate_def, metis inf_commute le_bot pp_inf_bot_iff regular_closed_bot) qed lemma conjugate_char_2_pp_additive: assumes "conjugate f g" and "additive f" and "additive g" shows "f x \ y \ f(x \ --(g y)) \ g y \ x \ g(y \ --(f x))" proof - have "f x \ y = f ((x \ --g y) \ (x \ -g y)) \ y" by (simp add: sup.commute sup_inf_distrib1) also have "... = (f (x \ --g y) \ y) \ (f (x \ -g y) \ y)" using assms(2) additive_def inf_sup_distrib2 by auto also have "... = f (x \ --g y) \ y" by (metis assms(1) conjugate_def inf_le2 pseudo_complement sup_bot.right_neutral) finally have 2: "f x \ y \ f (x \ --g y)" by simp have "g y \ x = g ((y \ --f x) \ (y \ -f x)) \ x" by (simp add: sup.commute sup_inf_distrib1) also have "... = (g (y \ --f x) \ x) \ (g (y \ -f x) \ x)" using assms(3) additive_def inf_sup_distrib2 by auto also have "... = g (y \ --f x) \ x" by (metis assms(1) conjugate_def inf.cobounded2 pseudo_complement sup_bot.right_neutral inf_commute) finally have "g y \ x \ g (y \ --f x)" by simp thus ?thesis using 2 by simp qed (* lemma compl_le_swap2_iff: "-x \ y \ -y \ x" nitpick [expect=genuine] oops lemma huntington_3: "x = -(-x \ -y) \ -(-x \ y)" nitpick [expect=genuine] oops lemma maddux_3_1: "x \ -x = y \ -y" nitpick [expect=genuine] oops lemma maddux_3_4: "x \ (y \ -y) = z \ -z" nitpick [expect=genuine] oops lemma maddux_3_11: "x = (x \ y) \ (x \ -y)" nitpick [expect=genuine] oops lemma maddux_3_19: "(-x \ y) \ (x \ z) = (x \ y) \ (-x \ z)" nitpick [expect=genuine] oops lemma compl_inter_eq: "x \ y = x \ z \ -x \ y = -x \ z \ y = z" nitpick [expect=genuine] oops lemma maddux_3_21: "x \ y = x \ (-x \ y)" nitpick [expect=genuine] oops lemma shunting_1: "x \ y \ x \ -y = bot" nitpick [expect=genuine] oops lemma shunting_2: "x \ y \ -x \ y = top" nitpick [expect=genuine] oops lemma conjugate_unique: "conjugate f g \ conjugate f h \ g = h" nitpick [expect=genuine] oops lemma conjugate_isotone_pp: "conjugate f g \ isotone f" nitpick [expect=genuine] oops lemma conjugate_char_1: "conjugate f g \ (\x y . f(x \ -(g y)) \ f x \ -y \ g(y \ -(f x)) \ g y \ -x)" nitpick [expect=genuine] oops lemma conjugate_char_2: "conjugate f g \ f bot = bot \ g bot = bot \ (\x y . f x \ y \ f(x \ g y) \ g y \ x \ g(y \ f x))" nitpick [expect=genuine] oops lemma shunting: "x \ y \ z \ x \ z \ -y" nitpick [expect=genuine] oops lemma shunting_var: "x \ -y \ z \ x \ z \ y" nitpick [expect=genuine] oops lemma sup_compl_top: "x \ -x = top" nitpick [expect=genuine] oops lemma selection_closed_p: "selection s x \ selection (-s) x" nitpick [expect=genuine] oops lemma selection_closed_pp: "selection s x \ selection (--s) x" nitpick [expect=genuine] oops *) end abbreviation stone_algebra_isomorphism :: "('a::stone_algebra \ 'b::stone_algebra) \ bool" where "stone_algebra_isomorphism f \ sup_inf_top_bot_uminus_isomorphism f" text \ Every bounded linear order can be expanded to a Stone algebra. The pseudocomplement takes \bot\ to the \top\ and every other element to \bot\. \ class linorder_stone_algebra_expansion = linorder_lattice_expansion + uminus + assumes uminus_def [simp]: "-x = (if x = bot then top else bot)" begin subclass stone_algebra apply unfold_locales using bot_unique min_def top_le by auto text \ The regular elements are the least and greatest elements. All elements except the least element are dense. \ lemma regular_bot_top: "regular x \ x = bot \ x = top" by simp lemma not_bot_dense: "x \ bot \ --x = top" by simp end subsection \Heyting Algebras\ text \ In this section we add a relative pseudocomplement operation to semilattices and to lattices. \ subsubsection \Heyting Semilattices\ text \ The pseudocomplement of an element \y\ relative to an element \z\ is the least element whose meet with \y\ is below \z\. This can be stated as a Galois connection. Specialising \z = bot\ gives (non-relative) pseudocomplements. Many properties can already be shown if the underlying structure is just a semilattice. \ class implies = fixes implies :: "'a \ 'a \ 'a" (infixl "\" 65) class heyting_semilattice = semilattice_inf + implies + assumes implies_galois: "x \ y \ z \ x \ y \ z" begin lemma implies_below_eq [simp]: "y \ (x \ y) = y" using implies_galois inf.absorb_iff1 inf.cobounded1 by blast lemma implies_increasing: "x \ y \ x" by (simp add: inf.orderI) lemma implies_galois_swap: "x \ y \ z \ y \ x \ z" by (metis implies_galois inf_commute) lemma implies_galois_var: "x \ y \ z \ y \ x \ z" by (simp add: implies_galois_swap implies_galois) lemma implies_galois_increasing: "x \ y \ (x \ y)" using implies_galois by blast lemma implies_galois_decreasing: "(y \ x) \ y \ x" using implies_galois by blast lemma implies_mp_below: "x \ (x \ y) \ y" using implies_galois_decreasing inf_commute by auto lemma implies_isotone: "x \ y \ z \ x \ z \ y" using implies_galois order_trans by blast lemma implies_antitone: "x \ y \ y \ z \ x \ z" by (meson implies_galois_swap order_lesseq_imp) lemma implies_isotone_inf: "x \ (y \ z) \ x \ y" by (simp add: implies_isotone) lemma implies_antitone_inf: "x \ z \ (x \ y) \ z" by (simp add: implies_antitone) lemma implies_curry: "x \ (y \ z) = (x \ y) \ z" by (metis implies_galois_decreasing implies_galois inf_assoc order.antisym) lemma implies_curry_flip: "x \ (y \ z) = y \ (x \ z)" by (simp add: implies_curry inf_commute) lemma triple_implies [simp]: "((x \ y) \ y) \ y = x \ y" using implies_antitone implies_galois_swap order.eq_iff by auto lemma implies_mp_eq [simp]: "x \ (x \ y) = x \ y" by (metis implies_below_eq implies_mp_below inf_left_commute inf.absorb2) lemma implies_dist_implies: "x \ (y \ z) \ (x \ y) \ (x \ z)" using implies_curry implies_curry_flip by auto lemma implies_import_inf [simp]: "x \ ((x \ y) \ (x \ z)) = x \ (y \ z)" by (metis implies_curry implies_mp_eq inf_commute) lemma implies_dist_inf: "x \ (y \ z) = (x \ y) \ (x \ z)" proof - have "(x \ y) \ (x \ z) \ x \ y \ z" by (simp add: implies_galois) hence "(x \ y) \ (x \ z) \ x \ (y \ z)" using implies_galois by blast thus ?thesis by (simp add: implies_isotone order.eq_iff) qed lemma implies_itself_top: "y \ x \ x" by (simp add: implies_galois_swap implies_increasing) lemma inf_implies_top: "z \ (x \ y) \ x" using implies_galois_var le_infI1 by blast lemma inf_inf_implies [simp]: "z \ ((x \ y) \ x) = z" by (simp add: inf_implies_top inf_absorb1) lemma le_implies_top: "x \ y \ z \ x \ y" using implies_antitone implies_itself_top order.trans by blast lemma le_iff_le_implies: "x \ y \ x \ x \ y" using implies_galois inf_idem by force lemma implies_inf_isotone: "x \ y \ (x \ z) \ (y \ z)" by (metis implies_curry implies_galois_increasing implies_isotone) lemma implies_transitive: "(x \ y) \ (y \ z) \ x \ z" using implies_dist_implies implies_galois_var implies_increasing order_lesseq_imp by blast lemma implies_inf_absorb [simp]: "x \ (x \ y) = x \ y" using implies_dist_inf implies_itself_top inf.absorb_iff2 by auto lemma implies_implies_absorb [simp]: "x \ (x \ y) = x \ y" by (simp add: implies_curry) lemma implies_inf_identity: "(x \ y) \ y = y" by (simp add: inf_commute) lemma implies_itself_same: "x \ x = y \ y" by (simp add: le_implies_top order.eq_iff) end text \ The following class gives equational axioms for the relative pseudocomplement operation (inequalities can be written as equations). \ class heyting_semilattice_eq = semilattice_inf + implies + assumes implies_mp_below: "x \ (x \ y) \ y" and implies_galois_increasing: "x \ y \ (x \ y)" and implies_isotone_inf: "x \ (y \ z) \ x \ y" begin subclass heyting_semilattice apply unfold_locales apply (rule iffI) apply (metis implies_galois_increasing implies_isotone_inf inf.absorb2 order_lesseq_imp) by (metis implies_mp_below inf_commute order_trans inf_mono order_refl) end text \ The following class allows us to explicitly give the pseudocomplement of an element relative to itself. \ class bounded_heyting_semilattice = bounded_semilattice_inf_top + heyting_semilattice begin lemma implies_itself [simp]: "x \ x = top" using implies_galois inf_le2 top_le by blast lemma implies_order: "x \ y \ x \ y = top" by (metis implies_galois inf_top.left_neutral top_unique) lemma inf_implies [simp]: "(x \ y) \ x = top" using implies_order inf_le1 by blast lemma top_implies [simp]: "top \ x = x" by (metis implies_mp_eq inf_top.left_neutral) end subsubsection \Heyting Lattices\ text \ We obtain further properties if the underlying structure is a lattice. In particular, the lattice operations are automatically distributive in this case. \ class heyting_lattice = lattice + heyting_semilattice begin lemma sup_distrib_inf_le: "(x \ y) \ (x \ z) \ x \ (y \ z)" proof - have "x \ z \ y \ (x \ (y \ z))" using implies_galois_var implies_increasing sup.bounded_iff sup.cobounded2 by blast hence "x \ y \ (x \ z) \ (x \ (y \ z))" using implies_galois_swap implies_increasing le_sup_iff by blast thus ?thesis by (simp add: implies_galois) qed subclass distrib_lattice apply unfold_locales using distrib_sup_le order.eq_iff sup_distrib_inf_le by auto lemma implies_isotone_sup: "x \ y \ x \ (y \ z)" by (simp add: implies_isotone) lemma implies_antitone_sup: "(x \ y) \ z \ x \ z" by (simp add: implies_antitone) lemma implies_sup: "x \ z \ (y \ z) \ ((x \ y) \ z)" proof - have "(x \ z) \ (y \ z) \ y \ z" by (simp add: implies_galois) hence "(x \ z) \ (y \ z) \ (x \ y) \ z" using implies_galois_swap implies_galois_var by fastforce thus ?thesis by (simp add: implies_galois) qed lemma implies_dist_sup: "(x \ y) \ z = (x \ z) \ (y \ z)" apply (rule order.antisym) apply (simp add: implies_antitone) by (simp add: implies_sup implies_galois) lemma implies_antitone_isotone: "(x \ y) \ (x \ y) \ x \ y" by (simp add: implies_antitone_sup implies_dist_inf le_infI2) lemma implies_antisymmetry: "(x \ y) \ (y \ x) = (x \ y) \ (x \ y)" by (metis implies_dist_sup implies_inf_absorb inf.commute) lemma sup_inf_implies [simp]: "(x \ y) \ (x \ y) = y" by (simp add: inf_sup_distrib2 sup.absorb2) lemma implies_subdist_sup: "(x \ y) \ (x \ z) \ x \ (y \ z)" by (simp add: implies_isotone) lemma implies_subdist_inf: "(x \ z) \ (y \ z) \ (x \ y) \ z" by (simp add: implies_antitone) lemma implies_sup_absorb: "(x \ y) \ z \ (x \ z) \ (y \ z)" by (metis implies_dist_sup implies_isotone_sup implies_increasing inf_inf_implies le_sup_iff sup_inf_implies) lemma sup_below_implies_implies: "x \ y \ (x \ y) \ y" by (simp add: implies_dist_sup implies_galois_swap implies_increasing) end class bounded_heyting_lattice = bounded_lattice + heyting_lattice begin subclass bounded_heyting_semilattice .. lemma implies_bot [simp]: "bot \ x = top" using implies_galois top_unique by fastforce end subsubsection \Heyting Algebras\ text \ The pseudocomplement operation can be defined in Heyting algebras, but it is typically not part of their signature. We add the definition as an axiom so that we can use the class hierarchy, for example, to inherit results from the class \pd_algebra\. \ class heyting_algebra = bounded_heyting_lattice + uminus + assumes uminus_eq: "-x = x \ bot" begin subclass pd_algebra apply unfold_locales using bot_unique implies_galois uminus_eq by auto lemma boolean_implies_below: "-x \ y \ x \ y" by (simp add: implies_increasing implies_isotone uminus_eq) lemma negation_implies: "-(x \ y) = --x \ -y" proof (rule order.antisym) show "-(x \ y) \ --x \ -y" using boolean_implies_below p_antitone by auto next have "x \ -y \ (x \ y) = bot" by (metis implies_mp_eq inf_p inf_bot_left inf_commute inf_left_commute) hence "--x \ -y \ (x \ y) = bot" using pp_inf_bot_iff inf_assoc by auto thus "--x \ -y \ -(x \ y)" by (simp add: pseudo_complement) qed lemma double_negation_dist_implies: "--(x \ y) = --x \ --y" apply (rule order.antisym) apply (metis pp_inf_below_iff implies_galois_decreasing implies_galois negation_implies ppp) by (simp add: p_antitone_iff negation_implies) (* lemma stone: "-x \ --x = top" nitpick [expect=genuine] oops *) end text \ The following class gives equational axioms for Heyting algebras. \ class heyting_algebra_eq = bounded_lattice + implies + uminus + assumes implies_mp_eq: "x \ (x \ y) = x \ y" and implies_import_inf: "x \ ((x \ y) \ (x \ z)) = x \ (y \ z)" and inf_inf_implies: "z \ ((x \ y) \ x) = z" and uminus_eq_eq: "-x = x \ bot" begin subclass heyting_algebra apply unfold_locales apply (rule iffI) apply (metis implies_import_inf inf.sup_left_divisibility inf_inf_implies le_iff_inf) apply (metis implies_mp_eq inf.commute inf.le_sup_iff inf.sup_right_isotone) by (simp add: uminus_eq_eq) end text \ A relative pseudocomplement is not enough to obtain the Stone equation, so we add it in the following class. \ class heyting_stone_algebra = heyting_algebra + assumes heyting_stone: "-x \ --x = top" begin subclass stone_algebra by unfold_locales (simp add: heyting_stone) (* lemma pre_linear: "(x \ y) \ (y \ x) = top" nitpick [expect=genuine] oops *) end subsubsection \Brouwer Algebras\ text \ Brouwer algebras are dual to Heyting algebras. The dual pseudocomplement of an element \y\ relative to an element \x\ is the least element whose join with \y\ is above \x\. We can now use the binary operation provided by Boolean algebras in Isabelle/HOL because it is compatible with dual relative pseudocomplements (not relative pseudocomplements). \ class brouwer_algebra = bounded_lattice + minus + uminus + assumes minus_galois: "x \ y \ z \ x - y \ z" and uminus_eq_minus: "-x = top - x" begin sublocale brouwer: heyting_algebra where inf = sup and less_eq = greater_eq and less = greater and sup = inf and bot = top and top = bot and implies = "\x y . y - x" apply unfold_locales apply simp apply simp apply simp apply simp apply (metis minus_galois sup_commute) by (simp add: uminus_eq_minus) lemma curry_minus: "x - (y \ z) = (x - y) - z" by (simp add: brouwer.implies_curry sup_commute) lemma minus_subdist_sup: "(x - z) \ (y - z) \ (x \ y) - z" by (simp add: brouwer.implies_dist_inf) lemma inf_sup_minus: "(x \ y) \ (x - y) = x" by (simp add: inf.absorb1 brouwer.inf_sup_distrib2) end subsection \Boolean Algebras\ text \ This section integrates Boolean algebras in the above hierarchy. In particular, we strengthen several results shown above. \ -context boolean_algebra +context Lattices.boolean_algebra begin text \ Every Boolean algebra is a Stone algebra, a Heyting algebra and a Brouwer algebra. \ subclass stone_algebra apply unfold_locales apply (rule iffI) apply (metis compl_sup_top inf.orderI inf_bot_right inf_sup_distrib1 inf_top_right sup_inf_absorb) using inf.commute inf.sup_right_divisibility apply fastforce by simp sublocale heyting: heyting_algebra where implies = "\x y . -x \ y" apply unfold_locales apply (rule iffI) using shunting_var_p sup_commute apply fastforce using shunting_var_p sup_commute apply force by simp subclass brouwer_algebra apply unfold_locales apply (simp add: diff_eq shunting_var_p sup.commute) by (simp add: diff_eq) lemma huntington_3 [simp]: "-(-x \ -y) \ -(-x \ y) = x" using huntington_3_pp by auto lemma maddux_3_1: "x \ -x = y \ -y" by simp lemma maddux_3_4: "x \ (y \ -y) = z \ -z" by simp lemma maddux_3_11 [simp]: "(x \ y) \ (x \ -y) = x" using brouwer.maddux_3_12 sup.commute by auto lemma maddux_3_19: "(-x \ y) \ (x \ z) = (x \ y) \ (-x \ z)" using maddux_3_19_pp by auto lemma compl_inter_eq: "x \ y = x \ z \ -x \ y = -x \ z \ y = z" by (metis inf_commute maddux_3_11) lemma maddux_3_21 [simp]: "x \ (-x \ y) = x \ y" by (simp add: sup_inf_distrib1) lemma shunting_1: "x \ y \ x \ -y = bot" by (simp add: pseudo_complement) lemma uminus_involutive: "uminus \ uminus = id" by auto lemma uminus_injective: "uminus \ f = uminus \ g \ f = g" by (metis comp_assoc id_o minus_comp_minus) lemma conjugate_unique: "conjugate f g \ conjugate f h \ g = h" using conjugate_unique_p uminus_injective by blast lemma dual_additive_additive: "dual_additive (uminus \ f) \ additive f" by (metis additive_def compl_eq_compl_iff dual_additive_def p_dist_sup o_def) lemma conjugate_additive: "conjugate f g \ additive f" by (simp add: conjugate_dual_additive dual_additive_additive) lemma conjugate_isotone: "conjugate f g \ isotone f" by (simp add: conjugate_additive additive_isotone) lemma conjugate_char_1: "conjugate f g \ (\x y . f(x \ -(g y)) \ f x \ -y \ g(y \ -(f x)) \ g y \ -x)" by (simp add: conjugate_char_1_pp) lemma conjugate_char_2: "conjugate f g \ f bot = bot \ g bot = bot \ (\x y . f x \ y \ f(x \ g y) \ g y \ x \ g(y \ f x))" by (simp add: conjugate_char_2_pp) lemma shunting: "x \ y \ z \ x \ z \ -y" by (simp add: heyting.implies_galois sup.commute) lemma shunting_var: "x \ -y \ z \ x \ z \ y" by (simp add: shunting) end class non_trivial_stone_algebra = non_trivial_bounded_order + stone_algebra class non_trivial_boolean_algebra = non_trivial_stone_algebra + boolean_algebra end diff --git a/thys/Stone_Relation_Algebras/Linear_Order_Matrices.thy b/thys/Stone_Relation_Algebras/Linear_Order_Matrices.thy --- a/thys/Stone_Relation_Algebras/Linear_Order_Matrices.thy +++ b/thys/Stone_Relation_Algebras/Linear_Order_Matrices.thy @@ -1,874 +1,873 @@ (* Title: Matrices over Bounded Linear Orders Author: Walter Guttmann Maintainer: Walter Guttmann *) section \Matrices over Bounded Linear Orders\ text \ In this theory we characterise relation-algebraic properties of matrices over bounded linear orders (for example, extended real numbers) in terms of the entries in the matrices. We consider, in particular, the following properties: univalent, injective, total, surjective, mapping, bijective, vector, covector, point, arc, reflexive, coreflexive, irreflexive, symmetric, antisymmetric, asymmetric. We also consider the effect of composition with the matrix of greatest elements and with coreflexives (tests). \ theory Linear_Order_Matrices imports Matrix_Relation_Algebras begin class non_trivial_linorder_stone_relation_algebra_expansion = linorder_stone_relation_algebra_expansion + non_trivial begin subclass non_trivial_bounded_order .. end text \ Before we look at matrices, we generalise selectivity to finite suprema. \ lemma linorder_finite_sup_selective: fixes f :: "'a::finite \ 'b::linorder_stone_algebra_expansion" shows "\i . (\\<^sub>k f k) = f i" apply (induct rule: comp_inf.one_sup_induct) apply blast using sup_selective by fastforce lemma linorder_top_finite_sup: fixes f :: "'a::finite \ 'b::linorder_stone_algebra_expansion" assumes "\k . f k \ top" shows "(\\<^sub>k f k) \ top" by (metis assms linorder_finite_sup_selective) text \ The following results show the effect of composition with the \top\ matrix from the left and from the right. \ lemma comp_top_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "(f \ mtop) (i,j) = (\\<^sub>k f (i,k))" apply (unfold times_matrix_def top_matrix_def) by (metis (no_types, lifting) case_prod_conv comp_right_one one_def sup_monoid.sum.cong) lemma top_comp_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "(mtop \ f) (i,j) = (\\<^sub>k f (k,j))" apply (unfold times_matrix_def top_matrix_def) by (metis (no_types, lifting) case_prod_conv comp_left_one one_def sup_monoid.sum.cong) text \ We characterise univalent matrices: in each row, at most one entry may be different from \bot\. \ lemma univalent_linorder_matrix_1: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_stone_relation_algebra.univalent f" and "f (i,j) \ bot" and "f (i,k) \ bot" shows "j = k" proof - have "(f\<^sup>t \ f) (j,k) = (\\<^sub>l (f\<^sup>t) (j,l) * f (l,k))" by (simp add: times_matrix_def) also have "... = (\\<^sub>l (f (l,j))\<^sup>T * f (l,k))" by (simp add: conv_matrix_def) also have "... = (\\<^sub>l f (l,j) * f (l,k))" by simp also have "... \ f (i,j) * f (i,k)" using comp_inf.ub_sum by fastforce finally have "(f\<^sup>t \ f) (j,k) \ bot" using assms(2,3) bot.extremum_uniqueI times_dense by fastforce hence "mone (j,k) \ (bot::'b)" by (metis assms(1) bot.extremum_uniqueI less_eq_matrix_def) thus ?thesis by (metis (mono_tags, lifting) case_prod_conv one_matrix_def) qed lemma univalent_linorder_matrix_2: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "\i j k . f (i,j) \ bot \ f (i,k) \ bot \ j = k" shows "matrix_stone_relation_algebra.univalent f" proof - show "f\<^sup>t \ f \ mone" proof (unfold less_eq_matrix_def, rule allI, rule prod_cases) fix j k show "(f\<^sup>t \ f) (j,k) \ mone (j,k)" proof (cases "j = k") assume "j = k" thus ?thesis by (simp add: one_matrix_def) next assume "j \ k" hence "(\\<^sub>i f (i,j) * f (i,k)) = bot" by (metis (no_types, lifting) assms semiring.mult_not_zero sup_monoid.sum.neutral) thus ?thesis by (simp add: times_matrix_def conv_matrix_def) qed qed qed lemma univalent_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.univalent f \ (\i j k . f (i,j) \ bot \ f (i,k) \ bot \ j = k)" using univalent_linorder_matrix_1 univalent_linorder_matrix_2 by auto text \ Injective matrices can then be characterised by applying converse: in each column, at most one entry may be different from \bot\. \ lemma injective_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.injective f \ (\i j k . f (j,i) \ bot \ f (k,i) \ bot \ j = k)" by (unfold matrix_stone_relation_algebra.injective_conv_univalent univalent_linorder_matrix) (simp add: conv_matrix_def) text \ Next come total matrices: each row has a \top\ entry. \ lemma total_linorder_matrix_1: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_stone_relation_algebra.total_var f" shows "\j . f (i,j) = top" proof - have "mone (i,i) \ (f \ f\<^sup>t) (i,i)" using assms less_eq_matrix_def by blast hence "top = (f \ f\<^sup>t) (i,i)" by (simp add: one_matrix_def top.extremum_unique) also have "... = (\\<^sub>j f (i,j) * (f\<^sup>t) (j,i))" by (simp add: times_matrix_def) also have "... = (\\<^sub>j f (i,j) * f (i,j))" by (simp add: conv_matrix_def) also have "... = (\\<^sub>j f (i,j))" by simp finally show ?thesis by (metis linorder_top_finite_sup) qed lemma total_linorder_matrix_2: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "\i . \j . f (i,j) = top" shows "matrix_stone_relation_algebra.total_var f" proof (unfold less_eq_matrix_def, rule allI, rule prod_cases) fix j k show "mone (j,k) \ (f \ f\<^sup>t) (j,k)" proof (cases "j = k") assume "j = k" hence "(\\<^sub>i f (j,i) * (f\<^sup>t) (i,k)) = (\\<^sub>i f (j,i))" by (simp add: conv_matrix_def) also have "... = top" by (metis (no_types) assms comp_inf.ub_sum sup.absorb2 sup_top_left) finally show ?thesis by (simp add: times_matrix_def) next assume "j \ k" thus ?thesis by (simp add: one_matrix_def) qed qed lemma total_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_bounded_idempotent_semiring.total f \ (\i . \j . f (i,j) = top)" using total_linorder_matrix_1 total_linorder_matrix_2 matrix_stone_relation_algebra.total_var by auto text \ Surjective matrices are again characterised by applying converse: each column has a \top\ entry. \ lemma surjective_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_bounded_idempotent_semiring.surjective f \ (\j . \i . f (i,j) = top)" by (unfold matrix_stone_relation_algebra.surjective_conv_total total_linorder_matrix) (simp add: conv_matrix_def) text \ A mapping therefore means that each row has exactly one \top\ entry and all others are \bot\. \ lemma mapping_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.mapping f \ (\i . \j . f (i,j) = top \ (\k . j \ k \ f (i,k) = bot))" by (unfold total_linorder_matrix univalent_linorder_matrix) (metis (mono_tags, opaque_lifting) comp_inf.mult_1_right comp_inf.mult_right_zero) lemma mapping_linorder_matrix_unique: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.mapping f \ (\i . \!j . f (i,j) = top \ (\k . j \ k \ f (i,k) = bot))" apply (unfold mapping_linorder_matrix) using bot_not_top by auto text \ Conversely, bijective means that each column has exactly one \top\ entry and all others are \bot\. \ lemma bijective_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.bijective f \ (\j . \i . f (i,j) = top \ (\k . i \ k \ f (k,j) = bot))" by (unfold matrix_stone_relation_algebra.bijective_conv_mapping mapping_linorder_matrix) (simp add: conv_matrix_def) lemma bijective_linorder_matrix_unique: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.bijective f \ (\j . \!i . f (i,j) = top \ (\k . i \ k \ f (k,j) = bot))" by (unfold matrix_stone_relation_algebra.bijective_conv_mapping mapping_linorder_matrix_unique) (simp add: conv_matrix_def) text \ We derive algebraic characterisations of matrices in which each row has an entry that is different from \bot\. \ lemma pp_total_linorder_matrix_1: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" assumes "\(f \ mtop) = mbot" shows "\j . f (i,j) \ bot" proof - have "\(\j . f (i,j) \ bot) \ \(f \ mtop) \ mbot" proof - assume "\(\j . f (i,j) \ bot)" hence "top = -(f \ mtop) (i,i)" by (simp add: comp_top_linorder_matrix linorder_finite_sup_selective) also have "... = (\(f \ mtop)) (i,i)" by (simp add: uminus_matrix_def) finally show "\(f \ mtop) \ mbot" by (metis bot_matrix_def bot_not_top) qed thus ?thesis using assms by blast qed lemma pp_total_linorder_matrix_2: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "\i . \j . f (i,j) \ bot" shows "\(f \ mtop) = mbot" proof (rule ext, rule prod_cases) fix i j have "(\(f \ mtop)) (i,j) = -(\\<^sub>k f (i,k))" by (simp add: comp_top_linorder_matrix uminus_matrix_def) also have "... = bot" by (metis antisym assms bot.extremum comp_inf.ub_sum uminus_def) finally show "(\(f \ mtop)) (i,j) = mbot (i,j)" by (simp add: bot_matrix_def) qed lemma pp_total_linorder_matrix_3: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "\(f \ mtop) = mbot \ (\i . \j . f (i,j) \ bot)" using pp_total_linorder_matrix_1 pp_total_linorder_matrix_2 by auto lemma pp_total_linorder_matrix: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_bounded_idempotent_semiring.total (\\f) \ (\i . \j . f (i,j) \ bot)" using matrix_stone_relation_algebra.pp_total pp_total_linorder_matrix_1 pp_total_linorder_matrix_2 by auto lemma pp_mapping_linorder_matrix: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.pp_mapping f \ (\i . \j . f (i,j) \ bot \ (\k . j \ k \ f (i,k) = bot))" by (metis (mono_tags, opaque_lifting) pp_total_linorder_matrix univalent_linorder_matrix_1 univalent_linorder_matrix_2) lemma pp_mapping_linorder_matrix_unique: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.pp_mapping f \ (\i . \!j . f (i,j) \ bot \ (\k . j \ k \ f (i,k) = bot))" apply (rule iffI) using pp_mapping_linorder_matrix apply blast by (metis pp_total_linorder_matrix univalent_linorder_matrix) text \ Next follow matrices in which each column has an entry that is different from \bot\. \ lemma pp_surjective_linorder_matrix_1: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "\(mtop \ f) = mbot \ (\j . \i . f (i,j) \ bot)" proof - have "\(mtop \ f) = mbot \ (\(mtop \ f))\<^sup>t = mbot\<^sup>t" by (metis matrix_stone_relation_algebra.conv_involutive) also have "... \ \(f\<^sup>t \ mtop) = mbot" by (simp add: matrix_stone_relation_algebra.conv_complement matrix_stone_relation_algebra.conv_dist_comp) also have "... \ (\i . \j . (f\<^sup>t) (i,j) \ bot)" using pp_total_linorder_matrix_3 by auto also have "... \ (\j . \i . f (i,j) \ bot)" by (simp add: conv_matrix_def) finally show ?thesis . qed lemma pp_surjective_linorder_matrix: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_bounded_idempotent_semiring.surjective (\\f) \ (\j . \i . f (i,j) \ bot)" using matrix_stone_relation_algebra.pp_surjective pp_surjective_linorder_matrix_1 by auto lemma pp_bijective_linorder_matrix: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.pp_bijective f \ (\j . \i . f (i,j) \ bot \ (\k . i \ k \ f (k,j) = bot))" by (unfold matrix_stone_relation_algebra.pp_bijective_conv_mapping pp_mapping_linorder_matrix) (simp add: conv_matrix_def) lemma pp_bijective_linorder_matrix_unique: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.pp_bijective f \ (\j . \!i . f (i,j) \ bot \ (\k . i \ k \ f (k,j) = bot))" by (unfold matrix_stone_relation_algebra.pp_bijective_conv_mapping pp_mapping_linorder_matrix_unique) (simp add: conv_matrix_def) text \ The regular matrices are those which contain only \bot\ or \top\ entries. \ lemma regular_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_p_algebra.regular f \ (\e . f e = bot \ f e = top)" proof - have "matrix_p_algebra.regular f \ (\\f = f)" by auto also have "... \ (\e . --f e = f e)" by (metis uminus_matrix_def ext) also have "... \ (\e . f e = bot \ f e = top)" by force finally show ?thesis . qed text \ Vectors are precisely the row-constant matrices. \ lemma vector_linorder_matrix_0: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_bounded_idempotent_semiring.vector f" shows "f (i,j) = (\\<^sub>k f (i,k))" by (metis assms comp_top_linorder_matrix) lemma vector_linorder_matrix_1: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_bounded_idempotent_semiring.vector f" shows "f (i,j) = f (i,k)" by (metis assms vector_linorder_matrix_0) lemma vector_linorder_matrix_2: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "\i j k . f (i,j) = f (i,k)" shows "matrix_bounded_idempotent_semiring.vector f" proof (rule ext, rule prod_cases) fix i j have "(f \ mtop) (i,j) = (\\<^sub>k f (i,k))" by (simp add: comp_top_linorder_matrix) also have "... = f (i,j)" by (metis assms linorder_finite_sup_selective) finally show "(f \ mtop) (i,j) = f (i,j)" . qed lemma vector_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_bounded_idempotent_semiring.vector f \ (\i j k . f (i,j) = f (i,k))" using vector_linorder_matrix_1 vector_linorder_matrix_2 by auto text \ Hence covectors are precisely the column-constant matrices. \ lemma covector_linorder_matrix_0: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_bounded_idempotent_semiring.covector f" shows "f (i,j) = (\\<^sub>k f (k,j))" by (metis assms top_comp_linorder_matrix) lemma covector_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_bounded_idempotent_semiring.covector f \ (\i j k . f (i,j) = f (k,j))" by (unfold matrix_stone_relation_algebra.covector_conv_vector vector_linorder_matrix) (metis (no_types, lifting) case_prod_conv conv_matrix_def conv_def) text \ A point is a matrix that has exactly one row, which is constant \top\, and all other rows are constant \bot\. \ lemma point_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.point f \ (\i . \j . f (i,j) = top \ (\k . i \ k \ f (k,j) = bot))" apply (unfold vector_linorder_matrix bijective_linorder_matrix) apply (rule iffI) apply metis by metis lemma point_linorder_matrix_unique: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.point f \ (\!i . \j . f (i,j) = top \ (\k . i \ k \ f (k,j) = bot))" apply (unfold vector_linorder_matrix bijective_linorder_matrix) apply (rule iffI) apply (metis bot_not_top) by metis lemma pp_point_linorder_matrix: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.pp_point f \ (\i . \j . f (i,j) \ bot \ (\k . f (i,j) = f (i,k)) \ (\k . i \ k \ f (k,j) = bot))" apply (unfold vector_linorder_matrix pp_bijective_linorder_matrix) apply (rule iffI) apply metis by metis lemma pp_point_linorder_matrix_unique: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.pp_point f \ (\!i . \j . f (i,j) \ bot \ (\k . f (i,j) = f (i,k)) \ (\k . i \ k \ f (k,j) = bot))" apply (unfold vector_linorder_matrix pp_bijective_linorder_matrix) apply (rule iffI) apply metis by metis text \ An arc is a matrix that has exactly one \top\ entry and all other entries are \bot\. \ lemma arc_linorder_matrix_1: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" assumes "matrix_stone_relation_algebra.arc f" shows "\e . f e = top \ (\d . e \ d \ f d = bot)" proof - have "matrix_stone_relation_algebra.point (f \ mtop)" by (simp add: assms matrix_bounded_idempotent_semiring.vector_mult_closed) from this obtain i where 1: "\j . (f \ mtop) (i,j) = top \ (\k . i \ k \ (f \ mtop) (k,j) = bot)" using point_linorder_matrix by blast have "matrix_stone_relation_algebra.point (f\<^sup>t \ mtop)" by (simp add: assms matrix_bounded_idempotent_semiring.vector_mult_closed) from this obtain j where "\i . (f\<^sup>t \ mtop) (j,i) = top \ (\k . j \ k \ (f\<^sup>t \ mtop) (k,i) = bot)" using point_linorder_matrix by blast hence 2: "\i . (mtop \ f) (i,j) = top \ (\k . j \ k \ (mtop \ f) (i,k) = bot)" by (metis (no_types) old.prod.case conv_matrix_def conv_def matrix_stone_relation_algebra.conv_dist_comp matrix_stone_relation_algebra.conv_top) have 3: "\i k . j \ k \ f (i,k) = bot" proof (intro allI, rule impI) fix i k assume "j \ k" hence "(\\<^sub>l f (l,k)) = bot" using 2 by (simp add: top_comp_linorder_matrix) thus "f (i,k) = bot" by (metis bot.extremum_uniqueI comp_inf.ub_sum) qed have "(\\<^sub>k f (i,k)) = top" using 1 by (simp add: comp_top_linorder_matrix) hence 4: "f (i,j) = top" using 3 by (metis bot_not_top linorder_finite_sup_selective) have "\k l . k \ i \ l \ j \ f (k,l) = bot" proof (intro allI, unfold imp_disjL, rule conjI) fix k l show "k \ i \ f (k,l) = bot" proof assume "k \ i" hence "(\\<^sub>m f (k,m)) = bot" using 1 by (simp add: comp_top_linorder_matrix) thus "f (k,l) = bot" by (metis bot.extremum_uniqueI comp_inf.ub_sum) qed show "l \ j \ f (k,l) = bot" using 3 by simp qed thus ?thesis using 4 by (metis old.prod.exhaust) qed lemma pp_arc_linorder_matrix_2: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "\e . f e \ bot \ (\d . e \ d \ f d = bot)" shows "matrix_stone_relation_algebra.pp_arc f" proof (unfold matrix_stone_relation_algebra.pp_arc_expanded, intro conjI) show "f \ mtop \ f\<^sup>t \ mone" proof (unfold less_eq_matrix_def, rule allI, rule prod_cases) fix i j show "(f \ mtop \ f\<^sup>t) (i,j) \ mone (i,j)" proof (cases "i = j") assume "i = j" thus ?thesis by (simp add: one_matrix_def) next assume "i \ j" hence 1: "\k l . f (i,k) * f (j,l) = bot" by (metis assms Pair_inject semiring.mult_not_zero) have "(f \ mtop \ f\<^sup>t) (i,j) = (\\<^sub>l (f \ mtop) (i,l) * (f\<^sup>t) (l,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>l (f \ mtop) (i,l) * f (j,l))" by (simp add: conv_matrix_def) also have "... = (\\<^sub>l (\\<^sub>k f (i,k)) * f (j,l))" by (simp add: comp_top_linorder_matrix) also have "... = (\\<^sub>l \\<^sub>k f (i,k) * f (j,l))" by (metis comp_right_dist_sum) also have "... = bot" using 1 linorder_finite_sup_selective by simp finally show ?thesis by simp qed qed next show "f\<^sup>t \ mtop \ f \ mone" proof (unfold less_eq_matrix_def, rule allI, rule prod_cases) fix i j show "(f\<^sup>t \ mtop \ f) (i,j) \ mone (i,j)" proof (cases "i = j") assume "i = j" thus ?thesis by (simp add: one_matrix_def) next assume "i \ j" hence 2: "\k l . f (k,i) * f (l,j) = bot" by (metis assms Pair_inject semiring.mult_not_zero) have "(f\<^sup>t \ mtop \ f) (i,j) = (\\<^sub>l (f\<^sup>t \ mtop) (i,l) * f (l,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>l (\\<^sub>k (f\<^sup>t) (i,k)) * f (l,j))" by (simp add: comp_top_linorder_matrix) also have "... = (\\<^sub>l (\\<^sub>k f (k,i)) * f (l,j))" by (simp add: conv_matrix_def) also have "... = (\\<^sub>l \\<^sub>k f (k,i) * f (l,j))" by (metis comp_right_dist_sum) also have "... = bot" using 2 linorder_finite_sup_selective by simp finally show ?thesis by simp qed qed next show "mtop \ \\f \ mtop = mtop" proof (rule ext, rule prod_cases) fix i j from assms obtain k l where "f (k,l) \ bot" using prod.collapse by auto hence "top = --f (k,l)" by simp also have "... \ (\\<^sub>k --f (k,l))" using comp_inf.ub_sum by metis also have "... \ (\\<^sub>l \\<^sub>k --f (k,l))" using comp_inf.ub_sum by simp finally have 3: "top \ (\\<^sub>l \\<^sub>k --f (k,l))" by simp have "(mtop \ \\f \ mtop) (i,j) = (\\<^sub>l (\\<^sub>k top * --f (k,l)) * top)" by (simp add: times_matrix_def top_matrix_def uminus_matrix_def) also have "... = (\\<^sub>l \\<^sub>k --f (k,l))" by (metis (no_types, lifting) sup_monoid.sum.cong comp_inf.mult_1_left times_inf comp_inf.mult_1_right) also have "... = top" using 3 top.extremum_unique by blast finally show "(mtop \ \\f \ mtop) (i,j) = mtop (i,j)" by (simp add: top_matrix_def) qed qed lemma arc_linorder_matrix_2: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" assumes "\e . f e = top \ (\d . e \ d \ f d = bot)" shows "matrix_stone_relation_algebra.arc f" proof (unfold matrix_stone_relation_algebra.arc_expanded, intro conjI) show "f \ mtop \ f\<^sup>t \ mone" by (metis (no_types, lifting) assms bot_not_top matrix_stone_relation_algebra.pp_arc_expanded pp_arc_linorder_matrix_2) next show "f\<^sup>t \ mtop \ f \ mone" by (metis (no_types, lifting) assms bot_not_top matrix_stone_relation_algebra.pp_arc_expanded pp_arc_linorder_matrix_2) next show "mtop \ f \ mtop = mtop" proof (rule ext, rule prod_cases) fix i j from assms obtain k l where "f (k,l) = top" using prod.collapse by auto hence "(\\<^sub>k f (k,l)) = top" by (metis (mono_tags) comp_inf.ub_sum top_unique) hence 3: "top \ (\\<^sub>l \\<^sub>k f (k,l))" by (metis (no_types) comp_inf.ub_sum) have "(mtop \ f \ mtop) (i,j) = (\\<^sub>l (\\<^sub>k top * f (k,l)) * top)" by (simp add: times_matrix_def top_matrix_def) also have "... = (\\<^sub>l \\<^sub>k f (k,l))" by (metis (no_types, lifting) sup_monoid.sum.cong comp_inf.mult_1_left times_inf comp_inf.mult_1_right) also have "... = top" using 3 top.extremum_unique by blast finally show "(mtop \ f \ mtop) (i,j) = mtop (i,j)" by (simp add: top_matrix_def) qed qed lemma arc_linorder_matrix: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.arc f \ (\e . f e = top \ (\d . e \ d \ f d = bot))" using arc_linorder_matrix_1 arc_linorder_matrix_2 by blast lemma arc_linorder_matrix_unique: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.arc f \ (\!e . f e = top \ (\d . e \ d \ f d = bot))" apply (rule iffI) apply (metis (no_types, opaque_lifting) arc_linorder_matrix bot_not_top) using arc_linorder_matrix by blast lemma pp_arc_linorder_matrix_1: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" assumes "matrix_stone_relation_algebra.pp_arc f" shows "\e . f e \ bot \ (\d . e \ d \ f d = bot)" proof - have "matrix_stone_relation_algebra.pp_point (f \ mtop)" by (simp add: assms matrix_bounded_idempotent_semiring.vector_mult_closed) from this obtain i where 1: "\j . (f \ mtop) (i,j) \ bot \ (\k . (f \ mtop) (i,j) = (f \ mtop) (i,k)) \ (\k . i \ k \ (f \ mtop) (k,j) = bot)" by (metis pp_point_linorder_matrix) have "matrix_stone_relation_algebra.pp_point (f\<^sup>t \ mtop)" by (simp add: assms matrix_bounded_idempotent_semiring.vector_mult_closed) from this obtain j where "\i . (f\<^sup>t \ mtop) (j,i) \ bot \ (\k . (f\<^sup>t \ mtop) (j,i) = (f\<^sup>t \ mtop) (j,k)) \ (\k . j \ k \ (f\<^sup>t \ mtop) (k,i) = bot)" by (metis pp_point_linorder_matrix) hence 2: "\i . (mtop \ f) (i,j) \ bot \ (\k . (mtop \ f) (i,j) = (mtop \ f) (k,j)) \ (\k . j \ k \ (mtop \ f) (i,k) = bot)" by (metis (no_types) old.prod.case conv_matrix_def conv_def matrix_stone_relation_algebra.conv_dist_comp matrix_stone_relation_algebra.conv_top) have 3: "\i k . j \ k \ f (i,k) = bot" proof (intro allI, rule impI) fix i k assume "j \ k" hence "(\\<^sub>l f (l,k)) = bot" using 2 by (simp add: top_comp_linorder_matrix) thus "f (i,k) = bot" by (metis bot.extremum_uniqueI comp_inf.ub_sum) qed have "(\\<^sub>k f (i,k)) \ bot" using 1 by (simp add: comp_top_linorder_matrix) hence 4: "f (i,j) \ bot" using 3 by (metis linorder_finite_sup_selective) have "\k l . k \ i \ l \ j \ f (k,l) = bot" proof (intro allI, unfold imp_disjL, rule conjI) fix k l show "k \ i \ f (k,l) = bot" proof assume "k \ i" hence "(\\<^sub>m f (k,m)) = bot" using 1 by (simp add: comp_top_linorder_matrix) thus "f (k,l) = bot" by (metis bot.extremum_uniqueI comp_inf.ub_sum) qed show "l \ j \ f (k,l) = bot" using 3 by simp qed thus ?thesis using 4 by (metis old.prod.exhaust) qed lemma pp_arc_linorder_matrix: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.pp_arc f \ (\e . f e \ bot \ (\d . e \ d \ f d = bot))" using pp_arc_linorder_matrix_1 pp_arc_linorder_matrix_2 by blast lemma pp_arc_linorder_matrix_unique: fixes f :: "('a::finite,'b::non_trivial_linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.pp_arc f \ (\!e . f e \ bot \ (\d . e \ d \ f d = bot))" apply (rule iffI) apply (metis (no_types, opaque_lifting) pp_arc_linorder_matrix) using pp_arc_linorder_matrix by blast text \ Reflexive matrices are those with a constant \top\ diagonal. \ lemma reflexive_linorder_matrix_1: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_idempotent_semiring.reflexive f" shows "f (i,i) = top" proof - have "(top::'b) = mone (i,i)" by (simp add: one_matrix_def) also have "... \ f (i,i)" using assms less_eq_matrix_def by blast finally show ?thesis by (simp add: top.extremum_unique) qed lemma reflexive_linorder_matrix_2: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "\i . f (i,i) = top" shows "matrix_idempotent_semiring.reflexive f" proof (unfold less_eq_matrix_def, rule allI, rule prod_cases) fix i j show "mone (i,j) \ f (i,j)" proof (cases "i = j") assume "i = j" thus ?thesis by (simp add: assms) next assume "i \ j" hence "(bot::'b) = mone (i,j)" by (simp add: one_matrix_def) thus ?thesis by simp qed qed lemma reflexive_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_idempotent_semiring.reflexive f \ (\i . f (i,i) = top)" using reflexive_linorder_matrix_1 reflexive_linorder_matrix_2 by auto text \ Coreflexive matrices are those in which all non-diagonal entries are \bot\. \ lemma coreflexive_linorder_matrix_1: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_idempotent_semiring.coreflexive f" and "i \ j" shows "f (i,j) = bot" proof - have "f (i,j) \ mone (i,j)" using assms less_eq_matrix_def by blast also have "... = bot" by (simp add: assms one_matrix_def) finally show ?thesis by (simp add: bot.extremum_unique) qed lemma coreflexive_linorder_matrix_2: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "\i j . i \ j \ f (i,j) = bot" shows "matrix_idempotent_semiring.coreflexive f" proof (unfold less_eq_matrix_def, rule allI, rule prod_cases) fix i j show "f (i,j) \ mone (i,j)" proof (cases "i = j") assume "i = j" hence "(top::'b) = mone (i,j)" by (simp add: one_matrix_def) thus ?thesis by simp next assume "i \ j" thus ?thesis by (simp add: assms) qed qed lemma coreflexive_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_idempotent_semiring.coreflexive f \ (\i j . i \ j \ f (i,j) = bot)" using coreflexive_linorder_matrix_1 coreflexive_linorder_matrix_2 by auto text \ Irreflexive matrices are those with a constant \bot\ diagonal. \ lemma irreflexive_linorder_matrix_1: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_stone_relation_algebra.irreflexive f" shows "f (i,i) = bot" proof - have "(top::'b) = mone (i,i)" by (simp add: one_matrix_def) hence "(bot::'b) = (\mone) (i,i)" by (simp add: uminus_matrix_def) hence "f (i,i) \ bot" by (metis assms less_eq_matrix_def) thus ?thesis by (simp add: bot.extremum_unique) qed lemma irreflexive_linorder_matrix_2: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "\i . f (i,i) = bot" shows "matrix_stone_relation_algebra.irreflexive f" proof (unfold less_eq_matrix_def, rule allI, rule prod_cases) fix i j show "f (i,j) \ (\mone) (i,j)" proof (cases "i = j") assume "i = j" thus ?thesis by (simp add: assms) next assume "i \ j" hence "(bot::'b) = mone (i,j)" by (simp add: one_matrix_def) hence "(top::'b) = (\mone) (i,j)" by (simp add: uminus_matrix_def) thus ?thesis by simp qed qed lemma irreflexive_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.irreflexive f \ (\i . f (i,i) = bot)" using irreflexive_linorder_matrix_1 irreflexive_linorder_matrix_2 by auto text \ As usual, symmetric matrices are those which do not change under transposition. \ lemma symmetric_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.symmetric f \ (\i j . f (i,j) = f (j,i))" by (metis (mono_tags, lifting) case_prod_conv cond_case_prod_eta conv_matrix_def conv_def) text \ Antisymmetric matrices are characterised as follows: each entry not on the diagonal or its mirror entry across the diagonal must be \bot\. \ lemma antisymmetric_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.antisymmetric f \ (\i j . i \ j \ f (i,j) = bot \ f (j,i) = bot)" proof - have "matrix_stone_relation_algebra.antisymmetric f \ (\i j . i \ j \ f (i,j) \ f (j,i) \ bot)" by (simp add: conv_matrix_def inf_matrix_def less_eq_matrix_def one_matrix_def) thus ?thesis by (metis (no_types, opaque_lifting) inf.absorb_iff1 inf.cobounded1 inf_bot_right inf_dense) qed text \ For asymmetric matrices the diagonal is included: each entry or its mirror entry across the diagonal must be \bot\. \ lemma asymmetric_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_stone_relation_algebra.asymmetric f \ (\i j . f (i,j) = bot \ f (j,i) = bot)" proof - have "matrix_stone_relation_algebra.asymmetric f \ (\i j . f (i,j) \ f (j,i) \ bot)" apply (unfold conv_matrix_def inf_matrix_def conv_def id_def bot_matrix_def) by (metis (mono_tags, lifting) bot.extremum bot.extremum_uniqueI case_prod_conv old.prod.exhaust) thus ?thesis by (metis (no_types, opaque_lifting) inf.absorb_iff1 inf.cobounded1 inf_bot_right inf_dense) qed text \ In a transitive matrix, the weight of one of the edges on an indirect route must be below the weight of the direct edge. \ lemma transitive_linorder_matrix: fixes f :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" shows "matrix_idempotent_semiring.transitive f \ (\i j k . f (i,k) \ f (i,j) \ f (k,j) \ f (i,j))" proof - have "matrix_idempotent_semiring.transitive f \ (\i j . (\\<^sub>k f (i,k) * f (k,j)) \ f (i,j))" by (simp add: times_matrix_def less_eq_matrix_def) also have "... \ (\i j k . f (i,k) * f (k,j) \ f (i,j))" by (simp add: lub_sum_iff) also have "... \ (\i j k . f (i,k) \ f (i,j) \ f (k,j) \ f (i,j))" using inf_less_eq by fastforce finally show ?thesis . qed text \ We finally show the effect of composing with a coreflexive (test) from the left and from the right. This amounts to a restriction of each row or column to the entry on the diagonal of the coreflexive. In this case, restrictions are formed by meets. \ lemma coreflexive_comp_linorder_matrix: fixes f g :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_idempotent_semiring.coreflexive f" shows "(f \ g) (i,j) = f (i,i) \ g (i,j)" proof - have 1: "\k . i \ k \ f (i,k) = bot" using assms coreflexive_linorder_matrix by auto have "(\\<^sub>k f (i,k)) = f (i,i) \ (\\<^bsub>k\UNIV-{i}\<^esub> f (i,k))" by (metis (no_types) UNIV_def brouwer.inf_bot_right finite_UNIV insert_def sup_monoid.sum.insert_remove) hence 2: "(\\<^sub>k f (i,k)) = f (i,i)" using 1 by (metis (no_types) linorder_finite_sup_selective sup_not_bot) have "(f \ g) (i,j) = (f \ mtop \ g) (i,j)" by (metis assms matrix_stone_relation_algebra.coreflexive_comp_top_inf) also have "... = (\\<^sub>k f (i,k)) \ g (i,j)" by (metis inf_matrix_def comp_top_linorder_matrix) finally show ?thesis using 2 by simp qed lemma comp_coreflexive_linorder_matrix: fixes f g :: "('a::finite,'b::linorder_stone_relation_algebra_expansion) square" assumes "matrix_idempotent_semiring.coreflexive g" shows "(f \ g) (i,j) = f (i,j) \ g (j,j)" proof - have "(f \ g) (i,j) = ((f \ g)\<^sup>t) (j,i)" by (simp add: conv_matrix_def) also have "... = (g \ f\<^sup>t) (j,i)" by (simp add: assms matrix_stone_relation_algebra.conv_dist_comp matrix_stone_relation_algebra.coreflexive_symmetric) also have "... = g (j,j) \ (f\<^sup>t) (j,i)" by (simp add: assms coreflexive_comp_linorder_matrix) also have "... = f (i,j) \ g (j,j)" by (metis (no_types, lifting) conv_def old.prod.case conv_matrix_def inf_commute) finally show ?thesis . qed end - diff --git a/thys/Stone_Relation_Algebras/Matrix_Relation_Algebras.thy b/thys/Stone_Relation_Algebras/Matrix_Relation_Algebras.thy --- a/thys/Stone_Relation_Algebras/Matrix_Relation_Algebras.thy +++ b/thys/Stone_Relation_Algebras/Matrix_Relation_Algebras.thy @@ -1,613 +1,613 @@ (* Title: Matrix Relation Algebras Author: Walter Guttmann Maintainer: Walter Guttmann *) 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,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" ("(\\<^sub>_ _)" [0,10] 10) "_sum_sup_monoid_bounded" :: "idt \ 'b set \ 'a::bounded_semilattice_sup_bot \ 'a" ("(\\<^bsub>_\_\<^esub> _)" [0,51,10] 10) translations "\\<^sub>x t" => "XCONST sup_monoid.sum (\x . t) { x . CONST True }" "\\<^bsub>x\X\<^esub> 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 (\\<^bsub>i\I\<^esub> f i) (\\<^bsub>i\I\<^esub> g i) \ P (f j \ (\\<^bsub>i\I\<^esub> f i)) (g j \ (\\<^bsub>i\I\<^esub> g i))" shows "P (\\<^sub>k f k) (\\<^sub>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 (\\<^bsub>i\I\<^esub> f i) (\\<^bsub>i\I\<^esub> g i) \ P (f j \ (\\<^bsub>i\I\<^esub> f i)) (g j \ (\\<^bsub>i\I\<^esub> g i))" shows "P (\\<^sub>k f k) (\\<^sub>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 "(\\<^sub>k f k * x) = (\\<^sub>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 "(\\<^sub>k x * f k) = x * (\\<^sub>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) \ (\\<^sub>k f k) \ (\\<^sub>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 \ (\\<^sub>k f k)" proof - have "i \ { k . True }" by simp thus "f i \ (\\<^sub>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 "(\\<^sub>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) \ (\\<^sub>k f k) \ x" using order.trans ub_sum lub_sum by blast 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 "(\\<^sub>k (f k)\<^sup>T) = (\\<^sub>k f k)\<^sup>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 "(\\<^sub>k --f k) = --(\\<^sub>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 "(\\<^sub>k f k \ x) = (\\<^sub>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) . \\<^sub>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" ("_\<^sup>t" [100] 100) where "f\<^sup>t = (\(i,j) . (f (j,i))\<^sup>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. \ interpretation matrix_order: order where less_eq = less_eq_matrix and less = "less_matrix :: ('a,'b::order) square \ ('a,'b) square \ bool" apply unfold_locales apply (simp add: less_matrix_def) apply (simp add: less_eq_matrix_def) apply (meson less_eq_matrix_def order_trans) by (meson less_eq_matrix_def antisym ext) interpretation matrix_semilattice_sup: semilattice_sup where sup = sup_matrix and less_eq = less_eq_matrix and less = "less_matrix :: ('a,'b::semilattice_sup) square \ ('a,'b) square \ bool" apply unfold_locales apply (simp add: sup_matrix_def less_eq_matrix_def) apply (simp add: sup_matrix_def less_eq_matrix_def) by (simp add: sup_matrix_def less_eq_matrix_def) interpretation matrix_semilattice_inf: semilattice_inf where inf = inf_matrix and less_eq = less_eq_matrix and less = "less_matrix :: ('a,'b::semilattice_inf) square \ ('a,'b) square \ bool" apply unfold_locales apply (simp add: inf_matrix_def less_eq_matrix_def) apply (simp add: inf_matrix_def less_eq_matrix_def) by (simp add: inf_matrix_def less_eq_matrix_def) interpretation matrix_bounded_semilattice_sup_bot: bounded_semilattice_sup_bot where sup = sup_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a,'b::bounded_semilattice_sup_bot) square" apply unfold_locales by (simp add: bot_matrix_def less_eq_matrix_def) interpretation matrix_bounded_semilattice_inf_top: bounded_semilattice_inf_top where inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and top = "top_matrix :: ('a,'b::bounded_semilattice_inf_top) square" apply unfold_locales by (simp add: less_eq_matrix_def top_matrix_def) interpretation matrix_lattice: lattice where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = "less_matrix :: ('a,'b::lattice) square \ ('a,'b) square \ bool" .. interpretation matrix_distrib_lattice: distrib_lattice where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = "less_matrix :: ('a,'b::distrib_lattice) square \ ('a,'b) square \ bool" apply unfold_locales by (simp add: sup_inf_distrib1 sup_matrix_def inf_matrix_def) interpretation matrix_bounded_lattice: bounded_lattice where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a,'b::bounded_lattice) square" and top = top_matrix .. interpretation matrix_bounded_distrib_lattice: bounded_distrib_lattice where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a,'b::bounded_distrib_lattice) square" and top = top_matrix .. interpretation matrix_p_algebra: p_algebra where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a,'b::p_algebra) square" and top = top_matrix and uminus = uminus_matrix apply unfold_locales apply (unfold inf_matrix_def bot_matrix_def less_eq_matrix_def uminus_matrix_def) by (meson pseudo_complement) interpretation matrix_pd_algebra: pd_algebra where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a,'b::pd_algebra) square" and top = top_matrix and uminus = uminus_matrix .. text \ In particular, matrices over Stone algebras form a Stone algebra. \ interpretation matrix_stone_algebra: stone_algebra where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a,'b::stone_algebra) square" and top = top_matrix and uminus = uminus_matrix by unfold_locales (simp add: sup_matrix_def uminus_matrix_def top_matrix_def) interpretation matrix_heyting_stone_algebra: heyting_stone_algebra where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a,'b::heyting_stone_algebra) square" and top = top_matrix and uminus = uminus_matrix and implies = implies_matrix apply unfold_locales apply (unfold inf_matrix_def sup_matrix_def bot_matrix_def top_matrix_def less_eq_matrix_def uminus_matrix_def implies_matrix_def) apply (simp add: implies_galois) apply (simp add: uminus_eq) by simp -interpretation matrix_boolean_algebra: boolean_algebra where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a,'b::boolean_algebra) square" and top = top_matrix and uminus = uminus_matrix and minus = minus_matrix +interpretation matrix_boolean_algebra: Lattices.boolean_algebra where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a,'b::boolean_algebra) square" and top = top_matrix and uminus = uminus_matrix and minus = minus_matrix apply unfold_locales apply simp apply (simp add: sup_matrix_def uminus_matrix_def top_matrix_def) by (simp add: inf_matrix_def uminus_matrix_def minus_matrix_def) subsection \Semirings\ text \ Next, we lift the semiring structure. Because of composition, this requires a restriction to finite matrices. \ interpretation matrix_monoid: monoid_mult where times = times_matrix and one = "one_matrix :: ('a::finite,'b::idempotent_semiring) square" proof fix f g h :: "('a,'b) square" show "(f \ g) \ h = f \ (g \ h)" proof (rule ext, rule prod_cases) fix i j have "((f \ g) \ h) (i,j) = (\\<^sub>l (f \ g) (i,l) * h (l,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>l (\\<^sub>k f (i,k) * g (k,l)) * h (l,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>l \\<^sub>k (f (i,k) * g (k,l)) * h (l,j))" by (metis (no_types) comp_right_dist_sum) also have "... = (\\<^sub>l \\<^sub>k f (i,k) * (g (k,l) * h (l,j)))" by (simp add: mult.assoc) also have "... = (\\<^sub>k \\<^sub>l f (i,k) * (g (k,l) * h (l,j)))" using sup_monoid.sum.swap by auto also have "... = (\\<^sub>k f (i,k) * (\\<^sub>l g (k,l) * h (l,j)))" by (metis (no_types) comp_left_dist_sum) also have "... = (\\<^sub>k f (i,k) * (g \ h) (k,j))" by (simp add: times_matrix_def) also have "... = (f \ (g \ h)) (i,j)" by (simp add: times_matrix_def) finally show "((f \ g) \ h) (i,j) = (f \ (g \ h)) (i,j)" . qed next fix f :: "('a,'b) square" show "mone \ f = f" proof (rule ext, rule prod_cases) fix i j have "(mone \ f) (i,j) = (\\<^sub>k mone (i,k) * f (k,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>k (if i = k then 1 else bot) * f (k,j))" by (simp add: one_matrix_def) also have "... = (\\<^sub>k if i = k then 1 * f (k,j) else bot * f (k,j))" by (metis (full_types, opaque_lifting)) also have "... = (\\<^sub>k if i = k then f (k,j) else bot)" by (meson mult_left_one mult_left_zero) also have "... = f (i,j)" by simp finally show "(mone \ f) (i,j) = f (i,j)" . qed next fix f :: "('a,'b) square" show "f \ mone = f" proof (rule ext, rule prod_cases) fix i j have "(f \ mone) (i,j) = (\\<^sub>k f (i,k) * mone (k,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>k f (i,k) * (if k = j then 1 else bot))" by (simp add: one_matrix_def) also have "... = (\\<^sub>k if k = j then f (i,k) * 1 else f (i,k) * bot)" by (metis (full_types, opaque_lifting)) also have "... = (\\<^sub>k if k = j then f (i,k) else bot)" by (meson mult.right_neutral semiring.mult_zero_right) also have "... = f (i,j)" by simp finally show "(f \ mone) (i,j) = f (i,j)" . qed qed interpretation matrix_idempotent_semiring: idempotent_semiring where sup = sup_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a::finite,'b::idempotent_semiring) square" and one = one_matrix and times = times_matrix proof fix f g h :: "('a,'b) square" show "f \ g \ f \ h \ f \ (g \ h)" proof (unfold less_eq_matrix_def, rule allI, rule prod_cases) fix i j have "(f \ g \ f \ h) (i,j) = (f \ g) (i,j) \ (f \ h) (i,j)" by (simp add: sup_matrix_def) also have "... = (\\<^sub>k f (i,k) * g (k,j)) \ (\\<^sub>k f (i,k) * h (k,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>k f (i,k) * g (k,j) \ f (i,k) * h (k,j))" by (simp add: sup_monoid.sum.distrib) also have "... = (\\<^sub>k f (i,k) * (g (k,j) \ h (k,j)))" by (simp add: mult_left_dist_sup) also have "... = (\\<^sub>k f (i,k) * (g \ h) (k,j))" by (simp add: sup_matrix_def) also have "... = (f \ (g \ h)) (i,j)" by (simp add: times_matrix_def) finally show "(f \ g \ f \ h) (i,j) \ (f \ (g \ h)) (i,j)" by simp qed next fix f g h :: "('a,'b) square" show "(f \ g) \ h = f \ h \ g \ h" proof (rule ext, rule prod_cases) fix i j have "((f \ g) \ h) (i,j) = (\\<^sub>k (f \ g) (i,k) * h (k,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>k (f (i,k) \ g (i,k)) * h (k,j))" by (simp add: sup_matrix_def) also have "... = (\\<^sub>k f (i,k) * h (k,j) \ g (i,k) * h (k,j))" by (meson mult_right_dist_sup) also have "... = (\\<^sub>k f (i,k) * h (k,j)) \ (\\<^sub>k g (i,k) * h (k,j))" by (simp add: sup_monoid.sum.distrib) also have "... = (f \ h) (i,j) \ (g \ h) (i,j)" by (simp add: times_matrix_def) also have "... = (f \ h \ g \ h) (i,j)" by (simp add: sup_matrix_def) finally show "((f \ g) \ h) (i,j) = (f \ h \ g \ h) (i,j)" . qed next fix f :: "('a,'b) square" show "mbot \ f = mbot" proof (rule ext, rule prod_cases) fix i j have "(mbot \ f) (i,j) = (\\<^sub>k mbot (i,k) * f (k,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>k bot * f (k,j))" by (simp add: bot_matrix_def) also have "... = bot" by simp also have "... = mbot (i,j)" by (simp add: bot_matrix_def) finally show "(mbot \ f) (i,j) = mbot (i,j)" . qed next fix f :: "('a,'b) square" show "mone \ f = f" by simp next fix f :: "('a,'b) square" show "f \ f \ mone" by simp next fix f g h :: "('a,'b) square" show "f \ (g \ h) = f \ g \ f \ h" proof (rule ext, rule prod_cases) fix i j have "(f \ (g \ h)) (i,j) = (\\<^sub>k f (i,k) * (g \ h) (k,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>k f (i,k) * (g (k,j) \ h (k,j)))" by (simp add: sup_matrix_def) also have "... = (\\<^sub>k f (i,k) * g (k,j) \ f (i,k) * h (k,j))" by (meson mult_left_dist_sup) also have "... = (\\<^sub>k f (i,k) * g (k,j)) \ (\\<^sub>k f (i,k) * h (k,j))" by (simp add: sup_monoid.sum.distrib) also have "... = (f \ g) (i,j) \ (f \ h) (i,j)" by (simp add: times_matrix_def) also have "... = (f \ g \ f \ h) (i,j)" by (simp add: sup_matrix_def) finally show "(f \ (g \ h)) (i,j) = (f \ g \ f \ h) (i,j)" . qed next fix f :: "('a,'b) square" show "f \ mbot = mbot" proof (rule ext, rule prod_cases) fix i j have "(f \ mbot) (i,j) = (\\<^sub>k f (i,k) * mbot (k,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>k f (i,k) * bot)" by (simp add: bot_matrix_def) also have "... = bot" by simp also have "... = mbot (i,j)" by (simp add: bot_matrix_def) finally show "(f \ mbot) (i,j) = mbot (i,j)" . qed qed interpretation matrix_bounded_idempotent_semiring: bounded_idempotent_semiring where sup = sup_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a::finite,'b::bounded_idempotent_semiring) square" and top = top_matrix and one = one_matrix and times = times_matrix proof fix f :: "('a,'b) square" show "f \ mtop = mtop" proof fix e have "(f \ mtop) e = f e \ mtop e" by (simp add: sup_matrix_def) also have "... = f e \ top" by (simp add: top_matrix_def) also have "... = top" by simp also have "... = mtop e" by (simp add: top_matrix_def) finally show "(f \ mtop) e = mtop e" . qed qed subsection \Stone Relation Algebras\ text \ Finally, we show that matrices over Stone relation algebras form a Stone relation algebra. \ interpretation matrix_stone_relation_algebra: stone_relation_algebra where sup = sup_matrix and inf = inf_matrix and less_eq = less_eq_matrix and less = less_matrix and bot = "bot_matrix :: ('a::finite,'b::stone_relation_algebra) square" and top = top_matrix and uminus = uminus_matrix and one = one_matrix and times = times_matrix and conv = conv_matrix proof fix f g h :: "('a,'b) square" show "(f \ g) \ h = f \ (g \ h)" by (simp add: matrix_monoid.mult_assoc) next fix f g h :: "('a,'b) square" show "(f \ g) \ h = f \ h \ g \ h" by (simp add: matrix_idempotent_semiring.mult_right_dist_sup) next fix f :: "('a,'b) square" show "mbot \ f = mbot" by simp next fix f :: "('a,'b) square" show "mone \ f = f" by simp next fix f :: "('a,'b) square" show "f\<^sup>t\<^sup>t = f" proof (rule ext, rule prod_cases) fix i j have "(f\<^sup>t\<^sup>t) (i,j) = ((f\<^sup>t) (j,i))\<^sup>T" by (simp add: conv_matrix_def) also have "... = f (i,j)" by (simp add: conv_matrix_def) finally show "(f\<^sup>t\<^sup>t) (i,j) = f (i,j)" . qed next fix f g :: "('a,'b) square" show "(f \ g)\<^sup>t = f\<^sup>t \ g\<^sup>t" proof (rule ext, rule prod_cases) fix i j have "((f \ g)\<^sup>t) (i,j) = ((f \ g) (j,i))\<^sup>T" by (simp add: conv_matrix_def) also have "... = (f (j,i) \ g (j,i))\<^sup>T" by (simp add: sup_matrix_def) also have "... = (f\<^sup>t) (i,j) \ (g\<^sup>t) (i,j)" by (simp add: conv_matrix_def conv_dist_sup) also have "... = (f\<^sup>t \ g\<^sup>t) (i,j)" by (simp add: sup_matrix_def) finally show "((f \ g)\<^sup>t) (i,j) = (f\<^sup>t \ g\<^sup>t) (i,j)" . qed next fix f g :: "('a,'b) square" show "(f \ g)\<^sup>t = g\<^sup>t \ f\<^sup>t" proof (rule ext, rule prod_cases) fix i j have "((f \ g)\<^sup>t) (i,j) = ((f \ g) (j,i))\<^sup>T" by (simp add: conv_matrix_def) also have "... = (\\<^sub>k f (j,k) * g (k,i))\<^sup>T" by (simp add: times_matrix_def) also have "... = (\\<^sub>k (f (j,k) * g (k,i))\<^sup>T)" by (metis (no_types) conv_dist_sum) also have "... = (\\<^sub>k (g (k,i))\<^sup>T * (f (j,k))\<^sup>T)" by (simp add: conv_dist_comp) also have "... = (\\<^sub>k (g\<^sup>t) (i,k) * (f\<^sup>t) (k,j))" by (simp add: conv_matrix_def) also have "... = (g\<^sup>t \ f\<^sup>t) (i,j)" by (simp add: times_matrix_def) finally show "((f \ g)\<^sup>t) (i,j) = (g\<^sup>t \ f\<^sup>t) (i,j)" . qed next fix f g h :: "('a,'b) square" show "(f \ g) \ h \ f \ (g \ (f\<^sup>t \ h))" proof (unfold less_eq_matrix_def, rule allI, rule prod_cases) fix i j have "((f \ g) \ h) (i,j) = (f \ g) (i,j) \ h (i,j)" by (simp add: inf_matrix_def) also have "... = (\\<^sub>k f (i,k) * g (k,j)) \ h (i,j)" by (simp add: times_matrix_def) also have "... = (\\<^sub>k f (i,k) * g (k,j) \ h (i,j))" by (metis (no_types) inf_right_dist_sum) also have "... \ (\\<^sub>k f (i,k) * (g (k,j) \ (f (i,k))\<^sup>T * h (i,j)))" by (rule leq_sum, meson dedekind_1) also have "... = (\\<^sub>k f (i,k) * (g (k,j) \ (f\<^sup>t) (k,i) * h (i,j)))" by (simp add: conv_matrix_def) also have "... \ (\\<^sub>k f (i,k) * (g (k,j) \ (\\<^sub>l (f\<^sup>t) (k,l) * h (l,j))))" by (rule leq_sum, rule allI, rule comp_right_isotone, rule inf.sup_right_isotone, rule ub_sum) also have "... = (\\<^sub>k f (i,k) * (g (k,j) \ (f\<^sup>t \ h) (k,j)))" by (simp add: times_matrix_def) also have "... = (\\<^sub>k f (i,k) * (g \ (f\<^sup>t \ h)) (k,j))" by (simp add: inf_matrix_def) also have "... = (f \ (g \ (f\<^sup>t \ h))) (i,j)" by (simp add: times_matrix_def) finally show "((f \ g) \ h) (i,j) \ (f \ (g \ (f\<^sup>t \ h))) (i,j)" . qed next fix f g :: "('a,'b) square" show "\\(f \ g) = \\f \ \\g" proof (rule ext, rule prod_cases) fix i j have "(\\(f \ g)) (i,j) = --((f \ g) (i,j))" by (simp add: uminus_matrix_def) also have "... = --(\\<^sub>k f (i,k) * g (k,j))" by (simp add: times_matrix_def) also have "... = (\\<^sub>k --(f (i,k) * g (k,j)))" by (metis (no_types) pp_dist_sum) also have "... = (\\<^sub>k --(f (i,k)) * --(g (k,j)))" by (meson pp_dist_comp) also have "... = (\\<^sub>k (\\f) (i,k) * (\\g) (k,j))" by (simp add: uminus_matrix_def) also have "... = (\\f \ \\g) (i,j)" by (simp add: times_matrix_def) finally show "(\\(f \ g)) (i,j) = (\\f \ \\g) (i,j)" . qed next let ?o = "mone :: ('a,'b) square" show "\\?o = ?o" proof (rule ext, rule prod_cases) fix i j have "(\\?o) (i,j) = --(?o (i,j))" by (simp add: uminus_matrix_def) also have "... = --(if i = j then 1 else bot)" by (simp add: one_matrix_def) also have "... = (if i = j then --1 else --bot)" by simp also have "... = (if i = j then 1 else bot)" by auto also have "... = ?o (i,j)" by (simp add: one_matrix_def) finally show "(\\?o) (i,j) = ?o (i,j)" . qed qed end diff --git a/thys/Subset_Boolean_Algebras/Subset_Boolean_Algebras.thy b/thys/Subset_Boolean_Algebras/Subset_Boolean_Algebras.thy --- a/thys/Subset_Boolean_Algebras/Subset_Boolean_Algebras.thy +++ b/thys/Subset_Boolean_Algebras/Subset_Boolean_Algebras.thy @@ -1,3608 +1,3608 @@ (* Title: Subset Boolean Algebras Authors: Walter Guttmann, Bernhard Möller Maintainer: Walter Guttmann *) theory Subset_Boolean_Algebras imports Stone_Algebras.P_Algebras begin section \Boolean Algebras\ text \ We show that Isabelle/HOL's \boolean_algebra\ class is equivalent to Huntington's axioms \cite{Huntington1933}. See \cite{WamplerDoty2016} for related results. \ subsection \Huntington's Axioms\ text \Definition 1\ class huntington = sup + uminus + assumes associative: "x \ (y \ z) = (x \ y) \ z" assumes commutative: "x \ y = y \ x" assumes huntington: "x = -(-x \ y) \ -(-x \ -y)" begin lemma top_unique: "x \ -x = y \ -y" proof - have "x \ -x = y \ -(--y \ -x) \ -(--y \ --x)" by (smt associative commutative huntington) thus ?thesis by (metis associative huntington) qed end subsection \Equivalence to \boolean_algebra\ Class\ text \Definition 2\ class extended = sup + inf + minus + uminus + bot + top + ord + assumes top_def: "top = (THE x . \y . x = y \ -y)" (* define without imposing uniqueness *) assumes bot_def: "bot = -(THE x . \y . x = y \ -y)" assumes inf_def: "x \ y = -(-x \ -y)" assumes minus_def: "x - y = -(-x \ y)" assumes less_eq_def: "x \ y \ x \ y = y" assumes less_def: "x < y \ x \ y = y \ \ (y \ x = x)" class huntington_extended = huntington + extended begin lemma top_char: "top = x \ -x" using top_def top_unique by auto lemma bot_char: "bot = -top" by (simp add: bot_def top_def) subclass boolean_algebra proof show 1: "\x y. (x < y) = (x \ y \ \ y \ x)" by (simp add: less_def less_eq_def) show 2: "\x. x \ x" proof - fix x have "x \ top = top \ --x" by (metis (full_types) associative top_char) thus "x \ x" by (metis (no_types) associative huntington less_eq_def top_char) qed show 3: "\x y z. x \ y \ y \ z \ x \ z" by (metis associative less_eq_def) show 4: "\x y. x \ y \ y \ x \ x = y" by (simp add: commutative less_eq_def) show 5: "\x y. x \ y \ x" using 2 by (metis associative huntington inf_def less_eq_def) show 6: "\x y. x \ y \ y" using 5 commutative inf_def by fastforce show 8: "\x y. x \ x \ y" using 2 associative less_eq_def by auto show 9: "\y x. y \ x \ y" using 8 commutative by fastforce show 10: "\y x z. y \ x \ z \ x \ y \ z \ x" by (metis associative less_eq_def) show 11: "\x. bot \ x" using 8 by (metis bot_char huntington top_char) show 12: "\x. x \ top" using 6 11 by (metis huntington bot_def inf_def less_eq_def top_def) show 13: "\x y z. x \ y \ z = (x \ y) \ (x \ z)" proof - have 2: "\x y z . x \ (y \ z) = (x \ y) \ z" by (simp add: associative) have 3: "\x y z . (x \ y) \ z = x \ (y \ z)" using 2 by metis have 4: "\x y . x \ y = y \ x" by (simp add: commutative) have 5: "\x y . x = - (- x \ y) \ - (- x \ - y)" by (simp add: huntington) have 6: "\x y . - (- x \ y) \ - (- x \ - y) = x" using 5 by metis have 7: "\x y . x \ y = - (- x \ - y)" by (simp add: inf_def) have 10: "\x y z . x \ (y \ z) = y \ (x \ z)" using 3 4 by metis have 11: "\x y z . - (- x \ y) \ (- (- x \ - y) \ z) = x \ z" using 3 6 by metis have 12: "\x y . - (x \ - y) \ - (- y \ - x) = y" using 4 6 by metis have 13: "\x y . - (- x \ y) \ - (- y \ - x) = x" using 4 6 by metis have 14: "\x y . - x \ - (- (- x \ y) \ - - (- x \ - y)) = - x \ y" using 6 by metis have 18: "\x y z . - (x \ - y) \ (- (- y \ - x) \ z) = y \ z" using 3 12 by metis have 20: "\x y . - (- x \ - y) \ - (y \ - x) = x" using 4 12 by metis have 21: "\x y . - (x \ - y) \ - (- x \ - y) = y" using 4 12 by metis have 22: "\x y . - x \ - (- (y \ - x) \ - - (- x \ - y)) = y \ - x" using 6 12 by metis have 23: "\x y . - x \ - (- x \ (- y \ - (y \ - x))) = y \ - x" using 3 4 6 12 by metis have 24: "\x y . - x \ - (- (- x \ - y) \ - - (- x \ y)) = - x \ - y" using 6 12 by metis have 28: "\x y . - (- x \ - y) \ - (- y \ x) = y" using 4 13 by metis have 30: "\x y . - x \ - (- y \ (- x \ - (- x \ y))) = - x \ y" using 3 4 6 13 by metis have 32: "\x y z . - (- x \ y) \ (z \ - (- y \ - x)) = z \ x" using 10 13 by metis have 37: "\x y z . - (- x \ - y) \ (- (y \ - x) \ z) = x \ z" using 3 20 by metis have 39: "\x y z . - (- x \ - y) \ (z \ - (y \ - x)) = z \ x" using 10 20 by metis have 40: "\x y z . - (x \ - y) \ (- (- x \ - y) \ z) = y \ z" using 3 21 by metis have 43: "\x y . - x \ - (- y \ (- x \ - (y \ - x))) = y \ - x" using 3 4 6 21 by metis have 47: "\x y z . - (x \ y) \ - (- (- x \ z) \ - (- (- x \ - z) \ y)) = - x \ z" using 6 11 by metis have 55: "\x y . x \ - (- y \ - - x) = y \ - (- x \ y)" using 4 11 12 by metis have 58: "\x y . x \ - (- - y \ - x) = x \ - (- x \ y)" using 4 11 13 by metis have 63: "\x y . x \ - (- - x \ - y) = y \ - (- x \ y)" using 4 11 21 by metis have 71: "\x y . x \ - (- y \ x) = y \ - (- x \ y)" using 4 11 28 by metis have 75: "\x y . x \ - (- y \ x) = y \ - (y \ - x)" using 4 71 by metis have 78: "\x y . - x \ (y \ - (- x \ (y \ - - (- x \ - y)))) = - x \ - (- x \ - y)" using 3 4 6 71 by metis have 86: "\x y . - (- x \ - (- y \ x)) \ - (y \ - (- x \ y)) = - y \ x" using 4 20 71 by metis have 172: "\x y . - x \ - (- x \ - y) = y \ - (- - x \ y)" using 14 75 by metis have 201: "\x y . x \ - (- y \ - - x) = y \ - (y \ - x)" using 4 55 by metis have 236: "\x y . x \ - (- - y \ - x) = x \ - (y \ - x)" using 4 58 by metis have 266: "\x y . - x \ - (- (- x \ - (y \ - - x)) \ - - (- x \ - - (- - x \ y))) = - x \ - (- - x \ y)" using 14 58 236 by metis have 678: "\x y z . - (- x \ - (- y \ x)) \ (- (y \ - (- x \ y)) \ z) = - y \ (x \ z)" using 3 4 37 71 by smt have 745: "\x y z . - (- x \ - (- y \ x)) \ (z \ - (y \ - (- x \ y))) = z \ (- y \ x)" using 4 39 71 by metis have 800: "\x y . - - x \ (- y \ (- (y \ - - x) \ - (- x \ (- - x \ (- y \ - (y \ - - x)))))) = x \ - (y \ - - x)" using 3 23 63 by metis have 944: "\x y . x \ - (x \ - - (- (- x \ - y) \ - - (- x \ y))) = - (- x \ - y) \ - (- (- x \ - y) \ - - (- x \ y))" using 4 24 71 by metis have 948: "\x y . - x \ - (- (y \ - (y \ - - x)) \ - - (- x \ (- y \ - x))) = - x \ - (- y \ - x)" using 24 75 by metis have 950: "\x y . - x \ - (- (y \ - (- - x \ y)) \ - - (- x \ (- x \ - y))) = - x \ - (- x \ - y)" using 24 75 by metis have 961: "\x y . - x \ - (- (y \ - (- - x \ y)) \ - - (- x \ (- - - x \ - y))) = y \ - (- - x \ y)" using 24 63 by metis have 966: "\x y . - x \ - (- (y \ - (y \ - - x)) \ - - (- x \ (- y \ - - - x))) = y \ - (y \ - - x)" using 24 201 by metis have 969: "\x y . - x \ - (- (- x \ - (y \ - - x)) \ - - (- x \ (- - y \ - - x))) = - x \ - (y \ - - x)" using 24 236 by metis have 1096: "\x y z . - x \ (- (- x \ - y) \ z) = y \ (- (- - x \ y) \ z)" using 3 172 by metis have 1098: "\x y z . - x \ (y \ - (- x \ - z)) = y \ (z \ - (- - x \ z))" using 10 172 by metis have 1105: "\x y . x \ - x = y \ - y" using 4 10 12 32 172 by metis have 1109: "\x y z . x \ (- x \ y) = z \ (- z \ y)" using 3 1105 by metis have 1110: "\x y z . x \ - x = y \ (z \ - (y \ z))" using 3 1105 by metis have 1114: "\x y . - (- x \ - - x) = - (y \ - y)" using 7 1105 by metis have 1115: "\x y z . x \ (y \ - y) = z \ (x \ - z)" using 10 1105 by metis have 1117: "\x y . - (x \ - - x) \ - (y \ - y) = - x" using 4 13 1105 by metis have 1121: "\x y . - (x \ - x) \ - (y \ - - y) = - y" using 4 28 1105 by metis have 1122: "\x . - - x = x" using 4 28 1105 1117 by metis have 1134: "\x y z . - (x \ - y) \ (z \ - z) = y \ (- y \ - x)" using 18 1105 1122 by metis have 1140: "\x . - x \ - (x \ (x \ - x)) = - x \ - x" using 4 22 1105 1122 1134 by metis have 1143: "\x y . x \ (- x \ y) = y \ (x \ - y)" using 37 1105 1122 1134 by metis have 1155: "\x y . - (x \ - x) \ - (y \ y) = - y" using 1121 1122 by metis have 1156: "\x y . - (x \ x) \ - (y \ - y) = - x" using 1117 1122 by metis have 1157: "\x y . - (x \ - x) = - (y \ - y)" using 4 1114 1122 by metis have 1167: "\x y z . - x \ (y \ - (- x \ - z)) = y \ (z \ - (x \ z))" using 1098 1122 by metis have 1169: "\x y z . - x \ (- (- x \ - y) \ z) = y \ (- (x \ y) \ z)" using 1096 1122 by metis have 1227: "\x y . - x \ - (- x \ (y \ (x \ - (- x \ - (y \ x))))) = - x \ - (y \ x)" using 3 4 969 1122 by smt have 1230: "\x y . - x \ - (- x \ (- y \ (- x \ - (y \ - (y \ x))))) = y \ - (y \ x)" using 3 4 966 1122 by smt have 1234: "\x y . - x \ - (- x \ (- x \ (- y \ - (y \ - (x \ y))))) = y \ - (x \ y)" using 3 4 961 1122 by metis have 1239: "\x y . - x \ - (- x \ - y) = y \ - (x \ y)" using 3 4 950 1122 1234 by metis have 1240: "\x y . - x \ - (- y \ - x) = y \ - (y \ x)" using 3 4 948 1122 1230 by metis have 1244: "\x y . x \ - (x \ (y \ (y \ - (x \ y)))) = - (- x \ - y) \ - (y \ (y \ - (x \ y)))" using 3 4 944 1122 1167 by metis have 1275: "\x y . x \ (- y \ (- (y \ x) \ - (x \ (- x \ (- y \ - (y \ x)))))) = x \ - (y \ x)" using 10 800 1122 by metis have 1346: "\x y . - x \ - (x \ (y \ (y \ (x \ - (x \ (y \ x)))))) = - x \ - (x \ y)" using 3 4 10 266 1122 1167 by smt have 1377: "\x y . - x \ (y \ - (- x \ (y \ (- x \ - y)))) = y \ - (x \ y)" using 78 1122 1239 by metis have 1394: "\x y . - (- x \ - y) \ - (y \ (y \ (- x \ - (x \ y)))) = x" using 3 4 10 20 30 1122 1239 by smt have 1427: "\x y . - (- x \ - y) \ - (y \ - (x \ (x \ - (x \ y)))) = x \ (x \ - (x \ y))" using 3 4 30 40 1240 by smt have 1436: "\x . - x \ - (x \ (x \ (- x \ - x))) = - x \ (- x \ - (x \ - x))" using 3 4 30 1140 1239 by smt have 1437: "\x y . - (x \ y) \ - (x \ - y) = - x" using 6 1122 by metis have 1438: "\x y . - (x \ y) \ - (y \ - x) = - y" using 12 1122 by metis have 1439: "\x y . - (x \ y) \ - (- y \ x) = - x" using 13 1122 by metis have 1440: "\x y . - (x \ - y) \ - (y \ x) = - x" using 20 1122 by metis have 1441: "\x y . - (x \ y) \ - (- x \ y) = - y" using 21 1122 by metis have 1568: "\x y . x \ (- y \ - x) = y \ (- y \ x)" using 10 1122 1143 by metis have 1598: "\x . - x \ - (x \ (x \ (x \ - x))) = - x \ (- x \ - (x \ - x))" using 4 1436 1568 by metis have 1599: "\x y . - x \ (y \ - (x \ (- x \ (- x \ y)))) = y \ - (x \ y)" using 10 1377 1568 by smt have 1617: "\x . x \ (- x \ (- x \ - (x \ - x))) = x \ - x" using 3 4 10 71 1122 1155 1568 1598 by metis have 1632: "\x y z . - (x \ - x) \ - (- y \ (- (z \ - z) \ - (y \ - (x \ - x)))) = y \ - (x \ - x)" using 43 1157 by metis have 1633: "\x y z . - (x \ - x) \ - (- y \ (- (x \ - x) \ - (y \ - (z \ - z)))) = y \ - (x \ - x)" using 43 1157 by metis have 1636: "\x y . x \ - (y \ (- y \ - (x \ x))) = x \ x" using 43 1109 1122 by metis have 1645: "\x y . x \ - x = y \ (y \ - y)" using 3 1110 1156 by metis have 1648: "\x y z . - (x \ (y \ (- y \ - x))) \ - (z \ - z) = - (y \ - y)" using 3 1115 1156 by metis have 1657: "\x y z . x \ - x = y \ (z \ - z)" using 1105 1645 by metis have 1664: "\x y z . x \ - x = y \ (z \ - y)" using 1115 1645 by metis have 1672: "\x y z . x \ - x = y \ (- y \ z)" using 3 4 1657 by metis have 1697: "\x y z . - x \ (y \ x) = z \ - z" using 1122 1664 by metis have 1733: "\x y z . - (x \ y) \ - (- (z \ - z) \ - (- (- x \ - x) \ y)) = x \ - x" using 4 47 1105 1122 by metis have 1791: "\x y z . x \ - (y \ (- y \ z)) = x \ - (x \ - x)" using 4 71 1122 1672 by metis have 1818: "\x y z . x \ - (- y \ (z \ y)) = x \ - (x \ - x)" using 4 71 1122 1697 by metis have 1861: "\x y z . - (x \ - x) \ - (y \ - (z \ - z)) = - y" using 1437 1657 by metis have 1867: "\x y z . - (x \ - x) \ - (- y \ - (z \ y)) = y" using 1122 1437 1697 by metis have 1868: "\x y . x \ - (y \ - y) = x" using 1122 1155 1633 1861 by metis have 1869: "\x y z . - (x \ - x) \ - (- y \ (- (z \ - z) \ - y)) = y" using 1632 1868 by metis have 1870: "\x y . - (x \ - x) \ - y = - y" using 1861 1868 by metis have 1872: "\x y z . x \ - (- y \ (z \ y)) = x" using 1818 1868 by metis have 1875: "\x y z . x \ - (y \ (- y \ z)) = x" using 1791 1868 by metis have 1883: "\x y . - (x \ (y \ (- y \ - x))) = - (y \ - y)" using 1648 1868 by metis have 1885: "\x . x \ (x \ - x) = x \ - x" using 4 1568 1617 1868 by metis have 1886: "\x . - x \ - x = - x" using 1598 1868 1885 by metis have 1890: "\x . - (x \ x) = - x" using 1156 1868 by metis have 1892: "\x y . - (x \ - x) \ y = y" using 1122 1869 1870 1886 by metis have 1893: "\x y . - (- x \ - (y \ x)) = x" using 1867 1892 by metis have 1902: "\x y . x \ (y \ - (x \ y)) = x \ - x" using 3 4 1122 1733 1886 1892 by metis have 1908: "\x . x \ x = x" using 1636 1875 1890 by metis have 1910: "\x y . x \ - (y \ x) = - y \ x" using 1599 1875 by metis have 1921: "\x y . x \ (- y \ - (y \ x)) = - y \ x" using 1275 1875 1910 by metis have 1951: "\x y . - x \ - (y \ x) = - x" using 1227 1872 1893 1908 by metis have 1954: "\x y z . x \ (y \ - (x \ z)) = y \ (- z \ x)" using 745 1122 1910 1951 by metis have 1956: "\x y z . x \ (- (x \ y) \ z) = - y \ (x \ z)" using 678 1122 1910 1951 by metis have 1959: "\x y . x \ - (x \ y) = - y \ x" using 86 1122 1910 1951 by metis have 1972: "\x y . x \ (- x \ y) = x \ - x" using 1902 1910 by metis have 2000: "\x y . - (- x \ - y) \ - (y \ (- x \ y)) = x \ - (y \ (- x \ y))" using 4 1244 1910 1959 by metis have 2054: "\x y . x \ - (y \ (- x \ y)) = x" using 1394 1921 2000 by metis have 2057: "\x y . - (x \ (y \ - y)) = - (y \ - y)" using 1883 1972 by metis have 2061: "\x y . x \ (- y \ x) = x \ - y" using 4 1122 1427 1910 1959 2054 by metis have 2090: "\x y z . x \ (- (y \ x) \ z) = x \ (- y \ z)" using 1122 1169 1956 by metis have 2100: "\x y . - x \ - (x \ y) = - x" using 4 1346 1868 1885 1910 1959 1972 2057 by metis have 2144: "\x y . x \ - (y \ - x) = x" using 1122 1440 2000 2061 by metis have 2199: "\x y . x \ (x \ y) = x \ y" using 3 1908 by metis have 2208: "\x y z . x \ (- (y \ - x) \ z) = x \ z" using 3 2144 by metis have 2349: "\x y z . - (x \ y) \ - (x \ (y \ z)) = - (x \ y)" using 3 2100 by metis have 2432: "\x y z . - (x \ (y \ z)) \ - (y \ (z \ - x)) = - (y \ z)" using 3 1438 by metis have 2530: "\x y z . - (- (x \ y) \ z) = - (y \ (- x \ z)) \ - (- y \ z)" using 4 1122 1439 2090 2208 by smt have 3364: "\x y z . - (- x \ y) \ (z \ - (x \ y)) = z \ - y" using 3 4 1122 1441 1910 1954 2199 by metis have 5763: "\x y z . - (x \ y) \ - (- x \ (y \ z)) = - (x \ y) \ - (y \ z)" using 4 2349 3364 by metis have 6113: "\x y z . - (x \ (y \ z)) \ - (z \ - x) = - (y \ z) \ - (z \ - x)" using 4 2432 3364 5763 by metis show "\x y z. x \ y \ z = (x \ y) \ (x \ z)" proof - fix x y z have "- (y \ z \ x) = - (- (- y \ z) \ - (- y \ - z) \ x) \ - (x \ - - z)" using 1437 2530 6113 by (smt commutative inf_def) thus "x \ y \ z = (x \ y) \ (x \ z)" using 12 1122 by (metis commutative inf_def) qed qed show 14: "\x. x \ - x = bot" proof - fix x have "(bot \ x) \ (bot \ -x) = bot" using huntington bot_def inf_def by auto thus "x \ -x = bot" using 11 less_eq_def by force qed show 15: "\x. x \ - x = top" using 5 14 by (metis (no_types, lifting) huntington bot_def less_eq_def top_def) show 16: "\x y. x - y = x \ - y" using 15 by (metis commutative huntington inf_def minus_def) show 7: "\x y z. x \ y \ x \ z \ x \ y \ z" by (simp add: 13 less_eq_def) qed end -context boolean_algebra +context Lattices.boolean_algebra begin sublocale ba_he: huntington_extended proof show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: sup_assoc) show "\x y. x \ y = y \ x" by (simp add: sup_commute) show "\x y. x = - (- x \ y) \ - (- x \ - y)" by simp show "top = (THE x. \y. x = y \ - y)" by auto show "bot = - (THE x. \y. x = y \ - y)" by auto show "\x y. x \ y = - (- x \ - y)" by simp show "\x y. x - y = - (- x \ y)" by (simp add: diff_eq) show "\x y. (x \ y) = (x \ y = y)" by (simp add: le_iff_sup) show "\x y. (x < y) = (x \ y = y \ y \ x \ x)" using sup.strict_order_iff sup_commute by auto qed end subsection \Stone Algebras\ text \ We relate Stone algebras to Boolean algebras. \ class stone_algebra_extended = stone_algebra + minus + assumes stone_minus_def[simp]: "x - y = x \ -y" class regular_stone_algebra = stone_algebra_extended + assumes double_complement[simp]: "--x = x" begin subclass boolean_algebra proof show "\x. x \ - x = bot" by simp show "\x. x \ - x = top" using regular_dense_top by fastforce show "\x y. x - y = x \ - y" by simp qed end -context boolean_algebra +context Lattices.boolean_algebra begin sublocale ba_rsa: regular_stone_algebra proof show "\x y. x - y = x \ - y" by (simp add: diff_eq) show "\x. - - x = x" by simp qed end section \Alternative Axiomatisations of Boolean Algebras\ text \ We consider four axiomatisations of Boolean algebras based only on join and complement. The first three are from the literature and the fourth, a version using equational axioms, is new. The motivation for Byrne's and the new axiomatisation is that the axioms are easier to understand than Huntington's third axiom. We also include Meredith's axiomatisation. \ subsection \Lee Byrne's Formulation A\ text \ The following axiomatisation is from \cite[Formulation A]{Byrne1946}; see also \cite{Frink1941}. \ text \Theorem 3\ class boolean_algebra_1 = sup + uminus + assumes ba1_associative: "x \ (y \ z) = (x \ y) \ z" assumes ba1_commutative: "x \ y = y \ x" assumes ba1_complement: "x \ -y = z \ -z \ x \ y = x" begin subclass huntington proof show 1: "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: ba1_associative) show "\x y. x \ y = y \ x" by (simp add: ba1_commutative) show "\x y. x = - (- x \ y) \ - (- x \ - y)" proof - have 2: "\x y. y \ (y \ x) = y \ x" using 1 by (metis ba1_complement) hence "\x. --x = x" by (smt ba1_associative ba1_commutative ba1_complement) hence "\x y. y \ -(y \ -x) = y \ x" by (smt ba1_associative ba1_commutative ba1_complement) thus "\x y. x = -(-x \ y) \ -(-x \ - y)" using 2 by (smt ba1_commutative ba1_complement) qed qed end context huntington begin sublocale h_ba1: boolean_algebra_1 proof show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: associative) show "\x y. x \ y = y \ x" by (simp add: commutative) show "\x y z. (x \ - y = z \ - z) = (x \ y = x)" proof fix x y z have 1: "\x y z. -(-x \ y) \ (-(-x \ -y) \ z) = x \ z" using associative huntington by force have 2: "\x y. -(x \ -y) \ -(-y \ -x) = y" by (metis commutative huntington) show "x \ - y = z \ - z \ x \ y = x" by (metis 1 2 associative commutative top_unique) show "x \ y = x \ x \ - y = z \ - z" by (metis associative huntington commutative top_unique) qed qed end subsection \Lee Byrne's Formulation B\ text \ The following axiomatisation is from \cite[Formulation B]{Byrne1946}. \ text \Theorem 4\ class boolean_algebra_2 = sup + uminus + assumes ba2_associative_commutative: "(x \ y) \ z = (y \ z) \ x" assumes ba2_complement: "x \ -y = z \ -z \ x \ y = x" begin subclass boolean_algebra_1 proof show "\x y z. x \ (y \ z) = x \ y \ z" by (smt ba2_associative_commutative ba2_complement) show "\x y. x \ y = y \ x" by (metis ba2_associative_commutative ba2_complement) show "\x y z. (x \ - y = z \ - z) = (x \ y = x)" by (simp add: ba2_complement) qed end context boolean_algebra_1 begin sublocale ba1_ba2: boolean_algebra_2 proof show "\x y z. x \ y \ z = y \ z \ x" using ba1_associative commutative by force show "\x y z. (x \ - y = z \ - z) = (x \ y = x)" by (simp add: ba1_complement) qed end subsection \Meredith's Equational Axioms\ text \ The following axiomatisation is from \cite[page 221 (1) \{A,N\}]{MeredithPrior1968}. \ class boolean_algebra_mp = sup + uminus + assumes ba_mp_1: "-(-x \ y) \ x = x" assumes ba_mp_2: "-(-x \ y) \ (z \ y) = y \ (z \ x)" begin subclass huntington proof show "\x y z. x \ (y \ z) = x \ y \ z" by (metis ba_mp_1 ba_mp_2) show "\x y. x \ y = y \ x" by (metis ba_mp_1 ba_mp_2) show "\x y. x = - (- x \ y) \ - (- x \ - y)" by (metis ba_mp_1 ba_mp_2) qed end context huntington begin sublocale mp_h: boolean_algebra_mp proof show 1: "\x y. - (- x \ y) \ x = x" by (metis h_ba1.ba1_associative h_ba1.ba1_complement huntington) show "\x y z. - (- x \ y) \ (z \ y) = y \ (z \ x)" proof - fix x y z have "y = -(-x \ -y) \ y" using 1 h_ba1.ba1_commutative by auto thus "-(-x \ y) \ (z \ y) = y \ (z \ x)" by (metis h_ba1.ba1_associative h_ba1.ba1_commutative huntington) qed qed end subsection \An Equational Axiomatisation based on Semilattices\ text \ The following version is an equational axiomatisation based on semilattices. We add the double complement rule and that \top\ is unique. The final axiom \ba3_export\ encodes the logical statement $P \vee Q = P \vee (\neg P \wedge Q)$. Its dual appears in \cite{BalbesHorn1970}. \ text \Theorem 5\ class boolean_algebra_3 = sup + uminus + assumes ba3_associative: "x \ (y \ z) = (x \ y) \ z" assumes ba3_commutative: "x \ y = y \ x" assumes ba3_idempotent[simp]: "x \ x = x" assumes ba3_double_complement[simp]: "--x = x" assumes ba3_top_unique: "x \ -x = y \ -y" assumes ba3_export: "x \ -(x \ y) = x \ -y" begin subclass huntington proof show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: ba3_associative) show "\x y. x \ y = y \ x" by (simp add: ba3_commutative) show "\x y. x = - (- x \ y) \ - (- x \ - y)" by (metis ba3_commutative ba3_double_complement ba3_export ba3_idempotent ba3_top_unique) qed end context huntington begin sublocale h_ba3: boolean_algebra_3 proof show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: h_ba1.ba1_associative) show "\x y. x \ y = y \ x" by (simp add: h_ba1.ba1_commutative) show 3: "\x. x \ x = x" using h_ba1.ba1_complement by blast show 4: "\x. - - x = x" by (metis h_ba1.ba1_commutative huntington top_unique) show "\x y. x \ - x = y \ - y" by (simp add: top_unique) show "\x y. x \ - (x \ y) = x \ - y" using 3 4 by (smt h_ba1.ba1_ba2.ba2_associative_commutative h_ba1.ba1_complement) qed end section \Subset Boolean Algebras\ text \ We apply Huntington's axioms to the range of a unary operation, which serves as complement on the range. This gives a Boolean algebra structure on the range without imposing any further constraints on the set. The obtained structure is used as a reference in the subsequent development and to inherit the results proved here. This is taken from \cite{Guttmann2012c,GuttmannStruthWeber2011b} and follows the development of Boolean algebras in \cite{Maddux1996}. \ text \Definition 6\ class subset_boolean_algebra = sup + uminus + assumes sub_associative: "-x \ (-y \ -z) = (-x \ -y) \ -z" assumes sub_commutative: "-x \ -y = -y \ -x" assumes sub_complement: "-x = -(--x \ -y) \ -(--x \ --y)" assumes sub_sup_closed: "-x \ -y = --(-x \ -y)" begin text \uniqueness of \top\, resulting in the lemma \top_def\ to replace the assumption \sub_top_def\\ lemma top_unique: "-x \ --x = -y \ --y" by (metis sub_associative sub_commutative sub_complement) text \consequences for join and complement\ lemma double_negation[simp]: "---x = -x" by (metis sub_complement sub_sup_closed) lemma complement_1: "--x = -(-x \ -y) \ -(-x \ --y)" by (metis double_negation sub_complement) lemma sup_right_zero_var: "-x \ (-y \ --y) = -z \ --z" by (smt complement_1 sub_associative sub_sup_closed top_unique) lemma sup_right_unit_idempotent: "-x \ -x = -x \ -(-y \ --y)" by (metis complement_1 double_negation sub_sup_closed sup_right_zero_var) lemma sup_idempotent[simp]: "-x \ -x = -x" by (smt complement_1 double_negation sub_associative sup_right_unit_idempotent) lemma complement_2: "-x = -(-(-x \ -y) \ -(-x \ --y))" using complement_1 by auto lemma sup_eq_cases: "-x \ -y = -x \ -z \ --x \ -y = --x \ -z \ -y = -z" by (metis complement_2 sub_commutative) lemma sup_eq_cases_2: "-y \ -x = -z \ -x \ -y \ --x = -z \ --x \ -y = -z" using sub_commutative sup_eq_cases by auto end text \Definition 7\ class subset_extended = sup + inf + minus + uminus + bot + top + ord + assumes sub_top_def: "top = (THE x . \y . x = -y \ --y)" (* define without imposing uniqueness *) assumes sub_bot_def: "bot = -(THE x . \y . x = -y \ --y)" assumes sub_inf_def: "-x \ -y = -(--x \ --y)" assumes sub_minus_def: "-x - -y = -(--x \ -y)" assumes sub_less_eq_def: "-x \ -y \ -x \ -y = -y" assumes sub_less_def: "-x < -y \ -x \ -y = -y \ \ (-y \ -x = -x)" class subset_boolean_algebra_extended = subset_boolean_algebra + subset_extended begin lemma top_def: "top = -x \ --x" using sub_top_def top_unique by blast text \consequences for meet\ lemma inf_closed: "-x \ -y = --(-x \ -y)" by (simp add: sub_inf_def) lemma inf_associative: "-x \ (-y \ -z) = (-x \ -y) \ -z" using sub_associative sub_inf_def sub_sup_closed by auto lemma inf_commutative: "-x \ -y = -y \ -x" by (simp add: sub_commutative sub_inf_def) lemma inf_idempotent[simp]: "-x \ -x = -x" by (simp add: sub_inf_def) lemma inf_absorb[simp]: "(-x \ -y) \ -x = -x" by (metis complement_1 sup_idempotent sub_inf_def sub_associative sub_sup_closed) lemma sup_absorb[simp]: "-x \ (-x \ -y) = -x" by (metis sub_associative sub_complement sub_inf_def sup_idempotent) lemma inf_demorgan: "-(-x \ -y) = --x \ --y" using sub_inf_def sub_sup_closed by auto lemma sub_sup_demorgan: "-(-x \ -y) = --x \ --y" by (simp add: sub_inf_def) lemma sup_cases: "-x = (-x \ -y) \ (-x \ --y)" by (metis inf_closed inf_demorgan sub_complement) lemma inf_cases: "-x = (-x \ -y) \ (-x \ --y)" by (metis complement_2 sub_sup_closed sub_sup_demorgan) lemma inf_complement_intro: "(-x \ -y) \ --x = -y \ --x" proof - have "(-x \ -y) \ --x = (-x \ -y) \ (--x \ -y) \ --x" by (metis inf_absorb inf_associative sub_sup_closed) also have "... = -y \ --x" by (metis inf_cases sub_commutative) finally show ?thesis . qed lemma sup_complement_intro: "-x \ -y = -x \ (--x \ -y)" by (metis inf_absorb inf_commutative inf_complement_intro sub_sup_closed sup_cases) lemma inf_left_dist_sup: "-x \ (-y \ -z) = (-x \ -y) \ (-x \ -z)" proof - have "-x \ (-y \ -z) = (-x \ (-y \ -z) \ -y) \ (-x \ (-y \ -z) \ --y)" by (metis sub_inf_def sub_sup_closed sup_cases) also have "... = (-x \ -y) \ (-x \ -z \ --y)" by (metis inf_absorb inf_associative inf_complement_intro sub_sup_closed) also have "... = (-x \ -y) \ ((-x \ -y \ -z) \ (-x \ -z \ --y))" using sub_associative sub_inf_def sup_absorb by auto also have "... = (-x \ -y) \ ((-x \ -z \ -y) \ (-x \ -z \ --y))" by (metis inf_associative inf_commutative) also have "... = (-x \ -y) \ (-x \ -z)" by (metis sub_inf_def sup_cases) finally show ?thesis . qed lemma sup_left_dist_inf: "-x \ (-y \ -z) = (-x \ -y) \ (-x \ -z)" proof - have "-x \ (-y \ -z) = -(--x \ (--y \ --z))" by (metis sub_inf_def sub_sup_closed sub_sup_demorgan) also have "... = (-x \ -y) \ (-x \ -z)" by (metis inf_left_dist_sup sub_sup_closed sub_sup_demorgan) finally show ?thesis . qed lemma sup_right_dist_inf: "(-y \ -z) \ -x = (-y \ -x) \ (-z \ -x)" using sub_commutative sub_inf_def sup_left_dist_inf by auto lemma inf_right_dist_sup: "(-y \ -z) \ -x = (-y \ -x) \ (-z \ -x)" by (metis inf_commutative inf_left_dist_sup sub_sup_closed) lemma case_duality: "(--x \ -y) \ (-x \ -z) = (-x \ -y) \ (--x \ -z)" proof - have 1: "-(--x \ --y) \ ----x = --x \ -y" using inf_commutative inf_complement_intro sub_sup_closed sub_sup_demorgan by auto have 2: "-(----x \ -(--x \ -z)) = -----x \ ---z" by (metis (no_types) double_negation sup_complement_intro sub_sup_demorgan) have 3: "-(--x \ --y) \ -x = -x" using inf_commutative inf_left_dist_sup sub_sup_closed sub_sup_demorgan by auto hence "-(--x \ --y) = -x \ -y" using sub_sup_closed sub_sup_demorgan by auto thus ?thesis by (metis double_negation 1 2 3 inf_associative inf_left_dist_sup sup_complement_intro) qed lemma case_duality_2: "(-x \ -y) \ (--x \ -z) = (-x \ -z) \ (--x \ -y)" using case_duality sub_commutative sub_inf_def by auto lemma complement_cases: "((-v \ -w) \ (--v \ -x)) \ -((-v \ -y) \ (--v \ -z)) = (-v \ -w \ --y) \ (--v \ -x \ --z)" proof - have 1: "(--v \ -w) = --(--v \ -w) \ (-v \ -x) = --(-v \ -x) \ (--v \ --y) = --(--v \ --y) \ (-v \ --z) = --(-v \ --z)" using sub_inf_def sub_sup_closed by auto have 2: "(-v \ (-x \ --z)) = --(-v \ (-x \ --z))" using sub_inf_def sub_sup_closed by auto have "((-v \ -w) \ (--v \ -x)) \ -((-v \ -y) \ (--v \ -z)) = ((-v \ -w) \ (--v \ -x)) \ (-(-v \ -y) \ -(--v \ -z))" using sub_inf_def by auto also have "... = ((-v \ -w) \ (--v \ -x)) \ ((--v \ --y) \ (-v \ --z))" using inf_demorgan by auto also have "... = (--v \ -w) \ (-v \ -x) \ ((--v \ --y) \ (-v \ --z))" by (metis case_duality double_negation) also have "... = (--v \ -w) \ ((-v \ -x) \ ((--v \ --y) \ (-v \ --z)))" by (metis 1 inf_associative sub_inf_def) also have "... = (--v \ -w) \ ((-v \ -x) \ (--v \ --y) \ (-v \ --z))" by (metis 1 inf_associative) also have "... = (--v \ -w) \ ((--v \ --y) \ (-v \ -x) \ (-v \ --z))" by (metis 1 inf_commutative) also have "... = (--v \ -w) \ ((--v \ --y) \ ((-v \ -x) \ (-v \ --z)))" by (metis 1 inf_associative) also have "... = (--v \ -w) \ ((--v \ --y) \ (-v \ (-x \ --z)))" by (simp add: sup_left_dist_inf) also have "... = (--v \ -w) \ (--v \ --y) \ (-v \ (-x \ --z))" using 1 2 by (metis inf_associative) also have "... = (--v \ (-w \ --y)) \ (-v \ (-x \ --z))" by (simp add: sup_left_dist_inf) also have "... = (-v \ (-w \ --y)) \ (--v \ (-x \ --z))" by (metis case_duality complement_1 complement_2 sub_inf_def) also have "... = (-v \ -w \ --y) \ (--v \ -x \ --z)" by (simp add: inf_associative) finally show ?thesis . qed lemma inf_cases_2: "--x = -(-x \ -y) \ -(-x \ --y)" using sub_inf_def sup_cases by auto text \consequences for \top\ and \bot\\ lemma sup_complement[simp]: "-x \ --x = top" using top_def by auto lemma inf_complement[simp]: "-x \ --x = bot" by (metis sub_bot_def sub_inf_def sub_top_def top_def) lemma complement_bot[simp]: "-bot = top" using inf_complement inf_demorgan sup_complement by fastforce lemma complement_top[simp]: "-top = bot" using sub_bot_def sub_top_def by blast lemma sup_right_zero[simp]: "-x \ top = top" using sup_right_zero_var by auto lemma sup_left_zero[simp]: "top \ -x = top" by (metis complement_bot sub_commutative sup_right_zero) lemma inf_right_unit[simp]: "-x \ bot = bot" by (metis complement_bot complement_top double_negation sub_sup_demorgan sup_right_zero) lemma inf_left_unit[simp]: "bot \ -x = bot" by (metis complement_top inf_commutative inf_right_unit) lemma sup_right_unit[simp]: "-x \ bot = -x" using sup_right_unit_idempotent by auto lemma sup_left_unit[simp]: "bot \ -x = -x" by (metis complement_top sub_commutative sup_right_unit) lemma inf_right_zero[simp]: "-x \ top = -x" by (metis inf_left_dist_sup sup_cases top_def) lemma sub_inf_left_zero[simp]: "top \ -x = -x" using inf_absorb top_def by fastforce lemma bot_double_complement[simp]: "--bot = bot" by simp lemma top_double_complement[simp]: "--top = top" by simp text \consequences for the order\ lemma reflexive: "-x \ -x" by (simp add: sub_less_eq_def) lemma transitive: "-x \ -y \ -y \ -z \ -x \ -z" by (metis sub_associative sub_less_eq_def) lemma antisymmetric: "-x \ -y \ -y \ -x \ -x = -y" by (simp add: sub_commutative sub_less_eq_def) lemma sub_bot_least: "bot \ -x" using sup_left_unit complement_top sub_less_eq_def by blast lemma top_greatest: "-x \ top" using complement_bot sub_less_eq_def sup_right_zero by blast lemma upper_bound_left: "-x \ -x \ -y" by (metis sub_associative sub_less_eq_def sub_sup_closed sup_idempotent) lemma upper_bound_right: "-y \ -x \ -y" using sub_commutative upper_bound_left by fastforce lemma sub_sup_left_isotone: assumes "-x \ -y" shows "-x \ -z \ -y \ -z" proof - have "-x \ -y = -y" by (meson assms sub_less_eq_def) thus ?thesis by (metis (full_types) sub_associative sub_commutative sub_sup_closed upper_bound_left) qed lemma sub_sup_right_isotone: "-x \ -y \ -z \ -x \ -z \ -y" by (simp add: sub_commutative sub_sup_left_isotone) lemma sup_isotone: assumes "-p \ -q" and "-r \ -s" shows "-p \ -r \ -q \ -s" proof - have "\x y. \ -x \ -y \ -r \ -x \ -y \ -s" by (metis (full_types) assms(2) sub_sup_closed sub_sup_right_isotone transitive) thus ?thesis by (metis (no_types) assms(1) sub_sup_closed sub_sup_left_isotone) qed lemma sub_complement_antitone: "-x \ -y \ --y \ --x" by (metis inf_absorb inf_demorgan sub_less_eq_def) lemma less_eq_inf: "-x \ -y \ -x \ -y = -x" by (metis inf_absorb inf_commutative sub_less_eq_def upper_bound_right sup_absorb) lemma inf_complement_left_antitone: "-x \ -y \ -(-y \ -z) \ -(-x \ -z)" by (simp add: sub_complement_antitone inf_demorgan sub_sup_left_isotone) lemma sub_inf_left_isotone: "-x \ -y \ -x \ -z \ -y \ -z" using sub_complement_antitone inf_closed inf_complement_left_antitone by fastforce lemma sub_inf_right_isotone: "-x \ -y \ -z \ -x \ -z \ -y" by (simp add: inf_commutative sub_inf_left_isotone) lemma inf_isotone: assumes "-p \ -q" and "-r \ -s" shows "-p \ -r \ -q \ -s" proof - have "\w x y z. (-w \ -x \ -y \ \ -w \ -x \ -z) \ \ -z \ -y" by (metis (no_types) inf_closed sub_inf_right_isotone transitive) thus ?thesis by (metis (no_types) assms inf_closed sub_inf_left_isotone) qed lemma least_upper_bound: "-x \ -z \ -y \ -z \ -x \ -y \ -z" by (metis sub_sup_closed transitive upper_bound_right sup_idempotent sup_isotone upper_bound_left) lemma lower_bound_left: "-x \ -y \ -x" by (metis sub_inf_def upper_bound_right sup_absorb) lemma lower_bound_right: "-x \ -y \ -y" using inf_commutative lower_bound_left by fastforce lemma greatest_lower_bound: "-x \ -y \ -x \ -z \ -x \ -y \ -z" by (metis inf_closed sub_inf_left_isotone less_eq_inf transitive lower_bound_left lower_bound_right) lemma less_eq_sup_top: "-x \ -y \ --x \ -y = top" by (metis complement_1 inf_commutative inf_complement_intro sub_inf_left_zero less_eq_inf sub_complement sup_complement_intro top_def) lemma less_eq_inf_bot: "-x \ -y \ -x \ --y = bot" by (metis complement_bot complement_top double_negation inf_demorgan less_eq_sup_top sub_inf_def) lemma shunting: "-x \ -y \ -z \ -y \ --x \ -z" proof (cases "--x \ (-z \ --y) = top") case True have "\v w. -v \ -w \ -w \ --v \ top" using less_eq_sup_top sub_commutative by blast thus ?thesis by (metis True sub_associative sub_commutative sub_inf_def sub_sup_closed) next case False hence "--x \ (-z \ --y) \ top \ \ -y \ -z \ --x" by (metis (no_types) less_eq_sup_top sub_associative sub_commutative sub_sup_closed) thus ?thesis using less_eq_sup_top sub_associative sub_commutative sub_inf_def sub_sup_closed by auto qed lemma shunting_right: "-x \ -y \ -z \ -x \ -z \ --y" by (metis inf_commutative sub_commutative shunting) lemma sup_less_eq_cases: assumes "-z \ -x \ -y" and "-z \ --x \ -y" shows "-z \ -y" proof - have "-z \ (-x \ -y) \ (--x \ -y)" by (metis assms greatest_lower_bound sub_sup_closed) also have "... = -y" by (metis inf_cases sub_commutative) finally show ?thesis . qed lemma sup_less_eq_cases_2: "-x \ -y \ -x \ -z \ --x \ -y \ --x \ -z \ -y \ -z" by (metis least_upper_bound sup_less_eq_cases sub_sup_closed) lemma sup_less_eq_cases_3: "-y \ -x \ -z \ -x \ -y \ --x \ -z \ --x \ -y \ -z" by (simp add: sup_less_eq_cases_2 sub_commutative) lemma inf_less_eq_cases: "-x \ -y \ -z \ --x \ -y \ -z \ -y \ -z" by (simp add: shunting sup_less_eq_cases) lemma inf_less_eq_cases_2: "-x \ -y \ -x \ -z \ --x \ -y \ --x \ -z \ -y \ -z" by (metis greatest_lower_bound inf_closed inf_less_eq_cases) lemma inf_less_eq_cases_3: "-y \ -x \ -z \ -x \ -y \ --x \ -z \ --x \ -y \ -z" by (simp add: inf_commutative inf_less_eq_cases_2) lemma inf_eq_cases: "-x \ -y = -x \ -z \ --x \ -y = --x \ -z \ -y = -z" by (metis inf_commutative sup_cases) lemma inf_eq_cases_2: "-y \ -x = -z \ -x \ -y \ --x = -z \ --x \ -y = -z" using inf_commutative inf_eq_cases by auto lemma wnf_lemma_1: "((-x \ -y) \ (--x \ -z)) \ -x = -x \ -y" proof - have "\u v w. (-u \ (-v \ --w)) \ -w = -u \ -w" by (metis inf_right_zero sub_associative sub_sup_closed sup_complement sup_idempotent sup_right_dist_inf) thus ?thesis by (metis (no_types) sub_associative sub_commutative sub_sup_closed sup_idempotent) qed lemma wnf_lemma_2: "((-x \ -y) \ (-z \ --y)) \ -y = -x \ -y" using sub_commutative wnf_lemma_1 by fastforce lemma wnf_lemma_3: "((-x \ -z) \ (--x \ -y)) \ --x = --x \ -y" by (metis case_duality case_duality_2 double_negation sub_commutative wnf_lemma_2) lemma wnf_lemma_4: "((-z \ -y) \ (-x \ --y)) \ --y = -x \ --y" using sub_commutative wnf_lemma_3 by auto end class subset_boolean_algebra' = sup + uminus + assumes sub_associative': "-x \ (-y \ -z) = (-x \ -y) \ -z" assumes sub_commutative': "-x \ -y = -y \ -x" assumes sub_complement': "-x = -(--x \ -y) \ -(--x \ --y)" assumes sub_sup_closed': "\z . -x \ -y = -z" begin subclass subset_boolean_algebra proof show "\x y z. - x \ (- y \ - z) = - x \ - y \ - z" by (simp add: sub_associative') show "\x y. - x \ - y = - y \ - x" by (simp add: sub_commutative') show "\x y. - x = - (- - x \ - y) \ - (- - x \ - - y)" by (simp add: sub_complement') show "\x y. - x \ - y = - - (- x \ - y)" proof - fix x y have "\x y. -y \ (-(--y \ -x) \ -(---x \ -y)) = -y \ --x" by (metis (no_types) sub_associative' sub_commutative' sub_complement') hence "\x. ---x = -x" by (metis (no_types) sub_commutative' sub_complement') thus "-x \ -y = --(-x \ -y)" by (metis sub_sup_closed') qed qed end text \ We introduce a type for the range of complement and show that it is an instance of \boolean_algebra\. \ typedef (overloaded) 'a boolean_subset = "{ x::'a::uminus . \y . x = -y }" by auto lemma simp_boolean_subset[simp]: "\y . Rep_boolean_subset x = -y" using Rep_boolean_subset by simp setup_lifting type_definition_boolean_subset text \Theorem 8.1\ instantiation boolean_subset :: (subset_boolean_algebra) huntington begin lift_definition sup_boolean_subset :: "'a boolean_subset \ 'a boolean_subset \ 'a boolean_subset" is sup using sub_sup_closed by auto lift_definition uminus_boolean_subset :: "'a boolean_subset \ 'a boolean_subset" is uminus by auto instance proof show "\x y z::'a boolean_subset. x \ (y \ z) = x \ y \ z" apply transfer using sub_associative by blast show "\x y::'a boolean_subset. x \ y = y \ x" apply transfer using sub_commutative by blast show "\x y::'a boolean_subset. x = - (- x \ y) \ - (- x \ - y)" apply transfer using sub_complement by blast qed end text \Theorem 8.2\ instantiation boolean_subset :: (subset_boolean_algebra_extended) huntington_extended begin lift_definition inf_boolean_subset :: "'a boolean_subset \ 'a boolean_subset \ 'a boolean_subset" is inf using inf_closed by auto lift_definition minus_boolean_subset :: "'a boolean_subset \ 'a boolean_subset \ 'a boolean_subset" is minus using sub_minus_def by auto lift_definition bot_boolean_subset :: "'a boolean_subset" is bot by (metis complement_top) lift_definition top_boolean_subset :: "'a boolean_subset" is top by (metis complement_bot) lift_definition less_eq_boolean_subset :: "'a boolean_subset \ 'a boolean_subset \ bool" is less_eq . lift_definition less_boolean_subset :: "'a boolean_subset \ 'a boolean_subset \ bool" is less . instance proof show 1: "top = (THE x. \y::'a boolean_subset. x = y \ - y)" proof (rule the_equality[symmetric]) show "\y::'a boolean_subset. top = y \ - y" apply transfer by auto show "\x::'a boolean_subset. \y. x = y \ - y \ x = top" apply transfer by force qed have "(bot::'a boolean_subset) = - top" apply transfer by simp thus "bot = - (THE x. \y::'a boolean_subset. x = y \ - y)" using 1 by simp show "\x y::'a boolean_subset. x \ y = - (- x \ - y)" apply transfer using sub_inf_def by blast show "\x y::'a boolean_subset. x - y = - (- x \ y)" apply transfer using sub_minus_def by blast show "\x y::'a boolean_subset. (x \ y) = (x \ y = y)" apply transfer using sub_less_eq_def by blast show "\x y::'a boolean_subset. (x < y) = (x \ y = y \ y \ x \ x)" apply transfer using sub_less_def by blast qed end section \Subset Boolean algebras with Additional Structure\ text \ We now discuss axioms that make the range of a unary operation a Boolean algebra, but add further properties that are common to the intended models. In the intended models, the unary operation can be a complement, a pseudocomplement or the antidomain operation. For simplicity, we mostly call the unary operation `complement'. We first look at structures based only on join and complement, and then add axioms for the remaining operations of Boolean algebras. In the intended models, the operation that is meet on the range of the complement can be a meet in the whole algebra or composition. \ subsection \Axioms Derived from the New Axiomatisation\ text \ The axioms of the first algebra are based on \boolean_algebra_3\. \ text \Definition 9\ class subset_boolean_algebra_1 = sup + uminus + assumes sba1_associative: "x \ (y \ z) = (x \ y) \ z" assumes sba1_commutative: "x \ y = y \ x" assumes sba1_idempotent[simp]: "x \ x = x" assumes sba1_double_complement[simp]: "---x = -x" assumes sba1_bot_unique: "-(x \ -x) = -(y \ -y)" assumes sba1_export: "-x \ -(-x \ y) = -x \ -y" begin text \Theorem 11.1\ subclass subset_boolean_algebra proof show "\x y z. - x \ (- y \ - z) = - x \ - y \ - z" by (simp add: sba1_associative) show "\x y. - x \ - y = - y \ - x" by (simp add: sba1_commutative) show "\x y. - x = - (- - x \ - y) \ - (- - x \ - - y)" by (smt sba1_bot_unique sba1_commutative sba1_double_complement sba1_export sba1_idempotent) thus "\x y. - x \ - y = - - (- x \ - y)" by (metis sba1_double_complement sba1_export) qed definition "sba1_bot \ THE x . \z . x = -(z \ -z)" lemma sba1_bot: "sba1_bot = -(z \ -z)" using sba1_bot_def sba1_bot_unique by auto end text \Boolean algebra operations based on join and complement\ text \Definition 10\ class subset_extended_1 = sup + inf + minus + uminus + bot + top + ord + assumes ba_bot: "bot = (THE x . \z . x = -(z \ -z))" assumes ba_top: "top = -(THE x . \z . x = -(z \ -z))" assumes ba_inf: "-x \ -y = -(--x \ --y)" assumes ba_minus: "-x - -y = -(--x \ -y)" assumes ba_less_eq: "x \ y \ x \ y = y" assumes ba_less: "x < y \ x \ y = y \ \ (y \ x = x)" class subset_extended_2 = subset_extended_1 + assumes ba_bot_unique: "-(x \ -x) = -(y \ -y)" begin lemma ba_bot_def: "bot = -(z \ -z)" using ba_bot ba_bot_unique by auto lemma ba_top_def: "top = --(z \ -z)" using ba_bot_def ba_top by simp end text \Subset forms Boolean Algebra, extended by Boolean algebra operations\ class subset_boolean_algebra_1_extended = subset_boolean_algebra_1 + subset_extended_1 begin subclass subset_extended_2 proof show "\x y. - (x \ - x) = - (y \ - y)" by (simp add: sba1_bot_unique) qed subclass semilattice_sup proof show "\x y. (x < y) = (x \ y \ \ y \ x)" by (simp add: ba_less ba_less_eq) show "\x. x \ x" by (simp add: ba_less_eq) show "\x y z. x \ y \ y \ z \ x \ z" by (metis sba1_associative ba_less_eq) show "\x y. x \ y \ y \ x \ x = y" by (simp add: sba1_commutative ba_less_eq) show "\x y. x \ x \ y" by (simp add: sba1_associative ba_less_eq) thus "\y x. y \ x \ y" by (simp add: sba1_commutative) show "\y x z. y \ x \ z \ x \ y \ z \ x" by (metis sba1_associative ba_less_eq) qed text \Theorem 11.2\ subclass subset_boolean_algebra_extended proof show "top = (THE x. \y. x = - y \ - - y)" by (smt ba_bot ba_bot_def ba_top sub_sup_closed the_equality) thus "bot = - (THE x. \y. x = - y \ - - y)" using ba_bot_def ba_top_def by force show "\x y. - x \ - y = - (- - x \ - - y)" by (simp add: ba_inf) show "\x y. - x - - y = - (- - x \ - y)" by (simp add: ba_minus) show "\x y. (- x \ - y) = (- x \ - y = - y)" using le_iff_sup by auto show "\x y. (- x < - y) = (- x \ - y = - y \ - y \ - x \ - x)" by (simp add: ba_less) qed end subsection \Stronger Assumptions based on Join and Complement\ text \ We add further axioms covering properties common to the antidomain and (pseudo)complement instances. \ text \Definition 12\ class subset_boolean_algebra_2 = sup + uminus + assumes sba2_associative: "x \ (y \ z) = (x \ y) \ z" assumes sba2_commutative: "x \ y = y \ x" assumes sba2_idempotent[simp]: "x \ x = x" assumes sba2_bot_unit: "x \ -(y \ -y) = x" assumes sba2_sub_sup_demorgan: "-(x \ y) = -(--x \ --y)" assumes sba2_export: "-x \ -(-x \ y) = -x \ -y" begin text \Theorem 13.1\ subclass subset_boolean_algebra_1 proof show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: sba2_associative) show "\x y. x \ y = y \ x" by (simp add: sba2_commutative) show "\x. x \ x = x" by simp show "\x. - - - x = - x" by (metis sba2_idempotent sba2_sub_sup_demorgan) show "\x y. - (x \ - x) = - (y \ - y)" by (metis sba2_bot_unit sba2_commutative) show "\x y. - x \ - (- x \ y) = - x \ - y" by (simp add: sba2_export) qed text \Theorem 13.2\ lemma double_complement_dist_sup: "--(x \ y) = --x \ --y" by (metis sba2_commutative sba2_export sba2_idempotent sba2_sub_sup_demorgan) lemma maddux_3_3[simp]: "-(x \ y) \ -(x \ -y) = -x" by (metis double_complement_dist_sup sba1_double_complement sba2_commutative sub_complement) lemma huntington_3_pp[simp]: "-(-x \ -y) \ -(-x \ y) = --x" using sba2_commutative maddux_3_3 by fastforce end class subset_boolean_algebra_2_extended = subset_boolean_algebra_2 + subset_extended_1 begin subclass subset_boolean_algebra_1_extended .. subclass bounded_semilattice_sup_bot proof show "\x. bot \ x" using sba2_bot_unit ba_bot_def sup_right_divisibility by auto qed text \Theorem 13.3\ lemma complement_antitone: "x \ y \ -y \ -x" by (metis le_iff_sup maddux_3_3 sba2_export sup_monoid.add_commute) lemma double_complement_isotone: "x \ y \ --x \ --y" by (simp add: complement_antitone) lemma sup_demorgan: "-(x \ y) = -x \ -y" using sba2_sub_sup_demorgan ba_inf by auto end subsection \Axioms for Meet\ text \ We add further axioms of \inf\ covering properties common to the antidomain and pseudocomplement instances. We omit the left distributivity rule and the right zero rule as they do not hold in some models. In particular, the operation \inf\ does not have to be commutative. \ text \Definition 14\ class subset_boolean_algebra_3_extended = subset_boolean_algebra_2_extended + assumes sba3_inf_associative: "x \ (y \ z) = (x \ y) \ z" assumes sba3_inf_right_dist_sup: "(x \ y) \ z = (x \ z) \ (y \ z)" assumes sba3_inf_complement_bot: "-x \ x = bot" assumes sba3_inf_left_unit[simp]: "top \ x = x" assumes sba3_complement_inf_double_complement: "-(x \ --y) = -(x \ y)" begin text \Theorem 15\ lemma inf_left_zero: "bot \ x = bot" by (metis inf_right_unit sba3_inf_associative sba3_inf_complement_bot) lemma inf_double_complement_export: "--(--x \ y) = --x \ --y" by (metis inf_closed sba3_complement_inf_double_complement) lemma inf_left_isotone: "x \ y \ x \ z \ y \ z" using sba3_inf_right_dist_sup sup_right_divisibility by auto lemma inf_complement_export: "--(-x \ y) = -x \ --y" by (metis inf_double_complement_export sba1_double_complement) lemma double_complement_above: "--x \ x = x" by (metis sup_monoid.add_0_right complement_bot inf_demorgan sba1_double_complement sba3_inf_complement_bot sba3_inf_right_dist_sup sba3_inf_left_unit) lemma "x \ y \ z \ x \ z \ y" nitpick [expect=genuine] oops lemma "x \ top = x" nitpick [expect=genuine] oops lemma "x \ y = y \ x" nitpick [expect=genuine] oops end subsection \Stronger Assumptions for Meet\ text \ The following axioms also hold in both models, but follow from the axioms of \subset_boolean_algebra_5_operations\. \ text \Definition 16\ class subset_boolean_algebra_4_extended = subset_boolean_algebra_3_extended + assumes sba4_inf_right_unit[simp]: "x \ top = x" assumes inf_right_isotone: "x \ y \ z \ x \ z \ y" begin lemma "x \ top = top" nitpick [expect=genuine] oops lemma "x \ bot = bot" nitpick [expect=genuine] oops lemma "x \ (y \ z) = (x \ y) \ (x \ z)" nitpick [expect=genuine] oops lemma "(x \ y = bot) = (x \ - y)" nitpick [expect=genuine] oops end section \Boolean Algebras in Stone Algebras\ text \ We specialise \inf\ to meet and complement to pseudocomplement. This puts Stone algebras into the picture; for these it is well known that regular elements form a Boolean subalgebra \cite{Graetzer1971}. \ text \Definition 17\ class subset_boolean_algebra_5_extended = subset_boolean_algebra_3_extended + assumes sba5_inf_commutative: "x \ y = y \ x" assumes sba5_inf_absorb: "x \ (x \ y) = x" begin subclass distrib_lattice_bot proof show "\x y. x \ y \ x" by (metis sba5_inf_commutative sba3_inf_right_dist_sup sba5_inf_absorb sup_right_divisibility) show "\x y. x \ y \ y" by (metis inf_left_isotone sba5_inf_absorb sba5_inf_commutative sup_ge2) show "\x y z. x \ y \ x \ z \ x \ y \ z" by (metis inf_left_isotone sba5_inf_absorb sup.orderE sup_monoid.add_commute) show "\x y z. x \ y \ z = (x \ y) \ (x \ z) " by (metis sba3_inf_right_dist_sup sba5_inf_absorb sba5_inf_commutative sup_assoc) qed lemma inf_demorgan_2: "-(x \ y) = -x \ -y" using sba3_complement_inf_double_complement sba5_inf_commutative sub_sup_closed sub_sup_demorgan by auto lemma inf_export: "x \ -(x \ y) = x \ -y" using inf_demorgan_2 sba3_inf_complement_bot sba3_inf_right_dist_sup sba5_inf_commutative by auto lemma complement_inf[simp]: "x \ -x = bot" using sba3_inf_complement_bot sba5_inf_commutative by auto text \Theorem 18.2\ subclass stone_algebra proof show "\x. x \ top" by (simp add: inf.absorb_iff2) show "\x y. (x \ y = bot) = (x \ - y)" by (metis (full_types) complement_bot complement_inf inf.cobounded1 inf.order_iff inf_export sba3_complement_inf_double_complement sba3_inf_left_unit) show "\x. - x \ - - x = top" by simp qed text \Theorem 18.1\ subclass subset_boolean_algebra_4_extended proof show "\x. x \ top = x" by simp show "\x y z. x \ y \ z \ x \ z \ y" using inf.sup_right_isotone by blast qed end context stone_algebra_extended begin text \Theorem 18.3\ subclass subset_boolean_algebra_5_extended proof show "\x y z. x \ (y \ z) = x \ y \ z" using sup_assoc by auto show "\x y. x \ y = y \ x" by (simp add: sup_commute) show "\x. x \ x = x" by simp show "\x y. x \ - (y \ - y) = x" by simp show "\x y. - (x \ y) = - (- - x \ - - y)" by auto show "\x y. - x \ - (- x \ y) = - x \ - y" by (metis maddux_3_21_pp p_dist_sup regular_closed_p) show "bot = (THE x. \z. x = - (z \ - z))" by simp thus "top = - (THE x. \z. x = - (z \ - z))" using p_bot by blast show "\x y. - x \ - y = - (- - x \ - - y)" by simp show "\x y. - x - - y = - (- - x \ - y)" by auto show "\x y. (x \ y) = (x \ y = y)" by (simp add: le_iff_sup) thus "\x y. (x < y) = (x \ y = y \ y \ x \ x)" by (simp add: less_le_not_le) show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: inf.sup_monoid.add_assoc) show "\x y z. (x \ y) \ z = x \ z \ y \ z" by (simp add: inf_sup_distrib2) show "\x. - x \ x = bot" by simp show "\x. top \ x = x" by simp show "\x y. - (x \ - - y) = - (x \ y)" by simp show "\x y. x \ y = y \ x" by (simp add: inf_commute) show "\x y. x \ (x \ y) = x" by simp qed end section \Domain Semirings\ text \ The following development of tests in IL-semirings, prepredomain semirings, predomain semirings and domain semirings is mostly based on \cite{MoellerDesharnais2019}; see also \cite{DesharnaisMoeller2014}. See \cite{DesharnaisMoellerStruth2006b} for domain axioms in idempotent semirings. See \cite{DesharnaisJipsenStruth2009,JacksonStokes2004} for domain axioms in semigroups and monoids. Some variants have been implemented in \cite{GomesGuttmannHoefnerStruthWeber2016}. \ subsection \Idempotent Left Semirings\ text \Definition 19\ class il_semiring = sup + inf + bot + top + ord + assumes il_associative: "x \ (y \ z) = (x \ y) \ z" assumes il_commutative: "x \ y = y \ x" assumes il_idempotent[simp]: "x \ x = x" assumes il_bot_unit: "x \ bot = x" assumes il_inf_associative: "x \ (y \ z) = (x \ y) \ z" assumes il_inf_right_dist_sup: "(x \ y) \ z = (x \ z) \ (y \ z)" assumes il_inf_left_unit[simp]: "top \ x = x" assumes il_inf_right_unit[simp]: "x \ top = x" assumes il_sub_inf_left_zero[simp]: "bot \ x = bot" assumes il_sub_inf_right_isotone: "x \ y \ z \ x \ z \ y" assumes il_less_eq: "x \ y \ x \ y = y" assumes il_less_def: "x < y \ x \ y \ \(y \ x)" begin lemma il_unit_bot: "bot \ x = x" using il_bot_unit il_commutative by fastforce subclass order proof show "\x y. (x < y) = (x \ y \ \ y \ x)" by (simp add: il_less_def) show "\x. x \ x" by (simp add: il_less_eq) show "\x y z. x \ y \ y \ z \ x \ z" by (metis il_associative il_less_eq) show "\x y. x \ y \ y \ x \ x = y" by (simp add: il_commutative il_less_eq) qed lemma il_sub_inf_right_isotone_var: "(x \ y) \ (x \ z) \ x \ (y \ z)" by (smt il_associative il_commutative il_idempotent il_less_eq il_sub_inf_right_isotone) lemma il_sub_inf_left_isotone: "x \ y \ x \ z \ y \ z" by (metis il_inf_right_dist_sup il_less_eq) lemma il_sub_inf_left_isotone_var: "(y \ x) \ (z \ x) \ (y \ z) \ x" by (simp add: il_inf_right_dist_sup) lemma sup_left_isotone: "x \ y \ x \ z \ y \ z" by (smt il_associative il_commutative il_idempotent il_less_eq) lemma sup_right_isotone: "x \ y \ z \ x \ z \ y" by (simp add: il_commutative sup_left_isotone) lemma bot_least: "bot \ x" by (simp add: il_less_eq il_unit_bot) lemma less_eq_bot: "x \ bot \ x = bot" by (simp add: il_bot_unit il_less_eq) abbreviation are_complementary :: "'a \ 'a \ bool" where "are_complementary x y \ x \ y = top \ x \ y = bot \ y \ x = bot" abbreviation test :: "'a \ bool" where "test x \ \y . are_complementary x y" definition tests :: "'a set" where "tests = { x . test x }" lemma bot_test: "test bot" by (simp add: il_unit_bot) lemma top_test: "test top" by (simp add: il_bot_unit) lemma test_sub_identity: "test x \ x \ top" using il_associative il_less_eq by auto lemma neg_unique: "are_complementary x y \ are_complementary x z \ y = z" by (metis order.antisym il_inf_left_unit il_inf_right_dist_sup il_inf_right_unit il_sub_inf_right_isotone_var) definition neg :: "'a \ 'a" ("!") where "!x \ THE y . are_complementary x y" lemma neg_char: assumes "test x" shows "are_complementary x (!x)" proof (unfold neg_def) from assms obtain y where 1: "are_complementary x y" by auto show "are_complementary x (THE y. are_complementary x y)" proof (rule theI) show "are_complementary x y" using 1 by simp show "\z. are_complementary x z \ z = y" using 1 neg_unique by blast qed qed lemma are_complementary_symmetric: "are_complementary x y \ are_complementary y x" using il_commutative by auto lemma neg_test: "test x \ test (!x)" using are_complementary_symmetric neg_char by blast lemma are_complementary_test: "test x \ are_complementary x y \ test y" using il_commutative by auto lemma neg_involutive: "test x \ !(!x) = x" using are_complementary_symmetric neg_char neg_unique by blast lemma test_inf_left_below: "test x \ x \ y \ y" by (metis il_associative il_idempotent il_inf_left_unit il_inf_right_dist_sup il_less_eq) lemma test_inf_right_below: "test x \ y \ x \ y" by (metis il_inf_right_unit il_sub_inf_right_isotone test_sub_identity) lemma neg_bot: "!bot = top" using il_unit_bot neg_char by fastforce lemma neg_top: "!top = bot" using bot_test neg_bot neg_involutive by fastforce lemma test_inf_idempotent: "test x \ x \ x = x" by (metis il_bot_unit il_inf_left_unit il_inf_right_dist_sup) lemma test_inf_semicommutative: assumes "test x" and "test y" shows "x \ y \ y \ x" proof - have "x \ y = (y \ x \ y) \ (!y \ x \ y)" by (metis assms(2) il_inf_left_unit il_inf_right_dist_sup neg_char) also have "... \ (y \ x \ y) \ (!y \ y)" proof - obtain z where "are_complementary y z" using assms(2) by blast hence "y \ (x \ y) \ !y \ (x \ y) \ y \ (x \ y)" by (metis assms(1) calculation il_sub_inf_left_isotone il_bot_unit il_idempotent il_inf_associative il_less_eq neg_char test_inf_right_below) thus ?thesis by (simp add: il_associative il_inf_associative il_less_eq) qed also have "... \ (y \ x) \ (!y \ y)" by (metis assms(2) il_bot_unit il_inf_right_unit il_sub_inf_right_isotone neg_char test_sub_identity) also have "... = y \ x" by (simp add: assms(2) il_bot_unit neg_char) finally show ?thesis . qed lemma test_inf_commutative: "test x \ test y \ x \ y = y \ x" by (simp add: order.antisym test_inf_semicommutative) lemma test_inf_bot: "test x \ x \ bot = bot" using il_inf_associative test_inf_idempotent by fastforce lemma test_absorb_1: "test x \ test y \ x \ (x \ y) = x" using il_commutative il_less_eq test_inf_right_below by auto lemma test_absorb_2: "test x \ test y \ x \ (y \ x) = x" by (metis test_absorb_1 test_inf_commutative) lemma test_absorb_3: "test x \ test y \ x \ (x \ y) = x" apply (rule order.antisym) apply (metis il_associative il_inf_right_unit il_less_eq il_sub_inf_right_isotone test_sub_identity) by (metis il_sub_inf_right_isotone_var test_absorb_1 test_inf_idempotent) lemma test_absorb_4: "test x \ test y \ (x \ y) \ x = x" by (smt il_inf_right_dist_sup test_inf_idempotent il_commutative il_less_eq test_inf_left_below) lemma test_import_1: assumes "test x" and "test y" shows "x \ (!x \ y) = x \ y" proof - have "x \ (!x \ y) = x \ ((y \ !y) \ x) \ (!x \ y)" by (simp add: assms(2) neg_char) also have "... = x \ (!y \ x) \ (x \ y) \ (!x \ y)" by (smt assms il_associative il_commutative il_inf_right_dist_sup test_inf_commutative) also have "... = x \ ((x \ !x) \ y)" by (smt calculation il_associative il_commutative il_idempotent il_inf_right_dist_sup) also have "... = x \ y" by (simp add: assms(1) neg_char) finally show ?thesis . qed lemma test_import_2: assumes "test x" and "test y" shows "x \ (y \ !x) = x \ y" proof - obtain z where 1: "are_complementary y z" using assms(2) by moura obtain w where 2: "are_complementary x w" using assms(1) by auto hence "x \ !x = bot" using neg_char by blast hence "!x \ y = y \ !x" using 1 2 by (metis il_commutative neg_char test_inf_commutative) thus ?thesis using 1 2 by (metis test_import_1) qed lemma test_import_3: assumes "test x" shows "(!x \ y) \ x = y \ x" by (simp add: assms(1) il_inf_right_dist_sup il_unit_bot neg_char) lemma test_import_4: assumes "test x" and "test y" shows "(!x \ y) \ x = x \ y" by (metis assms test_import_3 test_inf_commutative) lemma test_inf: "test x \ test y \ test z \ z \ x \ y \ z \ x \ z \ y" apply (rule iffI) using dual_order.trans test_inf_left_below test_inf_right_below apply blast by (smt il_less_eq il_sub_inf_right_isotone test_absorb_4) lemma test_shunting: assumes "test x" and "test y" shows "x \ y \ z \ x \ !y \ z" proof assume 1: "x \ y \ z" have "x = (!y \ x) \ (y \ x)" by (metis assms(2) il_commutative il_inf_left_unit il_inf_right_dist_sup neg_char) also have "... \ !y \ (y \ x)" by (simp add: assms(1) sup_left_isotone test_inf_right_below) also have "... \ !y \ z" using 1 by (simp add: assms sup_right_isotone test_inf_commutative) finally show "x \ !y \ z" . next assume "x \ !y \ z" hence "x \ y \ (!y \ z) \ y" using il_sub_inf_left_isotone by blast also have "... = z \ y" by (simp add: assms(2) test_import_3) also have "... \ z" by (simp add: assms(2) test_inf_right_below) finally show "x \ y \ z" . qed lemma test_shunting_bot: assumes "test x" and "test y" shows "x \ y \ x \ !y \ bot" by (simp add: assms il_bot_unit neg_involutive neg_test test_shunting) lemma test_shunting_bot_eq: assumes "test x" and "test y" shows "x \ y \ x \ !y = bot" by (simp add: assms test_shunting_bot less_eq_bot) lemma neg_antitone: assumes "test x" and "test y" and "x \ y" shows "!y \ !x" proof - have 1: "x \ !y = bot" using assms test_shunting_bot_eq by blast have 2: "x \ !x = top" by (simp add: assms(1) neg_char) have "are_complementary y (!y)" by (simp add: assms(2) neg_char) thus ?thesis using 1 2 by (metis il_unit_bot il_commutative il_inf_left_unit il_inf_right_dist_sup il_inf_right_unit il_sub_inf_right_isotone test_sub_identity) qed lemma test_sup_neg_1: assumes "test x" and "test y" shows "(x \ y) \ (!x \ !y) = top" proof - have "x \ !x = top" by (simp add: assms(1) neg_char) hence "x \ (y \ !x) = top" by (metis assms(2) il_associative il_commutative il_idempotent) hence "x \ (y \ !x \ !y) = top" by (simp add: assms neg_test test_import_2) thus ?thesis by (simp add: il_associative) qed lemma test_sup_neg_2: assumes "test x" and "test y" shows "(x \ y) \ (!x \ !y) = bot" proof - have 1: "are_complementary y (!y)" by (simp add: assms(2) neg_char) obtain z where 2: "are_complementary x z" using assms(1) by auto hence "!x = z" using neg_char neg_unique by blast thus ?thesis using 1 2 by (metis are_complementary_symmetric il_inf_associative neg_involutive test_import_3 test_inf_bot test_inf_commutative) qed lemma de_morgan_1: assumes "test x" and "test y" and "test (x \ y)" shows "!(x \ y) = !x \ !y" proof (rule order.antisym) have 1: "test (!(x \ y))" by (simp add: assms neg_test) have "x \ (x \ y) \ !y" by (metis (full_types) assms il_commutative neg_char test_shunting test_shunting_bot_eq) hence "x \ !(x \ y) \ !y" using 1 by (simp add: assms(1,3) neg_involutive test_shunting) hence "!(x \ y) \ x \ !y" using 1 by (metis assms(1) test_inf_commutative) thus "!(x \ y) \ !x \ !y" using 1 assms(1) test_shunting by blast have 2: "!x \ !(x \ y)" by (simp add: assms neg_antitone test_inf_right_below) have "!y \ !(x \ y)" by (simp add: assms neg_antitone test_inf_left_below) thus "!x \ !y \ !(x \ y)" using 2 by (metis il_associative il_less_eq) qed lemma de_morgan_2: assumes "test x" and "test y" and "test (x \ y)" shows "!(x \ y) = !x \ !y" proof (rule order.antisym) have 1: "!(x \ y) \ !x" by (metis assms il_inf_left_unit il_sub_inf_left_isotone neg_antitone test_absorb_3 test_sub_identity) have "!(x \ y) \ !y" by (metis assms il_commutative il_inf_left_unit il_sub_inf_left_isotone neg_antitone test_absorb_3 test_sub_identity) thus "!(x \ y) \ !x \ !y" using 1 by (simp add: assms neg_test test_inf) have "top \ x \ y \ !(x \ y)" by (simp add: assms(3) neg_char) hence "top \ !x \ y \ !(x \ y)" by (smt assms(1) assms(3) il_commutative il_inf_right_dist_sup il_inf_right_unit il_sub_inf_right_isotone il_unit_bot neg_char test_sub_identity) thus "!x \ !y \ !(x \ y)" by (simp add: assms(1) assms(2) neg_involutive neg_test test_shunting) qed lemma test_inf_closed_sup_complement: assumes "test x" and "test y" and "\u v . test u \ test v \ test (u \ v)" shows "!x \ !y \ (x \ y) = bot" proof - have 1: "!(!x \ !y) = x \ y" by (simp add: assms de_morgan_1 neg_involutive neg_test) have "test (!(!x \ !y))" by (metis assms neg_test) thus ?thesis using 1 by (metis assms(1,2) de_morgan_2 neg_char) qed lemma test_sup_complement_sup_closed: assumes "test x" and "test y" and "\u v . test u \ test v \ !u \ !v \ (u \ v) = bot" shows "test (x \ y)" by (meson assms test_sup_neg_1 test_sup_neg_2) lemma test_inf_closed_sup_closed: assumes "test x" and "test y" and "\u v . test u \ test v \ test (u \ v)" shows "test (x \ y)" using assms test_inf_closed_sup_complement test_sup_complement_sup_closed by simp end subsection \Prepredomain Semirings\ class dom = fixes d :: "'a \ 'a" class ppd_semiring = il_semiring + dom + assumes d_closed: "test (d x)" assumes d1: "x \ d x \ x" begin lemma d_sub_identity: "d x \ top" using d_closed test_sub_identity by blast lemma d1_eq: "x = d x \ x" proof - have "x = (d x \ top) \ x" using d_sub_identity il_less_eq by auto thus ?thesis using d1 il_commutative il_inf_right_dist_sup il_less_eq by force qed lemma d_increasing_sub_identity: "x \ top \ x \ d x" by (metis d1_eq il_inf_right_unit il_sub_inf_right_isotone) lemma d_top: "d top = top" by (simp add: d_increasing_sub_identity d_sub_identity dual_order.antisym) lemma d_bot_only: "d x = bot \ x = bot" by (metis d1_eq il_sub_inf_left_zero) lemma d_strict: "d bot \ bot" nitpick [expect=genuine] oops lemma d_isotone_var: "d x \ d (x \ y)" nitpick [expect=genuine] oops lemma d_fully_strict: "d x = bot \ x = bot" nitpick [expect=genuine] oops lemma test_d_fixpoint: "test x \ d x = x" nitpick [expect=genuine] oops end subsection \Predomain Semirings\ class pd_semiring = ppd_semiring + assumes d2: "test p \ d (p \ x) \ p" begin lemma d_strict: "d bot \ bot" using bot_test d2 by fastforce lemma d_strict_eq: "d bot = bot" using d_strict il_bot_unit il_less_eq by auto lemma test_d_fixpoint: "test x \ d x = x" by (metis order.antisym d1_eq d2 test_inf_idempotent test_inf_right_below) lemma d_surjective: "test x \ \y . d y = x" using test_d_fixpoint by blast lemma test_d_fixpoint_iff: "test x \ d x = x" by (metis d_closed test_d_fixpoint) lemma d_surjective_iff: "test x \ (\y . d y = x)" using d_surjective d_closed by blast lemma tests_d_range: "tests = range d" using tests_def image_def d_surjective_iff by auto lemma llp: assumes "test y" shows "d x \ y \ x \ y \ x" by (metis assms d1_eq d2 order.eq_iff il_sub_inf_left_isotone test_inf_left_below) lemma gla: assumes "test y" shows "y \ !(d x) \ y \ x \ bot" proof - obtain ad where 1: "\x. are_complementary (d x) (ad x)" using d_closed by moura hence 2: "\x y. d (d y \ x) \ d y" using d2 by blast have 3: "\x. ad x \ x = bot" using 1 by (metis d1_eq il_inf_associative il_sub_inf_left_zero) have 4: "\x y. d y \ x \ ad y \ x = top \ x" using 1 by (metis il_inf_right_dist_sup) have 5: "\x y z. z \ y \ x \ y \ (z \ x) \ y \ x \ y" by (simp add: il_inf_right_dist_sup il_less_eq) have 6: "\x. !(d x) = ad x" using 1 neg_char neg_unique by blast have 7: "\x. top \ x = x" by auto hence "\x. y \ x \ !y \ x = x" by (metis assms il_inf_right_dist_sup neg_char) thus ?thesis using 1 2 3 4 5 6 7 by (metis assms d1_eq il_commutative il_less_eq test_d_fixpoint) qed lemma gla_var: "test y \ y \ d x \ bot \ y \ x \ bot" using gla d_closed il_bot_unit test_shunting by auto lemma llp_var: assumes "test y" shows "y \ !(d x) \ x \ !y \ x" apply (rule iffI) apply (metis (no_types, opaque_lifting) assms gla Least_equality il_inf_left_unit il_inf_right_dist_sup il_less_eq il_unit_bot order.refl neg_char) by (metis assms gla gla_var llp il_commutative il_sub_inf_right_isotone neg_char) lemma d_idempotent: "d (d x) = d x" using d_closed test_d_fixpoint_iff by auto lemma d_neg: "test x \ d (!x) = !x" using il_commutative neg_char test_d_fixpoint_iff by fastforce lemma d_fully_strict: "d x = bot \ x = bot" using d_strict_eq d_bot_only by blast lemma d_ad_comp: "!(d x) \ x = bot" proof - have "\x. !(d x) \ d x = bot" by (simp add: d_closed neg_char) thus ?thesis by (metis d1_eq il_inf_associative il_sub_inf_left_zero) qed lemma d_isotone: assumes "x \ y" shows "d x \ d y" proof - obtain ad where 1: "\x. are_complementary (d x) (ad x)" using d_closed by moura hence "ad y \ x \ bot" by (metis assms d1_eq il_inf_associative il_sub_inf_left_zero il_sub_inf_right_isotone) thus ?thesis using 1 by (metis d2 il_bot_unit il_inf_left_unit il_inf_right_dist_sup il_less_eq) qed lemma d_isotone_var: "d x \ d (x \ y)" using d_isotone il_associative il_less_eq by auto lemma d3_conv: "d (x \ y) \ d (x \ d y)" by (metis (mono_tags, opaque_lifting) d1_eq d2 d_closed il_inf_associative) lemma d_test_inf_idempotent: "d x \ d x = d x" by (metis d_idempotent d1_eq) lemma d_test_inf_closed: assumes "test x" and "test y" shows "d (x \ y) = x \ y" proof (rule order.antisym) have "d (x \ y) = d (x \ y) \ d (x \ y)" by (simp add: d_test_inf_idempotent) also have "... \ x \ d (x \ y)" by (simp add: assms(1) d2 il_sub_inf_left_isotone) also have "... \ x \ y" by (metis assms d_isotone il_sub_inf_right_isotone test_inf_left_below test_d_fixpoint) finally show "d (x \ y) \ x \ y" . show "x \ y \ d (x \ y)" using assms d_increasing_sub_identity dual_order.trans test_inf_left_below test_sub_identity by blast qed lemma test_inf_closed: "test x \ test y \ test (x \ y)" using d_test_inf_closed test_d_fixpoint_iff by simp lemma test_sup_closed: "test x \ test y \ test (x \ y)" using test_inf_closed test_inf_closed_sup_closed by simp lemma d_export: assumes "test x" shows "d (x \ y) = x \ d y" proof (rule order.antisym) have 1: "d (x \ y) \ x" by (simp add: assms d2) have "d (x \ y) \ d y" by (metis assms d_isotone_var il_inf_left_unit il_inf_right_dist_sup) thus "d (x \ y) \ x \ d y" using 1 by (metis assms d_idempotent llp dual_order.trans il_sub_inf_right_isotone) have "y = (!x \ y) \ (x \ y)" by (metis assms il_commutative il_inf_left_unit il_inf_right_dist_sup neg_char) also have "... = (!x \ y) \ (d (x \ y) \ x \ y)" by (metis d1_eq il_inf_associative) also have "... = (!x \ y) \ (d (x \ y) \ y)" using 1 by (smt calculation d1_eq il_associative il_commutative il_inf_associative il_inf_right_dist_sup il_less_eq il_sub_inf_right_isotone_var) also have "... = (!x \ d (x \ y)) \ y" by (simp add: il_inf_right_dist_sup) finally have "y \ (!x \ d (x \ y)) \ y" by simp hence "d y \ !x \ d (x \ y)" using assms llp test_sup_closed neg_test d_closed by simp hence "d y \ x \ d (x \ y)" by (simp add: assms d_closed test_shunting) thus "x \ d y \ d (x \ y)" by (metis assms d_closed test_inf_commutative) qed lemma test_inf_left_dist_sup: assumes "test x" and "test y" and "test z" shows "x \ (y \ z) = (x \ y) \ (x \ z)" proof - have "x \ (y \ z) = (y \ z) \ x" using assms test_sup_closed test_inf_commutative by smt also have "... = (y \ x) \ (z \ x)" using il_inf_right_dist_sup by simp also have "... = (x \ y) \ (x \ z)" using assms test_sup_closed test_inf_commutative by smt finally show ?thesis . qed lemma "!x \ !y = !(!(!x \ !y))" nitpick [expect=genuine] oops lemma "d x = !(!x)" nitpick [expect=genuine] oops sublocale subset_boolean_algebra where uminus = "\ x . !(d x)" proof show "\x y z. !(d x) \ (!(d y) \ !(d z)) = !(d x) \ !(d y) \ !(d z)" using il_associative by blast show "\x y. !(d x) \ !(d y) = !(d y) \ !(d x)" by (simp add: il_commutative) show "\x y. !(d x) \ !(d y) = !(d (!(d (!(d x) \ !(d y)))))" proof - fix x y have "test (!(d x)) \ test (!(d y))" by (simp add: d_closed neg_test) hence "test (!(d x) \ !(d y))" by (simp add: test_sup_closed) thus "!(d x) \ !(d y) = !(d (!(d (!(d x) \ !(d y)))))" by (simp add: d_neg neg_involutive test_d_fixpoint) qed show "\x y. !(d x) = !(d (!(d (!(d x))) \ !(d y))) \ !(d (!(d (!(d x))) \ !(d (!(d y)))))" proof - fix x y have "!(d (!(d (!(d x))) \ !(d y))) \ !(d (!(d (!(d x))) \ !(d (!(d y))))) = !(d x \ !(d y)) \ !(d x \ d y)" using d_closed neg_test test_sup_closed neg_involutive test_d_fixpoint by auto also have "... = (!(d x) \ d y) \ (!(d x) \ !(d y))" using d_closed neg_test test_sup_closed neg_involutive de_morgan_2 by auto also have "... = !(d x) \ (d y \ !(d y))" using d_closed neg_test test_inf_left_dist_sup by auto also have "... = !(d x) \ top" by (simp add: neg_char d_closed) finally show "!(d x) = !(d (!(d (!(d x))) \ !(d y))) \ !(d (!(d (!(d x))) \ !(d (!(d y)))))" by simp qed qed lemma d_dist_sup: "d (x \ y) = d x \ d y" proof (rule order.antisym) have "x \ d x \ x" by (simp add: d1) also have "... \ (d x \ d y) \ (x \ y)" using il_associative il_inf_right_dist_sup il_less_eq il_sub_inf_right_isotone by auto finally have 1: "x \ (d x \ d y) \ (x \ y)" . have "y \ d y \ y" by (simp add: d1) also have "... \ (d y \ d x) \ (y \ x)" using il_associative il_idempotent il_inf_right_dist_sup il_less_eq il_sub_inf_right_isotone by simp finally have "y \ (d x \ d y) \ (x \ y)" using il_commutative by auto hence "x \ y \ (d x \ d y) \ (x \ y)" using 1 by (metis il_associative il_less_eq) thus "d (x \ y) \ d x \ d y" using llp test_sup_closed neg_test d_closed by simp show "d x \ d y \ d (x \ y)" using d_isotone_var il_associative il_commutative il_less_eq by fastforce qed end class pd_semiring_extended = pd_semiring + uminus + assumes uminus_def: "-x = !(d x)" begin subclass subset_boolean_algebra by (metis subset_boolean_algebra_axioms uminus_def ext) end subsection \Domain Semirings\ class d_semiring = pd_semiring + assumes d3: "d (x \ d y) \ d (x \ y)" begin lemma d3_eq: "d (x \ d y) = d (x \ y)" by (simp add: order.antisym d3 d3_conv) end text \ Axioms (d1), (d2) and (d3) are independent in IL-semirings. \ context il_semiring begin context fixes d :: "'a \ 'a" assumes d_closed: "test (d x)" begin context assumes d1: "x \ d x \ x" assumes d2: "test p \ d (p \ x) \ p" begin lemma d3: "d (x \ d y) \ d (x \ y)" nitpick [expect=genuine] oops end context assumes d1: "x \ d x \ x" assumes d3: "d (x \ d y) \ d (x \ y)" begin lemma d2: "test p \ d (p \ x) \ p" nitpick [expect=genuine] oops end context assumes d2: "test p \ d (p \ x) \ p" assumes d3: "d (x \ d y) \ d (x \ y)" begin lemma d1: "x \ d x \ x" nitpick [expect=genuine] oops end end end class d_semiring_var = ppd_semiring + assumes d3_var: "d (x \ d y) \ d (x \ y)" assumes d_strict_eq_var: "d bot = bot" begin lemma d2_var: assumes "test p" shows "d (p \ x) \ p" proof - have "!p \ p \ x = bot" by (simp add: assms neg_char) hence "d (!p \ p \ x) = bot" by (simp add: d_strict_eq_var) hence "d (!p \ d (p \ x)) = bot" by (metis d3_var il_inf_associative less_eq_bot) hence "!p \ d (p \ x) = bot" using d_bot_only by blast thus ?thesis by (metis (no_types, opaque_lifting) assms d_sub_identity il_bot_unit il_inf_left_unit il_inf_right_dist_sup il_inf_right_unit il_sub_inf_right_isotone neg_char) qed subclass d_semiring proof show "\p x. test p \ d (p \ x) \ p" by (simp add: d2_var) show "\x y. d (x \ d y) \ d (x \ y)" by (simp add: d3_var) qed end section \Antidomain Semirings\ text \ We now develop prepreantidomain semirings, preantidomain semirings and antidomain semirings. See \cite{DesharnaisStruth2008b,DesharnaisStruth2008a,DesharnaisStruth2011} for related work on internal axioms for antidomain. \ subsection \Prepreantidomain Semirings\ text \Definition 20\ class ppa_semiring = il_semiring + uminus + assumes a_inf_complement_bot: "-x \ x = bot" assumes a_stone[simp]: "-x \ --x = top" begin text \Theorem 21\ lemma l1: "-top = bot" by (metis a_inf_complement_bot il_inf_right_unit) lemma l2: "-bot = top" by (metis l1 a_stone il_unit_bot) lemma l3: "-x \ -y \ -x \ y = bot" by (metis a_inf_complement_bot il_bot_unit il_inf_right_dist_sup il_less_eq) lemma l5: "--x \ --y \ -y \ -x" by (metis (mono_tags, opaque_lifting) l3 a_stone bot_least il_bot_unit il_inf_left_unit il_inf_right_dist_sup il_inf_right_unit il_sub_inf_right_isotone sup_right_isotone) lemma l4: "---x = -x" by (metis l5 a_inf_complement_bot a_stone order.antisym bot_least il_inf_left_unit il_inf_right_dist_sup il_inf_right_unit il_sub_inf_right_isotone il_unit_bot) lemma l6: "-x \ --x = bot" by (metis l3 l5 a_inf_complement_bot a_stone il_inf_left_unit il_inf_right_dist_sup il_inf_right_unit il_less_eq il_sub_inf_right_isotone il_unit_bot) lemma l7: "-x \ -y = -y \ -x" using l6 a_inf_complement_bot a_stone test_inf_commutative by blast lemma l8: "x \ --x \ x" by (metis a_inf_complement_bot a_stone il_idempotent il_inf_left_unit il_inf_right_dist_sup il_less_eq il_unit_bot) sublocale ppa_ppd: ppd_semiring where d = "\x . --x" proof show "\x. test (- - x)" using l4 l6 by force show "\x. x \ - - x \ x" by (simp add: l8) qed (* The following statements have counterexamples, but they take a while to find. lemma "- x = - (- - x \ - y) \ - (- - x \ - - y)" nitpick [card=8, expect=genuine] oops lemma "- x \ - y = - - (- x \ - y)" nitpick [card=8, expect=genuine] oops *) end subsection \Preantidomain Semirings\ text \Definition 22\ class pa_semiring = ppa_semiring + assumes pad2: "--x \ -(-x \ y)" begin text \Theorem 23\ lemma l10: "-x \ y = bot \ -x \ -y" by (metis a_stone il_inf_left_unit il_inf_right_dist_sup il_unit_bot l4 pad2) lemma l10_iff: "-x \ y = bot \ -x \ -y" using l10 l3 by blast lemma l13: "--(--x \ y) \ --x" by (metis l4 l5 pad2) lemma l14: "-(x \ --y) \ -(x \ y)" by (metis il_inf_associative l4 pad2 ppa_ppd.d1_eq) lemma l9: "x \ y \ -y \ -x" by (metis l10 a_inf_complement_bot il_commutative il_less_eq il_sub_inf_right_isotone il_unit_bot) lemma l11: "- x \ - y = - (- - x \ - - y)" proof - have 1: "\x y . x \ y \ x \ y = y" by (simp add: il_less_eq) have 4: "\x y . \(x \ y) \ x \ y = y" using 1 by metis have 5: "\x y z . (x \ y) \ (x \ z) \ x \ (y \ z)" by (simp add: il_sub_inf_right_isotone_var) have 6: "\x y . - - x \ - (- x \ y)" by (simp add: pad2) have 7: "\x y z . x \ (y \ z) = (x \ y) \ z" by (simp add: il_associative) have 8: "\x y z . (x \ y) \ z = x \ (y \ z)" using 7 by metis have 9: "\x y . x \ y = y \ x" by (simp add: il_commutative) have 10: "\x . x \ bot = x" by (simp add: il_bot_unit) have 11: "\x . x \ x = x" by simp have 12: "\x y z . x \ (y \ z) = (x \ y) \ z" by (simp add: il_inf_associative) have 13: "\x y z . (x \ y) \ z = x \ (y \ z)" using 12 by metis have 14: "\x . top \ x = x" by simp have 15: "\x . x \ top = x" by simp have 16: "\x y z . (x \ y) \ z = (x \ z) \ (y \ z)" by (simp add: il_inf_right_dist_sup) have 17: "\x y z . (x \ y) \ (z \ y) = (x \ z) \ y" using 16 by metis have 18: "\x . bot \ x = bot" by simp have 19: "\x . - x \ - - x = top" by simp have 20: "\x . - x \ x = bot" by (simp add: a_inf_complement_bot) have 23: "\x y z . ((x \ y) \ (x \ z)) \ (x \ (y \ z)) = x \ (y \ z)" using 4 5 by metis have 24: "\x y z . (x \ (y \ z)) \ ((x \ y) \ (x \ z)) = x \ (y \ z)" using 9 23 by metis have 25: "\x y . - - x \ - (- x \ y) = - (- x \ y)" using 4 6 by metis have 26: "\x y z . x \ (y \ z) = y \ (x \ z)" using 8 9 by metis have 27: "\x y z . (x \ y) \ ((x \ z) \ (x \ (y \ z))) = x \ (y \ z)" using 9 24 26 by metis have 30: "\x . bot \ x = x" using 9 10 by metis have 31: "\x y . x \ (x \ y) = x \ y" using 8 11 by metis have 34: "\u x y z . ((x \ y) \ z) \ u = (x \ z) \ ((y \ z) \ u)" using 8 17 by metis have 35: "\u x y z . (x \ (y \ z)) \ (u \ z) = ((x \ y) \ u) \ z" using 13 17 by metis have 36: "\u x y z . (x \ y) \ (z \ (u \ y)) = (x \ (z \ u)) \ y" using 13 17 by metis have 39: "\x y . - x \ (- - x \ y) = top \ y" using 8 19 by metis have 41: "\x y . - x \ (x \ y) = bot" using 13 18 20 by metis have 42: "- top = bot" using 15 20 by metis have 43: "\x y . (- x \ y) \ x = y \ x" using 17 20 30 by metis have 44: "\x y . (x \ - y) \ y = x \ y" using 9 17 20 30 by metis have 46: "\x . - bot \ - - x = - bot" using 9 20 25 by metis have 50: "- bot = top" using 19 30 42 by metis have 51: "\x . top \ - - x = top" using 46 50 by metis have 63: "\x y . x \ ((x \ - y) \ (x \ - - y)) = x" using 9 15 19 26 27 by metis have 66: "\x y . (- (x \ y) \ x) \ (- (x \ y) \ y) = bot" using 9 20 27 30 by metis have 67: "\x y z . (x \ - - y) \ (x \ - (- y \ z)) = x \ - (- y \ z)" using 11 25 27 by metis have 70: "\x y . x \ (x \ - - y) = x" using 9 15 27 31 51 by metis have 82: "\x . top \ - x = top" using 9 19 31 by metis have 89: "\x y . x \ (- y \ x) = x" using 14 17 82 by metis have 102: "\x y z . x \ (y \ (x \ - - z)) = y \ x" using 26 70 by metis have 104: "\x y . x \ (x \ - y) = x" using 9 63 102 by metis have 112: "\x y z . (- x \ y) \ ((- - x \ y) \ z) = y \ z" using 14 19 34 by metis have 117: "\x y z . x \ ((x \ - y) \ z) = x \ z" using 8 104 by metis have 120: "\x y z . x \ (y \ (x \ - z)) = y \ x" using 26 104 by metis have 124: "\x . - - x \ x = x" using 14 19 43 by metis have 128: "\x y . - - x \ (x \ y) = x \ y" using 13 124 by metis have 131: "\x . - x \ - - - x = - x" using 9 25 124 by metis have 133: "\x . - - - x = - x" using 9 104 124 131 by metis have 135: "\x y . - x \ - (- - x \ y) = - (- - x \ y)" using 25 133 by metis have 137: "\x y . (- x \ y) \ - - x = y \ - - x" using 43 133 by metis have 145: "\x y z . ((- (x \ y) \ x) \ z) \ y = z \ y" using 20 30 35 by metis have 183: "\x y z . (x \ (- - (y \ z) \ y)) \ z = (x \ y) \ z" using 17 36 124 by metis have 289: "\x y . - x \ - (- x \ y) = top" using 25 39 82 by metis have 316: "\x y . - (- x \ y) \ x = x" using 14 43 289 by metis have 317: "\x y z . - (- x \ y) \ (x \ z) = x \ z" using 13 316 by metis have 320: "\x y . - x \ - - (- x \ y) = - x" using 9 25 316 by metis have 321: "\x y . - - (- x \ y) \ x = bot" using 41 316 by metis have 374: "\x y . - x \ - (x \ y) = - (x \ y)" using 25 128 133 by metis have 388: "\x y . - (x \ y) \ - x = - x" using 128 316 by metis have 389: "\x y . - - (x \ y) \ - x = bot" using 128 321 by metis have 405: "\x y z . - (x \ y) \ (- x \ z) = - x \ z" using 13 388 by metis have 406: "\x y z . - (x \ (y \ z)) \ - (x \ y) = - (x \ y)" using 13 388 by metis have 420: "\x y . - x \ - - (- x \ y) = - - (- x \ y)" using 316 388 by metis have 422: "\x y z . - - (x \ y) \ (- x \ z) = bot" using 13 18 389 by metis have 758: "\x y z . x \ (x \ (- y \ - z)) = x" using 13 104 117 by metis have 1092: "\x y . - (x \ y) \ x = bot" using 9 30 31 66 by metis have 1130: "\x y z . (- (x \ y) \ z) \ x = z \ x" using 17 30 1092 by metis have 1156: "\x y . - - x \ - (- x \ y) = - - x" using 67 104 124 133 by metis have 2098: "\x y . - - (x \ y) \ x = x" using 14 19 1130 by metis have 2125: "\x y . - - (x \ y) \ y = y" using 9 2098 by metis have 2138: "\x y . - x \ - - (x \ y) = top" using 9 289 2098 by metis have 2139: "\x y . - x \ - (x \ y) = - (x \ y)" using 316 2098 by metis have 2192: "\x y . - - x \ (- y \ x) = - y \ x" using 89 2125 by metis have 2202: "\x y . - x \ - - (y \ x) = top" using 9 289 2125 by metis have 2344: "\x y . - (- x \ y) \ - - y = top" using 89 2202 by metis have 2547: "\x y z . - x \ ((- - x \ - y) \ z) = - x \ (- y \ z)" using 112 117 by metis have 3023: "\x y . - x \ - (- y \ - x) = top" using 9 133 2344 by metis have 3134: "\x y . - (- x \ - y) \ y = y" using 14 43 3023 by metis have 3135: "\x y . - x \ (- y \ - x) = - y \ - x" using 14 44 3023 by metis have 3962: "\x y . - - (x \ y) \ - - x = - - x" using 14 137 2138 by metis have 5496: "\x y z . - - (x \ y) \ - (x \ z) = bot" using 422 2139 by metis have 9414: "\x y . - - (- x \ y) \ y = - x \ y" using 9 104 183 320 by metis have 9520: "\x y z . - - (- x \ y) \ - - (x \ z) = bot" using 374 5496 by metis have 11070: "\x y z . - (- - x \ y) \ (- x \ - z) = - (- - x \ y)" using 317 758 by metis have 12371: "\x y . - x \ - (- - x \ y) = - x" using 133 1156 by metis have 12377: "\x y . - x \ - (x \ y) = - x" using 128 133 1156 by metis have 12384: "\x y . - (x \ y) \ - y = - (x \ y)" using 133 1156 2125 by metis have 12394: "\x y . - - (- x \ - y) = - x \ - y" using 1156 3134 9414 by metis have 12640: "\x y . - x \ - (- y \ x) = - x" using 89 12384 by metis have 24648: "\x y . (- x \ - y) \ - (- x \ - y) = top" using 19 12394 by metis have 28270: "\x y z . - - (x \ y) \ - (- x \ z) = - (- x \ z)" using 374 405 by metis have 28339: "\x y . - (- - (x \ y) \ x) = - (x \ y)" using 124 406 12371 by metis have 28423: "\x y . - (- x \ - y) = - (- y \ - x)" using 13 3135 12394 28339 by metis have 28487: "\x y . - x \ - y = - y \ - x" using 2098 3962 12394 28423 by metis have 52423: "\x y . - (- x \ - (- x \ y)) \ y = y" using 14 145 24648 28487 by metis have 52522: "\x y . - x \ - (- x \ y) = - x \ - y" using 13 12377 12394 12640 28487 52423 by metis have 61103: "\x y z . - (- - x \ y) \ z = - x \ (- y \ z)" using 112 2547 12371 52522 by metis have 61158: "\x y . - - (- x \ y) = - x \ - - y" using 420 52522 by metis have 61231: "\x y z . - x \ (- - y \ - (x \ z)) = - x \ - - y" using 13 15 50 133 9520 52522 61158 by metis have 61313: "\x y . - x \ - y = - (- - y \ x)" using 120 11070 61103 by metis have 61393: "\x y . - (- x \ - - y) = - (- x \ y)" using 13 28270 61158 61231 61313 by metis have 61422: "\x y . - (- - x \ y) = - (- - y \ x)" using 13 135 2192 61158 61313 by metis show ?thesis using 61313 61393 61422 by metis qed lemma l12: "- x \ - y = - (x \ y)" proof - have 1: "\x y . x \ y \ x \ y = y" by (simp add: il_less_eq) have 4: "\x y . \(x \ y) \ x \ y = y" using 1 by metis have 5: "\x y z . (x \ y) \ (x \ z) \ x \ (y \ z)" by (simp add: il_sub_inf_right_isotone_var) have 6: "\x y . - - x \ - (- x \ y)" by (simp add: pad2) have 7: "\x y z . x \ (y \ z) = (x \ y) \ z" by (simp add: il_associative) have 8: "\x y z . (x \ y) \ z = x \ (y \ z)" using 7 by metis have 9: "\x y . x \ y = y \ x" by (simp add: il_commutative) have 10: "\x . x \ bot = x" by (simp add: il_bot_unit) have 11: "\x . x \ x = x" by simp have 12: "\x y z . x \ (y \ z) = (x \ y) \ z" by (simp add: il_inf_associative) have 13: "\x y z . (x \ y) \ z = x \ (y \ z)" using 12 by metis have 14: "\x . top \ x = x" by simp have 15: "\x . x \ top = x" by simp have 16: "\x y z . (x \ y) \ z = (x \ z) \ (y \ z)" by (simp add: il_inf_right_dist_sup) have 17: "\x y z . (x \ y) \ (z \ y) = (x \ z) \ y" using 16 by metis have 18: "\x . bot \ x = bot" by simp have 19: "\x . - x \ - - x = top" by simp have 20: "\x . - x \ x = bot" by (simp add: a_inf_complement_bot) have 22: "\x y z . ((x \ y) \ (x \ z)) \ (x \ (y \ z)) = x \ (y \ z)" using 4 5 by metis have 23: "\x y z . (x \ (y \ z)) \ ((x \ y) \ (x \ z)) = x \ (y \ z)" using 9 22 by metis have 24: "\x y . - - x \ - (- x \ y) = - (- x \ y)" using 4 6 by metis have 25: "\x y z . x \ (y \ z) = y \ (x \ z)" using 8 9 by metis have 26: "\x y z . (x \ y) \ ((x \ z) \ (x \ (y \ z))) = x \ (y \ z)" using 9 23 25 by metis have 29: "\x . bot \ x = x" using 9 10 by metis have 30: "\x y . x \ (x \ y) = x \ y" using 8 11 by metis have 32: "\x y . x \ (y \ x) = y \ x" using 8 9 11 by metis have 33: "\u x y z . ((x \ y) \ z) \ u = (x \ z) \ ((y \ z) \ u)" using 8 17 by metis have 34: "\u x y z . (x \ (y \ z)) \ (u \ z) = ((x \ y) \ u) \ z" using 13 17 by metis have 35: "\u x y z . (x \ y) \ (z \ (u \ y)) = (x \ (z \ u)) \ y" using 13 17 by metis have 36: "\x y . (top \ x) \ y = y \ (x \ y)" using 14 17 by metis have 37: "\x y . (x \ top) \ y = y \ (x \ y)" using 9 14 17 by metis have 38: "\x y . - x \ (- - x \ y) = top \ y" using 8 19 by metis have 40: "\x y . - x \ (x \ y) = bot" using 13 18 20 by metis have 41: "- top = bot" using 15 20 by metis have 42: "\x y . (- x \ y) \ x = y \ x" using 17 20 29 by metis have 43: "\x y . (x \ - y) \ y = x \ y" using 9 17 20 29 by metis have 45: "\x . - bot \ - - x = - bot" using 9 20 24 by metis have 46: "\u x y z . (x \ y) \ (z \ (u \ y)) = z \ ((x \ u) \ y)" using 17 25 by metis have 47: "\x y . - x \ (y \ - - x) = y \ top" using 19 25 by metis have 49: "- bot = top" using 19 29 41 by metis have 50: "\x . top \ - - x = top" using 45 49 by metis have 54: "\u x y z . (x \ y) \ ((x \ z) \ ((x \ (y \ z)) \ u)) = (x \ (y \ z)) \ u" using 8 26 by metis have 58: "\u x y z . (x \ (y \ z)) \ ((x \ (y \ u)) \ (x \ (y \ (z \ u)))) = x \ (y \ (z \ u))" using 13 26 by metis have 60: "\x y . x \ ((x \ y) \ (x \ (y \ top))) = x \ (y \ top)" using 15 25 26 by metis have 62: "\x y . x \ ((x \ - y) \ (x \ - - y)) = x" using 9 15 19 25 26 by metis have 65: "\x y . (- (x \ y) \ x) \ (- (x \ y) \ y) = bot" using 9 20 26 29 by metis have 66: "\x y z . (x \ - - y) \ (x \ - (- y \ z)) = x \ - (- y \ z)" using 11 24 26 by metis have 69: "\x y . x \ (x \ - - y) = x" using 9 15 26 30 50 by metis have 81: "\x . top \ - x = top" using 9 19 30 by metis have 82: "\x y z . (x \ y) \ (x \ (y \ z)) = x \ (y \ z)" using 11 26 30 by metis have 83: "\x y . x \ (x \ (y \ top)) = x \ (y \ top)" using 60 82 by metis have 88: "\x y . x \ (- y \ x) = x" using 14 17 81 by metis have 89: "\x y . top \ (x \ - y) = x \ top" using 25 81 by metis have 91: "\x y z . x \ (y \ (z \ x)) = y \ (z \ x)" using 8 32 by metis have 94: "\x y z . x \ (y \ (- z \ x)) = y \ x" using 25 88 by metis have 101: "\x y z . x \ (y \ (x \ - - z)) = y \ x" using 25 69 by metis have 102: "\x . x \ (x \ bot) = x" using 41 49 69 by metis have 103: "\x y . x \ (x \ - y) = x" using 9 62 101 by metis have 109: "\x y . x \ (y \ (x \ bot)) = y \ x" using 25 102 by metis have 111: "\x y z . (- x \ y) \ ((- - x \ y) \ z) = y \ z" using 14 19 33 by metis have 116: "\x y z . x \ ((x \ - y) \ z) = x \ z" using 8 103 by metis have 119: "\x y z . x \ (y \ (x \ - z)) = y \ x" using 25 103 by metis have 123: "\x . - - x \ x = x" using 14 19 42 by metis have 127: "\x y . - - x \ (x \ y) = x \ y" using 13 123 by metis have 130: "\x . - x \ - - - x = - x" using 9 24 123 by metis have 132: "\x . - - - x = - x" using 9 103 123 130 by metis have 134: "\x y . - x \ - (- - x \ y) = - (- - x \ y)" using 24 132 by metis have 136: "\x y . (- x \ y) \ - - x = y \ - - x" using 42 132 by metis have 138: "\x . - x \ - x = - x" using 123 132 by metis have 144: "\x y z . ((- (x \ y) \ x) \ z) \ y = z \ y" using 20 29 34 by metis have 157: "\x y . (- x \ y) \ - x = (top \ y) \ - x" using 17 36 138 by metis have 182: "\x y z . (x \ (- - (y \ z) \ y)) \ z = (x \ y) \ z" using 17 35 123 by metis have 288: "\x y . - x \ - (- x \ y) = top" using 24 38 81 by metis have 315: "\x y . - (- x \ y) \ x = x" using 14 42 288 by metis have 316: "\x y z . - (- x \ y) \ (x \ z) = x \ z" using 13 315 by metis have 319: "\x y . - x \ - - (- x \ y) = - x" using 9 24 315 by metis have 320: "\x y . - - (- x \ y) \ x = bot" using 40 315 by metis have 373: "\x y . - x \ - (x \ y) = - (x \ y)" using 24 127 132 by metis have 387: "\x y . - (x \ y) \ - x = - x" using 127 315 by metis have 388: "\x y . - - (x \ y) \ - x = bot" using 127 320 by metis have 404: "\x y z . - (x \ y) \ (- x \ z) = - x \ z" using 13 387 by metis have 405: "\x y z . - (x \ (y \ z)) \ - (x \ y) = - (x \ y)" using 13 387 by metis have 419: "\x y . - x \ - - (- x \ y) = - - (- x \ y)" using 315 387 by metis have 420: "\x y . - - x \ - - (x \ y) = - - (x \ y)" using 387 by metis have 421: "\x y z . - - (x \ y) \ (- x \ z) = bot" using 13 18 388 by metis have 536: "\x y . (x \ - - y) \ y = (x \ top) \ y" using 42 47 by metis have 662: "\u x y z . (x \ y) \ ((x \ (z \ y)) \ u) = (x \ (z \ y)) \ u" using 9 32 54 by metis have 705: "\u x y z . (x \ (y \ z)) \ ((x \ (y \ (z \ bot))) \ u) = (x \ (y \ z)) \ u" using 25 54 109 662 by metis have 755: "\x y z . (x \ - y) \ (z \ x) = z \ x" using 32 91 116 by metis have 757: "\x y z . x \ (x \ (- y \ - z)) = x" using 13 103 116 by metis have 930: "\x y z . (- (x \ (y \ z)) \ (x \ y)) \ (- (x \ (y \ z)) \ (x \ z)) = bot" using 9 20 29 58 by metis have 1091: "\x y . - (x \ y) \ x = bot" using 9 29 30 65 by metis have 1092: "\x y . - (x \ y) \ y = bot" using 29 30 65 1091 by metis have 1113: "\u x y z . - (x \ ((y \ z) \ u)) \ (x \ (z \ u)) = bot" using 29 46 65 1091 by metis have 1117: "\x y z . - (x \ y) \ (x \ (- z \ y)) = bot" using 29 65 94 1092 by metis have 1128: "\x y z . - (x \ (y \ z)) \ (x \ y) = bot" using 8 1091 by metis have 1129: "\x y z . (- (x \ y) \ z) \ x = z \ x" using 17 29 1091 by metis have 1155: "\x y . - - x \ - (- x \ y) = - - x" using 66 103 123 132 by metis have 1578: "\x y z . - (x \ (y \ z)) \ (x \ y) = bot" using 82 1091 by metis have 1594: "\x y z . - (x \ (y \ z)) \ (x \ z) = bot" using 29 930 1578 by metis have 2094: "\x y z . - (x \ (y \ (z \ top))) \ (x \ y) = bot" using 83 1128 by metis have 2097: "\x y . - - (x \ y) \ x = x" using 14 19 1129 by metis have 2124: "\x y . - - (x \ y) \ y = y" using 9 2097 by metis have 2135: "\x y . - - ((top \ x) \ y) \ y = y" using 36 2097 by metis have 2136: "\x y . - - ((x \ top) \ y) \ y = y" using 37 2097 by metis have 2137: "\x y . - x \ - - (x \ y) = top" using 9 288 2097 by metis have 2138: "\x y . - x \ - (x \ y) = - (x \ y)" using 315 2097 by metis have 2151: "\x y . - x \ - (x \ y) = - x" using 9 132 373 2097 by metis have 2191: "\x y . - - x \ (- y \ x) = - y \ x" using 88 2124 by metis have 2201: "\x y . - x \ - - (y \ x) = top" using 9 288 2124 by metis have 2202: "\x y . - x \ - (y \ x) = - (y \ x)" using 315 2124 by metis have 2320: "\x y . - (x \ (y \ top)) = - x" using 83 373 2151 by metis have 2343: "\x y . - (- x \ y) \ - - y = top" using 88 2201 by metis have 2546: "\x y z . - x \ ((- - x \ - y) \ z) = - x \ (- y \ z)" using 111 116 by metis have 2706: "\x y z . - x \ (y \ - - ((top \ z) \ - x)) = y \ - - ((top \ z) \ - x)" using 755 2135 by metis have 2810: "\x y . - x \ - ((y \ top) \ x) = - ((y \ top) \ x)" using 315 2136 by metis have 3022: "\x y . - x \ - (- y \ - x) = top" using 9 132 2343 by metis have 3133: "\x y . - (- x \ - y) \ y = y" using 14 42 3022 by metis have 3134: "\x y . - x \ (- y \ - x) = - y \ - x" using 14 43 3022 by metis have 3961: "\x y . - - (x \ y) \ - - x = - - x" using 14 136 2137 by metis have 4644: "\x y z . - (x \ - y) \ (x \ - (y \ z)) = bot" using 1594 2151 by metis have 5495: "\x y z . - - (x \ y) \ - (x \ z) = bot" using 421 2138 by metis have 9413: "\x y . - - (- x \ y) \ y = - x \ y" using 9 103 182 319 by metis have 9519: "\x y z . - - (- x \ y) \ - - (x \ z) = bot" using 373 5495 by metis have 11069: "\x y z . - (- - x \ y) \ (- x \ - z) = - (- - x \ y)" using 316 757 by metis have 12370: "\x y . - x \ - (- - x \ y) = - x" using 132 1155 by metis have 12376: "\x y . - x \ - (x \ y) = - x" using 127 132 1155 by metis have 12383: "\x y . - (x \ y) \ - y = - (x \ y)" using 132 1155 2124 by metis have 12393: "\x y . - - (- x \ - y) = - x \ - y" using 1155 3133 9413 by metis have 12407: "\x y . - - x \ - - (x \ y) = - - x" using 1155 2138 by metis have 12639: "\x y . - x \ - (- y \ x) = - x" using 88 12383 by metis have 24647: "\x y . (- x \ - y) \ - (- x \ - y) = top" using 19 12393 by metis have 28269: "\x y z . - - (x \ y) \ - (- x \ z) = - (- x \ z)" using 373 404 by metis have 28338: "\x y . - (- - (x \ y) \ x) = - (x \ y)" using 123 405 12370 by metis have 28422: "\x y . - (- x \ - y) = - (- y \ - x)" using 13 3134 12393 28338 by metis have 28485: "\x y . - x \ - y = - y \ - x" using 2097 3961 12393 28422 by metis have 30411: "\x y . - x \ (x \ (x \ y)) = bot" using 9 82 2094 2320 by metis have 30469: "\x . - x \ (x \ - - x) = bot" using 9 123 132 30411 by metis have 37513: "\x y . - (- x \ - y) \ - (y \ x) = bot" using 2202 4644 by metis have 52421: "\x y . - (- x \ - (- x \ y)) \ y = y" using 14 144 24647 28485 by metis have 52520: "\x y . - x \ - (- x \ y) = - x \ - y" using 13 12376 12393 12639 28485 52421 by metis have 52533: "\x y z . - - (x \ (y \ (z \ top))) \ (x \ y) = x \ y" using 15 49 2094 52421 by metis have 61101: "\x y z . - (- - x \ y) \ z = - x \ (- y \ z)" using 111 2546 12370 52520 by metis have 61156: "\x y . - - (- x \ y) = - x \ - - y" using 419 52520 by metis have 61162: "\x y . - (x \ (x \ y)) = - x" using 15 49 2138 30411 52520 by metis have 61163: "\x . - (x \ - - x) = - x" using 15 49 2138 30469 52520 by metis have 61229: "\x y z . - x \ (- - y \ - (x \ z)) = - x \ - - y" using 13 15 49 132 9519 52520 61156 by metis have 61311: "\x y . - x \ - y = - (- - y \ x)" using 119 11069 61101 by metis have 61391: "\x y . - (- x \ - - y) = - (- x \ y)" using 13 28269 61156 61229 61311 by metis have 61420: "\x y . - (- - x \ y) = - (- - y \ x)" using 13 134 2191 61156 61311 by metis have 61454: "\x y . - (x \ - (- y \ - x)) = - y \ - x" using 9 132 3133 61156 61162 by metis have 61648: "\x y . - x \ (x \ (- y \ - - x)) = bot" using 1117 61163 by metis have 62434: "\x y . - (- - x \ y) \ x = - y \ x" using 43 61311 by metis have 63947: "\x y . - (- x \ y) \ - (- y \ x) = bot" using 37513 61391 by metis have 64227: "\x y . - (x \ (- y \ - - x)) = - x" using 15 49 2138 52520 61648 by metis have 64239: "\x y . - (x \ (- - x \ y)) = - (x \ y)" using 9 25 12407 64227 by metis have 64241: "\x y . - (x \ (- - x \ - y)) = - x" using 28485 64227 by metis have 64260: "\x y . - (x \ - - (x \ y)) = - x" using 420 64241 by metis have 64271: "\x y . - (- x \ (y \ - - (y \ x))) = - (- x \ y)" using 9 25 42 64260 by metis have 64281: "\x y . - (- x \ y) = - (y \ - - ((top \ y) \ - x))" using 9 25 157 2706 64260 by metis have 64282: "\x y . - (x \ - - ((x \ top) \ y)) = - (x \ - - y)" using 9 25 132 536 2810 28485 61311 64260 by metis have 65110: "\x y . - ((- x \ y) \ (- y \ x)) = bot" using 9 14 49 37513 63947 by metis have 65231: "\x y . - (x \ ((- x \ y) \ - y)) = bot" using 9 25 65110 by metis have 65585: "\x y . - (x \ - y) = - - y \ - x" using 61311 61454 64239 by metis have 65615: "\x y . - x \ - ((x \ top) \ y) = - y \ - x" using 132 28485 64282 65585 by metis have 65616: "\x y . - (- x \ y) = - y \ - ((top \ y) \ - x)" using 132 28485 64281 65585 by metis have 65791: "\x y . - x \ - ((top \ x) \ - y) = - - y \ - x" using 89 132 12376 28485 64271 65585 65615 65616 by metis have 65933: "\x y . - (- x \ y) = - - x \ - y" using 65616 65791 by metis have 66082: "\x y z . - (x \ (y \ - z)) = - - z \ - (x \ y)" using 8 65585 by metis have 66204: "\x y . - - x \ - (y \ (- y \ x)) = bot" using 65231 66082 by metis have 66281: "\x y z . - (x \ (- y \ z)) = - - y \ - (x \ z)" using 25 65933 by metis have 67527: "\x y . - - (x \ (- x \ y)) \ y = y" using 14 49 62434 66204 by metis have 67762: "\x y . - (- - x \ (y \ (- y \ x))) = - x" using 61420 67527 by metis have 68018: "\x y z . - (x \ y) \ (x \ (y \ (z \ top))) = bot" using 8 83 1113 2320 by metis have 71989: "\x y z . - (x \ (y \ (z \ top))) = - (x \ y)" using 9 29 52533 67762 68018 by metis have 71997: "\x y z . - ((x \ (y \ top)) \ z) = - (x \ z)" using 17 2320 71989 by metis have 72090: "\x y z . - (x \ ((x \ y) \ z)) = - (x \ z)" using 10 14 705 71997 by metis have 72139: "\x y . - (x \ y) = - x \ - y" using 25 123 132 2138 65933 66281 72090 by metis show ?thesis using 72139 by metis qed lemma l15: "--(x \ y) = --x \ --y" by (simp add: l11 l12 l4) lemma l13_var: "- - (- x \ y) = - x \ - - y" proof - have 1: "\x y . x \ y \ x \ y = y" by (simp add: il_less_eq) have 4: "\x y . \(x \ y) \ x \ y = y" using 1 by metis have 5: "\x y z . (x \ y) \ (x \ z) \ x \ (y \ z)" by (simp add: il_sub_inf_right_isotone_var) have 6: "\x y . - - x \ - (- x \ y)" by (simp add: pad2) have 7: "\x y z . x \ (y \ z) = (x \ y) \ z" by (simp add: il_associative) have 8: "\x y z . (x \ y) \ z = x \ (y \ z)" using 7 by metis have 9: "\x y . x \ y = y \ x" by (simp add: il_commutative) have 10: "\x . x \ bot = x" by (simp add: il_bot_unit) have 11: "\x . x \ x = x" by simp have 12: "\x y z . x \ (y \ z) = (x \ y) \ z" by (simp add: il_inf_associative) have 13: "\x y z . (x \ y) \ z = x \ (y \ z)" using 12 by metis have 14: "\x . top \ x = x" by simp have 15: "\x . x \ top = x" by simp have 16: "\x y z . (x \ y) \ z = (x \ z) \ (y \ z)" by (simp add: il_inf_right_dist_sup) have 17: "\x y z . (x \ y) \ (z \ y) = (x \ z) \ y" using 16 by metis have 19: "\x . - x \ - - x = top" by simp have 20: "\x . - x \ x = bot" by (simp add: a_inf_complement_bot) have 22: "\x y z . ((x \ y) \ (x \ z)) \ (x \ (y \ z)) = x \ (y \ z)" using 4 5 by metis have 23: "\x y z . (x \ (y \ z)) \ ((x \ y) \ (x \ z)) = x \ (y \ z)" using 9 22 by metis have 24: "\x y . - - x \ - (- x \ y) = - (- x \ y)" using 4 6 by metis have 25: "\x y z . x \ (y \ z) = y \ (x \ z)" using 8 9 by metis have 26: "\x y z . (x \ y) \ ((x \ z) \ (x \ (y \ z))) = x \ (y \ z)" using 9 23 25 by metis have 29: "\x . bot \ x = x" using 9 10 by metis have 30: "\x y . x \ (x \ y) = x \ y" using 8 11 by metis have 34: "\u x y z . (x \ (y \ z)) \ (u \ z) = ((x \ y) \ u) \ z" using 13 17 by metis have 35: "\u x y z . (x \ y) \ (z \ (u \ y)) = (x \ (z \ u)) \ y" using 13 17 by metis have 38: "\x y . - x \ (- - x \ y) = top \ y" using 8 19 by metis have 41: "- top = bot" using 15 20 by metis have 42: "\x y . (- x \ y) \ x = y \ x" using 17 20 29 by metis have 43: "\x y . (x \ - y) \ y = x \ y" using 9 17 20 29 by metis have 45: "\x . - bot \ - - x = - bot" using 9 20 24 by metis have 49: "- bot = top" using 19 29 41 by metis have 50: "\x . top \ - - x = top" using 45 49 by metis have 62: "\x y . x \ ((x \ - y) \ (x \ - - y)) = x" using 9 15 19 25 26 by metis have 65: "\x y . (- (x \ y) \ x) \ (- (x \ y) \ y) = bot" using 9 20 26 29 by metis have 66: "\x y z . (x \ - - y) \ (x \ - (- y \ z)) = x \ - (- y \ z)" using 11 24 26 by metis have 69: "\x y . x \ (x \ - - y) = x" using 9 15 26 30 50 by metis have 81: "\x . top \ - x = top" using 9 19 30 by metis have 88: "\x y . x \ (- y \ x) = x" using 14 17 81 by metis have 101: "\x y z . x \ (y \ (x \ - - z)) = y \ x" using 25 69 by metis have 103: "\x y . x \ (x \ - y) = x" using 9 62 101 by metis have 123: "\x . - - x \ x = x" using 14 19 42 by metis have 127: "\x y . - - x \ (x \ y) = x \ y" using 13 123 by metis have 130: "\x . - x \ - - - x = - x" using 9 24 123 by metis have 132: "\x . - - - x = - x" using 9 103 123 130 by metis have 136: "\x y . (- x \ y) \ - - x = y \ - - x" using 42 132 by metis have 144: "\x y z . ((- (x \ y) \ x) \ z) \ y = z \ y" using 20 29 34 by metis have 182: "\x y z . (x \ (- - (y \ z) \ y)) \ z = (x \ y) \ z" using 17 35 123 by metis have 288: "\x y . - x \ - (- x \ y) = top" using 24 38 81 by metis have 315: "\x y . - (- x \ y) \ x = x" using 14 42 288 by metis have 319: "\x y . - x \ - - (- x \ y) = - x" using 9 24 315 by metis have 387: "\x y . - (x \ y) \ - x = - x" using 127 315 by metis have 405: "\x y z . - (x \ (y \ z)) \ - (x \ y) = - (x \ y)" using 13 387 by metis have 419: "\x y . - x \ - - (- x \ y) = - - (- x \ y)" using 315 387 by metis have 1091: "\x y . - (x \ y) \ x = bot" using 9 29 30 65 by metis have 1129: "\x y z . (- (x \ y) \ z) \ x = z \ x" using 17 29 1091 by metis have 1155: "\x y . - - x \ - (- x \ y) = - - x" using 66 103 123 132 by metis have 2097: "\x y . - - (x \ y) \ x = x" using 14 19 1129 by metis have 2124: "\x y . - - (x \ y) \ y = y" using 9 2097 by metis have 2137: "\x y . - x \ - - (x \ y) = top" using 9 288 2097 by metis have 2201: "\x y . - x \ - - (y \ x) = top" using 9 288 2124 by metis have 2343: "\x y . - (- x \ y) \ - - y = top" using 88 2201 by metis have 3022: "\x y . - x \ - (- y \ - x) = top" using 9 132 2343 by metis have 3133: "\x y . - (- x \ - y) \ y = y" using 14 42 3022 by metis have 3134: "\x y . - x \ (- y \ - x) = - y \ - x" using 14 43 3022 by metis have 3961: "\x y . - - (x \ y) \ - - x = - - x" using 14 136 2137 by metis have 9413: "\x y . - - (- x \ y) \ y = - x \ y" using 9 103 182 319 by metis have 12370: "\x y . - x \ - (- - x \ y) = - x" using 132 1155 by metis have 12376: "\x y . - x \ - (x \ y) = - x" using 127 132 1155 by metis have 12383: "\x y . - (x \ y) \ - y = - (x \ y)" using 132 1155 2124 by metis have 12393: "\x y . - - (- x \ - y) = - x \ - y" using 1155 3133 9413 by metis have 12639: "\x y . - x \ - (- y \ x) = - x" using 88 12383 by metis have 24647: "\x y . (- x \ - y) \ - (- x \ - y) = top" using 19 12393 by metis have 28338: "\x y . - (- - (x \ y) \ x) = - (x \ y)" using 123 405 12370 by metis have 28422: "\x y . - (- x \ - y) = - (- y \ - x)" using 13 3134 12393 28338 by metis have 28485: "\x y . - x \ - y = - y \ - x" using 2097 3961 12393 28422 by metis have 52421: "\x y . - (- x \ - (- x \ y)) \ y = y" using 14 144 24647 28485 by metis have 52520: "\x y . - x \ - (- x \ y) = - x \ - y" using 13 12376 12393 12639 28485 52421 by metis have 61156: "\x y . - - (- x \ y) = - x \ - - y" using 419 52520 by metis show ?thesis using 61156 by metis qed text \Theorem 25.1\ subclass subset_boolean_algebra_2 proof show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: il_associative) show "\x y. x \ y = y \ x" by (simp add: il_commutative) show "\x. x \ x = x" by simp show "\x y. x \ - (y \ - y) = x" using il_bot_unit l12 l6 by auto show "\x y. - (x \ y) = - (- - x \ - - y)" by (metis l15 l4) show "\x y. - x \ - (- x \ y) = - x \ - y" by (smt l11 l15 il_inf_right_dist_sup il_unit_bot l6 l7) qed lemma aa_test: "p = --p \ test p" by (metis ppa_ppd.d_closed) lemma test_aa_increasing: "test p \ p \ --p" by (simp add: ppa_ppd.d_increasing_sub_identity test_sub_identity) lemma "test p \ - - (p \ x) \ p" nitpick [expect=genuine] oops lemma "test p \ --p \ p" nitpick [expect=genuine] oops end class pa_algebra = pa_semiring + minus + assumes pa_minus_def: "-x - -y = -(--x \ -y)" begin subclass subset_boolean_algebra_2_extended proof show "bot = (THE x. \z. x = - (z \ - z))" using l12 l6 by auto thus "top = - (THE x. \z. x = - (z \ - z))" using l2 by blast show "\x y. - x \ - y = - (- - x \ - - y)" by (metis l12 l4) show "\x y. - x - - y = - (- - x \ - y)" by (simp add: pa_minus_def) show "\x y. (x \ y) = (x \ y = y)" by (simp add: il_less_eq) show "\x y. (x < y) = (x \ y = y \ y \ x \ x)" by (simp add: il_less_eq less_le_not_le) qed lemma "\x y. - (x \ - - y) = - (x \ y)" nitpick [expect=genuine] oops end subsection \Antidomain Semirings\ text \Definition 24\ class a_semiring = ppa_semiring + assumes ad3: "-(x \ y) \ -(x \ --y)" begin lemma l16: "- - x \ - (- x \ y)" proof - have 1: "\x y . x \ y \ x \ y = y" by (simp add: il_less_eq) have 3: "\x y z . x \ (y \ z) = (x \ y) \ z" by (simp add: il_associative) have 4: "\x y z . (x \ y) \ z = x \ (y \ z)" using 3 by metis have 5: "\x y . x \ y = y \ x" by (simp add: il_commutative) have 6: "\x . x \ bot = x" by (simp add: il_bot_unit) have 7: "\x . x \ x = x" by simp have 8: "\x y . \(x \ y) \ x \ y = y" using 1 by metis have 9: "\x y . x \ y \ x \ y \ y" using 1 by metis have 10: "\x y z . x \ (y \ z) = (x \ y) \ z" by (simp add: il_inf_associative) have 11: "\x y z . (x \ y) \ z = x \ (y \ z)" using 10 by metis have 12: "\x . top \ x = x" by simp have 13: "\x . x \ top = x" by simp have 14: "\x y z . (x \ y) \ (x \ z) \ x \ (y \ z)" by (simp add: il_sub_inf_right_isotone_var) have 15: "\x y z . (x \ y) \ z = (x \ z) \ (y \ z)" by (simp add: il_inf_right_dist_sup) have 16: "\x y z . (x \ y) \ (z \ y) = (x \ z) \ y" using 15 by metis have 17: "\x . bot \ x = bot" by simp have 18: "\x . - x \ - - x = top" by simp have 19: "\x . - x \ x = bot" by (simp add: a_inf_complement_bot) have 20: "\x y . - (x \ y) \ - (x \ - - y)" by (simp add: ad3) have 22: "\x y z . x \ (y \ z) = y \ (x \ z)" using 4 5 by metis have 25: "\x . bot \ x = x" using 5 6 by metis have 26: "\x y . x \ (x \ y) = x \ y" using 4 7 by metis have 33: "\x y z . (x \ y) \ ((x \ z) \ (x \ (y \ z))) = x \ (y \ z)" using 5 8 14 22 by metis have 47: "\x y . - x \ (- - x \ y) = top \ y" using 4 18 by metis have 48: "\x y . - - x \ (y \ - x) = y \ top" using 4 5 18 by metis have 51: "\x y . - x \ (x \ y) = bot" using 11 17 19 by metis have 52: "- top = bot" using 13 19 by metis have 56: "\x y . (- x \ y) \ x = y \ x" using 16 19 25 by metis have 57: "\x y . (x \ - y) \ y = x \ y" using 5 16 19 25 by metis have 58: "\x y . - (x \ y) \ - (x \ - - y) = - (x \ - - y)" using 8 20 by metis have 60: "\x . - x \ - - - x" using 12 20 by metis have 69: "- bot = top" using 18 25 52 by metis have 74: "\x y . x \ x \ y" using 9 26 by metis have 78: "\x . top \ - x = top" using 5 18 26 by metis have 80: "\x y . x \ y \ x" using 5 74 by metis have 86: "\x y z . x \ y \ x \ (z \ y)" using 22 80 by metis have 95: "\x . - x \ - - - x = - - - x" using 8 60 by metis have 143: "\x y . x \ (x \ - y) = x" using 5 13 26 33 78 by metis have 370: "\x y z . x \ (y \ - z) \ x \ y" using 86 143 by metis have 907: "\x . - x \ - x = - x" using 12 18 57 by metis have 928: "\x y . - x \ (- x \ y) = - x \ y" using 11 907 by metis have 966: "\x y . - (- x \ - - (x \ y)) = top" using 51 58 69 78 by metis have 1535: "\x . - x \ - - - - x = top" using 47 78 95 by metis have 1630: "\x y z . (x \ y) \ - z \ (x \ - z) \ y" using 16 370 by metis have 2422: "\x . - x \ - - - x = - - - x" using 12 57 1535 by metis have 6567: "\x y . - x \ - - (x \ y) = bot" using 12 19 966 by metis have 18123: "\x . - - - x = - x" using 95 143 2422 by metis have 26264: "\x y . - x \ (- y \ - x) \ - - y" using 12 18 1630 by metis have 26279: "\x y . - - (x \ y) \ - - x" using 25 6567 26264 by metis have 26307: "\x y . - - (- x \ y) \ - x" using 928 18123 26279 by metis have 26339: "\x y . - x \ - - (- x \ y) = - x" using 5 8 26307 by metis have 26564: "\x y . - x \ - (- x \ y) = top" using 5 48 78 18123 26339 by metis have 26682: "\x y . - (- x \ y) \ x = x" using 12 56 26564 by metis have 26864: "\x y . - - x \ - (- x \ y)" using 18123 26279 26682 by metis show ?thesis using 26864 by metis qed text \Theorem 25.2\ subclass pa_semiring proof show "\x y. - - x \ - (- x \ y)" by (rule l16) qed lemma l17: "-(x \ y) = -(x \ --y)" by (simp add: ad3 order.antisym l14) lemma a_complement_inf_double_complement: "-(x \ --y) = -(x \ y)" using l17 by auto sublocale a_d: d_semiring_var where d = "\x . --x" proof show "\x y. - - (x \ - - y) \ - - (x \ y)" using l17 by auto show "- - bot = bot" by (simp add: l1 l2) qed lemma "test p \ - - (p \ x) \ p" by (fact a_d.d2) end class a_algebra = a_semiring + minus + assumes a_minus_def: "-x - -y = -(--x \ -y)" begin subclass pa_algebra proof show "\x y. - x - - y = - (- - x \ - y)" by (simp add: a_minus_def) qed text \Theorem 25.4\ subclass subset_boolean_algebra_4_extended proof show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: il_inf_associative) show "\x y z. (x \ y) \ z = x \ z \ y \ z" by (simp add: il_inf_right_dist_sup) show "\x. - x \ x = bot" by (simp add: a_inf_complement_bot) show "\x. top \ x = x" by simp show "\x y. - (x \ - - y) = - (x \ y)" using l17 by auto show "\x. x \ top = x" by simp show "\x y z. x \ y \ z \ x \ z \ y" by (simp add: il_sub_inf_right_isotone) qed end context subset_boolean_algebra_4_extended begin subclass il_semiring proof show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: sup_assoc) show "\x y. x \ y = y \ x" by (simp add: sup_commute) show "\x. x \ x = x" by simp show "\x. x \ bot = x" by simp show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: sba3_inf_associative) show "\x y z. (x \ y) \ z = x \ z \ y \ z" by (simp add: sba3_inf_right_dist_sup) show "\x. top \ x = x" by simp show "\x. x \ top = x" by simp show "\x. bot \ x = bot" by (simp add: inf_left_zero) show "\x y z. x \ y \ z \ x \ z \ y" by (simp add: inf_right_isotone) show "\x y. (x \ y) = (x \ y = y)" by (simp add: le_iff_sup) show "\x y. (x < y) = (x \ y \ \ y \ x)" by (simp add: less_le_not_le) qed subclass a_semiring proof show "\x. - x \ x = bot" by (simp add: sba3_inf_complement_bot) show "\x. - x \ - - x = top" by simp show "\x y. - (x \ y) \ - (x \ - - y)" by (simp add: sba3_complement_inf_double_complement) qed sublocale sba4_a: a_algebra proof show "\x y. - x - - y = - (- - x \ - y)" by (simp add: sub_minus_def) qed end context stone_algebra begin text \Theorem 25.3\ subclass il_semiring proof show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: sup_assoc) show "\x y. x \ y = y \ x" by (simp add: sup_commute) show "\x. x \ x = x" by simp show "\x. x \ bot = x" by simp show "\x y z. x \ (y \ z) = x \ y \ z" by (simp add: inf.sup_monoid.add_assoc) show "\x y z. (x \ y) \ z = x \ z \ y \ z" by (simp add: inf_sup_distrib2) show "\x. top \ x = x" by simp show "\x. x \ top = x" by simp show "\x. bot \ x = bot" by simp show "\x y z. x \ y \ z \ x \ z \ y" using inf.sup_right_isotone by blast show "\x y. (x \ y) = (x \ y = y)" by (simp add: le_iff_sup) show "\x y. (x < y) = (x \ y \ \ y \ x)" by (simp add: less_le_not_le) qed subclass a_semiring proof show "\x. - x \ x = bot" by simp show "\x. - x \ - - x = top" by simp show "\x y. - (x \ y) \ - (x \ - - y)" by simp qed end end diff --git a/thys/UTP/utp/utp_pred_laws.thy b/thys/UTP/utp/utp_pred_laws.thy --- a/thys/UTP/utp/utp_pred_laws.thy +++ b/thys/UTP/utp/utp_pred_laws.thy @@ -1,963 +1,963 @@ section \ Predicate Calculus Laws \ theory utp_pred_laws imports utp_pred begin subsection \ Propositional Logic \ text \ Showing that predicates form a Boolean Algebra (under the predicate operators as opposed to the lattice operators) gives us many useful laws. \ -interpretation boolean_algebra diff_upred not_upred conj_upred "(\)" "(<)" +interpretation Lattices.boolean_algebra diff_upred not_upred conj_upred "(\)" "(<)" disj_upred false_upred true_upred by (unfold_locales; pred_auto) lemma taut_true [simp]: "`true`" by (pred_auto) lemma taut_false [simp]: "`false` = False" by (pred_auto) lemma taut_conj: "`A \ B` = (`A` \ `B`)" by (rel_auto) lemma taut_conj_elim [elim!]: "\ `A \ B`; \ `A`; `B` \ \ P \ \ P" by (rel_auto) lemma taut_refine_impl: "\ Q \ P; `P` \ \ `Q`" by (rel_auto) lemma taut_shEx_elim: "\ `(\<^bold>\ x \ P x)`; \ x. \ \ P x; \ x. `P x` \ Q \ \ Q" by (rel_blast) text \ Linking refinement and HOL implication \ lemma refine_prop_intro: assumes "\ \ P" "\ \ Q" "`Q` \ `P`" shows "P \ Q" using assms by (pred_auto) lemma taut_not: "\ \ P \ (\ `P`) = `\ P`" by (rel_auto) lemma taut_shAll_intro: "\ x. `P x` \ `\<^bold>\ x \ P x`" by (rel_auto) lemma taut_shAll_intro_2: "\ x y. `P x y` \ `\<^bold>\ (x, y) \ P x y`" by (rel_auto) lemma taut_impl_intro: "\ \ \ P; `P` \ `Q` \ \ `P \ Q`" by (rel_auto) lemma upred_eval_taut: "`P\\b\/&\<^bold>v\` = \P\\<^sub>eb" by (pred_auto) lemma refBy_order: "P \ Q = `Q \ P`" by (pred_auto) lemma conj_idem [simp]: "((P::'\ upred) \ P) = P" by (pred_auto) lemma disj_idem [simp]: "((P::'\ upred) \ P) = P" by (pred_auto) lemma conj_comm: "((P::'\ upred) \ Q) = (Q \ P)" by (pred_auto) lemma disj_comm: "((P::'\ upred) \ Q) = (Q \ P)" by (pred_auto) lemma conj_subst: "P = R \ ((P::'\ upred) \ Q) = (R \ Q)" by (pred_auto) lemma disj_subst: "P = R \ ((P::'\ upred) \ Q) = (R \ Q)" by (pred_auto) lemma conj_assoc:"(((P::'\ upred) \ Q) \ S) = (P \ (Q \ S))" by (pred_auto) lemma disj_assoc:"(((P::'\ upred) \ Q) \ S) = (P \ (Q \ S))" by (pred_auto) lemma conj_disj_abs:"((P::'\ upred) \ (P \ Q)) = P" by (pred_auto) lemma disj_conj_abs:"((P::'\ upred) \ (P \ Q)) = P" by (pred_auto) lemma conj_disj_distr:"((P::'\ upred) \ (Q \ R)) = ((P \ Q) \ (P \ R))" by (pred_auto) lemma disj_conj_distr:"((P::'\ upred) \ (Q \ R)) = ((P \ Q) \ (P \ R))" by (pred_auto) lemma true_disj_zero [simp]: "(P \ true) = true" "(true \ P) = true" by (pred_auto)+ lemma true_conj_zero [simp]: "(P \ false) = false" "(false \ P) = false" by (pred_auto)+ lemma false_sup [simp]: "false \ P = P" "P \ false = P" by (pred_auto)+ lemma true_inf [simp]: "true \ P = P" "P \ true = P" by (pred_auto)+ lemma imp_vacuous [simp]: "(false \ u) = true" by (pred_auto) lemma imp_true [simp]: "(p \ true) = true" by (pred_auto) lemma true_imp [simp]: "(true \ p) = p" by (pred_auto) lemma impl_mp1 [simp]: "(P \ (P \ Q)) = (P \ Q)" by (pred_auto) lemma impl_mp2 [simp]: "((P \ Q) \ P) = (Q \ P)" by (pred_auto) lemma impl_adjoin: "((P \ Q) \ R) = ((P \ R \ Q \ R) \ R)" by (pred_auto) lemma impl_refine_intro: "\ Q\<^sub>1 \ P\<^sub>1; P\<^sub>2 \ (P\<^sub>1 \ Q\<^sub>2) \ \ (P\<^sub>1 \ P\<^sub>2) \ (Q\<^sub>1 \ Q\<^sub>2)" by (pred_auto) lemma spec_refine: "Q \ (P \ R) \ (P \ Q) \ R" by (rel_auto) lemma impl_disjI: "\ `P \ R`; `Q \ R` \ \ `(P \ Q) \ R`" by (rel_auto) lemma conditional_iff: "(P \ Q) = (P \ R) \ `P \ (Q \ R)`" by (pred_auto) lemma p_and_not_p [simp]: "(P \ \ P) = false" by (pred_auto) lemma p_or_not_p [simp]: "(P \ \ P) = true" by (pred_auto) lemma p_imp_p [simp]: "(P \ P) = true" by (pred_auto) lemma p_iff_p [simp]: "(P \ P) = true" by (pred_auto) lemma p_imp_false [simp]: "(P \ false) = (\ P)" by (pred_auto) lemma not_conj_deMorgans [simp]: "(\ ((P::'\ upred) \ Q)) = ((\ P) \ (\ Q))" by (pred_auto) lemma not_disj_deMorgans [simp]: "(\ ((P::'\ upred) \ Q)) = ((\ P) \ (\ Q))" by (pred_auto) lemma conj_disj_not_abs [simp]: "((P::'\ upred) \ ((\P) \ Q)) = (P \ Q)" by (pred_auto) lemma subsumption1: "`P \ Q` \ (P \ Q) = Q" by (pred_auto) lemma subsumption2: "`Q \ P` \ (P \ Q) = P" by (pred_auto) lemma neg_conj_cancel1: "(\ P \ (P \ Q)) = (\ P \ Q :: '\ upred)" by (pred_auto) lemma neg_conj_cancel2: "(\ Q \ (P \ Q)) = (\ Q \ P :: '\ upred)" by (pred_auto) lemma double_negation [simp]: "(\ \ (P::'\ upred)) = P" by (pred_auto) lemma true_not_false [simp]: "true \ false" "false \ true" by (pred_auto)+ lemma closure_conj_distr: "([P]\<^sub>u \ [Q]\<^sub>u) = [P \ Q]\<^sub>u" by (pred_auto) lemma closure_imp_distr: "`[P \ Q]\<^sub>u \ [P]\<^sub>u \ [Q]\<^sub>u`" by (pred_auto) lemma true_iff [simp]: "(P \ true) = P" by (pred_auto) lemma taut_iff_eq: "`P \ Q` \ (P = Q)" by (pred_auto) lemma impl_alt_def: "(P \ Q) = (\ P \ Q)" by (pred_auto) subsection \ Lattice laws \ lemma uinf_or: fixes P Q :: "'\ upred" shows "(P \ Q) = (P \ Q)" by (pred_auto) lemma usup_and: fixes P Q :: "'\ upred" shows "(P \ Q) = (P \ Q)" by (pred_auto) lemma UINF_alt_def: "(\ i | A(i) \ P(i)) = (\ i \ A(i) \ P(i))" by (rel_auto) lemma USUP_true [simp]: "(\ P | F(P) \ true) = true" by (pred_auto) lemma UINF_mem_UNIV [simp]: "(\ x\UNIV \ P(x)) = (\ x \ P(x))" by (pred_auto) lemma USUP_mem_UNIV [simp]: "(\ x\UNIV \ P(x)) = (\ x \ P(x))" by (pred_auto) lemma USUP_false [simp]: "(\ i \ false) = false" by (pred_simp) lemma USUP_mem_false [simp]: "I \ {} \ (\ i\I \ false) = false" by (rel_simp) lemma USUP_where_false [simp]: "(\ i | false \ P(i)) = true" by (rel_auto) lemma UINF_true [simp]: "(\ i \ true) = true" by (pred_simp) lemma UINF_ind_const [simp]: "(\ i \ P) = P" by (rel_auto) lemma UINF_mem_true [simp]: "A \ {} \ (\ i\A \ true) = true" by (pred_auto) lemma UINF_false [simp]: "(\ i | P(i) \ false) = false" by (pred_auto) lemma UINF_where_false [simp]: "(\ i | false \ P(i)) = false" by (rel_auto) lemma UINF_cong_eq: "\ \ x. P\<^sub>1(x) = P\<^sub>2(x); \ x. `P\<^sub>1(x) \ Q\<^sub>1(x) =\<^sub>u Q\<^sub>2(x)` \ \ (\ x | P\<^sub>1(x) \ Q\<^sub>1(x)) = (\ x | P\<^sub>2(x) \ Q\<^sub>2(x))" by (unfold UINF_def, pred_simp, metis) lemma UINF_as_Sup: "(\ P \ \

\ P) = \ \

" apply (simp add: upred_defs bop.rep_eq lit.rep_eq Sup_uexpr_def) apply (pred_simp) apply (rule cong[of "Sup"]) apply (auto) done lemma UINF_as_Sup_collect: "(\P\A \ f(P)) = (\P\A. f(P))" apply (simp add: upred_defs bop.rep_eq lit.rep_eq Sup_uexpr_def) apply (pred_simp) apply (simp add: Setcompr_eq_image) done lemma UINF_as_Sup_collect': "(\P \ f(P)) = (\P. f(P))" apply (simp add: upred_defs bop.rep_eq lit.rep_eq Sup_uexpr_def) apply (pred_simp) apply (simp add: full_SetCompr_eq) done lemma UINF_as_Sup_image: "(\ P | \P\ \\<^sub>u \A\ \ f(P)) = \ (f ` A)" apply (simp add: upred_defs bop.rep_eq lit.rep_eq Sup_uexpr_def) apply (pred_simp) apply (rule cong[of "Sup"]) apply (auto) done lemma USUP_as_Inf: "(\ P \ \

\ P) = \ \

" apply (simp add: upred_defs bop.rep_eq lit.rep_eq Inf_uexpr_def) apply (pred_simp) apply (rule cong[of "Inf"]) apply (auto) done lemma USUP_as_Inf_collect: "(\P\A \ f(P)) = (\P\A. f(P))" apply (pred_simp) apply (simp add: Setcompr_eq_image) done lemma USUP_as_Inf_collect': "(\P \ f(P)) = (\P. f(P))" apply (simp add: upred_defs bop.rep_eq lit.rep_eq Sup_uexpr_def) apply (pred_simp) apply (simp add: full_SetCompr_eq) done lemma USUP_as_Inf_image: "(\ P \ \

\ f(P)) = \ (f ` \

)" apply (simp add: upred_defs bop.rep_eq lit.rep_eq Inf_uexpr_def) apply (pred_simp) apply (rule cong[of "Inf"]) apply (auto) done lemma USUP_image_eq [simp]: "USUP (\i. \i\ \\<^sub>u \f ` A\) g = (\ i\A \ g(f(i)))" by (pred_simp, rule_tac cong[of Inf Inf], auto) lemma UINF_image_eq [simp]: "UINF (\i. \i\ \\<^sub>u \f ` A\) g = (\ i\A \ g(f(i)))" by (pred_simp, rule_tac cong[of Sup Sup], auto) lemma subst_continuous [usubst]: "\ \ (\ A) = (\ {\ \ P | P. P \ A})" by (simp add: UINF_as_Sup[THEN sym] usubst setcompr_eq_image) lemma not_UINF: "(\ (\ i\A\ P(i))) = (\ i\A\ \ P(i))" by (pred_auto) lemma not_USUP: "(\ (\ i\A\ P(i))) = (\ i\A\ \ P(i))" by (pred_auto) lemma not_UINF_ind: "(\ (\ i \ P(i))) = (\ i \ \ P(i))" by (pred_auto) lemma not_USUP_ind: "(\ (\ i \ P(i))) = (\ i \ \ P(i))" by (pred_auto) lemma UINF_empty [simp]: "(\ i \ {} \ P(i)) = false" by (pred_auto) lemma UINF_insert [simp]: "(\ i\insert x xs \ P(i)) = (P(x) \ (\ i\xs \ P(i)))" apply (pred_simp) apply (subst Sup_insert[THEN sym]) apply (rule_tac cong[of Sup Sup]) apply (auto) done lemma UINF_atLeast_first: "P(n) \ (\ i \ {Suc n..} \ P(i)) = (\ i \ {n..} \ P(i))" proof - have "insert n {Suc n..} = {n..}" by (auto) thus ?thesis by (metis UINF_insert) qed lemma UINF_atLeast_Suc: "(\ i \ {Suc m..} \ P(i)) = (\ i \ {m..} \ P(Suc i))" by (rel_simp, metis (full_types) Suc_le_D not_less_eq_eq) lemma USUP_empty [simp]: "(\ i \ {} \ P(i)) = true" by (pred_auto) lemma USUP_insert [simp]: "(\ i\insert x xs \ P(i)) = (P(x) \ (\ i\xs \ P(i)))" apply (pred_simp) apply (subst Inf_insert[THEN sym]) apply (rule_tac cong[of Inf Inf]) apply (auto) done lemma USUP_atLeast_first: "(P(n) \ (\ i \ {Suc n..} \ P(i))) = (\ i \ {n..} \ P(i))" proof - have "insert n {Suc n..} = {n..}" by (auto) thus ?thesis by (metis USUP_insert conj_upred_def) qed lemma USUP_atLeast_Suc: "(\ i \ {Suc m..} \ P(i)) = (\ i \ {m..} \ P(Suc i))" by (rel_simp, metis (full_types) Suc_le_D not_less_eq_eq) lemma conj_UINF_dist: "(P \ (\ Q\S \ F(Q))) = (\ Q\S \ P \ F(Q))" by (simp add: upred_defs bop.rep_eq lit.rep_eq, pred_auto) lemma conj_UINF_ind_dist: "(P \ (\ Q \ F(Q))) = (\ Q \ P \ F(Q))" by pred_auto lemma disj_UINF_dist: "S \ {} \ (P \ (\ Q\S \ F(Q))) = (\ Q\S \ P \ F(Q))" by (simp add: upred_defs bop.rep_eq lit.rep_eq, pred_auto) lemma UINF_conj_UINF [simp]: "((\ i\I \ P(i)) \ (\ i\I \ Q(i))) = (\ i\I \ P(i) \ Q(i))" by (rel_auto) lemma conj_USUP_dist: "S \ {} \ (P \ (\ Q\S \ F(Q))) = (\ Q\S \ P \ F(Q))" by (subst uexpr_eq_iff, auto simp add: conj_upred_def USUP.rep_eq inf_uexpr.rep_eq bop.rep_eq lit.rep_eq) lemma USUP_conj_USUP [simp]: "((\ P \ A \ F(P)) \ (\ P \ A \ G(P))) = (\ P \ A \ F(P) \ G(P))" by (simp add: upred_defs bop.rep_eq lit.rep_eq, pred_auto) lemma UINF_all_cong [cong]: assumes "\ P. F(P) = G(P)" shows "(\ P \ F(P)) = (\ P \ G(P))" by (simp add: UINF_as_Sup_collect assms) lemma UINF_cong: assumes "\ P. P \ A \ F(P) = G(P)" shows "(\ P\A \ F(P)) = (\ P\A \ G(P))" by (simp add: UINF_as_Sup_collect assms) lemma USUP_all_cong: assumes "\ P. F(P) = G(P)" shows "(\ P \ F(P)) = (\ P \ G(P))" by (simp add: assms) lemma USUP_cong: assumes "\ P. P \ A \ F(P) = G(P)" shows "(\ P\A \ F(P)) = (\ P\A \ G(P))" by (simp add: USUP_as_Inf_collect assms) lemma UINF_subset_mono: "A \ B \ (\ P\B \ F(P)) \ (\ P\A \ F(P))" by (simp add: SUP_subset_mono UINF_as_Sup_collect) lemma USUP_subset_mono: "A \ B \ (\ P\A \ F(P)) \ (\ P\B \ F(P))" by (simp add: INF_superset_mono USUP_as_Inf_collect) lemma UINF_impl: "(\ P\A \ F(P) \ G(P)) = ((\ P\A \ F(P)) \ (\ P\A \ G(P)))" by (pred_auto) lemma USUP_is_forall: "(\ x \ P(x)) = (\<^bold>\ x \ P(x))" by (pred_simp) lemma USUP_ind_is_forall: "(\ x\A \ P(x)) = (\<^bold>\ x\\A\ \ P(x))" by (pred_auto) lemma UINF_is_exists: "(\ x \ P(x)) = (\<^bold>\ x \ P(x))" by (pred_simp) lemma UINF_all_nats [simp]: fixes P :: "nat \ '\ upred" shows "(\ n \ \ i\{0..n} \ P(i)) = (\ n \ P(n))" by (pred_auto) lemma USUP_all_nats [simp]: fixes P :: "nat \ '\ upred" shows "(\ n \ \ i\{0..n} \ P(i)) = (\ n \ P(n))" by (pred_auto) lemma UINF_upto_expand_first: "m < n \ (\ i \ {m.. P(i)) = ((P(m) :: '\ upred) \ (\ i \ {Suc m.. P(i)))" apply (rel_auto) using Suc_leI le_eq_less_or_eq by auto lemma UINF_upto_expand_last: "(\ i \ {0.. P(i)) = ((\ i \ {0.. P(i)) \ P(n))" apply (rel_auto) using less_SucE by blast lemma UINF_Suc_shift: "(\ i \ {Suc 0.. P(i)) = (\ i \ {0.. P(Suc i))" apply (rel_simp) apply (rule cong[of Sup], auto) using less_Suc_eq_0_disj by auto lemma USUP_upto_expand_first: "(\ i \ {0.. P(i)) = (P(0) \ (\ i \ {1.. P(i)))" apply (rel_auto) using not_less by auto lemma USUP_Suc_shift: "(\ i \ {Suc 0.. P(i)) = (\ i \ {0.. P(Suc i))" apply (rel_simp) apply (rule cong[of Inf], auto) using less_Suc_eq_0_disj by auto lemma UINF_list_conv: "(\ i \ {0.. f (xs ! i)) = foldr (\) (map f xs) false" apply (induct xs) apply (rel_auto) apply (simp add: UINF_upto_expand_first UINF_Suc_shift) done lemma USUP_list_conv: "(\ i \ {0.. f (xs ! i)) = foldr (\) (map f xs) true" apply (induct xs) apply (rel_auto) apply (simp_all add: USUP_upto_expand_first USUP_Suc_shift) done lemma UINF_refines: "\ \ i. i\I \ P \ Q i \ \ P \ (\ i\I \ Q i)" by (simp add: UINF_as_Sup_collect, metis SUP_least) lemma UINF_refines': assumes "\ i. P \ Q(i)" shows "P \ (\ i \ Q(i))" using assms apply (rel_auto) using Sup_le_iff by fastforce lemma UINF_pred_ueq [simp]: "(\ x | \x\ =\<^sub>u v \ P(x)) = (P x)\x\v\" by (pred_auto) lemma UINF_pred_lit_eq [simp]: "(\ x | \x = v\ \ P(x)) = (P v)" by (pred_auto) subsection \ Equality laws \ lemma eq_upred_refl [simp]: "(x =\<^sub>u x) = true" by (pred_auto) lemma eq_upred_sym: "(x =\<^sub>u y) = (y =\<^sub>u x)" by (pred_auto) lemma eq_cong_left: assumes "vwb_lens x" "$x \ Q" "$x\ \ Q" "$x \ R" "$x\ \ R" shows "(($x\ =\<^sub>u $x \ Q) = ($x\ =\<^sub>u $x \ R)) \ (Q = R)" using assms by (pred_simp, (meson mwb_lens_def vwb_lens_mwb weak_lens_def)+) lemma conj_eq_in_var_subst: fixes x :: "('a \ '\)" assumes "vwb_lens x" shows "(P \ $x =\<^sub>u v) = (P\v/$x\ \ $x =\<^sub>u v)" using assms by (pred_simp, (metis vwb_lens_wb wb_lens.get_put)+) lemma conj_eq_out_var_subst: fixes x :: "('a \ '\)" assumes "vwb_lens x" shows "(P \ $x\ =\<^sub>u v) = (P\v/$x\\ \ $x\ =\<^sub>u v)" using assms by (pred_simp, (metis vwb_lens_wb wb_lens.get_put)+) lemma conj_pos_var_subst: assumes "vwb_lens x" shows "($x \ Q) = ($x \ Q\true/$x\)" using assms by (pred_auto, metis (full_types) vwb_lens_wb wb_lens.get_put, metis (full_types) vwb_lens_wb wb_lens.get_put) lemma conj_neg_var_subst: assumes "vwb_lens x" shows "(\ $x \ Q) = (\ $x \ Q\false/$x\)" using assms by (pred_auto, metis (full_types) vwb_lens_wb wb_lens.get_put, metis (full_types) vwb_lens_wb wb_lens.get_put) lemma upred_eq_true [simp]: "(p =\<^sub>u true) = p" by (pred_auto) lemma upred_eq_false [simp]: "(p =\<^sub>u false) = (\ p)" by (pred_auto) lemma upred_true_eq [simp]: "(true =\<^sub>u p) = p" by (pred_auto) lemma upred_false_eq [simp]: "(false =\<^sub>u p) = (\ p)" by (pred_auto) lemma conj_var_subst: assumes "vwb_lens x" shows "(P \ var x =\<^sub>u v) = (P\v/x\ \ var x =\<^sub>u v)" using assms by (pred_simp, (metis (full_types) vwb_lens_def wb_lens.get_put)+) subsection \ HOL Variable Quantifiers \ lemma shEx_unbound [simp]: "(\<^bold>\ x \ P) = P" by (pred_auto) lemma shEx_bool [simp]: "shEx P = (P True \ P False)" by (pred_simp, metis (full_types)) lemma shEx_commute: "(\<^bold>\ x \ \<^bold>\ y \ P x y) = (\<^bold>\ y \ \<^bold>\ x \ P x y)" by (pred_auto) lemma shEx_cong: "\ \ x. P x = Q x \ \ shEx P = shEx Q" by (pred_auto) lemma shEx_insert: "(\<^bold>\ x \ insert\<^sub>u y A \ P(x)) = (P(x)\x\y\ \ (\<^bold>\ x \ A \ P(x)))" by (pred_auto) lemma shEx_one_point: "(\<^bold>\ x \ \x\ =\<^sub>u v \ P(x)) = P(x)\x\v\" by (rel_auto) lemma shAll_unbound [simp]: "(\<^bold>\ x \ P) = P" by (pred_auto) lemma shAll_bool [simp]: "shAll P = (P True \ P False)" by (pred_simp, metis (full_types)) lemma shAll_cong: "\ \ x. P x = Q x \ \ shAll P = shAll Q" by (pred_auto) text \ Quantifier lifting \ named_theorems uquant_lift lemma shEx_lift_conj_1 [uquant_lift]: "((\<^bold>\ x \ P(x)) \ Q) = (\<^bold>\ x \ P(x) \ Q)" by (pred_auto) lemma shEx_lift_conj_2 [uquant_lift]: "(P \ (\<^bold>\ x \ Q(x))) = (\<^bold>\ x \ P \ Q(x))" by (pred_auto) subsection \ Case Splitting \ lemma eq_split_subst: assumes "vwb_lens x" shows "(P = Q) \ (\ v. P\\v\/x\ = Q\\v\/x\)" using assms by (pred_auto, metis vwb_lens_wb wb_lens.source_stability) lemma eq_split_substI: assumes "vwb_lens x" "\ v. P\\v\/x\ = Q\\v\/x\" shows "P = Q" using assms(1) assms(2) eq_split_subst by blast lemma taut_split_subst: assumes "vwb_lens x" shows "`P` \ (\ v. `P\\v\/x\`)" using assms by (pred_auto, metis vwb_lens_wb wb_lens.source_stability) lemma eq_split: assumes "`P \ Q`" "`Q \ P`" shows "P = Q" using assms by (pred_auto) lemma bool_eq_splitI: assumes "vwb_lens x" "P\true/x\ = Q\true/x\" "P\false/x\ = Q\false/x\" shows "P = Q" by (metis (full_types) assms eq_split_subst false_alt_def true_alt_def) lemma subst_bool_split: assumes "vwb_lens x" shows "`P` = `(P\false/x\ \ P\true/x\)`" proof - from assms have "`P` = (\ v. `P\\v\/x\`)" by (subst taut_split_subst[of x], auto) also have "... = (`P\\True\/x\` \ `P\\False\/x\`)" by (metis (mono_tags, lifting)) also have "... = `(P\false/x\ \ P\true/x\)`" by (pred_auto) finally show ?thesis . qed lemma subst_eq_replace: fixes x :: "('a \ '\)" shows "(p\u/x\ \ u =\<^sub>u v) = (p\v/x\ \ u =\<^sub>u v)" by (pred_auto) subsection \ UTP Quantifiers \ lemma one_point: assumes "mwb_lens x" "x \ v" shows "(\ x \ P \ var x =\<^sub>u v) = P\v/x\" using assms by (pred_auto) lemma exists_twice: "mwb_lens x \ (\ x \ \ x \ P) = (\ x \ P)" by (pred_auto) lemma all_twice: "mwb_lens x \ (\ x \ \ x \ P) = (\ x \ P)" by (pred_auto) lemma exists_sub: "\ mwb_lens y; x \\<^sub>L y \ \ (\ x \ \ y \ P) = (\ y \ P)" by (pred_auto) lemma all_sub: "\ mwb_lens y; x \\<^sub>L y \ \ (\ x \ \ y \ P) = (\ y \ P)" by (pred_auto) lemma ex_commute: assumes "x \ y" shows "(\ x \ \ y \ P) = (\ y \ \ x \ P)" using assms apply (pred_auto) using lens_indep_comm apply fastforce+ done lemma all_commute: assumes "x \ y" shows "(\ x \ \ y \ P) = (\ y \ \ x \ P)" using assms apply (pred_auto) using lens_indep_comm apply fastforce+ done lemma ex_equiv: assumes "x \\<^sub>L y" shows "(\ x \ P) = (\ y \ P)" using assms by (pred_simp, metis (no_types, lifting) lens.select_convs(2)) lemma all_equiv: assumes "x \\<^sub>L y" shows "(\ x \ P) = (\ y \ P)" using assms by (pred_simp, metis (no_types, lifting) lens.select_convs(2)) lemma ex_zero: "(\ \ \ P) = P" by (pred_auto) lemma all_zero: "(\ \ \ P) = P" by (pred_auto) lemma ex_plus: "(\ y;x \ P) = (\ x \ \ y \ P)" by (pred_auto) lemma all_plus: "(\ y;x \ P) = (\ x \ \ y \ P)" by (pred_auto) lemma closure_all: "[P]\<^sub>u = (\ \ \ P)" by (pred_auto) lemma unrest_as_exists: "vwb_lens x \ (x \ P) \ ((\ x \ P) = P)" by (pred_simp, metis vwb_lens.put_eq) lemma ex_mono: "P \ Q \ (\ x \ P) \ (\ x \ Q)" by (pred_auto) lemma ex_weakens: "wb_lens x \ (\ x \ P) \ P" by (pred_simp, metis wb_lens.get_put) lemma all_mono: "P \ Q \ (\ x \ P) \ (\ x \ Q)" by (pred_auto) lemma all_strengthens: "wb_lens x \ P \ (\ x \ P)" by (pred_simp, metis wb_lens.get_put) lemma ex_unrest: "x \ P \ (\ x \ P) = P" by (pred_auto) lemma all_unrest: "x \ P \ (\ x \ P) = P" by (pred_auto) lemma not_ex_not: "\ (\ x \ \ P) = (\ x \ P)" by (pred_auto) lemma not_all_not: "\ (\ x \ \ P) = (\ x \ P)" by (pred_auto) lemma ex_conj_contr_left: "x \ P \ (\ x \ P \ Q) = (P \ (\ x \ Q))" by (pred_auto) lemma ex_conj_contr_right: "x \ Q \ (\ x \ P \ Q) = ((\ x \ P) \ Q)" by (pred_auto) subsection \ Variable Restriction \ lemma var_res_all: "P \\<^sub>v \ = P" by (rel_auto) lemma var_res_twice: "mwb_lens x \ P \\<^sub>v x \\<^sub>v x = P \\<^sub>v x" by (pred_auto) subsection \ Conditional laws \ lemma cond_def: "(P \ b \ Q) = ((b \ P) \ ((\ b) \ Q))" by (pred_auto) lemma cond_idem [simp]:"(P \ b \ P) = P" by (pred_auto) lemma cond_true_false [simp]: "true \ b \ false = b" by (pred_auto) lemma cond_symm:"(P \ b \ Q) = (Q \ \ b \ P)" by (pred_auto) lemma cond_assoc: "((P \ b \ Q) \ c \ R) = (P \ b \ c \ (Q \ c \ R))" by (pred_auto) lemma cond_distr: "(P \ b \ (Q \ c \ R)) = ((P \ b \ Q) \ c \ (P \ b \ R))" by (pred_auto) lemma cond_unit_T [simp]:"(P \ true \ Q) = P" by (pred_auto) lemma cond_unit_F [simp]:"(P \ false \ Q) = Q" by (pred_auto) lemma cond_conj_not: "((P \ b \ Q) \ (\ b)) = (Q \ (\ b))" by (rel_auto) lemma cond_and_T_integrate: "((P \ b) \ (Q \ b \ R)) = ((P \ Q) \ b \ R)" by (pred_auto) lemma cond_L6: "(P \ b \ (Q \ b \ R)) = (P \ b \ R)" by (pred_auto) lemma cond_L7: "(P \ b \ (P \ c \ Q)) = (P \ b \ c \ Q)" by (pred_auto) lemma cond_and_distr: "((P \ Q) \ b \ (R \ S)) = ((P \ b \ R) \ (Q \ b \ S))" by (pred_auto) lemma cond_or_distr: "((P \ Q) \ b \ (R \ S)) = ((P \ b \ R) \ (Q \ b \ S))" by (pred_auto) lemma cond_imp_distr: "((P \ Q) \ b \ (R \ S)) = ((P \ b \ R) \ (Q \ b \ S))" by (pred_auto) lemma cond_eq_distr: "((P \ Q) \ b \ (R \ S)) = ((P \ b \ R) \ (Q \ b \ S))" by (pred_auto) lemma cond_conj_distr:"(P \ (Q \ b \ S)) = ((P \ Q) \ b \ (P \ S))" by (pred_auto) lemma cond_disj_distr:"(P \ (Q \ b \ S)) = ((P \ Q) \ b \ (P \ S))" by (pred_auto) lemma cond_neg: "\ (P \ b \ Q) = ((\ P) \ b \ (\ Q))" by (pred_auto) lemma cond_conj: "P \ b \ c \ Q = (P \ c \ Q) \ b \ Q" by (pred_auto) lemma spec_cond_dist: "(P \ (Q \ b \ R)) = ((P \ Q) \ b \ (P \ R))" by (pred_auto) lemma cond_USUP_dist: "(\ P\S \ F(P)) \ b \ (\ P\S \ G(P)) = (\ P\S \ F(P) \ b \ G(P))" by (pred_auto) lemma cond_UINF_dist: "(\ P\S \ F(P)) \ b \ (\ P\S \ G(P)) = (\ P\S \ F(P) \ b \ G(P))" by (pred_auto) lemma cond_var_subst_left: assumes "vwb_lens x" shows "(P\true/x\ \ var x \ Q) = (P \ var x \ Q)" using assms by (pred_auto, metis (full_types) vwb_lens_wb wb_lens.get_put) lemma cond_var_subst_right: assumes "vwb_lens x" shows "(P \ var x \ Q\false/x\) = (P \ var x \ Q)" using assms by (pred_auto, metis (full_types) vwb_lens.put_eq) lemma cond_var_split: "vwb_lens x \ (P\true/x\ \ var x \ P\false/x\) = P" by (rel_simp, (metis (full_types) vwb_lens.put_eq)+) lemma cond_assign_subst: "vwb_lens x \ (P \ utp_expr.var x =\<^sub>u v \ Q) = (P\v/x\ \ utp_expr.var x =\<^sub>u v \ Q)" apply (rel_simp) using vwb_lens.put_eq by force lemma conj_conds: "(P1 \ b \ Q1 \ P2 \ b \ Q2) = (P1 \ P2) \ b \ (Q1 \ Q2)" by pred_auto lemma disj_conds: "(P1 \ b \ Q1 \ P2 \ b \ Q2) = (P1 \ P2) \ b \ (Q1 \ Q2)" by pred_auto lemma cond_mono: "\ P\<^sub>1 \ P\<^sub>2; Q\<^sub>1 \ Q\<^sub>2 \ \ (P\<^sub>1 \ b \ Q\<^sub>1) \ (P\<^sub>2 \ b \ Q\<^sub>2)" by (rel_auto) lemma cond_monotonic: "\ mono P; mono Q \ \ mono (\ X. P X \ b \ Q X)" by (simp add: mono_def, rel_blast) subsection \ Additional Expression Laws \ lemma le_pred_refl [simp]: fixes x :: "('a::preorder, '\) uexpr" shows "(x \\<^sub>u x) = true" by (pred_auto) lemma uzero_le_laws [simp]: "(0 :: ('a::{linordered_semidom}, '\) uexpr) \\<^sub>u numeral x = true" "(1 :: ('a::{linordered_semidom}, '\) uexpr) \\<^sub>u numeral x = true" "(0 :: ('a::{linordered_semidom}, '\) uexpr) \\<^sub>u 1 = true" by (pred_simp)+ lemma unumeral_le_1 [simp]: assumes "(numeral i :: 'a::{numeral,ord}) \ numeral j" shows "(numeral i :: ('a, '\) uexpr) \\<^sub>u numeral j = true" using assms by (pred_auto) lemma unumeral_le_2 [simp]: assumes "(numeral i :: 'a::{numeral,linorder}) > numeral j" shows "(numeral i :: ('a, '\) uexpr) \\<^sub>u numeral j = false" using assms by (pred_auto) lemma uset_laws [simp]: "x \\<^sub>u {}\<^sub>u = false" "x \\<^sub>u {m..n}\<^sub>u = (m \\<^sub>u x \ x \\<^sub>u n)" by (pred_auto)+ lemma ulit_eq [simp]: "x = y \ (\x\ =\<^sub>u \y\) = true" by (rel_auto) lemma ulit_neq [simp]: "x \ y \ (\x\ =\<^sub>u \y\) = false" by (rel_auto) lemma uset_mems [simp]: "x \\<^sub>u {y}\<^sub>u = (x =\<^sub>u y)" "x \\<^sub>u A \\<^sub>u B = (x \\<^sub>u A \ x \\<^sub>u B)" "x \\<^sub>u A \\<^sub>u B = (x \\<^sub>u A \ x \\<^sub>u B)" by (rel_auto)+ subsection \ Refinement By Observation \ text \ Function to obtain the set of observations of a predicate \ definition obs_upred :: "'\ upred \ '\ set" ("\_\\<^sub>o") where [upred_defs]: "\P\\<^sub>o = {b. \P\\<^sub>eb}" lemma obs_upred_refine_iff: "P \ Q \ \Q\\<^sub>o \ \P\\<^sub>o" by (pred_auto) text \ A refinement can be demonstrated by considering only the observations of the predicates which are relevant, i.e. not unrestricted, for them. In other words, if the alphabet can be split into two disjoint segments, $x$ and $y$, and neither predicate refers to $y$ then only $x$ need be considered when checking for observations. \ lemma refine_by_obs: assumes "x \ y" "bij_lens (x +\<^sub>L y)" "y \ P" "y \ Q" "{v. `P\\v\/x\`} \ {v. `Q\\v\/x\`}" shows "Q \ P" using assms(3-5) apply (simp add: obs_upred_refine_iff subset_eq) apply (pred_simp) apply (rename_tac b) apply (drule_tac x="get\<^bsub>x\<^esub>b" in spec) apply (auto simp add: assms) apply (metis assms(1) assms(2) bij_lens.axioms(2) bij_lens_axioms_def lens_override_def lens_override_plus)+ done subsection \ Cylindric Algebra \ lemma C1: "(\ x \ false) = false" by (pred_auto) lemma C2: "wb_lens x \ `P \ (\ x \ P)`" by (pred_simp, metis wb_lens.get_put) lemma C3: "mwb_lens x \ (\ x \ (P \ (\ x \ Q))) = ((\ x \ P) \ (\ x \ Q))" by (pred_auto) lemma C4a: "x \\<^sub>L y \ (\ x \ \ y \ P) = (\ y \ \ x \ P)" by (pred_simp, metis (no_types, lifting) lens.select_convs(2))+ lemma C4b: "x \ y \ (\ x \ \ y \ P) = (\ y \ \ x \ P)" using ex_commute by blast lemma C5: fixes x :: "('a \ '\)" shows "(&x =\<^sub>u &x) = true" by (pred_auto) lemma C6: assumes "wb_lens x" "x \ y" "x \ z" shows "(&y =\<^sub>u &z) = (\ x \ &y =\<^sub>u &x \ &x =\<^sub>u &z)" using assms by (pred_simp, (metis lens_indep_def)+) lemma C7: assumes "weak_lens x" "x \ y" shows "((\ x \ &x =\<^sub>u &y \ P) \ (\ x \ &x =\<^sub>u &y \ \ P)) = false" using assms by (pred_simp, simp add: lens_indep_sym) end \ No newline at end of file diff --git a/thys/Word_Lib/Guide.thy b/thys/Word_Lib/Guide.thy --- a/thys/Word_Lib/Guide.thy +++ b/thys/Word_Lib/Guide.thy @@ -1,414 +1,413 @@ (* * Copyright Florian Haftmann * * SPDX-License-Identifier: BSD-2-Clause *) (*<*) theory Guide imports Word_Lib_Sumo Word_64 Ancient_Numeral begin notation (output) push_bit (\push'_bit\) notation (output) drop_bit (\drop'_bit\) notation (output) signed_drop_bit (\signed'_drop'_bit\) notation (output) Generic_set_bit.set_bit (\Generic'_set'_bit.set'_bit\) hide_const (open) Generic_set_bit.set_bit push_bit drop_bit signed_drop_bit no_notation bit (infixl \!!\ 100) abbreviation \push_bit n a \ a << n\ abbreviation \drop_bit n a \ a >> n\ abbreviation \signed_drop_bit n a \ a >>> n\ (*>*) section \A short overview over bit operations and word types\ subsection \Basic theories and key ideas\ text \ When formalizing bit operations, it is tempting to represent bit values as explicit lists over a binary type. This however is a bad idea, mainly due to the inherent ambiguities in representation concerning repeating leading bits. Hence this approach avoids such explicit lists altogether following an algebraic path: \<^item> Bit values are represented by numeric types: idealized unbounded bit values can be represented by type \<^typ>\int\, bounded bit values by quotient types over \<^typ>\int\, aka \<^typ>\'a word\. \<^item> (A special case are idealized unbounded bit values ending in @{term [source] 0} which can be represented by type \<^typ>\nat\ but only support a restricted set of operations). The most fundamental ideas are developed in theory \<^theory>\HOL.Parity\ (which is part of \<^theory>\Main\): \<^item> Multiplication by \<^term>\2 :: int\ is a bit shift to the left and \<^item> Division by \<^term>\2 :: int\ is a bit shift to the right. \<^item> Concerning bounded bit values, iterated shifts to the left may result in eliminating all bits by shifting them all beyond the boundary. The property \<^prop>\(2 :: int) ^ n \ 0\ represents that \<^term>\n\ is \<^emph>\not\ beyond that boundary. \<^item> The projection on a single bit is then @{thm [mode=iff] bit_iff_odd [where ?'a = int, no_vars]}. \<^item> This leads to the most fundamental properties of bit values: \<^item> Equality rule: @{thm [display, mode=iff] bit_eq_iff [where ?'a = int, no_vars]} \<^item> Induction rule: @{thm [display, mode=iff] bits_induct [where ?'a = int, no_vars]} \<^item> Characteristic properties @{prop [source] \bit (f x) n \ P x n\} are available in fact collection \<^text>\bit_simps\. - On top of this, the following generic operations are provided - after import of theory \<^theory>\HOL-Library.Bit_Operations\: + On top of this, the following generic operations are provided:: \<^item> Singleton \<^term>\n\th bit: \<^term>\(2 :: int) ^ n\ \<^item> Bit mask upto bit \<^term>\n\: @{thm mask_eq_exp_minus_1 [where ?'a = int, no_vars]} \<^item> Left shift: @{thm push_bit_eq_mult [where ?'a = int, no_vars]} \<^item> Right shift: @{thm drop_bit_eq_div [where ?'a = int, no_vars]} \<^item> Truncation: @{thm take_bit_eq_mod [where ?'a = int, no_vars]} \<^item> Bitwise negation: @{thm [mode=iff] bit_not_iff [where ?'a = int, no_vars]} \<^item> Bitwise conjunction: @{thm [mode=iff] bit_and_iff [where ?'a = int, no_vars]} \<^item> Bitwise disjunction: @{thm [mode=iff] bit_or_iff [where ?'a = int, no_vars]} \<^item> Bitwise exclusive disjunction: @{thm [mode=iff] bit_xor_iff [where ?'a = int, no_vars]} \<^item> Setting a single bit: @{thm set_bit_def [where ?'a = int, no_vars]} \<^item> Unsetting a single bit: @{thm unset_bit_def [where ?'a = int, no_vars]} \<^item> Flipping a single bit: @{thm flip_bit_def [where ?'a = int, no_vars]} \<^item> Signed truncation, or modulus centered around \<^term>\0::int\: @{thm [display] signed_take_bit_def [where ?'a = int, no_vars]} \<^item> (Bounded) conversion from and to a list of bits: @{thm [display] horner_sum_bit_eq_take_bit [where ?'a = int, no_vars]} Bit concatenation on \<^typ>\int\ as given by @{thm [display] concat_bit_def [no_vars]} appears quite technical but is the logical foundation for the quite natural bit concatenation on \<^typ>\'a word\ (see below). Proper word types are introduced in theory \<^theory>\HOL-Library.Word\, with the following specific operations: \<^item> Standard arithmetic: @{term \(+) :: 'a::len word \ 'a word \ 'a word\}, @{term \uminus :: 'a::len word \ 'a word\}, @{term \(-) :: 'a::len word \ 'a word \ 'a word\}, @{term \(*) :: 'a::len word \ 'a word \ 'a word\}, @{term \0 :: 'a::len word\}, @{term \1 :: 'a::len word\}, numerals etc. \<^item> Standard bit operations: see above. \<^item> Conversion with unsigned interpretation of words: \<^item> @{term [source] \unsigned :: 'a::len word \ 'b::semiring_1\} \<^item> Important special cases as abbreviations: \<^item> @{term [source] \unat :: 'a::len word \ nat\} \<^item> @{term [source] \uint :: 'a::len word \ int\} \<^item> @{term [source] \ucast :: 'a::len word \ 'b::len word\} \<^item> Conversion with signed interpretation of words: \<^item> @{term [source] \signed :: 'a::len word \ 'b::ring_1\} \<^item> Important special cases as abbreviations: \<^item> @{term [source] \sint :: 'a::len word \ int\} \<^item> @{term [source] \scast :: 'a::len word \ 'b::len word\} \<^item> Operations with unsigned interpretation of words: \<^item> @{thm [mode=iff] word_le_nat_alt [no_vars]} \<^item> @{thm [mode=iff] word_less_nat_alt [no_vars]} \<^item> @{thm unat_div_distrib [no_vars]} \<^item> @{thm unat_drop_bit_eq [no_vars]} \<^item> @{thm unat_mod_distrib [no_vars]} \<^item> @{thm [mode=iff] udvd_iff_dvd [no_vars]} \<^item> Operations with signed interpretation of words: \<^item> @{thm [mode=iff] word_sle_eq [no_vars]} \<^item> @{thm [mode=iff] word_sless_alt [no_vars]} \<^item> @{thm sint_signed_drop_bit_eq [no_vars]} \<^item> Rotation and reversal: \<^item> @{term [source] \word_rotl :: nat \ 'a::len word \ 'a word\} \<^item> @{term [source] \word_rotr :: nat \ 'a::len word \ 'a word\} \<^item> @{term [source] \word_roti :: int \ 'a::len word \ 'a word\} \<^item> @{term [source] \word_reverse :: 'a::len word \ 'a word\} \<^item> Concatenation: @{term [source, display] \word_cat :: 'a::len word \ 'b::len word \ 'c::len word\} For proofs about words the following default strategies are applicable: \<^item> Using bit extensionality (facts \<^text>\bit_eq_iff\, \<^text>\bit_eqI\; fact collection \<^text>\bit_simps\). \<^item> Using the @{method transfer} method. \ subsection \More library theories\ text \ Note: currently, the theories listed here are hardly separate entities since they import each other in various ways. Always inspect them to understand what you pull in if you want to import one. \<^descr>[Syntax] \<^descr>[\<^theory>\Word_Lib.Syntax_Bundles\] Bundles to provide alternative syntax for various bit operations. \<^descr>[\<^theory>\Word_Lib.Hex_Words\] Printing word numerals as hexadecimal numerals. \<^descr>[\<^theory>\Word_Lib.Type_Syntax\] Pretty type-sensitive syntax for cast operations. \<^descr>[\<^theory>\Word_Lib.Word_Syntax\] Specific ASCII syntax for prominent bit operations on word. \<^descr>[Proof tools] \<^descr>[\<^theory>\Word_Lib.Norm_Words\] Rewriting word numerals to normal forms. \<^descr>[\<^theory>\Word_Lib.Bitwise\] Method @{method word_bitwise} decomposes word equalities and inequalities into bit propositions. \<^descr>[\<^theory>\Word_Lib.Word_EqI\] Method @{method word_eqI_solve} decomposes word equalities and inequalities into bit propositions. \<^descr>[Operations] \<^descr>[\<^theory>\Word_Lib.Signed_Division_Word\] Signed division on word: \<^item> @{term [source] \(sdiv) :: 'a::len word \ 'a word \ 'a word\} \<^item> @{term [source] \(smod) :: 'a::len word \ 'a word \ 'a word\} \<^descr>[\<^theory>\Word_Lib.Aligned\] \ \<^item> @{thm [mode=iff] is_aligned_iff_udvd [no_vars]} \<^descr>[\<^theory>\Word_Lib.Least_significant_bit\] The least significant bit as an alias: @{thm [mode=iff] lsb_odd [where ?'a = int, no_vars]} \<^descr>[\<^theory>\Word_Lib.Most_significant_bit\] The most significant bit: \<^item> @{thm [mode=iff] msb_int_def [of k]} \<^item> @{thm [mode=iff] word_msb_sint [no_vars]} \<^item> @{thm [mode=iff] msb_word_iff_sless_0 [no_vars]} \<^item> @{thm [mode=iff] msb_word_iff_bit [no_vars]} \<^descr>[\<^theory>\Word_Lib.Bit_Shifts_Infix_Syntax\] Abbreviations for bit shifts decorated with traditional infix syntax: \<^item> @{abbrev shiftl} \<^item> @{abbrev shiftr} \<^item> @{abbrev sshiftr} \<^descr>[\<^theory>\Word_Lib.Next_and_Prev\] \ \<^item> @{thm word_next_unfold [no_vars]} \<^item> @{thm word_prev_unfold [no_vars]} \<^descr>[\<^theory>\Word_Lib.Enumeration_Word\] More on explicit enumeration of word types. \<^descr>[\<^theory>\Word_Lib.More_Word_Operations\] Even more operations on word. \<^descr>[Types] \<^descr>[\<^theory>\Word_Lib.Signed_Words\] Formal tagging of word types with a \<^text>\signed\ marker. \<^descr>[Lemmas] \<^descr>[\<^theory>\Word_Lib.More_Word\] More lemmas on words. \<^descr>[\<^theory>\Word_Lib.Word_Lemmas\] More lemmas on words, covering many other theories mentioned here. \<^descr>[Words of popular lengths]. \<^descr>[\<^theory>\Word_Lib.Word_8\] for 8-bit words. \<^descr>[\<^theory>\Word_Lib.Word_16\] for 16-bit words. \<^descr>[\<^theory>\Word_Lib.Word_32\] for 32-bit words. \<^descr>[\<^theory>\Word_Lib.Word_64\] for 64-bit words. This theory is not part of \<^text>\Word_Lib_Sumo\, because it shadows names from \<^theory>\Word_Lib.Word_32\. They can be used together, but then require to use qualified names in applications. \ subsection \More library sessions\ text \ \<^descr>[\<^text>\Native_Word\] Makes machine words and machine arithmetic available for code generation. It provides a common abstraction that hides the differences between the different target languages. The code generator maps these operations to the APIs of the target languages. \ subsection \Legacy theories\ text \ The following theories contain material which has been factored out since it is not recommended to use it in new applications, mostly because matters can be expressed succinctly using already existing operations. This section gives some indication how to migrate away from those theories. However theorem coverage may still be terse in some cases. \<^descr>[\<^theory>\Word_Lib.Word_Lib_Sumo\] An entry point importing any relevant theory in that session. Intended for backward compatibility: start importing this theory when migrating applications to Isabelle2021, and later sort out what you really need. You may need to include \<^theory>\Word_Lib.Word_64\ separately. \<^descr>[\<^theory>\Word_Lib.Generic_set_bit\] Kind of an alias: @{thm set_bit_eq [no_vars]} \<^descr>[\<^theory>\Word_Lib.Typedef_Morphisms\] A low-level extension to HOL typedef providing conversions along type morphisms. The @{method transfer} method seems to be sufficient for most applications though. \<^descr>[\<^theory>\Word_Lib.Bit_Comprehension\] Comprehension syntax for bit values over predicates \<^typ>\nat \ bool\. For \<^typ>\'a::len word\, straightforward alternatives exist; difficult to handle for \<^typ>\int\. \<^descr>[\<^theory>\Word_Lib.Reversed_Bit_Lists\] Representation of bit values as explicit list in \<^emph>\reversed\ order. This should rarely be necessary: the \<^const>\bit\ projection should be sufficient in most cases. In case explicit lists are needed, existing operations can be used: @{thm [display] horner_sum_bit_eq_take_bit [where ?'a = int, no_vars]} \<^descr>[\<^theory>\Word_Lib.Many_More\] Collection of operations and theorems which are kept for backward compatibility and not used in other theories in session \<^text>\Word_Lib\. They are used in applications of \<^text>\Word_Lib\, but should be migrated to there. \ section \Changelog\ text \ \<^descr>[Changes since AFP 2021] ~ \<^item> Theory \<^theory>\Word_Lib.Ancient_Numeral\ is no part of \<^theory>\Word_Lib.Word_Lib_Sumo\ any longer. \<^item> Infix syntax for \<^term>\(AND)\, \<^term>\(OR)\, \<^term>\(XOR)\ organized in syntax bundle \<^text>\bit_operations_syntax\. \<^item> Abbreviation \<^abbrev>\max_word\ moved from distribution into theory \<^theory>\Word_Lib.Legacy_Aliases\. \<^item> Operation \<^const>\test_bit\ replaced by input abbreviation \<^abbrev>\test_bit\. \<^item> Operation \<^const>\shiftl\ replaced by input abbreviation \<^abbrev>\shiftl\. \<^item> Operation \<^const>\shiftr\ replaced by input abbreviation \<^abbrev>\shiftr\. \<^item> Operation \<^const>\sshiftr\ replaced by input abbreviation \<^abbrev>\sshiftr\. \<^item> Abbreviations \<^abbrev>\bin_nth\, \<^abbrev>\bin_last\, \<^abbrev>\bin_rest\, \<^abbrev>\bintrunc\, \<^abbrev>\sbintrunc\, \<^abbrev>\norm_sint\, \<^abbrev>\bin_cat\ moved into theory \<^theory>\Word_Lib.Legacy_Aliases\. \<^item> Operations \<^abbrev>\shiftl1\, \<^abbrev>\shiftr1\, \<^abbrev>\sshiftr1\, \<^abbrev>\bshiftr1\, \<^abbrev>\setBit\, \<^abbrev>\clearBit\ moved from distribution into theory \<^theory>\Word_Lib.Legacy_Aliases\ and replaced by input abbreviations. \<^item> Operation \<^const>\complement\ replaced by input abbreviation \<^abbrev>\complement\. \ (*<*) end (*>*) diff --git a/thys/Word_Lib/More_Arithmetic.thy b/thys/Word_Lib/More_Arithmetic.thy --- a/thys/Word_Lib/More_Arithmetic.thy +++ b/thys/Word_Lib/More_Arithmetic.thy @@ -1,137 +1,137 @@ (* * Copyright Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause *) section \Arithmetic lemmas\ theory More_Arithmetic - imports Main "HOL-Library.Type_Length" "HOL-Library.Bit_Operations" + imports Main "HOL-Library.Type_Length" begin lemma n_less_equal_power_2: "n < 2 ^ n" by (fact less_exp) lemma min_pm [simp]: "min a b + (a - b) = a" for a b :: nat by arith lemma min_pm1 [simp]: "a - b + min a b = a" for a b :: nat by arith lemma rev_min_pm [simp]: "min b a + (a - b) = a" for a b :: nat by arith lemma rev_min_pm1 [simp]: "a - b + min b a = a" for a b :: nat by arith lemma min_minus [simp]: "min m (m - k) = m - k" for m k :: nat by arith lemma min_minus' [simp]: "min (m - k) m = m - k" for m k :: nat by arith lemma nat_less_power_trans: fixes n :: nat assumes nv: "n < 2 ^ (m - k)" and kv: "k \ m" shows "2 ^ k * n < 2 ^ m" proof (rule order_less_le_trans) show "2 ^ k * n < 2 ^ k * 2 ^ (m - k)" by (rule mult_less_mono2 [OF nv zero_less_power]) simp show "(2::nat) ^ k * 2 ^ (m - k) \ 2 ^ m" using nv kv by (subst power_add [symmetric]) simp qed lemma nat_le_power_trans: fixes n :: nat shows "\n \ 2 ^ (m - k); k \ m\ \ 2 ^ k * n \ 2 ^ m" by (metis le_add_diff_inverse mult_le_mono2 semiring_normalization_rules(26)) lemma nat_add_offset_less: fixes x :: nat assumes yv: "y < 2 ^ n" and xv: "x < 2 ^ m" and mn: "sz = m + n" shows "x * 2 ^ n + y < 2 ^ sz" proof (subst mn) from yv obtain qy where "y + qy = 2 ^ n" and "0 < qy" by (auto dest: less_imp_add_positive) have "x * 2 ^ n + y < x * 2 ^ n + 2 ^ n" by simp fact+ also have "\ = (x + 1) * 2 ^ n" by simp also have "\ \ 2 ^ (m + n)" using xv by (subst power_add) (rule mult_le_mono1, simp) finally show "x * 2 ^ n + y < 2 ^ (m + n)" . qed lemma nat_power_less_diff: assumes lt: "(2::nat) ^ n * q < 2 ^ m" shows "q < 2 ^ (m - n)" using lt proof (induct n arbitrary: m) case 0 then show ?case by simp next case (Suc n) have ih: "\m. 2 ^ n * q < 2 ^ m \ q < 2 ^ (m - n)" and prem: "2 ^ Suc n * q < 2 ^ m" by fact+ show ?case proof (cases m) case 0 then show ?thesis using Suc by simp next case (Suc m') then show ?thesis using prem by (simp add: ac_simps ih) qed qed lemma power_2_mult_step_le: "\n' \ n; 2 ^ n' * k' < 2 ^ n * k\ \ 2 ^ n' * (k' + 1) \ 2 ^ n * (k::nat)" apply (cases "n'=n", simp) apply (metis Suc_leI le_refl mult_Suc_right mult_le_mono semiring_normalization_rules(7)) apply (drule (1) le_neq_trans) apply clarsimp apply (subgoal_tac "\m. n = n' + m") prefer 2 apply (simp add: le_Suc_ex) apply (clarsimp simp: power_add) apply (metis Suc_leI mult.assoc mult_Suc_right nat_mult_le_cancel_disj) done lemma nat_mult_power_less_eq: "b > 0 \ (a * b ^ n < (b :: nat) ^ m) = (a < b ^ (m - n))" using mult_less_cancel2[where m = a and k = "b ^ n" and n="b ^ (m - n)"] mult_less_cancel2[where m="a * b ^ (n - m)" and k="b ^ m" and n=1] apply (simp only: power_add[symmetric] nat_minus_add_max) apply (simp only: power_add[symmetric] nat_minus_add_max ac_simps) apply (simp add: max_def split: if_split_asm) done lemma diff_diff_less: "(i < m - (m - (n :: nat))) = (i < m \ i < n)" by auto lemma small_powers_of_2: \x < 2 ^ (x - 1)\ if \x \ 3\ for x :: nat proof - define m where \m = x - 3\ with that have \x = m + 3\ by simp moreover have \m + 3 < 4 * 2 ^ m\ by (induction m) simp_all ultimately show ?thesis by simp qed end diff --git a/thys/Word_Lib/More_Word.thy b/thys/Word_Lib/More_Word.thy --- a/thys/Word_Lib/More_Word.thy +++ b/thys/Word_Lib/More_Word.thy @@ -1,2550 +1,2550 @@ (* * Copyright Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause *) section \Lemmas on words\ theory More_Word imports "HOL-Library.Word" More_Arithmetic More_Divides begin context includes bit_operations_syntax begin \ \problem posed by TPHOLs referee: criterion for overflow of addition of signed integers\ lemma sofl_test: \sint x + sint y = sint (x + y) \ drop_bit (size x - 1) ((x + y XOR x) AND (x + y XOR y)) = 0\ for x y :: \'a::len word\ proof - obtain n where n: \LENGTH('a) = Suc n\ by (cases \LENGTH('a)\) simp_all have *: \sint x + sint y + 2 ^ Suc n > signed_take_bit n (sint x + sint y) \ sint x + sint y \ - (2 ^ n)\ \signed_take_bit n (sint x + sint y) > sint x + sint y - 2 ^ Suc n \ 2 ^ n > sint x + sint y\ using signed_take_bit_int_greater_eq [of \sint x + sint y\ n] signed_take_bit_int_less_eq [of n \sint x + sint y\] by (auto intro: ccontr) have \sint x + sint y = sint (x + y) \ (sint (x + y) < 0 \ sint x < 0) \ (sint (x + y) < 0 \ sint y < 0)\ using sint_less [of x] sint_greater_eq [of x] sint_less [of y] sint_greater_eq [of y] signed_take_bit_int_eq_self [of \LENGTH('a) - 1\ \sint x + sint y\] apply (auto simp add: not_less) apply (unfold sint_word_ariths) apply (subst signed_take_bit_int_eq_self) prefer 4 apply (subst signed_take_bit_int_eq_self) prefer 7 apply (subst signed_take_bit_int_eq_self) prefer 10 apply (subst signed_take_bit_int_eq_self) apply (auto simp add: signed_take_bit_int_eq_self signed_take_bit_eq_take_bit_minus take_bit_Suc_from_most n not_less intro!: *) apply (smt (z3) take_bit_nonnegative) apply (smt (z3) take_bit_int_less_exp) apply (smt (z3) take_bit_nonnegative) apply (smt (z3) take_bit_int_less_exp) done then show ?thesis apply (simp only: One_nat_def word_size drop_bit_eq_zero_iff_not_bit_last bit_and_iff bit_xor_iff) apply (simp add: bit_last_iff) done qed lemma unat_power_lower [simp]: "unat ((2::'a::len word) ^ n) = 2 ^ n" if "n < LENGTH('a::len)" using that by transfer simp lemma unat_p2: "n < LENGTH('a :: len) \ unat (2 ^ n :: 'a word) = 2 ^ n" by (fact unat_power_lower) lemma word_div_lt_eq_0: "x < y \ x div y = 0" for x :: "'a :: len word" by transfer simp lemma word_div_eq_1_iff: "n div m = 1 \ n \ m \ unat n < 2 * unat (m :: 'a :: len word)" apply (simp only: word_arith_nat_defs word_le_nat_alt word_of_nat_eq_iff flip: nat_div_eq_Suc_0_iff) apply (simp flip: unat_div unsigned_take_bit_eq) done lemma AND_twice [simp]: "(w AND m) AND m = w AND m" by (fact and.right_idem) lemma word_combine_masks: "w AND m = z \ w AND m' = z' \ w AND (m OR m') = (z OR z')" for w m m' z z' :: \'a::len word\ by (simp add: bit.conj_disj_distrib) lemma p2_gt_0: "(0 < (2 ^ n :: 'a :: len word)) = (n < LENGTH('a))" by (simp add : word_gt_0 not_le) lemma uint_2p_alt: \n < LENGTH('a::len) \ uint ((2::'a::len word) ^ n) = 2 ^ n\ using p2_gt_0 [of n, where ?'a = 'a] by (simp add: uint_2p) lemma p2_eq_0: \(2::'a::len word) ^ n = 0 \ LENGTH('a::len) \ n\ by (fact exp_eq_zero_iff) lemma p2len: \(2 :: 'a word) ^ LENGTH('a::len) = 0\ by simp lemma neg_mask_is_div: "w AND NOT (mask n) = (w div 2^n) * 2^n" for w :: \'a::len word\ by (rule bit_word_eqI) (auto simp add: bit_simps simp flip: push_bit_eq_mult drop_bit_eq_div) lemma neg_mask_is_div': "n < size w \ w AND NOT (mask n) = ((w div (2 ^ n)) * (2 ^ n))" for w :: \'a::len word\ by (rule neg_mask_is_div) lemma and_mask_arith: "w AND mask n = (w * 2^(size w - n)) div 2^(size w - n)" for w :: \'a::len word\ by (rule bit_word_eqI) (auto simp add: bit_simps word_size simp flip: push_bit_eq_mult drop_bit_eq_div) lemma and_mask_arith': "0 < n \ w AND mask n = (w * 2^(size w - n)) div 2^(size w - n)" for w :: \'a::len word\ by (rule and_mask_arith) lemma mask_2pm1: "mask n = 2 ^ n - (1 :: 'a::len word)" by (fact mask_eq_decr_exp) lemma add_mask_fold: "x + 2 ^ n - 1 = x + mask n" for x :: \'a::len word\ by (simp add: mask_eq_decr_exp) lemma word_and_mask_le_2pm1: "w AND mask n \ 2 ^ n - 1" for w :: \'a::len word\ by (simp add: mask_2pm1[symmetric] word_and_le1) lemma is_aligned_AND_less_0: "u AND mask n = 0 \ v < 2^n \ u AND v = 0" for u v :: \'a::len word\ apply (drule less_mask_eq) apply (simp flip: take_bit_eq_mask) apply (simp add: bit_eq_iff) apply (auto simp add: bit_simps) done lemma and_mask_eq_iff_le_mask: \w AND mask n = w \ w \ mask n\ for w :: \'a::len word\ apply (simp flip: take_bit_eq_mask) apply (cases \n \ LENGTH('a)\; transfer) apply (simp_all add: not_le min_def) apply (simp_all add: mask_eq_exp_minus_1) apply auto apply (metis take_bit_int_less_exp) apply (metis min_def nat_less_le take_bit_int_eq_self_iff take_bit_take_bit) done lemma less_eq_mask_iff_take_bit_eq_self: \w \ mask n \ take_bit n w = w\ for w :: \'a::len word\ by (simp add: and_mask_eq_iff_le_mask take_bit_eq_mask) lemma NOT_eq: "NOT (x :: 'a :: len word) = - x - 1" apply (cut_tac x = "x" in word_add_not) apply (drule add.commute [THEN trans]) apply (drule eq_diff_eq [THEN iffD2]) by simp lemma NOT_mask: "NOT (mask n :: 'a::len word) = - (2 ^ n)" by (simp add : NOT_eq mask_2pm1) lemma le_m1_iff_lt: "(x > (0 :: 'a :: len word)) = ((y \ x - 1) = (y < x))" by uint_arith lemma gt0_iff_gem1: \0 < x \ x - 1 < x\ for x :: \'a::len word\ by (metis add.right_neutral diff_add_cancel less_irrefl measure_unat unat_arith_simps(2) word_neq_0_conv word_sub_less_iff) lemma power_2_ge_iff: \2 ^ n - (1 :: 'a::len word) < 2 ^ n \ n < LENGTH('a)\ using gt0_iff_gem1 p2_gt_0 by blast lemma le_mask_iff_lt_2n: "n < len_of TYPE ('a) = (((w :: 'a :: len word) \ mask n) = (w < 2 ^ n))" unfolding mask_2pm1 by (rule trans [OF p2_gt_0 [THEN sym] le_m1_iff_lt]) lemma mask_lt_2pn: \n < LENGTH('a) \ mask n < (2 :: 'a::len word) ^ n\ by (simp add: mask_eq_exp_minus_1 power_2_ge_iff) lemma word_unat_power: "(2 :: 'a :: len word) ^ n = of_nat (2 ^ n)" by simp lemma of_nat_mono_maybe: assumes xlt: "x < 2 ^ len_of TYPE ('a)" shows "y < x \ of_nat y < (of_nat x :: 'a :: len word)" apply (subst word_less_nat_alt) apply (subst unat_of_nat)+ apply (subst mod_less) apply (erule order_less_trans [OF _ xlt]) apply (subst mod_less [OF xlt]) apply assumption done lemma word_and_max_word: fixes a::"'a::len word" shows "x = - 1 \ a AND x = a" by simp lemma word_and_full_mask_simp: \x AND mask LENGTH('a) = x\ for x :: \'a::len word\ proof (rule bit_eqI) fix n assume \2 ^ n \ (0 :: 'a word)\ then have \n < LENGTH('a)\ by simp then show \bit (x AND Bit_Operations.mask LENGTH('a)) n \ bit x n\ by (simp add: bit_and_iff bit_mask_iff) qed lemma of_int_uint: "of_int (uint x) = x" by (fact word_of_int_uint) corollary word_plus_and_or_coroll: "x AND y = 0 \ x + y = x OR y" for x y :: \'a::len word\ using word_plus_and_or[where x=x and y=y] by simp corollary word_plus_and_or_coroll2: "(x AND w) + (x AND NOT w) = x" for x w :: \'a::len word\ apply (subst disjunctive_add) apply (simp add: bit_simps) apply (simp flip: bit.conj_disj_distrib) done lemma nat_mask_eq: \nat (mask n) = mask n\ by (simp add: nat_eq_iff of_nat_mask_eq) lemma unat_mask_eq: \unat (mask n :: 'a::len word) = mask (min LENGTH('a) n)\ by transfer (simp add: nat_mask_eq) lemma word_plus_mono_left: fixes x :: "'a :: len word" shows "\y \ z; x \ x + z\ \ y + x \ z + x" by unat_arith lemma less_Suc_unat_less_bound: "n < Suc (unat (x :: 'a :: len word)) \ n < 2 ^ LENGTH('a)" by (auto elim!: order_less_le_trans intro: Suc_leI) lemma up_ucast_inj: "\ ucast x = (ucast y::'b::len word); LENGTH('a) \ len_of TYPE ('b) \ \ x = (y::'a::len word)" by transfer (simp add: min_def split: if_splits) lemmas ucast_up_inj = up_ucast_inj lemma up_ucast_inj_eq: "LENGTH('a) \ len_of TYPE ('b) \ (ucast x = (ucast y::'b::len word)) = (x = (y::'a::len word))" by (fastforce dest: up_ucast_inj) lemma no_plus_overflow_neg: "(x :: 'a :: len word) < -y \ x \ x + y" by (metis diff_minus_eq_add less_imp_le sub_wrap_lt) lemma ucast_ucast_eq: "\ ucast x = (ucast (ucast y::'a word)::'c::len word); LENGTH('a) \ LENGTH('b); LENGTH('b) \ LENGTH('c) \ \ x = ucast y" for x :: "'a::len word" and y :: "'b::len word" apply transfer apply (cases \LENGTH('c) = LENGTH('a)\) apply (auto simp add: min_def) done lemma ucast_0_I: "x = 0 \ ucast x = 0" by simp lemma word_add_offset_less: fixes x :: "'a :: len word" assumes yv: "y < 2 ^ n" and xv: "x < 2 ^ m" and mnv: "sz < LENGTH('a :: len)" and xv': "x < 2 ^ (LENGTH('a :: len) - n)" and mn: "sz = m + n" shows "x * 2 ^ n + y < 2 ^ sz" proof (subst mn) from mnv mn have nv: "n < LENGTH('a)" and mv: "m < LENGTH('a)" by auto have uy: "unat y < 2 ^ n" by (rule order_less_le_trans [OF unat_mono [OF yv] order_eq_refl], rule unat_power_lower[OF nv]) have ux: "unat x < 2 ^ m" by (rule order_less_le_trans [OF unat_mono [OF xv] order_eq_refl], rule unat_power_lower[OF mv]) then show "x * 2 ^ n + y < 2 ^ (m + n)" using ux uy nv mnv xv' apply (subst word_less_nat_alt) apply (subst unat_word_ariths)+ apply (subst mod_less) apply simp apply (subst mult.commute) apply (rule nat_less_power_trans [OF _ order_less_imp_le [OF nv]]) apply (rule order_less_le_trans [OF unat_mono [OF xv']]) apply (cases "n = 0"; simp) apply (subst unat_power_lower[OF nv]) apply (subst mod_less) apply (erule order_less_le_trans [OF nat_add_offset_less], assumption) apply (rule mn) apply simp apply (simp add: mn mnv) apply (erule nat_add_offset_less; simp) done qed lemma word_less_power_trans: fixes n :: "'a :: len word" assumes nv: "n < 2 ^ (m - k)" and kv: "k \ m" and mv: "m < len_of TYPE ('a)" shows "2 ^ k * n < 2 ^ m" using nv kv mv apply - apply (subst word_less_nat_alt) apply (subst unat_word_ariths) apply (subst mod_less) apply simp apply (rule nat_less_power_trans) apply (erule order_less_trans [OF unat_mono]) apply simp apply simp apply simp apply (rule nat_less_power_trans) apply (subst unat_power_lower[where 'a = 'a, symmetric]) apply simp apply (erule unat_mono) apply simp done lemma word_less_power_trans2: fixes n :: "'a::len word" shows "\n < 2 ^ (m - k); k \ m; m < LENGTH('a)\ \ n * 2 ^ k < 2 ^ m" by (subst field_simps, rule word_less_power_trans) lemma Suc_unat_diff_1: fixes x :: "'a :: len word" assumes lt: "1 \ x" shows "Suc (unat (x - 1)) = unat x" proof - have "0 < unat x" by (rule order_less_le_trans [where y = 1], simp, subst unat_1 [symmetric], rule iffD1 [OF word_le_nat_alt lt]) then show ?thesis by ((subst unat_sub [OF lt])+, simp only: unat_1) qed lemma word_eq_unatI: \v = w\ if \unat v = unat w\ using that by transfer (simp add: nat_eq_iff) lemma word_div_sub: fixes x :: "'a :: len word" assumes yx: "y \ x" and y0: "0 < y" shows "(x - y) div y = x div y - 1" apply (rule word_eq_unatI) apply (subst unat_div) apply (subst unat_sub [OF yx]) apply (subst unat_sub) apply (subst word_le_nat_alt) apply (subst unat_div) apply (subst le_div_geq) apply (rule order_le_less_trans [OF _ unat_mono [OF y0]]) apply simp apply (subst word_le_nat_alt [symmetric], rule yx) apply simp apply (subst unat_div) apply (subst le_div_geq [OF _ iffD1 [OF word_le_nat_alt yx]]) apply (rule order_le_less_trans [OF _ unat_mono [OF y0]]) apply simp apply simp done lemma word_mult_less_mono1: fixes i :: "'a :: len word" assumes ij: "i < j" and knz: "0 < k" and ujk: "unat j * unat k < 2 ^ len_of TYPE ('a)" shows "i * k < j * k" proof - from ij ujk knz have jk: "unat i * unat k < 2 ^ len_of TYPE ('a)" by (auto intro: order_less_subst2 simp: word_less_nat_alt elim: mult_less_mono1) then show ?thesis using ujk knz ij by (auto simp: word_less_nat_alt iffD1 [OF unat_mult_lem]) qed lemma word_mult_less_dest: fixes i :: "'a :: len word" assumes ij: "i * k < j * k" and uik: "unat i * unat k < 2 ^ len_of TYPE ('a)" and ujk: "unat j * unat k < 2 ^ len_of TYPE ('a)" shows "i < j" using uik ujk ij by (auto simp: word_less_nat_alt iffD1 [OF unat_mult_lem] elim: mult_less_mono1) lemma word_mult_less_cancel: fixes k :: "'a :: len word" assumes knz: "0 < k" and uik: "unat i * unat k < 2 ^ len_of TYPE ('a)" and ujk: "unat j * unat k < 2 ^ len_of TYPE ('a)" shows "(i * k < j * k) = (i < j)" by (rule iffI [OF word_mult_less_dest [OF _ uik ujk] word_mult_less_mono1 [OF _ knz ujk]]) lemma Suc_div_unat_helper: assumes szv: "sz < LENGTH('a :: len)" and usszv: "us \ sz" shows "2 ^ (sz - us) = Suc (unat (((2::'a :: len word) ^ sz - 1) div 2 ^ us))" proof - note usv = order_le_less_trans [OF usszv szv] from usszv obtain q where qv: "sz = us + q" by (auto simp: le_iff_add) have "Suc (unat (((2:: 'a word) ^ sz - 1) div 2 ^ us)) = (2 ^ us + unat ((2:: 'a word) ^ sz - 1)) div 2 ^ us" apply (subst unat_div unat_power_lower[OF usv])+ apply (subst div_add_self1, simp+) done also have "\ = ((2 ^ us - 1) + 2 ^ sz) div 2 ^ us" using szv by (simp add: unat_minus_one) also have "\ = 2 ^ q + ((2 ^ us - 1) div 2 ^ us)" apply (subst qv) apply (subst power_add) apply (subst div_mult_self2; simp) done also have "\ = 2 ^ (sz - us)" using qv by simp finally show ?thesis .. qed lemma enum_word_nth_eq: \(Enum.enum :: 'a::len word list) ! n = word_of_nat n\ if \n < 2 ^ LENGTH('a)\ for n using that by (simp add: enum_word_def) lemma length_enum_word_eq: \length (Enum.enum :: 'a::len word list) = 2 ^ LENGTH('a)\ by (simp add: enum_word_def) lemma unat_lt2p [iff]: \unat x < 2 ^ LENGTH('a)\ for x :: \'a::len word\ by transfer simp lemma of_nat_unat [simp]: "of_nat \ unat = id" by (rule ext, simp) lemma Suc_unat_minus_one [simp]: "x \ 0 \ Suc (unat (x - 1)) = unat x" by (metis Suc_diff_1 unat_gt_0 unat_minus_one) lemma word_add_le_dest: fixes i :: "'a :: len word" assumes le: "i + k \ j + k" and uik: "unat i + unat k < 2 ^ len_of TYPE ('a)" and ujk: "unat j + unat k < 2 ^ len_of TYPE ('a)" shows "i \ j" using uik ujk le by (auto simp: word_le_nat_alt iffD1 [OF unat_add_lem] elim: add_le_mono1) lemma word_add_le_mono1: fixes i :: "'a :: len word" assumes ij: "i \ j" and ujk: "unat j + unat k < 2 ^ len_of TYPE ('a)" shows "i + k \ j + k" proof - from ij ujk have jk: "unat i + unat k < 2 ^ len_of TYPE ('a)" by (auto elim: order_le_less_subst2 simp: word_le_nat_alt elim: add_le_mono1) then show ?thesis using ujk ij by (auto simp: word_le_nat_alt iffD1 [OF unat_add_lem]) qed lemma word_add_le_mono2: fixes i :: "'a :: len word" shows "\i \ j; unat j + unat k < 2 ^ LENGTH('a)\ \ k + i \ k + j" by (subst field_simps, subst field_simps, erule (1) word_add_le_mono1) lemma word_add_le_iff: fixes i :: "'a :: len word" assumes uik: "unat i + unat k < 2 ^ len_of TYPE ('a)" and ujk: "unat j + unat k < 2 ^ len_of TYPE ('a)" shows "(i + k \ j + k) = (i \ j)" proof assume "i \ j" show "i + k \ j + k" by (rule word_add_le_mono1) fact+ next assume "i + k \ j + k" show "i \ j" by (rule word_add_le_dest) fact+ qed lemma word_add_less_mono1: fixes i :: "'a :: len word" assumes ij: "i < j" and ujk: "unat j + unat k < 2 ^ len_of TYPE ('a)" shows "i + k < j + k" proof - from ij ujk have jk: "unat i + unat k < 2 ^ len_of TYPE ('a)" by (auto elim: order_le_less_subst2 simp: word_less_nat_alt elim: add_less_mono1) then show ?thesis using ujk ij by (auto simp: word_less_nat_alt iffD1 [OF unat_add_lem]) qed lemma word_add_less_dest: fixes i :: "'a :: len word" assumes le: "i + k < j + k" and uik: "unat i + unat k < 2 ^ len_of TYPE ('a)" and ujk: "unat j + unat k < 2 ^ len_of TYPE ('a)" shows "i < j" using uik ujk le by (auto simp: word_less_nat_alt iffD1 [OF unat_add_lem] elim: add_less_mono1) lemma word_add_less_iff: fixes i :: "'a :: len word" assumes uik: "unat i + unat k < 2 ^ len_of TYPE ('a)" and ujk: "unat j + unat k < 2 ^ len_of TYPE ('a)" shows "(i + k < j + k) = (i < j)" proof assume "i < j" show "i + k < j + k" by (rule word_add_less_mono1) fact+ next assume "i + k < j + k" show "i < j" by (rule word_add_less_dest) fact+ qed lemma word_mult_less_iff: fixes i :: "'a :: len word" assumes knz: "0 < k" and uik: "unat i * unat k < 2 ^ len_of TYPE ('a)" and ujk: "unat j * unat k < 2 ^ len_of TYPE ('a)" shows "(i * k < j * k) = (i < j)" using assms by (rule word_mult_less_cancel) lemma word_le_imp_diff_le: fixes n :: "'a::len word" shows "\k \ n; n \ m\ \ n - k \ m" by (auto simp: unat_sub word_le_nat_alt) lemma word_less_imp_diff_less: fixes n :: "'a::len word" shows "\k \ n; n < m\ \ n - k < m" by (clarsimp simp: unat_sub word_less_nat_alt intro!: less_imp_diff_less) lemma word_mult_le_mono1: fixes i :: "'a :: len word" assumes ij: "i \ j" and knz: "0 < k" and ujk: "unat j * unat k < 2 ^ len_of TYPE ('a)" shows "i * k \ j * k" proof - from ij ujk knz have jk: "unat i * unat k < 2 ^ len_of TYPE ('a)" by (auto elim: order_le_less_subst2 simp: word_le_nat_alt elim: mult_le_mono1) then show ?thesis using ujk knz ij by (auto simp: word_le_nat_alt iffD1 [OF unat_mult_lem]) qed lemma word_mult_le_iff: fixes i :: "'a :: len word" assumes knz: "0 < k" and uik: "unat i * unat k < 2 ^ len_of TYPE ('a)" and ujk: "unat j * unat k < 2 ^ len_of TYPE ('a)" shows "(i * k \ j * k) = (i \ j)" proof assume "i \ j" show "i * k \ j * k" by (rule word_mult_le_mono1) fact+ next assume p: "i * k \ j * k" have "0 < unat k" using knz by (simp add: word_less_nat_alt) then show "i \ j" using p by (clarsimp simp: word_le_nat_alt iffD1 [OF unat_mult_lem uik] iffD1 [OF unat_mult_lem ujk]) qed lemma word_diff_less: fixes n :: "'a :: len word" shows "\0 < n; 0 < m; n \ m\ \ m - n < m" apply (subst word_less_nat_alt) apply (subst unat_sub) apply assumption apply (rule diff_less) apply (simp_all add: word_less_nat_alt) done lemma word_add_increasing: fixes x :: "'a :: len word" shows "\ p + w \ x; p \ p + w \ \ p \ x" by unat_arith lemma word_random: fixes x :: "'a :: len word" shows "\ p \ p + x'; x \ x' \ \ p \ p + x" by unat_arith lemma word_sub_mono: "\ a \ c; d \ b; a - b \ a; c - d \ c \ \ (a - b) \ (c - d :: 'a :: len word)" by unat_arith lemma power_not_zero: "n < LENGTH('a::len) \ (2 :: 'a word) ^ n \ 0" by (metis p2_gt_0 word_neq_0_conv) lemma word_gt_a_gt_0: "a < n \ (0 :: 'a::len word) < n" apply (case_tac "n = 0") apply clarsimp apply (clarsimp simp: word_neq_0_conv) done lemma word_power_less_1 [simp]: "sz < LENGTH('a::len) \ (2::'a word) ^ sz - 1 < 2 ^ sz" apply (simp add: word_less_nat_alt) apply (subst unat_minus_one) apply simp_all done lemma word_sub_1_le: "x \ 0 \ x - 1 \ (x :: ('a :: len) word)" apply (subst no_ulen_sub) apply simp apply (cases "uint x = 0") apply (simp add: uint_0_iff) apply (insert uint_ge_0[where x=x]) apply arith done lemma push_bit_word_eq_nonzero: \push_bit n w \ 0\ if \w < 2 ^ m\ \m + n < LENGTH('a)\ \w \ 0\ for w :: \'a::len word\ using that apply (simp only: word_neq_0_conv word_less_nat_alt mod_0 unat_word_ariths unat_power_lower word_le_nat_alt) apply (metis add_diff_cancel_right' gr0I gr_implies_not0 less_or_eq_imp_le min_def push_bit_eq_0_iff take_bit_nat_eq_self_iff take_bit_push_bit take_bit_take_bit unsigned_push_bit_eq) done lemma unat_less_power: fixes k :: "'a::len word" assumes szv: "sz < LENGTH('a)" and kv: "k < 2 ^ sz" shows "unat k < 2 ^ sz" using szv unat_mono [OF kv] by simp lemma unat_mult_power_lem: assumes kv: "k < 2 ^ (LENGTH('a::len) - sz)" shows "unat (2 ^ sz * of_nat k :: (('a::len) word)) = 2 ^ sz * k" proof (cases \sz < LENGTH('a)\) case True with assms show ?thesis by (simp add: unat_word_ariths take_bit_eq_mod mod_simps) (simp add: take_bit_nat_eq_self_iff nat_less_power_trans flip: take_bit_eq_mod) next case False with assms show ?thesis by simp qed lemma word_plus_mcs_4: "\v + x \ w + x; x \ v + x\ \ v \ (w::'a::len word)" by uint_arith lemma word_plus_mcs_3: "\v \ w; x \ w + x\ \ v + x \ w + (x::'a::len word)" by unat_arith lemma word_le_minus_one_leq: "x < y \ x \ y - 1" for x :: "'a :: len word" by transfer (metis le_less_trans less_irrefl take_bit_decr_eq take_bit_nonnegative zle_diff1_eq) lemma word_less_sub_le[simp]: fixes x :: "'a :: len word" assumes nv: "n < LENGTH('a)" shows "(x \ 2 ^ n - 1) = (x < 2 ^ n)" using le_less_trans word_le_minus_one_leq nv power_2_ge_iff by blast lemma unat_of_nat_len: "x < 2 ^ LENGTH('a) \ unat (of_nat x :: 'a::len word) = x" by (simp add: take_bit_nat_eq_self_iff) lemma unat_of_nat_eq: "x < 2 ^ LENGTH('a) \ unat (of_nat x ::'a::len word) = x" by (rule unat_of_nat_len) lemma unat_eq_of_nat: "n < 2 ^ LENGTH('a) \ (unat (x :: 'a::len word) = n) = (x = of_nat n)" by transfer (auto simp add: take_bit_of_nat nat_eq_iff take_bit_nat_eq_self_iff intro: sym) lemma alignUp_div_helper: fixes a :: "'a::len word" assumes kv: "k < 2 ^ (LENGTH('a) - n)" and xk: "x = 2 ^ n * of_nat k" and le: "a \ x" and sz: "n < LENGTH('a)" and anz: "a mod 2 ^ n \ 0" shows "a div 2 ^ n < of_nat k" proof - have kn: "unat (of_nat k :: 'a word) * unat ((2::'a word) ^ n) < 2 ^ LENGTH('a)" using xk kv sz apply (subst unat_of_nat_eq) apply (erule order_less_le_trans) apply simp apply (subst unat_power_lower, simp) apply (subst mult.commute) apply (rule nat_less_power_trans) apply simp apply simp done have "unat a div 2 ^ n * 2 ^ n \ unat a" proof - have "unat a = unat a div 2 ^ n * 2 ^ n + unat a mod 2 ^ n" by (simp add: div_mult_mod_eq) also have "\ \ unat a div 2 ^ n * 2 ^ n" using sz anz by (simp add: unat_arith_simps) finally show ?thesis .. qed then have "a div 2 ^ n * 2 ^ n < a" using sz anz apply (subst word_less_nat_alt) apply (subst unat_word_ariths) apply (subst unat_div) apply simp apply (rule order_le_less_trans [OF mod_less_eq_dividend]) apply (erule order_le_neq_trans [OF div_mult_le]) done also from xk le have "\ \ of_nat k * 2 ^ n" by (simp add: field_simps) finally show ?thesis using sz kv apply - apply (erule word_mult_less_dest [OF _ _ kn]) apply (simp add: unat_div) apply (rule order_le_less_trans [OF div_mult_le]) apply (rule unat_lt2p) done qed lemma mask_out_sub_mask: "(x AND NOT (mask n)) = x - (x AND (mask n))" for x :: \'a::len word\ by (simp add: field_simps word_plus_and_or_coroll2) lemma subtract_mask: "p - (p AND mask n) = (p AND NOT (mask n))" "p - (p AND NOT (mask n)) = (p AND mask n)" for p :: \'a::len word\ by (simp add: field_simps word_plus_and_or_coroll2)+ lemma take_bit_word_eq_self_iff: \take_bit n w = w \ n \ LENGTH('a) \ w < 2 ^ n\ for w :: \'a::len word\ using take_bit_int_eq_self_iff [of n \take_bit LENGTH('a) (uint w)\] by (transfer fixing: n) auto lemma word_power_increasing: assumes x: "2 ^ x < (2 ^ y::'a::len word)" "x < LENGTH('a::len)" "y < LENGTH('a::len)" shows "x < y" using x using assms by transfer simp lemma mask_twice: "(x AND mask n) AND mask m = x AND mask (min m n)" for x :: \'a::len word\ by (simp flip: take_bit_eq_mask) lemma plus_one_helper[elim!]: "x < n + (1 :: 'a :: len word) \ x \ n" apply (simp add: word_less_nat_alt word_le_nat_alt field_simps) apply (case_tac "1 + n = 0") apply simp_all apply (subst(asm) unatSuc, assumption) apply arith done lemma plus_one_helper2: "\ x \ n; n + 1 \ 0 \ \ x < n + (1 :: 'a :: len word)" by (simp add: word_less_nat_alt word_le_nat_alt field_simps unatSuc) lemma less_x_plus_1: fixes x :: "'a :: len word" shows "x \ - 1 \ (y < (x + 1)) = (y < x \ y = x)" apply (rule iffI) apply (rule disjCI) apply (drule plus_one_helper) apply simp apply (subgoal_tac "x < x + 1") apply (erule disjE, simp_all) apply (rule plus_one_helper2 [OF order_refl]) apply (rule notI, drule max_word_wrap) apply simp done lemma word_Suc_leq: fixes k::"'a::len word" shows "k \ - 1 \ x < k + 1 \ x \ k" using less_x_plus_1 word_le_less_eq by auto lemma word_Suc_le: fixes k::"'a::len word" shows "x \ - 1 \ x + 1 \ k \ x < k" by (meson not_less word_Suc_leq) lemma word_lessThan_Suc_atMost: \{..< k + 1} = {..k}\ if \k \ - 1\ for k :: \'a::len word\ using that by (simp add: lessThan_def atMost_def word_Suc_leq) lemma word_atLeastLessThan_Suc_atLeastAtMost: \{l ..< u + 1} = {l..u}\ if \u \ - 1\ for l :: \'a::len word\ using that by (simp add: atLeastAtMost_def atLeastLessThan_def word_lessThan_Suc_atMost) lemma word_atLeastAtMost_Suc_greaterThanAtMost: \{m<..u} = {m + 1..u}\ if \m \ - 1\ for m :: \'a::len word\ using that by (simp add: greaterThanAtMost_def greaterThan_def atLeastAtMost_def atLeast_def word_Suc_le) lemma word_atLeastLessThan_Suc_atLeastAtMost_union: fixes l::"'a::len word" assumes "m \ - 1" and "l \ m" and "m \ u" shows "{l..m} \ {m+1..u} = {l..u}" proof - from ivl_disj_un_two(8)[OF assms(2) assms(3)] have "{l..u} = {l..m} \ {m<..u}" by blast with assms show ?thesis by(simp add: word_atLeastAtMost_Suc_greaterThanAtMost) qed lemma max_word_less_eq_iff [simp]: \- 1 \ w \ w = - 1\ for w :: \'a::len word\ by (fact word_order.extremum_unique) lemma word_or_zero: "(a OR b = 0) = (a = 0 \ b = 0)" for a b :: \'a::len word\ by (fact or_eq_0_iff) lemma word_2p_mult_inc: assumes x: "2 * 2 ^ n < (2::'a::len word) * 2 ^ m" assumes suc_n: "Suc n < LENGTH('a::len)" shows "2^n < (2::'a::len word)^m" by (smt suc_n le_less_trans lessI nat_less_le nat_mult_less_cancel_disj p2_gt_0 power_Suc power_Suc unat_power_lower word_less_nat_alt x) lemma power_overflow: "n \ LENGTH('a) \ 2 ^ n = (0 :: 'a::len word)" by simp lemmas extra_sle_sless_unfolds [simp] = word_sle_eq[where a=0 and b=1] word_sle_eq[where a=0 and b="numeral n"] word_sle_eq[where a=1 and b=0] word_sle_eq[where a=1 and b="numeral n"] word_sle_eq[where a="numeral n" and b=0] word_sle_eq[where a="numeral n" and b=1] word_sless_alt[where a=0 and b=1] word_sless_alt[where a=0 and b="numeral n"] word_sless_alt[where a=1 and b=0] word_sless_alt[where a=1 and b="numeral n"] word_sless_alt[where a="numeral n" and b=0] word_sless_alt[where a="numeral n" and b=1] for n lemma word_sint_1: "sint (1::'a::len word) = (if LENGTH('a) = 1 then -1 else 1)" by (fact signed_1) lemma ucast_of_nat: "is_down (ucast :: 'a :: len word \ 'b :: len word) \ ucast (of_nat n :: 'a word) = (of_nat n :: 'b word)" by transfer simp lemma scast_1': "(scast (1::'a::len word) :: 'b::len word) = (word_of_int (signed_take_bit (LENGTH('a::len) - Suc 0) (1::int)))" by transfer simp lemma scast_1: "(scast (1::'a::len word) :: 'b::len word) = (if LENGTH('a) = 1 then -1 else 1)" by (fact signed_1) lemma unat_minus_one_word: "unat (-1 :: 'a :: len word) = 2 ^ LENGTH('a) - 1" apply (simp only: flip: mask_eq_exp_minus_1) apply transfer apply (simp add: take_bit_minus_one_eq_mask nat_mask_eq) done lemmas word_diff_ls'' = word_diff_ls [where xa=x and x=x for x] lemmas word_diff_ls' = word_diff_ls'' [simplified] lemmas word_l_diffs' = word_l_diffs [where xa=x and x=x for x] lemmas word_l_diffs = word_l_diffs' [simplified] lemma two_power_increasing: "\ n \ m; m < LENGTH('a) \ \ (2 :: 'a :: len word) ^ n \ 2 ^ m" by (simp add: word_le_nat_alt) lemma word_leq_le_minus_one: "\ x \ y; x \ 0 \ \ x - 1 < (y :: 'a :: len word)" apply (simp add: word_less_nat_alt word_le_nat_alt) apply (subst unat_minus_one) apply assumption apply (cases "unat x") apply (simp add: unat_eq_zero) apply arith done lemma neg_mask_combine: "NOT(mask a) AND NOT(mask b) = NOT(mask (max a b) :: 'a::len word)" by (rule bit_word_eqI) (auto simp add: bit_simps) lemma neg_mask_twice: "x AND NOT(mask n) AND NOT(mask m) = x AND NOT(mask (max n m))" for x :: \'a::len word\ by (rule bit_word_eqI) (auto simp add: bit_simps) lemma multiple_mask_trivia: "n \ m \ (x AND NOT(mask n)) + (x AND mask n AND NOT(mask m)) = x AND NOT(mask m)" for x :: \'a::len word\ apply (rule trans[rotated], rule_tac w="mask n" in word_plus_and_or_coroll2) apply (simp add: word_bw_assocs word_bw_comms word_bw_lcs neg_mask_twice max_absorb2) done lemma word_of_nat_less: "\ n < unat x \ \ of_nat n < x" apply (simp add: word_less_nat_alt) apply (erule order_le_less_trans[rotated]) apply (simp add: take_bit_eq_mod) done lemma unat_mask: "unat (mask n :: 'a :: len word) = 2 ^ (min n (LENGTH('a))) - 1" apply (subst min.commute) apply (simp add: mask_eq_decr_exp not_less min_def split: if_split_asm) apply (intro conjI impI) apply (simp add: unat_sub_if_size) apply (simp add: power_overflow word_size) apply (simp add: unat_sub_if_size) done lemma mask_over_length: "LENGTH('a) \ n \ mask n = (-1::'a::len word)" by (simp add: mask_eq_decr_exp) lemma Suc_2p_unat_mask: "n < LENGTH('a) \ Suc (2 ^ n * k + unat (mask n :: 'a::len word)) = 2 ^ n * (k+1)" by (simp add: unat_mask) lemma sint_of_nat_ge_zero: "x < 2 ^ (LENGTH('a) - 1) \ sint (of_nat x :: 'a :: len word) \ 0" by (simp add: bit_iff_odd) lemma int_eq_sint: "x < 2 ^ (LENGTH('a) - 1) \ sint (of_nat x :: 'a :: len word) = int x" apply transfer apply (rule signed_take_bit_int_eq_self) apply simp_all apply (metis negative_zle numeral_power_eq_of_nat_cancel_iff) done lemma sint_of_nat_le: "\ b < 2 ^ (LENGTH('a) - 1); a \ b \ \ sint (of_nat a :: 'a :: len word) \ sint (of_nat b :: 'a :: len word)" apply (cases \LENGTH('a)\) apply simp_all apply transfer apply (subst signed_take_bit_eq_if_positive) apply (simp add: bit_simps) apply (metis bit_take_bit_iff nat_less_le order_less_le_trans take_bit_nat_eq_self_iff) apply (subst signed_take_bit_eq_if_positive) apply (simp add: bit_simps) apply (metis bit_take_bit_iff nat_less_le take_bit_nat_eq_self_iff) apply (simp flip: of_nat_take_bit add: take_bit_nat_eq_self) done lemma word_le_not_less: "((b::'a::len word) \ a) = (\(a < b))" by fastforce lemma less_is_non_zero_p1: fixes a :: "'a :: len word" shows "a < k \ a + 1 \ 0" apply (erule contrapos_pn) apply (drule max_word_wrap) apply (simp add: not_less) done lemma unat_add_lem': "(unat x + unat y < 2 ^ LENGTH('a)) \ (unat (x + y :: 'a :: len word) = unat x + unat y)" by (subst unat_add_lem[symmetric], assumption) lemma word_less_two_pow_divI: "\ (x :: 'a::len word) < 2 ^ (n - m); m \ n; n < LENGTH('a) \ \ x < 2 ^ n div 2 ^ m" apply (simp add: word_less_nat_alt) apply (subst unat_word_ariths) apply (subst mod_less) apply (rule order_le_less_trans [OF div_le_dividend]) apply (rule unat_lt2p) apply (simp add: power_sub) done lemma word_less_two_pow_divD: "\ (x :: 'a::len word) < 2 ^ n div 2 ^ m \ \ n \ m \ (x < 2 ^ (n - m))" apply (cases "n < LENGTH('a)") apply (cases "m < LENGTH('a)") apply (simp add: word_less_nat_alt) apply (subst(asm) unat_word_ariths) apply (subst(asm) mod_less) apply (rule order_le_less_trans [OF div_le_dividend]) apply (rule unat_lt2p) apply (clarsimp dest!: less_two_pow_divD) apply (simp add: power_overflow) apply (simp add: word_div_def) apply (simp add: power_overflow word_div_def) done lemma of_nat_less_two_pow_div_set: "\ n < LENGTH('a) \ \ {x. x < (2 ^ n div 2 ^ m :: 'a::len word)} = of_nat ` {k. k < 2 ^ n div 2 ^ m}" apply (simp add: image_def) apply (safe dest!: word_less_two_pow_divD less_two_pow_divD intro!: word_less_two_pow_divI) apply (rule_tac x="unat x" in exI) apply (simp add: power_sub[symmetric]) apply (subst unat_power_lower[symmetric, where 'a='a]) apply simp apply (erule unat_mono) apply (subst word_unat_power) apply (rule of_nat_mono_maybe) apply (rule power_strict_increasing) apply simp apply simp apply assumption done lemma ucast_less: "LENGTH('b) < LENGTH('a) \ (ucast (x :: 'b :: len word) :: ('a :: len word)) < 2 ^ LENGTH('b)" by transfer simp lemma ucast_range_less: "LENGTH('a :: len) < LENGTH('b :: len) \ range (ucast :: 'a word \ 'b word) = {x. x < 2 ^ len_of TYPE ('a)}" apply safe apply (erule ucast_less) apply (simp add: image_def) apply (rule_tac x="ucast x" in exI) apply (rule bit_word_eqI) apply (auto simp add: bit_simps) apply (metis bit_take_bit_iff less_mask_eq not_less take_bit_eq_mask) done lemma word_power_less_diff: "\2 ^ n * q < (2::'a::len word) ^ m; q < 2 ^ (LENGTH('a) - n)\ \ q < 2 ^ (m - n)" apply (case_tac "m \ LENGTH('a)") apply (simp add: power_overflow) apply (case_tac "n \ LENGTH('a)") apply (simp add: power_overflow) apply (cases "n = 0") apply simp apply (subst word_less_nat_alt) apply (subst unat_power_lower) apply simp apply (rule nat_power_less_diff) apply (simp add: word_less_nat_alt) apply (subst (asm) iffD1 [OF unat_mult_lem]) apply (simp add:nat_less_power_trans) apply simp done lemma word_less_sub_1: "x < (y :: 'a :: len word) \ x \ y - 1" by (fact word_le_minus_one_leq) lemma word_sub_mono2: "\ a + b \ c + d; c \ a; b \ a + b; d \ c + d \ \ b \ (d :: 'a :: len word)" apply (drule(1) word_sub_mono) apply simp apply simp apply simp done lemma word_not_le: "(\ x \ (y :: 'a :: len word)) = (y < x)" by fastforce lemma word_subset_less: "\ {x .. x + r - 1} \ {y .. y + s - 1}; x \ x + r - 1; y \ y + (s :: 'a :: len word) - 1; s \ 0 \ \ r \ s" apply (frule subsetD[where c=x]) apply simp apply (drule subsetD[where c="x + r - 1"]) apply simp apply (clarsimp simp: add_diff_eq[symmetric]) apply (drule(1) word_sub_mono2) apply (simp_all add: olen_add_eqv[symmetric]) apply (erule word_le_minus_cancel) apply (rule ccontr) apply (simp add: word_not_le) done lemma uint_power_lower: "n < LENGTH('a) \ uint (2 ^ n :: 'a :: len word) = (2 ^ n :: int)" by (rule uint_2p_alt) lemma power_le_mono: "\2 ^ n \ (2::'a::len word) ^ m; n < LENGTH('a); m < LENGTH('a)\ \ n \ m" apply (clarsimp simp add: le_less) apply safe apply (simp add: word_less_nat_alt) apply (simp only: uint_arith_simps(3)) apply (drule uint_power_lower)+ apply simp done lemma two_power_eq: "\n < LENGTH('a); m < LENGTH('a)\ \ ((2::'a::len word) ^ n = 2 ^ m) = (n = m)" apply safe apply (rule order_antisym) apply (simp add: power_le_mono[where 'a='a])+ done lemma unat_less_helper: "x < of_nat n \ unat x < n" apply (simp add: word_less_nat_alt) apply (erule order_less_le_trans) apply (simp add: take_bit_eq_mod) done lemma nat_uint_less_helper: "nat (uint y) = z \ x < y \ nat (uint x) < z" apply (erule subst) apply (subst unat_eq_nat_uint [symmetric]) apply (subst unat_eq_nat_uint [symmetric]) by (simp add: unat_mono) lemma of_nat_0: "\of_nat n = (0::'a::len word); n < 2 ^ LENGTH('a)\ \ n = 0" by transfer (simp add: take_bit_eq_mod) lemma of_nat_inj: "\x < 2 ^ LENGTH('a); y < 2 ^ LENGTH('a)\ \ (of_nat x = (of_nat y :: 'a :: len word)) = (x = y)" by (metis unat_of_nat_len) lemma div_to_mult_word_lt: "\ (x :: 'a :: len word) \ y div z \ \ x * z \ y" apply (cases "z = 0") apply simp apply (simp add: word_neq_0_conv) apply (rule order_trans) apply (erule(1) word_mult_le_mono1) apply (simp add: unat_div) apply (rule order_le_less_trans [OF div_mult_le]) apply simp apply (rule word_div_mult_le) done lemma ucast_ucast_mask: "(ucast :: 'a :: len word \ 'b :: len word) (ucast x) = x AND mask (len_of TYPE ('a))" apply (simp flip: take_bit_eq_mask) apply transfer apply (simp add: ac_simps) done lemma ucast_ucast_len: "\ x < 2 ^ LENGTH('b) \ \ ucast (ucast x::'b::len word) = (x::'a::len word)" apply (subst ucast_ucast_mask) apply (erule less_mask_eq) done lemma ucast_ucast_id: "LENGTH('a) < LENGTH('b) \ ucast (ucast (x::'a::len word)::'b::len word) = x" by (auto intro: ucast_up_ucast_id simp: is_up_def source_size_def target_size_def word_size) lemma unat_ucast: "unat (ucast x :: ('a :: len) word) = unat x mod 2 ^ (LENGTH('a))" proof - have \2 ^ LENGTH('a) = nat (2 ^ LENGTH('a))\ by simp moreover have \unat (ucast x :: 'a word) = unat x mod nat (2 ^ LENGTH('a))\ by transfer (simp flip: nat_mod_distrib take_bit_eq_mod) ultimately show ?thesis by (simp only:) qed lemma ucast_less_ucast: "LENGTH('a) \ LENGTH('b) \ (ucast x < ((ucast (y :: 'a::len word)) :: 'b::len word)) = (x < y)" apply (simp add: word_less_nat_alt unat_ucast) apply (subst mod_less) apply(rule less_le_trans[OF unat_lt2p], simp) apply (subst mod_less) apply(rule less_le_trans[OF unat_lt2p], simp) apply simp done \ \This weaker version was previously called @{text ucast_less_ucast}. We retain it to support existing proofs.\ lemmas ucast_less_ucast_weak = ucast_less_ucast[OF order.strict_implies_order] lemma unat_Suc2: fixes n :: "'a :: len word" shows "n \ -1 \ unat (n + 1) = Suc (unat n)" apply (subst add.commute, rule unatSuc) apply (subst eq_diff_eq[symmetric], simp add: minus_equation_iff) done lemma word_div_1: "(n :: 'a :: len word) div 1 = n" by (fact bits_div_by_1) lemma word_minus_one_le: "-1 \ (x :: 'a :: len word) = (x = -1)" by (fact word_order.extremum_unique) lemma up_scast_inj: "\ scast x = (scast y :: 'b :: len word); size x \ LENGTH('b) \ \ x = y" apply transfer apply (cases \LENGTH('a)\) apply simp_all apply (metis order_refl take_bit_signed_take_bit take_bit_tightened) done lemma up_scast_inj_eq: "LENGTH('a) \ len_of TYPE ('b) \ (scast x = (scast y::'b::len word)) = (x = (y::'a::len word))" by (fastforce dest: up_scast_inj simp: word_size) lemma word_le_add: fixes x :: "'a :: len word" shows "x \ y \ \n. y = x + of_nat n" by (rule exI [where x = "unat (y - x)"]) simp lemma word_plus_mcs_4': fixes x :: "'a :: len word" shows "\x + v \ x + w; x \ x + v\ \ v \ w" apply (rule word_plus_mcs_4) apply (simp add: add.commute) apply (simp add: add.commute) done lemma unat_eq_1: \unat x = Suc 0 \ x = 1\ by (auto intro!: unsigned_word_eqI [where ?'a = nat]) lemma word_unat_Rep_inject1: \unat x = unat 1 \ x = 1\ by (simp add: unat_eq_1) lemma and_not_mask_twice: "(w AND NOT (mask n)) AND NOT (mask m) = w AND NOT (mask (max m n))" for w :: \'a::len word\ by (rule bit_word_eqI) (auto simp add: bit_simps) lemma word_less_cases: "x < y \ x = y - 1 \ x < y - (1 ::'a::len word)" apply (drule word_less_sub_1) apply (drule order_le_imp_less_or_eq) apply auto done lemma mask_and_mask: "mask a AND mask b = (mask (min a b) :: 'a::len word)" by (simp flip: take_bit_eq_mask ac_simps) lemma mask_eq_0_eq_x: "(x AND w = 0) = (x AND NOT w = x)" for x w :: \'a::len word\ using word_plus_and_or_coroll2[where x=x and w=w] by auto lemma mask_eq_x_eq_0: "(x AND w = x) = (x AND NOT w = 0)" for x w :: \'a::len word\ using word_plus_and_or_coroll2[where x=x and w=w] by auto lemma compl_of_1: "NOT 1 = (-2 :: 'a :: len word)" by (fact not_one) lemma split_word_eq_on_mask: "(x = y) = (x AND m = y AND m \ x AND NOT m = y AND NOT m)" for x y m :: \'a::len word\ apply transfer apply (simp add: bit_eq_iff) apply (auto simp add: bit_simps ac_simps) done lemma word_FF_is_mask: "0xFF = (mask 8 :: 'a::len word)" by (simp add: mask_eq_decr_exp) lemma word_1FF_is_mask: "0x1FF = (mask 9 :: 'a::len word)" by (simp add: mask_eq_decr_exp) lemma ucast_of_nat_small: "x < 2 ^ LENGTH('a) \ ucast (of_nat x :: 'a :: len word) = (of_nat x :: 'b :: len word)" apply transfer apply (auto simp add: take_bit_of_nat min_def not_le) apply (metis linorder_not_less min_def take_bit_nat_eq_self take_bit_take_bit) done lemma word_le_make_less: fixes x :: "'a :: len word" shows "y \ -1 \ (x \ y) = (x < (y + 1))" apply safe apply (erule plus_one_helper2) apply (simp add: eq_diff_eq[symmetric]) done lemmas finite_word = finite [where 'a="'a::len word"] lemma word_to_1_set: "{0 ..< (1 :: 'a :: len word)} = {0}" by fastforce lemma word_leq_minus_one_le: fixes x :: "'a::len word" shows "\y \ 0; x \ y - 1 \ \ x < y" using le_m1_iff_lt word_neq_0_conv by blast lemma word_count_from_top: "n \ 0 \ {0 ..< n :: 'a :: len word} = {0 ..< n - 1} \ {n - 1}" apply (rule set_eqI, rule iffI) apply simp apply (drule word_le_minus_one_leq) apply (rule disjCI) apply simp apply simp apply (erule word_leq_minus_one_le) apply fastforce done lemma word_minus_one_le_leq: "\ x - 1 < y \ \ x \ (y :: 'a :: len word)" apply (cases "x = 0") apply simp apply (simp add: word_less_nat_alt word_le_nat_alt) apply (subst(asm) unat_minus_one) apply (simp add: word_less_nat_alt) apply (cases "unat x") apply (simp add: unat_eq_zero) apply arith done lemma word_div_less: "m < n \ m div n = 0" for m :: "'a :: len word" by (simp add: unat_mono word_arith_nat_defs(6)) lemma word_must_wrap: "\ x \ n - 1; n \ x \ \ n = (0 :: 'a :: len word)" using dual_order.trans sub_wrap word_less_1 by blast lemma range_subset_card: "\ {a :: 'a :: len word .. b} \ {c .. d}; b \ a \ \ d \ c \ d - c \ b - a" using word_sub_le word_sub_mono by fastforce lemma less_1_simp: "n - 1 < m = (n \ (m :: 'a :: len word) \ n \ 0)" by unat_arith lemma word_power_mod_div: fixes x :: "'a::len word" shows "\ n < LENGTH('a); m < LENGTH('a)\ \ x mod 2 ^ n div 2 ^ m = x div 2 ^ m mod 2 ^ (n - m)" apply (simp add: word_arith_nat_div unat_mod power_mod_div) apply (subst unat_arith_simps(3)) apply (subst unat_mod) apply (subst unat_of_nat)+ apply (simp add: mod_mod_power min.commute) done lemma word_range_minus_1': fixes a :: "'a :: len word" shows "a \ 0 \ {a - 1<..b} = {a..b}" by (simp add: greaterThanAtMost_def atLeastAtMost_def greaterThan_def atLeast_def less_1_simp) lemma word_range_minus_1: fixes a :: "'a :: len word" shows "b \ 0 \ {a..b - 1} = {a.. 'b :: len word) x" by transfer simp lemma overflow_plus_one_self: "(1 + p \ p) = (p = (-1 :: 'a :: len word))" apply rule apply (rule ccontr) apply (drule plus_one_helper2) apply (rule notI) apply (drule arg_cong[where f="\x. x - 1"]) apply simp apply (simp add: field_simps) apply simp done lemma plus_1_less: "(x + 1 \ (x :: 'a :: len word)) = (x = -1)" apply (rule iffI) apply (rule ccontr) apply (cut_tac plus_one_helper2[where x=x, OF order_refl]) apply simp apply clarsimp apply (drule arg_cong[where f="\x. x - 1"]) apply simp apply simp done lemma pos_mult_pos_ge: "[|x > (0::int); n>=0 |] ==> n * x >= n*1" apply (simp only: mult_left_mono) done lemma word_plus_strict_mono_right: fixes x :: "'a :: len word" shows "\y < z; x \ x + z\ \ x + y < x + z" by unat_arith lemma word_div_mult: "0 < c \ a < b * c \ a div c < b" for a b c :: "'a::len word" by (rule classical) (use div_to_mult_word_lt [of b a c] in \auto simp add: word_less_nat_alt word_le_nat_alt unat_div\) lemma word_less_power_trans_ofnat: "\n < 2 ^ (m - k); k \ m; m < LENGTH('a)\ \ of_nat n * 2 ^ k < (2::'a::len word) ^ m" apply (subst mult.commute) apply (rule word_less_power_trans) apply (simp_all add: word_less_nat_alt less_le_trans take_bit_eq_mod) done lemma word_1_le_power: "n < LENGTH('a) \ (1 :: 'a :: len word) \ 2 ^ n" by (rule inc_le[where i=0, simplified], erule iffD2[OF p2_gt_0]) lemma unat_1_0: "1 \ (x::'a::len word) = (0 < unat x)" by (auto simp add: word_le_nat_alt) lemma x_less_2_0_1': fixes x :: "'a::len word" shows "\LENGTH('a) \ 1; x < 2\ \ x = 0 \ x = 1" apply (cases \2 \ LENGTH('a)\) apply simp_all apply transfer apply auto apply (metis add.commute add.right_neutral even_two_times_div_two mod_div_trivial mod_pos_pos_trivial mult.commute mult_zero_left not_less not_take_bit_negative odd_two_times_div_two_succ) done lemmas word_add_le_iff2 = word_add_le_iff [folded no_olen_add_nat] lemma of_nat_power: shows "\ p < 2 ^ x; x < len_of TYPE ('a) \ \ of_nat p < (2 :: 'a :: len word) ^ x" apply (rule order_less_le_trans) apply (rule of_nat_mono_maybe) apply (erule power_strict_increasing) apply simp apply assumption apply (simp add: word_unat_power del: of_nat_power) done lemma of_nat_n_less_equal_power_2: "n < LENGTH('a::len) \ ((of_nat n)::'a word) < 2 ^ n" apply (induct n) apply clarsimp apply clarsimp apply (metis of_nat_power n_less_equal_power_2 of_nat_Suc power_Suc) done lemma eq_mask_less: fixes w :: "'a::len word" assumes eqm: "w = w AND mask n" and sz: "n < len_of TYPE ('a)" shows "w < (2::'a word) ^ n" by (subst eqm, rule and_mask_less' [OF sz]) lemma of_nat_mono_maybe': fixes Y :: "nat" assumes xlt: "x < 2 ^ len_of TYPE ('a)" assumes ylt: "y < 2 ^ len_of TYPE ('a)" shows "(y < x) = (of_nat y < (of_nat x :: 'a :: len word))" apply (subst word_less_nat_alt) apply (subst unat_of_nat)+ apply (subst mod_less) apply (rule ylt) apply (subst mod_less) apply (rule xlt) apply simp done lemma of_nat_mono_maybe_le: "\x < 2 ^ LENGTH('a); y < 2 ^ LENGTH('a)\ \ (y \ x) = ((of_nat y :: 'a :: len word) \ of_nat x)" apply (clarsimp simp: le_less) apply (rule disj_cong) apply (rule of_nat_mono_maybe', assumption+) apply auto using of_nat_inj apply blast done lemma mask_AND_NOT_mask: "(w AND NOT (mask n)) AND mask n = 0" for w :: \'a::len word\ by (rule bit_word_eqI) (simp add: bit_simps) lemma AND_NOT_mask_plus_AND_mask_eq: "(w AND NOT (mask n)) + (w AND mask n) = w" for w :: \'a::len word\ apply (subst disjunctive_add) apply (auto simp add: bit_simps) apply (rule bit_word_eqI) apply (auto simp add: bit_simps) done lemma mask_eqI: fixes x :: "'a :: len word" assumes m1: "x AND mask n = y AND mask n" and m2: "x AND NOT (mask n) = y AND NOT (mask n)" shows "x = y" proof - have *: \x = x AND mask n OR x AND NOT (mask n)\ for x :: \'a word\ by (rule bit_word_eqI) (auto simp add: bit_simps) from assms * [of x] * [of y] show ?thesis by simp qed lemma neq_0_no_wrap: fixes x :: "'a :: len word" shows "\ x \ x + y; x \ 0 \ \ x + y \ 0" by clarsimp lemma unatSuc2: fixes n :: "'a :: len word" shows "n + 1 \ 0 \ unat (n + 1) = Suc (unat n)" by (simp add: add.commute unatSuc) lemma word_of_nat_le: "n \ unat x \ of_nat n \ x" apply (simp add: word_le_nat_alt unat_of_nat) apply (erule order_trans[rotated]) apply (simp add: take_bit_eq_mod) done lemma word_unat_less_le: "a \ of_nat b \ unat a \ b" by (metis eq_iff le_cases le_unat_uoi word_of_nat_le) lemma mask_Suc_0 : "mask (Suc 0) = (1 :: 'a::len word)" by (simp add: mask_eq_decr_exp) lemma bool_mask': fixes x :: "'a :: len word" shows "2 < LENGTH('a) \ (0 < x AND 1) = (x AND 1 = 1)" by (simp add: and_one_eq mod_2_eq_odd) lemma ucast_ucast_add: fixes x :: "'a :: len word" fixes y :: "'b :: len word" shows "LENGTH('b) \ LENGTH('a) \ ucast (ucast x + y) = x + ucast y" apply transfer apply simp apply (subst (2) take_bit_add [symmetric]) apply (subst take_bit_add [symmetric]) apply simp done lemma lt1_neq0: fixes x :: "'a :: len word" shows "(1 \ x) = (x \ 0)" by unat_arith lemma word_plus_one_nonzero: fixes x :: "'a :: len word" shows "\x \ x + y; y \ 0\ \ x + 1 \ 0" apply (subst lt1_neq0 [symmetric]) apply (subst olen_add_eqv [symmetric]) apply (erule word_random) apply (simp add: lt1_neq0) done lemma word_sub_plus_one_nonzero: fixes n :: "'a :: len word" shows "\n' \ n; n' \ 0\ \ (n - n') + 1 \ 0" apply (subst lt1_neq0 [symmetric]) apply (subst olen_add_eqv [symmetric]) apply (rule word_random [where x' = n']) apply simp apply (erule word_sub_le) apply (simp add: lt1_neq0) done lemma word_le_minus_mono_right: fixes x :: "'a :: len word" shows "\ z \ y; y \ x; z \ x \ \ x - y \ x - z" apply (rule word_sub_mono) apply simp apply assumption apply (erule word_sub_le) apply (erule word_sub_le) done lemma word_0_sle_from_less: \0 \s x\ if \x < 2 ^ (LENGTH('a) - 1)\ for x :: \'a::len word\ using that apply transfer apply (cases \LENGTH('a)\) apply simp_all apply (metis bit_take_bit_iff min_def nat_less_le not_less_eq take_bit_int_eq_self_iff take_bit_take_bit) done lemma ucast_sub_ucast: fixes x :: "'a::len word" assumes "y \ x" assumes T: "LENGTH('a) \ LENGTH('b)" shows "ucast (x - y) = (ucast x - ucast y :: 'b::len word)" proof - from T have P: "unat x < 2 ^ LENGTH('b)" "unat y < 2 ^ LENGTH('b)" by (fastforce intro!: less_le_trans[OF unat_lt2p])+ then show ?thesis by (simp add: unat_arith_simps unat_ucast assms[simplified unat_arith_simps]) qed lemma word_1_0: "\a + (1::('a::len) word) \ b; a < of_nat x\ \ a < b" apply transfer apply (subst (asm) take_bit_incr_eq) apply (auto simp add: diff_less_eq) using take_bit_int_less_exp le_less_trans by blast lemma unat_of_nat_less:"\ a < b; unat b = c \ \ a < of_nat c" by fastforce lemma word_le_plus_1: "\ (y::('a::len) word) < y + n; a < n \ \ y + a \ y + a + 1" by unat_arith lemma word_le_plus:"\(a::('a::len) word) < a + b; c < b\ \ a \ a + c" by (metis order_less_imp_le word_random) lemma sint_minus1 [simp]: "(sint x = -1) = (x = -1)" apply (cases \LENGTH('a)\) apply simp_all apply transfer apply (simp flip: signed_take_bit_eq_iff_take_bit_eq) done lemma sint_0 [simp]: "(sint x = 0) = (x = 0)" by (fact signed_eq_0_iff) (* It is not always that case that "sint 1 = 1", because of 1-bit word sizes. * This lemma produces the different cases. *) lemma sint_1_cases: P if \\ len_of TYPE ('a::len) = 1; (a::'a word) = 0; sint a = 0 \ \ P\ \\ len_of TYPE ('a) = 1; a = 1; sint (1 :: 'a word) = -1 \ \ P\ \\ len_of TYPE ('a) > 1; sint (1 :: 'a word) = 1 \ \ P\ proof (cases \LENGTH('a) = 1\) case True then have \a = 0 \ a = 1\ by transfer auto with True that show ?thesis by auto next case False with that show ?thesis by (simp add: less_le Suc_le_eq) qed lemma sint_int_min: "sint (- (2 ^ (LENGTH('a) - Suc 0)) :: ('a::len) word) = - (2 ^ (LENGTH('a) - Suc 0))" apply (cases \LENGTH('a)\) apply simp_all apply transfer apply (simp add: signed_take_bit_int_eq_self) done lemma sint_int_max_plus_1: "sint (2 ^ (LENGTH('a) - Suc 0) :: ('a::len) word) = - (2 ^ (LENGTH('a) - Suc 0))" apply (cases \LENGTH('a)\) apply simp_all apply (subst word_of_int_2p [symmetric]) apply (subst int_word_sint) apply simp done lemma uint_range': \0 \ uint x \ uint x < 2 ^ LENGTH('a)\ for x :: \'a::len word\ by transfer simp lemma sint_of_int_eq: "\ - (2 ^ (LENGTH('a) - 1)) \ x; x < 2 ^ (LENGTH('a) - 1) \ \ sint (of_int x :: ('a::len) word) = x" by (simp add: signed_take_bit_int_eq_self) lemma of_int_sint: "of_int (sint a) = a" by simp lemma sint_ucast_eq_uint: "\ \ is_down (ucast :: ('a::len word \ 'b::len word)) \ \ sint ((ucast :: ('a::len word \ 'b::len word)) x) = uint x" apply transfer apply (simp add: signed_take_bit_take_bit) done lemma word_less_nowrapI': "(x :: 'a :: len word) \ z - k \ k \ z \ 0 < k \ x < x + k" by uint_arith lemma mask_plus_1: "mask n + 1 = (2 ^ n :: 'a::len word)" by (clarsimp simp: mask_eq_decr_exp) lemma unat_inj: "inj unat" by (metis eq_iff injI word_le_nat_alt) lemma unat_ucast_upcast: "is_up (ucast :: 'b word \ 'a word) \ unat (ucast x :: ('a::len) word) = unat (x :: ('b::len) word)" unfolding ucast_eq unat_eq_nat_uint apply transfer apply simp done lemma ucast_mono: "\ (x :: 'b :: len word) < y; y < 2 ^ LENGTH('a) \ \ ucast x < ((ucast y) :: 'a :: len word)" apply (simp only: flip: ucast_nat_def) apply (rule of_nat_mono_maybe) apply (rule unat_less_helper) apply simp apply (simp add: word_less_nat_alt) done lemma ucast_mono_le: "\x \ y; y < 2 ^ LENGTH('b)\ \ (ucast (x :: 'a :: len word) :: 'b :: len word) \ ucast y" apply (simp only: flip: ucast_nat_def) apply (subst of_nat_mono_maybe_le[symmetric]) apply (rule unat_less_helper) apply simp apply (rule unat_less_helper) apply (erule le_less_trans) apply (simp_all add: word_le_nat_alt) done lemma ucast_mono_le': "\ unat y < 2 ^ LENGTH('b); LENGTH('b::len) < LENGTH('a::len); x \ y \ \ ucast x \ (ucast y :: 'b word)" for x y :: \'a::len word\ by (auto simp: word_less_nat_alt intro: ucast_mono_le) lemma neg_mask_add_mask: "((x:: 'a :: len word) AND NOT (mask n)) + (2 ^ n - 1) = x OR mask n" unfolding mask_2pm1 [symmetric] apply (subst word_plus_and_or_coroll; rule bit_word_eqI) apply (auto simp add: bit_simps) done lemma le_step_down_word:"\(i::('a::len) word) \ n; i = n \ P; i \ n - 1 \ P\ \ P" by unat_arith lemma le_step_down_word_2: fixes x :: "'a::len word" shows "\x \ y; x \ y\ \ x \ y - 1" by (subst (asm) word_le_less_eq, clarsimp, simp add: word_le_minus_one_leq) lemma NOT_mask_AND_mask[simp]: "(w AND mask n) AND NOT (mask n) = 0" - by (clarsimp simp add: mask_eq_decr_exp Parity.bit_eq_iff bit_and_iff bit_not_iff bit_mask_iff) + by (rule bit_eqI) (simp add: bit_simps) lemma and_and_not[simp]:"(a AND b) AND NOT b = 0" for a b :: \'a::len word\ apply (subst word_bw_assocs(1)) apply clarsimp done lemma ex_mask_1[simp]: "(\x. mask x = (1 :: 'a::len word))" apply (rule_tac x=1 in exI) apply (simp add:mask_eq_decr_exp) done lemma not_switch:"NOT a = x \ a = NOT x" by auto lemma test_bit_eq_iff: "bit u = bit v \ u = v" for u v :: "'a::len word" by (simp add: bit_eq_iff fun_eq_iff) lemma test_bit_size: "bit w n \ n < size w" for w :: "'a::len word" by transfer simp lemma word_eq_iff: "x = y \ (\n?P \ ?Q\) for x y :: "'a::len word" by transfer (auto simp add: bit_eq_iff bit_take_bit_iff) lemma word_eqI: "(\n. n < size u \ bit u n = bit v n) \ u = v" for u :: "'a::len word" by (simp add: word_size word_eq_iff) lemma word_eqD: "u = v \ bit u x = bit v x" for u v :: "'a::len word" by simp lemma test_bit_bin': "bit w n \ n < size w \ bit (uint w) n" by transfer (simp add: bit_take_bit_iff) lemmas test_bit_bin = test_bit_bin' [unfolded word_size] lemma word_test_bit_def: \bit a = bit (uint a)\ by transfer (simp add: fun_eq_iff bit_take_bit_iff) lemmas test_bit_def' = word_test_bit_def [THEN fun_cong] lemma word_test_bit_transfer [transfer_rule]: "(rel_fun pcr_word (rel_fun (=) (=))) (\x n. n < LENGTH('a) \ bit x n) (bit :: 'a::len word \ _)" by transfer_prover lemma test_bit_wi: "bit (word_of_int x :: 'a::len word) n \ n < LENGTH('a) \ bit x n" by transfer simp lemma word_ops_nth_size: "n < size x \ bit (x OR y) n = (bit x n | bit y n) \ bit (x AND y) n = (bit x n \ bit y n) \ bit (x XOR y) n = (bit x n \ bit y n) \ bit (NOT x) n = (\ bit x n)" for x :: "'a::len word" by transfer (simp add: bit_or_iff bit_and_iff bit_xor_iff bit_not_iff) lemma word_ao_nth: "bit (x OR y) n = (bit x n | bit y n) \ bit (x AND y) n = (bit x n \ bit y n)" for x :: "'a::len word" by transfer (auto simp add: bit_or_iff bit_and_iff) lemmas lsb0 = len_gt_0 [THEN word_ops_nth_size [unfolded word_size]] lemma nth_sint: fixes w :: "'a::len word" defines "l \ LENGTH('a)" shows "bit (sint w) n = (if n < l - 1 then bit w n else bit w (l - 1))" unfolding sint_uint l_def by (auto simp: bit_signed_take_bit_iff word_test_bit_def not_less min_def) lemma test_bit_2p: "bit (word_of_int (2 ^ n)::'a::len word) m \ m = n \ m < LENGTH('a)" by transfer (auto simp add: bit_exp_iff) lemma nth_w2p: "bit ((2::'a::len word) ^ n) m \ m = n \ m < LENGTH('a::len)" by transfer (auto simp add: bit_exp_iff) lemma bang_is_le: "bit x m \ 2 ^ m \ x" for x :: "'a::len word" apply (rule xtrans(3)) apply (rule_tac [2] y = "x" in le_word_or2) apply (rule word_eqI) apply (auto simp add: word_ao_nth nth_w2p word_size) done lemmas msb0 = len_gt_0 [THEN diff_Suc_less, THEN word_ops_nth_size [unfolded word_size]] lemmas msb1 = msb0 [where i = 0] lemma test_bit_1 [iff]: "bit (1 :: 'a::len word) n \ n = 0" by transfer (auto simp add: bit_1_iff) lemma nth_0: "\ bit (0 :: 'a::len word) n" by transfer simp lemma nth_minus1: "bit (-1 :: 'a::len word) n \ n < LENGTH('a)" by transfer simp lemma nth_ucast: "bit (ucast w::'a::len word) n = (bit w n \ n < LENGTH('a))" by transfer (simp add: bit_take_bit_iff ac_simps) lemma drop_bit_numeral_bit0_1 [simp]: \drop_bit (Suc 0) (numeral k) = (word_of_int (drop_bit (Suc 0) (take_bit LENGTH('a) (numeral k))) :: 'a::len word)\ by (metis Word_eq_word_of_int drop_bit_word.abs_eq of_int_numeral) lemma nth_mask: \bit (mask n :: 'a::len word) i \ i < n \ i < size (mask n :: 'a word)\ by (auto simp add: word_size Word.bit_mask_iff) lemma nth_slice: "bit (slice n w :: 'a::len word) m = (bit w (m + n) \ m < LENGTH('a))" apply (auto simp add: bit_simps less_diff_conv dest: bit_imp_le_length) using bit_imp_le_length apply fastforce done lemma test_bit_cat [OF refl]: "wc = word_cat a b \ bit wc n = (n < size wc \ (if n < size b then bit b n else bit a (n - size b)))" apply (simp add: word_size not_less; transfer) apply (auto simp add: bit_concat_bit_iff bit_take_bit_iff) done \ \keep quantifiers for use in simplification\ lemma test_bit_split': "word_split c = (a, b) \ (\n m. bit b n = (n < size b \ bit c n) \ bit a m = (m < size a \ bit c (m + size b)))" by (auto simp add: word_split_bin' bit_unsigned_iff word_size bit_drop_bit_eq ac_simps dest: bit_imp_le_length) lemma test_bit_split: "word_split c = (a, b) \ (\n::nat. bit b n \ n < size b \ bit c n) \ (\m::nat. bit a m \ m < size a \ bit c (m + size b))" by (simp add: test_bit_split') lemma test_bit_split_eq: "word_split c = (a, b) \ ((\n::nat. bit b n = (n < size b \ bit c n)) \ (\m::nat. bit a m = (m < size a \ bit c (m + size b))))" apply (rule_tac iffI) apply (rule_tac conjI) apply (erule test_bit_split [THEN conjunct1]) apply (erule test_bit_split [THEN conjunct2]) apply (case_tac "word_split c") apply (frule test_bit_split) apply (erule trans) apply (fastforce intro!: word_eqI simp add: word_size) done lemma test_bit_rcat: "sw = size (hd wl) \ rc = word_rcat wl \ bit rc n = (n < size rc \ n div sw < size wl \ bit ((rev wl) ! (n div sw)) (n mod sw))" for wl :: "'a::len word list" by (simp add: word_size word_rcat_def rev_map bit_horner_sum_uint_exp_iff bit_simps not_le) lemmas test_bit_cong = arg_cong [where f = "bit", THEN fun_cong] lemma max_test_bit: "bit (- 1::'a::len word) n \ n < LENGTH('a)" by (fact nth_minus1) lemma map_nth_0 [simp]: "map (bit (0::'a::len word)) xs = replicate (length xs) False" by (simp flip: map_replicate_const) lemma word_and_1: "n AND 1 = (if bit n 0 then 1 else 0)" for n :: "_ word" by (rule bit_word_eqI) (auto simp add: bit_and_iff bit_1_iff intro: gr0I) lemma test_bit_1': "bit (1 :: 'a :: len word) n \ 0 < LENGTH('a) \ n = 0" by simp lemma nth_w2p_same: "bit (2^n :: 'a :: len word) n = (n < LENGTH('a))" by (simp add: nth_w2p) lemma word_leI: "(\n. \n < size (u::'a::len word); bit u n \ \ bit (v::'a::len word) n) \ u <= v" apply (rule order_trans [of u \u AND v\ v]) apply (rule eq_refl) apply (rule bit_word_eqI) apply (auto simp add: bit_simps word_and_le1 word_size) done lemma bang_eq: fixes x :: "'a::len word" shows "(x = y) = (\n. bit x n = bit y n)" by (auto simp add: bit_eq_iff) lemma neg_mask_test_bit: "bit (NOT(mask n) :: 'a :: len word) m = (n \ m \ m < LENGTH('a))" by (auto simp add: bit_simps) lemma upper_bits_unset_is_l2p: \(\n' \ n. n' < LENGTH('a) \ \ bit p n') \ (p < 2 ^ n)\ (is \?P \ ?Q\) if \n < LENGTH('a)\ for p :: "'a :: len word" proof assume ?Q then show ?P by (meson bang_is_le le_less_trans not_le word_power_increasing) next assume ?P have \take_bit n p = p\ proof (rule bit_word_eqI) fix q assume \q < LENGTH('a)\ show \bit (take_bit n p) q \ bit p q\ proof (cases \q < n\) case True then show ?thesis by (auto simp add: bit_simps) next case False then have \n \ q\ by simp with \?P\ \q < LENGTH('a)\ have \\ bit p q\ by simp then show ?thesis by (simp add: bit_simps) qed qed with that show ?Q using take_bit_word_eq_self_iff [of n p] by auto qed lemma less_2p_is_upper_bits_unset: "p < 2 ^ n \ n < LENGTH('a) \ (\n' \ n. n' < LENGTH('a) \ \ bit p n')" for p :: "'a :: len word" by (meson le_less_trans le_mask_iff_lt_2n upper_bits_unset_is_l2p word_zero_le) lemma test_bit_over: "n \ size (x::'a::len word) \ (bit x n) = False" by transfer auto lemma le_mask_high_bits: "w \ mask n \ (\i \ {n ..< size w}. \ bit w i)" for w :: \'a::len word\ apply (auto simp add: bit_simps word_size less_eq_mask_iff_take_bit_eq_self) apply (metis bit_take_bit_iff leD) apply (metis atLeastLessThan_iff leI take_bit_word_eq_self_iff upper_bits_unset_is_l2p) done lemma test_bit_conj_lt: "(bit x m \ m < LENGTH('a)) = bit x m" for x :: "'a :: len word" using test_bit_bin by blast lemma neg_test_bit: "bit (NOT x) n = (\ bit x n \ n < LENGTH('a))" for x :: "'a::len word" by (cases "n < LENGTH('a)") (auto simp add: test_bit_over word_ops_nth_size word_size) lemma nth_bounded: "\bit (x :: 'a :: len word) n; x < 2 ^ m; m \ len_of TYPE ('a)\ \ n < m" apply (rule ccontr) apply (auto simp add: not_less) apply (meson bit_imp_le_length bit_uint_iff less_2p_is_upper_bits_unset test_bit_bin) done lemma and_neq_0_is_nth: \x AND y \ 0 \ bit x n\ if \y = 2 ^ n\ for x y :: \'a::len word\ apply (simp add: bit_eq_iff bit_simps) using that apply (simp add: bit_simps not_le) apply transfer apply auto done lemma nth_is_and_neq_0: "bit (x::'a::len word) n = (x AND 2 ^ n \ 0)" by (subst and_neq_0_is_nth; rule refl) lemma max_word_not_less [simp]: "\ - 1 < x" for x :: \'a::len word\ by (fact word_order.extremum_strict) lemma bit_twiddle_min: "(y::'a::len word) XOR (((x::'a::len word) XOR y) AND (if x < y then -1 else 0)) = min x y" by (rule bit_eqI) (auto simp add: bit_simps) lemma bit_twiddle_max: "(x::'a::len word) XOR (((x::'a::len word) XOR y) AND (if x < y then -1 else 0)) = max x y" by (rule bit_eqI) (auto simp add: bit_simps max_def) lemma swap_with_xor: "\(x::'a::len word) = a XOR b; y = b XOR x; z = x XOR y\ \ z = b \ y = a" - by (auto simp add: Parity.bit_eq_iff bit_xor_iff max_def) + by (auto intro: bit_word_eqI simp add: bit_simps) lemma le_mask_imp_and_mask: "(x::'a::len word) \ mask n \ x AND mask n = x" by (metis and_mask_eq_iff_le_mask) lemma or_not_mask_nop: "((x::'a::len word) OR NOT (mask n)) AND mask n = x AND mask n" by (metis word_and_not word_ao_dist2 word_bw_comms(1) word_log_esimps(3)) lemma mask_subsume: "\n \ m\ \ ((x::'a::len word) OR y AND mask n) AND NOT (mask m) = x AND NOT (mask m)" by (rule bit_word_eqI) (auto simp add: bit_simps word_size) lemma and_mask_0_iff_le_mask: fixes w :: "'a::len word" shows "(w AND NOT(mask n) = 0) = (w \ mask n)" by (simp add: mask_eq_0_eq_x le_mask_imp_and_mask and_mask_eq_iff_le_mask) lemma mask_twice2: "n \ m \ ((x::'a::len word) AND mask m) AND mask n = x AND mask n" by (metis mask_twice min_def) lemma uint_2_id: "LENGTH('a) \ 2 \ uint (2::('a::len) word) = 2" by simp lemma div_of_0_id[simp]:"(0::('a::len) word) div n = 0" by (simp add: word_div_def) lemma degenerate_word:"LENGTH('a) = 1 \ (x::('a::len) word) = 0 \ x = 1" by (metis One_nat_def less_irrefl_nat sint_1_cases) lemma div_by_0_word:"(x::('a::len) word) div 0 = 0" by (metis div_0 div_by_0 unat_0 word_arith_nat_defs(6) word_div_1) lemma div_less_dividend_word:"\x \ 0; n \ 1\ \ (x::('a::len) word) div n < x" apply (cases \n = 0\) apply clarsimp apply (simp add:word_neq_0_conv) apply (subst word_arith_nat_div) apply (rule word_of_nat_less) apply (rule div_less_dividend) using unat_eq_zero word_unat_Rep_inject1 apply force apply (simp add:unat_gt_0) done lemma word_less_div: fixes x :: "('a::len) word" and y :: "('a::len) word" shows "x div y = 0 \ y = 0 \ x < y" apply (case_tac "y = 0", clarsimp+) by (metis One_nat_def Suc_le_mono le0 le_div_geq not_less unat_0 unat_div unat_gt_0 word_less_nat_alt zero_less_one) lemma not_degenerate_imp_2_neq_0:"LENGTH('a) > 1 \ (2::('a::len) word) \ 0" by (metis numerals(1) power_not_zero power_zero_numeral) lemma word_overflow:"(x::('a::len) word) + 1 > x \ x + 1 = 0" apply clarsimp by (metis diff_0 eq_diff_eq less_x_plus_1) lemma word_overflow_unat:"unat ((x::('a::len) word) + 1) = unat x + 1 \ x + 1 = 0" by (metis Suc_eq_plus1 add.commute unatSuc) lemma even_word_imp_odd_next:"even (unat (x::('a::len) word)) \ x + 1 = 0 \ odd (unat (x + 1))" apply (cut_tac x=x in word_overflow_unat) apply clarsimp done lemma odd_word_imp_even_next:"odd (unat (x::('a::len) word)) \ x + 1 = 0 \ even (unat (x + 1))" apply (cut_tac x=x in word_overflow_unat) apply clarsimp done lemma overflow_imp_lsb:"(x::('a::len) word) + 1 = 0 \ bit x 0" using even_plus_one_iff [of x] by simp lemma odd_iff_lsb:"odd (unat (x::('a::len) word)) = bit x 0" by transfer (simp add: even_nat_iff) lemma of_nat_neq_iff_word: "x mod 2 ^ LENGTH('a) \ y mod 2 ^ LENGTH('a) \ (((of_nat x)::('a::len) word) \ of_nat y) = (x \ y)" apply (rule iffI) apply (case_tac "x = y") apply (subst (asm) of_nat_eq_iff[symmetric]) apply auto apply (case_tac "((of_nat x)::('a::len) word) = of_nat y") apply auto apply (metis unat_of_nat) done lemma lsb_this_or_next: "\ (bit ((x::('a::len) word) + 1) 0) \ bit x 0" by simp lemma mask_or_not_mask: "x AND mask n OR x AND NOT (mask n) = x" for x :: \'a::len word\ apply (subst word_oa_dist, simp) apply (subst word_oa_dist2, simp) done lemma word_gr0_conv_Suc: "(m::'a::len word) > 0 \ \n. m = n + 1" by (metis add.commute add_minus_cancel) lemma revcast_down_us [OF refl]: "rc = revcast \ source_size rc = target_size rc + n \ rc w = ucast (signed_drop_bit n w)" for w :: "'a::len word" apply (simp add: source_size_def target_size_def) apply (rule bit_word_eqI) apply (simp add: bit_simps ac_simps) done lemma revcast_down_ss [OF refl]: "rc = revcast \ source_size rc = target_size rc + n \ rc w = scast (signed_drop_bit n w)" for w :: "'a::len word" apply (simp add: source_size_def target_size_def) apply (rule bit_word_eqI) apply (simp add: bit_simps ac_simps) done lemma revcast_down_uu [OF refl]: "rc = revcast \ source_size rc = target_size rc + n \ rc w = ucast (drop_bit n w)" for w :: "'a::len word" apply (simp add: source_size_def target_size_def) apply (rule bit_word_eqI) apply (simp add: bit_simps ac_simps) done lemma revcast_down_su [OF refl]: "rc = revcast \ source_size rc = target_size rc + n \ rc w = scast (drop_bit n w)" for w :: "'a::len word" apply (simp add: source_size_def target_size_def) apply (rule bit_word_eqI) apply (simp add: bit_simps ac_simps) done lemma cast_down_rev [OF refl]: "uc = ucast \ source_size uc = target_size uc + n \ uc w = revcast (push_bit n w)" for w :: "'a::len word" apply (simp add: source_size_def target_size_def) apply (rule bit_word_eqI) apply (simp add: bit_simps) done lemma revcast_up [OF refl]: "rc = revcast \ source_size rc + n = target_size rc \ rc w = push_bit n (ucast w :: 'a::len word)" apply (simp add: source_size_def target_size_def) apply (rule bit_word_eqI) apply (simp add: bit_simps) apply auto apply (metis add.commute add_diff_cancel_right) apply (metis diff_add_inverse2 diff_diff_add) done lemmas rc1 = revcast_up [THEN revcast_rev_ucast [symmetric, THEN trans, THEN word_rev_gal, symmetric]] lemmas rc2 = revcast_down_uu [THEN revcast_rev_ucast [symmetric, THEN trans, THEN word_rev_gal, symmetric]] lemma word_ops_nth: fixes x y :: \'a::len word\ shows word_or_nth: "bit (x OR y) n = (bit x n \ bit y n)" and word_and_nth: "bit (x AND y) n = (bit x n \ bit y n)" and word_xor_nth: "bit (x XOR y) n = (bit x n \ bit y n)" by (simp_all add: bit_simps) lemma word_power_nonzero: "\ (x :: 'a::len word) < 2 ^ (LENGTH('a) - n); n < LENGTH('a); x \ 0 \ \ x * 2 ^ n \ 0" by (metis gr_implies_not0 mult_eq_0_iff nat_mult_power_less_eq numeral_2_eq_2 p2_gt_0 unat_eq_zero unat_less_power unat_mult_lem unat_power_lower word_gt_a_gt_0 zero_less_Suc) lemma less_1_helper: "n \ m \ (n - 1 :: int) < m" by arith lemma div_power_helper: "\ x \ y; y < LENGTH('a) \ \ (2 ^ y - 1) div (2 ^ x :: 'a::len word) = 2 ^ (y - x) - 1" apply (simp flip: mask_eq_exp_minus_1 drop_bit_eq_div) apply (rule bit_word_eqI) apply (auto simp add: bit_simps not_le) done lemma max_word_mask: "(- 1 :: 'a::len word) = mask LENGTH('a)" by (fact minus_1_eq_mask) lemmas mask_len_max = max_word_mask[symmetric] lemma mask_out_first_mask_some: "\ x AND NOT (mask n) = y; n \ m \ \ x AND NOT (mask m) = y AND NOT (mask m)" for x y :: \'a::len word\ by (rule bit_word_eqI) (auto simp add: bit_simps word_size) lemma mask_lower_twice: "n \ m \ (x AND NOT (mask n)) AND NOT (mask m) = x AND NOT (mask m)" for x :: \'a::len word\ by (rule bit_word_eqI) (auto simp add: bit_simps word_size) lemma mask_lower_twice2: "(a AND NOT (mask n)) AND NOT (mask m) = a AND NOT (mask (max n m))" for a :: \'a::len word\ by (rule bit_word_eqI) (auto simp add: bit_simps) lemma ucast_and_neg_mask: "ucast (x AND NOT (mask n)) = ucast x AND NOT (mask n)" apply (rule bit_word_eqI) apply (auto simp add: bit_simps dest: bit_imp_le_length) done lemma ucast_and_mask: "ucast (x AND mask n) = ucast x AND mask n" apply (rule bit_word_eqI) apply (auto simp add: bit_simps dest: bit_imp_le_length) done lemma ucast_mask_drop: "LENGTH('a :: len) \ n \ (ucast (x AND mask n) :: 'a word) = ucast x" apply (rule bit_word_eqI) apply (auto simp add: bit_simps dest: bit_imp_le_length) done lemma mask_exceed: "n \ LENGTH('a) \ (x::'a::len word) AND NOT (mask n) = 0" by (rule bit_word_eqI) (simp add: bit_simps) lemma word_add_no_overflow:"(x::'a::len word) < - 1 \ x < x + 1" using less_x_plus_1 order_less_le by blast lemma lt_plus_1_le_word: fixes x :: "'a::len word" assumes bound:"n < unat (maxBound::'a word)" shows "x < 1 + of_nat n = (x \ of_nat n)" by (metis add.commute bound max_word_max word_Suc_leq word_not_le word_of_nat_less) lemma unat_ucast_up_simp: fixes x :: "'a::len word" assumes "LENGTH('a) \ LENGTH('b)" shows "unat (ucast x :: 'b::len word) = unat x" apply (rule bit_eqI) using assms apply (auto simp add: bit_simps dest: bit_imp_le_length) done lemma unat_ucast_less_no_overflow: "\n < 2 ^ LENGTH('a); unat f < n\ \ (f::('a::len) word) < of_nat n" by (erule (1) order_le_less_trans[OF _ of_nat_mono_maybe,rotated]) simp lemma unat_ucast_less_no_overflow_simp: "n < 2 ^ LENGTH('a) \ (unat f < n) = ((f::('a::len) word) < of_nat n)" using unat_less_helper unat_ucast_less_no_overflow by blast lemma unat_ucast_no_overflow_le: assumes no_overflow: "unat b < (2 :: nat) ^ LENGTH('a)" and upward_cast: "LENGTH('a) < LENGTH('b)" shows "(ucast (f::'a::len word) < (b :: 'b :: len word)) = (unat f < unat b)" proof - have LR: "ucast f < b \ unat f < unat b" apply (rule unat_less_helper) apply (simp add:ucast_nat_def) apply (rule_tac 'b1 = 'b in ucast_less_ucast[OF order.strict_implies_order, THEN iffD1]) apply (rule upward_cast) apply (simp add: ucast_ucast_mask less_mask_eq word_less_nat_alt unat_power_lower[OF upward_cast] no_overflow) done have RL: "unat f < unat b \ ucast f < b" proof- assume ineq: "unat f < unat b" have "ucast (f::'a::len word) < ((ucast (ucast b ::'a::len word)) :: 'b :: len word)" apply (simp add: ucast_less_ucast[OF order.strict_implies_order] upward_cast) apply (simp only: flip: ucast_nat_def) apply (rule unat_ucast_less_no_overflow[OF no_overflow ineq]) done then show ?thesis apply (rule order_less_le_trans) apply (simp add:ucast_ucast_mask word_and_le2) done qed then show ?thesis by (simp add:RL LR iffI) qed lemmas ucast_up_mono = ucast_less_ucast[THEN iffD2] lemma minus_one_word: "(-1 :: 'a :: len word) = 2 ^ LENGTH('a) - 1" by simp lemma le_2p_upper_bits: "\ (p::'a::len word) \ 2^n - 1; n < LENGTH('a) \ \ \n'\n. n' < LENGTH('a) \ \ bit p n'" by (subst upper_bits_unset_is_l2p; simp) lemma le2p_bits_unset: "p \ 2 ^ n - 1 \ \n'\n. n' < LENGTH('a) \ \ bit (p::'a::len word) n'" using upper_bits_unset_is_l2p [where p=p] by (cases "n < LENGTH('a)") auto lemma complement_nth_w2p: shows "n' < LENGTH('a) \ bit (NOT (2 ^ n :: 'a::len word)) n' = (n' \ n)" by (fastforce simp: word_ops_nth_size word_size nth_w2p) lemma word_unat_and_lt: "unat x < n \ unat y < n \ unat (x AND y) < n" by (meson le_less_trans word_and_le1 word_and_le2 word_le_nat_alt) lemma word_unat_mask_lt: "m \ size w \ unat ((w::'a::len word) AND mask m) < 2 ^ m" by (rule word_unat_and_lt) (simp add: unat_mask word_size) lemma word_sless_sint_le:"x sint x \ sint y - 1" by (metis word_sless_alt zle_diff1_eq) lemma upper_trivial: fixes x :: "'a::len word" shows "x \ 2 ^ LENGTH('a) - 1 \ x < 2 ^ LENGTH('a) - 1" by (simp add: less_le) lemma constraint_expand: fixes x :: "'a::len word" shows "x \ {y. lower \ y \ y \ upper} = (lower \ x \ x \ upper)" by (rule mem_Collect_eq) lemma card_map_elide: "card ((of_nat :: nat \ 'a::len word) ` {0.. CARD('a::len word)" proof - let ?of_nat = "of_nat :: nat \ 'a word" have "inj_on ?of_nat {i. i < CARD('a word)}" by (rule inj_onI) (simp add: card_word of_nat_inj) moreover have "{0.. {i. i < CARD('a word)}" using that by auto ultimately have "inj_on ?of_nat {0.. CARD('a::len word) \ card ((of_nat::nat \ 'a::len word) ` {0.. LENGTH('a) \ x = ucast y \ ucast x = y" for x :: "'a::len word" and y :: "'b::len word" by transfer simp lemma le_ucast_ucast_le: "x \ ucast y \ ucast x \ y" for x :: "'a::len word" and y :: "'b::len word" by (smt le_unat_uoi linorder_not_less order_less_imp_le ucast_nat_def unat_arith_simps(1)) lemma less_ucast_ucast_less: "LENGTH('b) \ LENGTH('a) \ x < ucast y \ ucast x < y" for x :: "'a::len word" and y :: "'b::len word" by (metis ucast_nat_def unat_mono unat_ucast_up_simp word_of_nat_less) lemma ucast_le_ucast: "LENGTH('a) \ LENGTH('b) \ (ucast x \ (ucast y::'b::len word)) = (x \ y)" for x :: "'a::len word" by (simp add: unat_arith_simps(1) unat_ucast_up_simp) lemmas ucast_up_mono_le = ucast_le_ucast[THEN iffD2] lemma ucast_or_distrib: fixes x :: "'a::len word" fixes y :: "'a::len word" shows "(ucast (x OR y) :: ('b::len) word) = ucast x OR ucast y" by (fact unsigned_or_eq) lemma word_exists_nth: "(w::'a::len word) \ 0 \ \i. bit w i" by (simp add: bit_eq_iff) lemma max_word_not_0 [simp]: "- 1 \ (0 :: 'a::len word)" by simp lemma unat_max_word_pos[simp]: "0 < unat (- 1 :: 'a::len word)" using unat_gt_0 [of \- 1 :: 'a::len word\] by simp (* Miscellaneous conditional injectivity rules. *) lemma mult_pow2_inj: assumes ws: "m + n \ LENGTH('a)" assumes le: "x \ mask m" "y \ mask m" assumes eq: "x * 2 ^ n = y * (2 ^ n::'a::len word)" shows "x = y" proof (rule bit_word_eqI) fix q assume \q < LENGTH('a)\ from eq have \push_bit n x = push_bit n y\ by (simp add: push_bit_eq_mult) moreover from le have \take_bit m x = x\ \take_bit m y = y\ by (simp_all add: less_eq_mask_iff_take_bit_eq_self) ultimately have \push_bit n (take_bit m x) = push_bit n (take_bit m y)\ by simp_all with \q < LENGTH('a)\ ws show \bit x q \ bit y q\ apply (simp add: push_bit_take_bit) unfolding bit_eq_iff apply (simp add: bit_simps not_le) apply (metis (full_types) \take_bit m x = x\ \take_bit m y = y\ add.commute add_diff_cancel_right' add_less_cancel_right bit_take_bit_iff le_add2 less_le_trans) done qed lemma word_of_nat_inj: assumes bounded: "x < 2 ^ LENGTH('a)" "y < 2 ^ LENGTH('a)" assumes of_nats: "of_nat x = (of_nat y :: 'a::len word)" shows "x = y" by (rule contrapos_pp[OF of_nats]; cases "x < y"; cases "y < x") (auto dest: bounded[THEN of_nat_mono_maybe]) lemma word_of_int_bin_cat_eq_iff: "(word_of_int (concat_bit LENGTH('b) (uint b) (uint a))::'c::len word) = word_of_int (concat_bit LENGTH('b) (uint d) (uint c)) \ b = d \ a = c" if "LENGTH('a) + LENGTH('b) \ LENGTH('c)" for a::"'a::len word" and b::"'b::len word" proof - from that show ?thesis using that concat_bit_eq_iff [of \LENGTH('b)\ \uint b\ \uint a\ \uint d\ \uint c\] apply (simp add: word_of_int_eq_iff take_bit_int_eq_self flip: word_eq_iff_unsigned) apply (simp add: concat_bit_def take_bit_int_eq_self bintr_uint take_bit_push_bit) done qed lemma word_cat_inj: "(word_cat a b::'c::len word) = word_cat c d \ a = c \ b = d" if "LENGTH('a) + LENGTH('b) \ LENGTH('c)" for a::"'a::len word" and b::"'b::len word" using word_of_int_bin_cat_eq_iff [OF that, of b a d c] by (simp add: word_cat_eq' ac_simps) lemma p2_eq_1: "2 ^ n = (1::'a::len word) \ n = 0" proof - have "2 ^ n = (1::'a word) \ n = 0" by (metis One_nat_def not_less one_less_numeral_iff p2_eq_0 p2_gt_0 power_0 power_0 power_inject_exp semiring_norm(76) unat_power_lower zero_neq_one) then show ?thesis by auto qed end end diff --git a/thys/Word_Lib/Word_Lemmas.thy b/thys/Word_Lib/Word_Lemmas.thy --- a/thys/Word_Lib/Word_Lemmas.thy +++ b/thys/Word_Lib/Word_Lemmas.thy @@ -1,1940 +1,1940 @@ (* * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause *) section "Lemmas with Generic Word Length" theory Word_Lemmas imports Type_Syntax Signed_Division_Word Signed_Words More_Word Most_significant_bit Enumeration_Word Aligned Bit_Shifts_Infix_Syntax begin context includes bit_operations_syntax begin lemma ucast_le_ucast_eq: fixes x y :: "'a::len word" assumes x: "x < 2 ^ n" assumes y: "y < 2 ^ n" assumes n: "n = LENGTH('b::len)" shows "(UCAST('a \ 'b) x \ UCAST('a \ 'b) y) = (x \ y)" apply (rule iffI) apply (cases "LENGTH('b) < LENGTH('a)") apply (subst less_mask_eq[OF x, symmetric]) apply (subst less_mask_eq[OF y, symmetric]) apply (unfold n) apply (subst ucast_ucast_mask[symmetric])+ apply (simp add: ucast_le_ucast)+ apply (erule ucast_mono_le[OF _ y[unfolded n]]) done lemma ucast_zero_is_aligned: \is_aligned w n\ if \UCAST('a::len \ 'b::len) w = 0\ \n \ LENGTH('b)\ proof (rule is_aligned_bitI) fix q assume \q < n\ moreover have \bit (UCAST('a::len \ 'b::len) w) q = bit 0 q\ using that by simp with \q < n\ \n \ LENGTH('b)\ show \\ bit w q\ by (simp add: bit_simps) qed lemma unat_ucast_eq_unat_and_mask: "unat (UCAST('b::len \ 'a::len) w) = unat (w AND mask LENGTH('a))" apply (simp flip: take_bit_eq_mask) apply transfer apply (simp add: ac_simps) done lemma le_max_word_ucast_id: \UCAST('b \ 'a) (UCAST('a \ 'b) x) = x\ if \x \ UCAST('b::len \ 'a) (- 1)\ for x :: \'a::len word\ proof - from that have a1: \x \ word_of_int (uint (word_of_int (2 ^ LENGTH('b) - 1) :: 'b word))\ by simp have f2: "((\i ia. (0::int) \ i \ \ 0 \ i + - 1 * ia \ i mod ia \ i) \ \ (0::int) \ - 1 + 2 ^ LENGTH('b) \ (0::int) \ - 1 + 2 ^ LENGTH('b) + - 1 * 2 ^ LENGTH('b) \ (- (1::int) + 2 ^ LENGTH('b)) mod 2 ^ LENGTH('b) = - 1 + 2 ^ LENGTH('b)) = ((\i ia. (0::int) \ i \ \ 0 \ i + - 1 * ia \ i mod ia \ i) \ \ (1::int) \ 2 ^ LENGTH('b) \ 2 ^ LENGTH('b) + - (1::int) * ((- 1 + 2 ^ LENGTH('b)) mod 2 ^ LENGTH('b)) = 1)" by force have f3: "\i ia. \ (0::int) \ i \ 0 \ i + - 1 * ia \ i mod ia = i" using mod_pos_pos_trivial by force have "(1::int) \ 2 ^ LENGTH('b)" by simp then have "2 ^ LENGTH('b) + - (1::int) * ((- 1 + 2 ^ LENGTH('b)) mod 2 ^ len_of TYPE ('b)) = 1" using f3 f2 by blast then have f4: "- (1::int) + 2 ^ LENGTH('b) = (- 1 + 2 ^ LENGTH('b)) mod 2 ^ LENGTH('b)" by linarith have f5: "x \ word_of_int (uint (word_of_int (- 1 + 2 ^ LENGTH('b))::'b word))" using a1 by force have f6: "2 ^ LENGTH('b) + - (1::int) = - 1 + 2 ^ LENGTH('b)" by force have f7: "- (1::int) * 1 = - 1" by auto have "\x0 x1. (x1::int) - x0 = x1 + - 1 * x0" by force then have "x \ 2 ^ LENGTH('b) - 1" using f7 f6 f5 f4 by (metis uint_word_of_int wi_homs(2) word_arith_wis(8) word_of_int_2p) then have \uint x \ uint (2 ^ LENGTH('b) - (1 :: 'a word))\ by (simp add: word_le_def) then have \uint x \ 2 ^ LENGTH('b) - 1\ by (simp add: uint_word_ariths) (metis \1 \ 2 ^ LENGTH('b)\ \uint x \ uint (2 ^ LENGTH('b) - 1)\ linorder_not_less lt2p_lem uint_1 uint_minus_simple_alt uint_power_lower word_le_def zle_diff1_eq) then show ?thesis apply (simp add: unsigned_ucast_eq take_bit_word_eq_self_iff) apply (meson \x \ 2 ^ LENGTH('b) - 1\ not_le word_less_sub_le) done qed lemma uint_shiftr_eq: \uint (w >> n) = uint w div 2 ^ n\ by transfer (simp flip: drop_bit_eq_div add: drop_bit_take_bit min_def le_less less_diff_conv) lemma bit_shiftl_word_iff [bit_simps]: \bit (w << m) n \ m \ n \ n < LENGTH('a) \ bit w (n - m)\ for w :: \'a::len word\ by (simp add: bit_push_bit_iff not_le) lemma shiftl_def: \w << n = ((*) 2 ^^ n) w\ for w :: \'a::len word\ proof - have \push_bit n = (((*) 2 ^^ n) :: int \ int)\ for n by (induction n) (simp_all add: fun_eq_iff funpow_swap1, simp add: ac_simps) then show ?thesis by transfer simp qed lemma shiftr_def: \w >> n = ((\w. w div 2) ^^ n) w\ for w :: \'a::len word\ proof - have \(\w. w div 2) ^^ n = (drop_bit n :: 'a word \ 'a word)\ by (induction n) (simp_all add: drop_bit_half drop_bit_Suc) then show ?thesis by simp qed lemma bit_shiftr_word_iff: \bit (w >> m) n \ bit w (m + n)\ for w :: \'a::len word\ by (simp add: bit_simps) lemma sshiftr_eq_funpow_sshiftr1: \w >>> n = (signed_drop_bit (Suc 0) ^^ n) w\ apply (rule sym) apply (induction n) apply simp_all done lemma uint_sshiftr_eq: \uint (w >>> n) = take_bit LENGTH('a) (sint w div 2 ^ n)\ for w :: \'a::len word\ by transfer (simp flip: drop_bit_eq_div) lemma sshiftr_0: "0 >>> n = 0" by (fact signed_drop_bit_of_0) lemma sshiftr_n1: "-1 >>> n = -1" by (fact signed_drop_bit_of_minus_1) lemma bit_sshiftr_word_iff: \bit (w >>> m) n \ bit w (if LENGTH('a) - m \ n \ n < LENGTH('a) then LENGTH('a) - 1 else (m + n))\ for w :: \'a::len word\ by (fact bit_signed_drop_bit_iff) lemma nth_sshiftr : "bit (w >>> m) n = (n < size w \ (if n + m \ size w then bit w (size w - 1) else bit w (n + m)))" apply (auto simp add: bit_simps word_size ac_simps not_less) apply (meson bit_imp_le_length bit_shiftr_word_iff leD) done lemma sshiftr_numeral: \(numeral k >>> numeral n :: 'a::len word) = word_of_int (drop_bit (numeral n) (signed_take_bit (LENGTH('a) - 1) (numeral k)))\ by (fact signed_drop_bit_word_numeral) lemma sshiftr_div_2n: "sint (w >>> n) = sint w div 2 ^ n" using sint_signed_drop_bit_eq [of n w] by (simp add: drop_bit_eq_div) lemma mask_eq: \mask n = (1 << n) - (1 :: 'a::len word)\ by (simp add: mask_eq_exp_minus_1 push_bit_of_1) lemma shiftl_0: "(0::'a::len word) << n = 0" by (fact push_bit_of_0) lemma shiftr_0: "(0::'a::len word) >> n = 0" by (fact drop_bit_of_0) lemma nth_shiftl': "bit (w << m) n \ n < size w \ n >= m \ bit w (n - m)" for w :: "'a::len word" by transfer (auto simp add: bit_push_bit_iff) lemmas nth_shiftl = nth_shiftl' [unfolded word_size] lemma nth_shiftr: "bit (w >> m) n = bit w (n + m)" for w :: "'a::len word" by (simp add: bit_simps ac_simps) lemma shiftr_div_2n: "uint (shiftr w n) = uint w div 2 ^ n" by (fact uint_shiftr_eq) lemma shiftl_rev: "shiftl w n = word_reverse (shiftr (word_reverse w) n)" by (rule bit_word_eqI) (auto simp add: bit_simps) lemma rev_shiftl: "word_reverse w << n = word_reverse (w >> n)" by (simp add: shiftl_rev) lemma shiftr_rev: "w >> n = word_reverse (word_reverse w << n)" by (simp add: rev_shiftl) lemma rev_shiftr: "word_reverse w >> n = word_reverse (w << n)" by (simp add: shiftr_rev) lemmas ucast_up = rc1 [simplified rev_shiftr [symmetric] revcast_ucast [symmetric]] lemmas ucast_down = rc2 [simplified rev_shiftr revcast_ucast [symmetric]] lemma shiftl_zero_size: "size x \ n \ x << n = 0" for x :: "'a::len word" apply transfer apply (simp add: take_bit_push_bit) done lemma shiftl_t2n: "shiftl w n = 2 ^ n * w" for w :: "'a::len word" by (simp add: push_bit_eq_mult) lemma word_shift_by_2: "x * 4 = (x::'a::len word) << 2" by (simp add: shiftl_t2n) lemma slice_shiftr: "slice n w = ucast (w >> n)" apply (rule bit_word_eqI) apply (cases \n \ LENGTH('b)\) apply (auto simp add: bit_slice_iff bit_ucast_iff bit_shiftr_word_iff ac_simps dest: bit_imp_le_length) done lemma shiftr_zero_size: "size x \ n \ x >> n = 0" for x :: "'a :: len word" by (rule word_eqI) (auto simp add: nth_shiftr dest: test_bit_size) lemma shiftr_x_0: "x >> 0 = x" for x :: "'a::len word" by simp lemma shiftl_x_0: "x << 0 = x" for x :: "'a::len word" by simp lemma shiftl_1: "(1::'a::len word) << n = 2^n" by (fact push_bit_of_1) lemma shiftr_1: "(1::'a::len word) >> n = (if n = 0 then 1 else 0)" by simp lemma shiftl0: "x << 0 = (x :: 'a :: len word)" by (fact shiftl_x_0) lemma and_not_mask: "w AND NOT (mask n) = (w >> n) << n" for w :: \'a::len word\ by (rule bit_word_eqI) (auto simp add: bit_simps) lemma and_mask: "w AND mask n = (w << (size w - n)) >> (size w - n)" for w :: \'a::len word\ by (rule bit_word_eqI) (auto simp add: bit_simps word_size) lemma shiftr_div_2n_w: "n < size w \ w >> n = w div (2^n :: 'a :: len word)" apply (unfold word_div_def) apply (simp add: uint_2p_alt word_size) apply (metis uint_shiftr_eq word_of_int_uint) done lemma le_shiftr: "u \ v \ u >> (n :: nat) \ (v :: 'a :: len word) >> n" apply transfer apply (simp add: take_bit_drop_bit) apply (simp add: drop_bit_eq_div zdiv_mono1) done lemma le_shiftr': "\ u >> n \ v >> n ; u >> n \ v >> n \ \ (u::'a::len word) \ v" apply (metis le_cases le_shiftr verit_la_disequality) done lemma shiftr_mask_le: "n <= m \ mask n >> m = (0 :: 'a::len word)" by (rule bit_word_eqI) (auto simp add: bit_simps) lemma shiftr_mask [simp]: \mask m >> m = (0::'a::len word)\ by (rule shiftr_mask_le) simp lemma le_mask_iff: "(w \ mask n) = (w >> n = 0)" for w :: \'a::len word\ apply safe apply (rule word_le_0_iff [THEN iffD1]) apply (rule xtrans(3)) apply (erule_tac [2] le_shiftr) apply simp apply (rule word_leI) apply (rename_tac n') apply (drule_tac x = "n' - n" in word_eqD) apply (simp add : nth_shiftr word_size bit_simps) apply (case_tac "n <= n'") by auto lemma and_mask_eq_iff_shiftr_0: "(w AND mask n = w) = (w >> n = 0)" for w :: \'a::len word\ apply (unfold test_bit_eq_iff [THEN sym]) apply (rule iffI) apply (rule ext) apply (rule_tac [2] ext) apply (auto simp add : word_ao_nth nth_shiftr) apply (drule arg_cong) apply (drule iffD2) apply assumption apply (simp add : word_ao_nth) prefer 2 apply (simp add : word_size test_bit_bin) apply transfer apply (auto simp add: fun_eq_iff bit_simps) apply (metis add_diff_inverse_nat) done lemma mask_shiftl_decompose: "mask m << n = mask (m + n) AND NOT (mask n :: 'a::len word)" by (rule bit_word_eqI) (auto simp add: bit_simps) lemma shiftl_over_and_dist: fixes a::"'a::len word" shows "(a AND b) << c = (a << c) AND (b << c)" by (fact push_bit_and) lemma shiftr_over_and_dist: fixes a::"'a::len word" shows "a AND b >> c = (a >> c) AND (b >> c)" by (fact drop_bit_and) lemma sshiftr_over_and_dist: fixes a::"'a::len word" shows "a AND b >>> c = (a >>> c) AND (b >>> c)" apply(rule word_eqI) apply(simp add:nth_sshiftr word_ao_nth word_size) done lemma shiftl_over_or_dist: fixes a::"'a::len word" shows "a OR b << c = (a << c) OR (b << c)" by (fact push_bit_or) lemma shiftr_over_or_dist: fixes a::"'a::len word" shows "a OR b >> c = (a >> c) OR (b >> c)" by (fact drop_bit_or) lemma sshiftr_over_or_dist: fixes a::"'a::len word" shows "a OR b >>> c = (a >>> c) OR (b >>> c)" apply(rule word_eqI) apply(simp add:nth_sshiftr word_ao_nth word_size) done lemmas shift_over_ao_dists = shiftl_over_or_dist shiftr_over_or_dist sshiftr_over_or_dist shiftl_over_and_dist shiftr_over_and_dist sshiftr_over_and_dist lemma shiftl_shiftl: fixes a::"'a::len word" shows "a << b << c = a << (b + c)" apply(rule word_eqI) apply(auto simp:word_size nth_shiftl add.commute add.left_commute) done lemma shiftr_shiftr: fixes a::"'a::len word" shows "a >> b >> c = a >> (b + c)" apply(rule word_eqI) apply(simp add:word_size nth_shiftr add.left_commute add.commute) done lemma shiftl_shiftr1: fixes a::"'a::len word" shows "c \ b \ a << b >> c = a AND (mask (size a - b)) << (b - c)" apply (rule word_eqI) apply (auto simp add: bit_simps not_le word_size ac_simps) done lemma shiftl_shiftr2: fixes a::"'a::len word" shows "b < c \ a << b >> c = (a >> (c - b)) AND (mask (size a - c))" apply(rule word_eqI) apply(auto simp:nth_shiftr nth_shiftl word_size word_ao_nth bit_simps) done lemma shiftr_shiftl1: fixes a::"'a::len word" shows "c \ b \ a >> b << c = (a >> (b - c)) AND (NOT (mask c))" by (rule bit_word_eqI) (auto simp add: bit_simps) lemma shiftr_shiftl2: fixes a::"'a::len word" shows "b < c \ a >> b << c = (a << (c - b)) AND (NOT (mask c))" apply (rule word_eqI) apply (auto simp add: bit_simps not_le word_size ac_simps) done lemmas multi_shift_simps = shiftl_shiftl shiftr_shiftr shiftl_shiftr1 shiftl_shiftr2 shiftr_shiftl1 shiftr_shiftl2 lemma shiftr_mask2: "n \ LENGTH('a) \ (mask n >> m :: ('a :: len) word) = mask (n - m)" by (rule bit_word_eqI) (auto simp add: bit_simps) lemma word_shiftl_add_distrib: fixes x :: "'a :: len word" shows "(x + y) << n = (x << n) + (y << n)" by (simp add: shiftl_t2n ring_distribs) lemma mask_shift: "(x AND NOT (mask y)) >> y = x >> y" for x :: \'a::len word\ apply (rule bit_eqI) apply (simp add: bit_and_iff bit_not_iff bit_shiftr_word_iff bit_mask_iff not_le) using bit_imp_le_length apply auto done lemma shiftr_div_2n': "unat (w >> n) = unat w div 2 ^ n" apply (unfold unat_eq_nat_uint) apply (subst shiftr_div_2n) apply (subst nat_div_distrib) apply simp apply (simp add: nat_power_eq) done lemma shiftl_shiftr_id: assumes nv: "n < LENGTH('a)" and xv: "x < 2 ^ (LENGTH('a) - n)" shows "x << n >> n = (x::'a::len word)" apply (simp add: shiftl_t2n) apply (rule word_eq_unatI) apply (subst shiftr_div_2n') apply (cases n) apply simp apply (subst iffD1 [OF unat_mult_lem])+ apply (subst unat_power_lower[OF nv]) apply (rule nat_less_power_trans [OF _ order_less_imp_le [OF nv]]) apply (rule order_less_le_trans [OF unat_mono [OF xv] order_eq_refl]) apply (rule unat_power_lower) apply simp apply (subst unat_power_lower[OF nv]) apply simp done lemma ucast_shiftl_eq_0: fixes w :: "'a :: len word" shows "\ n \ LENGTH('b) \ \ ucast (w << n) = (0 :: 'b :: len word)" by transfer (simp add: take_bit_push_bit) lemma word_shift_nonzero: "\ (x::'a::len word) \ 2 ^ m; m + n < LENGTH('a::len); x \ 0\ \ x << n \ 0" apply (simp only: word_neq_0_conv word_less_nat_alt shiftl_t2n mod_0 unat_word_ariths unat_power_lower word_le_nat_alt) apply (subst mod_less) apply (rule order_le_less_trans) apply (erule mult_le_mono2) apply (subst power_add[symmetric]) apply (rule power_strict_increasing) apply simp apply simp apply simp done lemma word_shiftr_lt: fixes w :: "'a::len word" shows "unat (w >> n) < (2 ^ (LENGTH('a) - n))" apply (subst shiftr_div_2n') apply transfer apply (simp flip: drop_bit_eq_div add: drop_bit_nat_eq drop_bit_take_bit) done lemma shiftr_less_t2n': "\ x AND mask (n + m) = x; m < LENGTH('a) \ \ x >> n < 2 ^ m" for x :: "'a :: len word" apply (simp add: word_size mask_eq_iff_w2p [symmetric] flip: take_bit_eq_mask) apply transfer apply (simp add: take_bit_drop_bit ac_simps) done lemma shiftr_less_t2n: "x < 2 ^ (n + m) \ x >> n < 2 ^ m" for x :: "'a :: len word" apply (rule shiftr_less_t2n') apply (erule less_mask_eq) apply (rule ccontr) apply (simp add: not_less) apply (subst (asm) p2_eq_0[symmetric]) apply (simp add: power_add) done lemma shiftr_eq_0: "n \ LENGTH('a) \ ((w::'a::len word) >> n) = 0" apply (cut_tac shiftr_less_t2n'[of w n 0], simp) apply (simp add: mask_eq_iff) apply (simp add: lt2p_lem) apply simp done lemma shiftl_less_t2n: fixes x :: "'a :: len word" shows "\ x < (2 ^ (m - n)); m < LENGTH('a) \ \ (x << n) < 2 ^ m" apply (simp add: word_size mask_eq_iff_w2p [symmetric] flip: take_bit_eq_mask) apply transfer apply (simp add: take_bit_push_bit) done lemma shiftl_less_t2n': "(x::'a::len word) < 2 ^ m \ m+n < LENGTH('a) \ x << n < 2 ^ (m + n)" by (rule shiftl_less_t2n) simp_all lemma scast_bit_test [simp]: "scast ((1 :: 'a::len signed word) << n) = (1 :: 'a word) << n" by (rule bit_word_eqI) (simp add: bit_simps) lemma signed_shift_guard_to_word: \unat x * 2 ^ y < 2 ^ n \ x = 0 \ x < 1 << n >> y\ if \n < LENGTH('a)\ \0 < n\ for x :: \'a::len word\ proof (cases \x = 0\) case True then show ?thesis by simp next case False then have \unat x \ 0\ by (simp add: unat_eq_0) then have \unat x \ 1\ by simp show ?thesis proof (cases \y < n\) case False then have \n \ y\ by simp then obtain q where \y = n + q\ using le_Suc_ex by blast moreover have \(2 :: nat) ^ n >> n + q \ 1\ by (simp add: drop_bit_eq_div power_add) ultimately show ?thesis using \x \ 0\ \unat x \ 1\ \n < LENGTH('a)\ by (simp add: power_add not_less word_le_nat_alt unat_drop_bit_eq push_bit_of_1) next case True with that have \y < LENGTH('a)\ by simp show ?thesis proof (cases \2 ^ n = unat x * 2 ^ y\) case True moreover have \unat x * 2 ^ y < 2 ^ LENGTH('a)\ using \n < LENGTH('a)\ by (simp flip: True) moreover have \(word_of_nat (2 ^ n) :: 'a word) = word_of_nat (unat x * 2 ^ y)\ using True by simp then have \2 ^ n = x * 2 ^ y\ by simp ultimately show ?thesis using \y < LENGTH('a)\ by (auto simp add: push_bit_of_1 drop_bit_eq_div word_less_nat_alt unat_div unat_word_ariths) next case False with \y < n\ have *: \unat x \ 2 ^ n div 2 ^ y\ by (auto simp flip: power_sub power_add) have \unat x * 2 ^ y < 2 ^ n \ unat x * 2 ^ y \ 2 ^ n\ using False by (simp add: less_le) also have \\ \ unat x \ 2 ^ n div 2 ^ y\ by (simp add: less_eq_div_iff_mult_less_eq) also have \\ \ unat x < 2 ^ n div 2 ^ y\ using * by (simp add: less_le) finally show ?thesis using that \x \ 0\ by (simp flip: push_bit_eq_mult drop_bit_eq_div add: push_bit_of_1 unat_drop_bit_eq word_less_iff_unsigned [where ?'a = nat]) qed qed qed lemma shiftr_not_mask_0: "n+m \ LENGTH('a :: len) \ ((w::'a::len word) >> n) AND NOT (mask m) = 0" by (rule bit_word_eqI) (auto simp add: bit_simps word_size dest: bit_imp_le_length) lemma shiftl_mask_is_0[simp]: "(x << n) AND mask n = 0" for x :: \'a::len word\ by (simp flip: take_bit_eq_mask add: take_bit_push_bit) lemma rshift_sub_mask_eq: "(a >> (size a - b)) AND mask b = a >> (size a - b)" for a :: \'a::len word\ using shiftl_shiftr2[where a=a and b=0 and c="size a - b"] apply (cases "b < size a") apply simp apply (simp add: linorder_not_less mask_eq_decr_exp word_size p2_eq_0[THEN iffD2]) done lemma shiftl_shiftr3: "b \ c \ a << b >> c = (a >> c - b) AND mask (size a - c)" for a :: \'a::len word\ apply (cases "b = c") apply (simp add: shiftl_shiftr1) apply (simp add: shiftl_shiftr2) done lemma and_mask_shiftr_comm: "m \ size w \ (w AND mask m) >> n = (w >> n) AND mask (m-n)" for w :: \'a::len word\ by (simp add: and_mask shiftr_shiftr) (simp add: word_size shiftl_shiftr3) lemma and_mask_shiftl_comm: "m+n \ size w \ (w AND mask m) << n = (w << n) AND mask (m+n)" for w :: \'a::len word\ by (simp add: and_mask word_size shiftl_shiftl) (simp add: shiftl_shiftr1) lemma le_mask_shiftl_le_mask: "s = m + n \ x \ mask n \ x << m \ mask s" for x :: \'a::len word\ by (simp add: le_mask_iff shiftl_shiftr3) lemma word_and_1_shiftl: "x AND (1 << n) = (if bit x n then (1 << n) else 0)" for x :: "'a :: len word" apply (rule bit_word_eqI; transfer) apply (auto simp add: bit_simps not_le ac_simps) done lemmas word_and_1_shiftls' = word_and_1_shiftl[where n=0] word_and_1_shiftl[where n=1] word_and_1_shiftl[where n=2] lemmas word_and_1_shiftls = word_and_1_shiftls' [simplified] lemma word_and_mask_shiftl: "x AND (mask n << m) = ((x >> m) AND mask n) << m" for x :: \'a::len word\ apply (rule bit_word_eqI; transfer) apply (auto simp add: bit_simps not_le ac_simps) done lemma shift_times_fold: "(x :: 'a :: len word) * (2 ^ n) << m = x << (m + n)" by (simp add: shiftl_t2n ac_simps power_add) lemma of_bool_nth: "of_bool (bit x v) = (x >> v) AND 1" for x :: \'a::len word\ by (simp add: bit_iff_odd_drop_bit word_and_1) lemma shiftr_mask_eq: "(x >> n) AND mask (size x - n) = x >> n" for x :: "'a :: len word" apply (simp flip: take_bit_eq_mask) apply transfer apply (simp add: take_bit_drop_bit) done lemma shiftr_mask_eq': "m = (size x - n) \ (x >> n) AND mask m = x >> n" for x :: "'a :: len word" by (simp add: shiftr_mask_eq) lemma and_eq_0_is_nth: fixes x :: "'a :: len word" shows "y = 1 << n \ ((x AND y) = 0) = (\ (bit x n))" by (simp add: and_exp_eq_0_iff_not_bit push_bit_of_1) lemma word_shift_zero: "\ x << n = 0; x \ 2^m; m + n < LENGTH('a)\ \ (x::'a::len word) = 0" apply (rule ccontr) apply (drule (2) word_shift_nonzero) apply simp done lemma mask_shift_and_negate[simp]:"(w AND mask n << m) AND NOT (mask n << m) = 0" for w :: \'a::len word\ - by (clarsimp simp add: mask_eq_decr_exp Parity.bit_eq_iff bit_and_iff bit_not_iff bit_push_bit_iff) + by (rule bit_word_eqI) (simp add: bit_simps) (* The seL4 bitfield generator produces functions containing mask and shift operations, such that * invoking two of them consecutively can produce something like the following. *) lemma bitfield_op_twice: "(x AND NOT (mask n << m) OR ((y AND mask n) << m)) AND NOT (mask n << m) = x AND NOT (mask n << m)" for x :: \'a::len word\ by (induct n arbitrary: m) (auto simp: word_ao_dist) lemma bitfield_op_twice'': "\NOT a = b << c; \x. b = mask x\ \ (x AND a OR (y AND b << c)) AND a = x AND a" for a b :: \'a::len word\ apply clarsimp apply (cut_tac n=xa and m=c and x=x and y=y in bitfield_op_twice) apply (clarsimp simp:mask_eq_decr_exp) apply (drule not_switch) apply clarsimp done lemma shiftr1_unfold: "x div 2 = x >> 1" by (simp add: drop_bit_eq_div) lemma shiftr1_is_div_2: "(x::('a::len) word) >> 1 = x div 2" by (simp add: drop_bit_eq_div) lemma shiftl1_is_mult: "(x << 1) = (x :: 'a::len word) * 2" by (metis One_nat_def mult_2 mult_2_right one_add_one power_0 power_Suc shiftl_t2n) lemma shiftr1_lt:"x \ 0 \ (x::('a::len) word) >> 1 < x" apply (subst shiftr1_is_div_2) apply (rule div_less_dividend_word) apply simp+ done lemma shiftr1_0_or_1:"(x::('a::len) word) >> 1 = 0 \ x = 0 \ x = 1" apply (subst (asm) shiftr1_is_div_2) apply (drule word_less_div) apply (case_tac "LENGTH('a) = 1") apply (simp add:degenerate_word) apply (erule disjE) apply (subgoal_tac "(2::'a word) \ 0") apply simp apply (rule not_degenerate_imp_2_neq_0) apply (subgoal_tac "LENGTH('a) \ 0") apply arith apply simp apply (rule x_less_2_0_1', simp+) done lemma shiftr1_irrelevant_lsb: "bit (x::('a::len) word) 0 \ x >> 1 = (x + 1) >> 1" apply (cases \LENGTH('a)\; transfer) apply (simp_all add: take_bit_drop_bit) apply (simp add: drop_bit_take_bit drop_bit_Suc) done lemma shiftr1_0_imp_only_lsb:"((x::('a::len) word) + 1) >> 1 = 0 \ x = 0 \ x + 1 = 0" by (metis One_nat_def shiftr1_0_or_1 word_less_1 word_overflow) lemma shiftr1_irrelevant_lsb': "\ (bit (x::('a::len) word) 0) \ x >> 1 = (x + 1) >> 1" by (metis shiftr1_irrelevant_lsb) (* Perhaps this one should be a simp lemma, but it seems a little dangerous. *) lemma cast_chunk_assemble_id: "\n = LENGTH('a::len); m = LENGTH('b::len); n * 2 = m\ \ (((ucast ((ucast (x::'b word))::'a word))::'b word) OR (((ucast ((ucast (x >> n))::'a word))::'b word) << n)) = x" apply (subgoal_tac "((ucast ((ucast (x >> n))::'a word))::'b word) = x >> n") apply clarsimp apply (subst and_not_mask[symmetric]) apply (subst ucast_ucast_mask) apply (subst word_ao_dist2[symmetric]) apply clarsimp apply (rule ucast_ucast_len) apply (rule shiftr_less_t2n') apply (subst and_mask_eq_iff_le_mask) apply (simp_all add: mask_eq_decr_exp flip: mult_2_right) apply (metis add_diff_cancel_left' len_gt_0 mult_2_right zero_less_diff) done lemma cast_chunk_scast_assemble_id: "\n = LENGTH('a::len); m = LENGTH('b::len); n * 2 = m\ \ (((ucast ((scast (x::'b word))::'a word))::'b word) OR (((ucast ((scast (x >> n))::'a word))::'b word) << n)) = x" apply (subgoal_tac "((scast x)::'a word) = ((ucast x)::'a word)") apply (subgoal_tac "((scast (x >> n))::'a word) = ((ucast (x >> n))::'a word)") apply (simp add:cast_chunk_assemble_id) apply (subst down_cast_same[symmetric], subst is_down, arith, simp)+ done lemma unat_shiftr_less_t2n: fixes x :: "'a :: len word" shows "unat x < 2 ^ (n + m) \ unat (x >> n) < 2 ^ m" by (simp add: shiftr_div_2n' power_add mult.commute less_mult_imp_div_less) lemma ucast_less_shiftl_helper: "\ LENGTH('b) + 2 < LENGTH('a); 2 ^ (LENGTH('b) + 2) \ n\ \ (ucast (x :: 'b::len word) << 2) < (n :: 'a::len word)" apply (erule order_less_le_trans[rotated]) using ucast_less[where x=x and 'a='a] apply (simp only: shiftl_t2n field_simps) apply (rule word_less_power_trans2; simp) done (* negating a mask which has been shifted to the very left *) lemma NOT_mask_shifted_lenword: "NOT (mask len << (LENGTH('a) - len) ::'a::len word) = mask (LENGTH('a) - len)" by (rule bit_word_eqI) (auto simp add: word_size bit_not_iff bit_push_bit_iff bit_mask_iff) (* Comparisons between different word sizes. *) lemma shiftr_less: "(w::'a::len word) < k \ w >> n < k" by (metis div_le_dividend le_less_trans shiftr_div_2n' unat_arith_simps(2)) lemma word_and_notzeroD: "w AND w' \ 0 \ w \ 0 \ w' \ 0" by auto lemma shiftr_le_0: "unat (w::'a::len word) < 2 ^ n \ w >> n = (0::'a::len word)" apply (auto simp add: take_bit_word_eq_self_iff word_less_nat_alt simp flip: take_bit_eq_self_iff_drop_bit_eq_0) apply (rule ccontr) apply (simp add: not_le) done lemma of_nat_shiftl: "(of_nat x << n) = (of_nat (x * 2 ^ n) :: ('a::len) word)" proof - have "(of_nat x::'a word) << n = of_nat (2 ^ n) * of_nat x" using shiftl_t2n by (metis word_unat_power) thus ?thesis by simp qed lemma shiftl_1_not_0: "n < LENGTH('a) \ (1::'a::len word) << n \ 0" by (simp add: shiftl_t2n) (* continue sorting out from here *) (* usually: x,y = (len_of TYPE ('a)) *) lemma bitmagic_zeroLast_leq_or1Last: "(a::('a::len) word) AND (mask len << x - len) \ a OR mask (y - len)" by (meson le_word_or2 order_trans word_and_le2) lemma zero_base_lsb_imp_set_eq_as_bit_operation: fixes base ::"'a::len word" assumes valid_prefix: "mask (LENGTH('a) - len) AND base = 0" shows "(base = NOT (mask (LENGTH('a) - len)) AND a) \ (a \ {base .. base OR mask (LENGTH('a) - len)})" proof have helper3: "x OR y = x OR y AND NOT x" for x y ::"'a::len word" by (simp add: word_oa_dist2) from assms show "base = NOT (mask (LENGTH('a) - len)) AND a \ a \ {base..base OR mask (LENGTH('a) - len)}" apply(simp add: word_and_le1) apply(metis helper3 le_word_or2 word_bw_comms(1) word_bw_comms(2)) done next assume "a \ {base..base OR mask (LENGTH('a) - len)}" hence a: "base \ a \ a \ base OR mask (LENGTH('a) - len)" by simp show "base = NOT (mask (LENGTH('a) - len)) AND a" proof - have f2: "\x\<^sub>0. base AND NOT (mask x\<^sub>0) \ a AND NOT (mask x\<^sub>0)" using a neg_mask_mono_le by blast have f3: "\x\<^sub>0. a AND NOT (mask x\<^sub>0) \ (base OR mask (LENGTH('a) - len)) AND NOT (mask x\<^sub>0)" using a neg_mask_mono_le by blast have f4: "base = base AND NOT (mask (LENGTH('a) - len))" using valid_prefix by (metis mask_eq_0_eq_x word_bw_comms(1)) hence f5: "\x\<^sub>6. (base OR x\<^sub>6) AND NOT (mask (LENGTH('a) - len)) = base OR x\<^sub>6 AND NOT (mask (LENGTH('a) - len))" using word_ao_dist by (metis) have f6: "\x\<^sub>2 x\<^sub>3. a AND NOT (mask x\<^sub>2) \ x\<^sub>3 \ \ (base OR mask (LENGTH('a) - len)) AND NOT (mask x\<^sub>2) \ x\<^sub>3" using f3 dual_order.trans by auto have "base = (base OR mask (LENGTH('a) - len)) AND NOT (mask (LENGTH('a) - len))" using f5 by auto hence "base = a AND NOT (mask (LENGTH('a) - len))" using f2 f4 f6 by (metis eq_iff) thus "base = NOT (mask (LENGTH('a) - len)) AND a" by (metis word_bw_comms(1)) qed qed lemma of_nat_eq_signed_scast: "(of_nat x = (y :: ('a::len) signed word)) = (of_nat x = (scast y :: 'a word))" by (metis scast_of_nat scast_scast_id(2)) lemma word_aligned_add_no_wrap_bounded: "\ w + 2^n \ x; w + 2^n \ 0; is_aligned w n \ \ (w::'a::len word) < x" by (blast dest: is_aligned_no_overflow le_less_trans word_leq_le_minus_one) lemma mask_Suc: "mask (Suc n) = (2 :: 'a::len word) ^ n + mask n" by (simp add: mask_eq_decr_exp) lemma mask_mono: "sz' \ sz \ mask sz' \ (mask sz :: 'a::len word)" by (simp add: le_mask_iff shiftr_mask_le) lemma aligned_mask_disjoint: "\ is_aligned (a :: 'a :: len word) n; b \ mask n \ \ a AND b = 0" by (metis and_zero_eq is_aligned_mask le_mask_imp_and_mask word_bw_lcs(1)) lemma word_and_or_mask_aligned: "\ is_aligned a n; b \ mask n \ \ a + b = a OR b" by (simp add: aligned_mask_disjoint word_plus_and_or_coroll) lemma word_and_or_mask_aligned2: \is_aligned b n \ a \ mask n \ a + b = a OR b\ using word_and_or_mask_aligned [of b n a] by (simp add: ac_simps) lemma is_aligned_ucastI: "is_aligned w n \ is_aligned (ucast w) n" by (simp add: bit_ucast_iff is_aligned_nth) lemma ucast_le_maskI: "a \ mask n \ UCAST('a::len \ 'b::len) a \ mask n" by (metis and_mask_eq_iff_le_mask ucast_and_mask) lemma ucast_add_mask_aligned: "\ a \ mask n; is_aligned b n \ \ UCAST ('a::len \ 'b::len) (a + b) = ucast a + ucast b" by (metis add.commute is_aligned_ucastI ucast_le_maskI ucast_or_distrib word_and_or_mask_aligned) lemma ucast_shiftl: "LENGTH('b) \ LENGTH ('a) \ UCAST ('a::len \ 'b::len) x << n = ucast (x << n)" by word_eqI_solve lemma ucast_leq_mask: "LENGTH('a) \ n \ ucast (x::'a::len word) \ mask n" apply (simp add: less_eq_mask_iff_take_bit_eq_self) apply transfer apply (simp add: ac_simps) done lemma shiftl_inj: "\ x << n = y << n; x \ mask (LENGTH('a)-n); y \ mask (LENGTH('a)-n) \ \ x = (y :: 'a :: len word)" apply word_eqI apply (rename_tac n') apply (case_tac "LENGTH('a) - n \ n'", simp) by (metis add.commute add.right_neutral diff_add_inverse le_diff_conv linorder_not_less zero_order(1)) lemma distinct_word_add_ucast_shift_inj: \p' = p \ off' = off\ if *: \p + (UCAST('a::len \ 'b::len) off << n) = p' + (ucast off' << n)\ and \is_aligned p n'\ \is_aligned p' n'\ \n' = n + LENGTH('a)\ \n' < LENGTH('b)\ proof - from \n' = n + LENGTH('a)\ have [simp]: \n' - n = LENGTH('a)\ \n + LENGTH('a) = n'\ by simp_all from \is_aligned p n'\ obtain q where p: \p = push_bit n' (word_of_nat q)\ \q < 2 ^ (LENGTH('b) - n')\ by (rule is_alignedE') from \is_aligned p' n'\ obtain q' where p': \p' = push_bit n' (word_of_nat q')\ \q' < 2 ^ (LENGTH('b) - n')\ by (rule is_alignedE') define m :: nat where \m = unat off\ then have off: \off = word_of_nat m\ by simp define m' :: nat where \m' = unat off'\ then have off': \off' = word_of_nat m'\ by simp have \push_bit n' q + take_bit n' (push_bit n m) < 2 ^ LENGTH('b)\ by (metis id_apply is_aligned_no_wrap''' of_nat_eq_id of_nat_push_bit p(1) p(2) take_bit_nat_eq_self_iff take_bit_nat_less_exp take_bit_push_bit that(2) that(5) unsigned_of_nat) moreover have \push_bit n' q' + take_bit n' (push_bit n m') < 2 ^ LENGTH('b)\ by (metis \n' - n = LENGTH('a)\ id_apply is_aligned_no_wrap''' m'_def of_nat_eq_id of_nat_push_bit off' p'(1) p'(2) take_bit_nat_eq_self_iff take_bit_push_bit that(3) that(5) unsigned_of_nat) ultimately have \push_bit n' q + take_bit n' (push_bit n m) = push_bit n' q' + take_bit n' (push_bit n m')\ using * by (simp add: p p' off off' push_bit_of_nat push_bit_take_bit word_of_nat_inj flip: of_nat_add) then have \int (push_bit n' q + take_bit n' (push_bit n m)) = int (push_bit n' q' + take_bit n' (push_bit n m'))\ by simp then have \concat_bit n' (int (push_bit n m)) (int q) = concat_bit n' (int (push_bit n m')) (int q')\ by (simp add: of_nat_push_bit of_nat_take_bit concat_bit_eq) then show ?thesis by (simp add: p p' off off' take_bit_of_nat take_bit_push_bit word_of_nat_eq_iff concat_bit_eq_iff) (simp add: push_bit_eq_mult) qed lemma word_upto_Nil: "y < x \ [x .e. y ::'a::len word] = []" by (simp add: upto_enum_red not_le word_less_nat_alt) lemma word_enum_decomp_elem: assumes "[x .e. (y ::'a::len word)] = as @ a # bs" shows "x \ a \ a \ y" proof - have "set as \ set [x .e. y] \ a \ set [x .e. y]" using assms by (auto dest: arg_cong[where f=set]) then show ?thesis by auto qed lemma word_enum_prefix: "[x .e. (y ::'a::len word)] = as @ a # bs \ as = (if x < a then [x .e. a - 1] else [])" apply (induct as arbitrary: x; clarsimp) apply (case_tac "x < y") prefer 2 apply (case_tac "x = y", simp) apply (simp add: not_less) apply (drule (1) dual_order.not_eq_order_implies_strict) apply (simp add: word_upto_Nil) apply (simp add: word_upto_Cons_eq) apply (case_tac "x < y") prefer 2 apply (case_tac "x = y", simp) apply (simp add: not_less) apply (drule (1) dual_order.not_eq_order_implies_strict) apply (simp add: word_upto_Nil) apply (clarsimp simp: word_upto_Cons_eq) apply (frule word_enum_decomp_elem) apply clarsimp apply (rule conjI) prefer 2 apply (subst word_Suc_le[symmetric]; clarsimp) apply (drule meta_spec) apply (drule (1) meta_mp) apply clarsimp apply (rule conjI; clarsimp) apply (subst (2) word_upto_Cons_eq) apply unat_arith apply simp done lemma word_enum_decomp_set: "[x .e. (y ::'a::len word)] = as @ a # bs \ a \ set as" by (metis distinct_append distinct_enum_upto' not_distinct_conv_prefix) lemma word_enum_decomp: assumes "[x .e. (y ::'a::len word)] = as @ a # bs" shows "x \ a \ a \ y \ a \ set as \ (\z \ set as. x \ z \ z \ y)" proof - from assms have "set as \ set [x .e. y] \ a \ set [x .e. y]" by (auto dest: arg_cong[where f=set]) with word_enum_decomp_set[OF assms] show ?thesis by auto qed lemma of_nat_unat_le_mask_ucast: "\of_nat (unat t) = w; t \ mask LENGTH('a)\ \ t = UCAST('a::len \ 'b::len) w" by (clarsimp simp: ucast_nat_def ucast_ucast_mask simp flip: and_mask_eq_iff_le_mask) lemma less_diff_gt0: "a < b \ (0 :: 'a :: len word) < b - a" by unat_arith lemma unat_plus_gt: "unat ((a :: 'a :: len word) + b) \ unat a + unat b" by (clarsimp simp: unat_plus_if_size) lemma const_less: "\ (a :: 'a :: len word) - 1 < b; a \ b \ \ a < b" by (metis less_1_simp word_le_less_eq) lemma add_mult_aligned_neg_mask: \(x + y * m) AND NOT(mask n) = (x AND NOT(mask n)) + y * m\ if \m AND (2 ^ n - 1) = 0\ for x y m :: \'a::len word\ by (metis (no_types, opaque_lifting) add.assoc add.commute add.right_neutral add_uminus_conv_diff mask_eq_decr_exp mask_eqs(2) mask_eqs(6) mult.commute mult_zero_left subtract_mask(1) that) lemma unat_of_nat_minus_1: "\ n < 2 ^ LENGTH('a); n \ 0 \ \ unat ((of_nat n:: 'a :: len word) - 1) = n - 1" by (simp add: of_nat_diff unat_eq_of_nat) lemma word_eq_zeroI: "a \ a - 1 \ a = 0" for a :: "'a :: len word" by (simp add: word_must_wrap) lemma word_add_format: "(-1 :: 'a :: len word) + b + c = b + (c - 1)" by simp lemma upto_enum_word_nth: "\ i \ j; k \ unat (j - i) \ \ [i .e. j] ! k = i + of_nat k" apply (clarsimp simp: upto_enum_def nth_append) apply (clarsimp simp: word_le_nat_alt[symmetric]) apply (rule conjI, clarsimp) apply (subst toEnum_of_nat, unat_arith) apply unat_arith apply (clarsimp simp: not_less unat_sub[symmetric]) apply unat_arith done lemma upto_enum_step_nth: "\ a \ c; n \ unat ((c - a) div (b - a)) \ \ [a, b .e. c] ! n = a + of_nat n * (b - a)" by (clarsimp simp: upto_enum_step_def not_less[symmetric] upto_enum_word_nth) lemma upto_enum_inc_1_len: "a < - 1 \ [(0 :: 'a :: len word) .e. 1 + a] = [0 .e. a] @ [1 + a]" apply (simp add: upto_enum_word) apply (subgoal_tac "unat (1+a) = 1 + unat a") apply simp apply (subst unat_plus_simple[THEN iffD1]) apply (metis add.commute no_plus_overflow_neg olen_add_eqv) apply unat_arith done lemma neg_mask_add: "y AND mask n = 0 \ x + y AND NOT(mask n) = (x AND NOT(mask n)) + y" for x y :: \'a::len word\ by (clarsimp simp: mask_out_sub_mask mask_eqs(7)[symmetric] mask_twice) lemma shiftr_shiftl_shiftr[simp]: "(x :: 'a :: len word) >> a << a >> a = x >> a" by word_eqI_solve lemma add_right_shift: "\ x AND mask n = 0; y AND mask n = 0; x \ x + y \ \ (x + y :: ('a :: len) word) >> n = (x >> n) + (y >> n)" apply (simp add: no_olen_add_nat is_aligned_mask[symmetric]) apply (simp add: unat_arith_simps shiftr_div_2n' split del: if_split) apply (subst if_P) apply (erule order_le_less_trans[rotated]) apply (simp add: add_mono) apply (simp add: shiftr_div_2n' is_aligned_iff_dvd_nat) done lemma sub_right_shift: "\ x AND mask n = 0; y AND mask n = 0; y \ x \ \ (x - y) >> n = (x >> n :: 'a :: len word) - (y >> n)" using add_right_shift[where x="x - y" and y=y and n=n] by (simp add: aligned_sub_aligned is_aligned_mask[symmetric] word_sub_le) lemma and_and_mask_simple: "y AND mask n = mask n \ (x AND y) AND mask n = x AND mask n" by (simp add: ac_simps) lemma and_and_mask_simple_not: "y AND mask n = 0 \ (x AND y) AND mask n = 0" by (simp add: ac_simps) lemma word_and_le': "b \ c \ (a :: 'a :: len word) AND b \ c" by (metis word_and_le1 order_trans) lemma word_and_less': "b < c \ (a :: 'a :: len word) AND b < c" by transfer simp lemma shiftr_w2p: "x < LENGTH('a) \ 2 ^ x = (2 ^ (LENGTH('a) - 1) >> (LENGTH('a) - 1 - x) :: 'a :: len word)" by word_eqI_solve lemma t2p_shiftr: "\ b \ a; a < LENGTH('a) \ \ (2 :: 'a :: len word) ^ a >> b = 2 ^ (a - b)" by word_eqI_solve lemma scast_1[simp]: "scast (1 :: 'a :: len signed word) = (1 :: 'a word)" by simp lemma unsigned_uminus1 [simp]: \(unsigned (-1::'b::len word)::'c::len word) = mask LENGTH('b)\ by (rule bit_word_eqI) (auto simp add: bit_simps) lemma ucast_ucast_mask_eq: "\ UCAST('a::len \ 'b::len) x = y; x AND mask LENGTH('b) = x \ \ x = ucast y" by (drule sym) (simp flip: take_bit_eq_mask add: unsigned_ucast_eq) lemma ucast_up_eq: "\ ucast x = (ucast y::'b::len word); LENGTH('a) \ LENGTH ('b) \ \ ucast x = (ucast y::'a::len word)" by word_eqI_solve lemma ucast_up_neq: "\ ucast x \ (ucast y::'b::len word); LENGTH('b) \ LENGTH ('a) \ \ ucast x \ (ucast y::'a::len word)" by (fastforce dest: ucast_up_eq) lemma mask_AND_less_0: "\ x AND mask n = 0; m \ n \ \ x AND mask m = 0" for x :: \'a::len word\ by (metis mask_twice2 word_and_notzeroD) lemma mask_len_id [simp]: "(x :: 'a :: len word) AND mask LENGTH('a) = x" using uint_lt2p [of x] by (simp add: mask_eq_iff) lemma scast_ucast_down_same: "LENGTH('b) \ LENGTH('a) \ SCAST('a \ 'b) = UCAST('a::len \ 'b::len)" by (simp add: down_cast_same is_down) lemma word_aligned_0_sum: "\ a + b = 0; is_aligned (a :: 'a :: len word) n; b \ mask n; n < LENGTH('a) \ \ a = 0 \ b = 0" by (simp add: word_plus_and_or_coroll aligned_mask_disjoint word_or_zero) lemma mask_eq1_nochoice: "\ LENGTH('a) > 1; (x :: 'a :: len word) AND 1 = x \ \ x = 0 \ x = 1" by (metis word_and_1) lemma shiftr_and_eq_shiftl: "(w >> n) AND x = y \ w AND (x << n) = (y << n)" for y :: "'a:: len word" by (metis (no_types, lifting) and_not_mask bit.conj_ac(1) bit.conj_ac(2) mask_eq_0_eq_x shiftl_mask_is_0 shiftl_over_and_dist) lemma add_mask_lower_bits': "\ len = LENGTH('a); is_aligned (x :: 'a :: len word) n; \n' \ n. n' < len \ \ bit p n' \ \ x + p AND NOT(mask n) = x" using add_mask_lower_bits by auto lemma leq_mask_shift: "(x :: 'a :: len word) \ mask (low_bits + high_bits) \ (x >> low_bits) \ mask high_bits" by (simp add: le_mask_iff shiftr_shiftr ac_simps) lemma ucast_ucast_eq_mask_shift: "(x :: 'a :: len word) \ mask (low_bits + LENGTH('b)) \ ucast((ucast (x >> low_bits)) :: 'b :: len word) = x >> low_bits" by (meson and_mask_eq_iff_le_mask eq_ucast_ucast_eq not_le_imp_less shiftr_less_t2n' ucast_ucast_len) lemma const_le_unat: "\ b < 2 ^ LENGTH('a); of_nat b \ a \ \ b \ unat (a :: 'a :: len word)" apply (simp add: word_le_def) apply (simp only: uint_nat zle_int) apply transfer apply (simp add: take_bit_nat_eq_self) done lemma upt_enum_offset_trivial: "\ x < 2 ^ LENGTH('a) - 1 ; n \ unat x \ \ ([(0 :: 'a :: len word) .e. x] ! n) = of_nat n" apply (induct x arbitrary: n) apply simp by (simp add: upto_enum_word_nth) lemma word_le_mask_out_plus_2sz: "x \ (x AND NOT(mask sz)) + 2 ^ sz - 1" for x :: \'a::len word\ by (metis add_diff_eq word_neg_and_le) lemma ucast_add: "ucast (a + (b :: 'a :: len word)) = ucast a + (ucast b :: ('a signed word))" by transfer (simp add: take_bit_add) lemma ucast_minus: "ucast (a - (b :: 'a :: len word)) = ucast a - (ucast b :: ('a signed word))" apply (insert ucast_add[where a=a and b="-b"]) apply (metis (no_types, opaque_lifting) add_diff_eq diff_add_cancel ucast_add) done lemma scast_ucast_add_one [simp]: "scast (ucast (x :: 'a::len word) + (1 :: 'a signed word)) = x + 1" apply (subst ucast_1[symmetric]) apply (subst ucast_add[symmetric]) apply clarsimp done lemma word_and_le_plus_one: "a > 0 \ (x :: 'a :: len word) AND (a - 1) < a" by (simp add: gt0_iff_gem1 word_and_less') lemma unat_of_ucast_then_shift_eq_unat_of_shift[simp]: "LENGTH('b) \ LENGTH('a) \ unat ((ucast (x :: 'a :: len word) :: 'b :: len word) >> n) = unat (x >> n)" by (simp add: shiftr_div_2n' unat_ucast_up_simp) lemma unat_of_ucast_then_mask_eq_unat_of_mask[simp]: "LENGTH('b) \ LENGTH('a) \ unat ((ucast (x :: 'a :: len word) :: 'b :: len word) AND mask m) = unat (x AND mask m)" by (metis ucast_and_mask unat_ucast_up_simp) lemma shiftr_less_t2n3: "\ (2 :: 'a word) ^ (n + m) = 0; m < LENGTH('a) \ \ (x :: 'a :: len word) >> n < 2 ^ m" by (fastforce intro: shiftr_less_t2n' simp: mask_eq_decr_exp power_overflow) lemma unat_shiftr_le_bound: "\ 2 ^ (LENGTH('a :: len) - n) - 1 \ bnd; 0 < n \ \ unat ((x :: 'a word) >> n) \ bnd" apply transfer apply (simp add: take_bit_drop_bit) apply (simp add: drop_bit_take_bit) apply (rule order_trans) defer apply assumption apply (simp add: nat_le_iff of_nat_diff) done lemma shiftr_eqD: "\ x >> n = y >> n; is_aligned x n; is_aligned y n \ \ x = y" by (metis is_aligned_shiftr_shiftl) lemma word_shiftr_shiftl_shiftr_eq_shiftr: "a \ b \ (x :: 'a :: len word) >> a << b >> b = x >> a" apply (rule bit_word_eqI) apply (auto simp add: bit_simps dest: bit_imp_le_length) done lemma of_int_uint_ucast: "of_int (uint (x :: 'a::len word)) = (ucast x :: 'b::len word)" by (fact Word.of_int_uint) lemma mod_mask_drop: "\ m = 2 ^ n; 0 < m; mask n AND msk = mask n \ \ (x mod m) AND msk = x mod m" for x :: \'a::len word\ by (simp add: word_mod_2p_is_mask word_bw_assocs) lemma mask_eq_ucast_eq: "\ x AND mask LENGTH('a) = (x :: ('c :: len word)); LENGTH('a) \ LENGTH('b)\ \ ucast (ucast x :: ('a :: len word)) = (ucast x :: ('b :: len word))" by (metis ucast_and_mask ucast_id ucast_ucast_mask ucast_up_eq) lemma of_nat_less_t2n: "of_nat i < (2 :: ('a :: len) word) ^ n \ n < LENGTH('a) \ unat (of_nat i :: 'a word) < 2 ^ n" by (metis order_less_trans p2_gt_0 unat_less_power word_neq_0_conv) lemma two_power_increasing_less_1: "\ n \ m; m \ LENGTH('a) \ \ (2 :: 'a :: len word) ^ n - 1 \ 2 ^ m - 1" by (metis diff_diff_cancel le_m1_iff_lt less_imp_diff_less p2_gt_0 two_power_increasing word_1_le_power word_le_minus_mono_left word_less_sub_1) lemma word_sub_mono4: "\ y + x \ z + x; y \ y + x; z \ z + x \ \ y \ z" for y :: "'a :: len word" by (simp add: word_add_le_iff2) lemma eq_or_less_helperD: "\ n = unat (2 ^ m - 1 :: 'a :: len word) \ n < unat (2 ^ m - 1 :: 'a word); m < LENGTH('a) \ \ n < 2 ^ m" by (meson le_less_trans nat_less_le unat_less_power word_power_less_1) lemma mask_sub: "n \ m \ mask m - mask n = mask m AND NOT(mask n :: 'a::len word)" by (metis (full_types) and_mask_eq_iff_shiftr_0 mask_out_sub_mask shiftr_mask_le word_bw_comms(1)) lemma neg_mask_diff_bound: "sz'\ sz \ (ptr AND NOT(mask sz')) - (ptr AND NOT(mask sz)) \ 2 ^ sz - 2 ^ sz'" (is "_ \ ?lhs \ ?rhs") for ptr :: \'a::len word\ proof - assume lt: "sz' \ sz" hence "?lhs = ptr AND (mask sz AND NOT(mask sz'))" by (metis add_diff_cancel_left' multiple_mask_trivia) also have "\ \ ?rhs" using lt by (metis (mono_tags) add_diff_eq diff_eq_eq eq_iff mask_2pm1 mask_sub word_and_le') finally show ?thesis by simp qed lemma mask_out_eq_0: "\ idx < 2 ^ sz; sz < LENGTH('a) \ \ (of_nat idx :: 'a :: len word) AND NOT(mask sz) = 0" by (simp add: of_nat_power less_mask_eq mask_eq_0_eq_x) lemma is_aligned_neg_mask_eq': "is_aligned ptr sz = (ptr AND NOT(mask sz) = ptr)" using is_aligned_mask mask_eq_0_eq_x by blast lemma neg_mask_mask_unat: "sz < LENGTH('a) \ unat ((ptr :: 'a :: len word) AND NOT(mask sz)) + unat (ptr AND mask sz) = unat ptr" by (metis AND_NOT_mask_plus_AND_mask_eq unat_plus_simple word_and_le2) lemma unat_pow_le_intro: "LENGTH('a) \ n \ unat (x :: 'a :: len word) < 2 ^ n" by (metis lt2p_lem not_le of_nat_le_iff of_nat_numeral semiring_1_class.of_nat_power uint_nat) lemma unat_shiftl_less_t2n: "\ unat (x :: 'a :: len word) < 2 ^ (m - n); m < LENGTH('a) \ \ unat (x << n) < 2 ^ m" by (metis More_Word.of_nat_power nat_mult_power_less_eq numeral_2_eq_2 of_nat_push_bit push_bit_eq_mult unat_less_power unat_of_nat_len unsigned_less word_eq_unatI zero_less_Suc) lemma unat_is_aligned_add: "\ is_aligned p n; unat d < 2 ^ n \ \ unat (p + d AND mask n) = unat d \ unat (p + d AND NOT(mask n)) = unat p" by (metis add.right_neutral and_mask_eq_iff_le_mask and_not_mask le_mask_iff mask_add_aligned mask_out_add_aligned mult_zero_right shiftl_t2n shiftr_le_0) lemma unat_shiftr_shiftl_mask_zero: "\ c + a \ LENGTH('a) + b ; c < LENGTH('a) \ \ unat (((q :: 'a :: len word) >> a << b) AND NOT(mask c)) = 0" by (fastforce intro: unat_is_aligned_add[where p=0 and n=c, simplified, THEN conjunct2] unat_shiftl_less_t2n unat_shiftr_less_t2n unat_pow_le_intro) lemmas of_nat_ucast = ucast_of_nat[symmetric] lemma shift_then_mask_eq_shift_low_bits: "x \ mask (low_bits + high_bits) \ (x >> low_bits) AND mask high_bits = x >> low_bits" for x :: \'a::len word\ by (simp add: leq_mask_shift le_mask_imp_and_mask) lemma leq_low_bits_iff_zero: "\ x \ mask (low bits + high bits); x >> low_bits = 0 \ \ (x AND mask low_bits = 0) = (x = 0)" for x :: \'a::len word\ using and_mask_eq_iff_shiftr_0 by force lemma unat_less_iff: "\ unat (a :: 'a :: len word) = b; c < 2 ^ LENGTH('a) \ \ (a < of_nat c) = (b < c)" using unat_ucast_less_no_overflow_simp by blast lemma is_aligned_no_overflow3: "\ is_aligned (a :: 'a :: len word) n; n < LENGTH('a); b < 2 ^ n; c \ 2 ^ n; b < c \ \ a + b \ a + (c - 1)" by (meson is_aligned_no_wrap' le_m1_iff_lt not_le word_less_sub_1 word_plus_mono_right) lemma mask_add_aligned_right: "is_aligned p n \ (q + p) AND mask n = q AND mask n" by (simp add: mask_add_aligned add.commute) lemma leq_high_bits_shiftr_low_bits_leq_bits_mask: "x \ mask high_bits \ (x :: 'a :: len word) << low_bits \ mask (low_bits + high_bits)" by (metis le_mask_shiftl_le_mask) lemma word_two_power_neg_ineq: "2 ^ m \ (0 :: 'a word) \ 2 ^ n \ - (2 ^ m :: 'a :: len word)" apply (cases "n < LENGTH('a)"; simp add: power_overflow) apply (cases "m < LENGTH('a)"; simp add: power_overflow) apply (simp add: word_le_nat_alt unat_minus word_size) apply (cases "LENGTH('a)"; simp) apply (simp add: less_Suc_eq_le) apply (drule power_increasing[where a=2 and n=n] power_increasing[where a=2 and n=m], simp)+ apply (drule(1) add_le_mono) apply simp done lemma unat_shiftl_absorb: "\ x \ 2 ^ p; p + k < LENGTH('a) \ \ unat (x :: 'a :: len word) * 2 ^ k = unat (x * 2 ^ k)" by (smt add_diff_cancel_right' add_lessD1 le_add2 le_less_trans mult.commute nat_le_power_trans unat_lt2p unat_mult_lem unat_power_lower word_le_nat_alt) lemma word_plus_mono_right_split: "\ unat ((x :: 'a :: len word) AND mask sz) + unat z < 2 ^ sz; sz < LENGTH('a) \ \ x \ x + z" apply (subgoal_tac "(x AND NOT(mask sz)) + (x AND mask sz) \ (x AND NOT(mask sz)) + ((x AND mask sz) + z)") apply (simp add:word_plus_and_or_coroll2 field_simps) apply (rule word_plus_mono_right) apply (simp add: less_le_trans no_olen_add_nat) using of_nat_power is_aligned_no_wrap' by force lemma mul_not_mask_eq_neg_shiftl: "NOT(mask n :: 'a::len word) = -1 << n" by (simp add: NOT_mask shiftl_t2n) lemma shiftr_mul_not_mask_eq_and_not_mask: "(x >> n) * NOT(mask n) = - (x AND NOT(mask n))" for x :: \'a::len word\ by (metis NOT_mask and_not_mask mult_minus_left semiring_normalization_rules(7) shiftl_t2n) lemma mask_eq_n1_shiftr: "n \ LENGTH('a) \ (mask n :: 'a :: len word) = -1 >> (LENGTH('a) - n)" by (metis diff_diff_cancel eq_refl mask_full shiftr_mask2) lemma is_aligned_mask_out_add_eq: "is_aligned p n \ (p + x) AND NOT(mask n) = p + (x AND NOT(mask n))" by (simp add: mask_out_sub_mask mask_add_aligned) lemmas is_aligned_mask_out_add_eq_sub = is_aligned_mask_out_add_eq[where x="a - b" for a b, simplified field_simps] lemma aligned_bump_down: "is_aligned x n \ (x - 1) AND NOT(mask n) = x - 2 ^ n" by (drule is_aligned_mask_out_add_eq[where x="-1"]) (simp add: NOT_mask) lemma unat_2tp_if: "unat (2 ^ n :: ('a :: len) word) = (if n < LENGTH ('a) then 2 ^ n else 0)" by (split if_split, simp_all add: power_overflow) lemma mask_of_mask: "mask (n::nat) AND mask (m::nat) = (mask (min m n) :: 'a::len word)" by word_eqI_solve lemma unat_signed_ucast_less_ucast: "LENGTH('a) \ LENGTH('b) \ unat (ucast (x :: 'a :: len word) :: 'b :: len signed word) = unat x" by (simp add: unat_ucast_up_simp) lemma toEnum_of_ucast: "LENGTH('b) \ LENGTH('a) \ (toEnum (unat (b::'b :: len word))::'a :: len word) = of_nat (unat b)" by (simp add: unat_pow_le_intro) lemmas unat_ucast_mask = unat_ucast_eq_unat_and_mask[where w=a for a] lemma t2n_mask_eq_if: "2 ^ n AND mask m = (if n < m then 2 ^ n else (0 :: 'a::len word))" by (rule word_eqI) (auto simp add: bit_simps) lemma unat_ucast_le: "unat (ucast (x :: 'a :: len word) :: 'b :: len word) \ unat x" by (simp add: ucast_nat_def word_unat_less_le) lemma ucast_le_up_down_iff: "\ LENGTH('a) \ LENGTH('b); (x :: 'b :: len word) \ ucast (- 1 :: 'a :: len word) \ \ (ucast x \ (y :: 'a word)) = (x \ ucast y)" using le_max_word_ucast_id ucast_le_ucast by metis lemma ucast_ucast_mask_shift: "a \ LENGTH('a) + b \ ucast (ucast (p AND mask a >> b) :: 'a :: len word) = p AND mask a >> b" by (metis add.commute le_mask_iff shiftr_mask_le ucast_ucast_eq_mask_shift word_and_le') lemma unat_ucast_mask_shift: "a \ LENGTH('a) + b \ unat (ucast (p AND mask a >> b) :: 'a :: len word) = unat (p AND mask a >> b)" by (metis linear ucast_ucast_mask_shift unat_ucast_up_simp) lemma mask_overlap_zero: "a \ b \ (p AND mask a) AND NOT(mask b) = 0" for p :: \'a::len word\ by (metis NOT_mask_AND_mask mask_lower_twice2 max_def) lemma mask_shifl_overlap_zero: "a + c \ b \ (p AND mask a << c) AND NOT(mask b) = 0" for p :: \'a::len word\ by (metis and_mask_0_iff_le_mask mask_mono mask_shiftl_decompose order_trans shiftl_over_and_dist word_and_le' word_and_le2) lemma mask_overlap_zero': "a \ b \ (p AND NOT(mask a)) AND mask b = 0" for p :: \'a::len word\ using mask_AND_NOT_mask mask_AND_less_0 by blast lemma mask_rshift_mult_eq_rshift_lshift: "((a :: 'a :: len word) >> b) * (1 << c) = (a >> b << c)" by (simp add: shiftl_t2n) lemma shift_alignment: "a \ b \ is_aligned (p >> a << a) b" using is_aligned_shift is_aligned_weaken by blast lemma mask_split_sum_twice: "a \ b \ (p AND NOT(mask a)) + ((p AND mask a) AND NOT(mask b)) + (p AND mask b) = p" for p :: \'a::len word\ by (simp add: add.commute multiple_mask_trivia word_bw_comms(1) word_bw_lcs(1) word_plus_and_or_coroll2) lemma mask_shift_eq_mask_mask: "(p AND mask a >> b << b) = (p AND mask a) AND NOT(mask b)" for p :: \'a::len word\ by (simp add: and_not_mask) lemma mask_shift_sum: "\ a \ b; unat n = unat (p AND mask b) \ \ (p AND NOT(mask a)) + (p AND mask a >> b) * (1 << b) + n = (p :: 'a :: len word)" apply (simp add: push_bit_of_1 flip: push_bit_eq_mult) apply (subst disjunctive_add) apply (auto simp add: bit_simps) apply (smt (z3) AND_NOT_mask_plus_AND_mask_eq and.comm_neutral and.right_idem and_not_mask bit.conj_disj_distrib bit.disj_cancel_right mask_out_first_mask_some word_bw_assocs(1) word_bw_comms(1) word_bw_comms(2) word_eq_unatI) done lemma is_up_compose: "\ is_up uc; is_up uc' \ \ is_up (uc' \ uc)" unfolding is_up_def by (simp add: Word.target_size Word.source_size) lemma of_int_sint_scast: "of_int (sint (x :: 'a :: len word)) = (scast x :: 'b :: len word)" by (fact Word.of_int_sint) lemma scast_of_nat_to_signed [simp]: "scast (of_nat x :: 'a :: len word) = (of_nat x :: 'a signed word)" by (rule bit_word_eqI) (simp add: bit_simps) lemma scast_of_nat_signed_to_unsigned_add: "scast (of_nat x + of_nat y :: 'a :: len signed word) = (of_nat x + of_nat y :: 'a :: len word)" by (metis of_nat_add scast_of_nat) lemma scast_of_nat_unsigned_to_signed_add: "(scast (of_nat x + of_nat y :: 'a :: len word)) = (of_nat x + of_nat y :: 'a :: len signed word)" by (metis Abs_fnat_hom_add scast_of_nat_to_signed) lemma and_mask_cases: fixes x :: "'a :: len word" assumes len: "n < LENGTH('a)" shows "x AND mask n \ of_nat ` set [0 ..< 2 ^ n]" apply (simp flip: take_bit_eq_mask) apply (rule image_eqI [of _ _ \unat (take_bit n x)\]) using len apply simp_all apply transfer apply simp done lemma sint_eq_uint_2pl: "\ (a :: 'a :: len word) < 2 ^ (LENGTH('a) - 1) \ \ sint a = uint a" by (simp add: not_msb_from_less sint_eq_uint word_2p_lem word_size) lemma pow_sub_less: "\ a + b \ LENGTH('a); unat (x :: 'a :: len word) = 2 ^ a \ \ unat (x * 2 ^ b - 1) < 2 ^ (a + b)" by (smt (z3) eq_or_less_helperD le_add2 le_eq_less_or_eq le_trans power_add unat_mult_lem unat_pow_le_intro unat_power_lower word_eq_unatI) lemma sle_le_2pl: "\ (b :: 'a :: len word) < 2 ^ (LENGTH('a) - 1); a \ b \ \ a <=s b" by (simp add: not_msb_from_less word_sle_msb_le) lemma sless_less_2pl: "\ (b :: 'a :: len word) < 2 ^ (LENGTH('a) - 1); a < b \ \ a > n = w AND mask (size w - n)" for w :: \'a::len word\ by (cases "n \ size w"; clarsimp simp: word_and_le2 and_mask shiftl_zero_size) lemma aligned_sub_aligned_simple: "\ is_aligned a n; is_aligned b n \ \ is_aligned (a - b) n" by (simp add: aligned_sub_aligned) lemma minus_one_shift: "- (1 << n) = (-1 << n :: 'a::len word)" by (simp flip: mul_not_mask_eq_neg_shiftl minus_exp_eq_not_mask add: push_bit_of_1) lemma ucast_eq_mask: "(UCAST('a::len \ 'b::len) x = UCAST('a \ 'b) y) = (x AND mask LENGTH('b) = y AND mask LENGTH('b))" by transfer (simp flip: take_bit_eq_mask add: ac_simps) context fixes w :: "'a::len word" begin private lemma sbintrunc_uint_ucast: assumes "Suc n = LENGTH('b::len)" shows "signed_take_bit n (uint (ucast w :: 'b word)) = signed_take_bit n (uint w)" by (rule bit_eqI) (use assms in \simp add: bit_simps\) private lemma test_bit_sbintrunc: assumes "i < LENGTH('a)" shows "bit (word_of_int (signed_take_bit n (uint w)) :: 'a word) i = (if n < i then bit w n else bit w i)" using assms by (simp add: bit_simps) private lemma test_bit_sbintrunc_ucast: assumes len_a: "i < LENGTH('a)" shows "bit (word_of_int (signed_take_bit (LENGTH('b) - 1) (uint (ucast w :: 'b word))) :: 'a word) i = (if LENGTH('b::len) \ i then bit w (LENGTH('b) - 1) else bit w i)" using len_a by (auto simp add: sbintrunc_uint_ucast bit_simps) lemma scast_ucast_high_bits: \scast (ucast w :: 'b::len word) = w \ (\ i \ {LENGTH('b) ..< size w}. bit w i = bit w (LENGTH('b) - 1))\ proof (cases \LENGTH('a) \ LENGTH('b)\) case True moreover define m where \m = LENGTH('b) - LENGTH('a)\ ultimately have \LENGTH('b) = m + LENGTH('a)\ by simp then show ?thesis apply (simp_all add: signed_ucast_eq word_size) apply (rule bit_word_eqI) apply (simp add: bit_signed_take_bit_iff) done next case False define q where \q = LENGTH('b) - 1\ then have \LENGTH('b) = Suc q\ by simp moreover define m where \m = Suc LENGTH('a) - LENGTH('b)\ with False \LENGTH('b) = Suc q\ have \LENGTH('a) = m + q\ by (simp add: not_le) ultimately show ?thesis apply (simp_all add: signed_ucast_eq word_size) apply (transfer fixing: m q) apply (simp add: signed_take_bit_take_bit) apply rule apply (subst bit_eq_iff) apply (simp add: bit_take_bit_iff bit_signed_take_bit_iff min_def) apply (auto simp add: Suc_le_eq) using less_imp_le_nat apply blast using less_imp_le_nat apply blast done qed lemma scast_ucast_mask_compare: "scast (ucast w :: 'b::len word) = w \ (w \ mask (LENGTH('b) - 1) \ NOT(mask (LENGTH('b) - 1)) \ w)" apply (clarsimp simp: le_mask_high_bits neg_mask_le_high_bits scast_ucast_high_bits word_size) apply (rule iffI; clarsimp) apply (rename_tac i j; case_tac "i = LENGTH('b) - 1"; case_tac "j = LENGTH('b) - 1") by auto lemma ucast_less_shiftl_helper': "\ LENGTH('b) + (a::nat) < LENGTH('a); 2 ^ (LENGTH('b) + a) \ n\ \ (ucast (x :: 'b::len word) << a) < (n :: 'a::len word)" apply (erule order_less_le_trans[rotated]) using ucast_less[where x=x and 'a='a] apply (simp only: shiftl_t2n field_simps) apply (rule word_less_power_trans2; simp) done end lemma ucast_ucast_mask2: "is_down (UCAST ('a \ 'b)) \ UCAST ('b::len \ 'c::len) (UCAST ('a::len \ 'b::len) x) = UCAST ('a \ 'c) (x AND mask LENGTH('b))" apply (simp flip: take_bit_eq_mask) apply transfer apply simp done lemma ucast_NOT: "ucast (NOT x) = NOT(ucast x) AND mask (LENGTH('a))" for x::"'a::len word" by word_eqI lemma ucast_NOT_down: "is_down UCAST('a::len \ 'b::len) \ UCAST('a \ 'b) (NOT x) = NOT(UCAST('a \ 'b) x)" by word_eqI lemma upto_enum_step_shift: "\ is_aligned p n \ \ ([p , p + 2 ^ m .e. p + 2 ^ n - 1]) = map ((+) p) [0, 2 ^ m .e. 2 ^ n - 1]" apply (erule is_aligned_get_word_bits) prefer 2 apply (simp add: map_idI) apply (clarsimp simp: upto_enum_step_def) apply (frule is_aligned_no_overflow) apply (simp add: linorder_not_le [symmetric]) done lemma upto_enum_step_shift_red: "\ is_aligned p sz; sz < LENGTH('a); us \ sz \ \ [p :: 'a :: len word, p + 2 ^ us .e. p + 2 ^ sz - 1] = map (\x. p + of_nat x * 2 ^ us) [0 ..< 2 ^ (sz - us)]" apply (subst upto_enum_step_shift, assumption) apply (simp add: upto_enum_step_red) done lemma upto_enum_step_subset: "set [x, y .e. z] \ {x .. z}" apply (clarsimp simp: upto_enum_step_def linorder_not_less) apply (drule div_to_mult_word_lt) apply (rule conjI) apply (erule word_random[rotated]) apply simp apply (rule order_trans) apply (erule word_plus_mono_right) apply simp apply simp done lemma ucast_distrib: fixes M :: "'a::len word \ 'a::len word \ 'a::len word" fixes M' :: "'b::len word \ 'b::len word \ 'b::len word" fixes L :: "int \ int \ int" assumes lift_M: "\x y. uint (M x y) = L (uint x) (uint y) mod 2 ^ LENGTH('a)" assumes lift_M': "\x y. uint (M' x y) = L (uint x) (uint y) mod 2 ^ LENGTH('b)" assumes distrib: "\x y. (L (x mod (2 ^ LENGTH('b))) (y mod (2 ^ LENGTH('b)))) mod (2 ^ LENGTH('b)) = (L x y) mod (2 ^ LENGTH('b))" assumes is_down: "is_down (ucast :: 'a word \ 'b word)" shows "ucast (M a b) = M' (ucast a) (ucast b)" apply (simp only: ucast_eq) apply (subst lift_M) apply (subst of_int_uint [symmetric], subst lift_M') apply (metis local.distrib local.is_down take_bit_eq_mod ucast_down_wi uint_word_of_int_eq word_of_int_uint) done lemma ucast_down_add: "is_down (ucast:: 'a word \ 'b word) \ ucast ((a :: 'a::len word) + b) = (ucast a + ucast b :: 'b::len word)" by (rule ucast_distrib [where L="(+)"], (clarsimp simp: uint_word_ariths)+, presburger, simp) lemma ucast_down_minus: "is_down (ucast:: 'a word \ 'b word) \ ucast ((a :: 'a::len word) - b) = (ucast a - ucast b :: 'b::len word)" apply (rule ucast_distrib [where L="(-)"], (clarsimp simp: uint_word_ariths)+) apply (metis mod_diff_left_eq mod_diff_right_eq) apply simp done lemma ucast_down_mult: "is_down (ucast:: 'a word \ 'b word) \ ucast ((a :: 'a::len word) * b) = (ucast a * ucast b :: 'b::len word)" apply (rule ucast_distrib [where L="(*)"], (clarsimp simp: uint_word_ariths)+) apply (metis mod_mult_eq) apply simp done lemma scast_distrib: fixes M :: "'a::len word \ 'a::len word \ 'a::len word" fixes M' :: "'b::len word \ 'b::len word \ 'b::len word" fixes L :: "int \ int \ int" assumes lift_M: "\x y. uint (M x y) = L (uint x) (uint y) mod 2 ^ LENGTH('a)" assumes lift_M': "\x y. uint (M' x y) = L (uint x) (uint y) mod 2 ^ LENGTH('b)" assumes distrib: "\x y. (L (x mod (2 ^ LENGTH('b))) (y mod (2 ^ LENGTH('b)))) mod (2 ^ LENGTH('b)) = (L x y) mod (2 ^ LENGTH('b))" assumes is_down: "is_down (scast :: 'a word \ 'b word)" shows "scast (M a b) = M' (scast a) (scast b)" apply (subst (1 2 3) down_cast_same [symmetric]) apply (insert is_down) apply (clarsimp simp: is_down_def target_size source_size is_down) apply (rule ucast_distrib [where L=L, OF lift_M lift_M' distrib]) apply (insert is_down) apply (clarsimp simp: is_down_def target_size source_size is_down) done lemma scast_down_add: "is_down (scast:: 'a word \ 'b word) \ scast ((a :: 'a::len word) + b) = (scast a + scast b :: 'b::len word)" by (rule scast_distrib [where L="(+)"], (clarsimp simp: uint_word_ariths)+, presburger, simp) lemma scast_down_minus: "is_down (scast:: 'a word \ 'b word) \ scast ((a :: 'a::len word) - b) = (scast a - scast b :: 'b::len word)" apply (rule scast_distrib [where L="(-)"], (clarsimp simp: uint_word_ariths)+) apply (metis mod_diff_left_eq mod_diff_right_eq) apply simp done lemma scast_down_mult: "is_down (scast:: 'a word \ 'b word) \ scast ((a :: 'a::len word) * b) = (scast a * scast b :: 'b::len word)" apply (rule scast_distrib [where L="(*)"], (clarsimp simp: uint_word_ariths)+) apply (metis mod_mult_eq) apply simp done lemma scast_ucast_1: "\ is_down (ucast :: 'a word \ 'b word); is_down (ucast :: 'b word \ 'c word) \ \ (scast (ucast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = ucast a" by (metis down_cast_same ucast_eq ucast_down_wi) lemma scast_ucast_3: "\ is_down (ucast :: 'a word \ 'c word); is_down (ucast :: 'b word \ 'c word) \ \ (scast (ucast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = ucast a" by (metis down_cast_same ucast_eq ucast_down_wi) lemma scast_ucast_4: "\ is_up (ucast :: 'a word \ 'b word); is_down (ucast :: 'b word \ 'c word) \ \ (scast (ucast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = ucast a" by (metis down_cast_same ucast_eq ucast_down_wi) lemma scast_scast_b: "\ is_up (scast :: 'a word \ 'b word) \ \ (scast (scast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = scast a" by (metis scast_eq sint_up_scast) lemma ucast_scast_1: "\ is_down (scast :: 'a word \ 'b word); is_down (ucast :: 'b word \ 'c word) \ \ (ucast (scast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = scast a" by (metis scast_eq ucast_down_wi) lemma ucast_scast_3: "\ is_down (scast :: 'a word \ 'c word); is_down (ucast :: 'b word \ 'c word) \ \ (ucast (scast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = scast a" by (metis scast_eq ucast_down_wi) lemma ucast_scast_4: "\ is_up (scast :: 'a word \ 'b word); is_down (ucast :: 'b word \ 'c word) \ \ (ucast (scast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = scast a" by (metis down_cast_same scast_eq sint_up_scast) lemma ucast_ucast_a: "\ is_down (ucast :: 'b word \ 'c word) \ \ (ucast (ucast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = ucast a" by (metis down_cast_same ucast_eq ucast_down_wi) lemma ucast_ucast_b: "\ is_up (ucast :: 'a word \ 'b word) \ \ (ucast (ucast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = ucast a" by (metis ucast_up_ucast) lemma scast_scast_a: "\ is_down (scast :: 'b word \ 'c word) \ \ (scast (scast (a :: 'a::len word) :: 'b::len word) :: 'c::len word) = scast a" apply (simp only: scast_eq) apply (metis down_cast_same is_up_down scast_eq ucast_down_wi) done lemma scast_down_wi [OF refl]: "uc = scast \ is_down uc \ uc (word_of_int x) = word_of_int x" by (metis down_cast_same is_up_down ucast_down_wi) lemmas cast_simps = is_down is_up scast_down_add scast_down_minus scast_down_mult ucast_down_add ucast_down_minus ucast_down_mult scast_ucast_1 scast_ucast_3 scast_ucast_4 ucast_scast_1 ucast_scast_3 ucast_scast_4 ucast_ucast_a ucast_ucast_b scast_scast_a scast_scast_b ucast_down_wi scast_down_wi ucast_of_nat scast_of_nat uint_up_ucast sint_up_scast up_scast_surj up_ucast_surj lemma sdiv_word_max: "(sint (a :: ('a::len) word) sdiv sint (b :: ('a::len) word) < (2 ^ (size a - 1))) = ((a \ - (2 ^ (size a - 1)) \ (b \ -1)))" (is "?lhs = (\ ?a_int_min \ \ ?b_minus1)") proof (rule classical) assume not_thesis: "\ ?thesis" have not_zero: "b \ 0" using not_thesis by (clarsimp) let ?range = \{- (2 ^ (size a - 1))..<2 ^ (size a - 1)} :: int set\ have result_range: "sint a sdiv sint b \ ?range \ {2 ^ (size a - 1)}" using sdiv_word_min [of a b] sdiv_word_max [of a b] by auto have result_range_overflow: "(sint a sdiv sint b = 2 ^ (size a - 1)) = (?a_int_min \ ?b_minus1)" apply (rule iffI [rotated]) apply (clarsimp simp: signed_divide_int_def sgn_if word_size sint_int_min) apply (rule classical) apply (case_tac "?a_int_min") apply (clarsimp simp: word_size sint_int_min) apply (metis diff_0_right int_sdiv_negated_is_minus1 minus_diff_eq minus_int_code(2) power_eq_0_iff sint_minus1 zero_neq_numeral) apply (subgoal_tac "abs (sint a) < 2 ^ (size a - 1)") apply (insert sdiv_int_range [where a="sint a" and b="sint b"])[1] apply (clarsimp simp: word_size) apply (insert sdiv_int_range [where a="sint a" and b="sint b"])[1] apply auto apply (cases \size a\) apply simp_all apply (smt (z3) One_nat_def diff_Suc_1 signed_word_eqI sint_int_min sint_range_size wsst_TYs(3)) done have result_range_simple: "(sint a sdiv sint b \ ?range) \ ?thesis" apply (insert sdiv_int_range [where a="sint a" and b="sint b"]) apply (clarsimp simp: word_size sint_int_min) done show ?thesis apply (rule UnE [OF result_range result_range_simple]) apply simp apply (clarsimp simp: word_size) using result_range_overflow apply (clarsimp simp: word_size) done qed lemmas sdiv_word_min' = sdiv_word_min [simplified word_size, simplified] lemmas sdiv_word_max' = sdiv_word_max [simplified word_size, simplified] lemma signed_arith_ineq_checks_to_eq: "((- (2 ^ (size a - 1)) \ (sint a + sint b)) \ (sint a + sint b \ (2 ^ (size a - 1) - 1))) = (sint a + sint b = sint (a + b ))" "((- (2 ^ (size a - 1)) \ (sint a - sint b)) \ (sint a - sint b \ (2 ^ (size a - 1) - 1))) = (sint a - sint b = sint (a - b))" "((- (2 ^ (size a - 1)) \ (- sint a)) \ (- sint a) \ (2 ^ (size a - 1) - 1)) = ((- sint a) = sint (- a))" "((- (2 ^ (size a - 1)) \ (sint a * sint b)) \ (sint a * sint b \ (2 ^ (size a - 1) - 1))) = (sint a * sint b = sint (a * b))" "((- (2 ^ (size a - 1)) \ (sint a sdiv sint b)) \ (sint a sdiv sint b \ (2 ^ (size a - 1) - 1))) = (sint a sdiv sint b = sint (a sdiv b))" "((- (2 ^ (size a - 1)) \ (sint a smod sint b)) \ (sint a smod sint b \ (2 ^ (size a - 1) - 1))) = (sint a smod sint b = sint (a smod b))" by (auto simp: sint_word_ariths word_size signed_div_arith signed_mod_arith signed_take_bit_int_eq_self_iff intro: sym dest: sym) lemma signed_arith_sint: "((- (2 ^ (size a - 1)) \ (sint a + sint b)) \ (sint a + sint b \ (2 ^ (size a - 1) - 1))) \ sint (a + b) = (sint a + sint b)" "((- (2 ^ (size a - 1)) \ (sint a - sint b)) \ (sint a - sint b \ (2 ^ (size a - 1) - 1))) \ sint (a - b) = (sint a - sint b)" "((- (2 ^ (size a - 1)) \ (- sint a)) \ (- sint a) \ (2 ^ (size a - 1) - 1)) \ sint (- a) = (- sint a)" "((- (2 ^ (size a - 1)) \ (sint a * sint b)) \ (sint a * sint b \ (2 ^ (size a - 1) - 1))) \ sint (a * b) = (sint a * sint b)" "((- (2 ^ (size a - 1)) \ (sint a sdiv sint b)) \ (sint a sdiv sint b \ (2 ^ (size a - 1) - 1))) \ sint (a sdiv b) = (sint a sdiv sint b)" "((- (2 ^ (size a - 1)) \ (sint a smod sint b)) \ (sint a smod sint b \ (2 ^ (size a - 1) - 1))) \ sint (a smod b) = (sint a smod sint b)" by (subst (asm) signed_arith_ineq_checks_to_eq; simp)+ end end