
haftmann@21249: (*  Title:      HOL/Lattices.thy
haftmann@21249:     Author:     Tobias Nipkow
haftmann@21249: *)
haftmann@21249: 
haftmann@22454: header {* Abstract lattices *}
haftmann@21249: 
haftmann@21249: theory Lattices
haftmann@35121: imports Orderings Groups
haftmann@21249: begin
haftmann@21249: 
haftmann@35301: subsection {* Abstract semilattice *}
haftmann@35301: 
haftmann@35301: text {*
haftmann@35301:   This locales provide a basic structure for interpretation into
haftmann@35301:   bigger structures;  extensions require careful thinking, otherwise
haftmann@35301:   undesired effects may occur due to interpretation.
haftmann@35301: *}
haftmann@35301: 
haftmann@35301: locale semilattice = abel_semigroup +
haftmann@35301:   assumes idem [simp]: "f a a = a"
haftmann@35301: begin
haftmann@35301: 
haftmann@35301: lemma left_idem [simp]:
haftmann@35301:   "f a (f a b) = f a b"
haftmann@35301:   by (simp add: assoc [symmetric])
haftmann@35301: 
haftmann@35301: end
haftmann@35301: 
haftmann@35301: 
haftmann@35301: subsection {* Idempotent semigroup *}
haftmann@35301: 
haftmann@35301: class ab_semigroup_idem_mult = ab_semigroup_mult +
haftmann@35301:   assumes mult_idem: "x * x = x"
haftmann@35301: 
haftmann@35301: sublocale ab_semigroup_idem_mult < times!: semilattice times proof
haftmann@35301: qed (fact mult_idem)
haftmann@35301: 
haftmann@35301: context ab_semigroup_idem_mult
haftmann@35301: begin
haftmann@35301: 
haftmann@35301: lemmas mult_left_idem = times.left_idem
haftmann@35301: 
haftmann@35301: end
haftmann@35301: 
haftmann@35301: 
haftmann@35724: subsection {* Concrete lattices *}
haftmann@21249: 
haftmann@25206: notation
wenzelm@25382:   less_eq  (infix "\<sqsubseteq>" 50) and
haftmann@32568:   less  (infix "\<sqsubset>" 50) and
haftmann@41082:   bot ("\<bottom>") and
haftmann@41082:   top ("\<top>")
haftmann@41082: 
krauss@44845: class inf =
krauss@44845:   fixes inf :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" (infixl "\<sqinter>" 70)
haftmann@25206: 
krauss@44845: class sup = 
krauss@44845:   fixes sup :: "'a \<Rightarrow> 'a \<Rightarrow> 'a" (infixl "\<squnion>" 65)
krauss@44845: 
krauss@44845: class semilattice_inf =  order + inf +
haftmann@22737:   assumes inf_le1 [simp]: "x \<sqinter> y \<sqsubseteq> x"
haftmann@22737:   and inf_le2 [simp]: "x \<sqinter> y \<sqsubseteq> y"
nipkow@21733:   and inf_greatest: "x \<sqsubseteq> y \<Longrightarrow> x \<sqsubseteq> z \<Longrightarrow> x \<sqsubseteq> y \<sqinter> z"
haftmann@21249: 
krauss@44845: class semilattice_sup = order + sup +
haftmann@22737:   assumes sup_ge1 [simp]: "x \<sqsubseteq> x \<squnion> y"
haftmann@22737:   and sup_ge2 [simp]: "y \<sqsubseteq> x \<squnion> y"
nipkow@21733:   and sup_least: "y \<sqsubseteq> x \<Longrightarrow> z \<sqsubseteq> x \<Longrightarrow> y \<squnion> z \<sqsubseteq> x"
haftmann@26014: begin
haftmann@26014: 
haftmann@26014: text {* Dual lattice *}
haftmann@26014: 
haftmann@31991: lemma dual_semilattice:
krauss@44845:   "class.semilattice_inf sup greater_eq greater"
haftmann@36635: by (rule class.semilattice_inf.intro, rule dual_order)
haftmann@27682:   (unfold_locales, simp_all add: sup_least)
haftmann@26014: 
haftmann@26014: end
haftmann@21249: 
haftmann@35028: class lattice = semilattice_inf + semilattice_sup
haftmann@21249: 
wenzelm@25382: 
haftmann@28562: subsubsection {* Intro and elim rules*}
nipkow@21733: 
haftmann@35028: context semilattice_inf
nipkow@21733: begin
haftmann@21249: 
haftmann@32064: lemma le_infI1:
haftmann@32064:   "a \<sqsubseteq> x \<Longrightarrow> a \<sqinter> b \<sqsubseteq> x"
haftmann@32064:   by (rule order_trans) auto
haftmann@21249: 
haftmann@32064: lemma le_infI2:
haftmann@32064:   "b \<sqsubseteq> x \<Longrightarrow> a \<sqinter> b \<sqsubseteq> x"
haftmann@32064:   by (rule order_trans) auto
nipkow@21733: 
haftmann@32064: lemma le_infI: "x \<sqsubseteq> a \<Longrightarrow> x \<sqsubseteq> b \<Longrightarrow> x \<sqsubseteq> a \<sqinter> b"
huffman@36008:   by (rule inf_greatest) (* FIXME: duplicate lemma *)
haftmann@21249: 
haftmann@32064: lemma le_infE: "x \<sqsubseteq> a \<sqinter> b \<Longrightarrow> (x \<sqsubseteq> a \<Longrightarrow> x \<sqsubseteq> b \<Longrightarrow> P) \<Longrightarrow> P"
huffman@36008:   by (blast intro: order_trans inf_le1 inf_le2)
haftmann@21249: 
nipkow@21734: lemma le_inf_iff [simp]:
haftmann@32064:   "x \<sqsubseteq> y \<sqinter> z \<longleftrightarrow> x \<sqsubseteq> y \<and> x \<sqsubseteq> z"
haftmann@32064:   by (blast intro: le_infI elim: le_infE)
nipkow@21733: 
haftmann@32064: lemma le_iff_inf:
haftmann@32064:   "x \<sqsubseteq> y \<longleftrightarrow> x \<sqinter> y = x"
haftmann@32064:   by (auto intro: le_infI1 antisym dest: eq_iff [THEN iffD1])
haftmann@21249: 
haftmann@43753: lemma inf_mono: "a \<sqsubseteq> c \<Longrightarrow> b \<sqsubseteq> d \<Longrightarrow> a \<sqinter> b \<sqsubseteq> c \<sqinter> d"
huffman@36008:   by (fast intro: inf_greatest le_infI1 le_infI2)
huffman@36008: 
haftmann@25206: lemma mono_inf:
haftmann@35028:   fixes f :: "'a \<Rightarrow> 'b\<Colon>semilattice_inf"
haftmann@34007:   shows "mono f \<Longrightarrow> f (A \<sqinter> B) \<sqsubseteq> f A \<sqinter> f B"
haftmann@25206:   by (auto simp add: mono_def intro: Lattices.inf_greatest)
nipkow@21733: 
haftmann@25206: end
nipkow@21733: 
haftmann@35028: context semilattice_sup
nipkow@21733: begin
haftmann@21249: 
haftmann@32064: lemma le_supI1:
haftmann@32064:   "x \<sqsubseteq> a \<Longrightarrow> x \<sqsubseteq> a \<squnion> b"
haftmann@25062:   by (rule order_trans) auto
haftmann@21249: 
haftmann@32064: lemma le_supI2:
haftmann@32064:   "x \<sqsubseteq> b \<Longrightarrow> x \<sqsubseteq> a \<squnion> b"
haftmann@25062:   by (rule order_trans) auto 
nipkow@21733: 
haftmann@32064: lemma le_supI:
haftmann@32064:   "a \<sqsubseteq> x \<Longrightarrow> b \<sqsubseteq> x \<Longrightarrow> a \<squnion> b \<sqsubseteq> x"
huffman@36008:   by (rule sup_least) (* FIXME: duplicate lemma *)
haftmann@21249: 
haftmann@32064: lemma le_supE:
haftmann@32064:   "a \<squnion> b \<sqsubseteq> x \<Longrightarrow> (a \<sqsubseteq> x \<Longrightarrow> b \<sqsubseteq> x \<Longrightarrow> P) \<Longrightarrow> P"
huffman@36008:   by (blast intro: order_trans sup_ge1 sup_ge2)
haftmann@22422: 
haftmann@32064: lemma le_sup_iff [simp]:
haftmann@32064:   "x \<squnion> y \<sqsubseteq> z \<longleftrightarrow> x \<sqsubseteq> z \<and> y \<sqsubseteq> z"
haftmann@32064:   by (blast intro: le_supI elim: le_supE)
nipkow@21733: 
haftmann@32064: lemma le_iff_sup:
haftmann@32064:   "x \<sqsubseteq> y \<longleftrightarrow> x \<squnion> y = y"
haftmann@32064:   by (auto intro: le_supI2 antisym dest: eq_iff [THEN iffD1])
nipkow@21734: 
haftmann@43753: lemma sup_mono: "a \<sqsubseteq> c \<Longrightarrow> b \<sqsubseteq> d \<Longrightarrow> a \<squnion> b \<sqsubseteq> c \<squnion> d"
huffman@36008:   by (fast intro: sup_least le_supI1 le_supI2)
huffman@36008: 
haftmann@25206: lemma mono_sup:
haftmann@35028:   fixes f :: "'a \<Rightarrow> 'b\<Colon>semilattice_sup"
haftmann@34007:   shows "mono f \<Longrightarrow> f A \<squnion> f B \<sqsubseteq> f (A \<squnion> B)"
haftmann@25206:   by (auto simp add: mono_def intro: Lattices.sup_least)
nipkow@21733: 
haftmann@25206: end
haftmann@23878: 
nipkow@21733: 
haftmann@32064: subsubsection {* Equational laws *}
haftmann@21249: 
haftmann@35028: sublocale semilattice_inf < inf!: semilattice inf
haftmann@34973: proof
haftmann@34973:   fix a b c
haftmann@34973:   show "(a \<sqinter> b) \<sqinter> c = a \<sqinter> (b \<sqinter> c)"
haftmann@34973:     by (rule antisym) (auto intro: le_infI1 le_infI2)
haftmann@34973:   show "a \<sqinter> b = b \<sqinter> a"
haftmann@34973:     by (rule antisym) auto
haftmann@34973:   show "a \<sqinter> a = a"
haftmann@34973:     by (rule antisym) auto
haftmann@34973: qed
haftmann@34973: 
haftmann@35028: context semilattice_inf
nipkow@21733: begin
nipkow@21733: 
haftmann@34973: lemma inf_assoc: "(x \<sqinter> y) \<sqinter> z = x \<sqinter> (y \<sqinter> z)"
haftmann@34973:   by (fact inf.assoc)
nipkow@21733: 
haftmann@34973: lemma inf_commute: "(x \<sqinter> y) = (y \<sqinter> x)"
haftmann@34973:   by (fact inf.commute)
nipkow@21733: 
haftmann@34973: lemma inf_left_commute: "x \<sqinter> (y \<sqinter> z) = y \<sqinter> (x \<sqinter> z)"
haftmann@34973:   by (fact inf.left_commute)
nipkow@21733: 
huffman@44921: lemma inf_idem: "x \<sqinter> x = x"
huffman@44921:   by (fact inf.idem) (* already simp *)
haftmann@34973: 
noschinl@44918: lemma inf_left_idem [simp]: "x \<sqinter> (x \<sqinter> y) = x \<sqinter> y"
haftmann@34973:   by (fact inf.left_idem)
nipkow@21733: 
haftmann@32642: lemma inf_absorb1: "x \<sqsubseteq> y \<Longrightarrow> x \<sqinter> y = x"
haftmann@32064:   by (rule antisym) auto
nipkow@21733: 
haftmann@32642: lemma inf_absorb2: "y \<sqsubseteq> x \<Longrightarrow> x \<sqinter> y = y"
haftmann@32064:   by (rule antisym) auto
haftmann@34973:  
haftmann@32064: lemmas inf_aci = inf_commute inf_assoc inf_left_commute inf_left_idem
nipkow@21733: 
nipkow@21733: end
nipkow@21733: 
haftmann@35028: sublocale semilattice_sup < sup!: semilattice sup
haftmann@34973: proof
haftmann@34973:   fix a b c
haftmann@34973:   show "(a \<squnion> b) \<squnion> c = a \<squnion> (b \<squnion> c)"
haftmann@34973:     by (rule antisym) (auto intro: le_supI1 le_supI2)
haftmann@34973:   show "a \<squnion> b = b \<squnion> a"
haftmann@34973:     by (rule antisym) auto
haftmann@34973:   show "a \<squnion> a = a"
haftmann@34973:     by (rule antisym) auto
haftmann@34973: qed
haftmann@34973: 
haftmann@35028: context semilattice_sup
nipkow@21733: begin
haftmann@21249: 
haftmann@34973: lemma sup_assoc: "(x \<squnion> y) \<squnion> z = x \<squnion> (y \<squnion> z)"
haftmann@34973:   by (fact sup.assoc)
nipkow@21733: 
haftmann@34973: lemma sup_commute: "(x \<squnion> y) = (y \<squnion> x)"
haftmann@34973:   by (fact sup.commute)
nipkow@21733: 
haftmann@34973: lemma sup_left_commute: "x \<squnion> (y \<squnion> z) = y \<squnion> (x \<squnion> z)"
haftmann@34973:   by (fact sup.left_commute)
nipkow@21733: 
huffman@44921: lemma sup_idem: "x \<squnion> x = x"
huffman@44921:   by (fact sup.idem) (* already simp *)
haftmann@34973: 
noschinl@44918: lemma sup_left_idem [simp]: "x \<squnion> (x \<squnion> y) = x \<squnion> y"
haftmann@34973:   by (fact sup.left_idem)
nipkow@21733: 
haftmann@32642: lemma sup_absorb1: "y \<sqsubseteq> x \<Longrightarrow> x \<squnion> y = x"
haftmann@32064:   by (rule antisym) auto
nipkow@21733: 
haftmann@32642: lemma sup_absorb2: "x \<sqsubseteq> y \<Longrightarrow> x \<squnion> y = y"
haftmann@32064:   by (rule antisym) auto
haftmann@21249: 
haftmann@32064: lemmas sup_aci = sup_commute sup_assoc sup_left_commute sup_left_idem
nipkow@21733: 
nipkow@21733: end
haftmann@21249: 
nipkow@21733: context lattice
nipkow@21733: begin
nipkow@21733: 
haftmann@31991: lemma dual_lattice:
krauss@44845:   "class.lattice sup (op \<ge>) (op >) inf"
haftmann@36635:   by (rule class.lattice.intro, rule dual_semilattice, rule class.semilattice_sup.intro, rule dual_order)
haftmann@31991:     (unfold_locales, auto)
haftmann@31991: 
noschinl@44918: lemma inf_sup_absorb [simp]: "x \<sqinter> (x \<squnion> y) = x"
haftmann@25102:   by (blast intro: antisym inf_le1 inf_greatest sup_ge1)
nipkow@21733: 
noschinl@44918: lemma sup_inf_absorb [simp]: "x \<squnion> (x \<sqinter> y) = x"
haftmann@25102:   by (blast intro: antisym sup_ge1 sup_least inf_le1)
nipkow@21733: 
haftmann@32064: lemmas inf_sup_aci = inf_aci sup_aci
nipkow@21734: 
haftmann@22454: lemmas inf_sup_ord = inf_le1 inf_le2 sup_ge1 sup_ge2
haftmann@22454: 
nipkow@21734: text{* Towards distributivity *}
haftmann@21249: 
nipkow@21734: lemma distrib_sup_le: "x \<squnion> (y \<sqinter> z) \<sqsubseteq> (x \<squnion> y) \<sqinter> (x \<squnion> z)"
haftmann@32064:   by (auto intro: le_infI1 le_infI2 le_supI1 le_supI2)
nipkow@21734: 
nipkow@21734: lemma distrib_inf_le: "(x \<sqinter> y) \<squnion> (x \<sqinter> z) \<sqsubseteq> x \<sqinter> (y \<squnion> z)"
haftmann@32064:   by (auto intro: le_infI1 le_infI2 le_supI1 le_supI2)
nipkow@21734: 
nipkow@21734: text{* If you have one of them, you have them all. *}
haftmann@21249: 
nipkow@21733: lemma distrib_imp1:
haftmann@21249: assumes D: "!!x y z. x \<sqinter> (y \<squnion> z) = (x \<sqinter> y) \<squnion> (x \<sqinter> z)"
haftmann@21249: shows "x \<squnion> (y \<sqinter> z) = (x \<squnion> y) \<sqinter> (x \<squnion> z)"
haftmann@21249: proof-
noschinl@44918:   have "x \<squnion> (y \<sqinter> z) = (x \<squnion> (x \<sqinter> z)) \<squnion> (y \<sqinter> z)" by simp
noschinl@44918:   also have "\<dots> = x \<squnion> (z \<sqinter> (x \<squnion> y))"
noschinl@44918:     by (simp add: D inf_commute sup_assoc del: sup_inf_absorb)
haftmann@21249:   also have "\<dots> = ((x \<squnion> y) \<sqinter> x) \<squnion> ((x \<squnion> y) \<sqinter> z)"
noschinl@44919:     by(simp add: inf_commute)
haftmann@21249:   also have "\<dots> = (x \<squnion> y) \<sqinter> (x \<squnion> z)" by(simp add:D)
haftmann@21249:   finally show ?thesis .
haftmann@21249: qed
haftmann@21249: 
nipkow@21733: lemma distrib_imp2:
haftmann@21249: assumes D: "!!x y z. x \<squnion> (y \<sqinter> z) = (x \<squnion> y) \<sqinter> (x \<squnion> z)"
haftmann@21249: shows "x \<sqinter> (y \<squnion> z) = (x \<sqinter> y) \<squnion> (x \<sqinter> z)"
haftmann@21249: proof-
noschinl@44918:   have "x \<sqinter> (y \<squnion> z) = (x \<sqinter> (x \<squnion> z)) \<sqinter> (y \<squnion> z)" by simp
noschinl@44918:   also have "\<dots> = x \<sqinter> (z \<squnion> (x \<sqinter> y))"
noschinl@44918:     by (simp add: D sup_commute inf_assoc del: inf_sup_absorb)
haftmann@21249:   also have "\<dots> = ((x \<sqinter> y) \<squnion> x) \<sqinter> ((x \<sqinter> y) \<squnion> z)"
noschinl@44919:     by(simp add: sup_commute)
haftmann@21249:   also have "\<dots> = (x \<sqinter> y) \<squnion> (x \<sqinter> z)" by(simp add:D)
haftmann@21249:   finally show ?thesis .
haftmann@21249: qed
haftmann@21249: 
nipkow@21733: end
haftmann@21249: 
haftmann@32568: subsubsection {* Strict order *}
haftmann@32568: 
haftmann@35028: context semilattice_inf
haftmann@32568: begin
haftmann@32568: 
haftmann@32568: lemma less_infI1:
haftmann@32568:   "a \<sqsubset> x \<Longrightarrow> a \<sqinter> b \<sqsubset> x"
haftmann@32642:   by (auto simp add: less_le inf_absorb1 intro: le_infI1)
haftmann@32568: 
haftmann@32568: lemma less_infI2:
haftmann@32568:   "b \<sqsubset> x \<Longrightarrow> a \<sqinter> b \<sqsubset> x"
haftmann@32642:   by (auto simp add: less_le inf_absorb2 intro: le_infI2)
haftmann@32568: 
haftmann@32568: end
haftmann@32568: 
haftmann@35028: context semilattice_sup
haftmann@32568: begin
haftmann@32568: 
haftmann@32568: lemma less_supI1:
haftmann@34007:   "x \<sqsubset> a \<Longrightarrow> x \<sqsubset> a \<squnion> b"
huffman@44921:   using dual_semilattice
huffman@44921:   by (rule semilattice_inf.less_infI1)
haftmann@32568: 
haftmann@32568: lemma less_supI2:
haftmann@34007:   "x \<sqsubset> b \<Longrightarrow> x \<sqsubset> a \<squnion> b"
huffman@44921:   using dual_semilattice
huffman@44921:   by (rule semilattice_inf.less_infI2)
haftmann@32568: 
haftmann@32568: end
haftmann@32568: 
haftmann@21249: 
haftmann@24164: subsection {* Distributive lattices *}
haftmann@21249: 
haftmann@22454: class distrib_lattice = lattice +
haftmann@21249:   assumes sup_inf_distrib1: "x \<squnion> (y \<sqinter> z) = (x \<squnion> y) \<sqinter> (x \<squnion> z)"
haftmann@21249: 
nipkow@21733: context distrib_lattice
nipkow@21733: begin
nipkow@21733: 
nipkow@21733: lemma sup_inf_distrib2:
huffman@44921:   "(y \<sqinter> z) \<squnion> x = (y \<squnion> x) \<sqinter> (z \<squnion> x)"
huffman@44921:   by (simp add: sup_commute sup_inf_distrib1)
haftmann@21249: 
nipkow@21733: lemma inf_sup_distrib1:
huffman@44921:   "x \<sqinter> (y \<squnion> z) = (x \<sqinter> y) \<squnion> (x \<sqinter> z)"
huffman@44921:   by (rule distrib_imp2 [OF sup_inf_distrib1])
haftmann@21249: 
nipkow@21733: lemma inf_sup_distrib2:
huffman@44921:   "(y \<squnion> z) \<sqinter> x = (y \<sqinter> x) \<squnion> (z \<sqinter> x)"
huffman@44921:   by (simp add: inf_commute inf_sup_distrib1)
haftmann@21249: 
haftmann@31991: lemma dual_distrib_lattice:
krauss@44845:   "class.distrib_lattice sup (op \<ge>) (op >) inf"
haftmann@36635:   by (rule class.distrib_lattice.intro, rule dual_lattice)
haftmann@31991:     (unfold_locales, fact inf_sup_distrib1)
haftmann@31991: 
huffman@36008: lemmas sup_inf_distrib =
huffman@36008:   sup_inf_distrib1 sup_inf_distrib2
huffman@36008: 
huffman@36008: lemmas inf_sup_distrib =
huffman@36008:   inf_sup_distrib1 inf_sup_distrib2
huffman@36008: 
nipkow@21733: lemmas distrib =
haftmann@21249:   sup_inf_distrib1 sup_inf_distrib2 inf_sup_distrib1 inf_sup_distrib2
haftmann@21249: 
nipkow@21733: end
nipkow@21733: 
haftmann@21249: 
haftmann@34007: subsection {* Bounded lattices and boolean algebras *}
haftmann@31991: 
kaliszyk@36352: class bounded_lattice_bot = lattice + bot
haftmann@31991: begin
haftmann@31991: 
haftmann@31991: lemma inf_bot_left [simp]:
haftmann@34007:   "\<bottom> \<sqinter> x = \<bottom>"
haftmann@31991:   by (rule inf_absorb1) simp
haftmann@31991: 
haftmann@31991: lemma inf_bot_right [simp]:
haftmann@34007:   "x \<sqinter> \<bottom> = \<bottom>"
haftmann@31991:   by (rule inf_absorb2) simp
haftmann@31991: 
kaliszyk@36352: lemma sup_bot_left [simp]:
kaliszyk@36352:   "\<bottom> \<squnion> x = x"
kaliszyk@36352:   by (rule sup_absorb2) simp
kaliszyk@36352: 
kaliszyk@36352: lemma sup_bot_right [simp]:
kaliszyk@36352:   "x \<squnion> \<bottom> = x"
kaliszyk@36352:   by (rule sup_absorb1) simp
kaliszyk@36352: 
kaliszyk@36352: lemma sup_eq_bot_iff [simp]:
kaliszyk@36352:   "x \<squnion> y = \<bottom> \<longleftrightarrow> x = \<bottom> \<and> y = \<bottom>"
kaliszyk@36352:   by (simp add: eq_iff)
kaliszyk@36352: 
kaliszyk@36352: end
kaliszyk@36352: 
kaliszyk@36352: class bounded_lattice_top = lattice + top
kaliszyk@36352: begin
kaliszyk@36352: 
haftmann@31991: lemma sup_top_left [simp]:
haftmann@34007:   "\<top> \<squnion> x = \<top>"
haftmann@31991:   by (rule sup_absorb1) simp
haftmann@31991: 
haftmann@31991: lemma sup_top_right [simp]:
haftmann@34007:   "x \<squnion> \<top> = \<top>"
haftmann@31991:   by (rule sup_absorb2) simp
haftmann@31991: 
haftmann@31991: lemma inf_top_left [simp]:
haftmann@34007:   "\<top> \<sqinter> x = x"
haftmann@31991:   by (rule inf_absorb2) simp
haftmann@31991: 
haftmann@31991: lemma inf_top_right [simp]:
haftmann@34007:   "x \<sqinter> \<top> = x"
haftmann@31991:   by (rule inf_absorb1) simp
haftmann@31991: 
huffman@36008: lemma inf_eq_top_iff [simp]:
huffman@36008:   "x \<sqinter> y = \<top> \<longleftrightarrow> x = \<top> \<and> y = \<top>"
huffman@36008:   by (simp add: eq_iff)
haftmann@32568: 
kaliszyk@36352: end
kaliszyk@36352: 
kaliszyk@36352: class bounded_lattice = bounded_lattice_bot + bounded_lattice_top
kaliszyk@36352: begin
kaliszyk@36352: 
kaliszyk@36352: lemma dual_bounded_lattice:
krauss@44845:   "class.bounded_lattice sup greater_eq greater inf \<top> \<bottom>"
kaliszyk@36352:   by unfold_locales (auto simp add: less_le_not_le)
haftmann@32568: 
haftmann@34007: end
haftmann@34007: 
haftmann@34007: class boolean_algebra = distrib_lattice + bounded_lattice + minus + uminus +
haftmann@34007:   assumes inf_compl_bot: "x \<sqinter> - x = \<bottom>"
haftmann@34007:     and sup_compl_top: "x \<squnion> - x = \<top>"
haftmann@34007:   assumes diff_eq: "x - y = x \<sqinter> - y"
haftmann@34007: begin
haftmann@34007: 
haftmann@34007: lemma dual_boolean_algebra:
krauss@44845:   "class.boolean_algebra (\<lambda>x y. x \<squnion> - y) uminus sup greater_eq greater inf \<top> \<bottom>"
haftmann@36635:   by (rule class.boolean_algebra.intro, rule dual_bounded_lattice, rule dual_distrib_lattice)
haftmann@34007:     (unfold_locales, auto simp add: inf_compl_bot sup_compl_top diff_eq)
haftmann@34007: 
noschinl@44918: lemma compl_inf_bot [simp]:
haftmann@34007:   "- x \<sqinter> x = \<bottom>"
haftmann@34007:   by (simp add: inf_commute inf_compl_bot)
haftmann@34007: 
noschinl@44918: lemma compl_sup_top [simp]:
haftmann@34007:   "- x \<squnion> x = \<top>"
haftmann@34007:   by (simp add: sup_commute sup_compl_top)
haftmann@34007: 
haftmann@31991: lemma compl_unique:
haftmann@34007:   assumes "x \<sqinter> y = \<bottom>"
haftmann@34007:     and "x \<squnion> y = \<top>"
haftmann@31991:   shows "- x = y"
haftmann@31991: proof -
haftmann@31991:   have "(x \<sqinter> - x) \<squnion> (- x \<sqinter> y) = (x \<sqinter> y) \<squnion> (- x \<sqinter> y)"
haftmann@31991:     using inf_compl_bot assms(1) by simp
haftmann@31991:   then have "(- x \<sqinter> x) \<squnion> (- x \<sqinter> y) = (y \<sqinter> x) \<squnion> (y \<sqinter> - x)"
haftmann@31991:     by (simp add: inf_commute)
haftmann@31991:   then have "- x \<sqinter> (x \<squnion> y) = y \<sqinter> (x \<squnion> - x)"
haftmann@31991:     by (simp add: inf_sup_distrib1)
haftmann@34007:   then have "- x \<sqinter> \<top> = y \<sqinter> \<top>"
haftmann@31991:     using sup_compl_top assms(2) by simp
krauss@34209:   then show "- x = y" by simp
haftmann@31991: qed
haftmann@31991: 
haftmann@31991: lemma double_compl [simp]:
haftmann@31991:   "- (- x) = x"
haftmann@31991:   using compl_inf_bot compl_sup_top by (rule compl_unique)
haftmann@31991: 
haftmann@31991: lemma compl_eq_compl_iff [simp]:
haftmann@31991:   "- x = - y \<longleftrightarrow> x = y"
haftmann@31991: proof
haftmann@31991:   assume "- x = - y"
huffman@36008:   then have "- (- x) = - (- y)" by (rule arg_cong)
haftmann@31991:   then show "x = y" by simp
haftmann@31991: next
haftmann@31991:   assume "x = y"
haftmann@31991:   then show "- x = - y" by simp
haftmann@31991: qed
haftmann@31991: 
haftmann@31991: lemma compl_bot_eq [simp]:
haftmann@34007:   "- \<bottom> = \<top>"
haftmann@31991: proof -
haftmann@34007:   from sup_compl_top have "\<bottom> \<squnion> - \<bottom> = \<top>" .
haftmann@31991:   then show ?thesis by simp
haftmann@31991: qed
haftmann@31991: 
haftmann@31991: lemma compl_top_eq [simp]:
haftmann@34007:   "- \<top> = \<bottom>"
haftmann@31991: proof -
haftmann@34007:   from inf_compl_bot have "\<top> \<sqinter> - \<top> = \<bottom>" .
haftmann@31991:   then show ?thesis by simp
haftmann@31991: qed
haftmann@31991: 
haftmann@31991: lemma compl_inf [simp]:
haftmann@31991:   "- (x \<sqinter> y) = - x \<squnion> - y"
haftmann@31991: proof (rule compl_unique)
huffman@36008:   have "(x \<sqinter> y) \<sqinter> (- x \<squnion> - y) = (y \<sqinter> (x \<sqinter> - x)) \<squnion> (x \<sqinter> (y \<sqinter> - y))"
huffman@36008:     by (simp only: inf_sup_distrib inf_aci)
huffman@36008:   then show "(x \<sqinter> y) \<sqinter> (- x \<squnion> - y) = \<bottom>"
haftmann@31991:     by (simp add: inf_compl_bot)
haftmann@31991: next
huffman@36008:   have "(x \<sqinter> y) \<squnion> (- x \<squnion> - y) = (- y \<squnion> (x \<squnion> - x)) \<sqinter> (- x \<squnion> (y \<squnion> - y))"
huffman@36008:     by (simp only: sup_inf_distrib sup_aci)
huffman@36008:   then show "(x \<sqinter> y) \<squnion> (- x \<squnion> - y) = \<top>"
haftmann@31991:     by (simp add: sup_compl_top)
haftmann@31991: qed
haftmann@31991: 
haftmann@31991: lemma compl_sup [simp]:
haftmann@31991:   "- (x \<squnion> y) = - x \<sqinter> - y"
huffman@44921:   using dual_boolean_algebra
huffman@44921:   by (rule boolean_algebra.compl_inf)
haftmann@31991: 
huffman@36008: lemma compl_mono:
huffman@36008:   "x \<sqsubseteq> y \<Longrightarrow> - y \<sqsubseteq> - x"
huffman@36008: proof -
huffman@36008:   assume "x \<sqsubseteq> y"
huffman@36008:   then have "x \<squnion> y = y" by (simp only: le_iff_sup)
huffman@36008:   then have "- (x \<squnion> y) = - y" by simp
huffman@36008:   then have "- x \<sqinter> - y = - y" by simp
huffman@36008:   then have "- y \<sqinter> - x = - y" by (simp only: inf_commute)
huffman@36008:   then show "- y \<sqsubseteq> - x" by (simp only: le_iff_inf)
huffman@36008: qed
huffman@36008: 
noschinl@44918: lemma compl_le_compl_iff [simp]:
haftmann@43753:   "- x \<sqsubseteq> - y \<longleftrightarrow> y \<sqsubseteq> x"
haftmann@43873:   by (auto dest: compl_mono)
haftmann@43873: 
haftmann@43873: lemma compl_le_swap1:
haftmann@43873:   assumes "y \<sqsubseteq> - x" shows "x \<sqsubseteq> -y"
haftmann@43873: proof -
haftmann@43873:   from assms have "- (- x) \<sqsubseteq> - y" by (simp only: compl_le_compl_iff)
haftmann@43873:   then show ?thesis by simp
haftmann@43873: qed
haftmann@43873: 
haftmann@43873: lemma compl_le_swap2:
haftmann@43873:   assumes "- y \<sqsubseteq> x" shows "- x \<sqsubseteq> y"
haftmann@43873: proof -
haftmann@43873:   from assms have "- x \<sqsubseteq> - (- y)" by (simp only: compl_le_compl_iff)
haftmann@43873:   then show ?thesis by simp
haftmann@43873: qed
haftmann@43873: 
haftmann@43873: lemma compl_less_compl_iff: (* TODO: declare [simp] ? *)
haftmann@43873:   "- x \<sqsubset> - y \<longleftrightarrow> y \<sqsubset> x"
noschinl@44919:   by (auto simp add: less_le)
haftmann@43873: 
haftmann@43873: lemma compl_less_swap1:
haftmann@43873:   assumes "y \<sqsubset> - x" shows "x \<sqsubset> - y"
haftmann@43873: proof -
haftmann@43873:   from assms have "- (- x) \<sqsubset> - y" by (simp only: compl_less_compl_iff)
haftmann@43873:   then show ?thesis by simp
haftmann@43873: qed
haftmann@43873: 
haftmann@43873: lemma compl_less_swap2:
haftmann@43873:   assumes "- y \<sqsubset> x" shows "- x \<sqsubset> y"
haftmann@43873: proof -
haftmann@43873:   from assms have "- x \<sqsubset> - (- y)" by (simp only: compl_less_compl_iff)
haftmann@43873:   then show ?thesis by simp
haftmann@43873: qed
huffman@36008: 
haftmann@31991: end
haftmann@31991: 
haftmann@31991: 
haftmann@22454: subsection {* Uniqueness of inf and sup *}
haftmann@22454: 
haftmann@35028: lemma (in semilattice_inf) inf_unique:
haftmann@22454:   fixes f (infixl "\<triangle>" 70)
haftmann@34007:   assumes le1: "\<And>x y. x \<triangle> y \<sqsubseteq> x" and le2: "\<And>x y. x \<triangle> y \<sqsubseteq> y"
haftmann@34007:   and greatest: "\<And>x y z. x \<sqsubseteq> y \<Longrightarrow> x \<sqsubseteq> z \<Longrightarrow> x \<sqsubseteq> y \<triangle> z"
haftmann@22737:   shows "x \<sqinter> y = x \<triangle> y"
haftmann@22454: proof (rule antisym)
haftmann@34007:   show "x \<triangle> y \<sqsubseteq> x \<sqinter> y" by (rule le_infI) (rule le1, rule le2)
haftmann@22454: next
haftmann@34007:   have leI: "\<And>x y z. x \<sqsubseteq> y \<Longrightarrow> x \<sqsubseteq> z \<Longrightarrow> x \<sqsubseteq> y \<triangle> z" by (blast intro: greatest)
haftmann@34007:   show "x \<sqinter> y \<sqsubseteq> x \<triangle> y" by (rule leI) simp_all
haftmann@22454: qed
haftmann@22454: 
haftmann@35028: lemma (in semilattice_sup) sup_unique:
haftmann@22454:   fixes f (infixl "\<nabla>" 70)
haftmann@34007:   assumes ge1 [simp]: "\<And>x y. x \<sqsubseteq> x \<nabla> y" and ge2: "\<And>x y. y \<sqsubseteq> x \<nabla> y"
haftmann@34007:   and least: "\<And>x y z. y \<sqsubseteq> x \<Longrightarrow> z \<sqsubseteq> x \<Longrightarrow> y \<nabla> z \<sqsubseteq> x"
haftmann@22737:   shows "x \<squnion> y = x \<nabla> y"
haftmann@22454: proof (rule antisym)
haftmann@34007:   show "x \<squnion> y \<sqsubseteq> x \<nabla> y" by (rule le_supI) (rule ge1, rule ge2)
haftmann@22454: next
haftmann@34007:   have leI: "\<And>x y z. x \<sqsubseteq> z \<Longrightarrow> y \<sqsubseteq> z \<Longrightarrow> x \<nabla> y \<sqsubseteq> z" by (blast intro: least)
haftmann@34007:   show "x \<nabla> y \<sqsubseteq> x \<squnion> y" by (rule leI) simp_all
haftmann@22454: qed
huffman@36008: 
haftmann@22454: 
haftmann@22916: subsection {* @{const min}/@{const max} on linear orders as
haftmann@22916:   special case of @{const inf}/@{const sup} *}
haftmann@22916: 
krauss@44845: sublocale linorder < min_max!: distrib_lattice min less_eq less max
haftmann@28823: proof
haftmann@22916:   fix x y z
haftmann@32512:   show "max x (min y z) = min (max x y) (max x z)"
haftmann@32512:     by (auto simp add: min_def max_def)
haftmann@22916: qed (auto simp add: min_def max_def not_le less_imp_le)
haftmann@21249: 
haftmann@35028: lemma inf_min: "inf = (min \<Colon> 'a\<Colon>{semilattice_inf, linorder} \<Rightarrow> 'a \<Rightarrow> 'a)"
haftmann@25102:   by (rule ext)+ (auto intro: antisym)
nipkow@21733: 
haftmann@35028: lemma sup_max: "sup = (max \<Colon> 'a\<Colon>{semilattice_sup, linorder} \<Rightarrow> 'a \<Rightarrow> 'a)"
haftmann@25102:   by (rule ext)+ (auto intro: antisym)
nipkow@21733: 
haftmann@21249: lemmas le_maxI1 = min_max.sup_ge1
haftmann@21249: lemmas le_maxI2 = min_max.sup_ge2
haftmann@21381:  
haftmann@34973: lemmas min_ac = min_max.inf_assoc min_max.inf_commute
haftmann@34973:   min_max.inf.left_commute
haftmann@21249: 
haftmann@34973: lemmas max_ac = min_max.sup_assoc min_max.sup_commute
haftmann@34973:   min_max.sup.left_commute
haftmann@34973: 
haftmann@21249: 
haftmann@46631: subsection {* Lattice on @{typ bool} *}
haftmann@22454: 
haftmann@31991: instantiation bool :: boolean_algebra
haftmann@25510: begin
haftmann@25510: 
haftmann@25510: definition
haftmann@41080:   bool_Compl_def [simp]: "uminus = Not"
haftmann@31991: 
haftmann@31991: definition
haftmann@41080:   bool_diff_def [simp]: "A - B \<longleftrightarrow> A \<and> \<not> B"
haftmann@31991: 
haftmann@31991: definition
haftmann@41080:   [simp]: "P \<sqinter> Q \<longleftrightarrow> P \<and> Q"
haftmann@25510: 
haftmann@25510: definition
haftmann@41080:   [simp]: "P \<squnion> Q \<longleftrightarrow> P \<or> Q"
haftmann@25510: 
haftmann@31991: instance proof
haftmann@41080: qed auto
haftmann@22454: 
haftmann@25510: end
haftmann@25510: 
haftmann@32781: lemma sup_boolI1:
haftmann@32781:   "P \<Longrightarrow> P \<squnion> Q"
haftmann@41080:   by simp
haftmann@32781: 
haftmann@32781: lemma sup_boolI2:
haftmann@32781:   "Q \<Longrightarrow> P \<squnion> Q"
haftmann@41080:   by simp
haftmann@32781: 
haftmann@32781: lemma sup_boolE:
haftmann@32781:   "P \<squnion> Q \<Longrightarrow> (P \<Longrightarrow> R) \<Longrightarrow> (Q \<Longrightarrow> R) \<Longrightarrow> R"
haftmann@41080:   by auto
haftmann@32781: 
haftmann@23878: 
haftmann@46631: subsection {* Lattice on @{typ "_ \<Rightarrow> _"} *}
haftmann@23878: 
haftmann@25510: instantiation "fun" :: (type, lattice) lattice
haftmann@25510: begin
haftmann@25510: 
haftmann@25510: definition
haftmann@41080:   "f \<sqinter> g = (\<lambda>x. f x \<sqinter> g x)"
haftmann@41080: 
haftmann@46689: lemma inf_apply (* CANDIDATE [simp, code] *):
haftmann@41080:   "(f \<sqinter> g) x = f x \<sqinter> g x"
haftmann@41080:   by (simp add: inf_fun_def)
haftmann@25510: 
haftmann@25510: definition
haftmann@41080:   "f \<squnion> g = (\<lambda>x. f x \<squnion> g x)"
haftmann@41080: 
haftmann@46689: lemma sup_apply (* CANDIDATE [simp, code] *):
haftmann@41080:   "(f \<squnion> g) x = f x \<squnion> g x"
haftmann@41080:   by (simp add: sup_fun_def)
haftmann@25510: 
haftmann@32780: instance proof
haftmann@41080: qed (simp_all add: le_fun_def inf_apply sup_apply)
haftmann@23878: 
haftmann@25510: end
haftmann@23878: 
haftmann@41080: instance "fun" :: (type, distrib_lattice) distrib_lattice proof
haftmann@41080: qed (rule ext, simp add: sup_inf_distrib1 inf_apply sup_apply)
haftmann@31991: 
haftmann@34007: instance "fun" :: (type, bounded_lattice) bounded_lattice ..
haftmann@34007: 
haftmann@31991: instantiation "fun" :: (type, uminus) uminus
haftmann@31991: begin
haftmann@31991: 
haftmann@31991: definition
haftmann@31991:   fun_Compl_def: "- A = (\<lambda>x. - A x)"
haftmann@31991: 
haftmann@46689: lemma uminus_apply (* CANDIDATE [simp, code] *):
haftmann@41080:   "(- A) x = - (A x)"
haftmann@41080:   by (simp add: fun_Compl_def)
haftmann@41080: 
haftmann@31991: instance ..
haftmann@31991: 
haftmann@31991: end
haftmann@31991: 
haftmann@31991: instantiation "fun" :: (type, minus) minus
haftmann@31991: begin
haftmann@31991: 
haftmann@31991: definition
haftmann@31991:   fun_diff_def: "A - B = (\<lambda>x. A x - B x)"
haftmann@31991: 
haftmann@46689: lemma minus_apply (* CANDIDATE [simp, code] *):
haftmann@41080:   "(A - B) x = A x - B x"
haftmann@41080:   by (simp add: fun_diff_def)
haftmann@41080: 
haftmann@31991: instance ..
haftmann@31991: 
haftmann@31991: end
haftmann@31991: 
haftmann@41080: instance "fun" :: (type, boolean_algebra) boolean_algebra proof
haftmann@41080: qed (rule ext, simp_all add: inf_apply sup_apply bot_apply top_apply uminus_apply minus_apply inf_compl_bot sup_compl_top diff_eq)+
berghofe@26794: 
haftmann@46631: 
haftmann@46631: subsection {* Lattice on unary and binary predicates *}
haftmann@46631: 
haftmann@46631: lemma inf1I: "A x \<Longrightarrow> B x \<Longrightarrow> (A \<sqinter> B) x"
haftmann@46631:   by (simp add: inf_fun_def)
haftmann@46631: 
haftmann@46631: lemma inf2I: "A x y \<Longrightarrow> B x y \<Longrightarrow> (A \<sqinter> B) x y"
haftmann@46631:   by (simp add: inf_fun_def)
haftmann@46631: 
haftmann@46631: lemma inf1E: "(A \<sqinter> B) x \<Longrightarrow> (A x \<Longrightarrow> B x \<Longrightarrow> P) \<Longrightarrow> P"
haftmann@46631:   by (simp add: inf_fun_def)
haftmann@46631: 
haftmann@46631: lemma inf2E: "(A \<sqinter> B) x y \<Longrightarrow> (A x y \<Longrightarrow> B x y \<Longrightarrow> P) \<Longrightarrow> P"
haftmann@46631:   by (simp add: inf_fun_def)
haftmann@46631: 
haftmann@46631: lemma inf1D1: "(A \<sqinter> B) x \<Longrightarrow> A x"
haftmann@46631:   by (simp add: inf_fun_def)
haftmann@46631: 
haftmann@46631: lemma inf2D1: "(A \<sqinter> B) x y \<Longrightarrow> A x y"
haftmann@46631:   by (simp add: inf_fun_def)
haftmann@46631: 
haftmann@46631: lemma inf1D2: "(A \<sqinter> B) x \<Longrightarrow> B x"
haftmann@46631:   by (simp add: inf_fun_def)
haftmann@46631: 
haftmann@46631: lemma inf2D2: "(A \<sqinter> B) x y \<Longrightarrow> B x y"
haftmann@46631:   by (simp add: inf_fun_def)
haftmann@46631: 
haftmann@46631: lemma sup1I1: "A x \<Longrightarrow> (A \<squnion> B) x"
haftmann@46631:   by (simp add: sup_fun_def)
haftmann@46631: 
haftmann@46631: lemma sup2I1: "A x y \<Longrightarrow> (A \<squnion> B) x y"
haftmann@46631:   by (simp add: sup_fun_def)
haftmann@46631: 
haftmann@46631: lemma sup1I2: "B x \<Longrightarrow> (A \<squnion> B) x"
haftmann@46631:   by (simp add: sup_fun_def)
haftmann@46631: 
haftmann@46631: lemma sup2I2: "B x y \<Longrightarrow> (A \<squnion> B) x y"
haftmann@46631:   by (simp add: sup_fun_def)
haftmann@46631: 
haftmann@46631: lemma sup1E: "(A \<squnion> B) x \<Longrightarrow> (A x \<Longrightarrow> P) \<Longrightarrow> (B x \<Longrightarrow> P) \<Longrightarrow> P"
haftmann@46631:   by (simp add: sup_fun_def) iprover
haftmann@46631: 
haftmann@46631: lemma sup2E: "(A \<squnion> B) x y \<Longrightarrow> (A x y \<Longrightarrow> P) \<Longrightarrow> (B x y \<Longrightarrow> P) \<Longrightarrow> P"
haftmann@46631:   by (simp add: sup_fun_def) iprover
haftmann@46631: 
haftmann@46631: text {*
haftmann@46631:   \medskip Classical introduction rule: no commitment to @{text A} vs
haftmann@46631:   @{text B}.
haftmann@46631: *}
haftmann@46631: 
haftmann@46631: lemma sup1CI: "(\<not> B x \<Longrightarrow> A x) \<Longrightarrow> (A \<squnion> B) x"
haftmann@46631:   by (auto simp add: sup_fun_def)
haftmann@46631: 
haftmann@46631: lemma sup2CI: "(\<not> B x y \<Longrightarrow> A x y) \<Longrightarrow> (A \<squnion> B) x y"
haftmann@46631:   by (auto simp add: sup_fun_def)
haftmann@46631: 
haftmann@46631: 
haftmann@25062: no_notation
wenzelm@25382:   less_eq  (infix "\<sqsubseteq>" 50) and
wenzelm@25382:   less (infix "\<sqsubset>" 50) and
wenzelm@25382:   inf  (infixl "\<sqinter>" 70) and
haftmann@32568:   sup  (infixl "\<squnion>" 65) and
haftmann@32568:   top ("\<top>") and
haftmann@32568:   bot ("\<bottom>")
haftmann@25062: 
haftmann@21249: end
haftmann@46631: 




