Theory Heyting
theory Heyting
imports
Closures
begin
section‹ Heyting algebras \label{sec:heyting_algebras} ›
text‹
Our (complete) lattices are Heyting algebras. The following development is oriented towards
using the derived Heyting implication in a logical fashion. As there are no standard classes for
semi-(complete-)lattices we simply work with complete lattices.
References:
▪ \<^citet>‹"Esakia:2019"› -- fundamental theory
▪ \<^citet>‹‹Lemma 5.2.1› in "vanDalen:2004"› -- some equivalences
▪ 🌐‹https://en.wikipedia.org/wiki/Pseudocomplement› -- properties
›
class heyting_algebra = complete_lattice +
assumes inf_Sup_distrib1: "⋀Y::'a set. ⋀x::'a. x ⊓ (⨆Y) = (⨆y∈Y. x ⊓ y)"
begin
definition heyting :: "'a ⇒ 'a ⇒ 'a" (infixr "❙⟶⇩H" 53) where
"x ❙⟶⇩H y = ⨆{z. x ⊓ z ≤ y}"
lemma heyting:
shows "z ≤ x ❙⟶⇩H y ⟷ z ⊓ x ≤ y" (is "?lhs ⟷ ?rhs")
proof(rule iffI)
from inf_Sup_distrib1 have "⨆{a. x ⊓ a ≤ y} ⊓ x ≤ y" by (simp add: SUP_le_iff inf_commute)
then show "?lhs ⟹ ?rhs" unfolding heyting_def by (meson inf_mono order.trans order_refl)
show "?rhs ⟹ ?lhs" by (simp add: heyting_def Sup_upper inf.commute)
qed
end
setup ‹Sign.mandatory_path "heyting"›
context heyting_algebra
begin
lemma commute:
shows "x ⊓ z ≤ y ⟷ z ≤ (x ❙⟶⇩H y)"
by (simp add: heyting inf.commute)
lemmas uncurry = iffD1[OF heyting]
lemmas curry = iffD2[OF heyting]
lemma curry_conv:
shows "(x ⊓ y ❙⟶⇩H z) = (x ❙⟶⇩H y ❙⟶⇩H z)"
by (simp add: order_eq_iff) (metis heyting eq_refl inf.assoc)
lemma swap:
shows "P ❙⟶⇩H Q ❙⟶⇩H R = Q ❙⟶⇩H P ❙⟶⇩H R"
by (metis curry_conv inf.commute)
lemma absorb:
shows "y ⊓ (x ❙⟶⇩H y) = y"
and "(x ❙⟶⇩H y) ⊓ y = y"
by (simp_all add: curry inf_absorb1 ac_simps)
lemma detachment:
shows "x ⊓ (x ❙⟶⇩H y) = x ⊓ y" (is ?thesis1)
and "(x ❙⟶⇩H y) ⊓ x = x ⊓ y" (is ?thesis2)
proof -
show ?thesis1 by (metis absorb(1) uncurry inf.assoc inf.commute inf.idem inf_iff_le(2))
then show ?thesis2 by (simp add: ac_simps)
qed
lemma discharge:
assumes "x' ≤ x"
shows "x' ⊓ (x ❙⟶⇩H y) = x' ⊓ y" (is ?thesis1)
and "(x ❙⟶⇩H y) ⊓ x' = y ⊓ x'" (is ?thesis2)
proof -
from assms show ?thesis1 by (metis curry_conv detachment(2) inf.absorb1)
then show ?thesis2 by (simp add: ac_simps)
qed
lemma trans:
shows "(x ❙⟶⇩H y) ⊓ (y ❙⟶⇩H z) ≤ x ❙⟶⇩H z"
by (metis curry detachment(2) swap uncurry inf_le2)
lemma rev_trans:
shows "(y ❙⟶⇩H z) ⊓ (x ❙⟶⇩H y) ≤ x ❙⟶⇩H z"
by (simp add: inf.commute trans)
lemma discard:
shows "Q ≤ P ❙⟶⇩H Q"
by (simp add: curry)
lemma infR:
shows "x ❙⟶⇩H y ⊓ z = (x ❙⟶⇩H y) ⊓ (x ❙⟶⇩H z)"
by (simp add: order_eq_iff curry uncurry detachment le_infI2)
lemma mono:
assumes "x' ≤ x"
assumes "y ≤ y'"
shows "x ❙⟶⇩H y ≤ x' ❙⟶⇩H y'"
using assms by (metis curry detachment(1) uncurry inf_commute inf_absorb2 le_infI1)
lemma strengthen[strg]:
assumes "st_ord (¬ F) X X'"
assumes "st_ord F Y Y'"
shows "st_ord F (X ❙⟶⇩H Y) (X' ❙⟶⇩H Y')"
using assms by (cases F; simp add: heyting.mono)
lemma mono2mono[cont_intro, partial_function_mono]:
assumes "monotone orda (≥) F"
assumes "monotone orda (≤) G"
shows "monotone orda (≤) (λx. F x ❙⟶⇩H G x)"
by (simp add: monotoneI curry discharge le_infI1 monotoneD[OF assms(1)] monotoneD[OF assms(2)])
lemma mp:
assumes "x ≤ y ❙⟶⇩H z"
assumes "x ≤ y"
shows "x ≤ z"
by (meson assms uncurry inf_greatest order.refl order_trans)
lemma botL:
shows "⊥ ❙⟶⇩H x = ⊤"
by (simp add: heyting top_le)
lemma top_conv:
shows "x ❙⟶⇩H y = ⊤ ⟷ x ≤ y"
by (metis curry detachment(2) inf_iff_le(1) inf_top.left_neutral)
lemma refl[simp]:
shows "x ❙⟶⇩H x = ⊤"
by (simp add: top_conv)
lemma topL[simp]:
shows "⊤ ❙⟶⇩H x = x"
by (metis detachment(1) inf_top_left)
lemma topR[simp]:
shows "x ❙⟶⇩H ⊤ = ⊤"
by (simp add: top_conv)
lemma K[simp]:
shows "x ❙⟶⇩H (y ❙⟶⇩H x) = ⊤"
by (simp add: discard top_conv)
subclass distrib_lattice
proof
have "x ⊓ (y ⊔ z) ≤ x ⊓ y ⊔ x ⊓ z" for x y z :: 'a
using commute by fastforce
then have "x ⊓ (y ⊔ z) = (x ⊓ y) ⊔ (x ⊓ z)" for x y z :: 'a
by (simp add: order.eq_iff le_infI2)
then show "x ⊔ (y ⊓ z) = (x ⊔ y) ⊓ (x ⊔ z)" for x y z :: 'a
by (rule distrib_imp1)
qed
lemma supL:
shows "(x ⊔ y) ❙⟶⇩H z = (x ❙⟶⇩H z) ⊓ (y ❙⟶⇩H z)"
by (simp add: order_eq_iff mono curry uncurry inf_sup_distrib1)
subclass (in complete_distrib_lattice) heyting_algebra by standard (rule inf_Sup)
lemma inf_Sup_distrib:
shows "x ⊓ ⨆Y = (⨆y∈Y. x ⊓ y)"
and "⨆Y ⊓ x = (⨆y∈Y. x ⊓ y)"
by (simp_all add: inf_Sup_distrib1 inf_commute)
lemma inf_SUP_distrib:
shows "x ⊓ (⨆i∈I. Y i) = (⨆i∈I. x ⊓ Y i)"
and "(⨆i∈I. Y i) ⊓ x = (⨆i∈I. Y i ⊓ x)"
by (simp_all add: inf_Sup_distrib image_image ac_simps)
end
lemma eq_boolean_implication:
fixes x :: "_::boolean_algebra"
shows "x ❙⟶⇩H y = x ❙⟶⇩B y"
by (simp add: order.eq_iff boolean_implication_def heyting.detachment heyting.curry flip: shunt1)
lemmas simp_thms =
heyting.botL
heyting.topL
heyting.topR
heyting.refl
lemma Sup_prime_Sup_irreducible_iff:
fixes x :: "_::heyting_algebra"
shows "Sup_prime x ⟷ Sup_irreducible x"
by (fastforce simp: Sup_prime_on_def Sup_irreducible_on_def inf.order_iff heyting.inf_Sup_distrib
intro: Sup_prime_on_imp_Sup_irreducible_on)
paragraph‹ Logical rules ala HOL ›
lemma bspec:
fixes P :: "_ ⇒ (_::heyting_algebra)"
shows "x ∈ X ⟹ (⨅x∈X. P x ❙⟶⇩H Q x) ⊓ P x ≤ Q x" (is "?X ⟹ ?thesis1")
and "x ∈ X ⟹ P x ⊓ (⨅x∈X. P x ❙⟶⇩H Q x) ≤ Q x" (is "_ ⟹ ?thesis2")
and "(⨅x. P x ❙⟶⇩H Q x) ⊓ P x ≤ Q x" (is ?thesis3)
and "P x ⊓ (⨅x. P x ❙⟶⇩H Q x) ≤ Q x" (is ?thesis4)
proof -
show "?X ⟹ ?thesis1" by (meson INF_lower heyting.uncurry)
then show "?X ⟹ ?thesis2" by (simp add: inf_commute)
show ?thesis3 by (simp add: Inf_lower heyting.commute inf_commute)
then show ?thesis4 by (simp add: inf_commute)
qed
lemma INFL:
fixes Q :: "_::heyting_algebra"
shows "(⨅x∈X. P x ❙⟶⇩H Q) = (⨆x∈X. P x) ❙⟶⇩H Q" (is "?lhs = ?rhs")
proof(rule antisym)
show "?lhs ≤ ?rhs" by (meson INFE SUPE order.refl heyting.commute heyting.uncurry)
show "?rhs ≤ ?lhs" by (simp add: INFI SupI heyting.mono)
qed
lemmas SUPL = heyting.INFL[symmetric]
lemma INFR:
fixes P :: "_::heyting_algebra"
shows "(⨅x∈X. P ❙⟶⇩H Q x) = (P ❙⟶⇩H (⨅x∈X. Q x))" (is "?lhs = ?rhs")
by (simp add: order_eq_iff INFI INF_lower heyting.mono)
(meson INFI INF_lower heyting.curry heyting.uncurry)
lemmas Inf_simps =
Inf_inf
inf_Inf
INF_inf_const1
INF_inf_const2
heyting.INFL
heyting.INFR
lemma SUPL_le:
fixes Q :: "_::heyting_algebra"
shows "(⨆x∈X. P x ❙⟶⇩H Q) ≤ (⨅x∈X. P x) ❙⟶⇩H Q"
by (simp add: INF_lower SUPE heyting.mono)
lemma SUPR_le:
fixes P :: "_::heyting_algebra"
shows "(⨆x∈X. P ❙⟶⇩H Q x) ≤ P ❙⟶⇩H (⨆x∈X. Q x)"
by (simp add: SUPE SUP_upper heyting.mono)
lemma SUP_inf:
fixes Q :: "_::heyting_algebra"
shows "(⨆x∈X. P x ⊓ Q) = (⨆x∈X. P x) ⊓ Q"
by (simp add: heyting.inf_SUP_distrib(2))
lemma inf_SUP:
fixes P :: "_::heyting_algebra"
shows "(⨆x∈X. P ⊓ Q x) = P ⊓ (⨆x∈X. Q x)"
by (simp add: heyting.inf_SUP_distrib(1))
lemmas Sup_simps =
sup_SUP
SUP_sup
heyting.inf_SUP
heyting.SUP_inf
lemma mcont2mcont_inf[cont_intro]:
fixes F :: "_ ⇒ 'a::heyting_algebra"
fixes G :: "_ ⇒ 'a::heyting_algebra"
assumes "mcont luba orda Sup (≤) F"
assumes "mcont luba orda Sup (≤) G"
shows "mcont luba orda Sup (≤) (λx. F x ⊓ G x)"
proof -
have mcont_inf1: "mcont Sup (≤) Sup (≤) (λy. x ⊓ y)" for x :: "'a::heyting_algebra"
by (auto intro!: contI mcontI monotoneI intro: le_infI2 simp flip: heyting.inf_SUP_distrib)
then have mcont_inf2: "mcont Sup (≤) Sup (≤) (λx. x ⊓ y)" for y :: "'a::heyting_algebra"
by (subst inf.commute) (rule mcont_inf1)
from assms mcont_inf1 mcont_inf2 show ?thesis
by (best intro: ccpo.mcont2mcont'[OF complete_lattice_ccpo] ccpo.mcont_const[OF complete_lattice_ccpo])
qed
lemma closure_imp_distrib_le:
fixes P Q :: "_ :: heyting_algebra"
assumes cl: "closure_axioms (≤) cl"
assumes cl_inf: "⋀x y. cl x ⊓ cl y ≤ cl (x ⊓ y)"
shows "P ❙⟶⇩H Q ≤ cl P ❙⟶⇩H cl Q"
proof -
from cl have "(P ❙⟶⇩H Q) ⊓ cl P ≤ cl (P ❙⟶⇩H Q) ⊓ cl P"
by (metis (mono_tags) closure_axioms_def inf_mono order.refl)
also have "… ≤ cl ((P ❙⟶⇩H Q) ⊓ P)"
by (simp add: cl_inf)
also from cl have "… ≤ cl Q"
by (metis (mono_tags) closure_axioms_def order.refl heyting.mono heyting.uncurry)
finally show ?thesis
by (simp add: heyting)
qed
setup ‹Sign.parent_path›
paragraph‹ Pseudocomplements ›
definition pseudocomplement :: "'a::heyting_algebra ⇒ 'a" ("❙¬⇩H _" [75] 75) where
"❙¬⇩Hx = x ❙⟶⇩H ⊥"
lemma pseudocomplementI:
shows "x ≤ ❙¬⇩Hy ⟷ x ⊓ y ≤ ⊥"
by (simp add: pseudocomplement_def heyting)
setup ‹Sign.mandatory_path "pseudocomplement"›
lemma monotone:
shows "antimono pseudocomplement"
by (simp add: antimonoI heyting.mono pseudocomplement_def)
lemmas strengthen[strg] = st_monotone[OF pseudocomplement.monotone]
lemmas mono = monotoneD[OF pseudocomplement.monotone]
lemmas mono2mono[cont_intro, partial_function_mono]
= monotone2monotone[OF pseudocomplement.monotone, simplified, of orda P for orda P]
lemma eq_boolean_negation:
fixes x :: "_::{boolean_algebra,heyting_algebra}"
shows "❙¬⇩Hx = -x"
by (simp add: pseudocomplement_def heyting.eq_boolean_implication)
lemma heyting:
shows "x ❙⟶⇩H ❙¬⇩Hx = ❙¬⇩Hx"
by (simp add: pseudocomplement_def order_eq_iff heyting heyting.detachment)
lemma Inf:
shows "x ⊓ ❙¬⇩Hx = ⊥"
and "❙¬⇩Hx ⊓ x = ⊥"
by (simp_all add: pseudocomplement_def heyting.detachment)
lemma double_le:
shows "x ≤ ❙¬⇩H❙¬⇩Hx"
by (simp add: pseudocomplement_def heyting.detachment heyting.curry)
interpretation double: closure_complete_lattice_class "pseudocomplement ∘ pseudocomplement"
by standard (simp; meson order.trans pseudocomplement.double_le pseudocomplement.mono)
lemma triple:
shows "❙¬⇩H❙¬⇩H❙¬⇩Hx = ❙¬⇩Hx"
by (simp add: order_eq_iff pseudocomplement.double_le pseudocomplement.mono)
lemma contrapos_le:
shows "x ❙⟶⇩H y ≤ ❙¬⇩Hy ❙⟶⇩H ❙¬⇩Hx"
by (simp add: heyting.curry heyting.trans pseudocomplement_def)
lemma sup_inf:
shows "❙¬⇩H(x ⊔ y) = ❙¬⇩Hx ⊓ ❙¬⇩Hy"
by (simp add: pseudocomplement_def heyting.supL)
lemma inf_sup_weak:
shows "❙¬⇩H(x ⊓ y) = ❙¬⇩H❙¬⇩H(❙¬⇩Hx ⊔ ❙¬⇩Hy)"
by (metis (no_types, opaque_lifting) pseudocomplement_def heyting.curry_conv heyting.supL inf_commute pseudocomplement.triple)
lemma fix_triv:
assumes "x = ❙¬⇩Hx"
shows "x = y"
using assms by (metis antisym bot.extremum inf.idem inf_le2 pseudocomplementI)
lemma double_top:
shows "❙¬⇩H❙¬⇩H(x ⊔ ❙¬⇩Hx) = ⊤"
by (metis pseudocomplement_def heyting.refl pseudocomplement.Inf(1) pseudocomplement.sup_inf)
lemma Inf_inf:
fixes P :: "_ ⇒ (_::heyting_algebra)"
shows "(⨅x. P x) ⊓ ❙¬⇩HP x = ⊥"
by (simp add: pseudocomplement_def Inf_lower heyting.discharge(1))
lemma SUP_le:
fixes P :: "_ ⇒ (_::heyting_algebra)"
shows "(⨆x∈X. P x) ≤ ❙¬⇩H(⨅x∈X. ❙¬⇩HP x)"
by (rule SUP_least) (meson INF_lower order.trans pseudocomplement.double_le pseudocomplement.mono)
lemma SUP_INF_le:
fixes P :: "_ ⇒ (_::heyting_algebra)"
shows "(⨆x∈X. ❙¬⇩HP x) ≤ ❙¬⇩H(⨅x∈X. P x)"
by (simp add: INF_lower SUPE pseudocomplement.mono)
lemma SUP:
fixes P :: "_ ⇒ (_::heyting_algebra)"
shows "❙¬⇩H(⨆x∈X. P x) = (⨅x∈X. ❙¬⇩HP x)"
by (simp add: order.eq_iff SUP_upper le_INF_iff pseudocomplement.mono)
(metis inf_commute pseudocomplement.SUP_le pseudocomplementI)
setup ‹Sign.parent_path›
subsection‹ Downwards closure of preorders (downsets) \label{sec:closures-downwards} ›
text‹
A ∗‹downset› (also ∗‹lower set› and ∗‹order ideal›) is a subset of a preorder that is closed under
the order relation. (An ∗‹ideal› is a downset that is \<^const>‹directed›.) Some results require
antisymmetry (a partial order).
References:
▪ \<^citet>‹"Vickers:1989"›, early chapters.
▪ 🌐‹https://en.wikipedia.org/wiki/Alexandrov_topology›
▪ \<^citet>‹‹\S3› in "AbadiPlotkin:1991"›
›
setup ‹Sign.mandatory_path "downwards"›
definition cl :: "'a::preorder set ⇒ 'a set" where
"cl P = {x |x y. y ∈ P ∧ x ≤ y}"
setup ‹Sign.parent_path›
interpretation downwards: closure_powerset_distributive downwards.cl
proof standard
show "(P ⊆ downwards.cl Q) ⟷ (downwards.cl P ⊆ downwards.cl Q)" for P Q :: "'a set"
unfolding downwards.cl_def by (auto dest: order_trans)
show "downwards.cl (⋃X) ⊆ ⋃ (downwards.cl ` X) ∪ downwards.cl {}" for X :: "'a set set"
unfolding downwards.cl_def by auto
qed
interpretation downwards: closure_powerset_distributive_anti_exchange "(downwards.cl::_::order set ⇒ _)"
by standard (unfold downwards.cl_def; blast intro: anti_exchangeI antisym)
setup ‹Sign.mandatory_path "downwards"›
lemma cl_empty:
shows "downwards.cl {} = {}"
unfolding downwards.cl_def by simp
lemma closed_empty[iff]:
shows "{} ∈ downwards.closed"
using downwards.cl_def by fastforce
lemma clI[intro]:
assumes "y ∈ P"
assumes "x ≤ y"
shows "x ∈ downwards.cl P"
unfolding closure.closed_def downwards.cl_def using assms by blast
lemma clE:
assumes "x ∈ downwards.cl P"
obtains y where "y ∈ P" and "x ≤ y"
using assms unfolding downwards.cl_def by fast
lemma closed_in:
assumes "x ∈ P"
assumes "y ≤ x"
assumes "P ∈ downwards.closed"
shows "y ∈ P"
using assms unfolding downwards.cl_def downwards.closed_def by blast
lemma order_embedding:
fixes x :: "_::preorder"
shows "downwards.cl {x} ⊆ downwards.cl {y} ⟷ x ≤ y"
using downwards.cl by (blast elim: downwards.clE)
text‹
The lattice of downsets of a set ‹X› is always a \<^class>‹heyting_algebra›.
References:
▪ \<^citet>‹‹\S7.5› in "Ono:2019"›; uses upsets, points to \<^citet>‹"Stone:1938"› as the origin
▪ \<^citet>‹‹\S2.2› in "Esakia:2019"›
▪ 🌐‹https://en.wikipedia.org/wiki/Intuitionistic_logic#Heyting_algebra_semantics›
›
definition imp :: "'a::preorder set ⇒ 'a set ⇒ 'a set" where
"imp P Q = {σ. ∀σ'≤σ. σ' ∈ P ⟶ σ' ∈ Q}"
lemma imp_refl:
shows "downwards.imp P P = UNIV"
by (simp add: downwards.imp_def)
lemma imp_contained:
assumes "P ⊆ Q"
shows "downwards.imp P Q = UNIV"
unfolding downwards.imp_def using assms by fast
lemma heyting_imp:
assumes "P ∈ downwards.closed"
shows "P ⊆ downwards.imp Q R ⟷ P ∩ Q ⊆ R"
using assms unfolding downwards.imp_def downwards.closed_def by blast
lemma imp_mp':
assumes "σ ∈ downwards.imp P Q"
assumes "σ ∈ P"
shows "σ ∈ Q"
using assms by (simp add: downwards.imp_def)
lemma imp_mp:
shows "P ∩ downwards.imp P Q ⊆ Q"
and "downwards.imp P Q ∩ P ⊆ Q"
by (meson IntD1 IntD2 downwards.imp_mp' subsetI)+
lemma imp_contains:
assumes "X ⊆ Q"
assumes "X ∈ downwards.closed"
shows "X ⊆ downwards.imp P Q"
using assms by (auto simp: downwards.imp_def elim: downwards.closed_in)
lemma imp_downwards:
assumes "y ∈ downwards.imp P Q"
assumes "x ≤ y"
shows "x ∈ downwards.imp P Q"
using assms order_trans by (force simp: downwards.imp_def)
lemma closed_imp:
shows "downwards.imp P Q ∈ downwards.closed"
by (meson downwards.clE downwards.closedI downwards.imp_downwards)
text‹
The set ‹downwards.imp P Q› is the greatest downset contained in the Boolean implication
‹P ❙⟶⇩B Q›, i.e., ‹downwards.imp› is the ∗‹kernel› of ‹(❙⟶⇩B)› \<^citep>‹"Zwiers:1989"›.
Note that ``kernel'' is a choice or interior function.
›
lemma imp_boolean_implication_subseteq:
shows "downwards.imp P Q ⊆ P ❙⟶⇩B Q"
unfolding downwards.imp_def boolean_implication.set_alt_def by blast
lemma downwards_closed_imp_greatest:
assumes "R ⊆ P ❙⟶⇩B Q"
assumes "R ∈ downwards.closed"
shows "R ⊆ downwards.imp P Q"
using assms unfolding boolean_implication.set_alt_def downwards.imp_def downwards.closed_def by blast
definition kernel :: "'a::order set ⇒ 'a set" where
"kernel X = ⨆{Q ∈ downwards.closed. Q ⊆ X}"
lemma kernel_def2:
shows "downwards.kernel X = {σ. ∀σ'≤σ. σ' ∈ X}" (is "?lhs = ?rhs")
proof(rule antisym)
show "?lhs ⊆ ?rhs"
unfolding downwards.kernel_def using downwards.closed_conv by blast
next
have "x ∈ ?lhs" if "x ∈ ?rhs" for x
unfolding downwards.kernel_def using that
by (auto elim: downwards.clE intro: exI[where x="downwards.cl {x}"])
then show "?rhs ⊆ ?lhs" by blast
qed
lemma kernel_contractive:
shows "downwards.kernel X ⊆ X"
unfolding downwards.kernel_def by blast
lemma kernel_idempotent:
shows "downwards.kernel (downwards.kernel X) = downwards.kernel X"
unfolding downwards.kernel_def by blast
lemma kernel_monotone:
shows "mono downwards.kernel"
unfolding downwards.kernel_def by (rule monotoneI) blast
lemma closed_kernel_conv:
shows "X ∈ downwards.closed ⟷ downwards.kernel X = X"
unfolding downwards.kernel_def2 downwards.closed_def by (blast elim: downwards.clE)
lemma closed_kernel:
shows "downwards.kernel X ∈ downwards.closed"
by (simp add: downwards.closed_kernel_conv downwards.kernel_idempotent)
lemma kernel_cl:
shows "downwards.kernel (downwards.cl X) = downwards.cl X"
using downwards.closed_kernel_conv by blast
lemma cl_kernel:
shows "downwards.cl (downwards.kernel X) = downwards.kernel X"
by (simp flip: downwards.closed_conv add: downwards.closed_kernel)
lemma kernel_boolean_implication:
fixes P :: "_::order"
shows "downwards.kernel (P ❙⟶⇩B Q) = downwards.imp P Q"
unfolding downwards.kernel_def2 boolean_implication.set_alt_def downwards.imp_def by blast
setup ‹Sign.parent_path›
end