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 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()
>>> from sage.all import *
>>> U = HyperbolicPlane().UHP()
>>> P = HyperbolicPlane().PD()
>>> H = HyperbolicPlane().HM()
U = HyperbolicPlane().UHP()
P = HyperbolicPlane().PD()
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
>>> from sage.all import *
>>> U.is_bounded() and P.is_bounded()
True
>>> H.is_bounded()
False
U.is_bounded() and P.is_bounded()
H.is_bounded()

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
>>> from sage.all import *
>>> U.is_isometry_group_projective()
True
>>> H.is_isometry_group_projective()
False
U.is_isometry_group_projective()
H.is_isometry_group_projective()

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
>>> from sage.all import *
>>> U.point_in_model(Integer(2) + I)
True
>>> U.point_in_model(Integer(2) - I)
False
>>> U.point_in_model(Integer(2))
False
>>> U.boundary_point_in_model(Integer(2))
True
U.point_in_model(2 + I)
U.point_in_model(2 - I)
U.point_in_model(2)
U.boundary_point_in_model(2)
class sage.geometry.hyperbolic_space.hyperbolic_model.HyperbolicModel(space, name, short_name, bounded, conformal, dimension, isometry_group, isometry_group_is_projective)[source]

Bases: Parent, UniqueRepresentation, BindableClass

Abstract base class for hyperbolic models.

Element[source]

alias of HyperbolicPoint

bdry_point_test(p)[source]

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
>>> from sage.all import *
>>> HyperbolicPlane().UHP().bdry_point_test(Integer(2))
>>> HyperbolicPlane().UHP().bdry_point_test(Integer(1) + I)
Traceback (most recent call last):
...
ValueError: I + 1 is not a valid boundary point in the UHP model
HyperbolicPlane().UHP().bdry_point_test(2)
HyperbolicPlane().UHP().bdry_point_test(1 + I)
boundary_point_in_model(p)[source]

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
>>> from sage.all import *
>>> HyperbolicPlane().UHP().boundary_point_in_model(I)
False
HyperbolicPlane().UHP().boundary_point_in_model(I)
dist(a, b)[source]

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
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> p1 = UHP.get_point(Integer(5) + Integer(7)*I)
>>> p2 = UHP.get_point(RealNumber('1.0') + I)
>>> UHP.dist(p1, p2)
2.23230104635820

>>> PD = HyperbolicPlane().PD()
>>> p1 = PD.get_point(Integer(0))
>>> p2 = PD.get_point(I/Integer(2))
>>> PD.dist(p1, p2)
arccosh(5/3)

>>> UHP(p1).dist(UHP(p2))
arccosh(5/3)

>>> KM = HyperbolicPlane().KM()
>>> p1 = KM.get_point((Integer(0), Integer(0)))
>>> p2 = KM.get_point((Integer(1)/Integer(2), Integer(1)/Integer(2)))
>>> numerical_approx(KM.dist(p1, p2))
0.881373587019543

>>> HM = HyperbolicPlane().HM()
>>> p1 = HM.get_point((Integer(0),Integer(0),Integer(1)))
>>> p2 = HM.get_point((Integer(1),Integer(0),sqrt(Integer(2))))
>>> numerical_approx(HM.dist(p1, p2))
0.881373587019543
UHP = HyperbolicPlane().UHP()
p1 = UHP.get_point(5 + 7*I)
p2 = UHP.get_point(1.0 + I)
UHP.dist(p1, p2)
PD = HyperbolicPlane().PD()
p1 = PD.get_point(0)
p2 = PD.get_point(I/2)
PD.dist(p1, p2)
UHP(p1).dist(UHP(p2))
KM = HyperbolicPlane().KM()
p1 = KM.get_point((0, 0))
p2 = KM.get_point((1/2, 1/2))
numerical_approx(KM.dist(p1, p2))
HM = HyperbolicPlane().HM()
p1 = HM.get_point((0,0,1))
p2 = HM.get_point((1,0,sqrt(2)))
numerical_approx(HM.dist(p1, p2))

Distance between a point and itself is 0:

sage: p = UHP.get_point(47 + I)
sage: UHP.dist(p, p)
0
>>> from sage.all import *
>>> p = UHP.get_point(Integer(47) + I)
>>> UHP.dist(p, p)
0
p = UHP.get_point(47 + I)
UHP.dist(p, p)

Points on the boundary are infinitely far from interior points:

sage: UHP.get_point(3).dist(UHP.get_point(I))
+Infinity
>>> from sage.all import *
>>> UHP.get_point(Integer(3)).dist(UHP.get_point(I))
+Infinity
UHP.get_point(3).dist(UHP.get_point(I))
get_geodesic(start, end=None, **graphics_options)[source]

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))
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_geodesic(I, Integer(2)*I)
Geodesic in UHP from I to 2*I

>>> HyperbolicPlane().PD().get_geodesic(Integer(0), I/Integer(2))
Geodesic in PD from 0 to 1/2*I

>>> HyperbolicPlane().KM().get_geodesic((Integer(1)/Integer(2), Integer(1)/Integer(2)), (Integer(0),Integer(0)))
Geodesic in KM from (1/2, 1/2) to (0, 0)

>>> HyperbolicPlane().HM().get_geodesic((Integer(0),Integer(0),Integer(1)), (Integer(1),Integer(0), sqrt(Integer(2))))
Geodesic in HM from (0, 0, 1) to (1, 0, sqrt(2))
HyperbolicPlane().UHP().get_geodesic(I, 2*I)
HyperbolicPlane().PD().get_geodesic(0, I/2)
HyperbolicPlane().KM().get_geodesic((1/2, 1/2), (0,0))
HyperbolicPlane().HM().get_geodesic((0,0,1), (1,0, sqrt(2)))
get_isometry(A)[source]

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))               # needs scipy
Isometry in KM
[1 0 0]
[0 1 0]
[0 0 1]

sage: HyperbolicPlane().HM().get_isometry(identity_matrix(3))               # needs scipy
Isometry in HM
[1 0 0]
[0 1 0]
[0 0 1]
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_isometry(identity_matrix(Integer(2)))
Isometry in UHP
[1 0]
[0 1]

>>> HyperbolicPlane().PD().get_isometry(identity_matrix(Integer(2)))
Isometry in PD
[1 0]
[0 1]

>>> HyperbolicPlane().KM().get_isometry(identity_matrix(Integer(3)))               # needs scipy
Isometry in KM
[1 0 0]
[0 1 0]
[0 0 1]

>>> HyperbolicPlane().HM().get_isometry(identity_matrix(Integer(3)))               # needs scipy
Isometry in HM
[1 0 0]
[0 1 0]
[0 0 1]
HyperbolicPlane().UHP().get_isometry(identity_matrix(2))
HyperbolicPlane().PD().get_isometry(identity_matrix(2))
HyperbolicPlane().KM().get_isometry(identity_matrix(3))               # needs scipy
HyperbolicPlane().HM().get_isometry(identity_matrix(3))               # needs scipy
get_point(coordinates, is_boundary=None, **graphics_options)[source]

Return a point in self.

Automatically determine the type of point to return given either:

  1. the coordinates of a point in the interior or ideal boundary of hyperbolic space, or

  2. a HyperbolicPoint object.

INPUT:

  • a point in hyperbolic space or on the ideal boundary

OUTPUT: a HyperbolicPoint

EXAMPLES:

We can create an interior point via the coordinates:

sage: HyperbolicPlane().UHP().get_point(2*I)
Point in UHP 2*I
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_point(Integer(2)*I)
Point in UHP 2*I
HyperbolicPlane().UHP().get_point(2*I)

Or we can create a boundary point via the coordinates:

sage: HyperbolicPlane().UHP().get_point(23)
Boundary point in UHP 23
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_point(Integer(23))
Boundary point in UHP 23
HyperbolicPlane().UHP().get_point(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
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_point(Integer(12) - I)
Traceback (most recent call last):
...
ValueError: -I + 12 is not a valid point in the UHP model
HyperbolicPlane().UHP().get_point(12 - I)
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'}
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_point(Integer(2) + Integer(3)*I)
Point in UHP 3*I + 2

>>> HyperbolicPlane().PD().get_point(Integer(0))
Point in PD 0

>>> HyperbolicPlane().KM().get_point((Integer(0),Integer(0)))
Point in KM (0, 0)

>>> HyperbolicPlane().HM().get_point((Integer(0),Integer(0),Integer(1)))
Point in HM (0, 0, 1)

>>> p = HyperbolicPlane().UHP().get_point(I, color='red')
>>> p.graphics_options()
{'color': 'red'}
HyperbolicPlane().UHP().get_point(2 + 3*I)
HyperbolicPlane().PD().get_point(0)
HyperbolicPlane().KM().get_point((0,0))
HyperbolicPlane().HM().get_point((0,0,1))
p = HyperbolicPlane().UHP().get_point(I, color='red')
p.graphics_options()
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_point(Integer(2) + Integer(3)*I)
Point in UHP 3*I + 2

>>> HyperbolicPlane().PD().get_point(Integer(0))
Point in PD 0

>>> HyperbolicPlane().KM().get_point((Integer(0),Integer(0)))
Point in KM (0, 0)

>>> HyperbolicPlane().HM().get_point((Integer(0),Integer(0),Integer(1)))
Point in HM (0, 0, 1)

>>> p = HyperbolicPlane().UHP().get_point(I, color='red')
>>> p.graphics_options()
{'color': 'red'}
HyperbolicPlane().UHP().get_point(2 + 3*I)
HyperbolicPlane().PD().get_point(0)
HyperbolicPlane().KM().get_point((0,0))
HyperbolicPlane().HM().get_point((0,0,1))
p = HyperbolicPlane().UHP().get_point(I, color='red')
p.graphics_options()
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)
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_point(Integer(12))
Boundary point in UHP 12

>>> HyperbolicPlane().UHP().get_point(infinity)
Boundary point in UHP +Infinity

>>> HyperbolicPlane().PD().get_point(I)
Boundary point in PD I

>>> HyperbolicPlane().KM().get_point((Integer(0),-Integer(1)))
Boundary point in KM (0, -1)
HyperbolicPlane().UHP().get_point(12)
HyperbolicPlane().UHP().get_point(infinity)
HyperbolicPlane().PD().get_point(I)
HyperbolicPlane().KM().get_point((0,-1))
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_point(Integer(12))
Boundary point in UHP 12

>>> HyperbolicPlane().UHP().get_point(infinity)
Boundary point in UHP +Infinity

>>> HyperbolicPlane().PD().get_point(I)
Boundary point in PD I

>>> HyperbolicPlane().KM().get_point((Integer(0),-Integer(1)))
Boundary point in KM (0, -1)
HyperbolicPlane().UHP().get_point(12)
HyperbolicPlane().UHP().get_point(infinity)
HyperbolicPlane().PD().get_point(I)
HyperbolicPlane().KM().get_point((0,-1))
is_bounded()[source]

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
>>> from sage.all import *
>>> HyperbolicPlane().UHP().is_bounded()
True
>>> HyperbolicPlane().PD().is_bounded()
True
>>> HyperbolicPlane().KM().is_bounded()
True
>>> HyperbolicPlane().HM().is_bounded()
False
HyperbolicPlane().UHP().is_bounded()
HyperbolicPlane().PD().is_bounded()
HyperbolicPlane().KM().is_bounded()
HyperbolicPlane().HM().is_bounded()
is_conformal()[source]

Return True if self is a conformal model.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: UHP.is_conformal()
True
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.is_conformal()
True
UHP = HyperbolicPlane().UHP()
UHP.is_conformal()
is_isometry_group_projective()[source]

Return True if the isometry group of self is projective.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: UHP.is_isometry_group_projective()
True
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.is_isometry_group_projective()
True
UHP = HyperbolicPlane().UHP()
UHP.is_isometry_group_projective()
isometry_from_fixed_points(repel, attract)[source]

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]
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> PD = HyperbolicPlane().PD()
>>> PD.isometry_from_fixed_points(-i, i)
Isometry in PD
[   3/4  1/4*I]
[-1/4*I    3/4]
UHP = HyperbolicPlane().UHP()
PD = HyperbolicPlane().PD()
PD.isometry_from_fixed_points(-i, i)
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]
>>> from sage.all import *
>>> p, q = PD.get_point(Integer(1)/Integer(2) + I/Integer(2)), PD.get_point(Integer(6)/Integer(13) + Integer(9)/Integer(13)*I)
>>> PD.isometry_from_fixed_points(p, q)
Traceback (most recent call last):
...
ValueError: fixed points of hyperbolic elements must be ideal

>>> p, q = PD.get_point(Integer(4)/Integer(5) + Integer(3)/Integer(5)*I), PD.get_point(-I)
>>> 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]
p, q = PD.get_point(1/2 + I/2), PD.get_point(6/13 + 9/13*I)
PD.isometry_from_fixed_points(p, q)
p, q = PD.get_point(4/5 + 3/5*I), PD.get_point(-I)
PD.isometry_from_fixed_points(p, q)
>>> from sage.all import *
>>> p, q = PD.get_point(Integer(1)/Integer(2) + I/Integer(2)), PD.get_point(Integer(6)/Integer(13) + Integer(9)/Integer(13)*I)
>>> PD.isometry_from_fixed_points(p, q)
Traceback (most recent call last):
...
ValueError: fixed points of hyperbolic elements must be ideal

>>> p, q = PD.get_point(Integer(4)/Integer(5) + Integer(3)/Integer(5)*I), PD.get_point(-I)
>>> 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]
p, q = PD.get_point(1/2 + I/2), PD.get_point(6/13 + 9/13*I)
PD.isometry_from_fixed_points(p, q)
p, q = PD.get_point(4/5 + 3/5*I), PD.get_point(-I)
PD.isometry_from_fixed_points(p, q)
isometry_in_model(A)[source]

Return True if the input matrix represents an isometry of the given model and False otherwise.

INPUT:

  • A – 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
>>> from sage.all import *
>>> HyperbolicPlane().UHP().isometry_in_model(identity_matrix(Integer(2)))
True

>>> HyperbolicPlane().UHP().isometry_in_model(identity_matrix(Integer(3)))
False
HyperbolicPlane().UHP().isometry_in_model(identity_matrix(2))
HyperbolicPlane().UHP().isometry_in_model(identity_matrix(3))
isometry_test(A)[source]

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
>>> from sage.all import *
>>> HyperbolicPlane().UHP().isometry_test(identity_matrix(Integer(2)))
>>> HyperbolicPlane().UHP().isometry_test(matrix(Integer(2), [I,Integer(1),Integer(2),Integer(1)]))
Traceback (most recent call last):
...
ValueError:
[I 1]
[2 1] is not a valid isometry in the UHP model
HyperbolicPlane().UHP().isometry_test(identity_matrix(2))
HyperbolicPlane().UHP().isometry_test(matrix(2, [I,1,2,1]))
name()[source]

Return the name of this model.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: UHP.name()
'Upper Half Plane Model'
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.name()
'Upper Half Plane Model'
UHP = HyperbolicPlane().UHP()
UHP.name()
point_in_model(p)[source]

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
>>> from sage.all import *
>>> HyperbolicPlane().UHP().point_in_model(I)
True
>>> HyperbolicPlane().UHP().point_in_model(-I)
False
HyperbolicPlane().UHP().point_in_model(I)
HyperbolicPlane().UHP().point_in_model(-I)
point_test(p)[source]

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
>>> from sage.all import *
>>> from sage.geometry.hyperbolic_space.hyperbolic_model import HyperbolicModelUHP
>>> HyperbolicPlane().UHP().point_test(Integer(2) + I)
>>> HyperbolicPlane().UHP().point_test(Integer(2) - I)
Traceback (most recent call last):
...
ValueError: -I + 2 is not a valid point in the UHP model
from sage.geometry.hyperbolic_space.hyperbolic_model import HyperbolicModelUHP
HyperbolicPlane().UHP().point_test(2 + I)
HyperbolicPlane().UHP().point_test(2 - I)
random_element(**kwargs)[source]

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
>>> from sage.all import *
>>> p = HyperbolicPlane().UHP().random_element()
>>> bool((p.coordinates().imag()) > Integer(0))
True

>>> p = HyperbolicPlane().PD().random_element()
>>> HyperbolicPlane().PD().point_in_model(p.coordinates())
True

>>> p = HyperbolicPlane().KM().random_element()
>>> HyperbolicPlane().KM().point_in_model(p.coordinates())
True

>>> p = HyperbolicPlane().HM().random_element().coordinates()
>>> bool((p[Integer(0)]**Integer(2) + p[Integer(1)]**Integer(2) - p[Integer(2)]**Integer(2) - Integer(1)) < Integer(10)**-Integer(8))
True
p = HyperbolicPlane().UHP().random_element()
bool((p.coordinates().imag()) > 0)
p = HyperbolicPlane().PD().random_element()
HyperbolicPlane().PD().point_in_model(p.coordinates())
p = HyperbolicPlane().KM().random_element()
HyperbolicPlane().KM().point_in_model(p.coordinates())
p = HyperbolicPlane().HM().random_element().coordinates()
bool((p[0]**2 + p[1]**2 - p[2]**2 - 1) < 10**-8)
random_geodesic(**kwargs)[source]

Return a random hyperbolic geodesic.

Return the geodesic between two random points.

EXAMPLES:

sage: h = HyperbolicPlane().PD().random_geodesic()
sage: all( e.coordinates().abs() <= 1 for e in h.endpoints() )
True
>>> from sage.all import *
>>> h = HyperbolicPlane().PD().random_geodesic()
>>> all( e.coordinates().abs() <= Integer(1) for e in h.endpoints() )
True
h = HyperbolicPlane().PD().random_geodesic()
all( e.coordinates().abs() <= 1 for e in h.endpoints() )
random_isometry(preserve_orientation=True, **kwargs)[source]

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: # needs scipy
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
>>> from sage.all import *
>>> # needs scipy
>>> A = HyperbolicPlane().PD().random_isometry()
>>> A.preserves_orientation()
True
>>> B = HyperbolicPlane().PD().random_isometry(preserve_orientation=False)
>>> B.preserves_orientation()
False
# needs scipy
A = HyperbolicPlane().PD().random_isometry()
A.preserves_orientation()
B = HyperbolicPlane().PD().random_isometry(preserve_orientation=False)
B.preserves_orientation()
random_point(**kwargs)[source]

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
>>> from sage.all import *
>>> p = HyperbolicPlane().UHP().random_point()
>>> bool((p.coordinates().imag()) > Integer(0))
True

>>> PD = HyperbolicPlane().PD()
>>> p = PD.random_point()
>>> PD.point_in_model(p.coordinates())
True
p = HyperbolicPlane().UHP().random_point()
bool((p.coordinates().imag()) > 0)
PD = HyperbolicPlane().PD()
p = PD.random_point()
PD.point_in_model(p.coordinates())
short_name()[source]

Return the short name of this model.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: UHP.short_name()
'UHP'
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.short_name()
'UHP'
UHP = HyperbolicPlane().UHP()
UHP.short_name()
class sage.geometry.hyperbolic_space.hyperbolic_model.HyperbolicModelHM(space)[source]

Bases: HyperbolicModel

Hyperboloid Model.

boundary_point_in_model(p)[source]

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
>>> from sage.all import *
>>> HM = HyperbolicPlane().HM()
>>> HM.boundary_point_in_model((Integer(0),Integer(0),Integer(1)))
False
>>> HM.boundary_point_in_model((Integer(1),Integer(0),sqrt(Integer(2))))
False
>>> HM.boundary_point_in_model((Integer(1),Integer(2),Integer(1)))
False
HM = HyperbolicPlane().HM()
HM.boundary_point_in_model((0,0,1))
HM.boundary_point_in_model((1,0,sqrt(2)))
HM.boundary_point_in_model((1,2,1))
get_background_graphic(**bdry_options)[source]

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()                   # needs sage.plot
>>> from sage.all import *
>>> H = HyperbolicPlane().HM().get_background_graphic()                   # needs sage.plot
H = HyperbolicPlane().HM().get_background_graphic()                   # needs sage.plot
isometry_in_model(A)[source]

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)                            # needs scipy
True
>>> from sage.all import *
>>> A = diagonal_matrix([Integer(1),Integer(1),-Integer(1)])
>>> HyperbolicPlane().HM().isometry_in_model(A)                            # needs scipy
True
A = diagonal_matrix([1,1,-1])
HyperbolicPlane().HM().isometry_in_model(A)                            # needs scipy
point_in_model(p)[source]

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
>>> from sage.all import *
>>> HM = HyperbolicPlane().HM()
>>> HM.point_in_model((Integer(0),Integer(0),Integer(1)))
True
>>> HM.point_in_model((Integer(1),Integer(0),sqrt(Integer(2))))
True
>>> HM.point_in_model((Integer(1),Integer(2),Integer(1)))
False
HM = HyperbolicPlane().HM()
HM.point_in_model((0,0,1))
HM.point_in_model((1,0,sqrt(2)))
HM.point_in_model((1,2,1))
class sage.geometry.hyperbolic_space.hyperbolic_model.HyperbolicModelKM(space)[source]

Bases: HyperbolicModel

Klein Model.

boundary_point_in_model(p)[source]

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
>>> from sage.all import *
>>> KM = HyperbolicPlane().KM()
>>> KM.boundary_point_in_model((Integer(1), Integer(0)))
True
>>> KM.boundary_point_in_model((Integer(1)/Integer(2), Integer(1)/Integer(2)))
False
>>> KM.boundary_point_in_model((Integer(1), RealNumber('.2')))
False
KM = HyperbolicPlane().KM()
KM.boundary_point_in_model((1, 0))
KM.boundary_point_in_model((1/2, 1/2))
KM.boundary_point_in_model((1, .2))
get_background_graphic(**bdry_options)[source]

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()                # needs sage.plot
>>> from sage.all import *
>>> circ = HyperbolicPlane().KM().get_background_graphic()                # needs sage.plot
circ = HyperbolicPlane().KM().get_background_graphic()                # needs sage.plot
isometry_in_model(A)[source]

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)                           # needs scipy
True
>>> from sage.all import *
>>> A = matrix(Integer(3), [[Integer(1), Integer(0), Integer(0)], [Integer(0), Integer(17)/Integer(8), Integer(15)/Integer(8)], [Integer(0), Integer(15)/Integer(8), Integer(17)/Integer(8)]])
>>> HyperbolicPlane().KM().isometry_in_model(A)                           # needs scipy
True
A = matrix(3, [[1, 0, 0], [0, 17/8, 15/8], [0, 15/8, 17/8]])
HyperbolicPlane().KM().isometry_in_model(A)                           # needs scipy
point_in_model(p)[source]

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
>>> from sage.all import *
>>> KM = HyperbolicPlane().KM()
>>> KM.point_in_model((Integer(1), Integer(0)))
False
>>> KM.point_in_model((Integer(1)/Integer(2), Integer(1)/Integer(2)))
True
>>> KM.point_in_model((Integer(1), RealNumber('.2')))
False
KM = HyperbolicPlane().KM()
KM.point_in_model((1, 0))
KM.point_in_model((1/2, 1/2))
KM.point_in_model((1, .2))
class sage.geometry.hyperbolic_space.hyperbolic_model.HyperbolicModelPD(space)[source]

Bases: HyperbolicModel

Poincaré Disk Model.

boundary_point_in_model(p)[source]

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
>>> from sage.all import *
>>> PD = HyperbolicPlane().PD()
>>> PD.boundary_point_in_model(RealNumber('1.00'))
True
>>> PD.boundary_point_in_model(Integer(1)/Integer(2) + I/Integer(2))
False
>>> PD.boundary_point_in_model(Integer(1) + RealNumber('.2')*I)
False
PD = HyperbolicPlane().PD()
PD.boundary_point_in_model(1.00)
PD.boundary_point_in_model(1/2 + I/2)
PD.boundary_point_in_model(1 + .2*I)
get_background_graphic(**bdry_options)[source]

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()                # needs sage.plot
>>> from sage.all import *
>>> circ = HyperbolicPlane().PD().get_background_graphic()                # needs sage.plot
circ = HyperbolicPlane().PD().get_background_graphic()                # needs sage.plot
isometry_in_model(A)[source]

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
>>> from sage.all import *
>>> z = [CC.random_element() for k in range(Integer(2))]; z.sort(key=abs)
>>> A = matrix(Integer(2),[z[Integer(1)], z[Integer(0)],z[Integer(0)].conjugate(),z[Integer(1)].conjugate()])
>>> HyperbolicPlane().PD().isometry_in_model(A)
True
z = [CC.random_element() for k in range(2)]; z.sort(key=abs)
A = matrix(2,[z[1], z[0],z[0].conjugate(),z[1].conjugate()])
HyperbolicPlane().PD().isometry_in_model(A)
point_in_model(p)[source]

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
>>> from sage.all import *
>>> PD = HyperbolicPlane().PD()
>>> PD.point_in_model(RealNumber('1.00'))
False
>>> PD.point_in_model(Integer(1)/Integer(2) + I/Integer(2))
True
>>> PD.point_in_model(Integer(1) + RealNumber('.2')*I)
False
PD = HyperbolicPlane().PD()
PD.point_in_model(1.00)
PD.point_in_model(1/2 + I/2)
PD.point_in_model(1 + .2*I)
class sage.geometry.hyperbolic_space.hyperbolic_model.HyperbolicModelUHP(space)[source]

Bases: HyperbolicModel

Upper Half Plane model.

Element[source]

alias of HyperbolicPointUHP

boundary_point_in_model(p)[source]

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
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.boundary_point_in_model(Integer(1) + I)
False
>>> UHP.boundary_point_in_model(infinity)
True
>>> UHP.boundary_point_in_model(CC(infinity))
True
>>> UHP.boundary_point_in_model(RR(infinity))
True
>>> UHP.boundary_point_in_model(Integer(1))
True
>>> UHP.boundary_point_in_model(Integer(12))
True
>>> UHP.boundary_point_in_model(Integer(1) - I)
False
>>> UHP.boundary_point_in_model(-Integer(2)*I)
False
>>> UHP.boundary_point_in_model(Integer(0))
True
>>> UHP.boundary_point_in_model(I)
False
UHP = HyperbolicPlane().UHP()
UHP.boundary_point_in_model(1 + I)
UHP.boundary_point_in_model(infinity)
UHP.boundary_point_in_model(CC(infinity))
UHP.boundary_point_in_model(RR(infinity))
UHP.boundary_point_in_model(1)
UHP.boundary_point_in_model(12)
UHP.boundary_point_in_model(1 - I)
UHP.boundary_point_in_model(-2*I)
UHP.boundary_point_in_model(0)
UHP.boundary_point_in_model(I)
get_background_graphic(**bdry_options)[source]

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()                 # needs sage.plot
>>> from sage.all import *
>>> hp = HyperbolicPlane().UHP().get_background_graphic()                 # needs sage.plot
hp = HyperbolicPlane().UHP().get_background_graphic()                 # needs sage.plot
isometry_from_fixed_points(repel, attract)[source]

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]
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.isometry_from_fixed_points(Integer(2) + I, Integer(3) + I)
Traceback (most recent call last):
...
ValueError: fixed points of hyperbolic elements must be ideal

>>> UHP.isometry_from_fixed_points(Integer(2), Integer(0))
Isometry in UHP
[  -1    0]
[-1/3 -1/3]
UHP = HyperbolicPlane().UHP()
UHP.isometry_from_fixed_points(2 + I, 3 + I)
UHP.isometry_from_fixed_points(2, 0)
isometry_in_model(A)[source]

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
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> A = matrix(Integer(2),[Integer(1),Integer(2),Integer(3),Integer(4)])
>>> UHP.isometry_in_model(A)
True
>>> B = matrix(Integer(2),[I,Integer(2),Integer(4),Integer(1)])
>>> UHP.isometry_in_model(B)
False
UHP = HyperbolicPlane().UHP()
A = matrix(2,[1,2,3,4])
UHP.isometry_in_model(A)
B = matrix(2,[I,2,4,1])
UHP.isometry_in_model(B)

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
>>> from sage.all import *
>>> C = matrix(Integer(2),[Integer(10),Integer(0),Integer(0),Integer(10)])
>>> UHP.isometry_in_model(C)
True
C = matrix(2,[10,0,0,10])
UHP.isometry_in_model(C)
point_in_model(p)[source]

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
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.point_in_model(Integer(1) + I)
True
>>> UHP.point_in_model(infinity)
False
>>> UHP.point_in_model(CC(infinity))
False
>>> UHP.point_in_model(RR(infinity))
False
>>> UHP.point_in_model(Integer(1))
False
>>> UHP.point_in_model(Integer(12))
False
>>> UHP.point_in_model(Integer(1) - I)
False
>>> UHP.point_in_model(-Integer(2)*I)
False
>>> UHP.point_in_model(I)
True
>>> UHP.point_in_model(Integer(0)) # Not interior point
False
UHP = HyperbolicPlane().UHP()
UHP.point_in_model(1 + I)
UHP.point_in_model(infinity)
UHP.point_in_model(CC(infinity))
UHP.point_in_model(RR(infinity))
UHP.point_in_model(1)
UHP.point_in_model(12)
UHP.point_in_model(1 - I)
UHP.point_in_model(-2*I)
UHP.point_in_model(I)
UHP.point_in_model(0) # Not interior point
random_isometry(preserve_orientation=True, **kwargs)[source]

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()                         # needs scipy
sage: B = HyperbolicPlane().UHP().random_isometry(preserve_orientation=False)           # needs scipy
sage: B.preserves_orientation()                                             # needs scipy
False
>>> from sage.all import *
>>> A = HyperbolicPlane().UHP().random_isometry()                         # needs scipy
>>> B = HyperbolicPlane().UHP().random_isometry(preserve_orientation=False)           # needs scipy
>>> B.preserves_orientation()                                             # needs scipy
False
A = HyperbolicPlane().UHP().random_isometry()                         # needs scipy
B = HyperbolicPlane().UHP().random_isometry(preserve_orientation=False)           # needs scipy
B.preserves_orientation()                                             # needs scipy
random_point(**kwargs)[source]

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
>>> from sage.all import *
>>> p = HyperbolicPlane().UHP().random_point().coordinates()
>>> bool((p.imag()) > Integer(0))
True
p = HyperbolicPlane().UHP().random_point().coordinates()
bool((p.imag()) > 0)