Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*- Hyperbolic Models
In this module, a hyperbolic model is a collection of data that allow the user to implement new models of hyperbolic space with minimal effort. The data include facts about the underlying set (such as whether the model is bounded), facts about the metric (such as whether the model is conformal), facts about the isometry group (such as whether it is a linear or projective group), and more. Generally speaking, any data or method that pertains to the model itself -- rather than the points, geodesics, or isometries of the model -- is implemented in this module.
Abstractly, a model of hyperbolic space is a connected, simply connected manifold equipped with a complete Riemannian metric of constant curvature `-1`. This module records information sufficient to enable computations in hyperbolic space without explicitly specifying the underlying set or its Riemannian metric. Although, see the `SageManifolds <http://sagemanifolds.obspm.fr/>`_ project if you would like to take this approach.
This module implements the abstract base class for a model of hyperbolic space of arbitrary dimension. It also contains the implementations of specific models of hyperbolic geometry.
AUTHORS:
- Greg Laun (2013): Initial version.
EXAMPLES:
We illustrate how the classes in this module encode data by comparing the upper half plane (UHP), Poincaré disk (PD) and hyperboloid (HM) models. First we create::
sage: U = HyperbolicPlane().UHP() sage: P = HyperbolicPlane().PD() sage: H = HyperbolicPlane().HM()
We note that the UHP and PD models are bounded while the HM model is not::
sage: U.is_bounded() and P.is_bounded() True sage: H.is_bounded() False
The isometry groups of UHP and PD are projective, while that of HM is linear::
sage: U.is_isometry_group_projective() True sage: H.is_isometry_group_projective() False
The models are responsible for determining if the coordinates of points and the matrix of linear maps are appropriate for constructing points and isometries in hyperbolic space::
sage: U.point_in_model(2 + I) True sage: U.point_in_model(2 - I) False sage: U.point_in_model(2) False sage: U.boundary_point_in_model(2) True """
#*********************************************************************** # # Copyright (C) 2013 Greg Laun <glaun@math.umd.edu> # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #***********************************************************************
HyperbolicPoint, HyperbolicPointUHP) HyperbolicIsometry, HyperbolicIsometryUHP, HyperbolicIsometryPD, HyperbolicIsometryKM, moebius_transform) HyperbolicGeodesic, HyperbolicGeodesicUHP, HyperbolicGeodesicPD, HyperbolicGeodesicKM, HyperbolicGeodesicHM) CoercionUHPtoPD, CoercionUHPtoKM, CoercionUHPtoHM, CoercionPDtoUHP, CoercionPDtoKM, CoercionPDtoHM, CoercionKMtoUHP, CoercionKMtoPD, CoercionKMtoHM, CoercionHMtoUHP, CoercionHMtoPD, CoercionHMtoKM)
##################################################################### ## Abstract model
r""" Abstract base class for hyperbolic models. """
dimension, isometry_group, isometry_group_is_projective): """ Initialize ``self``.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: TestSuite(UHP).run() sage: PD = HyperbolicPlane().PD() sage: TestSuite(PD).run() sage: KM = HyperbolicPlane().KM() sage: TestSuite(KM).run() sage: HM = HyperbolicPlane().HM() sage: TestSuite(HM).run() """
""" Return a string representation of ``self``.
EXAMPLES::
sage: HyperbolicPlane().UHP() Hyperbolic plane in the Upper Half Plane Model """
""" Construct an element of ``self``.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP(2 + I) Point in UHP I + 2 """
""" Return the name of this model.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP.name() 'Upper Half Plane Model' """
""" Return the short name of this model.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP.short_name() 'UHP' """
""" Return ``True`` if ``self`` is a bounded model.
EXAMPLES::
sage: HyperbolicPlane().UHP().is_bounded() True sage: HyperbolicPlane().PD().is_bounded() True sage: HyperbolicPlane().KM().is_bounded() True sage: HyperbolicPlane().HM().is_bounded() False """
""" Return ``True`` if ``self`` is a conformal model.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP.is_conformal() True """
""" Return ``True`` if the isometry group of ``self`` is projective.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP.is_isometry_group_projective() True """
r""" Return ``True`` if the point ``p`` is in the interior of the given model and ``False`` otherwise.
INPUT:
- any object that can converted into a complex number
OUTPUT:
- boolean
EXAMPLES::
sage: HyperbolicPlane().UHP().point_in_model(I) True sage: HyperbolicPlane().UHP().point_in_model(-I) False """ return True
r""" Test whether a point is in the model. If the point is in the model, do nothing. Otherwise, raise a ``ValueError``.
EXAMPLES::
sage: from sage.geometry.hyperbolic_space.hyperbolic_model import HyperbolicModelUHP sage: HyperbolicPlane().UHP().point_test(2 + I) sage: HyperbolicPlane().UHP().point_test(2 - I) Traceback (most recent call last): ... ValueError: -I + 2 is not a valid point in the UHP model """
r""" Return ``True`` if the point is on the ideal boundary of hyperbolic space and ``False`` otherwise.
INPUT:
- any object that can converted into a complex number
OUTPUT:
- boolean
EXAMPLES::
sage: HyperbolicPlane().UHP().boundary_point_in_model(I) False """ return True
r""" Test whether a point is in the model. If the point is in the model, do nothing; otherwise raise a ``ValueError``.
EXAMPLES::
sage: HyperbolicPlane().UHP().bdry_point_test(2) sage: HyperbolicPlane().UHP().bdry_point_test(1 + I) Traceback (most recent call last): ... ValueError: I + 1 is not a valid boundary point in the UHP model """
r""" Return ``True`` if the input matrix represents an isometry of the given model and ``False`` otherwise.
INPUT:
- a matrix that represents an isometry in the appropriate model
OUTPUT:
- boolean
EXAMPLES::
sage: HyperbolicPlane().UHP().isometry_in_model(identity_matrix(2)) True
sage: HyperbolicPlane().UHP().isometry_in_model(identity_matrix(3)) False """ return True
r""" Test whether an isometry ``A`` is in the model.
If the isometry is in the model, do nothing. Otherwise, raise a ``ValueError``.
EXAMPLES::
sage: HyperbolicPlane().UHP().isometry_test(identity_matrix(2)) sage: HyperbolicPlane().UHP().isometry_test(matrix(2, [I,1,2,1])) Traceback (most recent call last): ... ValueError: [I 1] [2 1] is not a valid isometry in the UHP model """
r""" Return a point in ``self``.
Automatically determine the type of point to return given either:
#. the coordinates of a point in the interior or ideal boundary of hyperbolic space, or #. a :class:`~sage.geometry.hyperbolic_space.hyperbolic_point.HyperbolicPoint` object.
INPUT:
- a point in hyperbolic space or on the ideal boundary
OUTPUT:
- a :class:`~sage.geometry.hyperbolic_space.hyperbolic_point.HyperbolicPoint`
EXAMPLES:
We can create an interior point via the coordinates::
sage: HyperbolicPlane().UHP().get_point(2*I) Point in UHP 2*I
Or we can create a boundary point via the coordinates::
sage: HyperbolicPlane().UHP().get_point(23) Boundary point in UHP 23
However we cannot create points outside of our model::
sage: HyperbolicPlane().UHP().get_point(12 - I) Traceback (most recent call last): ... ValueError: -I + 12 is not a valid point in the UHP model
::
sage: HyperbolicPlane().UHP().get_point(2 + 3*I) Point in UHP 3*I + 2
sage: HyperbolicPlane().PD().get_point(0) Point in PD 0
sage: HyperbolicPlane().KM().get_point((0,0)) Point in KM (0, 0)
sage: HyperbolicPlane().HM().get_point((0,0,1)) Point in HM (0, 0, 1)
sage: p = HyperbolicPlane().UHP().get_point(I, color="red") sage: p.graphics_options() {'color': 'red'}
::
sage: HyperbolicPlane().UHP().get_point(12) Boundary point in UHP 12
sage: HyperbolicPlane().UHP().get_point(infinity) Boundary point in UHP +Infinity
sage: HyperbolicPlane().PD().get_point(I) Boundary point in PD I
sage: HyperbolicPlane().KM().get_point((0,-1)) Boundary point in KM (0, -1) """
if coordinates.parent() is not self: coordinates = self(coordinates) coordinates.update_graphics(True, **graphics_options) return coordinates #both Point and BdryPoint
r""" Return a geodesic in the appropriate model.
EXAMPLES::
sage: HyperbolicPlane().UHP().get_geodesic(I, 2*I) Geodesic in UHP from I to 2*I
sage: HyperbolicPlane().PD().get_geodesic(0, I/2) Geodesic in PD from 0 to 1/2*I
sage: HyperbolicPlane().KM().get_geodesic((1/2, 1/2), (0,0)) Geodesic in KM from (1/2, 1/2) to (0, 0)
sage: HyperbolicPlane().HM().get_geodesic((0,0,1), (1,0, sqrt(2))) Geodesic in HM from (0, 0, 1) to (1, 0, sqrt(2))
TESTS::
sage: UHP = HyperbolicPlane().UHP() sage: g = UHP.get_geodesic(UHP.get_point(I), UHP.get_point(2 + I)) sage: h = UHP.get_geodesic(I, 2 + I) sage: g == h True """ if isinstance(start, HyperbolicGeodesic): G = start if G.model() is not self: G = G.to_model(self) G.update_graphics(True, **graphics_options) return G raise ValueError("the start and end points must be specified")
r""" Return an isometry in ``self`` from the matrix ``A`` in the isometry group of ``self``.
EXAMPLES::
sage: HyperbolicPlane().UHP().get_isometry(identity_matrix(2)) Isometry in UHP [1 0] [0 1]
sage: HyperbolicPlane().PD().get_isometry(identity_matrix(2)) Isometry in PD [1 0] [0 1]
sage: HyperbolicPlane().KM().get_isometry(identity_matrix(3)) Isometry in KM [1 0 0] [0 1 0] [0 0 1]
sage: HyperbolicPlane().HM().get_isometry(identity_matrix(3)) Isometry in HM [1 0 0] [0 1 0] [0 0 1] """ return A
r""" Return a random point in ``self``.
The points are uniformly distributed over the rectangle `[-10, 10] \times [0, 10 i]` in the upper half plane model.
EXAMPLES::
sage: p = HyperbolicPlane().UHP().random_element() sage: bool((p.coordinates().imag()) > 0) True
sage: p = HyperbolicPlane().PD().random_element() sage: HyperbolicPlane().PD().point_in_model(p.coordinates()) True
sage: p = HyperbolicPlane().KM().random_element() sage: HyperbolicPlane().KM().point_in_model(p.coordinates()) True
sage: p = HyperbolicPlane().HM().random_element().coordinates() sage: bool((p[0]**2 + p[1]**2 - p[2]**2 - 1) < 10**-8) True """
r""" Return a random point of ``self``.
The points are uniformly distributed over the rectangle `[-10, 10] \times [0, 10 i]` in the upper half plane model.
EXAMPLES::
sage: p = HyperbolicPlane().UHP().random_point() sage: bool((p.coordinates().imag()) > 0) True
sage: PD = HyperbolicPlane().PD() sage: p = PD.random_point() sage: PD.point_in_model(p.coordinates()) True """
r""" Return a random hyperbolic geodesic.
Return the geodesic between two random points.
EXAMPLES::
sage: h = HyperbolicPlane().PD().random_geodesic() sage: bool((h.endpoints()[0].coordinates()).imag() >= 0) True """
r""" Return a random isometry in the model of ``self``.
INPUT:
- ``preserve_orientation`` -- if ``True`` return an orientation-preserving isometry
OUTPUT:
- a hyperbolic isometry
EXAMPLES::
sage: A = HyperbolicPlane().PD().random_isometry() sage: A.preserves_orientation() True sage: B = HyperbolicPlane().PD().random_isometry(preserve_orientation=False) sage: B.preserves_orientation() False """
################ # Dist methods # ################
r""" Calculate the hyperbolic distance between ``a`` and ``b``.
INPUT:
- ``a``, ``b`` -- a point or geodesic
OUTPUT:
- the hyperbolic distance
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: p1 = UHP.get_point(5 + 7*I) sage: p2 = UHP.get_point(1.0 + I) sage: UHP.dist(p1, p2) 2.23230104635820
sage: PD = HyperbolicPlane().PD() sage: p1 = PD.get_point(0) sage: p2 = PD.get_point(I/2) sage: PD.dist(p1, p2) arccosh(5/3)
sage: UHP(p1).dist(UHP(p2)) arccosh(5/3)
sage: KM = HyperbolicPlane().KM() sage: p1 = KM.get_point((0, 0)) sage: p2 = KM.get_point((1/2, 1/2)) sage: numerical_approx(KM.dist(p1, p2)) 0.881373587019543
sage: HM = HyperbolicPlane().HM() sage: p1 = HM.get_point((0,0,1)) sage: p2 = HM.get_point((1,0,sqrt(2))) sage: numerical_approx(HM.dist(p1, p2)) 0.881373587019543
Distance between a point and itself is 0::
sage: p = UHP.get_point(47 + I) sage: UHP.dist(p, p) 0
Points on the boundary are infinitely far from interior points::
sage: UHP.get_point(3).dist(UHP.get_point(I)) +Infinity
TESTS::
sage: UHP.dist(UHP.get_point(I), UHP.get_point(2*I)) arccosh(5/4) sage: UHP.dist(I, 2*I) arccosh(5/4) """
return 0
# Find where a and b intersect the common perp... # ...and return their distance
raise NotImplementedError("can only compute distance between" " ultra-parallel and intersecting geodesics")
# If only one is a geodesic, make sure it's b to make things easier
r""" Compute the distance between two points.
INPUT:
- ``p1``, ``p2`` -- the coordinates of the points
EXAMPLES::
sage: HyperbolicPlane().PD()._dist_points(3/5*I, 0) arccosh(17/8) """
r""" Return the hyperbolic distance from a given hyperbolic geodesic and a hyperbolic point.
INPUT:
- ``start`` -- the start ideal point coordinates of the geodesic - ``end`` -- the end ideal point coordinates of the geodesic - ``p`` -- the coordinates of the point
OUTPUT:
- the hyperbolic distance
EXAMPLES::
sage: HyperbolicPlane().PD()._dist_geod_point(3/5*I + 4/5, I, 0) arccosh(1/10*sqrt(5)*((sqrt(5) - 1)^2 + 4) + 1)
If `p` is a boundary point, the distance is infinity::
sage: HyperbolicPlane().PD()._dist_geod_point(3/5*I + 4/5, I, 12/13*I + 5/13) +Infinity """
#################### # Isometry methods # ####################
r""" Given two fixed points ``repel`` and ``attract`` as hyperbolic points return a hyperbolic isometry with ``repel`` as repelling fixed point and ``attract`` as attracting fixed point.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: PD = HyperbolicPlane().PD() sage: PD.isometry_from_fixed_points(-i, i) Isometry in PD [ 3/4 1/4*I] [-1/4*I 3/4]
::
sage: p, q = PD.get_point(1/2 + I/2), PD.get_point(6/13 + 9/13*I) sage: PD.isometry_from_fixed_points(p, q) Traceback (most recent call last): ... ValueError: fixed points of hyperbolic elements must be ideal
sage: p, q = PD.get_point(4/5 + 3/5*I), PD.get_point(-I) sage: PD.isometry_from_fixed_points(p, q) Isometry in PD [ 1/6*I - 2/3 -1/3*I - 1/6] [ 1/3*I - 1/6 -1/6*I - 2/3] """
##################################################################### ## Upper half plane model
r""" Upper Half Plane model. """
""" Initialize ``self``.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: TestSuite(UHP).run() """ name="Upper Half Plane Model", short_name="UHP", bounded=True, conformal=True, dimension=2, isometry_group="PSL(2, \\RR)", isometry_group_is_projective=True)
""" Return if there is a coercion map from ``X`` to ``self``.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP.has_coerce_map_from(HyperbolicPlane().PD()) True sage: UHP.has_coerce_map_from(HyperbolicPlane().KM()) True sage: UHP.has_coerce_map_from(HyperbolicPlane().HM()) True sage: UHP.has_coerce_map_from(QQ) False """
r""" Check whether a complex number lies in the open upper half plane.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP.point_in_model(1 + I) True sage: UHP.point_in_model(infinity) False sage: UHP.point_in_model(CC(infinity)) False sage: UHP.point_in_model(RR(infinity)) False sage: UHP.point_in_model(1) False sage: UHP.point_in_model(12) False sage: UHP.point_in_model(1 - I) False sage: UHP.point_in_model(-2*I) False sage: UHP.point_in_model(I) True sage: UHP.point_in_model(0) # Not interior point False """ return p.is_boundary()
r""" Check whether a complex number is a real number or ``\infty``. In the ``UHP.model_name_name``, this is the ideal boundary of hyperbolic space.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP.boundary_point_in_model(1 + I) False sage: UHP.boundary_point_in_model(infinity) True sage: UHP.boundary_point_in_model(CC(infinity)) True sage: UHP.boundary_point_in_model(RR(infinity)) True sage: UHP.boundary_point_in_model(1) True sage: UHP.boundary_point_in_model(12) True sage: UHP.boundary_point_in_model(1 - I) False sage: UHP.boundary_point_in_model(-2*I) False sage: UHP.boundary_point_in_model(0) True sage: UHP.boundary_point_in_model(I) False """ return p.is_boundary()
r""" Check that ``A`` acts as an isometry on the upper half plane. That is, ``A`` must be an invertible `2 \times 2` matrix with real entries.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: A = matrix(2,[1,2,3,4]) sage: UHP.isometry_in_model(A) True sage: B = matrix(2,[I,2,4,1]) sage: UHP.isometry_in_model(B) False
An example of a matrix `A` such that `\det(A) \neq 1`, but the `A` acts isometrically::
sage: C = matrix(2,[10,0,0,10]) sage: UHP.isometry_in_model(C) True """ return True sum([k in RR for k in A.list()]) == 4 and abs(A.det()) > -EPSILON)
r""" Return a graphic object that makes the model easier to visualize. For the upper half space, the background object is the ideal boundary.
EXAMPLES::
sage: hp = HyperbolicPlane().UHP().get_background_graphic() """
################ # Dist methods # ################
r""" Compute the distance between two points in the Upper Half Plane using the hyperbolic metric.
INPUT:
- ``p1``, ``p2`` -- the coordinates of the points
EXAMPLES::
sage: HyperbolicPlane().UHP()._dist_points(4.0*I, I) 1.38629436111989 """
r""" Return the hyperbolic distance from a given hyperbolic geodesic and a hyperbolic point.
INPUT:
- ``start`` -- the start ideal point coordinates of the geodesic - ``end`` -- the end ideal point coordinates of the geodesic - ``p`` -- the coordinates of the point
OUTPUT:
- the hyperbolic distance
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP._dist_geod_point(2, infinity, I) arccosh(1/10*sqrt(5)*((sqrt(5) - 1)^2 + 4) + 1)
If `p` is a boundary point, the distance is infinity::
sage: HyperbolicPlane().UHP()._dist_geod_point(2, infinity, 5) +Infinity """ # Here is the trick for computing distance to a geodesic: # find an isometry mapping the geodesic to the geodesic between # 0 and infinity (so corresponding to the line imag(z) = 0. # then any complex number is r exp(i*theta) in polar coordinates. # the mutual perpendicular between this point and imag(z) = 0 # intersects imag(z) = 0 at ri. So we calculate the distance # between r exp(i*theta) and ri after we transform the original # point. # Not a straight line: # Map the endpoints to 0 and infinity and the midpoint to 1. T = HyperbolicGeodesicUHP._crossratio_matrix(start, (start + end)/2, end) else: # Is a straight line: # Map the endpoints to 0 and infinity and another endpoint to 1.
################# # Point Methods # #################
r""" Return a random point in the upper half plane. The points are uniformly distributed over the rectangle `[-10, 10] \times [0, 10i]`.
EXAMPLES::
sage: p = HyperbolicPlane().UHP().random_point().coordinates() sage: bool((p.imag()) > 0) True """ # TODO: use **kwargs to allow these to be set + I * RR.random_element(min=imag_min, max=imag_max)
#################### # Isometry Methods # ####################
r""" Given two fixed points ``repel`` and ``attract`` as complex numbers return a hyperbolic isometry with ``repel`` as repelling fixed point and ``attract`` as attracting fixed point.
EXAMPLES::
sage: UHP = HyperbolicPlane().UHP() sage: UHP.isometry_from_fixed_points(2 + I, 3 + I) Traceback (most recent call last): ... ValueError: fixed points of hyperbolic elements must be ideal
sage: UHP.isometry_from_fixed_points(2, 0) Isometry in UHP [ -1 0] [-1/3 -1/3]
TESTS::
sage: UHP = HyperbolicPlane().UHP() sage: UHP.isometry_from_fixed_points(0, 4) Isometry in UHP [ -1 0] [-1/5 -1/5] sage: UHP.isometry_from_fixed_points(UHP.get_point(0), UHP.get_point(4)) Isometry in UHP [ -1 0] [-1/5 -1/5] """
A = self._moebius_sending([infinity, attract, attract + 1], [infinity, attract, attract + 2]) [repel, infinity, repel + 2]) else: [repel, attract, max(repel, attract) + 1])
r""" Return a random isometry in the Upper Half Plane model.
INPUT:
- ``preserve_orientation`` -- if ``True`` return an orientation-preserving isometry
OUTPUT:
- a hyperbolic isometry
EXAMPLES::
sage: A = HyperbolicPlane().UHP().random_isometry() sage: B = HyperbolicPlane().UHP().random_isometry(preserve_orientation=False) sage: B.preserves_orientation() False """ [a,b,c,d] = [RR.random_element() for k in range(4)] M = M * matrix(2,[0,1,1,0]) M = M * matrix(2,[0,1,1,0])
################### # Helping Methods # ###################
def _moebius_sending(z, w): #UHP r""" Given two lists ``z`` and ``w`` of three points each in `\mathbb{CP}^1`, return the linear fractional transformation taking the points in ``z`` to the points in ``w``.
EXAMPLES::
sage: from sage.geometry.hyperbolic_space.hyperbolic_model import HyperbolicModelUHP sage: from sage.geometry.hyperbolic_space.hyperbolic_isometry import moebius_transform sage: bool(abs(moebius_transform(HyperbolicModelUHP._moebius_sending([1,2,infinity],[3 - I, 5*I,-12]),1) - 3 + I) < 10^-4) True sage: bool(abs(moebius_transform(HyperbolicModelUHP._moebius_sending([1,2,infinity],[3 - I, 5*I,-12]),2) - 5*I) < 10^-4) True sage: bool(abs(moebius_transform(HyperbolicModelUHP._moebius_sending([1,2,infinity],[3 - I, 5*I,-12]),infinity) + 12) < 10^-4) True """ raise TypeError("moebius_sending requires each list to be three points long")
##################################################################### ## Poincaré disk model
r""" Poincaré Disk Model. """
""" Initialize ``self``.
EXAMPLES::
sage: PD = HyperbolicPlane().PD() sage: TestSuite(PD).run() """ # name should really be 'Poincaré Disk Model', but utf8 is not # accepted by repr name=u'Poincare Disk Model', short_name="PD", bounded=True, conformal=True, dimension=2, isometry_group="PU(1, 1)", isometry_group_is_projective=True)
""" Return if there is a coercion map from ``X`` to ``self``.
EXAMPLES::
sage: PD = HyperbolicPlane().PD() sage: PD.has_coerce_map_from(HyperbolicPlane().UHP()) True sage: PD.has_coerce_map_from(HyperbolicPlane().KM()) True sage: PD.has_coerce_map_from(HyperbolicPlane().HM()) True sage: PD.has_coerce_map_from(QQ) False """
r""" Check whether a complex number lies in the open unit disk.
EXAMPLES::
sage: PD = HyperbolicPlane().PD() sage: PD.point_in_model(1.00) False sage: PD.point_in_model(1/2 + I/2) True sage: PD.point_in_model(1 + .2*I) False """ return p.is_boundary()
r""" Check whether a complex number lies in the open unit disk.
EXAMPLES::
sage: PD = HyperbolicPlane().PD() sage: PD.boundary_point_in_model(1.00) True sage: PD.boundary_point_in_model(1/2 + I/2) False sage: PD.boundary_point_in_model(1 + .2*I) False """ return p.is_boundary()
r""" Check if the given matrix ``A`` is in the group `U(1,1)`.
EXAMPLES::
sage: z = [CC.random_element() for k in range(2)]; z.sort(key=abs) sage: A = matrix(2,[z[1], z[0],z[0].conjugate(),z[1].conjugate()]) sage: HyperbolicPlane().PD().isometry_in_model(A) True """ return True # alpha = A[0][0] # beta = A[0][1] # Orientation preserving and reversing HyperbolicIsometryPD._orientation_preserving(I * A))
r""" Return a graphic object that makes the model easier to visualize.
For the Poincaré disk, the background object is the ideal boundary.
EXAMPLES::
sage: circ = HyperbolicPlane().PD().get_background_graphic() """
##################################################################### ## Klein disk model
r""" Klein Model. """
""" Initialize ``self``.
EXAMPLES::
sage: KM = HyperbolicPlane().KM() sage: TestSuite(KM).run() """ name="Klein Disk Model", short_name="KM", bounded=True, conformal=False, dimension=2, isometry_group="PSO(2, 1)", isometry_group_is_projective=True)
""" Return if there is a coercion map from ``X`` to ``self``.
EXAMPLES::
sage: KM = HyperbolicPlane().UHP() sage: KM.has_coerce_map_from(HyperbolicPlane().UHP()) True sage: KM.has_coerce_map_from(HyperbolicPlane().PD()) True sage: KM.has_coerce_map_from(HyperbolicPlane().HM()) True sage: KM.has_coerce_map_from(QQ) False """
r""" Check whether a point lies in the open unit disk.
EXAMPLES::
sage: KM = HyperbolicPlane().KM() sage: KM.point_in_model((1, 0)) False sage: KM.point_in_model((1/2, 1/2)) True sage: KM.point_in_model((1, .2)) False """ return p.is_boundary()
r""" Check whether a point lies in the unit circle, which corresponds to the ideal boundary of the hyperbolic plane in the Klein model.
EXAMPLES::
sage: KM = HyperbolicPlane().KM() sage: KM.boundary_point_in_model((1, 0)) True sage: KM.boundary_point_in_model((1/2, 1/2)) False sage: KM.boundary_point_in_model((1, .2)) False """ return p.is_boundary()
r""" Check if the given matrix ``A`` is in the group `SO(2,1)`.
EXAMPLES::
sage: A = matrix(3, [[1, 0, 0], [0, 17/8, 15/8], [0, 15/8, 17/8]]) sage: HyperbolicPlane().KM().isometry_in_model(A) True """ return True EPSILON)
r""" Return a graphic object that makes the model easier to visualize.
For the Klein model, the background object is the ideal boundary.
EXAMPLES::
sage: circ = HyperbolicPlane().KM().get_background_graphic() """
##################################################################### ## Hyperboloid model
r""" Hyperboloid Model. """
""" Initialize ``self``.
EXAMPLES::
sage: HM = HyperbolicPlane().HM() sage: TestSuite(HM).run() """ name="Hyperboloid Model", short_name="HM", bounded=False, conformal=True, dimension=2, isometry_group="SO(2, 1)", isometry_group_is_projective=False)
""" Return if there is a coercion map from ``X`` to ``self``.
EXAMPLES::
sage: HM = HyperbolicPlane().UHP() sage: HM.has_coerce_map_from(HyperbolicPlane().UHP()) True sage: HM.has_coerce_map_from(HyperbolicPlane().PD()) True sage: HM.has_coerce_map_from(HyperbolicPlane().KM()) True sage: HM.has_coerce_map_from(QQ) False """
r""" Check whether a complex number lies in the hyperboloid.
EXAMPLES::
sage: HM = HyperbolicPlane().HM() sage: HM.point_in_model((0,0,1)) True sage: HM.point_in_model((1,0,sqrt(2))) True sage: HM.point_in_model((1,2,1)) False """ return p.is_boundary()
r""" Return ``False`` since the Hyperboloid model has no boundary points.
EXAMPLES::
sage: HM = HyperbolicPlane().HM() sage: HM.boundary_point_in_model((0,0,1)) False sage: HM.boundary_point_in_model((1,0,sqrt(2))) False sage: HM.boundary_point_in_model((1,2,1)) False """
r""" Test that the matrix ``A`` is in the group `SO(2,1)^+`.
EXAMPLES::
sage: A = diagonal_matrix([1,1,-1]) sage: HyperbolicPlane().HM().isometry_in_model(A) True """ return True
r""" Return a graphic object that makes the model easier to visualize. For the hyperboloid model, the background object is the hyperboloid itself.
EXAMPLES::
sage: H = HyperbolicPlane().HM().get_background_graphic() """ (x, -x_max, x_max), (y,-x_max, x_max), opacity=hyperboloid_opacity, **bdry_options) |