Theory Axiom_Of_Choice

section ‹Axiom of Choice›

theory Axiom_Of_Choice
  imports Coproduct
begin

text ‹The two definitions below correspond to Definition 2.7.1 in Halvorson.›
definition section_of :: "cfunc  cfunc  bool" (infix "sectionof" 90)
  where "s sectionof f  s : codomain f  domain f  f c s = id (codomain f)"

definition split_epimorphism :: "cfunc  bool"
  where "split_epimorphism f  ( s.  s : codomain f  domain f  f c s = id (codomain f))"

lemma split_epimorphism_def2: 
  assumes f_type: "f : X  Y"
  assumes f_split_epic: "split_epimorphism f"
  shows " s. (f c s = id Y)  (s: Y  X)"
  using cfunc_type_def f_split_epic f_type split_epimorphism_def by auto

lemma sections_define_splits:
  assumes "s sectionof f"
  assumes "s : Y  X"
  shows "f : X  Y  split_epimorphism(f)"
  using assms cfunc_type_def section_of_def split_epimorphism_def by auto

text ‹The axiomatization below corresponds to Axiom 11 (Axiom of Choice) in Halvorson.›
axiomatization
  where
  axiom_of_choice: "epimorphism f  ( g . g sectionof f)"

lemma epis_give_monos:  
  assumes f_type: "f : X  Y"
  assumes f_epi: "epimorphism f"
  shows "g. g: Y  X  monomorphism g  f c g = id Y"
  using assms  
  by (typecheck_cfuncs_prems, metis axiom_of_choice cfunc_type_def comp_monic_imp_monic f_epi id_isomorphism iso_imp_epi_and_monic section_of_def)

corollary epis_are_split:
  assumes f_type: "f : X  Y"
  assumes f_epi: "epimorphism f"
  shows "split_epimorphism f"
  using epis_give_monos cfunc_type_def  f_epi split_epimorphism_def by blast

text ‹The lemma below corresponds to Proposition 2.6.8 in Halvorson.›
lemma monos_give_epis:
  assumes f_type[type_rule]: "f : X  Y"
  assumes f_mono: "monomorphism f"
  assumes X_nonempty: "nonempty X"
  shows "g. g: Y  X  epimorphism g  g c f = id X"
proof -
  obtain g m E where g_type[type_rule]: "g : X  E" and m_type[type_rule]: "m : E  Y" and
      g_epi: "epimorphism g" and m_mono[type_rule]: "monomorphism m" and f_eq: "f = m c g"
    using epi_monic_factorization2 f_type by blast

  have g_mono: "monomorphism g"
  proof (typecheck_cfuncs, unfold monomorphism_def3, clarify)
    fix x y A
    assume x_type[type_rule]: "x : A  X" and y_type[type_rule]: "y : A  X"
    assume "g c x = g c y"
    then have "(m c g) c x = (m c g) c y"
      by (typecheck_cfuncs, smt comp_associative2)
    then have "f c x = f c y"
      unfolding f_eq by auto
    then show "x = y"
      using f_mono f_type monomorphism_def2 x_type y_type by blast
  qed

  have g_iso: "isomorphism g"
    by (simp add: epi_mon_is_iso g_epi g_mono)
  then obtain g_inv where g_inv_type[type_rule]: "g_inv : E  X" and
      g_g_inv: "g c g_inv = id E" and g_inv_g: "g_inv c g = id X"
    using cfunc_type_def g_type isomorphism_def by auto

  obtain x where x_type[type_rule]: "x c X"
    using X_nonempty nonempty_def by blast

  show "g. g: Y  X  epimorphism g  g c f = idc X"
  proof (intro exI[where x="(g_inv ⨿ (x c β⇘Y  (E, m))) c try_cast m"], safe, typecheck_cfuncs)
    have func_f_elem_eq: " y. y c X  (g_inv ⨿ (x c β⇘Y  (E, m)) c try_cast m) c f c y = y"
    proof -
      fix y
      assume y_type[type_rule]: "y c X"

      have "(g_inv ⨿ (x c β⇘Y  (E, m)) c try_cast m) c f c y
          = g_inv ⨿ (x c β⇘Y  (E, m)) c (try_cast m c m) c g c y"
        unfolding f_eq by (typecheck_cfuncs, smt comp_associative2)
      also have "... = (g_inv ⨿ (x c β⇘Y  (E, m)) c left_coproj E (Y  (E,m))) c g c y"
        by (typecheck_cfuncs, smt comp_associative2 m_mono try_cast_m_m)
      also have "... = (g_inv c g) c y"
        by (typecheck_cfuncs, simp add: comp_associative2 left_coproj_cfunc_coprod)
      also have "... = y"
        by (typecheck_cfuncs, simp add: g_inv_g id_left_unit2)
      finally show "(g_inv ⨿ (x c β⇘Y  (E, m)) c try_cast m) c f c y = y".
    qed
    show "epimorphism (g_inv ⨿ (x c β⇘Y  (E, m)) c try_cast m)"
    proof (rule surjective_is_epimorphism, etcs_subst surjective_def2, clarify)
      fix y
      assume y_type[type_rule]: "y c X"
      show "xa. xa c Y  (g_inv ⨿ (x c β⇘Y  (E, m)) c try_cast m) c xa = y"
        by (rule exI[where x="f c y"], typecheck_cfuncs, smt func_f_elem_eq)
    qed
    show "(g_inv ⨿ (x c β⇘Y  (E, m)) c try_cast m) c f = idc X"
      by (insert comp_associative2 func_f_elem_eq id_left_unit2, typecheck_cfuncs, rule one_separator, auto)
  qed
qed

text ‹The lemma below corresponds to Exercise 2.7.2(i) in Halvorson.›
lemma split_epis_are_regular: 
  assumes f_type[type_rule]: "f : X  Y"
  assumes "split_epimorphism f"
  shows "regular_epimorphism f"
proof - 
  obtain s where s_type[type_rule]: "s : Y  X" and s_splits:  "f c s = id Y"
    by (meson assms(2) f_type split_epimorphism_def2)
  then have "coequalizer Y f (s c f) (id X)"
    unfolding coequalizer_def 
    by (typecheck_cfuncs, smt (verit, del_insts) comp_associative2 comp_type id_left_unit2 id_right_unit2 s_splits)
  then show ?thesis
    using assms coequalizer_is_epimorphism epimorphisms_are_regular by blast
qed

text ‹The lemma below corresponds to Exercise 2.7.2(ii) in Halvorson.›
lemma sections_are_regular_monos: 
  assumes s_type:  "s : Y  X"
  assumes "s sectionof f"
  shows "regular_monomorphism s"
proof -   
  have "coequalizer Y f (s c f) (id X)"
    unfolding coequalizer_def 
    by (rule exI[where x="X"], intro exI[where x="X"], typecheck_cfuncs,
        smt (z3) assms cfunc_type_def comp_associative2 comp_type id_left_unit id_right_unit2 section_of_def)
  then show ?thesis
    by (metis assms(2) cfunc_type_def comp_monic_imp_monic' id_isomorphism iso_imp_epi_and_monic mono_is_regmono section_of_def)
qed

end