Theory Poincare_Tarski

section ‹Poincar\'e model satisfies Tarski axioms›

theory Poincare_Tarski
  imports Poincare Poincare_Lines_Axis_Intersections Tarski
begin

(* ------------------------------------------------------------------ *)
subsection‹Pasch axiom›
(* ------------------------------------------------------------------ *)

lemma Pasch_fun_mono:
  fixes r1 r2 :: real
  assumes "0 < r1" and "r1  r2" and "r2 < 1"
  shows "r1 + 1/r1  r2 + 1/r2"
proof (cases "r1 = r2")
  case True
  thus ?thesis
    by simp
next
  case False
  hence "r2 - r1 > 0"
    using assms
    by simp

  have "r1 * r2 < 1"
    using assms
    by (smt mult_le_cancel_left1)
  hence "1 / (r1 * r2) > 1"
    using assms
    by simp
  hence "(r2 - r1) / (r1 * r2) > (r2 - r1)"
    using r2 - r1 > 0
    using mult_less_cancel_left_pos[of "r2 - r1" 1 "1 / (r1 * r2)"]
    by simp
  hence "1 / r1 - 1 / r2 > r2 - r1"
    using assms
    by (simp add: field_simps)
  thus ?thesis
    by simp
qed

text‹Pasch axiom, non-degenerative case.›
lemma Pasch_nondeg:
  assumes "x  unit_disc" and "y  unit_disc" and "z  unit_disc" and "u  unit_disc" and "v  unit_disc"
  assumes "distinct [x, y, z, u, v]" 
  assumes "¬ poincare_collinear {x, y, z}" 
  assumes "poincare_between x u z" and "poincare_between y v z"
  shows " a. a  unit_disc  poincare_between u a y  poincare_between x a v"
proof-
  have " y z u. distinct [x, y, z, u, v]  ¬ poincare_collinear {x, y, z}  y  unit_disc  z  unit_disc  u  unit_disc 
                 poincare_between x u z  poincare_between y v z  ( a. a  unit_disc  poincare_between u a y  poincare_between x a v)" (is "?P x v")
  proof (rule wlog_positive_x_axis[where P="?P"])
    fix v
    assume v: "is_real v" "0 < Re v" "Re v < 1"
    hence "of_complex v  unit_disc"
      by (auto simp add: cmod_eq_Re)
    show "?P 0h (of_complex v)"
    proof safe
      fix y z u
      assume distinct: "distinct [0h, y, z, u, of_complex v]"
      assume in_disc: "y  unit_disc" "z  unit_disc" "u  unit_disc"
      then obtain y' z' u'
        where *: "y = of_complex y'" "z = of_complex z'" "u = of_complex u'"
        using inf_or_of_complex inf_notin_unit_disc
        by metis

      have "y'  0" "z'  0" "u'  0" "v  0" "y'  z'" "y'  u'" "z'  u'" "y  z" "y  u" "z  u"
        using of_complex_inj distinct *
        by auto

      note distinct = distinct this

      assume "¬ poincare_collinear {0h, y, z}"

      hence nondeg_yz: "y'*cnj z'  cnj y' * z'"
        using * poincare_collinear_zero_iff[of y' z'] in_disc distinct
        by auto

      assume "poincare_between 0h u z"

      hence "Arg u' = Arg z'" "cmod u'  cmod z'"
        using * poincare_between_0uv[of u z] distinct in_disc
        by auto

      then obtain φ ru rz where
        uz_polar: "u' = cor ru * cis φ" "z' = cor rz * cis φ" "0 < ru" "ru  rz" "0 < rz" and
                  "φ = Arg u'" "φ = Arg z'"
        using * u'  0 z'  0
        by (smt cmod_cis norm_le_zero_iff)

      obtain θ ry where
        y_polar: "y' = cor ry * cis θ" "ry > 0" and "θ = Arg y'"
        using y'  0
        by (smt cmod_cis norm_le_zero_iff)

      from in_disc * u' = cor ru * cis φ z' = cor rz * cis φ y' = cor ry * cis θ
      have "ru < 1" "rz < 1" "ry < 1"
        by (auto simp: norm_mult)

      note polar = this y_polar uz_polar

      have nondeg: "cis θ * cis (- φ)  cis (- θ) * cis φ"
        using nondeg_yz polar
        by simp

      let ?yz = "poincare_line y z"
      let ?v = "calc_x_axis_intersection ?yz"

      assume "poincare_between y (of_complex v) z"

      hence "of_complex v  circline_set ?yz"
        using in_disc of_complex v  unit_disc
        using distinct poincare_between_poincare_collinear[of y "of_complex v" z]
        using unique_poincare_line[of y z]
        by (auto simp add: poincare_collinear_def)
      moreover
      have "of_complex v  circline_set x_axis"
        using is_real v
        unfolding circline_set_x_axis
        by auto
      moreover
      have "?yz  x_axis"
      proof (rule ccontr)
        assume "¬ ?thesis"
        hence "{0h, y, z}  circline_set (poincare_line y z)"
          unfolding circline_set_def
          using distinct poincare_line[of y z]
          by auto
        hence "poincare_collinear {0h, y, z}"
          unfolding poincare_collinear_def
          using distinct
          by force
        thus False
          using ¬ poincare_collinear {0h, y, z}
          by simp
      qed
      ultimately
      have "?v = of_complex v" "intersects_x_axis ?yz"
        using unique_calc_x_axis_intersection[of "poincare_line y z" "of_complex v"]
        using intersects_x_axis_iff[of ?yz]
        using distinct of_complex v  unit_disc
        by (metis IntI is_poincare_line_poincare_line)+

      have "intersects_x_axis_positive ?yz"
        using Re v > 0 of_complex v  unit_disc
        using of_complex v  circline_set ?yz of_complex v  circline_set x_axis
        using intersects_x_axis_positive_iff[of ?yz] y  z ?yz  x_axis
        unfolding positive_x_axis_def
        by force

      have "y  circline_set x_axis"
      proof (rule ccontr)
        assume "¬ ?thesis"
        moreover
        hence "poincare_line y (of_complex v) = x_axis"
          using distinct of_complex v  circline_set x_axis
          using in_disc of_complex v  unit_disc
          using unique_poincare_line[of y "of_complex v" x_axis]
          by simp
        moreover
        have "z  circline_set (poincare_line y (of_complex v))"
          using of_complex v  circline_set ?yz
          using unique_poincare_line[of y "of_complex v" "poincare_line y z"]
          using in_disc of_complex v  unit_disc distinct
          using poincare_line[of y z]
          unfolding circline_set_def
          by (metis distinct_length_2_or_more is_poincare_line_poincare_line mem_Collect_eq)
        ultimately
        have "y  circline_set x_axis" "z  circline_set x_axis"
          by auto
        hence "poincare_collinear {0h, y, z}"
          unfolding poincare_collinear_def
          by force
        thus False
          using ¬ poincare_collinear {0h, y, z}
          by simp
      qed

      moreover

      have "z  circline_set x_axis"
      proof (rule ccontr)
        assume "¬ ?thesis"
        moreover
        hence "poincare_line z (of_complex v) = x_axis"
          using distinct of_complex v  circline_set x_axis
          using in_disc of_complex v  unit_disc
          using unique_poincare_line[of z "of_complex v" x_axis]
          by simp
        moreover
        have "y  circline_set (poincare_line z (of_complex v))"
          using of_complex v  circline_set ?yz
          using unique_poincare_line[of z "of_complex v" "poincare_line y z"]
          using in_disc of_complex v  unit_disc distinct
          using poincare_line[of y z]
          unfolding circline_set_def
          by (metis distinct_length_2_or_more is_poincare_line_poincare_line mem_Collect_eq)
        ultimately
        have "y  circline_set x_axis" "z  circline_set x_axis"
          by auto
        hence "poincare_collinear {0h, y, z}"
          unfolding poincare_collinear_def
          by force
        thus False
          using ¬ poincare_collinear {0h, y, z}
          by simp
      qed

      ultimately

      have "φ * θ < 0"
        using poincare_between y (of_complex v) z
        using poincare_between_x_axis_intersection[of y z "of_complex v"]
        using in_disc of_complex v  unit_disc distinct
        using of_complex v  circline_set ?yz of_complex v  circline_set x_axis
        using φ = Arg z' θ = Arg y' *
        by (simp add: field_simps)

      have "φ  pi" "φ  0"
        using z  circline_set x_axis * polar cis_pi
        unfolding circline_set_x_axis
        by auto

      have "θ  pi" "θ  0"
        using y  circline_set x_axis * polar cis_pi
        unfolding circline_set_x_axis
        by auto

      have phi_sin: "φ > 0  sin φ > 0" "φ < 0  sin φ < 0"
        using φ = Arg z' φ  0 φ  pi
        using Arg_bounded[of z']
        by (smt sin_gt_zero sin_le_zero sin_pi_minus sin_0_iff_canon sin_ge_zero)+

      have theta_sin: "θ > 0  sin θ > 0" "θ < 0  sin θ < 0"
        using θ = Arg y' θ  0 θ  pi
        using Arg_bounded[of y']
        by (smt sin_gt_zero sin_le_zero sin_pi_minus sin_0_iff_canon sin_ge_zero)+

      have "sin φ * sin θ < 0"
        using φ * θ < 0 phi_sin theta_sin
        by (simp add: mult_less_0_iff)

      have "sin (φ - θ)  0"
      proof (rule ccontr)
        assume "¬ ?thesis"
        hence "sin (φ - θ) = 0"
          by simp
        have "- 2 * pi < φ - θ" "φ - θ < 2 * pi"
          using φ = Arg z' θ = Arg y' Arg_bounded[of z'] Arg_bounded[of y'] φ  pi θ  pi
          by auto
        hence "φ - θ = -pi  φ - θ = 0  φ - θ = pi"
          using sin (φ - θ) = 0
          by (smt sin_0_iff_canon sin_periodic_pi2)
        moreover
        {
          assume "φ - θ = - pi"
          hence "φ = θ - pi"
            by simp
          hence False
            using nondeg_yz
            using y' = cor ry * cis θ z' = cor rz * cis φ rz > 0 ry > 0
            by auto
        }
        moreover
        {
          assume "φ - θ = 0"
          hence "φ = θ"
            by simp
          hence False
            using y' = cor ry * cis θ z' = cor rz * cis φ rz > 0 ry > 0
            using nondeg_yz
            by auto
        }
        moreover
        {
          assume "φ - θ = pi"
          hence "φ = θ + pi"
            by simp
          hence False
            using y' = cor ry * cis θ z' = cor rz * cis φ rz > 0 ry > 0
            using nondeg_yz
            by auto
        }
        ultimately
        show False
          by auto
      qed

      have "u  circline_set x_axis"
      proof-
        have "¬ is_real u'"
          using * polar in_disc
          using φ  0 φ = Arg u' φ  pi  phi_sin(1) phi_sin(2)
          by (metis is_real_arg2)
        moreover
        have "u  h"
          using in_disc
          by auto
        ultimately
        show ?thesis
          using * of_complex_inj[of u']
          unfolding circline_set_x_axis
          by auto
      qed

      let ?yu = "poincare_line y u"
      have nondeg_yu: "y' * cnj u'  cnj u' * u'"
        using nondeg_yz polar ru > 0 rz > 0 distinct
        by auto

      {
        (* derive results simultaneously for both u and z *)
        fix r :: real
        assume "r > 0"

        have den: "cor ry * cis θ * cnj 1 * cnj (cor r * cis φ) * 1 - cor r * cis φ * cnj 1 * cnj (cor ry * cis θ) * 1  0"
          using 0 < r 0 < ry nondeg
          by auto

        let ?A = "2 * r * ry * sin(φ - θ)"
        let ?B = "𝗂 * (r * cis φ * (1 + ry2) - ry * cis θ * (1 + r2))"
        let ?ReB = "ry * (1 + r2) * sin θ - r * (1 + ry2) * sin φ"

        have "Re (𝗂 * (r * cis (-φ) * ry * cis (θ) - ry * cis (-θ) * r * cis (φ))) = ?A"
          by (simp add: sin_diff field_simps)
        moreover
        have "cor ry * cis (- θ) * (cor ry * cis θ) = ry2"  "cor r * cis (- φ) * (cor r * cis φ) = r2"
          by (metis cis_inverse cis_neq_zero divide_complex_def cor_squared nonzero_mult_div_cancel_right power2_eq_square semiring_normalization_rules(15))+
        ultimately
        have 1: "poincare_line_cvec_cmat (of_complex_cvec (cor ry * cis θ)) (of_complex_cvec (cor r * cis φ)) = (?A, ?B, cnj ?B, ?A)"
          using den
          unfolding poincare_line_cvec_cmat_def of_complex_cvec_def Let_def prod.case
          by (simp add: field_simps)

        have 2: "is_real ?A"
          by simp
        let ?mix = "cis θ * cis (- φ) - cis (- θ) * cis φ"
        have "is_imag ?mix"
          using eq_minus_cnj_iff_imag[of ?mix]
          by simp
        hence "Im ?mix  0"
          using nondeg
          using complex.expand[of ?mix 0]
          by auto
        hence 3: "Re ?A  0"
          using r > 0 ry > 0
          by (simp add: sin_diff field_simps)

        have "?A  0"
          using 2 3
          by auto
        hence 4: "cor ?A  0"
          using 2 3
          by (metis zero_complex.simps(1))

        have 5: "?ReB / ?A = (sin θ) / (2 * sin(φ - θ)) * (1/r + r) - (sin φ) / (2 * sin (φ - θ)) * (1/ry + ry)" 
          using ry > 0 r > 0
          apply (subst diff_divide_distrib)             
          apply (subst add_frac_num, simp)
          apply (subst add_frac_num, simp)
          apply (simp add: power2_eq_square mult.commute)
          apply (simp add: field_simps)
          done

        have "poincare_line_cvec_cmat (of_complex_cvec (cor ry * cis θ)) (of_complex_cvec (cor r * cis φ)) = (?A, ?B, cnj ?B, ?A) 
                is_real ?A  Re ?A  0  ?A  0  cor ?A  0 
                Re ?B = ?ReB 
                ?ReB / ?A = (sin θ) / (2 * sin(φ - θ)) * (1/r + r) - (sin φ) / (2 * sin (φ - θ)) * (1/ry + ry)"
          using 1 2 3 4 5
          by auto
      }
      note ** = this

      let ?Ayz = "2 * rz * ry * sin (φ - θ)"
      let ?Byz = "𝗂 * (rz * cis φ * (1 + ry2) - ry * cis θ * (1 + rz2))"
      let ?ReByz = "ry * (1 + rz2) * sin θ - rz * (1 + ry2) * sin φ"
      let ?Kz = "(sin θ) / (2 * sin(φ - θ)) * (1/rz + rz) - (sin φ) / (2 * sin (φ - θ)) * (1/ry + ry)"
      have yz: "poincare_line_cvec_cmat (of_complex_cvec (cor ry * cis θ)) (of_complex_cvec (cor rz * cis φ)) = (?Ayz, ?Byz, cnj ?Byz, ?Ayz)"
        "is_real ?Ayz" "Re ?Ayz  0" "?Ayz  0" "cor ?Ayz  0" "Re ?Byz = ?ReByz" and Kz: "?ReByz / ?Ayz = ?Kz"
        using **[OF 0 < rz]
        by auto

      let ?Ayu = "2 * ru * ry * sin (φ - θ)"
      let ?Byu = "𝗂 * (ru * cis φ * (1 + ry2) - ry * cis θ * (1 + ru2))"
      let ?ReByu = "ry * (1 + ru2) * sin θ - ru * (1 + ry2) * sin φ"
      let ?Ku = "(sin θ) / (2 * sin(φ - θ)) * (1/ru + ru) - (sin φ) / (2 * sin (φ - θ)) * (1/ry + ry)"
      have yu: "poincare_line_cvec_cmat (of_complex_cvec (cor ry * cis θ)) (of_complex_cvec (cor ru * cis φ)) = (?Ayu, ?Byu, cnj ?Byu, ?Ayu)"
        "is_real ?Ayu" "Re ?Ayu  0" "?Ayu  0" "cor ?Ayu  0" "Re ?Byu = ?ReByu" and Ku: "?ReByu / ?Ayu = ?Ku"
        using **[OF 0 < ru]
        by auto

      have "?Ayz  0"
        using sin (φ - θ)  0 ry > 0 rz > 0
        by auto

      have "Re ?Byz / ?Ayz < -1"
        using intersects_x_axis_positive ?yz
          * y' = cor ry * cis θ z' = cor rz * cis φ u' = cor ru * cis φ
        apply simp
        apply (transfer fixing: ry rz ru θ φ)
        apply (transfer fixing: ry rz ru θ φ)
      proof-
        assume "intersects_x_axis_positive_cmat (poincare_line_cvec_cmat (of_complex_cvec (cor ry * cis θ)) (of_complex_cvec (cor rz * cis φ)))"
        thus "(ry * sin θ * (1 + rz2) - rz * sin φ * (1 + ry2)) / (2 * rz * ry * sin (φ - θ)) < - 1"
          using yz
          by simp
      qed

      have "?ReByz / ?Ayz  ?ReByu / ?Ayu"
      proof (cases "sin φ > 0")
        case True
        hence "sin θ < 0"
          using sin φ * sin θ < 0
          by (smt mult_nonneg_nonneg)

        have "?ReByz < 0"
        proof-
          have "ry * (1 + rz2) * sin θ < 0"
            using ry > 0 rz > 0
            using sin θ < 0
            by (smt mult_pos_neg mult_pos_pos zero_less_power)
          moreover
          have "rz * (1 + ry2) * sin φ > 0"
            using ry > 0 rz > 0
            using sin φ > 0
            by (smt mult_pos_neg mult_pos_pos zero_less_power)
          ultimately
          show ?thesis
            by simp
        qed
        have "?Ayz > 0"
          using Re ?Byz / ?Ayz < -1 Re ?Byz = ?ReByz ?ReByz < 0
          by (smt divide_less_0_iff)
        hence "sin (φ - θ) > 0"
          using ry > 0 rz > 0
          by (smt mult_pos_pos zero_less_mult_pos)

        have "1 / ru + ru  1 / rz + rz"
          using Pasch_fun_mono[of ru rz] 0 < ru ru  rz rz < 1
          by simp
        hence "sin θ * (1 / ru + ru)  sin θ * (1 / rz + rz)"
          using sin θ < 0
          by auto
        thus ?thesis
          using ru > 0 rz > 0 ru  rz rz < 1 ?Ayz > 0 sin (φ - θ) > 0
          using divide_right_mono[of "sin θ * (1 / ru + ru)" "sin θ * (1 / rz + rz)" "2 * sin (φ - θ)"]
          by (subst Kz, subst Ku) simp
      next
        assume "¬ sin φ > 0"
        hence "sin φ < 0"
          using sin φ * sin θ < 0
          by (cases "sin φ = 0", simp_all)
        hence "sin θ > 0"
          using sin φ * sin θ < 0
          by (smt mult_nonpos_nonpos)
        have "?ReByz > 0"
        proof-
          have "ry * (1 + rz2) * sin θ > 0"
            using ry > 0 rz > 0
            using sin θ > 0
            by (smt mult_pos_neg mult_pos_pos zero_less_power)
          moreover
          have "rz * (1 + ry2) * sin φ < 0"
            using ry > 0 rz > 0
            using sin φ < 0
            by (smt mult_pos_neg mult_pos_pos zero_less_power)
          ultimately
          show ?thesis
            by simp
        qed
        have "?Ayz < 0"
          using Re ?Byz / ?Ayz < -1 ?Ayz  0 Re ?Byz = ?ReByz ?ReByz > 0
          by (smt divide_less_0_iff)
        hence "sin (φ - θ) < 0"
          using ry > 0 rz > 0
          by (smt mult_nonneg_nonneg)

        have "1 / ru + ru  1 / rz + rz"
          using Pasch_fun_mono[of ru rz] 0 < ru ru  rz rz < 1
          by simp
        hence "sin θ * (1 / ru + ru)  sin θ * (1 / rz + rz)"
          using sin θ > 0
          by auto
        thus ?thesis
          using ru > 0 rz > 0 ru  rz rz < 1 ?Ayz < 0 sin (φ - θ) < 0
          using divide_right_mono_neg[of  "sin θ * (1 / rz + rz)" "sin θ * (1 / ru + ru)" "2 * sin (φ - θ)"]
          by (subst Kz, subst Ku) simp
      qed

      have "intersects_x_axis_positive ?yu"
        using * y' = cor ry * cis θ z' = cor rz * cis φ u' = cor ru * cis φ
        apply simp
        apply (transfer fixing: ry rz ru θ φ)
        apply (transfer fixing: ry rz ru θ φ)
      proof-
        have "Re ?Byu / ?Ayu < -1"
          using Re ?Byz / ?Ayz < -1 ?ReByz / ?Ayz  ?ReByu / ?Ayu
          by (subst (asm) Re ?Byz = ?ReByz, subst Re ?Byu = ?ReByu) simp
        thus "intersects_x_axis_positive_cmat (poincare_line_cvec_cmat (of_complex_cvec (cor ry * cis θ)) (of_complex_cvec (cor ru * cis φ)))"
          using yu
          by simp
      qed

      let ?a = "calc_x_axis_intersection ?yu"
      have "?a  positive_x_axis" "?a  circline_set ?yu" "?a  unit_disc"
        using intersects_x_axis_positive ?yu
        using intersects_x_axis_positive_iff'[of ?yu] y  u
        by auto

      then obtain a' where a': "?a = of_complex a'" "is_real a'" "Re a' > 0" "Re a' < 1"
        unfolding positive_x_axis_def circline_set_x_axis
        by (auto simp add: cmod_eq_Re)

      have "intersects_x_axis ?yz" "intersects_x_axis ?yu"
        using intersects_x_axis_positive ?yz intersects_x_axis_positive ?yu
        by auto

      show "a. a  unit_disc  poincare_between u a y  poincare_between 0h a (of_complex v)"
      proof (rule_tac x="?a" in exI, safe)
        show "poincare_between u ?a y"
          using poincare_between_x_axis_intersection[of y u ?a]
          using calc_x_axis_intersection[OF is_poincare_line_poincare_line[OF y  u] intersects_x_axis ?yu]
          using calc_x_axis_intersection_in_unit_disc[OF is_poincare_line_poincare_line[OF y  u] intersects_x_axis ?yu]
          using in_disc y  u y  circline_set x_axis u  circline_set x_axis
          using * φ = Arg u' θ = Arg y' φ * θ < 0
          by (subst poincare_between_rev, auto simp add: mult.commute)
      next
        show "poincare_between 0h ?a (of_complex v)"
        proof-
          have "-?ReByz / ?Ayz  -?ReByu / ?Ayu"
            using ?ReByz / ?Ayz  ?ReByu / ?Ayu
            by linarith
          have "outward ?yz ?yu"
            using * y' = cor ry * cis θ z' = cor rz * cis φ u' = cor ru * cis φ
            apply simp
            apply (transfer fixing: ry rz ru θ φ)
            apply (transfer fixing: ry rz ru θ φ)
            apply (subst yz yu)+
            unfolding outward_cmat_def
            apply (simp only: Let_def prod.case)
            apply (subst yz yu)+
            using -?ReByz / ?Ayz  -?ReByu / ?Ayu
            by simp
          hence "Re a'  Re v"
            using ?v = of_complex v
            using ?a = of_complex a'
            using intersects_x_axis_positive ?yz intersects_x_axis_positive ?yu
            using outward[OF is_poincare_line_poincare_line[OF y  z] is_poincare_line_poincare_line[OF y  u]]
            by simp
          thus ?thesis
            using ?v = of_complex v
            using poincare_between_x_axis_0uv[of "Re a'" "Re v"] a' v
            by simp
        qed
      next
        show "?a  unit_disc"
          by fact
      qed
    qed
  next
    show "x  unit_disc" "v  unit_disc" "x  v"
      using assms
      by auto
  next
    fix M x v
    let ?Mx = "moebius_pt M x" and ?Mv = "moebius_pt M v"
    assume 1: "unit_disc_fix M" "x  unit_disc" "v  unit_disc" "x  v"
    assume 2: "?P ?Mx ?Mv"
    show "?P x v"
    proof safe
      fix y z u
      let ?My = "moebius_pt M y" and ?Mz = "moebius_pt M z" and ?Mu = "moebius_pt M u"
      assume "distinct [x, y, z, u, v]" "¬ poincare_collinear {x, y, z}" "y  unit_disc" "z  unit_disc" "u  unit_disc"
             "poincare_between x u z" "poincare_between y v z"
      hence " Ma. Ma  unit_disc  poincare_between ?Mu Ma ?My  poincare_between ?Mx Ma ?Mv"
        using 1 2[rule_format, of ?My ?Mz ?Mu]
        by simp
      then obtain Ma where Ma: "Ma  unit_disc" "poincare_between ?Mu Ma ?My  poincare_between ?Mx Ma ?Mv"
        by blast
      let ?a = "moebius_pt (-M) Ma"
      let ?Ma = "moebius_pt M ?a"
      have "?Ma = Ma"
        by (metis moebius_pt_invert uminus_moebius_def)
      hence "?Ma  unit_disc" "poincare_between ?Mu ?Ma ?My  poincare_between ?Mx ?Ma ?Mv"
        using Ma
        by auto
      thus "a. a  unit_disc  poincare_between u a y  poincare_between x a v"
        using unit_disc_fix_moebius_inv[OF unit_disc_fix M] unit_disc_fix M Ma  unit_disc
        using u  unit_disc v  unit_disc x  unit_disc y  unit_disc
        by (rule_tac x="?a" in exI, simp del: moebius_pt_comp_inv_right)
    qed
  qed
  thus ?thesis
    using assms
    by auto
qed

text‹Pasch axiom, only degenerative cases.›
lemma Pasch_deg:
  assumes "x  unit_disc" and "y  unit_disc" and "z  unit_disc" and "u  unit_disc" and "v  unit_disc"
  assumes "¬ distinct [x, y, z, u, v]  poincare_collinear {x, y, z}"
  assumes "poincare_between x u z" and "poincare_between y v z"
  shows " a. a  unit_disc  poincare_between u a y  poincare_between x a v"
proof(cases "poincare_collinear {x, y, z}")
  case True
  hence "poincare_between x y z  poincare_between y x z  poincare_between y z x"
    using assms(1, 2, 3) poincare_collinear3_between poincare_between_rev by blast
  show ?thesis
  proof(cases "poincare_between x y z")
    case True
    have "poincare_between x y v"
      using True assms poincare_between_transitivity
      by (meson poincare_between_rev)
    thus ?thesis
      using assms(2)
      by (rule_tac x="y" in exI, simp)
  next
    case False
    hence "poincare_between y x z  poincare_between y z x"
      using poincare_between x y z  poincare_between y x z  poincare_between y z x
      by simp
    show ?thesis
    proof(cases "poincare_between y x z")
      case True
      hence "poincare_between u x y"
        using assms
        by (meson poincare_between_rev poincare_between_transitivity)
      thus ?thesis
        using assms
        by (rule_tac x="x" in exI, simp)
    next
      case False
      hence "poincare_between y z x"
        using poincare_between y x z  poincare_between y z x
        by auto
      hence "poincare_between x z v"
        using assms
        by (meson poincare_between_rev poincare_between_transitivity)
      hence "poincare_between x u v"
        using assms poincare_between_transitivity poincare_between_rev
        by (smt poincare_between_sum_distances)
      thus ?thesis
        using assms
        by (rule_tac x="u" in exI, simp)
    qed
  qed
next
  case False
  hence "¬ distinct [x, y, z, u, v]"
    using assms(6) by auto
  show ?thesis
  proof(cases "u=z")
    case True
    thus ?thesis
      using assms
      apply(rule_tac x="v" in exI)
      by(simp add:poincare_between_rev)
  next
    case False (* "u ≠ z" *)
    hence "x  z"
      using assms poincare_between_sandwich by blast
    show ?thesis
    proof(cases "v=z")
      case True
      thus ?thesis
        using assms
        by (rule_tac x="u" in exI, simp)
    next
      case False (* v ≠ z *)
      hence "y  z"
        using assms poincare_between_sandwich by blast
      show ?thesis
      proof(cases "u = x")
        case True
        thus ?thesis
          using assms
          by (rule_tac x="x" in exI, simp)
      next
        case False (*u ≠ x*)
        have "x  y"
          using assms ¬ poincare_collinear {x, y, z}
          by fastforce
        have "x  v"
          using assms ¬ poincare_collinear {x, y, z}
          by (metis insert_commute poincare_between_poincare_collinear)
        have "u  y"
          using assms ¬ poincare_collinear {x, y, z}
          using poincare_between_poincare_collinear by blast
        have "u  v"
        proof(rule ccontr)
          assume "¬ u  v"
          hence "poincare_between x v z"
            using assms by auto
          hence "x  circline_set (poincare_line z v)"
            using poincare_between_rev[of x v z]
            using poincare_between_poincare_line_uvz[of z v x]
            using assms v  z
            by auto
          have "y  circline_set (poincare_line z v)"
            using assms ¬ u  v 
            using poincare_between_rev[of y v z]
            using poincare_between_poincare_line_uvz[of z v y]
            using assms v  z
            by auto
          have "z  circline_set (poincare_line z v)"
            using ex_poincare_line_two_points[of z v] v  z
            by auto
          have "is_poincare_line (poincare_line z v)"
            using v  z
            by auto
          hence "poincare_collinear {x, y, z}"
            using x  circline_set (poincare_line z v)
            using y  circline_set (poincare_line z v)
            using z  circline_set (poincare_line z v)
            unfolding poincare_collinear_def
            by (rule_tac x="poincare_line z v" in exI, simp)            
          thus False
            using ¬ poincare_collinear {x, y, z} by simp
        qed
        have "v = y"
          using u  v u  y x  v x  y u  x y  z v  z x  z u  z
          using ¬ distinct [x, y, z, u, v]
          by auto
        thus ?thesis
          using assms
          by (rule_tac x="y" in exI, simp)
      qed
    qed
  qed
qed

text ‹Axiom of Pasch›
lemma Pasch:
  assumes "x  unit_disc" and "y  unit_disc" and "z  unit_disc" and "u  unit_disc" and "v  unit_disc"
  assumes "poincare_between x u z" and "poincare_between y v z"
  shows " a. a  unit_disc  poincare_between u a y  poincare_between x a v"
proof(cases "distinct [x, y, z, u, v]  ¬ poincare_collinear {x, y, z}")
  case True
  thus ?thesis
    using assms Pasch_nondeg by auto
next
  case False
  thus ?thesis
    using assms Pasch_deg by auto
qed

(* ------------------------------------------------------------------ *)
subsection‹Segment construction axiom›
(* ------------------------------------------------------------------ *)

lemma segment_construction:
  assumes "x  unit_disc" and "y  unit_disc"
  assumes "a  unit_disc" and "b  unit_disc"
  shows " z. z  unit_disc  poincare_between x y z  poincare_distance y z = poincare_distance a b"
proof-
  obtain d where d: "d = poincare_distance a b"
    by auto
  have "d  0"
    using assms
    by (simp add: d poincare_distance_ge0)

  have " z. z  unit_disc  poincare_between x y z  poincare_distance y z = d" (is "?P x y")
  proof (cases "x = y")
    case True
    have " z. z  unit_disc  poincare_distance x z = d"
    proof (rule wlog_zero)
      show " z. z  unit_disc  poincare_distance 0h z = d"
        using ex_x_axis_poincare_distance_negative[of d] d  0
        by blast
    next
      show "x  unit_disc"
        by fact
    next
      fix a u
      assume "u  unit_disc" "cmod a < 1"
      assume "z. z  unit_disc  poincare_distance (moebius_pt (blaschke a) u) z = d"
      then obtain z where *: "z  unit_disc" "poincare_distance (moebius_pt (blaschke a) u) z = d"
        by auto
      obtain z' where z': "z = moebius_pt (blaschke a) z'" "z'  unit_disc"
        using z  unit_disc
        using unit_disc_fix_iff[of "blaschke a"] cmod a < 1
        using blaschke_unit_disc_fix[of a]
        by blast

      show "z. z  unit_disc  poincare_distance u z = d"
        using * z' u : unit_disc
        using blaschke_unit_disc_fix[of a] cmod a < 1
        by (rule_tac x=z' in exI, simp)
    qed
    thus ?thesis
      using x = y
      unfolding poincare_between_def
      by auto
  next
    case False
    show ?thesis
    proof (rule wlog_positive_x_axis[where P="λ y x. ?P x y"])
      fix x
      assume "is_real x" "0 < Re x" "Re x < 1"

      then obtain z where z: "is_real z" "Re z  0" "- 1 < Re z" "of_complex z  unit_disc"
        "of_complex z  unit_disc" "of_complex z  circline_set x_axis" "poincare_distance 0h (of_complex z) = d"
        using ex_x_axis_poincare_distance_negative[of d] d  0
        by auto

      have "poincare_between (of_complex x) 0h (of_complex z)"
      proof (cases "z = 0")
        case True
        thus ?thesis
          unfolding poincare_between_def
          by auto
      next
        case False
        have "x  0"
          using is_real x Re x > 0
          by auto
        thus ?thesis
          using poincare_between_x_axis_u0v[of x z]
          using z is_real x x  0 Re x > 0 False
          using complex_eq_if_Re_eq mult_pos_neg
          by fastforce
    qed
    thus "?P (of_complex x) 0h"
      using poincare_distance 0h (of_complex z) = d of_complex z  unit_disc
      by blast
  next
    show "x  unit_disc" "y  unit_disc"
      by fact+
  next
    show "y  x" using x  y by simp
  next
    fix M u v
    assume "unit_disc_fix M" "u  unit_disc" "v  unit_disc" "u  v"
    assume "?P (moebius_pt M v) (moebius_pt M u)"
    then obtain z where *: "z  unit_disc" "poincare_between (moebius_pt M v) (moebius_pt M u) z" "poincare_distance (moebius_pt M u) z = d"
      by auto
    obtain z' where z': "z = moebius_pt M z'" "z'  unit_disc"
        using z  unit_disc
        using unit_disc_fix_iff[of M] unit_disc_fix M
        by blast
      thus "?P v u"
        using * u  unit_disc v  unit_disc unit_disc_fix M
        by auto
    qed
  qed
  thus ?thesis
    using assms d
    by auto
qed

(* ------------------------------------------------------------------ *)
subsection‹Five segment axiom›
(* ------------------------------------------------------------------ *)

lemma five_segment_axiom:
  assumes
     in_disc: "x  unit_disc"  "y  unit_disc" "z  unit_disc" "u  unit_disc" and
     in_disc': "x'  unit_disc" "y'  unit_disc" "z'  unit_disc" "u'  unit_disc" and
      "x  y" and
      betw: "poincare_between x y z" "poincare_between x' y' z'" and
      xy: "poincare_distance x y = poincare_distance x' y'" and
      xu: "poincare_distance x u = poincare_distance x' u'" and
      yu: "poincare_distance y u = poincare_distance y' u'" and
      yz: "poincare_distance y z = poincare_distance y' z'"
    shows
     "poincare_distance z u = poincare_distance z' u'"
proof-
  from assms obtain M where
  M: "unit_disc_fix_f M" "M x = x'" "M u = u'" "M y = y'"
    using unit_disc_fix_f_congruent_triangles[of x y u]
    by blast
  have "M z = z'"
  proof (rule unique_poincare_distance_on_ray[where u=x' and v=y' and y="M z" and z=z' and d="poincare_distance x z"])
    show "0  poincare_distance x z"
      using poincare_distance_ge0 in_disc
      by simp
  next
    show "x'  y'"
      using M x  y
      using in_disc in_disc' poincare_distance_eq_0_iff xy
      by auto
  next
    show "poincare_distance x' (M z) = poincare_distance x z"
      using M in_disc
      unfolding unit_disc_fix_f_def
      by auto
  next
    show "M z  unit_disc"
      using M in_disc
      unfolding unit_disc_fix_f_def
      by auto
  next
    show "poincare_distance x' z' = poincare_distance x z"
      using xy yz betw
      using poincare_between_sum_distances[of x y z]
      using poincare_between_sum_distances[of x' y' z']
      using in_disc in_disc'
      by auto
  next
    show "poincare_between x' y' (M z)"
      using M
      using in_disc betw
      unfolding unit_disc_fix_f_def
      by auto
  qed fact+
  thus ?thesis
    using unit_disc_fix_f M
    using in_disc in_disc'
    M u = u'
    unfolding unit_disc_fix_f_def
    by auto
qed

(* ------------------------------------------------------------------ *)
subsection‹Upper dimension axiom›
(* ------------------------------------------------------------------ *)

lemma upper_dimension_axiom:
  assumes in_disc: "x  unit_disc" "y  unit_disc" "z  unit_disc" "u  unit_disc" "v  unit_disc"
  assumes "poincare_distance x u = poincare_distance x v"
          "poincare_distance y u = poincare_distance y v"
          "poincare_distance z u = poincare_distance z v"
          "u  v"
  shows "poincare_between x y z  poincare_between y z x  poincare_between z x y"
proof (cases "x = y  y = z  x = z")
  case True
  thus ?thesis
    using in_disc
    by auto
next
  case False
  hence "x  y" "x  z" "y  z"
    by auto
  let ?cong = "λ a b a' b'. poincare_distance a b = poincare_distance a' b'"
  have " z u v. z  unit_disc  u  unit_disc  v  unit_disc 
                 ?cong x u x v  ?cong y u y v  ?cong z u z v   u  v 
                 poincare_collinear {x, y, z}" (is "?P x y")
  proof (rule wlog_positive_x_axis[where P="?P"])
    fix x
    assume x: "is_real x" "0 < Re x" "Re x < 1"
    hence "x  0"
      by auto
    have "0h  circline_set x_axis"
      by simp
    show "?P 0h (of_complex x)"
    proof safe
      fix z u v
      assume in_disc: "z  unit_disc" "u  unit_disc" "v  unit_disc"
      then obtain z' u' v' where zuv: "z = of_complex z'" "u = of_complex u'" "v = of_complex v'"
        using inf_or_of_complex[of z] inf_or_of_complex[of u] inf_or_of_complex[of v]
        by auto

      assume cong: "?cong 0h u 0h v" "?cong (of_complex x) u (of_complex x) v" "?cong z u z v" "u  v"

      let ?r0 = "poincare_distance 0h u" and
          ?rx = "poincare_distance (of_complex x) u"

      have "?r0 > 0" "?rx > 0"
        using in_disc  cong
        using poincare_distance_eq_0_iff[of "0h" u] poincare_distance_ge0[of "0h" u]
        using poincare_distance_eq_0_iff[of "0h" v] poincare_distance_ge0[of "0h" v]
        using poincare_distance_eq_0_iff[of "of_complex x" u] poincare_distance_ge0[of "of_complex x" u]
        using poincare_distance_eq_0_iff[of "of_complex x" v] poincare_distance_ge0[of "of_complex x" v]
        using x
        by (auto simp add: cmod_eq_Re)

      let ?pc0 = "poincare_circle 0h ?r0" and
          ?pcx = "poincare_circle (of_complex x) ?rx"
      have "u  ?pc0  ?pcx" "v  ?pc0  ?pcx"
        using in_disc cong
        by (auto simp add: poincare_circle_def)
      hence "u = conjugate v"
        using intersect_poincare_circles_x_axis[of 0 x ?r0 ?rx u v]
        using x x  0 u  v ?r0 > 0 ?rx > 0
        by simp

      let ?ru = "poincare_distance u z"
      have "?ru > 0"
        using poincare_distance_ge0[of u z] in_disc
        using cong
        using poincare_distance_eq_0_iff[of z u] poincare_distance_eq_0_iff[of z v]
        using poincare_distance_eq_0_iff
        by force

      have "z  poincare_circle u ?ru  poincare_circle v ?ru"
        using cong in_disc
        unfolding poincare_circle_def
        by (simp add: poincare_distance_sym)

      hence "is_real z'"
        using intersect_poincare_circles_conjugate_centers[of u v ?ru z] u = conjugate v zuv
        using in_disc u  v ?ru > 0
        by simp

      thus "poincare_collinear {0h, of_complex x, z}"
        using poincare_line_0_real_is_x_axis[of "of_complex x"] x x  0 zuv 0h  circline_set x_axis
        unfolding poincare_collinear_def
        by (rule_tac x=x_axis in exI, auto simp add: circline_set_x_axis)
    qed
  next
    fix M x y
    assume 1: "unit_disc_fix M" "x  unit_disc" "y  unit_disc" "x  y"
    assume 2: "?P (moebius_pt M x) (moebius_pt M y)"
    show "?P x y"
    proof safe
      fix z u v
      assume "z  unit_disc" "u  unit_disc" "v  unit_disc"
             "?cong x u x v" "?cong y u y v" "?cong z u z v" "u  v"
      hence "poincare_collinear {moebius_pt M x, moebius_pt M y, moebius_pt M z}"
        using 1 2[rule_format, of "moebius_pt M z" "moebius_pt M u" "moebius_pt M v"]
        by simp
      then obtain p where "is_poincare_line p" "{moebius_pt M x, moebius_pt M y, moebius_pt M z}  circline_set p"
        unfolding poincare_collinear_def
        by auto
      thus "poincare_collinear {x, y, z}"
        using unit_disc_fix M
        unfolding poincare_collinear_def
        by (rule_tac x="moebius_circline (-M) p" in exI, auto)
    qed
  qed fact+

  thus ?thesis
    using assms
    using poincare_collinear3_between[of x y z]
    using poincare_between_rev
    by auto
qed

(* ------------------------------------------------------------------ *)
subsection‹Lower dimension axiom›
(* ------------------------------------------------------------------ *)

lemma lower_dimension_axiom:
  shows " a  unit_disc.  b  unit_disc.  c  unit_disc.
            ¬ poincare_between a b c  ¬ poincare_between b c a  ¬ poincare_between c a b"
proof-
  let ?u = "of_complex (1/2)" and ?v = "of_complex (𝗂/2)"
  have 1: "0h  unit_disc" and 2: "?u  unit_disc" and 3: "?v  unit_disc"
    by simp_all
  have *: "¬ poincare_collinear {0h, ?u, ?v}"
  proof (rule ccontr)
    assume "¬ ?thesis"
    then obtain p where "is_poincare_line p" "{0h, ?u, ?v}  circline_set p"
      unfolding poincare_collinear_def
      by auto
    moreover
    have "of_complex (1 / 2)  of_complex (𝗂 / 2)"
      using of_complex_inj
      by fastforce
    ultimately
    have "0h  circline_set (poincare_line ?u ?v)"
      using unique_poincare_line[of ?u ?v p]
      by auto
    thus False
      unfolding circline_set_def
      by simp (transfer, transfer, simp add: vec_cnj_def)
  qed
  show ?thesis
    apply (rule_tac x="0h" in bexI, rule_tac x="?u" in bexI, rule_tac x="?v" in bexI)
    apply (rule ccontr, auto)
    using *
    using poincare_between_poincare_collinear[OF 1 2 3]
    using poincare_between_poincare_collinear[OF 2 3 1]
    using poincare_between_poincare_collinear[OF 3 1 2]
    by (metis insert_commute)+
qed

(* ------------------------------------------------------------------ *)
subsection‹Negated Euclidean axiom›
(* ------------------------------------------------------------------ *)

lemma negated_euclidean_axiom_aux:
  assumes "on_circline H (of_complex (1/2 + 𝗂/2))" and "is_poincare_line H"
  assumes "intersects_x_axis_positive H"
  shows "¬ intersects_y_axis_positive H"
  using assms
proof (transfer, transfer)
  fix H
  assume hh: "hermitean H  H  mat_zero" "is_poincare_line_cmat H"
  obtain A B C D where "H = (A, B, C, D)"
    by (cases H, auto)
  hence *: "is_real A" "H = (A, B, cnj B, A)" "(cmod B)2 > (cmod A)2"
    using hermitean_elems[of A B C D] hh
    by auto

  assume "intersects_x_axis_positive_cmat H"
  hence "Re A  0" "Re B / Re A < - 1"
    using *
    by auto

  assume "on_circline_cmat_cvec H (of_complex_cvec (1 / 2 + 𝗂 / 2))"
  hence "6*A + 4*Re B + 4*Im B = 0"
    using *
    unfolding of_real_mult
    apply (subst Re_express_cnj[of B])
    apply (subst Im_express_cnj[of B])
    apply (simp add: vec_cnj_def)
    apply (simp add: field_simps)
    done
  hence "Re (6*A + 4*Re B + 4*Im B) = 0"
    by simp
  hence "3*Re A + 2*Re B + 2*Im B = 0"
    using is_real A
    by simp

  hence "3/2 + Re B/Re A + Im B/Re A = 0"
    using Re A  0
    by (simp add: field_simps)

  hence "-Im B/Re A - 3/2 < -1"
    using Re B / Re A < -1
    by simp
  hence "Im B/Re A > -1/2"
    by (simp add: field_simps)
  thus "¬ intersects_y_axis_positive_cmat H"
    using *
    by simp
qed

lemma negated_euclidean_axiom:
  shows " a b c d t.
           a  unit_disc  b  unit_disc  c  unit_disc  d  unit_disc  t  unit_disc 
           poincare_between a d t  poincare_between b d c  a  d 
                ( x y. x  unit_disc  y  unit_disc 
                        poincare_between a b x  poincare_between x t y  ¬ poincare_between a c y)"
proof-
  let ?a = "0h"
  let ?b = "of_complex (1/2)"
  let ?c = "of_complex (𝗂/2)"
  let ?dl = "(5 - sqrt 17) / 4"
  let ?d = "of_complex (?dl + 𝗂*?dl)"
  let ?t = "of_complex (1/2 + 𝗂/2)"

  have "?dl  0"
  proof-
    have "(sqrt 17)2  52"
      by simp
    hence "sqrt 17  5"
      by force
    thus ?thesis
      by simp
  qed

  have "?d  ?a"
  proof (rule ccontr)
    assume "¬ ?thesis"
    hence "?dl + 𝗂*?dl = 0"
      by simp
    hence "Re (?dl + 𝗂*?dl) = 0"
      by simp
    thus False
      using ?dl  0
      by simp
  qed

  have "?dl > 0"
  proof-
    have "(sqrt 17)2 < 52"
      by (simp add: power2_eq_square)
    hence "sqrt 17 < 5"
      by (rule power2_less_imp_less, simp)
    thus ?thesis
      by simp
  qed

  have "?a  ?b"
    by (metis divide_eq_0_iff of_complex_zero_iff zero_neq_numeral zero_neq_one)

  have "?a  ?c"
    by (metis complex_i_not_zero divide_eq_0_iff of_complex_zero_iff zero_neq_numeral)

  show ?thesis
  proof (rule_tac x="?a" in exI, rule_tac x="?b" in exI, rule_tac x="?c" in exI, rule_tac x="?d" in exI, rule_tac x="?t" in exI, safe)


    show "?a  unit_disc" "?b  unit_disc" "?c  unit_disc" "?t  unit_disc"
      by (auto simp add: cmod_def power2_eq_square)

    have cmod_d: "cmod (?dl + 𝗂*?dl) = ?dl * sqrt 2"
      using ?dl > 0
      unfolding cmod_def
      by (simp add: real_sqrt_mult)

    show "?d  unit_disc"
    proof-
      have "?dl < 1 / sqrt 2"
      proof-
        have "172 < (5 * sqrt 17)2"
          by (simp add: field_simps)
        hence "17 < 5 * sqrt 17"
          by (rule power2_less_imp_less, simp)
        hence "?dl2 < (1 / sqrt 2)2"
          by (simp add: power2_eq_square field_simps)
        thus "?dl < 1 / sqrt 2"
          by (rule power2_less_imp_less, simp)
      qed
      thus ?thesis
        using cmod_d
        by (simp add: field_simps)
    qed

    have cmod_d: "1 - (cmod (to_complex ?d))2 = (-17 + 5*sqrt 17) / 4" (is "_ = ?cmod_d")
      apply (simp only: to_complex_of_complex)
      apply (subst cmod_d)
      apply (simp add: power_mult_distrib)
      apply (simp add: power2_eq_square field_simps)
      done

    have cmod_d_c: "(cmod (to_complex ?d - to_complex ?c))2 = (17 - 4*sqrt 17) / 4" (is "_ = ?cmod_dc")
      unfolding cmod_square
      by (simp add: field_simps)

    have cmod_c: "1 - (cmod (to_complex ?c))2 = 3/4" (is "_ = ?cmod_c")
      by (simp add: power2_eq_square)

    have xx: " x::real. x + x = 2*x"
      by simp

    have "cmod ((to_complex ?b) - (to_complex ?d)) = cmod ((to_complex ?d) - (to_complex ?c))"
      by (simp add: cmod_def power2_eq_square field_simps)
    moreover
    have "cmod (to_complex ?b) = cmod (to_complex ?c)"
      by simp
    ultimately
    have *: "poincare_distance_formula' (to_complex ?b) (to_complex ?d) =
             poincare_distance_formula' (to_complex ?d) (to_complex ?c)"
      unfolding poincare_distance_formula'_def
      by simp

    have **: "poincare_distance_formula' (to_complex ?d) (to_complex ?c) = (sqrt 17) / 3"
      unfolding poincare_distance_formula'_def
    proof (subst cmod_d, subst cmod_c, subst cmod_d_c)
      have "(sqrt 17 * 15)2  512"
        by simp
      hence "sqrt 17 * 15  51"
        by force
      hence "sqrt 17 * 15 - 51  0"
        by simp

      have "(5 * sqrt 17)2  172"
        by simp
      hence "5 * sqrt 17  17"
        by force
      hence "?cmod_d * ?cmod_c  0"
        by simp
      hence "1 + 2 * (?cmod_dc / (?cmod_d * ?cmod_c)) =  (?cmod_d * ?cmod_c + 2 * ?cmod_dc) / (?cmod_d * ?cmod_c)"
        using add_frac_num[of "?cmod_d * ?cmod_c" "2 * ?cmod_dc" 1]
        by (simp add: field_simps)
      also have "... = (64 * (85 - sqrt 17 * 17)) / (64 * (sqrt 17 * 15 - 51))"
        by (simp add: field_simps)
      also have "... = (85 - sqrt 17 * 17) / (sqrt 17 * 15 - 51)"
        by (rule mult_divide_mult_cancel_left, simp)
      also have "... = sqrt 17 / 3"
        by (subst frac_eq_eq, fact, simp, simp add: field_simps)
      finally
      show "1 + 2 * (?cmod_dc / (?cmod_d * ?cmod_c)) = sqrt 17 / 3"
        .
    qed

    have "sqrt 17  3"
    proof-
      have "(sqrt 17)2  32"
        by simp
      thus ?thesis
        by (rule power2_le_imp_le, simp)
    qed
    thus "poincare_between ?b ?d ?c"
      unfolding poincare_between_sum_distances[OF ?b  unit_disc ?d  unit_disc ?c  unit_disc]
      unfolding poincare_distance_formula[OF ?b  unit_disc ?d  unit_disc]
      unfolding poincare_distance_formula[OF ?d  unit_disc ?c  unit_disc]
      unfolding poincare_distance_formula[OF ?b  unit_disc ?c  unit_disc]
      unfolding poincare_distance_formula_def
      apply (subst *, subst xx, subst **, subst arcosh_double)
      apply (simp_all add: cmod_def power2_eq_square)
      done

    show "poincare_between ?a ?d ?t"
    proof (subst poincare_between_0uv[OF ?d  unit_disc ?t  unit_disc ?d  ?a])
      show "?t  0h"
      proof (rule ccontr)
        assume "¬ ?thesis"
        hence "1/2 + 𝗂/2 = 0"
          by simp
        hence "Re (1/2 + 𝗂/2) = 0"
          by simp
        thus False
          by simp
      qed
    next
      have "192  (5 * sqrt 17)2"
        by simp
      hence "19  5 * sqrt 17"
        by (rule power2_le_imp_le, simp)
      hence "cmod (to_complex ?d)  cmod (to_complex ?t)"
        by (simp add: Let_def cmod_def power2_eq_square field_simps)
      moreover
      have "Arg (to_complex ?d) = Arg (to_complex ?t)"
      proof-
        have 1: "to_complex ?d = ((5 - sqrt 17) / 4) * (1 + 𝗂)"
          by (simp add: field_simps)

        have 2: "to_complex ?t = (cor (1/2)) * (1 + 𝗂)"
          by (simp add: field_simps)

        have "(sqrt 17)2 < 52"
          by simp
        hence "sqrt 17 < 5"
          by (rule power2_less_imp_less, simp)
        hence 3: "(5 - sqrt 17) / 4 > 0"
          by simp

        have 4: "(1::real) / 2 > 0"
          by simp

        show ?thesis
          apply (subst 1, subst 2)
          apply (subst arg_mult_real_positive[OF 3])
          apply (subst arg_mult_real_positive[OF 4])
          by simp
      qed
      ultimately
      show "let d' = to_complex ?d; t' = to_complex ?t in Arg d' = Arg t'  cmod d'  cmod t'"
        by simp
    qed

    show "?a = ?d  False"
      using ?d  ?a
      by simp

    fix x y
    assume "x  unit_disc" "y  unit_disc"

    assume abx: "poincare_between ?a ?b x"
    hence "x  circline_set x_axis"
      using poincare_between_poincare_line_uvz[of ?a ?b x] x  unit_disc ?a  ?b
      using poincare_line_0_real_is_x_axis[of ?b]
      by (auto simp add: circline_set_x_axis)

    have "x  0h"
      using abx poincare_between_sandwich[of ?a ?b] ?a  ?b
      by auto

    have "x  positive_x_axis"
      using x  circline_set x_axis x  0h x  unit_disc
      using abx poincare_between_x_axis_0uv[of "1/2" "Re (to_complex x)"]
      unfolding circline_set_x_axis positive_x_axis_def
      by (auto simp add: cmod_eq_Re abs_less_iff complex_eq_if_Re_eq)

    assume acy: "poincare_between ?a ?c y"
    hence "y  circline_set y_axis"
      using poincare_between_poincare_line_uvz[of ?a ?c y] y  unit_disc ?a  ?c
      using poincare_line_0_imag_is_y_axis[of ?c]
      by (auto simp add: circline_set_y_axis)

    have "y  0h"
      using acy poincare_between_sandwich[of ?a ?c] ?a  ?c
      by auto

    have "y  positive_y_axis"
    proof-
      have " x. x  0; poincare_between 0h (of_complex (𝗂 / 2)) (of_complex x); is_imag x; - 1 < Im x  0 < Im x"
        by (smt add.left_neutral complex.expand divide_complex_def complex_eq divide_less_0_1_iff divide_less_eq_1_pos imaginary_unit.simps(1) mult.left_neutral of_real_1 of_real_add of_real_divide of_real_eq_0_iff one_add_one poincare_between_y_axis_0uv zero_complex.simps(1) zero_complex.simps(2) zero_less_divide_1_iff)
      thus ?thesis
        using y  circline_set y_axis y  0h y  unit_disc
        using acy
        unfolding circline_set_y_axis positive_y_axis_def
        by (auto simp add: cmod_eq_Im abs_less_iff)
    qed

    have "x  y"
      using x  positive_x_axis y  positive_y_axis
      unfolding positive_x_axis_def positive_y_axis_def circline_set_x_axis circline_set_y_axis
      by auto

    assume xty: "poincare_between x ?t y"

    let ?xy = "poincare_line x y"

    have "?t  circline_set ?xy"
      using xty poincare_between_poincare_line_uzv[OF x  y x  unit_disc y  unit_disc ?t  unit_disc]
      by simp

    moreover

    have "?xy  x_axis"
      using poincare_line_circline_set[OF x  y] y  positive_y_axis
      by (auto simp add: circline_set_x_axis positive_y_axis_def)
    hence "intersects_x_axis_positive ?xy"
      using intersects_x_axis_positive_iff[of "?xy"] x  y x  unit_disc x  positive_x_axis
      by auto

    moreover

    have "?xy  y_axis"
      using poincare_line_circline_set[OF x  y] x  positive_x_axis
      by (auto simp add: circline_set_y_axis positive_x_axis_def)
    hence "intersects_y_axis_positive ?xy"
      using intersects_y_axis_positive_iff[of "?xy"] x  y y  unit_disc y  positive_y_axis
      by auto

    ultimately

    show False
      using negated_euclidean_axiom_aux[of ?xy] x  y
      unfolding circline_set_def
      by auto
  qed
qed

text ‹Alternate form of the Euclidean axiom -- this one is much easier to prove›
lemma negated_euclidean_axiom':
  shows " a b c.
           a  unit_disc  b  unit_disc  c  unit_disc  ¬(poincare_collinear {a, b, c})  
                ¬( x. x  unit_disc  
                  poincare_distance a x = poincare_distance b x 
                  poincare_distance a x = poincare_distance c x)"
proof-
  let ?a = "of_complex (𝗂/2)"
  let ?b = "of_complex (-𝗂/2)"
  let ?c = "of_complex (1/5)"

  have "(𝗂/2)  (-𝗂/2)"
    by simp
  hence "?a  ?b"
    by (metis to_complex_of_complex)
  have "(𝗂/2)  (1/5)"
    by simp
  hence "?a  ?c"
    by (metis to_complex_of_complex)
  have "(-𝗂/2)  (1/5)"
    by (simp add: minus_equation_iff)
  hence "?b  ?c"
    by (metis to_complex_of_complex)

  have "?a  unit_disc" "?b  unit_disc" "?c  unit_disc"
    by auto

  moreover
  have "¬(poincare_collinear {?a, ?b, ?c})"
    unfolding poincare_collinear_def
  proof(rule ccontr)
    assume " ¬ (p. is_poincare_line p  {?a, ?b, ?c}  circline_set p)"
    then obtain p where "is_poincare_line p  {?a, ?b, ?c}  circline_set p"
      by auto
    let ?ab = "poincare_line ?a ?b"
    have "p = ?ab"
      using is_poincare_line p  {?a, ?b, ?c}  circline_set p
      using unique_poincare_line[of ?a ?b] ?a  ?b ?a  unit_disc ?b  unit_disc
      by auto
    have "?c  circline_set ?ab"
    proof(rule ccontr)
      assume "¬ ?c  circline_set ?ab"
      have "poincare_between ?a 0h ?b"
        unfolding poincare_between_def
        using cross_ratio_0inf by auto
      hence "0h  circline_set ?ab"
        using ?a  ?b ?a  unit_disc ?b  unit_disc
        using poincare_between_poincare_line_uzv zero_in_unit_disc 
        by blast
      hence "?ab = poincare_line 0h ?a"
        using unique_poincare_line[of ?a ?b] ?a  ?b ?a  unit_disc ?b  unit_disc
        using is_poincare_line p  {?a, ?b, ?c}  circline_set p 
        using p = ?ab poincare_line_circline_set(1) unique_poincare_line
        by (metis add.inverse_neutral divide_minus_left of_complex_zero_iff  zero_in_unit_disc)
      hence "(𝗂/2) * cnj(1/5) = cnj(𝗂/2) * (1/5)"
        using poincare_collinear_zero_iff[of "(𝗂/2)" "(1/5)"]
        using ?a  ?c ¬ ?c  circline_set ?ab ?a  unit_disc ?c  unit_disc p = ?ab
        using 0h  circline_set ?ab is_poincare_line p  {?a, ?b, ?c}  circline_set p 
        using poincare_collinear_def by auto
      thus False
        by simp
    qed 
    thus False
      using p = ?ab is_poincare_line p  {?a, ?b, ?c}  circline_set p 
      by auto
  qed

  moreover

  have "¬( x. x  unit_disc  
                  poincare_distance ?a x = poincare_distance ?b x 
                  poincare_distance ?a x = poincare_distance ?c x)"
  proof(rule ccontr)
    assume "¬ ?thesis"
    then obtain x where "x  unit_disc" "poincare_distance ?a x = poincare_distance ?b x"
                        "poincare_distance ?a x = poincare_distance ?c x"
      by blast
    let ?x = "to_complex x"
    have "poincare_distance_formula' (𝗂/2) ?x = poincare_distance_formula' (-𝗂/2) ?x"
      using poincare_distance ?a x = poincare_distance ?b x
      using x  unit_disc ?a  unit_disc ?b  unit_disc
      by (metis cosh_dist to_complex_of_complex)
    hence "(cmod (𝗂 / 2 - ?x))2 = (cmod (- 𝗂 / 2 - ?x))2"
      unfolding poincare_distance_formula'_def
      apply (simp add:field_simps)
      using x  unit_disc unit_disc_cmod_square_lt_1 by fastforce
    hence "Im ?x = 0"
      unfolding cmod_def
      by (simp add: power2_eq_iff)

    have "1 - (Re ?x)2  0"
      using x  unit_disc unit_disc_cmod_square_lt_1
      using cmod_power2 by force
    hence "24 - 24 * (Re ?x)2  0"
      by simp
    have "poincare_distance_formula' (𝗂/2) ?x = poincare_distance_formula' (1/5) ?x"
      using poincare_distance ?a x = poincare_distance ?c x
      using x  unit_disc ?a  unit_disc ?c  unit_disc
      by (metis cosh_dist to_complex_of_complex)
    hence "(2 + 8 * (Re ?x)2) /(3 - 3 * (Re ?x)2) = 2 * (1 - Re ?x * 5)2 / (24 - 24 * (Re ?x)2)" (is "?lhs = ?rhs")
      unfolding poincare_distance_formula'_def
      apply (simp add:field_simps)
      unfolding cmod_def 
      using Im ?x = 0 
      by (simp add:field_simps)
    hence *: "?lhs * (24 - 24 * (Re ?x)2)  = ?rhs * (24 - 24 * (Re ?x)2) "
      using (24 - 24 * (Re ?x)2)  0 
      by simp
    have "?lhs * (24 - 24 * (Re ?x)2) = (2 + 8 * (Re ?x)2) * 8"
      using (24 - 24 * (Re ?x)2)  0 1 - (Re ?x)2  0
      by (simp add:field_simps)
    have "?rhs * (24 - 24 * (Re ?x)2) = 2 * (1 - Re ?x * 5)2"
      using (24 - 24 * (Re ?x)2)  0 1 - (Re ?x)2  0
      by (simp add:field_simps)
    hence "(2 + 8 * (Re ?x)2) * 8 = 2 * (1 - Re ?x * 5)2"
      using * ?lhs * (24 - 24 * (Re ?x)2) = (2 + 8 * (Re ?x)2) * 8
      by simp      
    hence "7 * (Re ?x)2 + 10 * (Re ?x) + 7 = 0"
      by (simp add:field_simps comm_ring_1_class.power2_diff)
    thus False
      using discriminant_iff[of 7 "Re (to_complex x)" 10 7] discrim_def[of 7 10 7]
      by auto
  qed

  ultimately show ?thesis
    apply (rule_tac x="?a" in exI)
    apply (rule_tac x="?b" in exI)
    apply (rule_tac x="?c" in exI)
    by auto
qed

(* ------------------------------------------------------------------ *)
subsection‹Continuity axiom›
(* ------------------------------------------------------------------ *)

text ‹The set $\phi$ is on the left of the set $\psi$›
abbreviation set_order where
 "set_order A φ ψ  x unit_disc. y unit_disc.  φ x  ψ y  poincare_between A x y"
text ‹The point $B$ is between the sets $\phi$ and $\psi$›
abbreviation point_between_sets where
 "point_between_sets φ B ψ  x unit_disc. y unit_disc.  φ x  ψ y  poincare_between x B y"

lemma  continuity:
  assumes " A  unit_disc. set_order A φ ψ"
  shows   " B  unit_disc. point_between_sets φ B ψ"
proof (cases "( x0  unit_disc. φ x0)  ( y0  unit_disc. ψ y0)")
  case False
  thus ?thesis
    using assms by blast
next
  case True
  then obtain Y0 where "ψ Y0" "Y0  unit_disc"
    by auto
  obtain A where *: "A  unit_disc" "set_order A φ ψ"
    using assms
    by auto
  show ?thesis
  proof(cases " x  unit_disc. φ x  x = A")
    case True
    thus ?thesis
      using A  unit_disc
      using poincare_between_nonstrict(1) by blast
  next
    case False
    then obtain X0 where "φ X0" "X0  A" "X0  unit_disc"
      by auto
    have "Y0  A"
    proof(rule ccontr)
      assume "¬ Y0  A"
      hence " x  unit_disc. φ x  poincare_between A x A"
        using * ψ Y0
        by (cases A) force
      hence " x  unit_disc. φ x  x = A"
        using * poincare_between_sandwich by blast
      thus False
        using False by auto
    qed

    show ?thesis
    proof (cases " B  unit_disc. φ B  ψ B")
      case True
      then obtain B where "B  unit_disc" "φ B" "ψ B"
        by auto
      hence " x  unit_disc. φ x  poincare_between A x B"
        using * by auto
      have " y  unit_disc. ψ y  poincare_between A B y"
        using * B  unit_disc φ B
        by auto

      show ?thesis
      proof(rule+)
        show "B  unit_disc"
          by fact
      next
        fix x y
        assume "x  unit_disc" "y  unit_disc" "φ x  ψ y"
        hence "poincare_between A x B" "poincare_between A B y"
          using  x  unit_disc. φ x  poincare_between A x B
          using  y  unit_disc. ψ y  poincare_between A B y
          by simp+
        thus "poincare_between x B y"
          using x  unit_disc y  unit_disc B  unit_disc A  unit_disc
          using poincare_between_transitivity[of A x B y]
          by simp
      qed
    next
      case False
      have "poincare_between A X0 Y0"
        using φ X0 ψ Y0 * Y0  unit_disc X0  unit_disc
        by auto
      have " φ.  ψ. set_order A φ ψ  ¬ ( B  unit_disc. φ B  ψ B)  φ X0  
                      ( y  unit_disc. ψ y)  ( x  unit_disc. φ x)
                    ( B  unit_disc. point_between_sets φ B ψ)"
            (is "?P A X0")
      proof (rule wlog_positive_x_axis[where P="?P"])
        show "A  unit_disc"
          by fact
      next
        show "X0  unit_disc"
          by fact
      next
        show "A  X0"
          using X0  A by simp
      next
        fix M u v
        let ?M = "λ x. moebius_pt M x"
        let ?Mu = "?M u" and ?Mv = "?M v"
        assume hip: "unit_disc_fix M" "u  unit_disc" "v  unit_disc" "u  v"
               "?P ?Mu ?Mv"
        show "?P u v"
        proof safe
          fix φ ψ x y
          assume "set_order u φ ψ" "¬ (Bunit_disc. φ B  ψ B)" "φ v"
                  "y  unit_disc" "ψ y" "x  unit_disc" "φ x"

          let ?Mφ = "λ X'.  X. φ X  ?M X = X'" 
          let ?Mψ = "λ X'.  X. ψ X  ?M X = X'"

          obtain  where " = ?Mφ" by simp
          obtain  where " = ?Mψ" by simp

          have " ?Mv"
            using φ v using  = ?Mφ 
            by blast
          moreover
          have "¬ ( B unit_disc.  B   B)"
            using ¬ (Bunit_disc. φ B  ψ B)
            using  = ?Mφ  = ?Mψ
            by (metis hip(1) moebius_pt_invert unit_disc_fix_discI unit_disc_fix_moebius_inv)
          moreover
          have " y  unit_disc.  y"
            using y  unit_disc ψ y   = ?Mψ unit_disc_fix M
            by auto
          moreover
          have "set_order ?Mu ?Mφ ?Mψ"
          proof ((rule ballI)+, rule impI)                                       
            fix Mx My
            assume "Mx  unit_disc" "My  unit_disc" "?Mφ Mx  ?Mψ My"
            then obtain x y where "φ x  ?M x = Mx" "ψ y  ?M y = My"
              by blast

            hence "x  unit_disc" "y  unit_disc"
              using Mx  unit_disc My  unit_disc unit_disc_fix M
              by (metis moebius_pt_comp_inv_left unit_disc_fix_discI unit_disc_fix_moebius_inv)+

            hence "poincare_between u x y"
              using set_order u φ ψ
              using Mx  unit_disc My  unit_disc φ x  ?M x = Mx ψ y  ?M y = My
              by blast
            then show "poincare_between ?Mu Mx My"
              using φ x  ?M x = Mx ψ y  ?M y = My
              using x  unit_disc y  unit_disc u  unit_disc unit_disc_fix M 
              using unit_disc_fix_moebius_preserve_poincare_between by blast
          qed

          hence  "set_order ?Mu  "
            using  = ?Mφ  = ?Mψ
            by simp
          ultimately
          have " Mb  unit_disc. point_between_sets  Mb "
            using hip(5)
            by blast
          then obtain Mb where bbb: 
            "Mb  unit_disc" "point_between_sets ?Mφ Mb ?Mψ"
            using  = ?Mφ  = ?Mψ
            by auto

          let ?b = "moebius_pt (moebius_inv M) Mb"
          show " b  unit_disc. point_between_sets φ b ψ"
          proof (rule_tac x="?b" in bexI, (rule ballI)+, rule impI)
            fix x y
            assume "x  unit_disc" "y  unit_disc" "φ x  ψ y"
            hence "poincare_between u x y"
              using set_order u φ ψ
              by blast
            
            let ?Mx = "?M x" and ?My = "?M y"

            have "?Mφ ?Mx" "?Mψ ?My"
              using φ x  ψ y
              by blast+
            have "?Mx  unit_disc" "?My  unit_disc"
              using x  unit_disc unit_disc_fix M y  unit_disc
              by auto

            hence "poincare_between ?Mx Mb ?My"
              using ?Mφ ?Mx ?Mψ ?My ?Mx  unit_disc ?My  unit_disc bbb
              by auto

            then show "poincare_between x ?b y"
              using unit_disc_fix M 
              using x  unit_disc y  unit_disc Mb  unit_disc ?Mx  unit_disc ?My  unit_disc
              using unit_disc_fix_moebius_preserve_poincare_between[of M x ?b y]
              by auto
          next
            show "?b  unit_disc"
              using bbb unit_disc_fix M
              by auto
          qed
        qed
      next
        fix X
        assume xx: "is_real X" "0 < Re X" "Re X < 1"
        let ?X = "of_complex X"
        show "?P 0h ?X"
        proof ((rule allI)+, rule impI, (erule conjE)+)
          fix φ ψ
          assume "set_order 0h φ ψ" "¬ (Bunit_disc. φ B  ψ B)" "φ ?X" 
                 "yunit_disc. ψ y" "xunit_disc. φ x"
          have "?X  unit_disc"
            using xx
            by (simp add: cmod_eq_Re)

          have ψpos: " y  unit_disc. ψ y  (is_real (to_complex y)  Re (to_complex y) > 0)"
          proof(rule ballI, rule impI)
            fix y
            let ?y = "to_complex y"
            assume "y  unit_disc" "ψ y"

            hence "poincare_between 0h ?X y"
              using set_order 0h φ ψ
              using ?X  unit_disc φ ?X
              by auto

            thus "is_real ?y  0 < Re ?y"
              using xx ?X  unit_disc y  unit_disc
              by (metis (mono_tags, opaque_lifting) arg_0_iff of_complex_zero_iff poincare_between_0uv poincare_between_sandwich to_complex_of_complex unit_disc_to_complex_inj zero_in_unit_disc)
          qed

          have φnoneg: " x  unit_disc. φ x  (is_real (to_complex x)  Re (to_complex x)  0)"
          proof(rule ballI, rule impI)
            fix x
            assume "x  unit_disc" "φ x"

            obtain y where "y  unit_disc" "ψ y"
              using  y  unit_disc. ψ y by blast

            let ?x = "to_complex x" and ?y = "to_complex y"

            have "is_real ?y" "Re ?y > 0"
              using ψpos ψ y y  unit_disc
              by auto

            have "poincare_between 0h x y"
              using set_order 0h φ ψ
              using x  unit_disc φ x yunit_disc ψ y
              by auto

            thus "is_real ?x  0  Re ?x"
              using x  unit_disc y  unit_disc is_real (to_complex y) ψ y
              using set_order 0h φ ψ
              using φ ?X ?X  unit_disc Re ?y > 0
              by (metis arg_0_iff le_less of_complex_zero poincare_between_0uv to_complex_of_complex zero_complex.simps(1) zero_complex.simps(2))
          qed

          have φlessψ: "xunit_disc. yunit_disc. φ x  ψ y  Re (to_complex x) < Re (to_complex y)"
          proof((rule ballI)+, rule impI)
            fix x y
            let ?x = "to_complex x" and ?y = "to_complex y"
            assume "x  unit_disc" "y  unit_disc" "φ x  ψ y"

            hence "poincare_between 0h x y"
              using set_order 0h φ ψ
              by auto
            moreover
            have "is_real ?x" "Re ?x  0"
              using φnoneg
              using x  unit_disc φ x  ψ y by auto
            moreover
            have "is_real ?y" "Re ?y > 0"
              using ψpos
              using y  unit_disc φ x  ψ y by auto
            ultimately
            have "Re ?x  Re ?y"
              using x  unit_disc y  unit_disc
              by (metis Re_complex_of_real arg_0_iff le_less of_complex_zero poincare_between_0uv rcis_cmod_Arg rcis_zero_arg to_complex_of_complex)

            have "Re ?x  Re ?y"
              using φ x  ψ y is_real ?x is_real ?y
              using ¬ (Bunit_disc. φ B  ψ B) x  unit_disc y  unit_disc
              by (metis complex.expand unit_disc_to_complex_inj)

            thus "Re ?x < Re ?y"
              using Re ?x  Re ?y by auto
          qed

          have " b  unit_disc.  x  unit_disc.  y  unit_disc. 
                    is_real (to_complex b)  
                    (φ x  ψ y  (Re (to_complex x)  Re (to_complex b)  Re (to_complex b)  Re (to_complex y)))"
          proof-
            let ?Phi = "{x. (of_complex (cor x))  unit_disc  φ (of_complex (cor x))}"

            have " x  unit_disc. φ x  Re (to_complex x)  Sup ?Phi"
            proof(safe)
              fix x
              let ?x = "to_complex x"
              assume "x  unit_disc" "φ x"
              hence "is_real ?x" "Re ?x  0"
                using φnoneg
                by auto
              hence "cor (Re ?x) = ?x"
                 using complex_of_real_Re by blast
              hence "of_complex (cor (Re ?x))  unit_disc"
                using x  unit_disc 
                by (metis inf_notin_unit_disc of_complex_to_complex)
              moreover
              have "φ (of_complex (cor (Re ?x)))"
                using cor (Re ?x) = ?x φ x x  unit_disc
                by (metis inf_notin_unit_disc of_complex_to_complex)
              ultimately
              have "Re ?x  ?Phi"
                by auto

              have "M. x  ?Phi. x  M"
                using φlessψ
                using  y  unit_disc. ψ y
                by (metis (mono_tags, lifting) Re_complex_of_real le_less mem_Collect_eq to_complex_of_complex)

              thus "Re ?x  Sup ?Phi"
                using cSup_upper[of "Re ?x" ?Phi]
                unfolding bdd_above_def
                using Re ?x  ?Phi
                by auto                
            qed

            have " y  unit_disc. ψ y  Sup ?Phi  Re (to_complex y)"
            proof (safe)
              fix y
              let ?y = "to_complex y"
              assume "ψ y" "y  unit_disc"
              show "Sup ?Phi  Re ?y"
              proof (rule ccontr)
                assume "¬ ?thesis"
                hence "Re ?y < Sup ?Phi"
                  by auto

                have " x. φ (of_complex (cor x))  (of_complex (cor x))  unit_disc"
                proof -
                  obtain x' where "x'  unit_disc" "φ x'"
                    using  x  unit_disc. φ x by blast
                  let ?x' = "to_complex x'"
                  have "is_real ?x'"
                    using x'  unit_disc φ x'
                    using φnoneg
                    by auto
                  hence "cor (Re ?x') = ?x'"
                    using complex_of_real_Re by blast
                  hence "x' = of_complex (cor (Re ?x'))"
                    using x'  unit_disc
                    by (metis inf_notin_unit_disc of_complex_to_complex)
                  show ?thesis
                    apply (rule_tac x="Re ?x'" in exI)
                    using x'  unit_disc 
                    apply (subst (asm) x' = of_complex (cor (Re ?x')), simp)
                    using φ x'
                    by (subst (asm) (2) x' = of_complex (cor (Re ?x')), simp)               
                qed

                hence "?Phi  {}"
                  by auto

                then obtain x where "φ (of_complex (cor x))" "Re ?y < x"
                                    "(of_complex (cor x))  unit_disc"
                  using Re ?y < Sup ?Phi
                  using less_cSupE[of "Re ?y" ?Phi]
                  by auto
                moreover
                have "Re ?y < Re (to_complex (of_complex (cor x)))"
                  using Re ?y < x 
                  by simp
                ultimately
                show False
                  using φlessψ
                  using ψ y y  unit_disc
                  by (metis less_not_sym)
              qed
            qed

            thus ?thesis
              using  x  unit_disc. φ x  Re (to_complex x)  Sup ?Phi
              apply (rule_tac x="(of_complex (cor (Sup ?Phi)))" in bexI, simp)
              using yunit_disc. ψ y φ ?X ?X  unit_disc
              using yunit_disc. ψ y  is_real (to_complex y)  0 < Re (to_complex y)
              by (smt complex_of_real_Re inf_notin_unit_disc norm_of_real of_complex_to_complex to_complex_of_complex unit_disc_iff_cmod_lt_1 xx(2))
          qed

          then obtain B where "B  unit_disc" "is_real (to_complex B)"
            "xunit_disc. yunit_disc. φ x  ψ y  Re (to_complex x)  Re (to_complex B) 
             Re (to_complex B)  Re (to_complex y)"
            by blast

          show " b  unit_disc. point_between_sets φ b ψ"
          proof (rule_tac x="B" in bexI)
            show "B  unit_disc"
              by fact
          next
            show "point_between_sets φ B ψ"
            proof ((rule ballI)+, rule impI)
              fix x y 
              let ?x = "to_complex x" and ?y = "to_complex y" and ?B = "to_complex B"
              assume "x  unit_disc" "y  unit_disc" "φ x  ψ y"

              hence "Re ?x  Re ?B  Re ?B  Re ?y"
                using xunit_disc. yunit_disc. φ x  ψ y  Re (to_complex x)  Re ?B 
                       Re (to_complex B)  Re (to_complex y)
                by auto
              moreover
              have "is_real ?x" "Re ?x  0"
                using φnoneg
                using x  unit_disc φ x  ψ y
                by auto
              moreover
              have "is_real ?y" "Re ?y > 0"
                using ψpos
                using y  unit_disc φ x  ψ y
                by auto
              moreover
              have "cor (Re ?x) = ?x"
                using complex_of_real_Re is_real ?x by blast
              hence "x = of_complex (cor (Re ?x))"
                using x  unit_disc
                by (metis inf_notin_unit_disc of_complex_to_complex)
              moreover
              have "cor (Re ?y) = ?y"
                using complex_of_real_Re is_real ?y by blast
              hence "y = of_complex (cor (Re ?y))"
                using y  unit_disc
                by (metis inf_notin_unit_disc of_complex_to_complex)
              moreover
              have "cor (Re ?B) = ?B"
                using complex_of_real_Re is_real (to_complex  B) by blast
              hence "B = of_complex (cor (Re ?B))"
                using B  unit_disc
                by (metis inf_notin_unit_disc of_complex_to_complex)
              ultimately
              show "poincare_between x B y"
                using is_real (to_complex B) x  unit_disc y  unit_disc B  unit_disc
                using poincare_between_x_axis_uvw[of "Re (to_complex x)" "Re (to_complex B)" "Re (to_complex y)"]
                by (smt Re_complex_of_real arg_0_iff poincare_between_nonstrict(1) rcis_cmod_Arg rcis_zero_arg unit_disc_iff_cmod_lt_1)
            qed
          qed            
        qed
      qed 
      thus ?thesis
        using False φ X0 ψ Y0 * Y0  unit_disc X0  unit_disc
        by auto
    qed      
  qed
qed


(* ------------------------------------------------------------------ *)
subsection‹Limiting parallels axiom›
(* ------------------------------------------------------------------ *)

text ‹Auxiliary definitions›

definition poincare_on_line where
  "poincare_on_line p a b  poincare_collinear {p, a, b}"

definition poincare_on_ray where 
  "poincare_on_ray p a b  poincare_between a p b  poincare_between a b p"

definition poincare_in_angle where
  "poincare_in_angle p a b c 
      b  a  b  c  p  b  ( x  unit_disc. poincare_between a x c  x  a  x  c  poincare_on_ray p b x)"

definition poincare_ray_meets_line where
  "poincare_ray_meets_line a b c d  ( x  unit_disc. poincare_on_ray x a b  poincare_on_line x c d)"

text ‹All points on ray are collinear›
lemma poincare_on_ray_poincare_collinear:
  assumes "p  unit_disc" and "a  unit_disc" and "b  unit_disc" and "poincare_on_ray p a b"
  shows "poincare_collinear {p, a, b}"
  using assms poincare_between_poincare_collinear
  unfolding poincare_on_ray_def
  by (metis insert_commute)

text ‹H-isometries preserve all defined auxiliary relations›

lemma unit_disc_fix_preserves_poincare_on_line [simp]:
  assumes "unit_disc_fix M" and "p  unit_disc" "a  unit_disc" "b  unit_disc"
  shows "poincare_on_line (moebius_pt M p) (moebius_pt M a) (moebius_pt M b)  poincare_on_line p a b"
  using assms
  unfolding poincare_on_line_def
  by auto

lemma unit_disc_fix_preserves_poincare_on_ray [simp]:
  assumes "unit_disc_fix M" "p  unit_disc" "a  unit_disc" "b  unit_disc"
  shows "poincare_on_ray (moebius_pt M p) (moebius_pt M a) (moebius_pt M b)  poincare_on_ray p a b"
  using assms
  unfolding poincare_on_ray_def
  by auto

lemma unit_disc_fix_preserves_poincare_in_angle [simp]:
  assumes "unit_disc_fix M" "p  unit_disc" "a  unit_disc" "b  unit_disc" "c  unit_disc"
  shows "poincare_in_angle (moebius_pt M p) (moebius_pt M a) (moebius_pt M b) (moebius_pt M c)  poincare_in_angle p a b c" (is "?lhs  ?rhs")
proof
  assume "?lhs"
  then obtain Mx where *: "Mx  unit_disc"
      "poincare_between (moebius_pt M a) Mx (moebius_pt M c)"
      "Mx  moebius_pt M a" "Mx  moebius_pt M c"  "poincare_on_ray (moebius_pt M p) (moebius_pt M b) Mx"
      "moebius_pt M b  moebius_pt M a" "moebius_pt M b  moebius_pt M c" "moebius_pt M p  moebius_pt M b"
    unfolding poincare_in_angle_def
    by auto
  obtain x where "Mx = moebius_pt M x" "x  unit_disc"
    by (metis "*"(1) assms(1) image_iff unit_disc_fix_iff)
  thus ?rhs
    using * assms
    unfolding poincare_in_angle_def
    by auto
next
  assume ?rhs
  then obtain x where *: "x  unit_disc"
      "poincare_between a x c"
      "x  a" "x  c"  "poincare_on_ray p b x"
      "b  a" "b  c" "p  b"
    unfolding poincare_in_angle_def
    by auto
  thus ?lhs
    using assms
    unfolding poincare_in_angle_def
    by auto (rule_tac x="moebius_pt M x" in bexI, auto)
qed

lemma unit_disc_fix_preserves_poincare_ray_meets_line [simp]:
  assumes "unit_disc_fix M" "a  unit_disc" "b  unit_disc" "c  unit_disc" "d  unit_disc"
  shows "poincare_ray_meets_line (moebius_pt M a) (moebius_pt M b) (moebius_pt M c) (moebius_pt M d)  poincare_ray_meets_line a b c d" (is "?lhs  ?rhs")
proof
  assume ?lhs
  then obtain Mx where *: "Mx  unit_disc" "poincare_on_ray Mx (moebius_pt M a) (moebius_pt M b)" 
    "poincare_on_line Mx (moebius_pt M c) (moebius_pt M d)"
    unfolding poincare_ray_meets_line_def
    by auto
  obtain x where "Mx = moebius_pt M x" "x  unit_disc"
    by (metis "*"(1) assms(1) image_iff unit_disc_fix_iff)
  thus ?rhs
    using assms *
    unfolding poincare_ray_meets_line_def poincare_on_line_def
    by auto
next
  assume ?rhs
  then obtain x where *: "x  unit_disc" "poincare_on_ray x a b" 
    "poincare_on_line x c d"
    unfolding poincare_ray_meets_line_def
    by auto
  thus ?lhs
    using assms *
    unfolding poincare_ray_meets_line_def poincare_on_line_def
    by auto (rule_tac x="moebius_pt M x" in bexI, auto)
qed

text ‹H-lines that intersect on the absolute do not meet (they do not share a common h-point)›
lemma tangent_not_meet:
  assumes "x1  unit_disc" and "x2  unit_disc" and "x1  x2" and "¬ poincare_collinear {0h, x1, x2}"
  assumes "i  ideal_points (poincare_line x1 x2)" "a  unit_disc" "a  0h" "poincare_collinear {0h, a, i}"
  shows "¬ poincare_ray_meets_line 0h a x1 x2"
proof (rule ccontr)
  assume "¬ ?thesis"
  then obtain x where "x  unit_disc" "poincare_on_ray x 0h a" "poincare_collinear {x, x1, x2}"
    unfolding poincare_ray_meets_line_def poincare_on_line_def
    by auto

  have "poincare_collinear {0h, a, x}"
    using poincare_on_ray x 0h a x  unit_disc a  unit_disc
    by (meson poincare_between_poincare_collinear poincare_between_rev poincare_on_ray_def poincare_on_ray_poincare_collinear zero_in_unit_disc)

  have "x  0h"
    using ¬ poincare_collinear {0h, x1, x2} poincare_collinear {x, x1, x2}
    unfolding poincare_collinear_def
    by (auto simp add: assms(2) assms(3) poincare_between_rev)

  let ?l1 = "poincare_line 0h a"
  let ?l2 = "poincare_line x1 x2"

  have "i  circline_set unit_circle"
    using i  ideal_points (poincare_line x1 x2)
    using assms(3) ideal_points_on_unit_circle is_poincare_line_poincare_line by blast

  have "i  circline_set ?l1"
    using poincare_collinear {0h, a, i}
    unfolding poincare_collinear_def
    using a  unit_disc a  0h
    by (metis insert_subset unique_poincare_line zero_in_unit_disc)

  moreover

  have "x  circline_set ?l1"
    using a  unit_disc a  0h poincare_collinear {0h, a, x} x  unit_disc
    by (metis poincare_collinear3_between poincare_between_poincare_line_uvz poincare_between_poincare_line_uzv poincare_line_sym zero_in_unit_disc)

  moreover

  have "inversion x  circline_set ?l1"
    using poincare_collinear {0h, a, x}
    using poincare_line_inversion_full[of "0h" a x] a  unit_disc a  0h x  unit_disc
    by (metis poincare_collinear3_between is_poincare_line_inverse_point is_poincare_line_poincare_line poincare_between_poincare_line_uvz poincare_between_poincare_line_uzv poincare_line_sym zero_in_unit_disc)

  moreover

  have "x  circline_set ?l2"
    using poincare_collinear {x, x1, x2} x1  x2 x1  unit_disc x2  unit_disc x  unit_disc
    by (metis insert_commute inversion_noteq_unit_disc poincare_between_poincare_line_uvz poincare_between_poincare_line_uzv poincare_collinear3_iff poincare_line_sym_general)

  moreover

  hence "inversion x  circline_set ?l2"
    using  x1  x2 x1  unit_disc x2  unit_disc x  unit_disc
    using poincare_line_inversion_full[of x1 x2 x]
    unfolding circline_set_def
    by auto

  moreover

  have "i  circline_set ?l2"
    using x1  x2 x1  unit_disc x2  unit_disc
    using i  ideal_points ?l2
    by (simp add: ideal_points_on_circline)

  moreover

  have "x  inversion x"
    using x  unit_disc
    using inversion_noteq_unit_disc by fastforce

  moreover

  have "x  i"
    using x  unit_disc
    using i  circline_set unit_circle circline_set_def inversion_noteq_unit_disc 
    by fastforce+

  moreover

  have "inversion x  i"
    using i  circline_set unit_circle x  i circline_set_def inversion_unit_circle 
    by fastforce

  ultimately
          
  have "?l1 = ?l2"
    using unique_circline_set[of x "inversion x" i]
    by blast

  hence "0h  circline_set ?l2"
    by (metis a  0h poincare_line_circline_set(1))

  thus False
    using ¬ poincare_collinear {0h, x1, x2}
    unfolding poincare_collinear_def
    using poincare_collinear {x, x1, x2} x1  x2 x1  unit_disc x2  unit_disc poincare_collinear_def unique_poincare_line
    by auto
qed 

lemma limiting_parallels:
  assumes "a  unit_disc" and "x1  unit_disc" and "x2  unit_disc" and "¬ poincare_on_line a x1 x2"
  shows "a1unit_disc. a2unit_disc.
          ¬ poincare_on_line a a1 a2 
          ¬ poincare_ray_meets_line a a1 x1 x2  ¬ poincare_ray_meets_line a a2 x1 x2 
          (a'unit_disc. poincare_in_angle a' a1 a a2  poincare_ray_meets_line a a' x1 x2)" (is "?P a x1 x2")
proof-
  have "¬ poincare_collinear {a, x1, x2}"
    using ¬ poincare_on_line a x1 x2
    unfolding poincare_on_line_def
    by simp

  have " x1 x2. x1  unit_disc  x2  unit_disc  ¬ poincare_collinear {a, x1, x2}  ?P a x1 x2" (is "?Q a")
  proof (rule wlog_zero[OF a  unit_disc])
    fix a u
    assume *: "u  unit_disc" "cmod a < 1"
    hence uf: "unit_disc_fix (blaschke a)"
      by simp
    assume **: "?Q (moebius_pt (blaschke a) u)"
    show "?Q u"
    proof safe
      fix x1 x2
      let ?M = "moebius_pt (blaschke a)"
      assume xx: "x1  unit_disc" "x2  unit_disc" "¬ poincare_collinear {u, x1, x2}"
      hence MM: "?M x1  unit_disc  ?M x2 unit_disc  ¬ poincare_collinear {?M u, ?M x1, ?M x2}"   
        using *
        by auto
      show "?P u x1 x2" (is "a1unit_disc. a2unit_disc. ?P' a1 a2 u x1 x2")
      proof-
        obtain Ma1 Ma2 where MM: "Ma1  unit_disc" "Ma2  unit_disc" "?P' Ma1 Ma2 (?M u) (?M x1) (?M x2)"   
          using **[rule_format, OF MM]
          by blast
        hence MM': "a'unit_disc. poincare_in_angle a' Ma1 (?M u) Ma2  poincare_ray_meets_line (?M u) a' (?M x1) (?M x2)"
          by auto
        obtain a1 a2 where a: "a1  unit_disc" "a2  unit_disc" "?M a1 = Ma1" "?M a2 = Ma2"
          using uf
          by (metis Ma1  unit_disc Ma2  unit_disc image_iff unit_disc_fix_iff)

        have "a'unit_disc. poincare_in_angle a' a1 u a2  poincare_ray_meets_line u a' x1 x2"
        proof safe
          fix a'
          assume "a'  unit_disc" "poincare_in_angle a' a1 u a2"
          thus "poincare_ray_meets_line u a' x1 x2"
            using MM(1-2) MM'[rule_format, of "?M a'"] * uf a xx
            by (meson unit_disc_fix_discI unit_disc_fix_preserves_poincare_in_angle unit_disc_fix_preserves_poincare_ray_meets_line)
        qed

        hence "?P' a1 a2 u x1 x2"
          using MM * uf xx a
          by auto
          
        thus ?thesis
          using a1  unit_disc a2  unit_disc
          by blast
      qed
    qed
  next
    show "?Q 0h"
    proof safe
      fix x1 x2
      assume "x1  unit_disc" "x2  unit_disc"
      assume "¬ poincare_collinear {0h, x1, x2}"
      show "?P 0h x1 x2"
      proof-
        let ?lx = "poincare_line x1 x2"

        have "x1  x2"
          using x1  unit_disc x2  unit_disc¬ poincare_collinear  {0h, x1, x2}
          using poincare_collinear3_between                  
          by auto

        have lx: "is_poincare_line ?lx"
          using is_poincare_line_poincare_line[OF x1  x2]
          by simp

        obtain i1 i2 where "ideal_points ?lx = {i1, i2}"
          by (meson x1  x2 is_poincare_line_poincare_line obtain_ideal_points)
      
        let ?li = "poincare_line i1 i2"
        let ?i1 = "to_complex i1"
        let ?i2 = "to_complex i2"

        have "i1  unit_circle_set" "i2  unit_circle_set"
          using lx ideal_points ?lx = {i1, i2}
          unfolding unit_circle_set_def
          by (metis ideal_points_on_unit_circle insertI1, metis ideal_points_on_unit_circle insertI1 insertI2)
                                                               
        have "i1  i2"
          using ideal_points ?lx = {i1, i2} x1  unit_disc x1  x2 x2  unit_disc ideal_points_different(1) 
          by blast

        let ?a1 = "of_complex (?i1 / 2)"
        let ?a2 = "of_complex (?i2 / 2)"
        let ?la = "poincare_line ?a1 ?a2"

        have "?a1  unit_disc" "?a2  unit_disc"
          using i1  unit_circle_set i2  unit_circle_set
          unfolding unit_circle_set_def unit_disc_def disc_def circline_set_def
          by auto (transfer, transfer, case_tac i1, case_tac i2, simp add: vec_cnj_def)+

        have "?a1  0h" "?a2  0h" 
          using i1  unit_circle_set i2  unit_circle_set
          unfolding unit_circle_set_def
          by auto

        have "?a1  ?a2"
          using i1  i2
          by (metis i1  unit_circle_set i2  unit_circle_set circline_set_def divide_cancel_right inversion_infty inversion_unit_circle mem_Collect_eq of_complex_to_complex of_complex_zero to_complex_of_complex unit_circle_set_def zero_neq_numeral)

        have "poincare_collinear {0h, ?a1, i1}"
          unfolding poincare_collinear_def
          using ?a1  0h[symmetric] is_poincare_line_poincare_line[of "0h" ?a1]
          unfolding circline_set_def
          apply (rule_tac x="poincare_line 0h ?a1" in exI, auto)
          apply (transfer, transfer, auto simp add: vec_cnj_def)
          done                                                               

        have "poincare_collinear {0h, ?a2, i2}"
          unfolding poincare_collinear_def
          using ?a2  0h[symmetric] is_poincare_line_poincare_line[of "0h" ?a2]
          unfolding circline_set_def
          apply (rule_tac x="poincare_line 0h ?a2" in exI, auto)
          apply (transfer, transfer, auto simp add: vec_cnj_def)
          done                                                               

        have "¬ poincare_ray_meets_line 0h ?a1 x1 x2"
          using tangent_not_meet[of x1 x2 i1 ?a1]
          using x1  unit_disc x2  unit_disc ?a1  unit_disc x1  x2 ¬ poincare_collinear {0h, x1, x2}
          using ideal_points ?lx = {i1, i2} ?a1  0h poincare_collinear {0h, ?a1, i1}
          by simp

        moreover

        have "¬ poincare_ray_meets_line 0h ?a2 x1 x2"
          using tangent_not_meet[of x1 x2 i2 ?a2]
          using x1  unit_disc x2  unit_disc ?a2  unit_disc x1  x2 ¬ poincare_collinear {0h, x1, x2}
          using ideal_points ?lx = {i1, i2} ?a2  0h poincare_collinear {0h, ?a2, i2}
          by simp

        moreover

        have "a'  unit_disc. poincare_in_angle a' ?a1 0h ?a2  poincare_ray_meets_line 0h a' x1 x2"
          unfolding poincare_in_angle_def
        proof safe
          fix a' a
          assume *: "a'  unit_disc" "a  unit_disc" "poincare_on_ray a' 0h a" "a'  0h"
                    "poincare_between ?a1 a ?a2" "a  ?a1" "a  ?a2"
          show "poincare_ray_meets_line 0h a' x1 x2"
          proof-
            have " a' a1 a2 x1 x2 i1 i2.
                  a'  unit_disc  x1  unit_disc  x2  unit_disc  x1  x2 
                  ¬ poincare_collinear {0h, x1, x2}  ideal_points (poincare_line x1 x2) = {i1, i2} 
                  a1 = of_complex (to_complex i1 / 2)  a2 = of_complex (to_complex i2 / 2) 
                  i1  i2  a1  a2  poincare_collinear {0h, a1, i1}  poincare_collinear {0h, a2, i2} 
                  a1  unit_disc  a2  unit_disc  i1  unit_circle_set  i2  unit_circle_set 
                  poincare_on_ray a' 0h a  a'  0h  poincare_between a1 a a2  a  a1  a  a2 
                  poincare_ray_meets_line 0h a' x1 x2" (is " a' a1 a2 x1 x2 i1 i2. ?R 0h a' a1 a2 x1 x2 i1 i2 a")
            proof (rule wlog_rotation_to_positive_x_axis[OF a  unit_disc])
              let ?R' = "λ a zero.  a' a1 a2 x1 x2 i1 i2. ?R zero a' a1 a2 x1 x2 i1 i2 a"
              fix xa
              assume xa: "is_real xa" "0 < Re xa" "Re xa < 1"
              let ?a = "of_complex xa"
              show "?R' ?a 0h"
              proof safe
                fix a' a1 a2 x1 x2 i1 i2
                let ?i1 = "to_complex i1" and ?i2 = "to_complex i2"
                let ?a1 = "of_complex (?i1 / 2)" and ?a2 = "of_complex (?i2 / 2)"
                let ?la = "poincare_line ?a1 ?a2" and ?lx = "poincare_line x1 x2" and ?li = "poincare_line i1 i2"
                assume "a'  unit_disc" "x1  unit_disc" "x2  unit_disc" "x1  x2"
                assume "¬ poincare_collinear {0h, x1, x2}" "ideal_points ?lx = {i1, i2}"
                assume "poincare_on_ray a' 0h ?a" "a'  0h"
                assume "poincare_between ?a1 ?a ?a2"  "?a  ?a1" "?a  ?a2"
                assume "i1  i2" "?a1  ?a2" "poincare_collinear {0h, ?a1, i1}"  "poincare_collinear {0h, ?a2, i2}"
                assume "?a1  unit_disc"  "?a2  unit_disc"
                assume "i1  unit_circle_set" "i2  unit_circle_set"
                show "poincare_ray_meets_line 0h a' x1 x2"
                proof-   
                  have "?lx = ?li"
                    using ideal_points ?lx = {i1, i2} x1  x2 ideal_points_line_unique
                    by auto

                  have lx: "is_poincare_line ?lx"
                    using is_poincare_line_poincare_line[OF x1  x2]
                    by simp

                  have "x1  circline_set ?lx" "x2  circline_set ?lx"
                    using lx x1  x2
                    by auto

                  have "?lx  x_axis"
                    using ¬ poincare_collinear {0h, x1, x2} x1  circline_set ?lx x2  circline_set ?lx lx
                    unfolding poincare_collinear_def 
                    by auto

                  have "0h  circline_set ?lx"
                    using ¬ poincare_collinear {0h, x1, x2} lx x1  circline_set ?lx x2  circline_set ?lx
                    unfolding poincare_collinear_def
                    by auto

                  have "xa  0" "?a  0h" 
                    using xa
                    by auto
                  hence "0h  ?a"
                    by metis

                  have "?a  positive_x_axis"
                    using xa
                    unfolding positive_x_axis_def 
                    by simp

                  have "?a  unit_disc"
                    using xa
                    by (auto simp add: cmod_eq_Re)

                  have "?a  circline_set ?la"
                    using poincare_between ?a1 ?a ?a2
                    using ?a1  ?a2 ?a  unit_disc ?a1  unit_disc ?a2  unit_disc poincare_between_poincare_line_uzv 
                    by blast
                                                
                  have "?a1  circline_set ?la" "?a2  circline_set ?la"
                    by (auto simp add: ?a1  ?a2)

                  have la: "is_poincare_line ?la"
                    using is_poincare_line_poincare_line[OF ?a1  ?a2]
                    by  simp

                  have inv: "inversion i1 = i1" "inversion i2 = i2"
                    using i1  unit_circle_set i2  unit_circle_set
                    by (auto simp add: circline_set_def unit_circle_set_def)

                  have  "i1  h" "i2  h"
                    using inv
                    by auto

                  have "?a1  circline_set x_axis  ?a2  circline_set x_axis"
                  proof (rule ccontr)
                    assume "¬ ?thesis"
                    hence "?a1  circline_set x_axis  ?a2  circline_set x_axis"
                      by auto
                    hence "?la = x_axis"
                    proof
                      assume "?a1  circline_set x_axis"
                      hence "{?a, ?a1}  circline_set ?la  circline_set x_axis"
                        using ?a  circline_set ?la ?a1  circline_set ?la?a  positive_x_axis
                        using circline_set_x_axis_I xa(1) 
                        by blast
                      thus "?la = x_axis"
                        using unique_is_poincare_line[of ?a ?a1 ?la x_axis]
                        using ?a1  unit_disc ?a  unit_disc la ?a  ?a1
                        by auto
                    next
                      assume "?a2  circline_set x_axis"
                      hence "{?a, ?a2}  circline_set ?la  circline_set x_axis"
                        using ?a  circline_set ?la ?a2  circline_set ?la ?a  positive_x_axis
                        using circline_set_x_axis_I xa(1) 
                        by blast
                      thus "?la = x_axis"
                        using unique_is_poincare_line[of ?a ?a2 ?la x_axis]
                        using ?a2  unit_disc ?a  unit_disc la ?a  ?a2
                        by auto
                    qed

                    hence "i1  circline_set x_axis  i2  circline_set x_axis"
                      using ?a1  circline_set ?la ?a2  circline_set ?la
                      by (metis i1  h i2  h of_complex (to_complex i1 / 2)  unit_disc of_complex (to_complex i2 / 2)  unit_disc poincare_collinear {0h, of_complex (to_complex i1 / 2), i1} poincare_collinear {0h, of_complex (to_complex i2 / 2), i2} divide_eq_0_iff inf_not_of_complex inv(1) inv(2) inversion_noteq_unit_disc of_complex_to_complex of_complex_zero_iff poincare_collinear3_poincare_lines_equal_general poincare_line_0_real_is_x_axis poincare_line_circline_set(2) zero_in_unit_disc zero_neq_numeral)

                    thus False
                      using ?lx  x_axis unique_is_poincare_line_general[of i1 i2 ?li x_axis] i1  i2 inv ?lx = ?li
                      by auto
                  qed

                  hence "?la  x_axis"
                    using ?a1  ?a2 poincare_line_circline_set(1)      
                    by fastforce

                  have "intersects_x_axis_positive ?la"
                    using intersects_x_axis_positive_iff[of ?la] ?la  x_axis ?a  circline_set ?la la
                    using ?a  unit_disc ?a  positive_x_axis
                    by auto

                  have "intersects_x_axis ?lx"
                  proof-
                    have "Arg (to_complex ?a1) * Arg (to_complex ?a2) < 0"
                      using poincare_between ?a1 ?a ?a2 ?a1  unit_disc ?a2  unit_disc
                      using poincare_between_x_axis_intersection[of ?a1 ?a2 "of_complex xa"]
                      using ?a1  ?a2 ?a  unit_disc ?a1  circline_set x_axis  ?a2  circline_set x_axis ?a  positive_x_axis
                      using ?a  circline_set ?la                                                                                         
                      unfolding positive_x_axis_def
                      by simp

                    moreover

                    have " x y x' y' :: real. sgn x' = sgn x; sgn y' = sgn y  x*y < 0  x'*y' < 0"
                      by (metis sgn_less sgn_mult)

                    ultimately

                    have "Im (to_complex ?a1) * Im (to_complex ?a2) < 0"
                      using arg_Im_sgn[of "to_complex ?a1"] arg_Im_sgn[of "to_complex ?a2"]
                      using ?a1  unit_disc ?a2  unit_disc ?a1  circline_set x_axis  ?a2  circline_set x_axis 
                      using inf_or_of_complex[of ?a1] inf_or_of_complex[of ?a2] circline_set_x_axis
                      by (metis circline_set_x_axis_I to_complex_of_complex)

                    thus ?thesis
                      using ideal_points_intersects_x_axis[of ?lx i1 i2]
                      using ideal_points ?lx = {i1, i2} lx ?lx  x_axis
                      by simp
                  qed

                  have "intersects_x_axis_positive ?lx"
                  proof-
                    have "cmod ?i1 = 1" "cmod ?i2 = 1"                
                      using i1  unit_circle_set i2  unit_circle_set 
                      unfolding unit_circle_set_def 
                      by auto

                    let ?a1' = "?i1 / 2" and ?a2' = "?i2 / 2"
                    let ?Aa1 = "𝗂 * (?a1' * cnj ?a2' - ?a2' * cnj ?a1')" and 
                        ?Ba1 = "𝗂 * (?a2' * cor ((cmod ?a1')2 + 1) - ?a1' * cor ((cmod ?a2')2 + 1))"

                    have "?Aa1  0  ?Ba1  0"
                      using cmod (to_complex i1) = 1  cmod (to_complex i2) = 1 ?a1  ?a2              
                      by (auto simp add: power_divide complex_mult_cnj_cmod)

                    have "is_real ?Aa1"
                      by simp

                    have "?a1  inversion ?a2"
                      using ?a1  unit_disc ?a2  unit_disc inversion_noteq_unit_disc by fastforce

                    hence "Re ?Ba1 / Re ?Aa1 < -1"
                      using intersects_x_axis_positive ?la ?a1  ?a2
                      using intersects_x_axis_positive_mk_circline[of ?Aa1 ?Ba1] ?Aa1  0  ?Ba1  0 is_real ?Aa1
                      using poincare_line_non_homogenous[of ?a1 ?a2]
                      by (simp add: Let_def)

                    moreover

                    let ?i1' = "to_complex i1" and ?i2' = "to_complex i2"
                    let ?Ai1 = "𝗂 * (?i1' * cnj ?i2' - ?i2' * cnj ?i1')" and 
                        ?Bi1 = "𝗂 * (?i2' * cor ((cmod ?i1')2 + 1) - ?i1' * cor ((cmod ?i2')2 + 1))"

                    have "?Ai1  0  ?Bi1  0"
                      using cmod (to_complex i1) = 1  cmod (to_complex i2) = 1 ?a1  ?a2              
                      by (auto simp add: power_divide complex_mult_cnj_cmod)

                    have "is_real ?Ai1"
                      by simp

                    have "sgn (Re ?Bi1 / Re ?Ai1) = sgn (Re ?Ba1 / Re ?Aa1)"  
                    proof-
                      have "Re ?Bi1 / Re ?Ai1 = (Im ?i1 * 2 - Im ?i2 * 2) /
                                                (Im ?i2 * (Re ?i1 * 2) - Im ?i1 * (Re ?i2 * 2))"
                        using cmod ?i1 = 1  cmod ?i2 = 1
                        by (auto simp add: complex_mult_cnj_cmod field_simps)
                      also have "... =  (Im ?i1 - Im ?i2) /
                                        (Im ?i2 * (Re ?i1) - Im ?i1 * (Re ?i2))" (is "... = ?expr")
                        apply (subst left_diff_distrib[symmetric])
                        apply (subst semiring_normalization_rules(18))+
                        apply (subst left_diff_distrib[symmetric])
                        by (metis mult.commute mult_divide_mult_cancel_left_if zero_neq_numeral)
                      finally have 1: "Re ?Bi1 / Re ?Ai1 = (Im ?i1 - Im ?i2) / (Im ?i2 * (Re ?i1) - Im ?i1 * (Re ?i2))"
                        .

                
                      have "Re ?Ba1 / Re ?Aa1 = (Im ?i1 * 20 - Im ?i2 * 20) /
                                                (Im ?i2 * (Re ?i1 * 16) - Im ?i1 * (Re ?i2 * 16))"
                        using cmod (to_complex i1) = 1  cmod (to_complex i2) = 1
                        by (auto simp add: complex_mult_cnj_cmod field_simps)
                      also have "... = (20 / 16) * ((Im ?i1 - Im ?i2) /
                                       (Im ?i2 * (Re ?i1) - Im ?i1 * (Re ?i2)))"
                        apply (subst left_diff_distrib[symmetric])+
                        apply (subst semiring_normalization_rules(18))+
                        apply (subst left_diff_distrib[symmetric])+
                        by (metis (no_types, opaque_lifting)  field_class.field_divide_inverse mult.commute times_divide_times_eq)
                      finally have 2: "Re ?Ba1 / Re ?Aa1 = (5 / 4) * ((Im ?i1 - Im ?i2) / (Im ?i2 * (Re ?i1) - Im ?i1 * (Re ?i2)))"
                        by simp

                      have "?expr  0"
                        using Re ?Ba1 / Re ?Aa1 < -1
                        apply  (subst (asm) 2)
                        by linarith
                      thus ?thesis
                        apply (subst 1, subst 2)
                        apply (simp only: sgn_mult)
                        by simp
                    qed
                      

                    moreover

                    have "i1  inversion i2"
                      by (simp add: i1  i2 inv(2))

                    have "(Re ?Bi1 / Re ?Ai1)2 > 1"
                    proof-
                      have "?Ai1 = 0  (Re ?Bi1)2 > (Re ?Ai1)2"
                        using intersects_x_axis ?lx
                        using i1  i2 i1  h i2  h i1  inversion i2
                        using intersects_x_axis_mk_circline[of ?Ai1 ?Bi1] ?Ai1  0  ?Bi1  0 is_real ?Ai1
                        using poincare_line_non_homogenous[of i1 i2] ?lx = ?li
                        by metis
                                                  
                      moreover
                      have "?Ai1  0"
                      proof (rule ccontr)
                        assume "¬ ?thesis"
                        hence "0h  circline_set ?li"
                          unfolding circline_set_def
                          apply simp
                          apply (transfer, transfer, case_tac i1, case_tac i2)
                          by (auto simp add: vec_cnj_def field_simps)
                        thus False
                          using 0h  circline_set ?lx ?lx = ?li
                          by simp
                      qed

                      ultimately

                      have "(Re ?Bi1)2 > (Re ?Ai1)2"    
                        by auto

                      moreover

                      have "Re ?Ai1  0"
                        using is_real ?Ai1 ?Ai1  0
                        by (simp add: complex_eq_iff)

                      ultimately

                      show ?thesis
                        by (simp add: power_divide)
                    qed

                    moreover

                    {
                      fix x1 x2 :: real
                      assume "sgn x1 = sgn x2" "x1 < -1" "x22 > 1"
                      hence "x2 < -1"
                        by (smt one_power2 real_sqrt_abs real_sqrt_less_iff sgn_neg sgn_pos)
                    }

                    ultimately

                    have "Re ?Bi1 / Re ?Ai1 < -1"
                      by metis

                    thus ?thesis
                      using i1  i2 i1  h i2  h i1  inversion i2
                      using intersects_x_axis_positive_mk_circline[of ?Ai1 ?Bi1] ?Ai1  0  ?Bi1  0 is_real ?Ai1
                      using poincare_line_non_homogenous[of i1 i2] ?lx = ?li
                      by (simp add: Let_def)
                  qed

                  then obtain x where x: "x  unit_disc" "x  circline_set ?lx  positive_x_axis"
                    using intersects_x_axis_positive_iff[OF lx ?lx  x_axis]
                    by auto

                  have "poincare_on_ray x 0h a'  poincare_collinear {x1, x2, x}"
                  proof
                    show "poincare_collinear {x1, x2, x}"
                      using x lx x1  circline_set ?lx x2  circline_set ?lx
                      unfolding poincare_collinear_def
                      by auto
                  next
                    show "poincare_on_ray x 0h a'"
                      unfolding poincare_on_ray_def
                    proof-
                      have  "a'  circline_set x_axis"
                        using poincare_on_ray a' 0h ?a xa 0h  ?a xa  0 a'  unit_disc
                        unfolding poincare_on_ray_def 
                        using poincare_line_0_real_is_x_axis[of "of_complex xa"]
                        using poincare_between_poincare_line_uvz[of "0h" "of_complex xa" a']
                        using poincare_between_poincare_line_uzv[of "0h" "of_complex xa" a']
                        by (auto simp  add: cmod_eq_Re)

                      then obtain xa' where xa': "a' = of_complex xa'" "is_real xa'"
                        using a'  unit_disc
                        using circline_set_def on_circline_x_axis 
                        by auto

                      hence "-1 < Re xa'" "Re xa' < 1" "xa'  0"
                        using a'  unit_disc a'  0h
                        by (auto simp add: cmod_eq_Re)

                      hence "Re xa' > 0" "Re xa' < 1" "is_real xa'"
                        using poincare_on_ray a' 0h (of_complex xa)
                        using poincare_between_x_axis_0uv[of "Re xa'" "Re xa"]
                        using poincare_between_x_axis_0uv[of "Re xa" "Re xa'"]
                        using circline_set_positive_x_axis_I[of "Re xa'"]
                        using xa xa' complex_of_real_Re
                        unfolding poincare_on_ray_def
                        by (smt of_real_0, linarith, blast)

                      moreover

                      obtain xx where "is_real xx" "Re xx > 0" "Re xx < 1" "x = of_complex xx"
                        using x
                        unfolding positive_x_axis_def
                        using circline_set_def cmod_eq_Re on_circline_x_axis
                        by auto

                      ultimately

                      show "poincare_between 0h x a'  poincare_between 0h a' x"
                        using a' = of_complex xa'
                        by (smt a'  unit_disc arg_0_iff poincare_between_0uv poincare_between_def to_complex_of_complex x(1))
                    qed

                  qed

                  thus ?thesis               
                    using x  unit_disc
                    unfolding poincare_ray_meets_line_def poincare_on_line_def
                    by (metis insert_commute)
                qed
              qed
            next
              show "a  0h"
              proof (rule ccontr)
                assume "¬ ?thesis"
                then obtain k where "k<0" "to_complex ?a1 = cor k * to_complex ?a2"
                  using poincare_between_u0v[OF ?a1  unit_disc ?a2  unit_disc ?a1  0h ?a2  0h]
                  using poincare_between ?a1 a ?a2
                  by auto
                hence "to_complex i1 = cor k * to_complex i2" "k < 0"
                  by auto
                hence "0h  circline_set (poincare_line x1 x2)"
                  using ideal_points_proportional[of "poincare_line x1 x2" i1 i2 k] ideal_points (poincare_line x1 x2) = {i1, i2}
                  using is_poincare_line_poincare_line[OF x1  x2]
                  by simp
                thus False
                  using ¬ poincare_collinear {0h, x1, x2}
                  using is_poincare_line_poincare_line[OF x1  x2]
                  unfolding poincare_collinear_def
                  by (meson x1  x2 empty_subsetI insert_subset poincare_line_circline_set(1) poincare_line_circline_set(2))
              qed
            next
              fix φ u
              let ?R' = "λ a zero.  a' a1 a2 x1 x2 i1 i2. ?R zero a' a1 a2 x1 x2 i1 i2 a"
              let ?M = "moebius_pt (moebius_rotation φ)"
              assume *: "u  unit_disc" "u  0h" and **: "?R' (?M u) 0h"
              have uf: "unit_disc_fix (moebius_rotation φ)"
                by simp
              have "?M 0h = 0h"
                by auto
              hence **: "?R' (?M u) (?M 0h)"
                using **
                by simp
              show "?R' u 0h"
              proof (rule allI)+
                fix a' a1 a2 x1 x2 i1 i2
                have i1: "i1  unit_circle_set  moebius_pt (moebius_rotation φ) (of_complex (to_complex i1 / 2)) = of_complex (to_complex (moebius_pt (moebius_rotation φ) i1) / 2)"
                  using unit_circle_set_def by force
                
                have i2: "i2  unit_circle_set  moebius_pt (moebius_rotation φ) (of_complex (to_complex i2 / 2)) = of_complex (to_complex (moebius_pt (moebius_rotation φ) i2) / 2)"
                  using unit_circle_set_def by force
                
                show "?R 0h a' a1 a2 x1 x2 i1 i2 u"
                  using **[rule_format, of "?M a'" "?M x1" "?M x2" "?M i1" "?M i2" "?M a1" "?M a2"] uf * 
                  apply (auto simp del:  moebius_pt_moebius_rotation_zero moebius_pt_moebius_rotation)
                  using i1 i2
                  by simp
              qed
            qed
            thus ?thesis                                                                  
              using a'  unit_disc x1  unit_disc x2  unit_disc x1  x2 
              using ¬ poincare_collinear {0h, x1, x2} ideal_points ?lx = {i1, i2} i1  i2
              using ?a1  ?a2 poincare_collinear {0h, ?a1, i1} poincare_collinear {0h, ?a2, i2}
              using ?a1  unit_disc ?a2  unit_disc i1  unit_circle_set i2  unit_circle_set
              using poincare_on_ray a' 0h a a'  0h poincare_between ?a1 a ?a2 a  ?a1 a  ?a2
              by blast
          qed
        qed

        moreover

        have "¬ poincare_on_line 0h ?a1 ?a2"
        proof
          assume *: "poincare_on_line 0h ?a1 ?a2"
          hence "poincare_collinear {0h, ?a1, ?a2}"
            unfolding poincare_on_line_def
            by simp
          hence "poincare_line 0h ?a1 = poincare_line 0h ?a2"
            using poincare_collinear3_poincare_lines_equal_general[of "0h" ?a1 ?a2]
            using ?a1  unit_disc ?a1  0h ?a2  unit_disc ?a2  0h 
            by (metis inversion_noteq_unit_disc zero_in_unit_disc)

          have "i1  circline_set (poincare_line 0h ?a1)"
            using poincare_collinear {0h, ?a1, i1}
            using poincare_collinear3_poincare_line_general[of i1 "0h" ?a1]
            using ?a1  unit_disc ?a1  0h
            by (metis insert_commute inversion_noteq_unit_disc zero_in_unit_disc)
          moreover
          have "i2  circline_set (poincare_line 0h ?a1)"
            using poincare_collinear {0h, ?a2, i2}
            using poincare_collinear3_poincare_line_general[of i2 "0h" ?a2]
            using ?a2  unit_disc ?a2  0h poincare_line 0h ?a1 = poincare_line 0h ?a2
            by (metis insert_commute inversion_noteq_unit_disc zero_in_unit_disc)

          ultimately

          have "poincare_collinear {0h, i1, i2}"
            using ?a1  unit_disc ?a1  0h poincare_collinear {0h, ?a1, i1}
            by (smt insert_subset poincare_collinear_def unique_poincare_line zero_in_unit_disc)
          hence "0h  circline_set (poincare_line i1 i2)"
            using poincare_collinear3_poincare_line_general[of "0h" i1 i2]
            using i1  i2 i2  unit_circle_set unit_circle_set_def
            by force

          moreover

          have "?lx = ?li"
            using ideal_points ?lx = {i1, i2} x1  x2 ideal_points_line_unique
            by auto

          ultimately

          show False
            using ¬ poincare_collinear {0h, x1, x2}
            using x1  x2 poincare_line_poincare_collinear3_general
            by auto
        qed          

        ultimately

        show ?thesis
          using ?a1  unit_disc ?a2  unit_disc
          by blast
      qed
    qed
  qed
  thus ?thesis
    using x1  unit_disc x2  unit_disc ¬ poincare_collinear {a, x1, x2}
    by blast
qed                                                                        

subsection‹Interpretation of locales›

global_interpretation PoincareTarskiAbsolute: TarskiAbsolute where cong  = p_congruent and betw = p_between
  defines p_on_line = PoincareTarskiAbsolute.on_line and
          p_on_ray = PoincareTarskiAbsolute.on_ray and
          p_in_angle = PoincareTarskiAbsolute.in_angle and
          p_ray_meets_line = PoincareTarskiAbsolute.ray_meets_line
proof-
  show "TarskiAbsolute p_congruent p_between"
  proof
    text‹ 1. Reflexivity of congruence ›
    fix x y
    show "p_congruent x y y x"
      unfolding p_congruent_def
      by transfer (simp add: poincare_distance_sym)
  next
    text‹ 2. Transitivity of congruence ›
    fix x y z u v w
    show "p_congruent x y z u  p_congruent x y v w  p_congruent z u v w"
      by (transfer, simp)
  next
    text‹ 3. Identity of congruence ›
    fix x y z
    show "p_congruent x y z z  x = y"
      unfolding p_congruent_def
      by transfer (simp add: poincare_distance_eq_0_iff)
  next
    text‹ 4. Segment construction ›
    fix x y a b
    show " z. p_between x y z  p_congruent y z a b"
      using segment_construction
      unfolding p_congruent_def
      by transfer (simp, blast)
  next
    text‹ 5. Five segment ›
    fix x y z x' y' z' u u'
    show "x  y  p_between x y z  p_between x' y' z' 
      p_congruent x y x' y'  p_congruent y z y' z' 
      p_congruent x u x' u'  p_congruent y u y' u' 
      p_congruent z u z' u'"
      unfolding p_congruent_def
      apply transfer
      using five_segment_axiom                                             
      by meson
  next
    text‹ 6. Identity of betweeness ›
    fix x y
    show "p_between x y x  x = y"
      by transfer (simp add: poincare_between_sum_distances poincare_distance_eq_0_iff poincare_distance_sym)
  next
    text‹ 7. Pasch ›
    fix x y z u v
    show "p_between x u z  p_between y v z  ( a. p_between u a y  p_between x a v)"
      apply transfer
      using Pasch
      by blast
  next
    text‹ 8. Lower dimension ›
    show " a.  b.  c. ¬ p_between a b c  ¬ p_between b c a  ¬ p_between c a b"
      apply (transfer)
      using lower_dimension_axiom
      by simp
  next
    text‹ 9. Upper dimension ›
    fix x y z u v
    show "p_congruent x u x v  p_congruent y u y v  p_congruent z u z v  u  v 
          p_between x y z  p_between y z x  p_between z x y"
      unfolding p_congruent_def
      by (transfer, simp add: upper_dimension_axiom)
  qed
qed 


interpretation PoincareTarskiHyperbolic: TarskiHyperbolic
  where cong = p_congruent and betw = p_between
proof
  text‹ 10. Euclid negation ›
  show " a b c d t. p_between a d t  p_between b d c  a  d 
                   ( x y. p_between a b x  p_between a c y  ¬ p_between x t y)"
    using negated_euclidean_axiom
    by transfer (auto, blast)
next
  fix a x1  x2
  assume "¬ TarskiAbsolute.on_line p_between a x1 x2"
  hence "¬ p_on_line a x1 x2"
    using TarskiAbsolute.on_line_def[OF PoincareTarskiAbsolute.TarskiAbsolute_axioms]
    using PoincareTarskiAbsolute.on_line_def
    by simp
  text‹ 11. Limiting parallels  ›
  thus "a1 a2.
          ¬ TarskiAbsolute.on_line p_between a a1 a2 
          ¬ TarskiAbsolute.ray_meets_line p_between a a1 x1 x2 
          ¬ TarskiAbsolute.ray_meets_line p_between a a2 x1 x2 
          (a'. TarskiAbsolute.in_angle p_between a' a1 a a2  TarskiAbsolute.ray_meets_line p_between a a' x1 x2)"
    unfolding TarskiAbsolute.in_angle_def[OF PoincareTarskiAbsolute.TarskiAbsolute_axioms]
    unfolding TarskiAbsolute.on_ray_def[OF PoincareTarskiAbsolute.TarskiAbsolute_axioms]
    unfolding TarskiAbsolute.ray_meets_line_def[OF PoincareTarskiAbsolute.TarskiAbsolute_axioms]
    unfolding TarskiAbsolute.on_ray_def[OF PoincareTarskiAbsolute.TarskiAbsolute_axioms]
    unfolding TarskiAbsolute.on_line_def[OF PoincareTarskiAbsolute.TarskiAbsolute_axioms]
    unfolding PoincareTarskiAbsolute.on_line_def
    apply transfer
  proof- 
    fix a x1 x2
    assume *: "a  unit_disc" "x1  unit_disc" "x2  unit_disc"
              "¬ (poincare_between a x1 x2  poincare_between x1 a x2  poincare_between x1 x2 a)"
    hence "¬ poincare_on_line a x1 x2"
      using poincare_collinear3_iff[of a x1 x2]
      using poincare_between_rev poincare_on_line_def by blast
    hence "a1unit_disc.
            a2unit_disc.
            ¬ poincare_on_line a a1 a2 
            ¬ poincare_ray_meets_line a a1 x1 x2 
            ¬ poincare_ray_meets_line a a2 x1 x2 
            (a'unit_disc.
                poincare_in_angle a' a1 a a2 
                poincare_ray_meets_line a a' x1 x2)"
      using limiting_parallels[of a x1 x2] *
      by blast
    then obtain a1 a2 where **: "a1unit_disc" "a2unit_disc" "¬ poincare_on_line a a1 a2"
                            "¬ poincare_ray_meets_line a a2 x1 x2"
                            "¬ poincare_ray_meets_line a a1 x1 x2"
                            "a'unit_disc.
                                  poincare_in_angle a' a1 a a2 
                                  poincare_ray_meets_line a a' x1 x2"
      by blast
    have "¬ (x{z. z  unit_disc}.
                    (poincare_between a x a1 
                     poincare_between a a1 x) 
                    (poincare_between x x1 x2 
                     poincare_between x1 x x2 
                     poincare_between x1 x2 x))"
      using ¬ poincare_ray_meets_line a a1 x1 x2
      unfolding poincare_on_line_def poincare_ray_meets_line_def poincare_on_ray_def
      using poincare_collinear3_iff[of _ x1 x2] poincare_between_rev *(2, 3)
      by auto
    moreover
    have "¬ (x{z. z  unit_disc}.
                    (poincare_between a x a2 
                     poincare_between a a2 x) 
                    (poincare_between x x1 x2 
                     poincare_between x1 x x2 
                     poincare_between x1 x2 x))"
      using ¬ poincare_ray_meets_line a a2 x1 x2
      unfolding poincare_on_line_def poincare_ray_meets_line_def poincare_on_ray_def
      using poincare_collinear3_iff[of _ x1 x2] poincare_between_rev *(2, 3)
      by auto
    moreover
    have "¬ (poincare_between a a1 a2  poincare_between a1 a a2  poincare_between a1 a2 a)"
      using ¬ poincare_on_line a a1 a2 poincare_collinear3_iff[of a a1 a2]
      using *(1) **(1-2)
      unfolding poincare_on_line_def
      by simp
    moreover 
    have "(a'{z. z  unit_disc}.
                 a  a1 
                 a  a2 
                 a'  a 
                 (x{z. z  unit_disc}.
                     poincare_between a1 x a2 
                     x  a1 
                     x  a2 
                     (poincare_between a a' x 
                      poincare_between a x a')) 
                 (x{z. z  unit_disc}.
                     (poincare_between a x a' 
                      poincare_between a a' x) 
                     (poincare_between x x1 x2 
                      poincare_between x1 x x2 
                      poincare_between x1 x2 x)))"
      using **(6)
      unfolding poincare_on_line_def poincare_in_angle_def poincare_ray_meets_line_def poincare_on_ray_def
      using poincare_collinear3_iff[of _ x1 x2] poincare_between_rev *(2, 3)
      by auto
    ultimately
    show "a1{z. z  unit_disc}.
           a2{z. z  unit_disc}.
             ¬ (poincare_between a a1 a2  poincare_between a1 a a2  poincare_between a1 a2 a) 
             ¬ (x{z. z  unit_disc}.
                    (poincare_between a x a1 
                     poincare_between a a1 x) 
                    (poincare_between x x1 x2 
                     poincare_between x1 x x2 
                     poincare_between x1 x2 x)) 
             ¬ (x{z. z  unit_disc}.
                    (poincare_between a x a2 
                     poincare_between a a2 x) 
                    (poincare_between x x1 x2 
                     poincare_between x1 x x2 
                     poincare_between x1 x2 x)) 
             (a'{z. z  unit_disc}.
                 a  a1 
                 a  a2 
                 a'  a 
                 (x{z. z  unit_disc}.
                     poincare_between a1 x a2 
                     x  a1 
                     x  a2 
                     (poincare_between a a' x 
                      poincare_between a x a')) 
                 (x{z. z  unit_disc}.
                     (poincare_between a x a' 
                      poincare_between a a' x) 
                     (poincare_between x x1 x2 
                      poincare_between x1 x x2 
                      poincare_between x1 x2 x)))" 
      using **(1, 2)
      by auto
   qed
qed

interpretation PoincareElementaryTarskiHyperbolic: ElementaryTarskiHyperbolic p_congruent p_between
proof
  text‹ 12.  Continuity ›
  fix φ ψ
  assume " a.  x.  y. φ x  ψ y  p_between a x y"
  thus " b.  x.  y. φ x  ψ y  p_between x b y"
    apply transfer
    using continuity
    by auto
qed

end