# Theory Birkhoff_Finite_Distributive_Lattices

theory Birkhoff_Finite_Distributive_Lattices
imports
"HOL-Library.Finite_Lattice"
"HOL.Transcendental"
begin

unbundle lattice_syntax

text ‹ The proof of Birkhoff's representation theorem for finite
distributive lattices @{cite birkhoffRingsSets1937} presented
here follows Davey and Priestley @{cite daveyChapterRepresentationFinite2002}. ›

section ‹ Atoms, Join Primes and Join Irreducibles \label{sec:join-irreducibles} ›

text ‹ Atomic elements are defined as follows. ›

definition (in bounded_lattice_bot) atomic :: "'a ⇒ bool" where
"atomic x ≡ x ≠ ⊥ ∧ (∀ y. y ≤ x ⟶ y = ⊥ ∨ y = x)"

text ‹ Two related concepts are ∗‹join-prime› elements and ∗‹join-irreducible›
elements. ›

definition (in bounded_lattice_bot) join_prime :: "'a ⇒ bool" where
"join_prime x ≡ x ≠ ⊥ ∧ (∀ y z . x ≤ y ⊔ z ⟶ x ≤ y ∨ x ≤ z)"

definition (in bounded_lattice_bot) join_irreducible :: "'a ⇒ bool" where
"join_irreducible x ≡ x ≠ ⊥ ∧ (∀ y z . y < x ⟶ z < x ⟶ y ⊔ z < x)"

lemma (in bounded_lattice_bot) join_irreducible_def':
"join_irreducible x = (x ≠ ⊥ ∧ (∀ y z . x = y ⊔ z ⟶ x = y ∨ x = z))"
unfolding join_irreducible_def
by (metis
nless_le
sup.bounded_iff
sup.cobounded1
sup_ge2)

text ‹ Every join-prime is also join-irreducible. ›

lemma (in bounded_lattice_bot) join_prime_implies_join_irreducible:
assumes "join_prime x"
shows "join_irreducible x"
using assms
unfolding
join_irreducible_def'
join_prime_def

text ‹ In the special case when the underlying lattice is
distributive, the join-prime elements and join-irreducible
elements coincide. ›

class bounded_distrib_lattice_bot = bounded_lattice_bot +
assumes sup_inf_distrib1: "x ⊔ (y ⊓ z) = (x ⊔ y) ⊓ (x ⊔ z)"
begin

subclass distrib_lattice
by (unfold_locales, metis (full_types) sup_inf_distrib1)

end

context complete_distrib_lattice
begin

subclass bounded_distrib_lattice_bot
by (unfold_locales,
metis (full_types)
sup_inf_distrib1)

end

lemma (in bounded_distrib_lattice_bot) join_irreducible_is_join_prime:
"join_irreducible x = join_prime x"
proof
assume "join_prime x"
thus "join_irreducible x"
next
assume "join_irreducible x"
{
fix y z
assume "x ≤ y ⊔ z"
hence "x = x ⊓ (y ⊔ z)"
by (metis local.inf.orderE)
hence "x = (x ⊓ y) ⊔ (x ⊓ z)"
using inf_sup_distrib1 by auto
hence "(x = x ⊓ y) ∨ (x = x ⊓ z)"
using ‹join_irreducible x›
unfolding join_irreducible_def'
by metis
hence "(x ≤ y) ∨ (x ≤ z)"
by (metis (full_types) local.inf.cobounded2)
}
thus "join_prime x"
by (metis
‹join_irreducible x›
join_irreducible_def'
join_prime_def)
qed

text ‹ Every atomic element is join-irreducible. ›

lemma (in bounded_lattice_bot) atomic_implies_join_prime:
assumes "atomic x"
shows "join_irreducible x"
using assms
unfolding
atomic_def
join_irreducible_def'
by (metis (no_types, opaque_lifting)
sup.cobounded2
sup_bot.right_neutral)

text ‹ In the case of Boolean algebras, atomic elements and
join-prime elements are one-in-the-same. ›

lemma (in boolean_algebra) join_prime_is_atomic:
"atomic x = join_prime x"
proof
assume "atomic x"
{
fix y z
assume "x ≤ y ⊔ z"
hence "x = (x ⊓ y) ⊔ (x ⊓ z)"
using inf.absorb1 inf_sup_distrib1 by fastforce
moreover
have "x ≤ y ∨ (x ⊓ y) = ⊥"
"x ≤ z ∨ (x ⊓ z) = ⊥"
using ‹atomic x› inf.cobounded1 inf.cobounded2
unfolding atomic_def
by fastforce+
ultimately have "x ≤ y ∨ x ≤ z"
using ‹atomic x› atomic_def by auto
}
thus "join_prime x"
using ‹atomic x› join_prime_def atomic_def
by auto
next
assume "join_prime x"
{
fix y
assume "y ≤ x" "y ≠ x"
hence "x = x ⊔ y"
using sup.orderE by blast
also have "… = (x ⊔ y) ⊓ (y ⊔ -y)"
by simp
finally have "x = (x ⊓ -y) ⊔ y"
hence "x ≤ -y"
using
‹join_prime x›
‹y ≠ x›
‹y ≤ x›
antisym_conv
inf_le2
sup_neg_inf
unfolding join_prime_def
by blast
hence "y ≤ y ⊓ -y"
by (metis
‹x = x ⊔ y›
inf.orderE
inf_compl_bot_right
inf_sup_absorb
order_refl
sup.commute)
hence "y = ⊥"
using sup_absorb2 by fastforce
}
thus "atomic x"
using ‹join_prime x›
unfolding
atomic_def
join_prime_def
by auto
qed

text ‹ All atomic elements are disjoint. ›

lemma (in bounded_lattice_bot) atomic_disjoint:
assumes "atomic α"
and "atomic β"
shows "(α = β) ⟷ (α ⊓ β ≠ ⊥)"
proof
assume "α = β"
hence "α ⊓ β = α"
by simp
thus "α ⊓ β ≠ ⊥"
using ‹atomic α›
unfolding atomic_def
by auto
next
assume "α ⊓ β ≠ ⊥"
hence "β ≤ α ∧ α ≤ β"
by (metis
assms
atomic_def
inf_absorb2
inf_le1
inf_le2)
thus "α = β" by auto
qed

definition (in bounded_lattice_bot) atomic_elements ("𝒜") where
"𝒜 ≡ {a . atomic a}"

definition (in bounded_lattice_bot) join_irreducible_elements ("𝒥") where
"𝒥 ≡ {a . join_irreducible a}"

section ‹ Birkhoff's Representation Theorem For Finite Distributive Lattices \label{section:birkhoffs-theorem} ›

text ‹ Birkhoff's representation theorem for finite distributive
lattices follows from the fact that every non-‹⊥› element
can be represented by the join-irreducible elements beneath it. ›

text ‹ In this section we merely demonstrate the representation aspect of
Birkhoff's theorem. In \S\ref{section:isomorphism} we show this
representation is a lattice homomorphism. ›

text ‹ The fist step to representing elements is to show that there ∗‹exist›
join-irreducible elements beneath them. This is done by showing if there is
no join-irreducible element, we can make a descending chain with more elements
than the finite Boolean algebra under consideration. ›

fun (in order) descending_chain_list :: "'a list ⇒ bool" where
"descending_chain_list [] = True"
| "descending_chain_list [x] = True"
| "descending_chain_list (x # x' # xs)
= (x < x' ∧ descending_chain_list (x' # xs))"

lemma (in order) descending_chain_list_tail:
assumes "descending_chain_list (s # S)"
shows "descending_chain_list S"
using assms
by (induct S, auto)

lemma (in order) descending_chain_list_drop_penultimate:
assumes "descending_chain_list (s # s' # S)"
shows "descending_chain_list (s # S)"
using assms
by (induct S, simp, auto)

lemma (in order) descending_chain_list_less_than_others:
assumes "descending_chain_list (s # S)"
shows   "∀s' ∈ set S. s < s'"
using assms
by (induct S,
auto,

lemma (in order) descending_chain_list_distinct:
assumes "descending_chain_list S"
shows "distinct S"
using assms
by (induct S,
simp,
meson
descending_chain_list_less_than_others
descending_chain_list_tail
distinct.simps(2)
less_irrefl)

lemma (in finite_distrib_lattice) join_irreducible_lower_bound_exists:
assumes "¬ (x ≤ y)"
shows "∃ z ∈ 𝒥. z ≤ x ∧ ¬ (z ≤ y)"
proof (rule ccontr)
assume ⋆: "¬ (∃ z ∈ 𝒥. z ≤ x ∧ ¬ (z ≤ y))"
{
fix z :: 'a
assume
"z ≤ x"
"¬ (z ≤ y)"
with ⋆ obtain p q where
"p < z"
"q < z"
"p ⊔ q = z"
by (metis (full_types)
bot_least
dual_order.not_eq_order_implies_strict
join_irreducible_def'
join_irreducible_elements_def
sup_ge1
sup_ge2
mem_Collect_eq)
hence "¬ (p ≤ y) ∨ ¬ (q ≤ y)"
by (metis (full_types) ‹¬ z ≤ y› sup_least)
hence "∃ p < z. ¬ (p ≤ y)"
by (metis ‹p < z› ‹q < z›)
}
note fresh = this
{
fix n :: nat
have "∃ S . descending_chain_list S
∧ length S = n
∧ (∀s ∈ set S. s ≤ x ∧ ¬ (s ≤ y))"
proof (induct n)
case 0
then show ?case by simp
next
case (Suc n)
then show ?case proof (cases "n = 0")
case True
hence "descending_chain_list [x]
∧ length [x] = Suc n
∧ (∀s ∈ set [x]. s ≤ x ∧ ¬ (s ≤ y))"
by (metis
Suc
assms
length_0_conv
length_Suc_conv
descending_chain_list.simps(2)
le_less set_ConsD)
then show ?thesis
by blast
next
case False
from this obtain s S where
"descending_chain_list (s # S)"
"length (s # S) = n"
"∀s ∈ set (s # S). s ≤ x ∧ ¬ (s ≤ y)"
using
Suc.hyps
length_0_conv
descending_chain_list.elims(2)
by metis
note A = this
hence "s ≤ x" "¬ (s ≤ y)" by auto
obtain s' :: 'a where
"s' < s"
"¬ (s' ≤ y)"
using
fresh [OF ‹s ≤ x› ‹¬ (s ≤ y)›]
by auto
note B = this
let ?S' = "s' # s # S"
from A and B have
"descending_chain_list ?S'"
"length ?S' = Suc n"
"∀s ∈ set ?S'. s ≤ x ∧ ¬ (s ≤ y)"
by auto
then show ?thesis by blast
qed
qed
}
from this obtain S :: "'a list" where
"descending_chain_list S"
"length S = 1 + (card (UNIV::'a set))"
by auto
hence "card (set S) = 1 + (card (UNIV::'a set))"
using descending_chain_list_distinct
distinct_card
by fastforce
hence "¬ card (set S) ≤ card (UNIV::'a set)"
by presburger
thus "False"
using card_mono finite_UNIV by blast
qed

definition (in bounded_lattice_bot)
join_irreducibles_embedding :: "'a ⇒ 'a set" ("⦃ _ ⦄" ) where
"⦃ x ⦄ ≡ {a ∈ 𝒥. a ≤ x}"

text ‹ We can now show every element is exactly the suprema of the
join-irreducible elements beneath them in any distributive lattice. ›

theorem (in finite_distrib_lattice) sup_join_prime_embedding_ident:
"x = ⨆ ⦃ x ⦄"
proof -
have "∀ a ∈ ⦃ x ⦄. a ≤ x"
by (metis (no_types, lifting)
join_irreducibles_embedding_def
mem_Collect_eq)
hence "⨆ ⦃ x ⦄ ≤ x"
moreover
{
fix y :: 'a
assume "⨆ ⦃ x ⦄ ≤ y"
have "x ≤ y"
proof (rule ccontr)
assume "¬ x ≤ y"
from this obtain a where
"a ∈ 𝒥"
"a ≤ x"
"¬ a ≤ y"
using join_irreducible_lower_bound_exists [OF ‹¬ x ≤ y›]
by metis
hence "a ∈ ⦃ x ⦄"
by (metis (no_types, lifting)
join_irreducibles_embedding_def
mem_Collect_eq)
hence "a ≤ y"
using ‹⨆⦃ x ⦄ ≤ y›
Sup_upper
order.trans
by blast
thus "False"
by (metis (full_types) ‹¬ a ≤ y›)
qed
}
ultimately show ?thesis
using antisym_conv by blast
qed

text ‹ Just as ‹x = ⨆ ⦃ x ⦄›, the reverse is also true; ‹λ x. ⦃ x ⦄›
and ‹λ S. ⨆ S› are inverses where ‹S ∈ 𝒪𝒥›, the set of downsets
in ‹Pow 𝒥›. ›

definition (in bounded_lattice_bot) down_irreducibles ("𝒪𝒥") where
"𝒪𝒥 ≡ { S ∈ Pow 𝒥 . (∃ x . S = ⦃ x ⦄) }"

lemma (in finite_distrib_lattice) join_irreducible_embedding_sup_ident:
assumes "S ∈ 𝒪𝒥"
shows "S = ⦃ ⨆ S ⦄"
proof -
obtain x where
"S = ⦃ x ⦄"
using
‹S ∈ 𝒪𝒥›
unfolding
down_irreducibles_def
by auto
with ‹S ∈ 𝒪𝒥› have "∀ s ∈ S. s ∈ 𝒥 ∧ s ≤ ⨆ S"
unfolding
down_irreducibles_def
Pow_def
using Sup_upper
by fastforce
hence "S ⊆ ⦃ ⨆ S ⦄"
unfolding join_irreducibles_embedding_def
by blast
moreover
{
fix y
assume
"y ∈ 𝒥"
"y ≤ ⨆ S"
have "finite S" by auto
from ‹finite S› and ‹y ≤ ⨆ S› have "∃ s ∈ S. y ≤ s"
proof (induct S rule: finite_induct)
case empty
hence "y ≤ ⊥"
by (metis Sup_empty)
then show ?case
using
‹y ∈ 𝒥›
unfolding
join_irreducible_elements_def
join_irreducible_def
by (metis (mono_tags, lifting)
le_bot
mem_Collect_eq)
next
case (insert s S)
hence "y ≤ s ∨ y ≤ ⨆ S"
using
‹y ∈ 𝒥›
unfolding
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_def
by auto
then show ?case
by (metis (full_types)
insert.hyps(3)
insertCI)
qed
hence "y ≤ x"
by (metis (no_types, lifting)
‹S = ⦃ x ⦄›
join_irreducibles_embedding_def
order_trans
mem_Collect_eq)
hence "y ∈ S"
by (metis (no_types, lifting)
‹S = ⦃ x ⦄›
‹y ∈ 𝒥›
join_irreducibles_embedding_def
mem_Collect_eq)
}
hence "⦃ ⨆ S ⦄ ⊆ S"
unfolding
join_irreducibles_embedding_def
by blast
ultimately show ?thesis by auto
qed

text ‹ Given that ‹λ x. ⦃ x ⦄› has a left and right inverse, we can show
it is a ∗‹bijection›. ›

text ‹ The bijection below is recognizable as a form of ∗‹Birkhoff's Representation Theorem›
for finite distributive lattices. ›

theorem (in finite_distrib_lattice) birkhoffs_theorem:
"bij_betw (λ x. ⦃ x ⦄) UNIV 𝒪𝒥"
unfolding bij_betw_def
proof
{
fix x y
assume "⦃ x ⦄ = ⦃ y ⦄"
hence "⨆ ⦃ x ⦄ = ⨆ ⦃ y ⦄"
by simp
hence "x = y"
using sup_join_prime_embedding_ident
by auto
}
thus "inj (λ x. ⦃ x ⦄)"
unfolding inj_def
by auto
next
show "range (λ x. ⦃ x ⦄) = 𝒪𝒥"
unfolding
down_irreducibles_def
join_irreducibles_embedding_def
by auto
qed

section ‹ Finite Ditributive Lattice Isomorphism \label{section:isomorphism} ›

text ‹ The form of Birkhoff's theorem presented in \S\ref{section:birkhoffs-theorem}
simply gave a bijection between a finite distributive lattice and the
downsets of its join-irreducible elements. This relationship can be
extended to a full-blown ∗‹lattice homomorphism›. In particular
we have the following properties:

▪ ‹⊥› and ‹⊤› are preserved; specifically ‹⦃ ⊥ ⦄ = {}› and
‹⦃ ⊤ ⦄ = 𝒥›.

▪ Order is preserved: ‹x ≤ y = (⦃ x ⦄ ⊆ ⦃ y ⦄)›.

▪ ‹λ x . ⦃ x ⦄› is a lower complete semi-lattice homomorphism, mapping
‹⦃ ⨆ X ⦄ = (⋃ x ∈ X . ⦃ x ⦄)›.

▪ In addition to preserving arbitrary joins, ‹λ x . ⦃ x ⦄› is a
lattice homomorphism, since it also preserves finitary meets with
‹ ⦃ x ⊓ y ⦄ = ⦃ x ⦄ ∩ ⦃ y ⦄ ›. Arbitrary meets are also preserved,
but relative to a top element ‹𝒥›, or in other words
‹ ⦃ ⨅ X ⦄ = 𝒥 ∩ (⋂ x ∈ X. ⦃ x ⦄) ›.

▪ In the case of a Boolean algebra, complementation corresponds to
relative set complementation via ‹⦃ - x ⦄ = 𝒥 - ⦃ x ⦄›.
›

lemma (in finite_distrib_lattice) join_irreducibles_bot:
"⦃ ⊥ ⦄ = {}"
unfolding
join_irreducibles_embedding_def
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_def

lemma (in finite_distrib_lattice) join_irreducibles_top:
"⦃ ⊤ ⦄ = 𝒥"
unfolding
join_irreducibles_embedding_def
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_def
by auto

lemma (in finite_distrib_lattice) join_irreducibles_order_isomorphism:
"x ≤ y = (⦃ x ⦄ ⊆ ⦃ y ⦄)"
by (rule iffI,
metis (mono_tags, lifting)
join_irreducibles_embedding_def
order_trans
mem_Collect_eq
subsetI,
metis (full_types)
Sup_subset_mono
sup_join_prime_embedding_ident)

lemma (in finite_distrib_lattice) join_irreducibles_join_homomorphism:
"⦃ x ⊔ y ⦄ = ⦃ x ⦄ ∪ ⦃ y ⦄"
proof
show "⦃ x ⊔ y ⦄ ⊆ ⦃ x ⦄ ∪ ⦃ y ⦄"
unfolding
join_irreducibles_embedding_def
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_def
by blast
next
show "⦃ x ⦄ ∪ ⦃ y ⦄ ⊆ ⦃ x ⊔ y ⦄"
unfolding
join_irreducibles_embedding_def
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_def
using
le_supI1
sup.absorb_iff1
sup.assoc
by force
qed

lemma (in finite_distrib_lattice) join_irreducibles_sup_homomorphism:
"⦃ ⨆ X ⦄ = (⋃ x ∈ X . ⦃ x ⦄)"
proof -
have "finite X"
by simp
thus ?thesis
proof (induct X rule: finite_induct)
case empty
then show ?case by (simp add: join_irreducibles_bot)
next
case (insert x X)
then show ?case by (simp add: join_irreducibles_join_homomorphism)
qed
qed

lemma (in finite_distrib_lattice) join_irreducibles_meet_homomorphism:
"⦃ x ⊓ y ⦄ = ⦃ x ⦄ ∩ ⦃ y ⦄"
unfolding
join_irreducibles_embedding_def
by auto

text ‹ Arbitrary meets are also preserved, but relative to a top element ‹𝒥›. ›

lemma (in finite_distrib_lattice) join_irreducibles_inf_homomorphism:
"⦃ ⨅ X ⦄ = 𝒥 ∩ (⋂ x ∈ X. ⦃ x ⦄)"
proof -
have "finite X"
by simp
thus ?thesis
proof (induct X rule: finite_induct)
case empty
then show ?case by (simp add: join_irreducibles_top)
next
case (insert x X)
then show ?case by (simp add: join_irreducibles_meet_homomorphism, blast)
qed
qed

text ‹ Finally, we show that complementation is preserved. ›

text ‹ To begin, we define the class of finite Boolean algebras.
This class is simply an extension of @{class boolean_algebra},
extended with \<^term>‹finite UNIV› as per the axiom class @{class finite}. We also
also extend the language of the class with ∗‹infima› and ∗‹suprema›
(i.e. ‹⨅ A› and ‹⨆ A› respectively). ›

class finite_boolean_algebra = boolean_algebra + finite + Inf + Sup +
assumes Inf_def: "⨅ A = Finite_Set.fold (⊓) ⊤ A"
assumes Sup_def: "⨆ A = Finite_Set.fold (⊔) ⊥ A"
begin

text ‹ Finite Boolean algebras are trivially a subclass of finite
distributive lattices, which are necessarily ∗‹complete›. ›

subclass finite_distrib_lattice_complete
using
Inf_fin.coboundedI
Sup_fin.coboundedI
finite_UNIV
le_bot
top_unique
Inf_def
Sup_def
by (unfold_locales, blast, fastforce+)

subclass bounded_distrib_lattice_bot
by (unfold_locales, metis sup_inf_distrib1)
end

lemma (in finite_boolean_algebra) join_irreducibles_complement_homomorphism:
"⦃ - x ⦄ = 𝒥 - ⦃ x ⦄"
proof
show "⦃ - x ⦄ ⊆ 𝒥 - ⦃ x ⦄"
proof
fix j
assume "j ∈ ⦃ - x ⦄"
hence "j ∉ ⦃ x ⦄"
unfolding
join_irreducibles_embedding_def
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_def
by (metis
(mono_tags, lifting)
CollectD
bot_unique
inf.boundedI
inf_compl_bot)
thus "j ∈ 𝒥 - ⦃ x ⦄"
using ‹j ∈ ⦃ - x ⦄›
unfolding
join_irreducibles_embedding_def
by blast
qed
next
show "𝒥 - ⦃ x ⦄ ⊆ ⦃ - x ⦄"
proof
fix j
assume "j ∈ 𝒥 - ⦃ x ⦄"
hence "j ∈ 𝒥" and "¬ j ≤ x"
unfolding join_irreducibles_embedding_def
by blast+
moreover have "j ≤ x ⊔ -x"
by auto
ultimately have "j ≤ -x"
unfolding
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_def
by blast
thus "j ∈ ⦃ - x ⦄"
unfolding join_irreducibles_embedding_def
using ‹j ∈ 𝒥›
by auto
qed
qed

section ‹ Cardinality ›

text ‹ Another consequence of Birkhoff's theorem from \S\ref{section:birkhoffs-theorem}
is that every finite Boolean algebra has a cardinality which is
a power of two. This gives a bound on the number of
atoms/join-prime/irreducible elements, which must be logarithmic in
the size of the finite Boolean algebra they belong to. ›

text ‹ We first show that ‹𝒪𝒥›, the downsets of the join-irreducible elements
‹𝒥›, are the same as the powerset of ‹𝒥› in any finite Boolean algebra. ›

lemma (in finite_boolean_algebra) 𝒪𝒥_is_Pow_𝒥:
"𝒪𝒥 = Pow 𝒥"
proof
show "𝒪𝒥 ⊆ Pow 𝒥"
unfolding down_irreducibles_def
by auto
next
show "Pow 𝒥 ⊆ 𝒪𝒥"
proof (rule ccontr)
assume "¬ Pow 𝒥 ⊆ 𝒪𝒥"
from this obtain S where
"S ⊆ 𝒥"
"∀ x. S ≠ {a ∈ 𝒥. a ≤ x}"
unfolding
down_irreducibles_def
join_irreducibles_embedding_def
by auto
hence "S ≠ {a ∈ 𝒥. a ≤ ⨆ S}"
by auto
moreover
have "∀ s ∈ S . s ∈ 𝒥 ∧ s ≤ ⨆ S"
by (metis (no_types, lifting)
‹S ⊆ 𝒥›
Sup_upper subsetD)
hence "S ⊆ {a ∈ 𝒥. a ≤ ⨆ S}"
by (metis (mono_tags, lifting) Ball_Collect)
ultimately have "∃ y ∈ 𝒥 . y ≤ ⨆ S ∧ y ∉ S"
by (metis (mono_tags, lifting)
mem_Collect_eq
subsetI
subset_antisym)
moreover
{
fix y
assume
"y ∈ 𝒥"
"y ≤ ⨆ S"
from
finite [of S]
‹y ≤ ⨆ S›
‹S ⊆ 𝒥›
have "y ∈ S"
proof (induct S rule: finite_induct)
case empty
hence "y ≤ ⊥"
by (metis (full_types) local.Sup_empty)
then show ?case
using ‹y ∈ 𝒥›
unfolding
join_irreducible_elements_def
join_irreducible_def
by (metis (mono_tags, lifting)
le_bot
mem_Collect_eq)
next
case (insert s S)
hence "y ≤ s ∨ y ≤ ⨆ S"
using ‹y ∈ 𝒥›
unfolding
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_def
by simp
moreover
{
assume "y ≤ s"
have "atomic s"
by (metis in_mono
insert.prems(2)
insertCI
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_is_atomic
mem_Collect_eq)
hence "y = s"
by (metis (no_types, lifting)
‹y ∈ 𝒥›
‹y ≤ s›
atomic_def
join_irreducible_def
join_irreducible_elements_def
mem_Collect_eq)
}
ultimately show ?case
by (metis
insert.prems(2)
insert_iff
insert_subset
insert(3))
qed
}
ultimately show False by auto
qed
qed

lemma (in finite_boolean_algebra) UNIV_card:
"card (UNIV::'a set) = card (Pow 𝒥)"
using
bij_betw_same_card [where f="λx. ⦃ x ⦄"]
birkhoffs_theorem
unfolding
𝒪𝒥_is_Pow_𝒥
by blast

lemma finite_Pow_card:
assumes "finite X"
shows "card (Pow X) = 2 powr (card X)"
using assms
proof (induct X rule: finite_induct)
case empty
then show ?case by fastforce
next
case (insert x X)
have "0 ≤ (2 :: real)" by auto
hence two_powr_one: "(2 :: real) = 2 powr 1" by fastforce
have "bij_betw (λ x. fst x ∪ snd x) ({{},{x}} × Pow X) (Pow (insert x X))"
unfolding bij_betw_def
proof
{
fix y z
assume
"y ∈ {{}, {x}} × Pow X"
"z ∈ {{}, {x}} × Pow X"
"fst y ∪ snd y = fst z ∪ snd z"
(is "?Uy = ?Uz")
hence
"x ∉ snd y"
"x ∉ snd z"
"fst y = {x} ∨ fst y = {}"
"fst z = {x} ∨ fst z = {}"
using insert.hyps(2) by auto
hence
"x ∈ ?Uy ⟷ fst y = {x}"
"x ∈ ?Uz ⟷ fst z = {x}"
"x ∉ ?Uy ⟷ fst y = {}"
"x ∉ ?Uz ⟷ fst z = {}"
"snd y = ?Uy - {x}"
"snd z = ?Uz - {x}"
by auto
hence
"x ∈ ?Uy ⟷ y = ({x}, ?Uy - {x})"
"x ∈ ?Uz ⟷ z = ({x}, ?Uz - {x})"
"x ∉ ?Uy ⟷ y = ({}, ?Uy - {x})"
"x ∉ ?Uz ⟷ z = ({}, ?Uz - {x})"
by (metis fst_conv prod.collapse)+
hence "y = z"
using ‹?Uy = ?Uz›
by metis
}
thus "inj_on (λx. fst x ∪ snd x) ({{}, {x}} × Pow X)"
unfolding inj_on_def
by auto
next
show "(λx. fst x ∪ snd x)  ({{}, {x}} × Pow X) = Pow (insert x X)"
proof (intro equalityI subsetI)
fix y
assume "y ∈ (λx. fst x ∪ snd x)  ({{}, {x}} × Pow X)"
from this obtain z where
"z ∈ ({{}, {x}} × Pow X)"
"y = fst z ∪ snd z"
by auto
hence
"snd z ⊆ X"
"fst z ⊆ insert x X"
using SigmaE by auto
thus "y ∈ Pow (insert x X)"
using ‹y = fst z ∪ snd z› by blast
next
fix y
assume "y ∈ Pow (insert x X)"
let ?z = "(if x ∈ y then {x} else {}, y - {x})"
have "?z ∈ ({{}, {x}} × Pow X)"
using ‹y ∈ Pow (insert x X)› by auto
moreover have "(λx. fst x ∪ snd x) ?z = y"
by auto
ultimately show "y ∈ (λx. fst x ∪ snd x)  ({{}, {x}} × Pow X)"
by blast
qed
qed
hence "card (Pow (insert x X)) = card ({{},{x}} × Pow X)"
using bij_betw_same_card by fastforce
also have "… = 2 * card (Pow X)"
also have "… = 2 * (2 powr (card X))"
also have "… = (2 powr 1) * 2 powr (card X)"
using two_powr_one
by fastforce
also have "… = 2 powr (1 + card X)"
also have "… = 2 powr (card (insert x X))"
finally show ?case .
qed

lemma (in finite_boolean_algebra) UNIV_card_powr_2:
"card (UNIV::'a set) = 2 powr (card 𝒥)"
using
finite [of 𝒥]
finite_Pow_card [of 𝒥]
UNIV_card
by linarith

lemma (in finite_boolean_algebra) join_irreducibles_card_log_2:
"card 𝒥 = log 2 (card (UNIV :: 'a set))"
proof (cases "card (UNIV :: 'a set) = 1")
case True
hence "∃ x :: 'a. UNIV = {x}"
using card_1_singletonE by blast
hence "∀ x y :: 'a. x ∈ UNIV ⟶ y ∈ UNIV ⟶ x = y"
by (metis (mono_tags) singletonD)
hence "∀ x y :: 'a. x = y"
by blast
hence "∀ x. x = ⊥"
by blast
hence "𝒥 = {}"
unfolding
join_irreducible_elements_def
join_irreducible_is_join_prime
join_prime_def
by blast
hence "card 𝒥 = (0 :: real)"
by simp
moreover
have "log 2 (card (UNIV :: 'a set)) = 0"
ultimately show ?thesis by auto
next
case False
hence "0 < 2 powr (card 𝒥)" "2 powr (card 𝒥) ≠ 1"
using finite_UNIV_card_ge_0 finite UNIV_card_powr_2
by (simp, linarith)
hence "log 2 (2 powr (card 𝒥)) = card 𝒥"
by simp
then show ?thesis
using UNIV_card_powr_2
by simp
qed

end
`