Theory GyroVectorSpaceIsomorphism

theory GyroVectorSpaceIsomorphism
  imports GyroVectorSpace
begin

locale gyrocarrier_isomorphism' =
       gyrocarrier_norms_embed' to_carrier +
       gyrocarrier to_carrier + 
   G:  gyrocarrier_norms_embed' to_carrier'
   for to_carrier :: "'a::gyrocommutative_gyrogroup  'b::{real_inner, real_normed_algebra_1}" and
       to_carrier' :: "'c::gyrocommutative_gyrogroup  'd::{real_inner, real_normed_algebra_1}"  +
 fixes φ :: "'a  'c"
begin

definition φR :: "real  real" where 
  "φR x = G.to_real' (φ (of_real' x))"

end

locale gyrocarrier_isomorphism = gyrocarrier_isomorphism' +
  assumes φbij [simp]:
    "bij φ"
  assumes φplus [simp]:
    " u v :: 'a. φ (u  v) = φ u  φ v"
  assumes φinner_unit:
    " u v :: 'a. u  0g; v  0g 
                    inner (to_carrier' (φ u) /R G.gyronorm (φ u)) (to_carrier' (φ v) /R G.gyronorm (φ v)) = 
                    inner (to_carrier u /R gyronorm u) (to_carrier v /R gyronorm v)"
  assumes φRgyronorm [simp]:
    " a. φR (gyronorm a) = G.gyronorm (φ a)"
begin

lemma φinvφ [simp]:
  shows "φ (inv φ a) = a"
  by (meson φbij bij_inv_eq_iff)

lemma invφφ [simp]:
  shows "(inv φ) (φ a) = a"
  by (metis φbij bij_inv_eq_iff)

lemma φzero [simp]:
  shows "φ 0g = 0g"
  by (metis φplus gyro_left_cancel gyro_right_id)

lemma φminus [simp]:
  shows "φ ( a) =  (φ a)"
  by (metis φplus φzero gyro_equation_left gyro_left_inv)

lemma invφplus[simp]:
  shows "(inv φ)(a  b) = inv φ a  inv φ b"
  by (metis φbij φplus bij_inv_eq_iff)

lemma φgyr [simp]:
  shows "φ (gyr u v a) = gyr (φ u) (φ v) (φ a)"
  by (simp add: gyr_def)

lemma invφgyr [simp]:
  shows "(inv φ) (gyr u v a) = gyr (inv φ u) (inv φ v) (inv φ a)"
  by (metis φbij φgyr bij_inv_eq_iff)

lemma φinner:
  assumes "u  0g" "v  0g"
  shows "G.gyroinner (φ u) (φ v) =
         (G.gyronorm (φ u) / gyronorm u) *R (G.gyronorm (φ v) / gyronorm v) *R gyroinner u v"
proof-
  have "φ u  0g" "φ v  0g"
    by (metis φbij φzero assms(1) bij_inv_eq_iff)
       (metis φbij φzero assms(2) bij_inv_eq_iff)
  then have "G.gyronorm (φ u)  0" "G.gyronorm (φ v)  0"
    using G.norm_zero_iff 
    by blast+
  then have "inner (to_carrier' (φ u)) (to_carrier' (φ v)) = 
        G.gyronorm (φ u) *R G.gyronorm (φ v) *R inner (to_carrier' (φ u) /R G.gyronorm (φ u)) (to_carrier' (φ v) /R G.gyronorm (φ v))"
    by (smt (verit, ccfv_threshold) divideR_right inner_commute inner_scaleR_right real_scaleR_def)
  also have " = G.gyronorm (φ u) *R G.gyronorm (φ v) *R inner (to_carrier u /R gyronorm u) (to_carrier v /R gyronorm v)"
    using φinner_unit[OF assms]
    by simp
  finally show ?thesis
    unfolding G.gyroinner_def gyroinner_def
    by (simp add: divide_inverse_commute)
qed

lemma gyronorm'gyr:
  shows "G.gyronorm (gyr u v a) = G.gyronorm a"
proof (cases "a = 0g")
  case True
  then show ?thesis
    by (simp add: gyr_id_3)
next
  case False
  then show ?thesis
    by (metis φRgyronorm φinvφ invφgyr norm_gyr)
qed

end

sublocale gyrocarrier_isomorphism  gyrocarrier to_carrier'
proof
  fix u v a b
  show "G.gyroinner (gyr u v a) (gyr u v b) = G.gyroinner a b"
  proof (cases "a = 0g  b = 0g")
    case True
    then show ?thesis
      by (metis G.gyroinner_def G.to_carrier_zero gyr_id_3 inner_zero_left inner_zero_right)
  next
    case False

    let ?Ga = "gyr (inv φ u) (inv φ v) (inv φ a)" and ?Gb = "gyr (inv φ u) (inv φ v) (inv φ b)"

    have "G.gyroinner (gyr u v a) (gyr u v b) = G.gyroinner (φ ?Ga) (φ ?Gb)"
      using invφgyr 
      by simp
    also have " = (G.gyronorm (φ ?Ga) / ?Ga) *R (G.gyronorm (φ ?Gb) / ?Gb) *R ?Ga  ?Gb" 
    proof (subst φinner)
      show "gyr (inv φ u) (inv φ v) (inv φ a)  0g"
        by (metis False φinvφ φzero gyr_id_3 gyr_inj)
    next
      show "gyr (inv φ u) (inv φ v) (inv φ b)  0g"
        by (metis False φinvφ φzero gyr_id_3 gyr_inj)
    qed simp
    also have " = (G.gyronorm (φ ?Ga) / ?Ga) *R (G.gyronorm (φ ?Gb) / ?Gb) *R (inv φ a)  (inv φ b)"
      using inner_gyroauto_invariant
      by presburger
    finally have "G.gyroinner (gyr u v a) (gyr u v b) = (G.gyronorm (gyr u v a) / gyronorm ?Ga) *R (G.gyronorm (gyr u v b) / gyronorm ?Gb) *R (inv φ a)  (inv φ b)"
      by auto

    moreover

    have "G.gyroinner a b = (G.gyronorm a / inv φ a) *R (G.gyronorm b / inv φ b) *R inv φ a  inv φ b"
      using φinner[of "inv φ a" "inv φ b"] 
      by (metis False φinvφ φzero)

    moreover
    have "gyr (inv φ u) (inv φ v) (inv φ a) = inv φ a"
         "gyr (inv φ u) (inv φ v) (inv φ b) = inv φ b"
      by (auto simp add: norm_gyr)

    moreover

    have "G.gyronorm (gyr u v a) = G.gyronorm a"
         "G.gyronorm (gyr u v b) = G.gyronorm b"
      using gyronorm'gyr
      by auto
 
    ultimately

    show ?thesis
      by simp
  qed
qed

locale pre_gyrovector_space_isomorphism' = 
    pre_gyrovector_space to_carrier scale + 
    gyrocarrier_norms_embed' to_carrier + 
  GC: gyrocarrier_norms_embed' to_carrier'  
  for to_carrier :: "'a::gyrocommutative_gyrogroup  'b::{real_inner, real_normed_algebra_1}" and
      to_carrier' :: "'c::gyrocommutative_gyrogroup  'd::{real_inner, real_normed_algebra_1}" and
      scale :: "real  'a  'a" and 
      scale' :: "real  'c  'c"  +
  fixes φ :: "'a  'c"

sublocale pre_gyrovector_space_isomorphism'  gyrocarrier_isomorphism'
  ..

locale pre_gyrovector_space_isomorphism = 
   pre_gyrovector_space_isomorphism' +
   gyrocarrier_isomorphism +
   assumes φscale [simp]:
      " r :: real.  u :: 'a. φ (scale r u) = scale' r (φ u)"
begin

lemma scale'_1:
  shows "scale' 1 a = a"
  using φscale[of 1 "(inv φ) a"]
  by (simp add: scale_1)

lemma scale'_distrib:
  shows "scale' (r1 + r2) a = scale' r1 a  scale' r2 a"
  using φscale[symmetric, of "r1 + r2" "(inv φ) a"]
  using scale_distrib
  by auto

lemma scale'_assoc:
  shows "scale' (r1 * r2) a = scale' r1 (scale' r2 a)"
  using φscale[symmetric, of "r1 * r2" "(inv φ) a"]
  using scale_assoc 
  by force

lemma scale'_gyroauto_id:
  shows "gyr (scale' r1 v) (scale' r2 v) = id"
proof
  fix x
  show "gyr (scale' r1 v) (scale' r2 v) x = id x"
    using φscale[symmetric, of r1 "(inv φ) v"] φscale[symmetric, of r2 "(inv φ) v"]
    by (metis φinvφ gyroauto_id id_apply invφφ invφgyr)
qed

lemma scale'_gyroauto_property:
  shows "gyr u v (scale' r a) = scale' r (gyr u v a)"
  using φscale[of r "inv φ (gyr u v a)"]
  using φscale[of r "inv φ a"]
  by (metis φbij bij_inv_eq_iff gyroauto_property invφgyr)

end

locale gyrovector_space_isomorphism' = 
  pre_gyrovector_space_isomorphism + 
  gyrovector_space_norms_embed scale +
  GC: gyrocarrier_norms_embed to_carrier' scale' +
  assumes φreals:
    "φ ` reals = GC.reals"
begin

lemma φRnorms:
  assumes "a  norms"
  shows "φR a  GC.norms"
  using assms
  by (metis GC.bij_betw_to_real' φR_def φreals bij_betw_iff_bijections bij_reals_norms image_iff)

lemma φof_real'[simp]:
  assumes "a  norms"
  shows "φ (of_real' a) = GC.of_real' (φR a)"
  using assms
  by (metis GC.of_real' φR_def φreals bij_betwE bij_reals_norms image_iff)

lemma φgyronorm [simp]:
  shows "φ (of_real' (gyronorm a)) = GC.of_real' (GC.gyronorm (φ a))"
  by simp

lemma φRplus [simp]:
  assumes "a  norms" "b  norms"
  shows "φR (a R b) = GC.oplusR (φR a) (φR b)"
proof-
  have "φR (a R b) = GC.to_real' (φ (of_real' a)  φ (of_real' b))"
    unfolding φR_def oplusR_def
  proof (subst of_real')
    show "of_real' a  of_real' b  reals"
      by (meson assms(1) assms(2) bij_betwE bij_reals_norms oplus_reals)
  qed simp
  then show ?thesis
    using assms
    unfolding GC.oplusR_def
    by simp
qed

lemma φRplus' [simp]:
  "φR ((a) R (b)) = GC.oplusR (φR (a)) (φR (b))"
  by (simp add: GC.oplusR_def φR_def)

lemma φRtimes [simp]:
  assumes "a  norms"
  shows "φR (r R a) = GC.otimesR r (φR a)"
proof-
  have "φR (r R a) = GC.to_real' (φ (of_real' (to_real' (scale r (of_real' a)))))"
    unfolding φR_def otimesR_def
    by simp
  also have " = GC.to_real' (φ (scale r (of_real' a)))"
    using assms
    by (metis bij_betwE bij_reals_norms of_real' otimes_reals)    
  finally show ?thesis
    using assms
    unfolding GC.otimesR_def
    by simp
qed

lemma φRtimes' [simp]:
  shows "φR (r R (a)) = GC.otimesR r (φR (a))"
  by (simp add: GC.otimesR_def φR_def)

lemma φRinv [simp]:
  assumes "a  norms"
  shows "φR (R a) = GC.oinvR (φR a)"
proof-
  have "φR (R a) = GC.to_real' (φ (of_real' (to_real' ( (of_real' a)))))"
    unfolding φR_def oinvR_def
    by simp
  also have " = GC.to_real' (φ ( (of_real' a)))"
    by (metis assms bij_betwE bij_reals_norms of_real' oinv_reals)
  finally show ?thesis
    using assms
    unfolding GC.oinvR_def
    by simp
qed

lemma φRinv' [simp]:
  "φR (R (a)) = GC.oinvR (φR (a))"
  by (simp add: φR_def GC.oinvR_def)


lemma scale'_prop1':
  assumes "u  0g" "r  0"
  shows "to_carrier' (φ (scale ¦r¦ u)) /R GC.gyronorm (φ (scale ¦r¦ u)) = 
         (to_carrier' (φ u) /R GC.gyronorm (φ u))" (is "?a = ?b")
proof-
  have "scale r u = scale (abs r) u"
    using homogeneity by force

  have "inner ?b ?a =
        inner (to_carrier u /R u) (to_carrier (scale ¦r¦ u) /R scale ¦r¦ u)"
    using φinner_unit[where u=u and v="scale (abs r) u"] 
    by fastforce
  also have " = inner (to_carrier u /R u) (to_carrier u /R u)"
    using scale_prop1[of r u] u  0g r  0 scale r u = scale (abs r) u
    by simp
  finally have "inner ?b ?a = 1"
    by (smt (verit, ccfv_threshold) φinner_unit assms(1) gyronorm_def inverse_nonnegative_iff_nonnegative inverse_nonzero_iff_nonzero left_inverse norm_eq norm_eq_1 norm_le_zero_iff norm_scaleR norm_zero_iff scaleR_eq_0_iff to_carrier_zero_iff)
    
  show ?thesis
  proof (rule inner_eq_1)
    show "inner ?a ?b = 1"
      using inner ?b ?a = 1
      by (simp add: inner_commute)
  next
    show "norm ?a = 1"
      by (smt (verit, ccfv_threshold) φinner_unit assms(1) assms(2) gyronorm_def scale_prop1 inverse_nonnegative_iff_nonnegative inverse_nonzero_iff_nonzero left_inverse local.norm_zero norm_eq norm_ge_zero norm_scaleR norm_zero_iff scaleR_eq_0_iff to_carrier_zero_iff)
  next
    show "norm ?b = 1"
      using GC.norm_zero_iff φzero assms(1) GC.gyronorm_def invφφ inverse_negative_iff_negative left_inverse norm_not_less_zero norm_scaleR
      by (smt (verit, del_insts))
  qed
qed 

lemma scale'_prop1:
  assumes "a  0g" "r  0"
  shows "to_carrier' (scale' ¦r¦ a) /R GC.gyronorm (scale' r a) = to_carrier' a /R GC.gyronorm a"
proof-
  from assms have *: "inv φ a  0g" "r  0"
    by (metis φinvφ φzero, simp)
  show ?thesis
    using scale'_prop1'[OF *]
    by (metis φRgyronorm φinvφ φscale abs_idempotent homogeneity)
qed

lemma scale'_homogeneity:
  shows "GC.gyronorm (scale' r a) = GC.otimesR ¦r¦ (GC.gyronorm a)"
proof-
  have "GC.gyronorm (scale' r a) = GC.gyronorm (φ (scale r (inv φ a)))"
    using φscale[of r "inv φ a"]
    by simp
  also have " = φR (gyronorm (scale r (inv φ a)))"
    by simp
  also have " = φR (¦r¦ R (inv φ a))"
    using homogeneity
    by simp
  also have " =  φR (to_real' (scale ¦r¦ (of_real' (inv φ a))))"
    unfolding otimesR_def
    by simp
  also have " = GC.to_real' (φ (scale ¦r¦ (of_real' (gyronorm (inv φ a)))))"
    using GC.otimesR_def φRtimes otimesR_def
    by force
  also have " = GC.to_real' (scale' ¦r¦ (φ (of_real' (gyronorm (inv φ a)))))"
    using φscale
    by simp
  also have " = GC.to_real' (scale' ¦r¦ (GC.of_real' (GC.gyronorm (φ (inv φ a)))))"
    by (subst φgyronorm, simp)
  finally
  show "GC.gyronorm (scale' r a) = GC.otimesR ¦r¦ (GC.gyronorm a)"
    unfolding GC.otimesR_def
    by simp
qed

end

sublocale gyrovector_space_isomorphism'  GV: pre_gyrovector_space to_carrier' scale'
  by (meson gyrocarrier_axioms scale'_prop1  pre_gyrovector_space.intro pre_gyrovector_space_axioms.intro scale'_1 scale'_assoc scale'_distrib scale'_gyroauto_id scale'_gyroauto_property)

locale gyrovector_space_isomorphism = 
  gyrovector_space_isomorphism' + 
  assumes φRmono:
    " a b. a  norms; b  norms; 0  a; a  b  φR a  φR b" 
begin

lemma scale'_triangle:
  shows  "GC.gyronorm (a  b)  GC.oplusR (GC.gyronorm a) (GC.gyronorm b)"
proof-
  have "GC.gyronorm (a  b) = φR (inv φ a  inv φ b)"
    by simp
  moreover
  have "GC.oplusR (GC.gyronorm a) (GC.gyronorm b) = φR ((inv φ a) R (inv φ b))"
    by simp
  moreover
  have "φR (inv φ a  inv φ b)  φR ((inv φ a) R (inv φ b))"
  proof (rule φRmono)
    show "inv φ a  inv φ b  norms"
      unfolding norms_def
      by auto
  next
    show "inv φ a R (inv φ b)  norms"
    proof (rule oplusR_norms)
      show "inv φ a  norms" "inv φ b  norms"
        unfolding norms_def
        by auto
    qed
  next
    show "0  inv φ a  inv φ b"
      by (simp add: gyronorm_def)
  next
    show "inv φ a  inv φ b  (inv φ a) R (inv φ b)"
      by (simp add: gyrotriangle)
  qed
  ultimately
  show  "GC.gyronorm (a  b)  GC.oplusR (GC.gyronorm a) (GC.gyronorm b)"
    by simp
qed

end

sublocale gyrovector_space_isomorphism  gyrovector_space_norms_embed scale' to_carrier'
  by (meson GC.gyrocarrier_norms_embed_axioms GV.pre_gyrovector_space_axioms gyrocarrier_axioms gyrovector_space_isomorphism.scale'_triangle gyrovector_space_isomorphism_axioms gyrovector_space_norms_embed_axioms.intro gyrovector_space_norms_embed_def scale'_homogeneity)

(* ------------------------------------------------------------ *)

locale gyrocarrier_isomorphism_norms_embed' = gyrovector_space_norms_embed scale to_carrier + 
             GC: gyrocarrier_norms_embed' to_carrier'
  for to_carrier :: "'a::gyrocommutative_gyrogroup  'b::{real_inner, real_normed_algebra_1}" and
      to_carrier' :: "'c::gyrocommutative_gyrogroup  'd::{real_inner, real_normed_algebra_1}" and
      scale :: "real  'a  'a" + 
  fixes scale' :: "real  'c  'c" 
  fixes φ :: "'a  'c"
begin

definition φR :: "real  real" where 
  "φR x = GC.to_real' (φ (of_real' x))"

end

locale gyrocarrier_isomorphism_norms_embed = gyrocarrier_isomorphism_norms_embed' +
  assumes φbij:
    "bij φ"
  assumes φplus [simp]:
    " u v :: 'a. φ (u  v) = φ u  φ v"
  assumes φscale [simp]:
    " r :: real.  u :: 'a. φ (scale r u) = scale' r (φ u)"
  assumes φreals:
    "φ ` reals = GC.reals"
  assumes φRgyronorm [simp]:
    " a. φR (gyronorm a) = GC.gyronorm (φ a)"
  assumes GCoinvRminus:
    " a. a  GC.norms  GC.oinvR a = -a"
begin

lemma φinvφ [simp]:
  shows "φ (inv φ a) = a"
  by (meson φbij bij_inv_eq_iff)

lemma φzero [simp]:
  shows "φ 0g = 0g"
  by (metis φplus gyro_left_cancel gyro_right_id)

lemma φminus [simp]:
  shows "φ ( a) =  (φ a)"
  by (metis φplus φzero gyro_equation_left gyro_left_inv)

lemma φgyronorm [simp]:
  shows "φ (of_real' (gyronorm a)) = GC.of_real' (GC.gyronorm (φ a))"
  by (metis (no_types, opaque_lifting) GC.of_real' φR_def φRgyronorm φreals bij_betwE bij_reals_norms image_eqI norm_in_norms)

lemma φRinv' [simp]:
  "φR (R (a)) = GC.oinvR (φR (a))"
  by (simp add: GC.oinvR_def φR_def)
end

sublocale gyrocarrier_isomorphism_norms_embed  GV': gyrocarrier_norms_embed to_carrier' scale'
proof
  fix a b
  assume "a  GC.reals" "b  GC.reals"
  then obtain x y where 
    "a = GC.of_real' (φR (inv φ x))  a = GC.of_real' (- φR (inv φ x))" 
    "b = GC.of_real' (φR (inv φ y))  b = GC.of_real' (- φR (inv φ y))"
    unfolding GC.reals_def GC.norms_def GC.of_real'_def
    by fastforce
  then have "a  b = GC.of_real' (φR (inv φ x))  GC.of_real' (φR (inv φ y)) 
             a  b = GC.of_real' (φR (inv φ x))  GC.of_real' (- φR (inv φ y))  
             a  b = GC.of_real' (- φR (inv φ x))  GC.of_real' (- φR (inv φ y))  
             a  b = GC.of_real' (- φR (inv φ x))  GC.of_real' (φR (inv φ y))"
    by auto
  then have "a  b = GC.of_real' (φR (inv φ x))  GC.of_real' (φR (inv φ y)) 
             a  b = GC.of_real' (φR (inv φ x))  GC.of_real' (φR (R (inv φ y)))  
             a  b = GC.of_real' (φR (R (inv φ x)))  GC.of_real' (φR (R ((inv φ y))))  
             a  b = GC.of_real' (φR (R (inv φ x)))  GC.of_real' (φR (inv φ y))"
    by (simp add: GCoinvRminus)
  then show "a  b  GC.reals"
    by (smt (verit, del_insts) a  GC.reals b  GC.reals φplus φreals image_iff oplus_reals)
next
  fix a
  assume "a  GC.reals"
  then obtain x where 
    "a = GC.of_real' (φR (inv φ x))  a = GC.of_real' (- φR (inv φ x))" 
    unfolding GC.reals_def GC.norms_def GC.of_real'_def
    by fastforce
  then have " a =  (GC.of_real' (φR (inv φ x))) 
              a =  (GC.of_real' (- φR (inv φ x)))"
    by auto
  then have " a =  (GC.of_real' (φR (inv φ x))) 
              a =  (GC.of_real' (φR (R (inv φ x))))"
    by (simp add: GCoinvRminus)
  then show " a  GC.reals"
    by (metis (no_types, opaque_lifting) a  GC.reals φminus φreals image_iff oinv_reals)
next
  fix a r
  assume "a  GC.reals"
  then obtain x where 
    "a = GC.of_real' (φR (inv φ x))  a = GC.of_real' (- φR (inv φ x))" 
    unfolding GC.reals_def GC.norms_def GC.of_real'_def
    by fastforce
  then have "scale' r a = scale' r (GC.of_real' (φR (inv φ x))) 
             scale' r a = scale' r (GC.of_real' (- φR (inv φ x)))"
    by auto
  then have "scale' r a = scale' r (GC.of_real' (φR (inv φ x))) 
             scale' r a = scale' r (GC.of_real' (φR (R (inv φ x))))"
    by (simp add: GCoinvRminus)
  then show "scale' r a  GC.reals"
    by (smt (verit, best) a  GC.reals φreals φscale image_iff otimes_reals)
qed

end