Theory MobiusGyroGroup
theory MobiusGyroGroup
imports Complex_Main HOL.Real_Vector_Spaces HOL.Transcendental MoreComplex
GyroGroup PoincareDisc
begin
definition ozero_m' :: "complex" where
"ozero_m' = 0"
lift_definition ozero_m :: PoincareDisc ("0⇩m") is ozero_m'
unfolding ozero_m'_def
by simp
lemma to_complex_0 [simp]:
shows "to_complex 0⇩m = 0"
by transfer (simp add: ozero_m'_def)
lemma to_complex_0_iff [iff]:
shows "to_complex x = 0 ⟷ x = 0⇩m"
by transfer (simp add: ozero_m'_def)
definition oplus_m' :: "complex ⇒ complex ⇒ complex" where
"oplus_m' a z = (a + z) / (1 + (cnj a) * z)"
lemma oplus_m'_in_disc:
assumes "cmod c1 < 1" "cmod c2 < 1"
shows "cmod (oplus_m' c1 c2) < 1"
proof-
have "Im ((c1 + c2) * (cnj c1 + cnj c2)) = 0"
by (metis complex_In_mult_cnj_zero complex_cnj_add)
moreover
have "Im ((1 + cnj c1 * c2) * (1 + c1 * cnj c2)) = 0"
by (cases c1, cases c2, simp add: field_simps)
ultimately
have 1: "Re (oplus_m' c1 c2 * cnj (oplus_m' c1 c2)) =
Re (((c1 + c2) * (cnj c1 + cnj c2))) /
Re (((1 + cnj c1 * c2) * (1 + c1 * cnj c2)))"
unfolding oplus_m'_def
by (simp add: complex_is_Real_iff)
have "Re (((c1 + c2) * (cnj c1 + cnj c2))) =
(cmod c1)⇧2 + (cmod c2)⇧2 + Re (cnj c1 * c2 + c1 * cnj c2)"
by (smt Re_complex_of_real complex_norm_square plus_complex.simps(1) semiring_normalization_rules(34) semiring_normalization_rules(7))
moreover
have "Re (((1 + cnj c1 * c2) * (1 + c1 * cnj c2))) =
Re (1 + cnj c1 * c2 + cnj c2 * c1 + c1 * cnj c1 * c2 * cnj c2)"
by (simp add: field_simps)
hence *: "Re (((1 + cnj c1 * c2) * (1 + c1 * cnj c2))) =
1 + Re (cnj c1 * c2 + c1 * cnj c2) + (cmod c1)⇧2 * (cmod c2)⇧2"
by (smt Re_complex_of_real ab_semigroup_mult_class.mult_ac(1) complex_In_mult_cnj_zero complex_cnj_one complex_norm_square one_complex.simps(1) one_power2 plus_complex.simps(1) power2_eq_square semiring_normalization_rules(7) times_complex.simps(1))
moreover
have "(cmod c1)⇧2 + (cmod c2)⇧2 < 1 + (cmod c1)⇧2 * (cmod c2)⇧2"
proof-
have "(cmod c1)⇧2 < 1" "(cmod c2)⇧2 < 1"
using assms
by (simp_all add: cmod_def)
hence "(1 - (cmod c1)⇧2) * (1 - (cmod c2)⇧2) > 0"
by simp
thus ?thesis
by (simp add: field_simps)
qed
ultimately
have "Re (((c1 + c2) * (cnj c1 + cnj c2))) < Re (((1 + cnj c1 * c2) * (1 + c1 * cnj c2)))"
by simp
moreover
have "Re (((1 + cnj c1 * c2) * (1 + c1 * cnj c2))) > 0"
by (smt "*" Re_complex_div_lt_0 calculation complex_cnj_add divide_self mult_zero_left one_complex.simps(1) zero_complex.simps(1))
ultimately
have 2: "Re (((c1 + c2) * (cnj c1 + cnj c2))) / Re (((1 + cnj c1 * c2) * (1 + c1 * cnj c2))) < 1"
by (simp add: divide_less_eq)
have "Re (oplus_m' c1 c2 * cnj (oplus_m' c1 c2)) < 1"
using 1 2
by simp
thus ?thesis
by (simp add: complex_mod_sqrt_Re_mult_cnj)
qed
lift_definition oplus_m :: "PoincareDisc ⇒ PoincareDisc ⇒ PoincareDisc" (infixl "⊕⇩m" 100) is oplus_m'
proof-
fix c1 c2
assume "cmod c1 < 1" "cmod c2 < 1"
thus "cmod (oplus_m' c1 c2) < 1"
by (simp add: oplus_m'_in_disc)
qed
definition ominus_m' :: "complex ⇒ complex" where
"ominus_m' z = - z"
lemma ominus_m'_in_disc:
assumes "cmod z < 1"
shows "cmod (ominus_m' z) < 1"
using assms
unfolding ominus_m'_def
by simp
lift_definition ominus_m :: "PoincareDisc ⇒ PoincareDisc" ("⊖⇩m") is ominus_m'
proof-
fix c
assume "cmod c < 1"
thus "cmod (ominus_m' c) < 1"
by (simp add: ominus_m'_def)
qed
lemma m_left_id:
shows "0⇩m ⊕⇩m a = a"
by (transfer, simp add: oplus_m'_def ozero_m'_def)
lemma m_left_inv:
shows "⊖⇩m a ⊕⇩m a = 0⇩m"
by (transfer, simp add: oplus_m'_def ominus_m'_def ozero_m'_def)
definition gyr_m' :: "complex ⇒ complex ⇒ complex ⇒ complex" where
"gyr_m' a b z = ((1 + a * cnj b) / (1 + cnj a * b)) * z"
lift_definition gyr⇩m :: "PoincareDisc ⇒ PoincareDisc ⇒ PoincareDisc ⇒ PoincareDisc" is gyr_m'
proof-
fix a b z
assume "cmod a < 1" "cmod b < 1" "cmod z < 1"
have "cmod (1 + a * cnj b) = cmod (1 + cnj a * b)"
by (metis complex_cnj_add complex_cnj_cnj complex_cnj_mult complex_cnj_one complex_mod_cnj)
hence "cmod ((1 + a * cnj b) / (1 + cnj a * b)) = 1"
by (simp add: ‹cmod a < 1› ‹cmod b < 1› den_not_zero norm_divide)
thus "cmod (gyr_m' a b z) < 1"
using ‹cmod z < 1›
unfolding gyr_m'_def
by (metis mult_cancel_right1 norm_mult)
qed
lemma gyr_m_commute:
"a ⊕⇩m b = gyr⇩m a b (b ⊕⇩m a)"
by transfer (metis (no_types, opaque_lifting) oplus_m'_def gyr_m'_def add.commute den_not_zero mult.commute nonzero_mult_divide_mult_cancel_right2 times_divide_times_eq)
lemma gyr_m_left_assoc:
"a ⊕⇩m (b ⊕⇩m z) = (a ⊕⇩m b) ⊕⇩m gyr⇩m a b z"
proof transfer
fix a b z
assume *: "cmod a < 1" "cmod b < 1" "cmod z < 1"
have 1: "oplus_m' a (oplus_m' b z) =
(a + b + (1 + a * cnj b) * z) /
((cnj a + cnj b) * z + (1 + cnj a * b))"
unfolding gyr_m'_def oplus_m'_def
by (smt "*"(2) "*"(3) ab_semigroup_mult_class.mult_ac(1) add.left_commute add_divide_eq_iff combine_common_factor den_not_zero divide_divide_eq_right mult.commute mult_cancel_right2 nonzero_mult_div_cancel_left semiring_normalization_rules(1) semiring_normalization_rules(23) semiring_normalization_rules(34) times_divide_eq_right)
have 2: "oplus_m' (oplus_m' a b) (gyr_m' a b z) =
((a + b) + (1 + a * cnj b) * z) /
((cnj a + cnj b) * z + (1 + cnj a * b))"
proof-
have x: "((a + b) / (1 + cnj a * b) +
(1 + a * cnj b) / (1 + cnj a * b) * z) =
((a + b) + (1 + a * cnj b) * z) / (1 + cnj a * b)"
by (metis add_divide_distrib times_divide_eq_left)
moreover
have "1 + cnj ((a + b) / (1 + cnj a * b)) *
((1 + a * cnj b) / (1 + cnj a * b) * z) =
1 + (cnj a + cnj b) / (1 + cnj a * b) * z"
using divide_divide_times_eq divide_eq_0_iff mult_eq_0_iff nonzero_mult_div_cancel_left
by force
hence y: "1 + cnj ((a + b) / (1 + cnj a * b)) *
((1 + a * cnj b) / (1 + cnj a * b) * z) =
((cnj a + cnj b) * z + (1 + cnj a * b)) / (1 + cnj a * b)"
by (metis "*"(1) "*"(2) add.commute add_divide_distrib den_not_zero divide_self times_divide_eq_left)
ultimately
show ?thesis
unfolding gyr_m'_def oplus_m'_def
by (subst x, subst y, simp add: "*"(1) "*"(2) den_not_zero)
qed
show "oplus_m' a (oplus_m' b z) =
oplus_m' (oplus_m' a b) (gyr_m' a b z)"
by (subst 1, subst 2, simp)
qed
lemma gyr_m_inv:
"gyr⇩m a b (gyr⇩m b a z) = z"
by transfer (simp add: gyr_m'_def, metis den_not_zero nonzero_mult_div_cancel_left nonzero_mult_divide_mult_cancel_right semiring_normalization_rules(7))
lemma gyr_m_bij:
shows "bij (gyr⇩m a b)"
by (metis bij_betw_def inj_def gyr_m_inv surj_def)
lemma gyr_m_not_degenerate:
shows "∃ z1 z2. gyr⇩m a b z1 ≠ gyr⇩m a b z2"
proof-
obtain z1 z2 :: PoincareDisc where "z1 ≠ z2"
using poincare_disc_two_elems
by blast
hence "gyr⇩m a b z1 ≠ gyr⇩m a b z2"
by (metis gyr_m_inv)
thus ?thesis
by blast
qed
lemma gyr_m_left_loop:
shows "gyr⇩m a b = gyr⇩m (a ⊕⇩m b) b"
proof-
have "∃ z. gyr⇩m (a ⊕⇩m b) b z ≠ 0⇩m"
using gyr_m_not_degenerate
by metis
hence "⋀ z. gyr⇩m a b z = gyr⇩m (a ⊕⇩m b) b z"
proof transfer
fix a b z
assume "∃z∈{z. cmod z < 1}. gyr_m' (oplus_m' a b) b z ≠ ozero_m'"
then obtain z' where
"cmod z' < 1" "gyr_m' (oplus_m' a b) b z' ≠ ozero_m'"
by auto
hence *: "1 + (a + b) / (1 + cnj a * b) * cnj b ≠ 0"
by (simp add: gyr_m'_def oplus_m'_def ozero_m'_def)
assume "cmod a < 1" "cmod b < 1" "cmod z < 1"
have 1: "1 + (a + b) / (1 + cnj a * b) * cnj b =
(1 + cnj a * b + a * cnj b + b * cnj b) / (1 + cnj a * b)"
using ‹cmod a < 1› ‹cmod b < 1› add_divide_distrib den_not_zero divide_self times_divide_eq_left
by (metis (no_types, lifting) ab_semigroup_add_class.add_ac(1) distrib_right)
have 2: "1 + cnj ((a + b) / (1 + cnj a * b)) * b =
(1 + cnj a * b + a * cnj b + b * cnj b) / (1 + a * cnj b)"
by (smt "1" complex_cnj_add complex_cnj_cnj complex_cnj_divide complex_cnj_mult complex_cnj_one semiring_normalization_rules(23) semiring_normalization_rules(7))
have "1 + cnj a * b + a * cnj b + b * cnj b ≠ 0"
using * 1
by auto
then show "gyr_m' a b z = gyr_m' (oplus_m' a b) b z"
unfolding gyr_m'_def oplus_m'_def
by (subst 1, subst 2, simp)
qed
thus ?thesis
by auto
qed
lemma gyr_m_distrib:
shows "gyr⇩m a b (a' ⊕⇩m b') = gyr⇩m a b a' ⊕⇩m gyr⇩m a b b'"
apply transfer
apply (simp add: gyr_m'_def oplus_m'_def)
apply (simp add: add_divide_distrib distrib_left)
done