Theory Cardinality

theory Cardinality

imports "List-Infinite.InfiniteSet2" Representation

begin

context uminus
begin

no_notation uminus ("- _" [81] 80)

end

section ‹Atoms Below an Element in Partial Orders›

text ‹
We define the set and the number of atoms below an element in a partial order.
To handle infinitely many atoms we use enat›, which are natural numbers with infinity, and icard›, which modifies card› by giving a separate option of being infinite.
We include general results about enat›, icard›, sets functions and atoms.
›

lemma enat_mult_strict_mono:
  assumes "a < b" "c < d" "(0::enat) < b" "0  c"
  shows "a * c < b * d"
proof -
  have "a    c  "
    using assms(1,2) linorder_not_le by fastforce
  thus ?thesis
    using assms by (smt (verit, del_insts) enat_0_less_mult_iff idiff_eq_conv_enat ileI1 imult_ile_mono imult_is_infinity_enat less_eq_idiff_eq_sum less_le_not_le mult_eSuc_right order.strict_trans1 order_le_neq_trans zero_enat_def)
qed

lemma enat_mult_strict_mono':
  assumes "a < b" and "c < d" and "(0::enat)  a" and "0  c"
  shows "a * c < b * d"
  using assms by (auto simp add: enat_mult_strict_mono)

lemma finite_icard_card:
  "finite A  icard A = icard B  card A = card B"
  by (metis icard_def icard_eq_enat_imp_card)

lemma icard_eq_sum:
  "finite A  icard A = sum (λx. 1) A"
  by (simp add: icard_def of_nat_eq_enat)

lemma icard_sum_constant_function:
  assumes "xA . f x = c"
      and "finite A"
    shows "sum f A = (icard A) * c"
  by (metis assms icard_finite_conv of_nat_eq_enat sum.cong sum_constant)

lemma icard_le_finite:
  assumes "icard A  icard B"
      and "finite B"
    shows "finite A"
  by (metis assms enat_ord_simps(5) icard_infinite_conv)

lemma bij_betw_same_icard:
  "bij_betw f A B  icard A = icard B"
  by (simp add: bij_betw_finite bij_betw_same_card icard_def)

lemma surj_icard_le: "B  f ` A  icard B  icard A"
  by (meson icard_image_le icard_mono preorder_class.order_trans)

lemma icard_image_part_le:
  assumes "xA . f x  B"
      and "xA . f x  {}"
      and "xA . yA . x  y  f x  f y = {}"
    shows "icard A  icard B"
proof -
  have "xA . y . y  f x  B"
    using assms(1,2) by fastforce
  hence "g . xA . g x  f x  B"
    using bchoice by simp
  from this obtain g where 1: "xA . g x  f x  B"
    by auto
  hence "inj_on g A"
    by (metis Int_iff assms(3) empty_iff inj_onI)
  thus "icard A  icard B"
    using 1 icard_inj_on_le by fastforce
qed

lemma finite_image_part_le:
  assumes "xA . f x  B"
      and "xA . f x  {}"
      and "xA . yA . x  y  f x  f y = {}"
      and "finite B"
    shows "finite A"
  by (metis assms icard_image_part_le icard_le_finite)

context semiring_1
begin

lemma sum_constant_function:
  assumes "xA . f x = c"
    shows "sum f A = of_nat (card A) * c"
proof (cases "finite A")
  case True
  show ?thesis
  proof (rule finite_subset_induct)
    show "finite A"
      using True by simp
    show "A  A"
      by simp
    show "sum f {} = of_nat (card {}) * c"
      by simp
    fix a F
    assume "finite F" "a  A" "a  F" "sum f F = of_nat (card F) * c"
    thus "sum f (insert a F) = of_nat (card (insert a F)) * c"
      using assms by (metis sum.insert sum_constant)
  qed
next
  case False
  thus ?thesis
    by simp
qed

end

context order
begin

lemma ne_finite_has_minimal:
  assumes "finite S"
      and "S  {}"
    shows "mS . xS . x  m  x = m"
proof (rule finite_ne_induct)
  show "finite S"
    using assms(1) by simp
  show "S  {}"
    using assms(2) by simp
  show "x . m{x}. y{x}. y  m  y = m"
    by auto
  show "x F . finite F  F  {}  x  F  (mF . yF . y  m  y = m)  (minsert x F . yinsert x F . y  m  y = m)"
    by (metis finite_insert insert_not_empty finite_has_minimal)
qed

end

context order_bot
begin

abbreviation atoms_below :: "'a  'a set" ("AB")
  where "atoms_below x  { a . atom a  a  x }"

definition num_atoms_below :: "'a  enat" ("nAB")
  where "num_atoms_below x  icard (atoms_below x)"

lemma AB_iso:
  "x  y  AB x  AB y"
  by (simp add: Collect_mono dual_order.trans)

lemma AB_bot:
  "AB bot = {}"
  by (simp add: bot_unique)

lemma nAB_bot:
  "nAB bot = 0"
proof -
  have "nAB bot = icard (AB bot)"
    by (simp add: num_atoms_below_def)
  also have "... = 0"
    by (metis (mono_tags, lifting) AB_bot icard_empty)
  finally show ?thesis
    .
qed

lemma AB_atom:
  "atom a  AB a = {a}"
  by blast

lemma nAB_atom:
  "atom a  nAB a = 1"
proof -
  assume "atom a"
  hence "AB a = {a}"
    using AB_atom by meson
  thus "nAB a = 1"
    by (simp add: num_atoms_below_def one_eSuc)
qed

lemma nAB_iso:
  "x  y  nAB x  nAB y"
  using icard_mono AB_iso num_atoms_below_def by auto

end

context bounded_semilattice_sup_bot
begin

lemma nAB_iso_sup:
  "nAB x  nAB (x  y)"
  by (simp add: nAB_iso)

end

context bounded_lattice
begin

lemma different_atoms_disjoint:
  "atom x  atom y  x  y  x  y = bot"
  using inf_le1 le_iff_inf by auto

lemma AB_dist_inf:
  "AB (x  y) = AB x  AB y"
  by auto

lemma AB_iso_inf:
  "AB (x  y)  AB x"
  by (simp add: Collect_mono)

lemma AB_iso_sup:
  "AB x  AB (x  y)"
  by (simp add: Collect_mono le_supI1)

lemma AB_disjoint:
  assumes "x  y = bot"
    shows "AB x  AB y = {}"
proof (rule Int_emptyI)
  fix a
  assume "a  AB x" "a  AB y"
  hence "atom a  a  x  a  y"
    by simp
  thus False
    using assms bot_unique by fastforce
qed

lemma nAB_iso_inf:
  "nAB (x  y)  nAB x"
  by (simp add: nAB_iso)

end

context distrib_lattice_bot
begin

lemma atom_in_sup:
  assumes "atom a"
      and "a  x  y"
    shows "a  x  a  y"
proof -
  have 1: "a = (a  x)  (a  y)"
    using assms(2) inf_sup_distrib1 le_iff_inf by force
  have "a  x = bot  a  x = a"
    using assms(1) by fastforce
  thus ?thesis
    using 1 le_iff_inf sup_bot_left by fastforce
qed

lemma atom_in_sup_iff:
  assumes "atom a"
    shows "a  x  y  a  x  a  y"
  using assms atom_in_sup le_supI1 le_supI2 by blast

lemma atom_in_sup_xor:
  "atom a  a  x  y  x  y = bot  (a  x  ¬ a  y)  (¬ a  x  a  y)"
  using atom_in_sup bot_unique le_inf_iff by blast

lemma atom_in_sup_xor_iff:
  assumes "atom a"
      and "x  y = bot"
    shows "a  x  y  (a  x  ¬ a  y)  (¬ a  x  a  y)"
  using assms atom_in_sup_xor le_supI1 le_supI2 by auto

lemma AB_dist_sup:
  "AB (x  y) = AB x  AB y"
proof
  show "AB (x  y)  AB x  AB y"
    using atom_in_sup by fastforce
next
  show "AB x  AB y  AB (x  y)"
    using le_supI1 le_supI2 by fastforce
qed

end

context bounded_distrib_lattice
begin

lemma nAB_add:
  "nAB x + nAB y = nAB (x  y) + nAB (x  y)"
proof -
  have "nAB x + nAB y = icard (AB x  AB y) + icard (AB x  AB y)"
    using num_atoms_below_def icard_Un_Int by auto
  also have "... = nAB (x  y) + nAB (x  y)"
    using num_atoms_below_def AB_dist_inf AB_dist_sup by auto
  finally show ?thesis
    .
qed

lemma nAB_split_disjoint:
  assumes "x  y = bot"
    shows "nAB (x  y) = nAB x + nAB y"
  by (simp add: assms nAB_add nAB_bot)

end

context p_algebra
begin

lemma atom_in_p:
  "atom a  a  x  a  -x"
  using inf.orderI pseudo_complement by force

lemma atom_in_p_xor:
  "atom a  (a  x  ¬ a  -x)  (¬ a  x  a  -x)"
  by (metis atom_in_p le_iff_inf pseudo_complement)

text ‹
The following two lemmas also hold in distributive lattices with a least element (see above).
However, p-algebras are not necessarily distributive, so the following results are indepenent.
›

lemma atom_in_sup':
  "atom a  a  x  y  a  x  a  y"
  by (metis inf.absorb_iff2 inf.sup_ge2 pseudo_complement sup_least)

lemma AB_dist_sup':
  "AB (x  y) = AB x  AB y"
proof
  show "AB (x  y)  AB x  AB y"
    using atom_in_sup' by fastforce
next
  show "AB x  AB y  AB (x  y)"
    using le_supI1 le_supI2 by fastforce
qed

lemma AB_split_1:
  "AB x = AB ((x  y)  (x  -y))"
proof
  show "AB x  AB ((x  y)  (x  -y))"
  proof
    fix a
    assume "a  AB x"
    hence "atom a  a  x"
      by simp
    hence "atom a  a  (x  y)  (x  -y)"
      by (metis atom_in_p_xor inf.boundedI le_supI1 le_supI2)
    thus "a  AB ((x  y)  (x  -y))"
      by simp
  qed
next
  show "AB ((x  y)  (x  -y))  AB x"
    using atom_in_sup' inf.boundedE by blast
qed

lemma AB_split_2:
  "AB x = AB (x  y)  AB (x  -y)"
  using AB_dist_sup' AB_split_1 by auto

lemma AB_split_2_disjoint:
  "AB (x  y)  AB (x  -y) = {}"
  using atom_in_p_xor by fastforce

lemma AB_pp:
  "AB (--x) = AB x"
  by (metis (opaque_lifting) atom_in_p_xor)

lemma nAB_pp:
  "nAB (--x) = nAB x"
  using AB_pp num_atoms_below_def by auto

lemma nAB_split_1:
  "nAB x = nAB ((x  y)  (x  - y))"
  using AB_split_1 num_atoms_below_def by simp

lemma nAB_split_2:
  "nAB x = nAB (x  y) + nAB (x  -y)"
proof -
  have "icard (AB (x  y)) + icard (AB (x  -y)) = icard (AB (x  y)  AB (x  -y)) + icard (AB (x  y)  AB (x  -y))"
    using icard_Un_Int by auto
  also have "... = icard (AB x)"
    using AB_split_2 AB_split_2_disjoint by auto
  finally show ?thesis
    using num_atoms_below_def by auto
qed

end

section ‹Atoms Below an Element in Stone Relation Algebras›

text ‹
We extend our study of atoms below an element to Stone relation algebras.
We consider combinations of the following five assumptions: the Stone relation algebra is atomic, atom-rectangular, atom-simple, a relation algebra, or has finitely many atoms.
We include general properties of atoms, rectangles and simple elements.
›

context stone_relation_algebra
begin

abbreviation rectangle :: "'a  bool" where "rectangle x  x * top * x  x"
abbreviation simple    :: "'a  bool" where "simple x     top * x * top = top"

lemma rectangle_eq:
  "rectangle x  x * top * x = x"
  by (simp add: order.eq_iff ex231d)

lemma arc_univalent_injective_rectangle_simple:
  "arc a  univalent a  injective a  rectangle a  simple a"
  by (smt (z3) arc_top_arc comp_associative conv_dist_comp conv_involutive ideal_top_closed surjective_vector_top rectangle_eq)

lemma conv_atom:
  "atom x  atom (xT)"
  by (metis conv_involutive conv_isotone symmetric_bot_closed)

lemma conv_atom_iff:
  "atom x  atom (xT)"
  by (metis conv_atom conv_involutive)

lemma counterexample_different_atoms_top_disjoint:
  "atom x  atom y  x  y  x * top  y = bot"
  nitpick[expect=genuine,card=4]
  oops

lemma counterexample_different_univalent_atoms_top_disjoint:
  "atom x  univalent x  atom y  univalent y  x  y  x * top  y = bot"
  nitpick[expect=genuine,card=4]
  oops

lemma AB_card_4_1:
  "a  x  a  y  a  x  y  a  x  y"
  using le_supI1 by auto

lemma AB_card_4_2:
  assumes "atom a"
    shows "(a  x  ¬ a  y)  (¬ a  x  a  y)  a  x  y  ¬ a  x  y"
  using assms atom_in_sup le_supI1 le_supI2 by auto

lemma AB_card_4_3:
  assumes "atom a"
    shows "¬ a  x  ¬ a  y  ¬ a  x  y  ¬ a  x  y"
  using assms AB_card_4_2 by auto

lemma AB_card_5_1:
  assumes "atom a"
      and "a  xT * y  z"
    shows "x * a  y  x * z  y"
      and "x * a  y  bot"
proof -
  show "x * a  y  x * z  y"
    using assms(2) comp_inf.mult_left_isotone mult_right_isotone by auto
  show "x * a  y  bot"
    by (smt assms inf.left_commute inf.left_idem inf_absorb1 schroeder_1)
qed

lemma AB_card_5_2:
  assumes "univalent x"
      and "atom a"
      and "atom b"
      and "b  xT * y  z"
      and "a  b"
    shows "(x * a  y)  (x * b  y) = bot"
      and "x * a  y  x * b  y"
proof -
  show "(x * a  y)  (x * b  y) = bot"
    by (metis assms(1-3,5) comp_inf.semiring.mult_zero_left inf.cobounded1 inf.left_commute inf.sup_monoid.add_commute semiring.mult_not_zero univalent_comp_left_dist_inf)
  thus "x * a  y  x * b  y"
    using AB_card_5_1(2) assms(3,4) by fastforce
qed

lemma AB_card_6_0:
  assumes "univalent x"
      and "atom a"
      and "a  x"
      and "atom b"
      and "b  x"
      and "a  b"
    shows "a * top  b * top = bot"
proof -
  have "aT * b  1"
    by (meson assms(1,3,5) comp_isotone conv_isotone dual_order.trans)
  hence "a * top  b = bot"
    by (metis assms(2,4,6) comp_inf.semiring.mult_zero_left comp_right_one inf.cobounded1 inf.cobounded2 inf.orderE schroeder_1)
  thus ?thesis
    using vector_bot_closed vector_export_comp by force
qed

lemma AB_card_6_1:
  assumes "atom a"
      and "a  x  y * zT"
    shows "a * z  y  x * z  y"
      and "a * z  y  bot"
proof -
  show "a * z  y  x * z  y"
    using assms(2) inf.sup_left_isotone mult_left_isotone by auto
  show "a * z  y  bot"
    by (metis assms inf.absorb2 inf.boundedE schroeder_2)
qed

lemma AB_card_6_2:
  assumes "univalent x"
      and "atom a"
      and "a  x  y * zT"
      and "atom b"
      and "b  x  y * zT"
      and "a  b"
    shows "(a * z  y)  (b * z  y) = bot"
      and "a * z  y  b * z  y"
proof -
  have "(a * z  y)  (b * z  y)  a * top  b * top"
    by (meson comp_inf.comp_isotone comp_inf.ex231d inf.boundedE mult_right_isotone)
  also have "... = bot"
    using AB_card_6_0 assms by force
  finally show "(a * z  y)  (b * z  y) = bot"
    using le_bot by blast
  thus "a * z  y  b * z  y"
    using AB_card_6_1(2) assms(4,5) by fastforce
qed

lemma nAB_conv:
  "nAB x = nAB (xT)"
proof (unfold num_atoms_below_def, rule bij_betw_same_icard)
  show "bij_betw conv (AB x) (AB (xT))"
  proof (unfold bij_betw_def, rule conjI)
    show "inj_on conv (AB x)"
      by (metis (mono_tags, lifting) inj_onI conv_involutive)
    show "conv ` AB x = AB (xT)"
    proof
      show "conv ` AB x  AB (xT)"
        using conv_atom_iff conv_isotone by force
      show "AB (xT)  conv ` AB x"
      proof
        fix y
        assume "y  AB (xT)"
        hence "atom y  y  xT"
          by auto
        hence "atom (yT)  yT  x"
          using conv_atom_iff conv_order by force
        hence "yT  AB x"
          by auto
        thus "y  conv ` AB x"
          by (metis (no_types, lifting) image_iff conv_involutive)
      qed
    qed
  qed
qed

lemma domain_atom:
  assumes "atom a"
    shows "atom (a * top  1)"
proof
  show "a * top  1  bot"
    by (metis assms domain_vector_conv ex231a inf_vector_comp mult_left_zero vector_export_comp_unit)
next
  show "y. y  bot  y  a * top  1  y = a * top  1"
  proof (rule allI, rule impI)
    fix y
    assume 1: "y  bot  y  a * top  1"
    hence 2: "y = 1  y * a * top"
      using dedekind_injective comp_associative coreflexive_idempotent coreflexive_symmetric inf.absorb2 inf.sup_monoid.add_commute by auto
    hence "y * a  bot"
      using 1 comp_inf.semiring.mult_zero_right vector_bot_closed by force
    hence "a = y * a"
      using 1 by (metis assms comp_right_one coreflexive_comp_top_inf inf.boundedE mult_sub_right_one)
    thus "y = a * top  1"
      using 2 inf.sup_monoid.add_commute by auto
  qed
qed

lemma codomain_atom:
  assumes "atom a"
    shows "atom (top * a  1)"
proof -
  have "top * a  1 = aT * top  1"
    by (simp add: domain_vector_covector inf.sup_monoid.add_commute)
  thus ?thesis
    using domain_atom conv_atom assms by auto
qed

lemma atom_rectangle_atom_one_rep:
  "(a . atom a  a * top * a  a)  (a . atom a  a  1  a * top * a  1)"
proof
  assume "a . atom a  a * top * a  a"
  thus "a . atom a  a  1  a * top * a  1"
    by auto
next
  assume 1: "a . atom a  a  1  a * top * a  1"
  show "a . atom a  a * top * a  a"
  proof (rule allI, rule impI)
    fix a
    assume "atom a"
    hence "atom (a * top  1)"
      by (simp add: domain_atom)
    hence "(a * top  1) * top * (a * top  1)  1"
      using 1 by simp
    hence "a * top * aT  1"
      by (smt comp_associative conv_dist_comp coreflexive_symmetric ex231e inf_top.right_neutral symmetric_top_closed vector_export_comp_unit)
    thus "a * top * a  a"
      by (smt comp_associative conv_dist_comp domain_vector_conv order.eq_iff ex231e inf.absorb2 inf.sup_monoid.add_commute mapping_one_closed symmetric_top_closed top_right_mult_increasing vector_export_comp_unit)
  qed
qed

lemma AB_card_2_1:
  assumes "a * top * a  a"
    shows "(a * top  1) * top * (top * a  1) = a"
  by (metis assms comp_inf.vector_top_closed covector_comp_inf ex231d order.antisym inf_commute surjective_one_closed vector_export_comp_unit vector_top_closed mult_assoc)

lemma atomsimple_atom1simple:
  "(a . atom a  top * a * top = top)  (a . atom a  a  1  top * a * top = top)"
proof
  assume "a . atom a  top * a * top = top"
  thus "a . atom a  a  1  top * a * top = top"
    by simp
next
  assume 1: "a . atom a  a  1  top * a * top = top"
  show "a . atom a  top * a * top = top"
  proof (rule allI, rule impI)
    fix a
    assume "atom a"
    hence 2: "atom (a * top  1)"
      by (simp add: domain_atom)
    have "top * (a * top  1) * top = top * a * top"
      using comp_associative vector_export_comp_unit by auto
    thus "top * a * top = top"
      using 1 2 by auto
  qed
qed

lemma AB_card_2_2:
  assumes "atom a"
      and "a  1"
      and "atom b"
      and "b  1"
      and "a . atom a  top * a * top = top"
    shows "a * top * b * top  1 = a" and "top * a * top * b  1 = b"
proof -
  show "a * top * b * top  1 = a"
    using assms(2,3,5) comp_associative coreflexive_comp_top_inf_one by auto
  show "top * a * top * b  1 = b"
    using assms(1,4,5) epm_3 inf.sup_monoid.add_commute by auto
qed

abbreviation dom_cod :: "'a  'a × 'a"
  where "dom_cod a  (a * top  1, top * a  1)"

lemma dom_cod_atoms_1:
  "dom_cod ` AB top  AB 1 × AB 1"
proof
  fix x
  assume "x  dom_cod ` AB top"
  from this obtain a where 1: "atom a  x = dom_cod a"
    by auto
  hence "a * top  1  AB 1  top * a  1  AB 1"
    using domain_atom codomain_atom by auto
  thus "x  AB 1 × AB 1"
    using 1 by auto
qed

end

class stone_relation_algebra_simple = stone_relation_algebra +
  assumes simple: "x  bot  simple x"
begin

lemma point_ideal_point:
  "point x  ideal_point x"
  using simple by fastforce

end

subsection ‹Atomic›

class stone_relation_algebra_atomic = stone_relation_algebra +
  assumes atomic: "x  bot  (a . atom a  a  x)"
begin

lemma AB_nonempty:
  "x  bot  AB x  {}"
  using atomic by fastforce

lemma AB_nonempty_iff:
  "x  bot  AB x  {}"
  using AB_nonempty AB_bot by blast

lemma atomsimple_simple:
  "(a . a  bot  top * a * top = top)  (a . atom a  top * a * top = top)"
proof
  assume "a . a  bot  top * a * top = top"
  thus "a . atom a  top * a * top = top"
    by simp
next
  assume 1: "a . atom a  top * a * top = top"
  show "a . a  bot  top * a * top = top"
  proof (rule allI, rule impI)
    fix a
    assume "a  bot"
    from this atomic obtain b where 2: "atom b  b  a"
      by auto
    hence "top * b * top = top"
      using 1 by auto
    thus "top * a * top = top"
      using 2 by (metis order.antisym mult_left_isotone mult_right_isotone top.extremum)
  qed
qed

lemma AB_card_2_3:
  assumes "a  bot"
      and "a  1"
      and "b  bot"
      and "b  1"
      and "a . a  bot  top * a * top = top"
    shows "a * top * b * top  1 = a" and "top * a * top * b  1 = b"
proof -
  show "a * top * b * top  1 = a"
    using assms(2,3,5) comp_associative coreflexive_comp_top_inf_one by auto
  show "top * a * top * b  1 = b"
    using assms(1,4,5) epm_3 inf.sup_monoid.add_commute by auto
qed

lemma injective_down_closed:
  "x  y  injective y  injective x"
  using conv_isotone mult_isotone by fastforce

lemma univalent_down_closed:
  "x  y  univalent y  univalent x"
  using conv_isotone mult_isotone by fastforce

lemma nAB_bot_iff:
  "x = bot  nAB x = 0"
  by (smt (verit, best) icard_0_eq AB_nonempty_iff num_atoms_below_def)

text ‹
It is unclear if atomic› is necessary for the following two results, but it seems likely.
›

lemma nAB_univ_comp_meet:
  assumes "univalent x"
    shows "nAB (xT * y  z)  nAB (x * z  y)"
proof (unfold num_atoms_below_def, rule icard_image_part_le)
  show "a  AB (xT * y  z) . AB (x * a  y)  AB (x * z  y)"
  proof
    fix a
    assume "a  AB (xT * y  z)"
    hence "x * a  y  x * z  y"
      using AB_card_5_1(1) by auto
    thus "AB (x * a  y)  AB (x * z  y)"
      using AB_iso by blast
  qed
next
  show "a  AB (xT * y  z) . AB (x * a  y)  {}"
  proof
    fix a
    assume "a  AB (xT * y  z)"
    hence "x * a  y  bot"
      using AB_card_5_1(2) by auto
    thus "AB (x * a  y)  {}"
      using atomic by fastforce
  qed
next
  show "a  AB (xT * y  z) . b  AB (xT * y  z) . a  b  AB (x * a  y)  AB (x * b  y) = {}"
  proof (intro ballI, rule impI)
    fix a b
    assume "a  AB (xT * y  z)" "b  AB (xT * y  z)" "a  b"
    hence "(x * a  y)  (x * b  y) = bot"
      using assms AB_card_5_2(1) by auto
    thus "AB (x * a  y)  AB (x * b  y) = {}"
      using AB_bot AB_dist_inf by blast
  qed
qed

lemma nAB_univ_meet_comp:
  assumes "univalent x"
    shows "nAB (x  y * zT)  nAB (x * z  y)"
proof (unfold num_atoms_below_def, rule icard_image_part_le)
  show "a  AB (x  y * zT) . AB (a * z  y)  AB (x * z  y)"
  proof
    fix a
    assume "a  AB (x  y * zT)"
    hence "a * z  y  x * z  y"
      using AB_card_6_1(1) by auto
    thus "AB (a * z  y)  AB (x * z  y)"
      using AB_iso by blast
  qed
next
  show "a  AB (x  y * zT) . AB (a * z  y)  {}"
  proof
    fix a
    assume "a  AB (x  y * zT)"
    hence "a * z  y  bot"
      using AB_card_6_1(2) by auto
    thus "AB (a * z  y)  {}"
      using atomic by fastforce
  qed
next
  show "a  AB (x  y * zT) . b  AB (x  y * zT) . a  b  AB (a * z  y)  AB (b * z  y) = {}"
  proof (intro ballI, rule impI)
    fix a b
    assume "a  AB (x  y * zT)" "b  AB (x  y * zT)" "a  b"
    hence "(a * z  y)  (b * z  y) = bot"
      using assms AB_card_6_2(1) by auto
    thus "AB (a * z  y)  AB (b * z  y) = {}"
      using AB_bot AB_dist_inf by blast
  qed
qed

end

subsection ‹Atom-rectangular›

class stone_relation_algebra_atomrect = stone_relation_algebra +
  assumes atomrect: "atom a  rectangle a"
begin

lemma atomrect_eq:
  "atom a  a * top * a = a"
  by (simp add: order.antisym ex231d atomrect)

lemma AB_card_2_4:
  assumes "atom a"
    shows "(a * top  1) * top * (top * a  1) = a"
  by (simp add: assms AB_card_2_1 atomrect)

lemma simple_atom_2:
  assumes "atom a"
      and "a  1"
      and "atom b"
      and "b  1"
      and "x  bot"
      and "x  a * top * b"
    shows "x = a * top * b"
proof -
  have 1: "x * top  1  bot"
    by (metis assms(5) inf_top_right le_bot top_right_mult_increasing vector_bot_closed vector_export_comp_unit)
  have "x * top  1  a * top * b * top  1"
    using assms(6) comp_inf.comp_isotone comp_isotone by blast
  also have "...  a * top  1"
    by (metis comp_associative comp_inf.mult_right_isotone inf.sup_monoid.add_commute mult_right_isotone top.extremum)
  also have "... = a"
    by (simp add: assms(2) coreflexive_comp_top_inf_one)
  finally have 2: "x * top  1 = a"
    using 1 by (simp add: assms(1) domain_atom)
  have 3: "top * x  1  bot"
    using 1 by (metis schroeder_1 schroeder_2 surjective_one_closed symmetric_top_closed total_one_closed)
  have "top * x  1  top * a * top * b  1"
    by (metis assms(6) comp_associative comp_inf.comp_isotone mult_right_isotone reflexive_one_closed)
  also have "...  top * b  1"
    using inf.sup_mono mult_left_isotone top_greatest by blast
  also have "... = b"
    using assms(4) epm_3 inf.sup_monoid.add_commute by auto
  finally have "top * x  1 = b"
    using 3 by (simp add: assms(3) codomain_atom)
  hence "a * top * b = x * top * x"
    using 2 by (smt abel_semigroup.commute covector_comp_inf inf.abel_semigroup_axioms inf_top_right surjective_one_closed vector_export_comp_unit vector_top_closed mult_assoc)
  also have "... = a * top * b * top * (x  a * top * b)"
    using assms(6) calculation inf_absorb1 by auto
  also have "...  a * top * (x  a * top * b)"
    by (metis comp_associative comp_inf_covector inf.idem inf.order_iff mult_right_isotone)
  also have "...  a * top * (x  a * top)"
    using comp_associative comp_inf.mult_right_isotone mult_right_isotone by auto
  also have "... = a * top * aT * x"
    by (metis comp_associative comp_inf_vector inf_top.left_neutral)
  also have "... = a * top * a * x"
    by (simp add: assms(2) coreflexive_symmetric)
  also have "... = a * x"
    by (simp add: assms(1) atomrect_eq)
  also have "...  x"
    using assms(2) mult_left_isotone by fastforce
  finally show ?thesis
    using assms(6) order.antisym by blast
qed

lemma dom_cod_inj_atoms:
  "inj_on dom_cod (AB top)"
proof
  fix a b
  assume 1: "a  AB top" "b  AB top" "dom_cod a = dom_cod b"
  have "a = a * top * a"
    using 1 atomrect_eq by auto
  also have "... = (a * top  1) * top * (top * a  1)"
    using calculation AB_card_2_1 by auto
  also have "... = (b * top  1) * top * (top * b  1)"
    using 1 by simp
  also have "... = b * top * b"
    using abel_semigroup.commute comp_inf_covector inf.abel_semigroup_axioms vector_export_comp_unit mult_assoc by fastforce
  also have "... = b"
    using 1 atomrect_eq by auto
  finally show "a = b"
    .
qed

lemma finite_AB_iff:
  "finite (AB top)  finite (AB 1)"
proof
  have "AB 1  AB top"
    by auto
  thus "finite (AB top)  finite (AB 1)"
    by (meson finite_subset)
next
  assume 1: "finite (AB 1)"
  show "finite (AB top)"
  proof (rule inj_on_finite)
    show "inj_on dom_cod (AB top)"
      using dom_cod_inj_atoms by blast
    show "dom_cod ` AB top  AB 1 × AB 1"
      using dom_cod_atoms_1 by blast
    show "finite (AB 1 × AB 1)"
      using 1 by blast
  qed
qed

lemma nAB_top_1:
  "nAB top  nAB 1 * nAB 1"
proof (unfold num_atoms_below_def icard_cartesian_product[THEN sym], rule icard_inj_on_le)
  show "inj_on dom_cod (AB top)"
    using dom_cod_inj_atoms by blast
  show "dom_cod ` AB top  AB 1 × AB 1"
    using dom_cod_atoms_1 by blast
qed

lemma atom_vector_injective:
  assumes "atom x"
    shows "injective (x * top)"
proof -
  have "atom (x * top  1)"
    by (simp add: assms domain_atom)
  hence "(x * top  1) * top * (x * top  1)  1"
    using atom_rectangle_atom_one_rep atomrect by auto
  hence "x * top * xT  1"
    by (smt comp_associative conv_dist_comp coreflexive_symmetric ex231e inf_top.right_neutral symmetric_top_closed vector_export_comp_unit)
  thus "injective (x * top)"
    by (metis comp_associative conv_dist_comp symmetric_top_closed vector_top_closed)
qed

lemma atom_injective:
  "atom x  injective x"
  by (metis atom_vector_injective comp_associative conv_dist_comp dual_order.trans mult_right_isotone symmetric_top_closed top_left_mult_increasing)

lemma atom_covector_univalent:
  "atom x  univalent (top * x)"
  by (metis comp_associative conv_involutive atom_vector_injective conv_atom_iff conv_dist_comp symmetric_top_closed)

lemma atom_univalent:
  "atom x  univalent x"
  using atom_injective conv_atom_iff univalent_conv_injective by blast

lemma counterexample_atom_simple:
  "atom x  simple x"
  nitpick[expect=genuine,card=3]
  oops

lemma symmetric_atom_below_1:
  assumes "atom x"
      and "x = xT"
    shows "x  1"
proof -
  have "x = x * top * xT"
    using assms atomrect_eq by auto
  also have "...  1"
    by (metis assms(1) atom_vector_injective conv_dist_comp equivalence_top_closed ideal_top_closed mult_assoc)
  finally show ?thesis
    .
qed

end

subsection ‹Atomic and Atom-Rectangular›

class stone_relation_algebra_atomic_atomrect = stone_relation_algebra_atomic + stone_relation_algebra_atomrect
begin

lemma point_dense:
  assumes "x  bot"
      and "x  1"
    shows "a . a  bot  a * top * a  1  a  x"
proof -
  from atomic obtain a where 1: "atom a  a  x"
    using assms(1) by auto
  hence "a * top * a  a"
    by (simp add: atomrect)
  also have "...  1"
    using 1 assms(2) order_trans by blast
  finally show ?thesis
    using 1 by blast
qed

end

subsection ‹Atom-simple›

class stone_relation_algebra_atomsimple = stone_relation_algebra +
  assumes atomsimple: "atom a  simple a"
begin

lemma AB_card_2_5:
  assumes "atom a"
      and "a  1"
      and "atom b"
      and "b  1"
    shows "a * top * b * top  1 = a" and "top * a * top * b  1 = b"
  using assms AB_card_2_2 atomsimple by auto

lemma simple_atom_1:
  "atom a  atom b  a * top * b  bot"
  by (metis order.antisym atomsimple bot_least comp_associative mult_left_zero top_right_mult_increasing)

end

subsection ‹Atomic and Atom-simple›

class stone_relation_algebra_atomic_atomsimple = stone_relation_algebra_atomic + stone_relation_algebra_atomsimple
begin

subclass stone_relation_algebra_simple
  apply unfold_locales
  using atomsimple atomsimple_simple by blast

lemma AB_card_2_6:
  assumes "a  bot"
      and "a  1"
      and "b  bot"
      and "b  1"
    shows "a * top * b * top  1 = a" and "top * a * top * b  1 = b"
  using assms AB_card_2_3 simple atomsimple_simple by auto

lemma dom_cod_atoms_2:
  "AB 1 × AB 1  dom_cod ` AB top"
proof
  fix x
  assume "x  AB 1 × AB 1"
  from this obtain a b where 1: "atom a  a  1  atom b  b  1  x = (a,b)"
    by auto
  hence "a * top * b  bot"
    by (simp add: simple_atom_1)
  from this obtain c where 2: "atom c  c  a * top * b"
    using atomic by blast
  hence "c * top  1  a * top  1"
    by (smt comp_inf.comp_isotone inf.boundedE inf.orderE inf_vector_comp reflexive_one_closed top_right_mult_increasing)
  also have "... = a"
    using 1 by (simp add: coreflexive_comp_top_inf_one)
  finally have 3: "c * top  1 = a"
    using 1 2 domain_atom by simp
  have "top * c  top * b"
    using 2 3 by (smt comp_associative comp_inf.reflexive_top_closed comp_inf.vector_top_closed comp_inf_covector comp_isotone simple vector_export_comp_unit)
  hence "top * c  1  b"
    using 1 by (smt epm_3 inf.cobounded1 inf.left_commute inf.orderE injective_one_closed reflexive_one_closed)
  hence "top * c  1 = b"
    using 1 2 codomain_atom by simp
  hence "dom_cod c = x"
    using 1 3 by simp
  thus "x  dom_cod ` AB top"
    using 2 by auto
qed

lemma dom_cod_atoms:
  "AB 1 × AB 1 = dom_cod ` AB top"
  using dom_cod_atoms_2 dom_cod_atoms_1 by blast

end

subsection ‹Atom-rectangular and Atom-simple›

class stone_relation_algebra_atomrect_atomsimple = stone_relation_algebra_atomrect + stone_relation_algebra_atomsimple
begin

lemma simple_atom:
  assumes "atom a"
      and "a  1"
      and "atom b"
      and "b  1"
    shows "atom (a * top * b)"
  using assms simple_atom_1 simple_atom_2 by auto

lemma nAB_top_2:
  "nAB 1 * nAB 1  nAB top"
proof (unfold num_atoms_below_def icard_cartesian_product[THEN sym], rule icard_inj_on_le)
  let ?f = "λ(a,b) . a * top * b"
  show "inj_on ?f (AB 1 × AB 1)"
  proof
    fix x y
    assume "x  AB 1 × AB 1" "y  AB 1 × AB 1"
    from this obtain a b c d where 1: "atom a  a  1  atom b  b  1  x = (a,b)  atom c  c  1  atom d  d  1  y = (c,d)"
      by auto
    assume "?f x = ?f y"
    hence 2: "a * top * b = c * top * d"
      using 1 by auto
    hence 3: "a = c"
      using 1 by (smt atomsimple comp_associative coreflexive_comp_top_inf_one)
    have "b = d"
      using 1 2 by (smt atomsimple comp_associative epm_3 injective_one_closed)
    thus "x = y"
      using 1 3 by simp
  qed
  show "?f ` (AB 1 × AB 1)  AB top"
  proof
    fix x
    assume "x  ?f ` (AB 1 × AB 1)"
    from this obtain a b where 4: "atom a  a  1  atom b  b  1  x = a * top * b"
      by auto
    hence "a * top * b  AB top"
      using simple_atom by simp
    thus "x  AB top"
      using 4 by simp
  qed
qed

lemma nAB_top:
  "nAB 1 * nAB 1 = nAB top"
  using nAB_top_1 nAB_top_2 by auto

lemma atom_covector_mapping:
  "atom a  mapping (top * a)"
  using atom_covector_univalent atomsimple by blast

lemma atom_covector_regular:
  "atom a  regular (top * a)"
  by (simp add: atom_covector_mapping mapping_regular)

lemma atom_vector_bijective:
  "atom a  bijective (a * top)"
  using atom_vector_injective comp_associative atomsimple by auto

lemma atom_vector_regular:
  "atom a  regular (a * top)"
  by (simp add: atom_vector_bijective bijective_regular)

lemma atom_rectangle_regular:
  "atom a  regular (a * top * a)"
  by (smt atom_covector_regular atom_vector_regular comp_associative pp_dist_comp regular_closed_top)

lemma atom_regular:
  "atom a  regular a"
  using atom_rectangle_regular atomrect_eq by auto

end

subsection ‹Atomic, Atom-rectangular and Atom-simple›

class stone_relation_algebra_atomic_atomrect_atomsimple = stone_relation_algebra_atomic + stone_relation_algebra_atomrect + stone_relation_algebra_atomsimple
begin

subclass stone_relation_algebra_atomic_atomrect ..
subclass stone_relation_algebra_atomic_atomsimple ..
subclass stone_relation_algebra_atomrect_atomsimple ..

lemma nAB_atom_iff:
  "atom a  nAB a = 1"
proof
  assume "atom a"
  thus "nAB a = 1"
    by (simp add: nAB_atom)
next
  assume "nAB a = 1"
  from this obtain b where 1: "AB a = {b}"
    using icard_1_imp_singleton num_atoms_below_def one_eSuc by fastforce
  hence 2: "atom b  b  a"
    by auto
  hence 3: "AB (a  b) = {b}"
    by fastforce
  have "AB (a  b)  AB (a  -b) = AB a  AB (a  b)  AB (a  -b) = {}"
    using AB_split_2 AB_split_2_disjoint by simp
  hence "{b}  AB (a  -b) = {b}  {b}  AB (a  -b) = {}"
    using 1 3 by simp
  hence "AB (a  -b) = {}"
    by auto
  hence "a  -b = bot"
    using AB_nonempty_iff by blast
  hence "a  b"
    using 2 atom_regular pseudo_complement by auto
  thus "atom a"
    using 2 by auto
qed

end

subsection ‹Finitely Many Atoms›

class stone_relation_algebra_finiteatoms = stone_relation_algebra +
  assumes finiteatoms: "finite { a . atom a }"
begin

lemma finite_AB:
  "finite (AB x)"
  using finite_Collect_conjI finiteatoms by force

lemma nAB_top_finite:
  "nAB top  "
  by (smt (verit, best) finite_AB icard_infinite_conv num_atoms_below_def)

end

subsection ‹Atomic and Finitely Many Atoms›

class stone_relation_algebra_atomic_finiteatoms = stone_relation_algebra_atomic + stone_relation_algebra_finiteatoms
begin

lemma finite_ideal_points:
  "finite { p . ideal_point p }"
proof (cases "bot = top")
  case True
  hence "p . ideal_point p  p = bot"
    using le_bot top.extremum by blast
  hence "{ p . ideal_point p }  {bot}"
    by auto
  thus ?thesis
    using finite_subset by auto
next
  case False
  let ?p = "{ p . ideal_point p }"
  show 0: "finite ?p"
  proof (rule finite_image_part_le)
    show "x?p . AB x  AB top"
      using top.extremum by auto
    have "x?p . x  bot"
      using False by auto
    thus "x?p . AB x  {}"
      using AB_nonempty by auto
    show "x?p . y?p . x  y  AB x  AB y = {}"
    proof (intro ballI, rule impI, rule ccontr)
      fix x y
      assume "x  ?p" "y  ?p" "x  y"
      hence 1: "x  y = bot"
        by (simp add: different_ideal_points_disjoint)
      assume "AB x  AB y  {}"
      from this obtain a where "atom a  a  x  a  y"
        by auto
      thus False
        using 1 by (metis comp_inf.semiring.mult_zero_left inf.absorb2 inf.sup_monoid.add_assoc)
    qed
    show "finite (AB top)"
      using finite_AB by blast
  qed
qed

end

subsection ‹Atom-rectangular and Finitely Many Atoms›

class stone_relation_algebra_atomrect_finiteatoms = stone_relation_algebra_atomrect + stone_relation_algebra_finiteatoms

subsection ‹Atomic, Atom-rectangular and Finitely Many Atoms›

class stone_relation_algebra_atomic_atomrect_finiteatoms = stone_relation_algebra_atomic + stone_relation_algebra_atomrect + stone_relation_algebra_finiteatoms
begin

subclass stone_relation_algebra_atomic_atomrect ..
subclass stone_relation_algebra_atomic_finiteatoms ..
subclass stone_relation_algebra_atomrect_finiteatoms ..

lemma counterexample_nAB_atom_iff:
  "atom x  nAB x = 1"
  nitpick[expect=genuine,card=3]
  oops

lemma counterexample_nAB_top_iff_eq:
  "nAB x = nAB top  x = top"
  nitpick[expect=genuine,card=3]
  oops

lemma counterexample_nAB_top_iff_leq:
  "nAB top  nAB x  x = top"
  nitpick[expect=genuine,card=3]
  oops

end

subsection ‹Atom-simple and Finitely Many Atoms›

class stone_relation_algebra_atomsimple_finiteatoms = stone_relation_algebra_atomsimple + stone_relation_algebra_finiteatoms

subsection ‹Atomic, Atom-simple and Finitely Many Atoms›

class stone_relation_algebra_atomic_atomsimple_finiteatoms = stone_relation_algebra_atomic + stone_relation_algebra_atomsimple + stone_relation_algebra_finiteatoms
begin

subclass stone_relation_algebra_atomic_atomsimple ..
subclass stone_relation_algebra_atomic_finiteatoms ..
subclass stone_relation_algebra_atomsimple_finiteatoms ..

lemma nAB_top_2:
  "nAB 1 * nAB 1  nAB top"
proof (unfold num_atoms_below_def icard_cartesian_product[THEN sym], rule surj_icard_le)
  show "AB 1 × AB 1  dom_cod ` AB top"
    using dom_cod_atoms_2 by blast
qed

lemma counterexample_nAB_atom_iff_2:
  "atom x  nAB x = 1"
  nitpick[expect=genuine,card=6]
  oops

lemma counterexample_nAB_top_iff_eq_2:
  "nAB x = nAB top  x = top"
  nitpick[expect=genuine,card=6]
  oops

lemma counterexample_nAB_top_iff_leq_2:
  "nAB top  nAB x  x = top"
  nitpick[expect=genuine,card=6]
  oops

lemma counterexample_nAB_atom_top_iff_leq_2:
  "(atom x  nAB x = 1)  (nAB y = nAB top  y = top)  (nAB top  nAB y  y = top)"
  nitpick[expect=genuine,card=6]
  oops

end

subsection ‹Atom-rectangular, Atom-simple and Finitely Many Atoms›

class stone_relation_algebra_atomrect_atomsimple_finiteatoms = stone_relation_algebra_atomrect + stone_relation_algebra_atomsimple + stone_relation_algebra_finiteatoms
begin

subclass stone_relation_algebra_atomrect_atomsimple ..
subclass stone_relation_algebra_atomrect_finiteatoms ..
subclass stone_relation_algebra_atomsimple_finiteatoms ..

end

subsection ‹Atomic, Atom-rectangular, Atom-simple and Finitely Many Atoms›

class stone_relation_algebra_atomic_atomrect_atomsimple_finiteatoms = stone_relation_algebra_atomic + stone_relation_algebra_atomrect + stone_relation_algebra_atomsimple + stone_relation_algebra_finiteatoms
begin

subclass stone_relation_algebra_atomic_atomrect_atomsimple ..
subclass stone_relation_algebra_atomic_atomrect_finiteatoms ..
subclass stone_relation_algebra_atomic_atomsimple_finiteatoms ..
subclass stone_relation_algebra_atomrect_atomsimple_finiteatoms ..

lemma all_regular:
  "regular x"
proof (cases "x = bot")
  case True
  thus ?thesis
    by simp
next
  case False
  hence 1: "AB x  {}"
    using AB_nonempty by blast
  have 2: "finite (AB x)"
    using finite_AB by blast
  have 3: "regular (Sup_fin (AB x))"
  proof (rule finite_ne_subset_induct')
    show "finite (AB x)"
      using 2 by simp
    show "AB x  {}"
      using 1 by simp
    show "AB x  AB top"
      by auto
    show "a . a  AB top  Sup_fin {a} = --Sup_fin {a}"
      using atom_regular by auto
    show "a F . finite F  F  {}  F  AB top  a  AB top  a  F  Sup_fin F = --Sup_fin F  Sup_fin (insert a F) = --Sup_fin (insert a F)"
      using atom_regular by auto
  qed
  have "x  -Sup_fin (AB x) = bot"
  proof (rule ccontr)
    assume "x  -Sup_fin (AB x)  bot"
    from this obtain b where 4: "atom b  b  x  -Sup_fin (AB x)"
      using atomic by blast
    hence "b  Sup_fin (AB x)"
      using Sup_fin.coboundedI 2 by force
    thus "False"
      using 4 atom_in_p_xor by auto
  qed
  hence 5: "x  Sup_fin (AB x)"
    using 3 by (simp add: pseudo_complement)
  have "Sup_fin (AB x)  x"
    using 1 2 Sup_fin.boundedI by fastforce
  thus ?thesis
    using 3 5 order.antisym by force
qed

sublocale ra: relation_algebra where minus = "λx y . x  - y"
proof
  show "x . x  - x = bot"
    by simp
  show "x . x  - x = top"
    using all_regular pp_sup_p by fast
  show "x y . x  - y = x  - y"
    by simp
qed

end

class stone_relation_algebra_finite = stone_relation_algebra + finite
begin

subclass stone_relation_algebra_atomic_finiteatoms
proof
  show "finite { a . atom a }"
    by simp
  show "x. x  bot  (a. atom a  a  x)"
  proof
    fix x
    assume 1: "x  bot"
    let ?s = "{ y . y  x  y  bot }"
    have 2: "finite ?s"
      by auto
    have 3: "?s  {}"
      using 1 by blast
    from ne_finite_has_minimal obtain m where "m?s  (x?s . x  m  x = m)"
      using 2 3 by meson
    hence "atom m  m  x"
      using order_trans by blast
    thus "a. atom a  a  x"
      by auto
  qed
qed

end

subsection ‹Relation Algebra and Atomic›

class relation_algebra_atomic = relation_algebra + stone_relation_algebra_atomic
begin

lemma nAB_atom_iff:
  "atom a  nAB a = 1"
proof
  assume "atom a"
  thus "nAB a = 1"
    by (simp add: nAB_atom)
next
  assume "nAB a = 1"
  from this obtain b where 1: "AB a = {b}"
    using icard_1_imp_singleton num_atoms_below_def one_eSuc by fastforce
  hence 2: "atom b  b  a"
    by auto
  hence 3: "AB (a  b) = {b}"
    by fastforce
  have "AB (a  b)  AB (a  -b) = AB a  AB (a  b)  AB (a  -b) = {}"
    using AB_split_2 AB_split_2_disjoint by simp
  hence "{b}  AB (a  -b) = {b}  {b}  AB (a  -b) = {}"
    using 1 3 by simp
  hence "AB (a  -b) = {}"
    by auto
  hence "a  -b = bot"
    using AB_nonempty_iff by blast
  hence "a  b"
    by (simp add: shunting_1)
  thus "atom a"
    using 2 by auto
qed

end

subsection ‹Relation Algebra, Atomic and Finitely Many Atoms›

class relation_algebra_atomic_finiteatoms = relation_algebra_atomic + stone_relation_algebra_atomic_finiteatoms
begin

text Sup_fin› only works for non-empty finite sets.
›

lemma atomistic:
  assumes "x  bot"
    shows "x = Sup_fin (AB x)"
proof (rule order.antisym)
  show "x  Sup_fin (AB x)"
  proof (rule ccontr)
    assume "¬ x  Sup_fin (AB x)"
    hence "x  -Sup_fin (AB x)  bot"
      using shunting_1 by blast
    from this obtain a where 1: "atom a  a  x  -Sup_fin (AB x)"
      using atomic by blast
    hence "a  AB x"
      by simp
    hence "a  Sup_fin (AB x)"
      using Sup_fin.coboundedI finite_AB by auto
    thus "False"
      using 1 atom_in_p_xor by auto
  qed
  show "Sup_fin (AB x)  x"
  proof (rule Sup_fin.boundedI)
    show "finite (AB x)"
      using finite_AB by auto
    show "AB x  {}"
      using assms atomic by blast
    show "a. a  AB x  a  x"
      by auto
  qed
qed

lemma counterexample_nAB_top:
  "1  top  nAB top = nAB 1 * nAB 1"
  nitpick[expect=genuine,card=4]
  oops

end

class relation_algebra_atomic_atomsimple_finiteatoms = relation_algebra_atomic_finiteatoms + stone_relation_algebra_atomic_atomsimple_finiteatoms
begin

lemma counterexample_atom_rectangle:
  "atom x  rectangle x"
  nitpick[expect=genuine,card=4]
  oops

lemma counterexample_atom_univalent:
  "atom x  univalent x"
  nitpick[expect=genuine,card=4]
  oops

lemma counterexample_point_dense:
  assumes "x  bot"
      and "x  1"
    shows "a . a  bot  a * top * a  1  a  x"
  nitpick[expect=genuine,card=4]
  oops

end

class relation_algebra_atomic_atomrect_atomsimple_finiteatoms = relation_algebra_atomic_atomsimple_finiteatoms + stone_relation_algebra_atomic_atomrect_atomsimple_finiteatoms

section ‹Cardinality in Stone Relation Algebras›

text ‹
We study various axioms for a cardinality operation in Stone relation algebras.
›

class card =
  fixes cardinality :: "'a  enat" ("#_" [100] 100)

class sra_card = stone_relation_algebra + card
begin

abbreviation card_bot              :: "'a  bool" where "card_bot              _  #bot = 0"
abbreviation card_bot_iff          :: "'a  bool" where "card_bot_iff          _  x::'a . #x = 0  x = bot"
abbreviation card_top              :: "'a  bool" where "card_top              _  #top = #1 * #1"
abbreviation card_conv             :: "'a  bool" where "card_conv             _  x::'a . #(xT) = #x"
abbreviation card_add              :: "'a  bool" where "card_add              _  x y::'a . #x + #y = #(x  y) + #(x  y)"
abbreviation card_iso              :: "'a  bool" where "card_iso              _  x y::'a . x  y  #x  #y"
abbreviation card_univ_comp_meet   :: "'a  bool" where "card_univ_comp_meet   _  x y z::'a . univalent x  #(xT * y  z)  #(x * z  y)"
abbreviation card_univ_meet_comp   :: "'a  bool" where "card_univ_meet_comp   _  x y z::'a . univalent x  #(x  y * zT)  #(x * z  y)"
abbreviation card_comp_univ        :: "'a  bool" where "card_comp_univ        _  x y::'a . univalent x  #(y * x)  #y"
abbreviation card_univ_meet_vector :: "'a  bool" where "card_univ_meet_vector _  x y::'a . univalent x  #(x  y * top)  #y"
abbreviation card_univ_meet_conv   :: "'a  bool" where "card_univ_meet_conv   _  x y::'a . univalent x  #(x  y * yT)  #y"
abbreviation card_domain_sym       :: "'a  bool" where "card_domain_sym       _  x::'a . #(1  x * xT)  #x"
abbreviation card_domain_sym_conv  :: "'a  bool" where "card_domain_sym_conv  _  x::'a . #(1  xT * x)  #x"
abbreviation card_domain           :: "'a  bool" where "card_domain           _  x::'a . #(1  x * top)  #x"
abbreviation card_domain_conv      :: "'a  bool" where "card_domain_conv      _  x::'a . #(1  xT * top)  #x"
abbreviation card_codomain         :: "'a  bool" where "card_codomain         _  x::'a . #(1  top * x)  #x"
abbreviation card_codomain_conv    :: "'a  bool" where "card_codomain_conv    _  x::'a . #(1  top * xT)  #x"
abbreviation card_univ             :: "'a  bool" where "card_univ             _  x::'a . univalent x  #x  #(x * top)"
abbreviation card_atom             :: "'a  bool" where "card_atom             _  x::'a . atom x  #x = 1"
abbreviation card_atom_iff         :: "'a  bool" where "card_atom_iff         _  x::'a . atom x  #x = 1"
abbreviation card_top_iff_eq       :: "'a  bool" where "card_top_iff_eq       _  x::'a . #x = #top  x = top"
abbreviation card_top_iff_leq      :: "'a  bool" where "card_top_iff_leq      _  x::'a . #top  #x  x = top"
abbreviation card_top_finite       :: "'a  bool" where "card_top_finite       _  #top  "

lemma card_domain_iff:
  "card_domain _  card_domain_sym _"
  by (simp add: domain_vector_conv)

lemma card_codomain_conv_iff:
  "card_codomain_conv _  card_domain _"
  by (simp add: domain_vector_covector)

lemma card_codomain_iff:
  assumes card_conv: "card_conv _"
    shows "card_codomain _  card_codomain_conv _"
  by (metis card_conv conv_involutive)

lemma card_domain_conv_iff:
  "card_codomain _  card_domain_conv _"
  using domain_vector_covector by auto

lemma card_domain_sym_conv_iff:
  "card_domain_conv _  card_domain_sym_conv _"
  by (simp add: domain_vector_conv)

lemma card_bot:
  assumes card_bot_iff: "card_bot_iff _"
    shows "card_bot _"
  using card_bot_iff by auto

lemma card_comp_univ_implies_card_univ_comp_meet:
  assumes card_conv: "card_conv _"
      and card_comp_univ: "card_comp_univ _"
    shows "card_univ_comp_meet _"
proof (intro allI, rule impI)
  fix x y z
  assume 1: "univalent x"
  have "#(xT * y  z) = #(yT * x  zT)"
    by (metis card_conv conv_dist_comp conv_dist_inf conv_involutive)
  also have "... = #((yT  zT * xT) * x)"
    using 1 by (simp add: dedekind_univalent)
  also have "...  #(yT  zT * xT)"
    using 1 card_comp_univ by blast
  also have "... = #(x * z  y)"
    by (metis card_conv conv_dist_comp conv_dist_inf inf.sup_monoid.add_commute)
  finally show "#(xT * y  z)  #(x * z  y)"
    .
qed

lemma card_univ_meet_conv_implies_card_domain_sym:
  assumes card_univ_meet_conv: "card_univ_meet_conv _"
    shows "card_domain_sym _"
  by (simp add: card_univ_meet_conv)

lemma card_add_disjoint:
  assumes card_bot: "card_bot _"
      and card_add: "card_add _"
      and "x  y = bot"
    shows "#(x  y) = #x + #y"
  by (simp add: assms(3) card_add card_bot)

lemma card_dist_sup_disjoint:
  assumes card_bot: "card_bot _"
      and card_add: "card_add _"
      and "A  {}"
      and "finite A"
      and "xA . yA . x  y  x  y = bot"
    shows "#Sup_fin A = sum cardinality A"
proof (rule finite_ne_subset_induct')
  show "finite A"
    using assms(4) by simp
  show "A  {}"
    using assms(3) by simp
  show "A  A"
    by simp
  show "x . x  A  #Sup_fin {x} = sum cardinality {x}"
    by auto
  fix x F
  assume 1: "finite F" "F  {}" "F  A" "x  A" "x  F" "#Sup_fin F = sum cardinality F"
  have "#Sup_fin (insert x F) = #(x  Sup_fin F)"
    using 1 by simp
  also have "... = #x + #Sup_fin F"
  proof -
    have "x  Sup_fin F = Sup_fin { x  y | y . y  F }"
      using 1 inf_Sup1_distrib by simp
    also have "... = Sup_fin { bot | y . y  F }"
      using 1 assms(5) by (metis (mono_tags, opaque_lifting) subset_iff)
    also have "...  bot"
      by (rule Sup_fin.boundedI, simp_all add: 1)
    finally have "x  Sup_fin F = bot"
      by (simp add: order.antisym)
    thus ?thesis
      using card_add_disjoint assms by auto
  qed
  also have "... = sum cardinality (insert x F)"
    using 1 by simp
  finally show "#Sup_fin (insert x F) = sum cardinality (insert x F)"
    .
qed

lemma card_dist_sup_atoms:
  assumes card_bot: "card_bot _"
      and card_add: "card_add _"
      and "A  {}"
      and "finite A"
      and "A  AB top"
    shows "#Sup_fin A = sum cardinality A"
proof -
  have "xA . yA . x  y  x  y = bot"
    using different_atoms_disjoint assms(5) by auto
  thus ?thesis
    using card_dist_sup_disjoint assms(1-4) by auto
qed

lemma card_univ_meet_comp_implies_card_domain_sym:
  assumes card_univ_meet_comp: "card_univ_meet_comp _"
    shows "card_domain_sym _"
  by (metis card_univ_meet_comp inf.idem mult_1_left univalent_one_closed)

lemma card_top_greatest:
  assumes card_iso: "card_iso _"
    shows "#x  #top"
  by (simp add: card_iso)

lemma card_pp_increasing:
  assumes card_iso: "card_iso _"
    shows "#x  #(--x)"
  by (simp add: card_iso pp_increasing)

lemma card_top_iff_eq_leq:
  assumes card_iso: "card_iso _"
    shows "card_top_iff_eq _  card_top_iff_leq _"
  using card_iso card_top_greatest nle_le by blast

lemma card_univ_comp_meet_implies_card_comp_univ:
  assumes card_iso: "card_iso _"
      and card_conv: "card_conv _"
      and card_univ_comp_meet: "card_univ_comp_meet _"
    shows "card_comp_univ _"
proof (intro allI, rule impI)
  fix x y
  assume 1: "univalent x"
  have "#(y * x) = #(xT * yT)"
    by (metis card_conv conv_dist_comp)
  also have "... = #(top  xT * yT)"
    by simp
  also have "...  #(x * top  yT)"
    using 1 by (metis card_univ_comp_meet inf.sup_monoid.add_commute)
  also have "...  #(yT)"
    using card_iso by simp
  also have "... = #y"
    by (simp add: card_conv)
  finally show "#(y * x)  #y"
    .
qed

lemma card_comp_univ_iff_card_univ_comp_meet:
  assumes card_iso: "card_iso _"
      and card_conv: "card_conv _"
    shows "card_comp_univ _  card_univ_comp_meet _"
  using card_iso card_univ_comp_meet_implies_card_comp_univ card_conv card_comp_univ_implies_card_univ_comp_meet by blast

lemma card_univ_meet_vector_implies_card_univ_meet_comp:
  assumes card_iso: "card_iso _"
      and card_univ_meet_vector: "card_univ_meet_vector _"
    shows "card_univ_meet_comp _"
proof (intro allI, rule impI)
  fix x y z
  assume 1: "univalent x"
  have "#(x  y * zT) = #(x  (y  x * z) * (zT  yT * x))"
    by (metis conv_involutive dedekind_eq inf.sup_monoid.add_commute)
  also have "...  #(x  (y  x * z) * top)"
    using card_iso inf.sup_right_isotone mult_isotone by auto
  also have "...  #(x * z  y)"
    using 1 by (simp add: card_univ_meet_vector inf.sup_monoid.add_commute)
  finally show "#(x  y * zT)  #(x * z  y)"
    .
qed

lemma card_univ_meet_comp_implies_card_univ_meet_vector:
  assumes card_iso: "card_iso _"
      and card_univ_meet_comp: "card_univ_meet_comp _"
    shows "card_univ_meet_vector _"
proof (intro allI, rule impI)
  fix x y z
  assume 1: "univalent x"
  have "#(x  y * top)  #(x * top  y)"
    using 1 by (metis card_univ_meet_comp symmetric_top_closed)
  also have "...  #y"
    using card_iso by auto
  finally show "#(x  y * top)  #y"
    .
qed

lemma card_univ_meet_vector_iff_card_univ_meet_comp:
  assumes card_iso: "card_iso _"
    shows "card_univ_meet_vector _  card_univ_meet_comp _"
  using card_iso card_univ_meet_comp_implies_card_univ_meet_vector card_univ_meet_vector_implies_card_univ_meet_comp by blast

lemma card_univ_meet_vector_implies_card_univ_meet_conv:
  assumes card_iso: "card_iso _"
      and card_univ_meet_vector: "card_univ_meet_vector _"
    shows "card_univ_meet_conv _"
proof (intro allI, rule impI)
  fix x y z
  assume 1: "univalent x"
  have "#(x  y * yT)  #(x  y * top)"
    using card_iso comp_inf.mult_right_isotone mult_right_isotone by auto
  also have "...  #y"
    using 1 by (simp add: card_univ_meet_vector)
  finally show "#(x  y * yT)  #y"
    .
qed

lemma card_domain_sym_implies_card_univ_meet_vector:
  assumes card_comp_univ: "card_comp_univ _"
      and card_domain_sym: "card_domain_sym _"
    shows "card_univ_meet_vector _"
proof (intro allI, rule impI)
  fix x y z
  assume 1: "univalent x"
  have "#(x  y * top) = #((y * top  1) * (x  y * top))"
    by (simp add: inf.absorb2 vector_export_comp_unit)
  also have "...  #(y * top  1)"
    using 1 by (simp add: card_comp_univ univalent_inf_closed)
  also have "...  #y"
    using card_domain_sym card_domain_iff inf.sup_monoid.add_commute by auto
  finally show "#(x  y * top)  #y"
    .
qed

lemma card_domain_sym_iff_card_univ_meet_vector:
  assumes card_iso: "card_iso _"
      and card_comp_univ: "card_comp_univ _"
    shows "card_domain_sym _  card_univ_meet_vector _"
  using card_iso card_comp_univ card_domain_sym_implies_card_univ_meet_vector card_univ_meet_vector_implies_card_univ_meet_conv card_univ_meet_conv_implies_card_domain_sym by blast

lemma card_univ_meet_conv_iff_card_univ_meet_comp:
  assumes card_iso: "card_iso _"
      and card_comp_univ: "card_comp_univ _"
    shows "card_univ_meet_conv _  card_univ_meet_comp _"
  using card_iso card_comp_univ card_domain_sym_implies_card_univ_meet_vector card_univ_meet_vector_iff_card_univ_meet_comp card_univ_meet_vector_implies_card_univ_meet_conv univalent_one_closed by blast

lemma card_domain_sym_iff_card_univ_meet_comp:
  assumes card_iso: "card_iso _"
      and card_comp_univ: "card_comp_univ _"
    shows "card_domain_sym _  card_univ_meet_comp _"
  using card_iso card_comp_univ card_domain_sym_implies_card_univ_meet_vector card_univ_meet_conv_iff_card_univ_meet_comp card_univ_meet_vector_iff_card_univ_meet_comp card_univ_meet_conv_implies_card_domain_sym by blast

lemma card_univ_comp_mapping:
  assumes card_comp_univ: "card_comp_univ _"
      and card_univ_meet_comp: "card_univ_meet_comp _"
      and "univalent x"
      and "mapping y"
    shows "#(x * y) = #x"
proof -
  have "#x = #(x  top * yT)"
    using assms(4) total_conv_surjective by auto
  also have "...  #(x * y  top)"
    using assms(3) card_univ_meet_comp by blast
  finally have "#x  #(x * y)"
    by simp
  thus ?thesis
    using assms(4) card_comp_univ nle_le by blast
qed

lemma card_point_one:
  assumes card_comp_univ: "card_comp_univ _"
      and card_univ_meet_comp: "card_univ_meet_comp _"
      and card_conv: "card_conv _"
      and "point x"
    shows "#x = #1"
proof -
  have "mapping (xT)"
    using assms(4) surjective_conv_total by auto
  thus ?thesis
    by (smt card_univ_comp_mapping card_comp_univ card_conv card_univ_meet_comp coreflexive_comp_top_inf inf.absorb2 reflexive_one_closed top_right_mult_increasing total_one_closed univalent_one_closed)
qed

lemma counterexample_card_univ_comp_meet_card_comp_univ:
  assumes card_add: "card_add _"
      and card_conv: "card_conv _"
      and card_bot_iff: "card_bot_iff _"
      and card_atom_iff: "card_atom_iff _"
      and card_univ_meet_comp: "card_univ_meet_comp _"
    shows "card_univ_comp_meet _  card_comp_univ _"
  nitpick[expect=genuine]
  oops

lemma counterexample_card_univ_meet_comp_card_univ_meet_vector:
  assumes card_add: "card_add _"
      and card_conv: "card_conv _"
      and card_bot_iff: "card_bot_iff _"
      and card_atom_iff: "card_atom_iff _"
      and card_univ_comp_meet: "card_univ_comp_meet _"
    shows "card_univ_meet_comp _  card_univ_meet_vector _"
  nitpick[expect=genuine]
  oops

lemma counterexample_card_univ_meet_comp_card_univ_meet_conv:
  assumes card_add: "card_add _"
      and card_conv: "card_conv _"
      and card_bot_iff: "card_bot_iff _"
      and card_atom_iff: "card_atom_iff _"
      and card_univ_comp_meet: "card_univ_comp_meet _"
    shows "card_univ_meet_comp _  card_univ_meet_conv _"
  nitpick[expect=genuine]
  oops

lemma counterexample_card_univ_meet_vector_card_domain_sym:
  assumes card_add: "card_add _"
      and card_conv: "card_conv _"
      and card_bot_iff: "card_bot_iff _"
      and card_atom_iff: "card_atom_iff _"
      and card_univ_comp_meet: "card_univ_comp_meet _"
    shows "card_univ_meet_vector _  card_domain_sym _"
  nitpick[expect=genuine]
  oops

lemma counterexample_card_univ_meet_conv_card_domain_sym:
  assumes card_add: "card_add _"
      and card_conv: "card_conv _"
      and card_bot_iff: "card_bot_iff _"
      and card_atom_iff: "card_atom_iff _"
      and card_univ_comp_meet: "card_univ_comp_meet _"
    shows "card_univ_meet_conv _  card_domain_sym _"
  nitpick[expect=genuine]
  oops

end

subsection ‹Cardinality in Relation Algebras›

class ra_card = sra_card + relation_algebra
begin

lemma card_iso:
  assumes card_bot: "card_bot _"
      and card_add: "card_add _"
    shows "card_iso _"
proof (intro allI, rule impI)
  fix x y
  assume "x  y"
  hence "#y = #(x  (-x  y))"
    by (simp add: sup_absorb2)
  also have "... = #(x  (-x  y)) + #(x  (-x  y))"
    by (simp add: card_bot)
  also have "... = #x + #(-x  y)"
    by (metis card_add)
  finally show "#x  #y"
    using le_iff_add by blast
qed

lemma card_top_iff_eq:
  assumes card_bot_iff: "card_bot_iff _"
      and card_add: "card_add _"
      and card_top_finite: "card_top_finite _"
    shows "card_top_iff_eq _"
proof (rule allI, rule iffI)
  fix x
  assume 1: "#x = #top"
  have "#top = #(x  -x)"
    by simp
  also have "... = #x + #(-x)"
    using card_add card_bot_iff card_add_disjoint inf_p by blast
  also have "... = #top + #(-x)"
    using 1 by simp
  finally have "#(-x) = 0"
    by (simp add: card_top_finite)
  hence "-x = bot"
    using card_bot_iff by blast
  thus "x = top"
    using comp_inf.pp_total by auto
next
  fix x
  assume "x = top"
  thus "#x = #top"
    by simp
qed

end

class sra_card_atomic_finiteatoms = sra_card + stone_relation_algebra_atomic_finiteatoms
begin

lemma counterexample_card_nAB:
  assumes card_bot_iff: "card_bot_iff _"
      and card_atom_iff: "card_atom_iff _"
      and card_conv: "card_conv _"
      and card_add: "card_add _"
      and card_iso: "card_iso _"
      and card_top_iff_eq: "card_top_iff_eq _"
      and card_top_finite: "card_top_finite _"
    shows "#x = nAB x"
  nitpick[expect=genuine]
  oops

end

class ra_card_atomic_finiteatoms = ra_card + relation_algebra_atomic_finiteatoms
begin

lemma card_nAB:
  assumes card_bot: "card_bot _"
      and card_add: "card_add _"
      and card_atom: "card_atom _"
    shows "#x = nAB x"
proof (cases "x = bot")
  case True
  thus ?thesis
    by (simp add: card_bot nAB_bot)
next
  case False
  have 1: "finite (AB x)"
    using finite_AB by blast
  have 2: "AB x  {}"
    using False AB_nonempty_iff by blast
  have "#x = #Sup_fin (AB x)"
    using atomistic False by auto
  also have "... = sum cardinality (AB x)"
    using 1 2 card_bot card_add card_dist_sup_disjoint different_atoms_disjoint by force
  also have "... = sum (λx . 1) (AB x)"
    using card_atom by simp
  also have "... = icard (AB x)"
    by (metis (mono_tags, lifting) icard_eq_sum finite_AB)
  also have "... = nAB x"
    by (simp add: num_atoms_below_def)
  finally show ?thesis
    .
qed

end

class card_ab = sra_card +
  assumes card_nAB': "#x = nAB x"

class sra_card_ab_atomsimple_finiteatoms = sra_card + card_ab + stone_relation_algebra_atomsimple_finiteatoms +
  assumes card_bot_iff: "card_bot_iff _"
  assumes card_top: "card_top _"
begin

subclass stone_relation_algebra_atomic_atomsimple_finiteatoms
proof
  show "x . x  bot  (a . atom a  a  x)"
  proof
    fix x
    assume "x  bot"
    hence "#x  0"
      using card_bot_iff by auto
    hence "nAB x  0"
      by (simp add: card_nAB')
    hence "AB x  {}"
      by (metis (mono_tags, lifting) icard_empty num_atoms_below_def)
    thus "a . atom a  a  x"
      by auto
  qed
qed

lemma dom_cod_inj_atoms:
  "inj_on dom_cod (AB top)"
proof (rule eq_card_imp_inj_on)
  show 1: "finite (AB top)"
    using finite_AB by blast
  have "icard (dom_cod ` AB top) = icard (AB 1 × AB 1)"
    using dom_cod_atoms by auto
  also have "... = icard (AB 1) * icard (AB 1)"
    using icard_cartesian_product by blast
  also have "... = #1 * #1"
    by (simp add: card_nAB' num_atoms_below_def)
  also have "... = #top"
    by (simp add: card_top)
  also have "... = icard (AB top)"
    by (simp add: card_nAB' num_atoms_below_def)
  finally have "icard (dom_cod ` AB top) = icard (AB top)"
    .
  thus "card (dom_cod ` AB top) = card (AB top)"
    using 1 by (smt (z3) finite_icard_card)
qed

subclass stone_relation_algebra_atomic_atomrect_atomsimple_finiteatoms
proof
  have "a . atom a  a  1  a * top * a  1"
  proof
    fix a
    assume 1: "atom a  a  1"
    show "a * top * a  1"
    proof (rule ccontr)
      assume "¬ a * top * a  1"
      hence "a * top * a  -1  bot"
        by (simp add: pseudo_complement)
      from this obtain b where 2: "atom b  b  a * top * a  -1"
        using atomic by blast
      hence "b * top  a * top"
        by (metis comp_associative dual_order.trans inf.boundedE mult_left_isotone mult_right_isotone top.extremum)
      hence "b * top  1  a * top  1"
        using 1 comp_inf.comp_isotone by auto
      hence 3: "b * top  1 = a * top  1"
        using 1 2 domain_atom by simp
      have "top * b  top * a"
        using 2 by (metis comp_associative comp_inf.vector_top_closed comp_inf_covector inf.boundedE mult_right_isotone vector_export_comp_unit vector_top_closed)
      hence "top * b  1  top * a  1"
        using inf_mono by blast
      hence "top * b  1 = top * a  1"
        using 1 2 codomain_atom by simp
      hence 4: "dom_cod b = dom_cod a"
        using 3 by simp
      have "b  AB top  a  AB top"
        using 1 2 by simp
      hence "b = a"
        using inj_onD dom_cod_inj_atoms 4 by smt
      thus "False"
        using 1 2 comp_inf.coreflexive_pseudo_complement le_bot by fastforce
    qed
  qed
  thus "a . atom a  a * top * a  a"
    by (metis atom_rectangle_atom_one_rep)
qed

lemma atom_rectangle_card:
  assumes "atom a"
    shows "#(a * top * a) = 1"
  by (simp add: assms atomrect_eq card_nAB' nAB_atom)

lemma atom_regular_rectangle:
  assumes "atom a"
    shows "--a = a * top * a"
proof (rule order.antisym)
  show "--a  a * top * a"
    using assms atom_rectangle_regular ex231d pp_dist_comp by auto
  show "a * top * a  --a"
  proof (rule ccontr)
    assume "¬ a * top * a  --a"
    hence "a * top * a  -a  bot"
      by (simp add: pseudo_complement)
    from this obtain b where 1: "atom b  b  a * top * a  -a"
      using atomic by blast
    hence 2: "b  a"
      using inf.absorb2 by fastforce
    have 3: "a  AB (a * top * a)  b  AB (a * top * a)"
      using 1 assms ex231d by auto
    from atom_rectangle_card obtain c where "AB (a * top * a) = {c}"
      using card_nAB' num_atoms_below_def assms icard_1_imp_singleton one_eSuc by fastforce
    thus "False"
      using 2 3 by auto
  qed
qed

sublocale ra_atom: relation_algebra_atomic where minus = "λx y . x  - y" ..

end

class ra_card_atomic_atomsimple_finiteatoms = ra_card + relation_algebra_atomic_atomsimple_finiteatoms +
  assumes card_bot: "card_bot _"
  assumes card_add: "card_add _"
  assumes card_atom: "card_atom _"
  assumes card_top: "card_top _"
begin

subclass ra_card_atomic_finiteatoms
  ..

subclass sra_card_ab_atomsimple_finiteatoms
  apply unfold_locales
  using card_add card_atom card_bot card_nAB apply blast
  using card_add card_atom card_bot card_nAB nAB_bot_iff apply presburger
  using card_top by auto

subclass relation_algebra_atomic_atomrect_atomsimple_finiteatoms
  ..

end

subsection ‹Counterexamples›

class ra_card_notop = ra_card +
  assumes card_bot_iff: "card_bot_iff _"
  assumes card_conv: "card_conv _"
  assumes card_add: "card_add _"
  assumes card_atom_iff: "card_atom_iff _"
  assumes card_univ_comp_meet: "card_univ_comp_meet _"
  assumes card_univ_meet_comp: "card_univ_meet_comp _"

class ra_card_all = ra_card_notop +
  assumes card_top: "card_top _"
  assumes card_top_finite: "card_top_finite _"

class ra_card_notop_atomic_finiteatoms = ra_card_atomic_finiteatoms + ra_card_notop

class ra_card_all_atomic_finiteatoms = ra_card_notop_atomic_finiteatoms + ra_card_all

abbreviation r0000 :: "bool  bool  bool" where "r0000 x y  False"
abbreviation r1000 :: "bool  bool  bool" where "r1000 x y  ¬x  ¬y"
abbreviation r0001 :: "bool  bool  bool" where "r0001 x y  x  y"
abbreviation r1001 :: "bool  bool  bool" where "r1001 x y  x = y"
abbreviation r0110 :: "bool  bool  bool" where "r0110 x y  x  y"
abbreviation r1111 :: "bool  bool  bool" where "r1111 x y  True"

lemma r_all_different:
                  "r0000  r1000" "r0000  r0001" "r0000  r1001" "r0000  r0110" "r0000  r1111"
  "r1000  r0000"                 "r1000  r0001" "r1000  r1001" "r1000  r0110" "r1000  r1111"
  "r0001  r0000" "r0001  r1000"                 "r0001  r1001" "r0001  r0110" "r0001  r1111"
  "r1001  r0000" "r1001  r1000" "r1001  r0001"                 "r1001  r0110" "r1001  r1111"
  "r0110  r0000" "r0110  r1000" "r0110  r0001" "r0110  r1001"                 "r0110  r1111"
  "r1111  r0000" "r1111  r1000" "r1111  r0001" "r1111  r1001" "r1111  r0110"
  by metis+

typedef (overloaded) ra1 = "{r0000,r1001,r0110,r1111}"
  by auto

typedef (overloaded) ra2 = "{r0000,r1000,r0001,r1001}"
  by auto

setup_lifting type_definition_ra1
setup_lifting type_definition_ra2
setup_lifting type_definition_prod

instantiation Enum.finite_4 :: ra_card_atomic_finiteatoms
begin

definition one_finite_4 :: Enum.finite_4 where "one_finite_4 = finite_4.a2"
definition conv_finite_4 :: "Enum.finite_4  Enum.finite_4" where "conv_finite_4 x = x"
definition times_finite_4 :: "Enum.finite_4  Enum.finite_4  Enum.finite_4" where "times_finite_4 x y = (case (x,y) of (finite_4.a1,_)  finite_4.a1 | (_,finite_4.a1)  finite_4.a1 | (finite_4.a2,y)  y | (x,finite_4.a2)  x | _  finite_4.a4)"
definition cardinality_finite_4 :: "Enum.finite_4  enat" where "cardinality_finite_4 x = (case x of finite_4.a1  0 | finite_4.a4  2 | _  1)"

instance
  apply intro_classes
  subgoal by (simp add: times_finite_4_def split: finite_4.splits)
  subgoal by (simp add: times_finite_4_def sup_finite_4_def split: finite_4.splits)
  subgoal by (simp add: times_finite_4_def)
  subgoal by (simp add: times_finite_4_def one_finite_4_def split: finite_4.splits)
  subgoal by (simp add: conv_finite_4_def)
  subgoal by (simp add: sup_finite_4_def conv_finite_4_def)
  subgoal by (simp add: times_finite_4_def conv_finite_4_def split: finite_4.splits)
  subgoal by (simp add: times_finite_4_def inf_finite_4_def conv_finite_4_def less_eq_finite_4_def split: finite_4.splits)
  subgoal by (simp add: times_finite_4_def)
  subgoal by simp
  subgoal by (auto simp add: less_eq_finite_4_def split: finite_4.splits)
  subgoal by simp
  done

end

instantiation Enum.finite_4 :: ra_card_notop_atomic_finiteatoms
begin

instance
  apply intro_classes
  subgoal 1
    apply (clarsimp simp: cardinality_finite_4_def split: finite_4.splits)
    by (metis enat_0 one_neq_zero zero_neq_numeral)
  subgoal 2 by (simp add: conv_finite_4_def)
  subgoal 3 by (simp add: cardinality_finite_4_def sup_finite_4_def inf_finite_4_def split: finite_4.splits)
  subgoal 4 using zero_one_enat_neq(2) by (auto simp add: cardinality_finite_4_def less_eq_finite_4_def split: finite_4.splits)
  subgoal 5 using 1 3 4 by (metis (no_types, lifting) card_nAB nAB_univ_comp_meet)
  subgoal 6 using 1 3 4 by (metis (no_types, lifting) card_nAB nAB_univ_meet_comp)
  done

end

instantiation ra1 :: ra_card_atomic_finiteatoms
begin

lift_definition bot_ra1 :: ra1 is "r0000" by simp
lift_definition one_ra1 :: ra1 is "r1001" by simp
lift_definition top_ra1 :: ra1 is "r1111" by simp
lift_definition conv_ra1 :: "ra1  ra1" is id by simp
lift_definition uminus_ra1 :: "ra1  ra1" is "λr x y . ¬ r x y" by auto
lift_definition sup_ra1 :: "ra1  ra1  ra1" is "λq r x y . q x y  r x y" by auto
lift_definition inf_ra1 :: "ra1  ra1  ra1" is "λq r x y . q x y  r x y" by auto
lift_definition times_ra1 :: "ra1  ra1  ra1" is "λq r x y . z . q x z  r z y" by fastforce
lift_definition minus_ra1 :: "ra1  ra1  ra1" is "λq r x y . q x y  ¬ r x y" by auto
lift_definition less_eq_ra1 :: "ra1  ra1  bool" is "λq r . x y . q x y  r x y" .
lift_definition less_ra1 :: "ra1  ra1  bool" is "λq r . (x y . q x y  r x y)  q  r" .
lift_definition cardinality_ra1 :: "ra1  enat" is "λq . if q = r0000 then 0 else if q = r1111 then 2 else 1" .

instance
  apply intro_classes
  subgoal apply transfer by blast
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by auto
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by auto
  subgoal apply transfer by meson
  subgoal apply transfer by simp
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by fastforce
  subgoal apply transfer by auto
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by blast
  subgoal apply transfer by simp
  done

end

lemma four_cases:
  assumes "P x1" "P x2" "P x3" "P x4"
    shows "y  { x . x  {x1, x2, x3, x4} } . P y"
  using assms by auto

lemma r_aux:
  "(λx y. r1001 x y  r0110 x y) = r1111" "(λx y. r1001 x y  r0110 x y) = r0000"
  "(λx y. r0110 x y  r1001 x y) = r1111" "(λx y. r0110 x y  r1001 x y) = r0000"
  "(λx y. r1000 x y  r0001 x y) = r1001" "(λx y. r1000 x y  r0001 x y) = r0000"
  "(λx y. r1000 x y  r1001 x y) = r1001" "(λx y. r1000 x y  r1001 x y) = r1000"
  "(λx y. r0001 x y  r1000 x y) = r1001" "(λx y. r0001 x y  r1000 x y) = r0000"
  "(λx y. r0001 x y  r1001 x y) = r1001" "(λx y. r0001 x y  r1001 x y) = r0001"
  "(λx y. r1001 x y  r1000 x y) = r1001" "(λx y. r1001 x y  r1000 x y) = r1000"
  "(λx y. r1001 x y  r0001 x y) = r1001" "(λx y. r1001 x y  r0001 x y) = r0001"
  by meson+

instantiation ra1 :: ra_card_notop_atomic_finiteatoms
begin

instance
  apply intro_classes
  subgoal 1 apply transfer by (metis zero_neq_numeral zero_one_enat_neq(1))
  subgoal 2 apply transfer by simp
  subgoal 3 apply transfer using r_aux r_all_different by auto
  subgoal 4 apply transfer using r_all_different zero_one_enat_neq(1) by auto
  subgoal 5 using 1 3 4 card_nAB nAB_univ_comp_meet by (metis (no_types, lifting) card_nAB nAB_univ_comp_meet)
  subgoal 6 using 1 3 4 by (metis (no_types, lifting) card_nAB nAB_univ_meet_comp)
  done

end

instantiation ra2 :: ra_card_atomic_finiteatoms
begin

lift_definition bot_ra2 :: ra2 is "r0000" by simp
lift_definition one_ra2 :: ra2 is "r1001" by simp
lift_definition top_ra2 :: ra2 is "r1001" by simp
lift_definition conv_ra2 :: "ra2  ra2" is id by simp
lift_definition uminus_ra2 :: "ra2  ra2" is "λr x y . x = y  ¬ r x y" by auto
lift_definition sup_ra2 :: "ra2  ra2  ra2" is "λq r x y . q x y  r x y" by auto
lift_definition inf_ra2 :: "ra2  ra2  ra2" is "λq r x y . q x y  r x y" by auto
lift_definition times_ra2 :: "ra2  ra2  ra2" is "λq r x y . z . q x z  r z y" by auto
lift_definition minus_ra2 :: "ra2  ra2  ra2" is "λq r x y . q x y  ¬ r x y" by auto
lift_definition less_eq_ra2 :: "ra2  ra2  bool" is "λq r . x y . q x y  r x y" .
lift_definition less_ra2 :: "ra2  ra2  bool" is "λq r . (x y . q x y  r x y)  q  r" .
lift_definition cardinality_ra2 :: "ra2  enat" is "λq . if q = r0000 then 0 else if q = r1001 then 2 else 1" .

instance
  apply intro_classes
  subgoal apply transfer by blast
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by auto
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by (clarsimp, metis (full_types))
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by simp
  done

end

instantiation ra2 :: ra_card_notop_atomic_finiteatoms
begin

instance
  apply intro_classes
  subgoal 1 apply transfer by (metis one_neq_zero zero_neq_numeral)
  subgoal 2 apply transfer by simp
  subgoal 3 apply transfer
    apply (rule four_cases)
    subgoal using r_all_different by auto
    subgoal apply (rule four_cases) using r_aux r_all_different by auto
    subgoal apply (rule four_cases) using r_aux r_all_different by auto
    subgoal using r_aux r_all_different by auto
    done
  subgoal 4 apply transfer using r_all_different zero_one_enat_neq(1) by auto
  subgoal 5 using 1 3 4 by (metis (no_types, lifting) card_nAB nAB_univ_comp_meet)
  subgoal 6 using 1 3 4 by (metis (no_types, lifting) card_nAB nAB_univ_meet_comp)
  done

end

instantiation prod :: (stone_relation_algebra,stone_relation_algebra) stone_relation_algebra
begin

lift_definition bot_prod :: "'a × 'b" is "(bot::'a,bot::'b)" .
lift_definition one_prod :: "'a × 'b" is "(1::'a,1::'b)" .
lift_definition top_prod :: "'a × 'b" is "(top::'a,top::'b)" .
lift_definition conv_prod :: "'a × 'b  'a × 'b" is "λ(u,v) . (conv u,conv v)" .
lift_definition uminus_prod :: "'a × 'b  'a × 'b" is "λ(u,v) . (uminus u,uminus v)" .
lift_definition sup_prod :: "'a × 'b  'a × 'b  'a × 'b" is "λ(u,v) (w,x) . (u  w,v  x)" .
lift_definition inf_prod :: "'a × 'b  'a × 'b  'a × 'b" is "λ(u,v) (w,x) . (u  w,v  x)" .
lift_definition times_prod :: "'a × 'b  'a × 'b  'a × 'b" is "λ(u,v) (w,x) . (u * w,v * x)" .
lift_definition less_eq_prod :: "'a × 'b  'a × 'b  bool" is "λ(u,v) (w,x) . u  w  v  x" .
lift_definition less_prod :: "'a × 'b  'a × 'b  bool" is "λ(u,v) (w,x) . u  w  v  x  ¬(u = w  v = x)" .

instance
  apply intro_classes
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal by (unfold less_eq_prod_def, clarsimp)
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by (clarsimp, simp add: sup_inf_distrib1)
  subgoal apply transfer by (clarsimp, simp add: pseudo_complement)
  subgoal apply transfer by auto
  subgoal apply transfer by (clarsimp, simp add: mult.assoc)
  subgoal apply transfer by (clarsimp, simp add: mult_right_dist_sup)
  subgoal apply transfer by simp
  subgoal apply transfer by simp
  subgoal apply transfer by auto
  subgoal apply transfer by (clarsimp, simp add: conv_dist_sup)
  subgoal apply transfer by (clarsimp, simp add: conv_dist_comp)
  subgoal apply transfer by (clarsimp, simp add: dedekind_1)
  subgoal apply transfer by (clarsimp, simp add: pp_dist_comp)
  subgoal apply transfer by simp
  done

end

instantiation prod :: (relation_algebra,relation_algebra) relation_algebra
begin

lift_definition minus_prod :: "'a × 'b  'a × 'b  'a × 'b" is "λ(u,v) (w,x) . (u - w,v - x)" .

instance
  apply intro_classes
  subgoal apply transfer by auto
  subgoal apply transfer by auto
  subgoal apply transfer by (clarsimp, simp add: diff_eq)
  done

end

instantiation prod :: (relation_algebra_atomic_finiteatoms,relation_algebra_atomic_finiteatoms) relation_algebra_atomic_finiteatoms
begin

instance
  apply intro_classes
  subgoal apply transfer by (clarsimp, metis atomic bot.extremum inf.antisym_conv)
  subgoal
  proof -
    have 1: "a::'a . b::'b . atom (a,b)  (a = bot  atom b)  (atom a  b = bot)"
    proof (intro allI, rule impI)
      fix a :: 'a and b :: 'b
      assume 2: "atom (a,b)"
      show "(a = bot  atom b)  (atom a  b = bot)"
      proof (cases "a = bot")
        case 3: True
        show ?thesis
        proof (cases "b = bot")
          case True
          thus ?thesis
            using 2 3 by (simp add: bot_prod.abs_eq)
        next
          case False
          from this obtain c where 4: "atom c  c  b"
            using atomic by auto
          hence "(bot,c)  (a,b)  (bot,c)  bot"
            by (simp add: less_eq_prod_def bot_prod.abs_eq)
          hence "(bot,c) = (a,b)"
            using 2 by auto
          thus ?thesis
            using 4 by auto
        qed
      next
        case False
        from this obtain c where 5: "atom c  c  a"
          using atomic by auto
        hence "(c,bot)  (a,b)  (c,bot)  bot"
          by (simp add: less_eq_prod_def bot_prod.abs_eq)
        hence "(c,bot) = (a,b)"
          using 2 by auto
        thus ?thesis
          using 5 by auto
      qed
    qed
    have 6: "{ (a,b) | a b . atom (a,b) }  { (bot,b) | b::'b . atom b }  { (a,bot) | a::'a . atom a }"
    proof
      fix x :: "'a × 'b"
      assume "x  { (a,b) | a b . atom (a,b) }"
      from this obtain a b where 7: "x = (a,b)  atom (a,b)"
        by auto
      hence "(a = bot  atom b)  (atom a  b = bot)"
        using 1 by simp
      thus "x  { (bot,b) | b . atom b }  { (a,bot) | a . atom a }"
        using 7 by auto
    qed
    have "finite { (bot,b) | b::'b . atom b }  finite { (a,bot) | a::'a . atom a }"
      by (simp add: finiteatoms)
    hence 8: "finite ({ (bot,b) | b::'b . atom b }  { (a,bot) | a::'a . atom a })"
      by blast
    have 9: "finite { (a,b) | a b . atom (a::'a,b::'b) }"
      by (rule rev_finite_subset, rule 8, rule 6)
    have "{ (a,b) | a b . atom (a,b) } = { x :: 'a × 'b . atom x }"
      by auto
    thus "finite { x :: 'a × 'b . atom x }"
      using 9 by simp
  qed
  done

end

instantiation prod :: (ra_card_notop_atomic_finiteatoms,ra_card_notop_atomic_finiteatoms) ra_card_notop_atomic_finiteatoms
begin

lift_definition cardinality_prod :: "'a × 'b  enat" is "λ(u,v) . #u + #v" .

instance
  apply intro_classes
  subgoal apply transfer by (smt (verit) card_bot_iff case_prod_conv surj_pair zero_eq_add_iff_both_eq_0)
  subgoal apply transfer by (simp add: card_conv)
  subgoal apply transfer by (clarsimp, metis card_add semiring_normalization_rules(20))
  subgoal apply transfer apply (clarsimp, rule iffI)
    subgoal by (metis add.commute add.right_neutral bot.extremum card_atom_iff card_bot_iff dual_order.refl)
    subgoal for a b proof -
      assume 1: "#a + #b = 1"
      show ?thesis
      proof (cases "#a = 0")
        case True
        hence "#b = 1"
          using 1 by auto
        thus ?thesis
          by (metis True bot.extremum_unique card_atom_iff card_bot_iff)
      next
        case False
        hence "#a  1"
          by (simp add: ileI1 one_eSuc)
        hence 2: "#a = 1"
          using 1 by (metis ile_add1 order_antisym)
        hence "#b = 0"
          using 1 by auto
        thus ?thesis
          using 2 by (metis bot.extremum_unique card_atom_iff card_bot_iff)
      qed
    qed
    done
  subgoal apply transfer by (simp add: add_mono card_univ_comp_meet)
  subgoal apply transfer by (simp add: add_mono card_univ_meet_comp)
  done

end

type_synonym finite_4_square = "Enum.finite_4 × Enum.finite_4"

interpretation finite_4_square: ra_card_atomic_finiteatoms where cardinality = "cardinality" and inf = "(⊓)" and less_eq = "(≤)" and less = "(<)" and sup = "(⊔)" and bot = "bot::finite_4_square" and top = "top" and uminus = "uminus" and one = "1" and times = "(*)" and conv = "conv" and minus = "(-)" ..

interpretation finite_4_square: ra_card_all_atomic_finiteatoms where cardinality = "cardinality" and inf = "(⊓)" and less_eq = "(≤)" and less = "(<)" and sup = "(⊔)" and bot = "bot::finite_4_square" and top = "top" and uminus = "uminus" and one = "1" and times = "(*)" and conv = "conv" and minus = "(-)"
  apply unfold_locales
  subgoal apply transfer by (simp add: cardinality_finite_4_def one_finite_4_def)
  subgoal apply transfer by (smt (verit) card_add card_atom_iff card_bot_iff card_nAB cardinality_prod.abs_eq nAB_top_finite top_prod.abs_eq)
  done

lemma counterexample_atom_rectangle_2:
  "atom a  a * top * a  (a::finite_4_square)"
  nitpick[expect=genuine]
  oops

lemma counterexample_atom_univalent_2:
  "atom a  univalent (a::finite_4_square)"
  nitpick[expect=genuine]
  oops

lemma counterexample_point_dense_2:
  assumes "x  bot"
      and "x  1"
    shows "a::finite_4_square . a  bot  a * top * a  1  a  x"
  nitpick[expect=genuine]
  oops

type_synonym ra11 = "ra1 × ra1"

interpretation ra11: ra_card_atomic_finiteatoms where cardinality = "cardinality" and inf = "(⊓)" and less_eq = "(≤)" and less = "(<)" and sup = "(⊔)" and bot = "bot::ra11" and top = "top" and uminus = "uminus" and one = "1" and times = "(*)" and conv = "conv" and minus = "(-)" ..

interpretation ra11: ra_card_all_atomic_finiteatoms where cardinality = "cardinality" and inf = "(⊓)" and less_eq = "(≤)" and less = "(<)" and sup = "(⊔)" and bot = "bot::ra11" and top = "top" and uminus = "uminus" and one = "1" and times = "(*)" and conv = "conv" and minus = "(-)"
  apply unfold_locales
  subgoal apply transfer apply transfer using r_all_different by auto
  subgoal apply transfer apply transfer using numeral_ne_infinity by fastforce
  done

interpretation ra11: stone_relation_algebra_atomrect where inf = "(⊓)" and less_eq = "(≤)" and less = "(<)" and sup = "(⊔)" and bot = "bot::ra11" and top = "top" and uminus = "uminus" and one = "1" and times = "(*)" and conv = "conv"
  apply unfold_locales
  apply transfer apply transfer
  nitpick[expect=genuine]
  oops

lemma "¬ (a::ra1×ra1 . atom a  a * top * a  a)"
proof -
  let ?a = "(1::ra1,bot::ra1)"
  have 1: "atom ?a"
  proof
    show "?a  bot"
      by (metis (full_types) bot_prod.transfer bot_ra1.rep_eq one_ra1.rep_eq prod.inject)
    have "(a :: ra1) (b :: ra1) . (a,b)  ?a  (a,b)  bot  a = 1  b = bot"
    proof -
      fix a b :: ra1
      assume "(a,b)  ?a"
      hence 2: "a  1  b  bot"
        by (simp add: less_eq_prod_def)
      assume "(a,b)  bot"
      hence 3: "a  bot  b = bot"
        using 2 by (simp add: bot.extremum_unique bot_prod.abs_eq)
      have "atom (1::ra1)"
        apply transfer apply (rule conjI)
        subgoal by (simp add: r_all_different)
        subgoal by auto
        done
      thus "a = 1  b = bot"
        using 2 3 by blast
    qed
    thus "y . y  bot  y  ?a  y = ?a"
      by clarsimp
  qed
  have "¬ ?a * top * ?a  ?a"
    apply (unfold top_prod_def times_prod_def less_eq_prod_def)
    apply transfer
    by auto
  thus ?thesis
    using 1 by auto
qed

end