passagemath-symbolics 10.8.1a1__cp314-cp314t-musllinux_1_2_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- passagemath_symbolics/__init__.py +3 -0
- passagemath_symbolics-10.8.1a1.dist-info/METADATA +186 -0
- passagemath_symbolics-10.8.1a1.dist-info/RECORD +181 -0
- passagemath_symbolics-10.8.1a1.dist-info/WHEEL +5 -0
- passagemath_symbolics-10.8.1a1.dist-info/top_level.txt +3 -0
- sage/all__sagemath_symbolics.py +17 -0
- sage/calculus/all.py +14 -0
- sage/calculus/calculus.py +2838 -0
- sage/calculus/desolvers.py +1864 -0
- sage/calculus/predefined.py +51 -0
- sage/calculus/tests.py +225 -0
- sage/calculus/var.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/calculus/var.pyx +401 -0
- sage/dynamics/all__sagemath_symbolics.py +6 -0
- sage/dynamics/complex_dynamics/all.py +5 -0
- sage/dynamics/complex_dynamics/mandel_julia.py +765 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +1034 -0
- sage/ext/all__sagemath_symbolics.py +1 -0
- sage/ext_data/kenzo/CP2.txt +45 -0
- sage/ext_data/kenzo/CP3.txt +349 -0
- sage/ext_data/kenzo/CP4.txt +4774 -0
- sage/ext_data/kenzo/README.txt +49 -0
- sage/ext_data/kenzo/S4.txt +20 -0
- sage/ext_data/magma/latex/latex.m +1021 -0
- sage/ext_data/magma/latex/latex.spec +1 -0
- sage/ext_data/magma/sage/basic.m +356 -0
- sage/ext_data/magma/sage/sage.spec +1 -0
- sage/ext_data/magma/spec +9 -0
- sage/geometry/all__sagemath_symbolics.py +8 -0
- sage/geometry/hyperbolic_space/all.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_coercion.py +755 -0
- sage/geometry/hyperbolic_space/hyperbolic_constants.py +5 -0
- sage/geometry/hyperbolic_space/hyperbolic_geodesic.py +2419 -0
- sage/geometry/hyperbolic_space/hyperbolic_interface.py +206 -0
- sage/geometry/hyperbolic_space/hyperbolic_isometry.py +1083 -0
- sage/geometry/hyperbolic_space/hyperbolic_model.py +1502 -0
- sage/geometry/hyperbolic_space/hyperbolic_point.py +621 -0
- sage/geometry/riemannian_manifolds/all.py +7 -0
- sage/geometry/riemannian_manifolds/parametrized_surface3d.py +1632 -0
- sage/geometry/riemannian_manifolds/surface3d_generators.py +461 -0
- sage/interfaces/all__sagemath_symbolics.py +1 -0
- sage/interfaces/magma.py +2991 -0
- sage/interfaces/magma_free.py +90 -0
- sage/interfaces/maple.py +1402 -0
- sage/interfaces/mathematica.py +1345 -0
- sage/interfaces/mathics.py +1312 -0
- sage/interfaces/sympy.py +1398 -0
- sage/interfaces/sympy_wrapper.py +197 -0
- sage/interfaces/tides.py +938 -0
- sage/libs/all__sagemath_symbolics.py +6 -0
- sage/manifolds/all.py +7 -0
- sage/manifolds/calculus_method.py +553 -0
- sage/manifolds/catalog.py +437 -0
- sage/manifolds/chart.py +4010 -0
- sage/manifolds/chart_func.py +3416 -0
- sage/manifolds/continuous_map.py +2183 -0
- sage/manifolds/continuous_map_image.py +155 -0
- sage/manifolds/differentiable/affine_connection.py +2475 -0
- sage/manifolds/differentiable/all.py +1 -0
- sage/manifolds/differentiable/automorphismfield.py +1383 -0
- sage/manifolds/differentiable/automorphismfield_group.py +604 -0
- sage/manifolds/differentiable/bundle_connection.py +1445 -0
- sage/manifolds/differentiable/characteristic_cohomology_class.py +1840 -0
- sage/manifolds/differentiable/chart.py +1241 -0
- sage/manifolds/differentiable/curve.py +1028 -0
- sage/manifolds/differentiable/de_rham_cohomology.py +541 -0
- sage/manifolds/differentiable/degenerate.py +559 -0
- sage/manifolds/differentiable/degenerate_submanifold.py +1668 -0
- sage/manifolds/differentiable/diff_form.py +1660 -0
- sage/manifolds/differentiable/diff_form_module.py +1062 -0
- sage/manifolds/differentiable/diff_map.py +1315 -0
- sage/manifolds/differentiable/differentiable_submanifold.py +291 -0
- sage/manifolds/differentiable/examples/all.py +1 -0
- sage/manifolds/differentiable/examples/euclidean.py +2517 -0
- sage/manifolds/differentiable/examples/real_line.py +897 -0
- sage/manifolds/differentiable/examples/sphere.py +1186 -0
- sage/manifolds/differentiable/examples/symplectic_space.py +187 -0
- sage/manifolds/differentiable/examples/symplectic_space_test.py +40 -0
- sage/manifolds/differentiable/integrated_curve.py +4035 -0
- sage/manifolds/differentiable/levi_civita_connection.py +841 -0
- sage/manifolds/differentiable/manifold.py +4254 -0
- sage/manifolds/differentiable/manifold_homset.py +1826 -0
- sage/manifolds/differentiable/metric.py +3032 -0
- sage/manifolds/differentiable/mixed_form.py +1507 -0
- sage/manifolds/differentiable/mixed_form_algebra.py +559 -0
- sage/manifolds/differentiable/multivector_module.py +800 -0
- sage/manifolds/differentiable/multivectorfield.py +1522 -0
- sage/manifolds/differentiable/poisson_tensor.py +268 -0
- sage/manifolds/differentiable/pseudo_riemannian.py +755 -0
- sage/manifolds/differentiable/pseudo_riemannian_submanifold.py +1839 -0
- sage/manifolds/differentiable/scalarfield.py +1343 -0
- sage/manifolds/differentiable/scalarfield_algebra.py +472 -0
- sage/manifolds/differentiable/symplectic_form.py +912 -0
- sage/manifolds/differentiable/symplectic_form_test.py +220 -0
- sage/manifolds/differentiable/tangent_space.py +412 -0
- sage/manifolds/differentiable/tangent_vector.py +616 -0
- sage/manifolds/differentiable/tensorfield.py +4665 -0
- sage/manifolds/differentiable/tensorfield_module.py +963 -0
- sage/manifolds/differentiable/tensorfield_paral.py +2450 -0
- sage/manifolds/differentiable/tensorfield_paral_test.py +16 -0
- sage/manifolds/differentiable/vector_bundle.py +1725 -0
- sage/manifolds/differentiable/vectorfield.py +1717 -0
- sage/manifolds/differentiable/vectorfield_module.py +2445 -0
- sage/manifolds/differentiable/vectorframe.py +1832 -0
- sage/manifolds/family.py +270 -0
- sage/manifolds/local_frame.py +1490 -0
- sage/manifolds/manifold.py +3090 -0
- sage/manifolds/manifold_homset.py +452 -0
- sage/manifolds/operators.py +359 -0
- sage/manifolds/point.py +994 -0
- sage/manifolds/scalarfield.py +3718 -0
- sage/manifolds/scalarfield_algebra.py +629 -0
- sage/manifolds/section.py +3111 -0
- sage/manifolds/section_module.py +831 -0
- sage/manifolds/structure.py +229 -0
- sage/manifolds/subset.py +2721 -0
- sage/manifolds/subsets/all.py +1 -0
- sage/manifolds/subsets/closure.py +131 -0
- sage/manifolds/subsets/pullback.py +883 -0
- sage/manifolds/topological_submanifold.py +891 -0
- sage/manifolds/trivialization.py +733 -0
- sage/manifolds/utilities.py +1348 -0
- sage/manifolds/vector_bundle.py +1347 -0
- sage/manifolds/vector_bundle_fiber.py +332 -0
- sage/manifolds/vector_bundle_fiber_element.py +111 -0
- sage/matrix/all__sagemath_symbolics.py +1 -0
- sage/matrix/matrix_symbolic_dense.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_dense.pxd +6 -0
- sage/matrix/matrix_symbolic_dense.pyx +1030 -0
- sage/matrix/matrix_symbolic_sparse.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/matrix/matrix_symbolic_sparse.pxd +6 -0
- sage/matrix/matrix_symbolic_sparse.pyx +1038 -0
- sage/modules/all__sagemath_symbolics.py +1 -0
- sage/modules/vector_callable_symbolic_dense.py +105 -0
- sage/modules/vector_symbolic_dense.py +116 -0
- sage/modules/vector_symbolic_sparse.py +118 -0
- sage/rings/all__sagemath_symbolics.py +4 -0
- sage/rings/asymptotic/all.py +6 -0
- sage/rings/asymptotic/asymptotic_expansion_generators.py +1485 -0
- sage/rings/asymptotic/asymptotic_ring.py +4858 -0
- sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +4106 -0
- sage/rings/asymptotic/growth_group.py +5373 -0
- sage/rings/asymptotic/growth_group_cartesian.py +1400 -0
- sage/rings/asymptotic/term_monoid.py +5205 -0
- sage/rings/function_field/all__sagemath_symbolics.py +2 -0
- sage/rings/polynomial/all__sagemath_symbolics.py +1 -0
- sage/symbolic/all.py +15 -0
- sage/symbolic/assumptions.py +987 -0
- sage/symbolic/benchmark.py +93 -0
- sage/symbolic/callable.py +456 -0
- sage/symbolic/callable.pyi +66 -0
- sage/symbolic/comparison_impl.pyi +38 -0
- sage/symbolic/complexity_measures.py +35 -0
- sage/symbolic/constants.py +1286 -0
- sage/symbolic/constants_c_impl.pyi +10 -0
- sage/symbolic/expression_conversion_algebraic.py +310 -0
- sage/symbolic/expression_conversion_sympy.py +317 -0
- sage/symbolic/expression_conversions.py +1727 -0
- sage/symbolic/function_factory.py +355 -0
- sage/symbolic/function_factory.pyi +41 -0
- sage/symbolic/getitem_impl.pyi +24 -0
- sage/symbolic/integration/all.py +1 -0
- sage/symbolic/integration/external.py +271 -0
- sage/symbolic/integration/integral.py +1075 -0
- sage/symbolic/maxima_wrapper.py +162 -0
- sage/symbolic/operators.py +267 -0
- sage/symbolic/operators.pyi +61 -0
- sage/symbolic/pynac_constant_impl.pyi +13 -0
- sage/symbolic/pynac_function_impl.pyi +8 -0
- sage/symbolic/random_tests.py +461 -0
- sage/symbolic/relation.py +2062 -0
- sage/symbolic/ring.cpython-314t-aarch64-linux-musl.so +0 -0
- sage/symbolic/ring.pxd +5 -0
- sage/symbolic/ring.pyi +110 -0
- sage/symbolic/ring.pyx +1393 -0
- sage/symbolic/series_impl.pyi +10 -0
- sage/symbolic/subring.py +1025 -0
- sage/symbolic/symengine.py +19 -0
- sage/symbolic/tests.py +40 -0
- sage/symbolic/units.py +1468 -0
|
@@ -0,0 +1,755 @@
|
|
|
1
|
+
# sage_setup: distribution = sagemath-symbolics
|
|
2
|
+
"""
|
|
3
|
+
Coercion Maps Between Hyperbolic Plane Models
|
|
4
|
+
|
|
5
|
+
This module implements the coercion maps between different hyperbolic
|
|
6
|
+
plane models.
|
|
7
|
+
|
|
8
|
+
AUTHORS:
|
|
9
|
+
|
|
10
|
+
- Travis Scrimshaw (2014): initial version
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
#***********************************************************************
|
|
14
|
+
# Copyright (C) 2014 Travis Scrimshaw <tscrim at ucdavis.edu>
|
|
15
|
+
#
|
|
16
|
+
# Distributed under the terms of the GNU General Public License (GPL)
|
|
17
|
+
# as published by the Free Software Foundation; either version 2 of
|
|
18
|
+
# the License, or (at your option) any later version.
|
|
19
|
+
# http://www.gnu.org/licenses/
|
|
20
|
+
#***********************************************************************
|
|
21
|
+
|
|
22
|
+
from sage.categories.morphism import Morphism
|
|
23
|
+
from sage.symbolic.constants import I
|
|
24
|
+
from sage.matrix.constructor import matrix
|
|
25
|
+
from sage.modules.free_module_element import vector
|
|
26
|
+
from sage.rings.integer import Integer
|
|
27
|
+
from sage.rings.infinity import infinity
|
|
28
|
+
from sage.functions.other import real, imag
|
|
29
|
+
from sage.misc.functional import sqrt
|
|
30
|
+
from sage.geometry.hyperbolic_space.hyperbolic_constants import EPSILON
|
|
31
|
+
from sage.misc.lazy_import import lazy_import
|
|
32
|
+
lazy_import('sage.misc.call', 'attrcall')
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class HyperbolicModelCoercion(Morphism):
|
|
36
|
+
"""
|
|
37
|
+
Abstract base class for morphisms between the hyperbolic models.
|
|
38
|
+
"""
|
|
39
|
+
def _repr_type(self):
|
|
40
|
+
"""
|
|
41
|
+
Return the type of morphism.
|
|
42
|
+
|
|
43
|
+
EXAMPLES::
|
|
44
|
+
|
|
45
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
46
|
+
sage: PD = HyperbolicPlane().PD()
|
|
47
|
+
sage: phi = UHP.coerce_map_from(PD)
|
|
48
|
+
sage: phi._repr_type()
|
|
49
|
+
'Coercion Isometry'
|
|
50
|
+
"""
|
|
51
|
+
return "Coercion Isometry"
|
|
52
|
+
|
|
53
|
+
def _call_(self, x):
|
|
54
|
+
"""
|
|
55
|
+
Return the image of ``x`` under ``self``.
|
|
56
|
+
|
|
57
|
+
EXAMPLES::
|
|
58
|
+
|
|
59
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
60
|
+
sage: PD = HyperbolicPlane().PD()
|
|
61
|
+
sage: HM = HyperbolicPlane().HM()
|
|
62
|
+
sage: phi = UHP.coerce_map_from(PD)
|
|
63
|
+
sage: phi(PD.get_point(0.5+0.5*I))
|
|
64
|
+
Point in UHP 2.00000000000000 + 1.00000000000000*I
|
|
65
|
+
sage: psi = HM.coerce_map_from(UHP)
|
|
66
|
+
sage: psi(UHP.get_point(I))
|
|
67
|
+
Point in HM (0, 0, 1)
|
|
68
|
+
|
|
69
|
+
It is an error to try to convert a boundary point to a model
|
|
70
|
+
that doesn't support boundary points::
|
|
71
|
+
|
|
72
|
+
sage: psi(UHP.get_point(infinity))
|
|
73
|
+
Traceback (most recent call last):
|
|
74
|
+
...
|
|
75
|
+
NotImplementedError: boundary points are not implemented for the Hyperboloid Model
|
|
76
|
+
|
|
77
|
+
It is an error to try to convert a boundary point to a model
|
|
78
|
+
that doesn't support boundary points::
|
|
79
|
+
|
|
80
|
+
sage: psi(UHP(infinity))
|
|
81
|
+
Traceback (most recent call last):
|
|
82
|
+
...
|
|
83
|
+
NotImplementedError: boundary points are not implemented for the Hyperboloid Model
|
|
84
|
+
"""
|
|
85
|
+
C = self.codomain()
|
|
86
|
+
if not C.is_bounded() and self.domain().is_bounded() and x.is_boundary():
|
|
87
|
+
msg = "boundary points are not implemented for the {}"
|
|
88
|
+
raise NotImplementedError(msg.format(C.name()))
|
|
89
|
+
|
|
90
|
+
y = self.image_coordinates(x.coordinates())
|
|
91
|
+
if self.domain().is_bounded():
|
|
92
|
+
bdry = x.is_boundary()
|
|
93
|
+
else:
|
|
94
|
+
bdry = C.boundary_point_in_model(y)
|
|
95
|
+
|
|
96
|
+
return C.element_class(C, y, bdry, check=False, **x.graphics_options())
|
|
97
|
+
|
|
98
|
+
def convert_geodesic(self, x):
|
|
99
|
+
"""
|
|
100
|
+
Convert the geodesic ``x`` of the domain into a geodesic of
|
|
101
|
+
the codomain.
|
|
102
|
+
|
|
103
|
+
EXAMPLES::
|
|
104
|
+
|
|
105
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
106
|
+
sage: PD = HyperbolicPlane().PD()
|
|
107
|
+
sage: phi = UHP.coerce_map_from(PD)
|
|
108
|
+
sage: phi.convert_geodesic(PD.get_geodesic(0.5+0.5*I, -I))
|
|
109
|
+
Geodesic in UHP from 2.00000000000000 + 1.00000000000000*I to 0
|
|
110
|
+
"""
|
|
111
|
+
return self.codomain().get_geodesic(self(x.start()), self(x.end()),
|
|
112
|
+
**x.graphics_options())
|
|
113
|
+
|
|
114
|
+
def convert_isometry(self, x):
|
|
115
|
+
"""
|
|
116
|
+
Convert the hyperbolic isometry ``x`` of the domain into an
|
|
117
|
+
isometry of the codomain.
|
|
118
|
+
|
|
119
|
+
EXAMPLES::
|
|
120
|
+
|
|
121
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
122
|
+
sage: HM = HyperbolicPlane().HM()
|
|
123
|
+
sage: phi = HM.coerce_map_from(UHP)
|
|
124
|
+
sage: I2 = UHP.get_isometry(identity_matrix(2))
|
|
125
|
+
sage: phi.convert_isometry(I2)
|
|
126
|
+
Isometry in HM
|
|
127
|
+
[1 0 0]
|
|
128
|
+
[0 1 0]
|
|
129
|
+
[0 0 1]
|
|
130
|
+
"""
|
|
131
|
+
C = self.codomain()
|
|
132
|
+
return C._Isometry(C, self.image_isometry_matrix(x._matrix), check=False)
|
|
133
|
+
|
|
134
|
+
def __invert__(self):
|
|
135
|
+
"""
|
|
136
|
+
Return the inverse coercion of ``self``.
|
|
137
|
+
|
|
138
|
+
EXAMPLES::
|
|
139
|
+
|
|
140
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
141
|
+
sage: PD = HyperbolicPlane().PD()
|
|
142
|
+
sage: phi = UHP.coerce_map_from(PD)
|
|
143
|
+
sage: ~phi
|
|
144
|
+
Coercion Isometry morphism:
|
|
145
|
+
From: Hyperbolic plane in the Upper Half Plane Model
|
|
146
|
+
To: Hyperbolic plane in the Poincare Disk Model
|
|
147
|
+
"""
|
|
148
|
+
return self.domain().coerce_map_from(self.codomain())
|
|
149
|
+
|
|
150
|
+
############
|
|
151
|
+
# From UHP #
|
|
152
|
+
############
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class CoercionUHPtoPD(HyperbolicModelCoercion):
|
|
156
|
+
"""
|
|
157
|
+
Coercion from the UHP to PD model.
|
|
158
|
+
"""
|
|
159
|
+
def image_coordinates(self, x):
|
|
160
|
+
"""
|
|
161
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
162
|
+
under ``self``.
|
|
163
|
+
|
|
164
|
+
EXAMPLES::
|
|
165
|
+
|
|
166
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
167
|
+
sage: PD = HyperbolicPlane().PD()
|
|
168
|
+
sage: phi = PD.coerce_map_from(UHP)
|
|
169
|
+
sage: phi.image_coordinates(I)
|
|
170
|
+
0
|
|
171
|
+
"""
|
|
172
|
+
if x == infinity:
|
|
173
|
+
return I
|
|
174
|
+
return (x - I) / (Integer(1) - I*x)
|
|
175
|
+
|
|
176
|
+
def image_isometry_matrix(self, x):
|
|
177
|
+
"""
|
|
178
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
179
|
+
under ``self``.
|
|
180
|
+
|
|
181
|
+
EXAMPLES::
|
|
182
|
+
|
|
183
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
184
|
+
sage: PD = HyperbolicPlane().PD()
|
|
185
|
+
sage: phi = PD.coerce_map_from(UHP)
|
|
186
|
+
sage: phi.image_isometry_matrix(identity_matrix(2))
|
|
187
|
+
[1 0]
|
|
188
|
+
[0 1]
|
|
189
|
+
"""
|
|
190
|
+
if x.det() < 0:
|
|
191
|
+
# x = I * x
|
|
192
|
+
return matrix([[1,-I],[-I,1]]) * x * matrix([[1,I],[I,1]]).conjugate()/Integer(2)
|
|
193
|
+
return matrix([[1,-I],[-I,1]]) * x * matrix([[1,I],[I,1]])/Integer(2)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class CoercionUHPtoKM(HyperbolicModelCoercion):
|
|
197
|
+
"""
|
|
198
|
+
Coercion from the UHP to KM model.
|
|
199
|
+
"""
|
|
200
|
+
def image_coordinates(self, x):
|
|
201
|
+
"""
|
|
202
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
203
|
+
under ``self``.
|
|
204
|
+
|
|
205
|
+
EXAMPLES::
|
|
206
|
+
|
|
207
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
208
|
+
sage: KM = HyperbolicPlane().KM()
|
|
209
|
+
sage: phi = KM.coerce_map_from(UHP)
|
|
210
|
+
sage: phi.image_coordinates(3 + I)
|
|
211
|
+
(6/11, 9/11)
|
|
212
|
+
"""
|
|
213
|
+
if x == infinity:
|
|
214
|
+
return (0, 1)
|
|
215
|
+
return ((2*real(x))/(real(x)**2 + imag(x)**2 + 1),
|
|
216
|
+
(real(x)**2 + imag(x)**2 - 1)/(real(x)**2 + imag(x)**2 + 1))
|
|
217
|
+
|
|
218
|
+
def image_isometry_matrix(self, x):
|
|
219
|
+
"""
|
|
220
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
221
|
+
under ``self``.
|
|
222
|
+
|
|
223
|
+
EXAMPLES::
|
|
224
|
+
|
|
225
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
226
|
+
sage: KM = HyperbolicPlane().KM()
|
|
227
|
+
sage: phi = KM.coerce_map_from(UHP)
|
|
228
|
+
sage: phi.image_isometry_matrix(identity_matrix(2))
|
|
229
|
+
[1 0 0]
|
|
230
|
+
[0 1 0]
|
|
231
|
+
[0 0 1]
|
|
232
|
+
"""
|
|
233
|
+
return SL2R_to_SO21(x)
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class CoercionUHPtoHM(HyperbolicModelCoercion):
|
|
237
|
+
"""
|
|
238
|
+
Coercion from the UHP to HM model.
|
|
239
|
+
"""
|
|
240
|
+
def image_coordinates(self, x):
|
|
241
|
+
"""
|
|
242
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
243
|
+
under ``self``.
|
|
244
|
+
|
|
245
|
+
EXAMPLES::
|
|
246
|
+
|
|
247
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
248
|
+
sage: HM = HyperbolicPlane().HM()
|
|
249
|
+
sage: phi = HM.coerce_map_from(UHP)
|
|
250
|
+
sage: phi.image_coordinates(3 + I)
|
|
251
|
+
(3, 9/2, 11/2)
|
|
252
|
+
"""
|
|
253
|
+
return vector((real(x)/imag(x),
|
|
254
|
+
(real(x)**2 + imag(x)**2 - 1)/(2*imag(x)),
|
|
255
|
+
(real(x)**2 + imag(x)**2 + 1)/(2*imag(x))))
|
|
256
|
+
|
|
257
|
+
def image_isometry_matrix(self, x):
|
|
258
|
+
"""
|
|
259
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
260
|
+
under ``self``.
|
|
261
|
+
|
|
262
|
+
EXAMPLES::
|
|
263
|
+
|
|
264
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
265
|
+
sage: HM = HyperbolicPlane().HM()
|
|
266
|
+
sage: phi = HM.coerce_map_from(UHP)
|
|
267
|
+
sage: phi.image_isometry_matrix(identity_matrix(2))
|
|
268
|
+
[1 0 0]
|
|
269
|
+
[0 1 0]
|
|
270
|
+
[0 0 1]
|
|
271
|
+
"""
|
|
272
|
+
return SL2R_to_SO21(x)
|
|
273
|
+
|
|
274
|
+
###########
|
|
275
|
+
# From PD #
|
|
276
|
+
###########
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
class CoercionPDtoUHP(HyperbolicModelCoercion):
|
|
280
|
+
"""
|
|
281
|
+
Coercion from the PD to UHP model.
|
|
282
|
+
"""
|
|
283
|
+
def image_coordinates(self, x):
|
|
284
|
+
"""
|
|
285
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
286
|
+
under ``self``.
|
|
287
|
+
|
|
288
|
+
EXAMPLES::
|
|
289
|
+
|
|
290
|
+
sage: PD = HyperbolicPlane().PD()
|
|
291
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
292
|
+
sage: phi = UHP.coerce_map_from(PD)
|
|
293
|
+
sage: phi.image_coordinates(0.5+0.5*I)
|
|
294
|
+
2.00000000000000 + 1.00000000000000*I
|
|
295
|
+
sage: phi.image_coordinates(0)
|
|
296
|
+
I
|
|
297
|
+
sage: phi.image_coordinates(I)
|
|
298
|
+
+Infinity
|
|
299
|
+
sage: phi.image_coordinates(-I)
|
|
300
|
+
0
|
|
301
|
+
|
|
302
|
+
TESTS:
|
|
303
|
+
|
|
304
|
+
Check that the second bug discussed in :issue:`32362` is fixed::
|
|
305
|
+
|
|
306
|
+
sage: PD = HyperbolicPlane().PD()
|
|
307
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
308
|
+
sage: r = exp((pi*I/2).n())
|
|
309
|
+
sage: p = PD.get_point(r)
|
|
310
|
+
sage: UHP(p)
|
|
311
|
+
Boundary point in UHP +Infinity
|
|
312
|
+
"""
|
|
313
|
+
if abs(x - I) < EPSILON:
|
|
314
|
+
return infinity
|
|
315
|
+
return (x + I)/(Integer(1) + I*x)
|
|
316
|
+
|
|
317
|
+
def image_isometry_matrix(self, x):
|
|
318
|
+
"""
|
|
319
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
320
|
+
under ``self``.
|
|
321
|
+
|
|
322
|
+
EXAMPLES:
|
|
323
|
+
|
|
324
|
+
We check that orientation-reversing isometries behave as they
|
|
325
|
+
should::
|
|
326
|
+
|
|
327
|
+
sage: PD = HyperbolicPlane().PD()
|
|
328
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
329
|
+
sage: phi = UHP.coerce_map_from(PD)
|
|
330
|
+
sage: phi.image_isometry_matrix(matrix([[0,I],[I,0]]))
|
|
331
|
+
[-1 0]
|
|
332
|
+
[ 0 -1]
|
|
333
|
+
"""
|
|
334
|
+
from sage.geometry.hyperbolic_space.hyperbolic_isometry import HyperbolicIsometryPD
|
|
335
|
+
if not HyperbolicIsometryPD._orientation_preserving(x):
|
|
336
|
+
return matrix([[1,I],[I,1]]) * x * matrix([[1,-I],[-I,1]]).conjugate() / Integer(2)
|
|
337
|
+
return matrix([[1,I],[I,1]]) * x * matrix([[1,-I],[-I,1]]) / Integer(2)
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
class CoercionPDtoKM(HyperbolicModelCoercion):
|
|
341
|
+
"""
|
|
342
|
+
Coercion from the PD to KM model.
|
|
343
|
+
"""
|
|
344
|
+
def image_coordinates(self, x):
|
|
345
|
+
"""
|
|
346
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
347
|
+
under ``self``.
|
|
348
|
+
|
|
349
|
+
EXAMPLES::
|
|
350
|
+
|
|
351
|
+
sage: PD = HyperbolicPlane().PD()
|
|
352
|
+
sage: KM = HyperbolicPlane().KM()
|
|
353
|
+
sage: phi = KM.coerce_map_from(PD)
|
|
354
|
+
sage: phi.image_coordinates(0.5+0.5*I)
|
|
355
|
+
(0.666666666666667, 0.666666666666667)
|
|
356
|
+
"""
|
|
357
|
+
return (2*real(x)/(Integer(1) + real(x)**2 + imag(x)**2),
|
|
358
|
+
2*imag(x)/(Integer(1) + real(x)**2 + imag(x)**2))
|
|
359
|
+
|
|
360
|
+
def image_isometry_matrix(self, x):
|
|
361
|
+
"""
|
|
362
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
363
|
+
under ``self``.
|
|
364
|
+
|
|
365
|
+
EXAMPLES::
|
|
366
|
+
|
|
367
|
+
sage: PD = HyperbolicPlane().PD()
|
|
368
|
+
sage: KM = HyperbolicPlane().KM()
|
|
369
|
+
sage: phi = KM.coerce_map_from(PD)
|
|
370
|
+
sage: phi.image_isometry_matrix(matrix([[0,I],[I,0]]))
|
|
371
|
+
[-1 0 0]
|
|
372
|
+
[ 0 1 0]
|
|
373
|
+
[ 0 0 -1]
|
|
374
|
+
"""
|
|
375
|
+
return SL2R_to_SO21(matrix(2, [1, I, I, 1]) * x *
|
|
376
|
+
matrix(2, [1, -I, -I, 1]) / Integer(2))
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
class CoercionPDtoHM(HyperbolicModelCoercion):
|
|
380
|
+
"""
|
|
381
|
+
Coercion from the PD to HM model.
|
|
382
|
+
"""
|
|
383
|
+
def image_coordinates(self, x):
|
|
384
|
+
"""
|
|
385
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
386
|
+
under ``self``.
|
|
387
|
+
|
|
388
|
+
EXAMPLES::
|
|
389
|
+
|
|
390
|
+
sage: PD = HyperbolicPlane().PD()
|
|
391
|
+
sage: HM = HyperbolicPlane().HM()
|
|
392
|
+
sage: phi = HM.coerce_map_from(PD)
|
|
393
|
+
sage: phi.image_coordinates(0.5+0.5*I)
|
|
394
|
+
(2.00000000000000, 2.00000000000000, 3.00000000000000)
|
|
395
|
+
"""
|
|
396
|
+
return vector((2*real(x)/(1 - real(x)**2 - imag(x)**2),
|
|
397
|
+
2*imag(x)/(1 - real(x)**2 - imag(x)**2),
|
|
398
|
+
(real(x)**2 + imag(x)**2 + 1) /
|
|
399
|
+
(1 - real(x)**2 - imag(x)**2)))
|
|
400
|
+
|
|
401
|
+
def image_isometry_matrix(self, x):
|
|
402
|
+
"""
|
|
403
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
404
|
+
under ``self``.
|
|
405
|
+
|
|
406
|
+
EXAMPLES::
|
|
407
|
+
|
|
408
|
+
sage: PD = HyperbolicPlane().PD()
|
|
409
|
+
sage: HM = HyperbolicPlane().HM()
|
|
410
|
+
sage: phi = HM.coerce_map_from(PD)
|
|
411
|
+
sage: phi.image_isometry_matrix(matrix([[0,I],[I,0]]))
|
|
412
|
+
[-1 0 0]
|
|
413
|
+
[ 0 1 0]
|
|
414
|
+
[ 0 0 -1]
|
|
415
|
+
"""
|
|
416
|
+
return SL2R_to_SO21(matrix(2, [1, I, I, 1]) * x *
|
|
417
|
+
matrix(2, [1, -I, -I, 1]) / Integer(2))
|
|
418
|
+
|
|
419
|
+
###########
|
|
420
|
+
# From KM #
|
|
421
|
+
###########
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
class CoercionKMtoUHP(HyperbolicModelCoercion):
|
|
425
|
+
"""
|
|
426
|
+
Coercion from the KM to UHP model.
|
|
427
|
+
"""
|
|
428
|
+
def image_coordinates(self, x):
|
|
429
|
+
"""
|
|
430
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
431
|
+
under ``self``.
|
|
432
|
+
|
|
433
|
+
EXAMPLES::
|
|
434
|
+
|
|
435
|
+
sage: KM = HyperbolicPlane().KM()
|
|
436
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
437
|
+
sage: phi = UHP.coerce_map_from(KM)
|
|
438
|
+
sage: phi.image_coordinates((0, 0))
|
|
439
|
+
I
|
|
440
|
+
sage: phi.image_coordinates((0, 1))
|
|
441
|
+
+Infinity
|
|
442
|
+
"""
|
|
443
|
+
if tuple(x) == (0, 1):
|
|
444
|
+
return infinity
|
|
445
|
+
return (-x[0]/(x[1] - 1)
|
|
446
|
+
+ I*(-(sqrt(-x[0]**2 - x[1]**2 + 1) - x[0]**2 - x[1]**2 + 1)
|
|
447
|
+
/ ((x[1] - 1)*sqrt(-x[0]**2 - x[1]**2 + 1) + x[1] - 1)))
|
|
448
|
+
|
|
449
|
+
def image_isometry_matrix(self, x):
|
|
450
|
+
"""
|
|
451
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
452
|
+
under ``self``.
|
|
453
|
+
|
|
454
|
+
EXAMPLES::
|
|
455
|
+
|
|
456
|
+
sage: KM = HyperbolicPlane().KM()
|
|
457
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
458
|
+
sage: phi = UHP.coerce_map_from(KM)
|
|
459
|
+
sage: m = matrix([[5/3,0,4/3], [0,1,0], [4/3,0,5/3]])
|
|
460
|
+
sage: phi.image_isometry_matrix(m)
|
|
461
|
+
[2*sqrt(1/3) sqrt(1/3)]
|
|
462
|
+
[ sqrt(1/3) 2*sqrt(1/3)]
|
|
463
|
+
"""
|
|
464
|
+
return SO21_to_SL2R(x)
|
|
465
|
+
|
|
466
|
+
|
|
467
|
+
class CoercionKMtoPD(HyperbolicModelCoercion):
|
|
468
|
+
"""
|
|
469
|
+
Coercion from the KM to PD model.
|
|
470
|
+
"""
|
|
471
|
+
def image_coordinates(self, x):
|
|
472
|
+
"""
|
|
473
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
474
|
+
under ``self``.
|
|
475
|
+
|
|
476
|
+
EXAMPLES::
|
|
477
|
+
|
|
478
|
+
sage: KM = HyperbolicPlane().KM()
|
|
479
|
+
sage: PD = HyperbolicPlane().PD()
|
|
480
|
+
sage: phi = PD.coerce_map_from(KM)
|
|
481
|
+
sage: phi.image_coordinates((0, 0))
|
|
482
|
+
0
|
|
483
|
+
"""
|
|
484
|
+
return (x[0]/(1 + (1 - x[0]**2 - x[1]**2).sqrt())
|
|
485
|
+
+ I*x[1]/(1 + (1 - x[0]**2 - x[1]**2).sqrt()))
|
|
486
|
+
|
|
487
|
+
def image_isometry_matrix(self, x):
|
|
488
|
+
"""
|
|
489
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
490
|
+
under ``self``.
|
|
491
|
+
|
|
492
|
+
EXAMPLES::
|
|
493
|
+
|
|
494
|
+
sage: KM = HyperbolicPlane().KM()
|
|
495
|
+
sage: PD = HyperbolicPlane().PD()
|
|
496
|
+
sage: phi = PD.coerce_map_from(KM)
|
|
497
|
+
sage: m = matrix([[5/3,0,4/3], [0,1,0], [4/3,0,5/3]])
|
|
498
|
+
sage: phi.image_isometry_matrix(m)
|
|
499
|
+
[2*sqrt(1/3) sqrt(1/3)]
|
|
500
|
+
[ sqrt(1/3) 2*sqrt(1/3)]
|
|
501
|
+
"""
|
|
502
|
+
return (matrix(2,[1,-I,-I,1]) * SO21_to_SL2R(x) *
|
|
503
|
+
matrix(2,[1,I,I,1])/Integer(2))
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
class CoercionKMtoHM(HyperbolicModelCoercion):
|
|
507
|
+
"""
|
|
508
|
+
Coercion from the KM to HM model.
|
|
509
|
+
"""
|
|
510
|
+
def image_coordinates(self, x):
|
|
511
|
+
"""
|
|
512
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
513
|
+
under ``self``.
|
|
514
|
+
|
|
515
|
+
EXAMPLES::
|
|
516
|
+
|
|
517
|
+
sage: KM = HyperbolicPlane().KM()
|
|
518
|
+
sage: HM = HyperbolicPlane().HM()
|
|
519
|
+
sage: phi = HM.coerce_map_from(KM)
|
|
520
|
+
sage: phi.image_coordinates((0, 0))
|
|
521
|
+
(0, 0, 1)
|
|
522
|
+
"""
|
|
523
|
+
return (vector((2*x[0], 2*x[1], 1 + x[0]**2 + x[1]**2))
|
|
524
|
+
/ (1 - x[0]**2 - x[1]**2))
|
|
525
|
+
|
|
526
|
+
def image_isometry_matrix(self, x):
|
|
527
|
+
"""
|
|
528
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
529
|
+
under ``self``.
|
|
530
|
+
|
|
531
|
+
EXAMPLES::
|
|
532
|
+
|
|
533
|
+
sage: KM = HyperbolicPlane().KM()
|
|
534
|
+
sage: HM = HyperbolicPlane().HM()
|
|
535
|
+
sage: phi = HM.coerce_map_from(KM)
|
|
536
|
+
sage: m = matrix([[5/3,0,4/3], [0,1,0], [4/3,0,5/3]])
|
|
537
|
+
sage: phi.image_isometry_matrix(m)
|
|
538
|
+
[5/3 0 4/3]
|
|
539
|
+
[ 0 1 0]
|
|
540
|
+
[4/3 0 5/3]
|
|
541
|
+
"""
|
|
542
|
+
return x
|
|
543
|
+
|
|
544
|
+
###########
|
|
545
|
+
# From HM #
|
|
546
|
+
###########
|
|
547
|
+
|
|
548
|
+
|
|
549
|
+
class CoercionHMtoUHP(HyperbolicModelCoercion):
|
|
550
|
+
"""
|
|
551
|
+
Coercion from the HM to UHP model.
|
|
552
|
+
"""
|
|
553
|
+
def image_coordinates(self, x):
|
|
554
|
+
"""
|
|
555
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
556
|
+
under ``self``.
|
|
557
|
+
|
|
558
|
+
EXAMPLES::
|
|
559
|
+
|
|
560
|
+
sage: HM = HyperbolicPlane().HM()
|
|
561
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
562
|
+
sage: phi = UHP.coerce_map_from(HM)
|
|
563
|
+
sage: phi.image_coordinates( vector((0,0,1)) )
|
|
564
|
+
I
|
|
565
|
+
"""
|
|
566
|
+
return -((x[0]*x[2] + x[0]) + I*(x[2] + 1)) / ((x[1] - 1)*x[2]
|
|
567
|
+
- x[0]**2 - x[1]**2 + x[1] - 1)
|
|
568
|
+
|
|
569
|
+
def image_isometry_matrix(self, x):
|
|
570
|
+
"""
|
|
571
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
572
|
+
under ``self``.
|
|
573
|
+
|
|
574
|
+
EXAMPLES::
|
|
575
|
+
|
|
576
|
+
sage: HM = HyperbolicPlane().HM()
|
|
577
|
+
sage: UHP = HyperbolicPlane().UHP()
|
|
578
|
+
sage: phi = UHP.coerce_map_from(HM)
|
|
579
|
+
sage: phi.image_isometry_matrix(identity_matrix(3))
|
|
580
|
+
[1 0]
|
|
581
|
+
[0 1]
|
|
582
|
+
"""
|
|
583
|
+
return SO21_to_SL2R(x)
|
|
584
|
+
|
|
585
|
+
|
|
586
|
+
class CoercionHMtoPD(HyperbolicModelCoercion):
|
|
587
|
+
"""
|
|
588
|
+
Coercion from the HM to PD model.
|
|
589
|
+
"""
|
|
590
|
+
def image_coordinates(self, x):
|
|
591
|
+
"""
|
|
592
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
593
|
+
under ``self``.
|
|
594
|
+
|
|
595
|
+
EXAMPLES::
|
|
596
|
+
|
|
597
|
+
sage: HM = HyperbolicPlane().HM()
|
|
598
|
+
sage: PD = HyperbolicPlane().PD()
|
|
599
|
+
sage: phi = PD.coerce_map_from(HM)
|
|
600
|
+
sage: phi.image_coordinates( vector((0,0,1)) )
|
|
601
|
+
0
|
|
602
|
+
"""
|
|
603
|
+
return x[0]/(1 + x[2]) + I*(x[1]/(1 + x[2]))
|
|
604
|
+
|
|
605
|
+
def image_isometry_matrix(self, x):
|
|
606
|
+
"""
|
|
607
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
608
|
+
under ``self``.
|
|
609
|
+
|
|
610
|
+
EXAMPLES::
|
|
611
|
+
|
|
612
|
+
sage: HM = HyperbolicPlane().HM()
|
|
613
|
+
sage: PD = HyperbolicPlane().PD()
|
|
614
|
+
sage: phi = PD.coerce_map_from(HM)
|
|
615
|
+
sage: phi.image_isometry_matrix(identity_matrix(3))
|
|
616
|
+
[1 0]
|
|
617
|
+
[0 1]
|
|
618
|
+
"""
|
|
619
|
+
return (matrix(2,[1,-I,-I,1]) * SO21_to_SL2R(x) *
|
|
620
|
+
matrix(2,[1,I,I,1])/Integer(2))
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
class CoercionHMtoKM(HyperbolicModelCoercion):
|
|
624
|
+
"""
|
|
625
|
+
Coercion from the HM to KM model.
|
|
626
|
+
"""
|
|
627
|
+
def image_coordinates(self, x):
|
|
628
|
+
"""
|
|
629
|
+
Return the image of the coordinates of the hyperbolic point ``x``
|
|
630
|
+
under ``self``.
|
|
631
|
+
|
|
632
|
+
EXAMPLES::
|
|
633
|
+
|
|
634
|
+
sage: HM = HyperbolicPlane().HM()
|
|
635
|
+
sage: KM = HyperbolicPlane().KM()
|
|
636
|
+
sage: phi = KM.coerce_map_from(HM)
|
|
637
|
+
sage: phi.image_coordinates( vector((0,0,1)) )
|
|
638
|
+
(0, 0)
|
|
639
|
+
"""
|
|
640
|
+
return (x[0]/(1 + x[2]), x[1]/(1 + x[2]))
|
|
641
|
+
|
|
642
|
+
def image_isometry_matrix(self, x):
|
|
643
|
+
"""
|
|
644
|
+
Return the image of the matrix of the hyperbolic isometry ``x``
|
|
645
|
+
under ``self``.
|
|
646
|
+
|
|
647
|
+
EXAMPLES::
|
|
648
|
+
|
|
649
|
+
sage: HM = HyperbolicPlane().HM()
|
|
650
|
+
sage: KM = HyperbolicPlane().KM()
|
|
651
|
+
sage: phi = KM.coerce_map_from(HM)
|
|
652
|
+
sage: phi.image_isometry_matrix(identity_matrix(3))
|
|
653
|
+
[1 0 0]
|
|
654
|
+
[0 1 0]
|
|
655
|
+
[0 0 1]
|
|
656
|
+
"""
|
|
657
|
+
return x
|
|
658
|
+
|
|
659
|
+
#####################################################################
|
|
660
|
+
## Helper functions
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
def SL2R_to_SO21(A):
|
|
664
|
+
r"""
|
|
665
|
+
Given a matrix in `SL(2, \RR)` return its irreducible representation in
|
|
666
|
+
`O(2,1)`.
|
|
667
|
+
|
|
668
|
+
Note that this is not the only homomorphism, but it is the only one
|
|
669
|
+
that works in the context of the implemented 2D hyperbolic geometry
|
|
670
|
+
models.
|
|
671
|
+
|
|
672
|
+
EXAMPLES::
|
|
673
|
+
|
|
674
|
+
sage: from sage.geometry.hyperbolic_space.hyperbolic_coercion import SL2R_to_SO21
|
|
675
|
+
sage: A = SL2R_to_SO21(identity_matrix(2))
|
|
676
|
+
sage: J = matrix([[1,0,0],[0,1,0],[0,0,-1]]) #Lorentzian Gram matrix
|
|
677
|
+
sage: norm(A.transpose()*J*A - J) < 10**-4 # needs scipy
|
|
678
|
+
True
|
|
679
|
+
"""
|
|
680
|
+
a, b, c, d = (A/A.det().sqrt()).list()
|
|
681
|
+
|
|
682
|
+
# Kill ~0 imaginary parts
|
|
683
|
+
components = [
|
|
684
|
+
a*d + b*c, a*c - b*d, a*c + b*d, a*b - c*d,
|
|
685
|
+
Integer(1)/Integer(2)*a**2 - Integer(1)/Integer(2)*b**2 -
|
|
686
|
+
Integer(1)/Integer(2)*c**2 + Integer(1)/Integer(2)*d**2,
|
|
687
|
+
Integer(1)/Integer(2)*a**2 + Integer(1)/Integer(2)*b**2 -
|
|
688
|
+
Integer(1)/Integer(2)*c**2 - Integer(1)/Integer(2)*d**2,
|
|
689
|
+
a*b + c*d, Integer(1)/Integer(2)*a**2 -
|
|
690
|
+
Integer(1)/Integer(2)*b**2 + Integer(1)/Integer(2)*c**2 -
|
|
691
|
+
Integer(1)/Integer(2)*d**2, Integer(1)/Integer(2)*a**2 +
|
|
692
|
+
Integer(1)/Integer(2)*b**2 + Integer(1)/Integer(2)*c**2 +
|
|
693
|
+
Integer(1)/Integer(2)*d**2
|
|
694
|
+
]
|
|
695
|
+
B = matrix(3, [real(comp) for comp in components])
|
|
696
|
+
|
|
697
|
+
#B = B.apply_map(attrcall('real'))
|
|
698
|
+
if A.det() > 0:
|
|
699
|
+
return B
|
|
700
|
+
else:
|
|
701
|
+
# Orientation-reversing isometries swap the nappes of
|
|
702
|
+
# the lightcone. This fixes that issue.
|
|
703
|
+
return -B
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
def SO21_to_SL2R(M):
|
|
707
|
+
r"""
|
|
708
|
+
A homomorphism from `SO(2, 1)` to `SL(2, \RR)`.
|
|
709
|
+
|
|
710
|
+
Note that this is not the only homomorphism, but it is the only one
|
|
711
|
+
that works in the context of the implemented 2D hyperbolic geometry
|
|
712
|
+
models.
|
|
713
|
+
|
|
714
|
+
EXAMPLES::
|
|
715
|
+
|
|
716
|
+
sage: from sage.geometry.hyperbolic_space.hyperbolic_coercion import SO21_to_SL2R
|
|
717
|
+
sage: (SO21_to_SL2R(identity_matrix(3)) - identity_matrix(2)).norm() < 10**-4 # needs scipy
|
|
718
|
+
True
|
|
719
|
+
"""
|
|
720
|
+
####################################################################
|
|
721
|
+
# SL(2,R) is the double cover of SO (2,1)^+, so we need to choose #
|
|
722
|
+
# a lift. I have formulas for the absolute values of each entry #
|
|
723
|
+
# a,b ,c,d of the lift matrix(2,[a,b,c,d]), but we need to choose #
|
|
724
|
+
# one entry to be positive. I choose d for no particular reason, #
|
|
725
|
+
# unless d = 0, then we choose c > 0. The basic strategy for this #
|
|
726
|
+
# function is to find the linear map induced by the SO(2,1) #
|
|
727
|
+
# element on the Lie algebra sl(2, R). This corresponds to the #
|
|
728
|
+
# Adjoint action by a matrix A or -A in SL(2,R). To find which #
|
|
729
|
+
# matrix let X,Y,Z be a basis for sl(2,R) and look at the images #
|
|
730
|
+
# of X,Y,Z as well as the second and third standard basis vectors #
|
|
731
|
+
# for 2x2 matrices (these are traceless, so are in the Lie #
|
|
732
|
+
# algebra). These corresponds to AXA^-1 etc and give formulas #
|
|
733
|
+
# for the entries of A. #
|
|
734
|
+
####################################################################
|
|
735
|
+
(m_1,m_2,m_3,m_4,m_5,m_6,m_7,m_8,m_9) = M.list()
|
|
736
|
+
d = sqrt(Integer(1)/Integer(2)*m_5 - Integer(1)/Integer(2)*m_6 -
|
|
737
|
+
Integer(1)/Integer(2)*m_8 + Integer(1)/Integer(2)*m_9)
|
|
738
|
+
if M.det() > 0: # EPSILON?
|
|
739
|
+
det_sign = 1
|
|
740
|
+
elif M.det() < 0: # EPSILON?
|
|
741
|
+
det_sign = -1
|
|
742
|
+
if d > 0: # EPSILON?
|
|
743
|
+
c = (-Integer(1)/Integer(2)*m_4 + Integer(1)/Integer(2)*m_7)/d
|
|
744
|
+
b = (-Integer(1)/Integer(2)*m_2 + Integer(1)/Integer(2)*m_3)/d
|
|
745
|
+
ad = det_sign*1 + b*c # ad - bc = pm 1
|
|
746
|
+
a = ad/d
|
|
747
|
+
else: # d is 0, so we make c > 0
|
|
748
|
+
c = sqrt(-Integer(1)/Integer(2)*m_5 - Integer(1)/Integer(2)*m_6 +
|
|
749
|
+
Integer(1)/Integer(2)*m_8 + Integer(1)/Integer(2)*m_9)
|
|
750
|
+
d = (-Integer(1)/Integer(2)*m_4 + Integer(1)/Integer(2)*m_7)/c
|
|
751
|
+
# d = 0, so ad - bc = -bc = pm 1.
|
|
752
|
+
b = - (det_sign*1)/c
|
|
753
|
+
a = (Integer(1)/Integer(2)*m_4 + Integer(1)/Integer(2)*m_7)/b
|
|
754
|
+
A = matrix(2, [a, b, c, d])
|
|
755
|
+
return A
|