Hyperbolic Isometries

This module implements the abstract base class for isometries of hyperbolic space of arbitrary dimension. It also contains the implementations for specific models of hyperbolic geometry.

The isometry groups of all implemented models are either matrix Lie groups or are doubly covered by matrix Lie groups. As such, the isometry constructor takes a matrix as input. However, since the isometries themselves may not be matrices, quantities like the trace and determinant are not directly accessible from this class.

AUTHORS:

  • Greg Laun (2013): initial version

EXAMPLES:

We can construct isometries in the upper half plane model, abbreviated UHP for convenience:

sage: UHP = HyperbolicPlane().UHP()
sage: UHP.get_isometry(matrix(2,[1,2,3,4]))
Isometry in UHP
[1 2]
[3 4]
sage: A = UHP.get_isometry(matrix(2,[0,1,1,0]))
sage: A.inverse()
Isometry in UHP
[0 1]
[1 0]
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.get_isometry(matrix(Integer(2),[Integer(1),Integer(2),Integer(3),Integer(4)]))
Isometry in UHP
[1 2]
[3 4]
>>> A = UHP.get_isometry(matrix(Integer(2),[Integer(0),Integer(1),Integer(1),Integer(0)]))
>>> A.inverse()
Isometry in UHP
[0 1]
[1 0]
class sage.geometry.hyperbolic_space.hyperbolic_isometry.HyperbolicIsometry(model, A, check=True)[source]

Bases: Morphism

Abstract base class for hyperbolic isometries. This class should never be instantiated.

INPUT:

  • A – a matrix representing a hyperbolic isometry in the appropriate model

EXAMPLES:

sage: HyperbolicPlane().HM().get_isometry(identity_matrix(3))
Isometry in HM
[1 0 0]
[0 1 0]
[0 0 1]
>>> from sage.all import *
>>> HyperbolicPlane().HM().get_isometry(identity_matrix(Integer(3)))
Isometry in HM
[1 0 0]
[0 1 0]
[0 0 1]
attracting_fixed_point()[source]

For a hyperbolic isometry, return the attracting fixed point; otherwise raise a ValueError.

OUTPUT: a hyperbolic point

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: A = UHP.get_isometry(Matrix(2,[4,0,0,1/4]))
sage: A.attracting_fixed_point()
Boundary point in UHP +Infinity
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> A = UHP.get_isometry(Matrix(Integer(2),[Integer(4),Integer(0),Integer(0),Integer(1)/Integer(4)]))
>>> A.attracting_fixed_point()
Boundary point in UHP +Infinity
axis()[source]

For a hyperbolic isometry, return the axis of the transformation; otherwise raise a ValueError.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: H = UHP.get_isometry(matrix(2,[2,0,0,1/2]))
sage: H.axis()
Geodesic in UHP from 0 to +Infinity
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> H = UHP.get_isometry(matrix(Integer(2),[Integer(2),Integer(0),Integer(0),Integer(1)/Integer(2)]))
>>> H.axis()
Geodesic in UHP from 0 to +Infinity

It is an error to call this function on an isometry that is not hyperbolic:

sage: P = UHP.get_isometry(matrix(2,[1,4,0,1]))
sage: P.axis()
Traceback (most recent call last):
...
ValueError: the isometry is not hyperbolic: axis is undefined
>>> from sage.all import *
>>> P = UHP.get_isometry(matrix(Integer(2),[Integer(1),Integer(4),Integer(0),Integer(1)]))
>>> P.axis()
Traceback (most recent call last):
...
ValueError: the isometry is not hyperbolic: axis is undefined
classification()[source]

Classify the hyperbolic isometry as elliptic, parabolic, hyperbolic or a reflection.

A hyperbolic isometry fixes two points on the boundary of hyperbolic space, a parabolic isometry fixes one point on the boundary of hyperbolic space, and an elliptic isometry fixes no points.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: H = UHP.get_isometry(matrix(2,[2,0,0,1/2]))
sage: H.classification()
'hyperbolic'

sage: P = UHP.get_isometry(matrix(2,[1,1,0,1]))
sage: P.classification()
'parabolic'

sage: E = UHP.get_isometry(matrix(2,[-1,0,0,1]))
sage: E.classification()
'reflection'
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> H = UHP.get_isometry(matrix(Integer(2),[Integer(2),Integer(0),Integer(0),Integer(1)/Integer(2)]))
>>> H.classification()
'hyperbolic'

>>> P = UHP.get_isometry(matrix(Integer(2),[Integer(1),Integer(1),Integer(0),Integer(1)]))
>>> P.classification()
'parabolic'

>>> E = UHP.get_isometry(matrix(Integer(2),[-Integer(1),Integer(0),Integer(0),Integer(1)]))
>>> E.classification()
'reflection'
fixed_geodesic()[source]

If self is a reflection in a geodesic, return that geodesic.

EXAMPLES:

sage: A = HyperbolicPlane().PD().get_isometry(matrix([[0, 1], [1, 0]]))
sage: A.fixed_geodesic()
Geodesic in PD from -1 to 1
>>> from sage.all import *
>>> A = HyperbolicPlane().PD().get_isometry(matrix([[Integer(0), Integer(1)], [Integer(1), Integer(0)]]))
>>> A.fixed_geodesic()
Geodesic in PD from -1 to 1
fixed_point_set()[source]

Return a list containing the fixed point set of orientation-preserving isometries.

OUTPUT: list of hyperbolic points or a hyperbolic geodesic

EXAMPLES:

sage: KM = HyperbolicPlane().KM()
sage: H = KM.get_isometry(matrix([[5/3,0,4/3], [0,1,0], [4/3,0,5/3]]))
sage: g = H.fixed_point_set(); g
Geodesic in KM from (1, 0) to (-1, 0)
sage: H(g.start()) == g.start()
True
sage: H(g.end()) == g.end()
True
sage: A = KM.get_isometry(matrix([[1,0,0], [0,-1,0], [0,0,1]]))
sage: A.preserves_orientation()
False
sage: A.fixed_point_set()
Geodesic in KM from (1, 0) to (-1, 0)
>>> from sage.all import *
>>> KM = HyperbolicPlane().KM()
>>> H = KM.get_isometry(matrix([[Integer(5)/Integer(3),Integer(0),Integer(4)/Integer(3)], [Integer(0),Integer(1),Integer(0)], [Integer(4)/Integer(3),Integer(0),Integer(5)/Integer(3)]]))
>>> g = H.fixed_point_set(); g
Geodesic in KM from (1, 0) to (-1, 0)
>>> H(g.start()) == g.start()
True
>>> H(g.end()) == g.end()
True
>>> A = KM.get_isometry(matrix([[Integer(1),Integer(0),Integer(0)], [Integer(0),-Integer(1),Integer(0)], [Integer(0),Integer(0),Integer(1)]]))
>>> A.preserves_orientation()
False
>>> A.fixed_point_set()
Geodesic in KM from (1, 0) to (-1, 0)

sage: B = KM.get_isometry(identity_matrix(3))
sage: B.fixed_point_set()
Traceback (most recent call last):
...
ValueError: the identity transformation fixes the entire hyperbolic plane
>>> from sage.all import *
>>> B = KM.get_isometry(identity_matrix(Integer(3)))
>>> B.fixed_point_set()
Traceback (most recent call last):
...
ValueError: the identity transformation fixes the entire hyperbolic plane
is_identity()[source]

Return True if self is the identity isometry.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: UHP.get_isometry(matrix(2,[4,1,3,2])).is_identity()
False
sage: UHP.get_isometry(identity_matrix(2)).is_identity()
True
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.get_isometry(matrix(Integer(2),[Integer(4),Integer(1),Integer(3),Integer(2)])).is_identity()
False
>>> UHP.get_isometry(identity_matrix(Integer(2))).is_identity()
True
matrix()[source]

Return the matrix of the isometry.

Note

We do not allow the matrix constructor to work as these may be elements of a projective group (ex. \(PSL(n, \RR)\)), so these isometries aren’t true matrices.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: UHP.get_isometry(-identity_matrix(2)).matrix()
[-1  0]
[ 0 -1]
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.get_isometry(-identity_matrix(Integer(2))).matrix()
[-1  0]
[ 0 -1]
model()[source]

Return the model to which self belongs.

EXAMPLES:

sage: HyperbolicPlane().UHP().get_isometry(identity_matrix(2)).model()
Hyperbolic plane in the Upper Half Plane Model

sage: HyperbolicPlane().PD().get_isometry(identity_matrix(2)).model()
Hyperbolic plane in the Poincare Disk Model

sage: HyperbolicPlane().KM().get_isometry(identity_matrix(3)).model()
Hyperbolic plane in the Klein Disk Model

sage: HyperbolicPlane().HM().get_isometry(identity_matrix(3)).model()
Hyperbolic plane in the Hyperboloid Model
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_isometry(identity_matrix(Integer(2))).model()
Hyperbolic plane in the Upper Half Plane Model

>>> HyperbolicPlane().PD().get_isometry(identity_matrix(Integer(2))).model()
Hyperbolic plane in the Poincare Disk Model

>>> HyperbolicPlane().KM().get_isometry(identity_matrix(Integer(3))).model()
Hyperbolic plane in the Klein Disk Model

>>> HyperbolicPlane().HM().get_isometry(identity_matrix(Integer(3))).model()
Hyperbolic plane in the Hyperboloid Model
preserves_orientation()[source]

Return True if self is orientation-preserving and False otherwise.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: A = UHP.get_isometry(identity_matrix(2))
sage: A.preserves_orientation()
True
sage: B = UHP.get_isometry(matrix(2,[0,1,1,0]))
sage: B.preserves_orientation()
False
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> A = UHP.get_isometry(identity_matrix(Integer(2)))
>>> A.preserves_orientation()
True
>>> B = UHP.get_isometry(matrix(Integer(2),[Integer(0),Integer(1),Integer(1),Integer(0)]))
>>> B.preserves_orientation()
False
repelling_fixed_point()[source]

For a hyperbolic isometry, return the attracting fixed point; otherwise raise a ValueError.

OUTPUT: a hyperbolic point

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: A = UHP.get_isometry(Matrix(2,[4,0,0,1/4]))
sage: A.repelling_fixed_point()
Boundary point in UHP 0
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> A = UHP.get_isometry(Matrix(Integer(2),[Integer(4),Integer(0),Integer(0),Integer(1)/Integer(4)]))
>>> A.repelling_fixed_point()
Boundary point in UHP 0
to_model(other)[source]

Convert the current object to image in another model.

INPUT:

  • other – (a string representing) the image model

EXAMPLES:

sage: H = HyperbolicPlane()
sage: UHP = H.UHP()
sage: PD = H.PD()
sage: KM = H.KM()
sage: HM = H.HM()

sage: A = UHP.get_isometry(identity_matrix(2))
sage: A.to_model(HM)
Isometry in HM
[1 0 0]
[0 1 0]
[0 0 1]
sage: A.to_model('HM')
Isometry in HM
[1 0 0]
[0 1 0]
[0 0 1]

sage: A = PD.get_isometry(matrix([[I, 0], [0, -I]]))
sage: A.to_model(UHP)
Isometry in UHP
[ 0  1]
[-1  0]
sage: A.to_model(HM)
Isometry in HM
[-1  0  0]
[ 0 -1  0]
[ 0  0  1]
sage: A.to_model(KM)
Isometry in KM
[-1  0  0]
[ 0 -1  0]
[ 0  0  1]

sage: A = HM.get_isometry(diagonal_matrix([-1, -1, 1]))
sage: A.to_model('UHP')
Isometry in UHP
[ 0 -1]
[ 1  0]
sage: A.to_model('PD')
Isometry in PD
[-I  0]
[ 0  I]
sage: A.to_model('KM')
Isometry in KM
[-1  0  0]
[ 0 -1  0]
[ 0  0  1]
>>> from sage.all import *
>>> H = HyperbolicPlane()
>>> UHP = H.UHP()
>>> PD = H.PD()
>>> KM = H.KM()
>>> HM = H.HM()

>>> A = UHP.get_isometry(identity_matrix(Integer(2)))
>>> A.to_model(HM)
Isometry in HM
[1 0 0]
[0 1 0]
[0 0 1]
>>> A.to_model('HM')
Isometry in HM
[1 0 0]
[0 1 0]
[0 0 1]

>>> A = PD.get_isometry(matrix([[I, Integer(0)], [Integer(0), -I]]))
>>> A.to_model(UHP)
Isometry in UHP
[ 0  1]
[-1  0]
>>> A.to_model(HM)
Isometry in HM
[-1  0  0]
[ 0 -1  0]
[ 0  0  1]
>>> A.to_model(KM)
Isometry in KM
[-1  0  0]
[ 0 -1  0]
[ 0  0  1]

>>> A = HM.get_isometry(diagonal_matrix([-Integer(1), -Integer(1), Integer(1)]))
>>> A.to_model('UHP')
Isometry in UHP
[ 0 -1]
[ 1  0]
>>> A.to_model('PD')
Isometry in PD
[-I  0]
[ 0  I]
>>> A.to_model('KM')
Isometry in KM
[-1  0  0]
[ 0 -1  0]
[ 0  0  1]
translation_length()[source]

For hyperbolic elements, return the translation length; otherwise, raise a ValueError.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: H = UHP.get_isometry(matrix(2,[2,0,0,1/2]))
sage: H.translation_length()
2*arccosh(5/4)
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> H = UHP.get_isometry(matrix(Integer(2),[Integer(2),Integer(0),Integer(0),Integer(1)/Integer(2)]))
>>> H.translation_length()
2*arccosh(5/4)

sage: f_1 = UHP.get_point(-1)
sage: f_2 = UHP.get_point(1)
sage: H = UHP.isometry_from_fixed_points(f_1, f_2)
sage: p = UHP.get_point(exp(i*7*pi/8))
sage: bool((p.dist(H*p) - H.translation_length()) < 10**-9)
True
>>> from sage.all import *
>>> f_1 = UHP.get_point(-Integer(1))
>>> f_2 = UHP.get_point(Integer(1))
>>> H = UHP.isometry_from_fixed_points(f_1, f_2)
>>> p = UHP.get_point(exp(i*Integer(7)*pi/Integer(8)))
>>> bool((p.dist(H*p) - H.translation_length()) < Integer(10)**-Integer(9))
True
class sage.geometry.hyperbolic_space.hyperbolic_isometry.HyperbolicIsometryKM(model, A, check=True)[source]

Bases: HyperbolicIsometry

Create a hyperbolic isometry in the KM model.

INPUT:

  • a matrix in \(SO(2,1)\)

EXAMPLES:

sage: HyperbolicPlane().KM().get_isometry(identity_matrix(3))
Isometry in KM
[1 0 0]
[0 1 0]
[0 0 1]
>>> from sage.all import *
>>> HyperbolicPlane().KM().get_isometry(identity_matrix(Integer(3)))
Isometry in KM
[1 0 0]
[0 1 0]
[0 0 1]
class sage.geometry.hyperbolic_space.hyperbolic_isometry.HyperbolicIsometryPD(model, A, check=True)[source]

Bases: HyperbolicIsometry

Create a hyperbolic isometry in the PD model.

INPUT:

  • a matrix in \(PU(1,1)\)

EXAMPLES:

sage: HyperbolicPlane().PD().get_isometry(identity_matrix(2))
Isometry in PD
[1 0]
[0 1]
>>> from sage.all import *
>>> HyperbolicPlane().PD().get_isometry(identity_matrix(Integer(2)))
Isometry in PD
[1 0]
[0 1]
preserves_orientation()[source]

Return True if self preserves orientation and False otherwise.

EXAMPLES:

sage: PD = HyperbolicPlane().PD()
sage: PD.get_isometry(matrix([[-I, 0], [0, I]])).preserves_orientation()
True
sage: PD.get_isometry(matrix([[0, I], [I, 0]])).preserves_orientation()
False
>>> from sage.all import *
>>> PD = HyperbolicPlane().PD()
>>> PD.get_isometry(matrix([[-I, Integer(0)], [Integer(0), I]])).preserves_orientation()
True
>>> PD.get_isometry(matrix([[Integer(0), I], [I, Integer(0)]])).preserves_orientation()
False
class sage.geometry.hyperbolic_space.hyperbolic_isometry.HyperbolicIsometryUHP(model, A, check=True)[source]

Bases: HyperbolicIsometry

Create a hyperbolic isometry in the UHP model.

INPUT:

  • a matrix in \(GL(2, \RR)\)

EXAMPLES:

sage: HyperbolicPlane().UHP().get_isometry(identity_matrix(2))
Isometry in UHP
[1 0]
[0 1]
>>> from sage.all import *
>>> HyperbolicPlane().UHP().get_isometry(identity_matrix(Integer(2)))
Isometry in UHP
[1 0]
[0 1]
attracting_fixed_point()[source]

Return the attracting fixed point.

Otherwise, this raises a ValueError.

OUTPUT: a hyperbolic point

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: A = matrix(2,[4,0,0,1/4])
sage: UHP.get_isometry(A).attracting_fixed_point()
Boundary point in UHP +Infinity
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> A = matrix(Integer(2),[Integer(4),Integer(0),Integer(0),Integer(1)/Integer(4)])
>>> UHP.get_isometry(A).attracting_fixed_point()
Boundary point in UHP +Infinity
classification()[source]

Classify the hyperbolic isometry as elliptic, parabolic, or hyperbolic.

A hyperbolic isometry fixes two points on the boundary of hyperbolic space, a parabolic isometry fixes one point on the boundary of hyperbolic space, and an elliptic isometry fixes no points.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: UHP.get_isometry(identity_matrix(2)).classification()
'identity'

sage: UHP.get_isometry(4*identity_matrix(2)).classification()
'identity'

sage: UHP.get_isometry(matrix(2,[2,0,0,1/2])).classification()
'hyperbolic'

sage: UHP.get_isometry(matrix(2, [0, 3, -1/3, 6])).classification()
'hyperbolic'

sage: UHP.get_isometry(matrix(2,[1,1,0,1])).classification()
'parabolic'

sage: UHP.get_isometry(matrix(2,[-1,0,0,1])).classification()
'reflection'
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.get_isometry(identity_matrix(Integer(2))).classification()
'identity'

>>> UHP.get_isometry(Integer(4)*identity_matrix(Integer(2))).classification()
'identity'

>>> UHP.get_isometry(matrix(Integer(2),[Integer(2),Integer(0),Integer(0),Integer(1)/Integer(2)])).classification()
'hyperbolic'

>>> UHP.get_isometry(matrix(Integer(2), [Integer(0), Integer(3), -Integer(1)/Integer(3), Integer(6)])).classification()
'hyperbolic'

>>> UHP.get_isometry(matrix(Integer(2),[Integer(1),Integer(1),Integer(0),Integer(1)])).classification()
'parabolic'

>>> UHP.get_isometry(matrix(Integer(2),[-Integer(1),Integer(0),Integer(0),Integer(1)])).classification()
'reflection'
fixed_point_set()[source]

Return a list or geodesic containing the fixed point set of orientation-preserving isometries.

OUTPUT: list of hyperbolic points or a hyperbolic geodesic

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: H = UHP.get_isometry(matrix(2, [-2/3,-1/3,-1/3,-2/3]))
sage: g = H.fixed_point_set(); g
Geodesic in UHP from -1 to 1
sage: H(g.start()) == g.start()
True
sage: H(g.end()) == g.end()
True
sage: A = UHP.get_isometry(matrix(2,[0,1,1,0]))
sage: A.preserves_orientation()
False
sage: A.fixed_point_set()
Geodesic in UHP from 1 to -1
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> H = UHP.get_isometry(matrix(Integer(2), [-Integer(2)/Integer(3),-Integer(1)/Integer(3),-Integer(1)/Integer(3),-Integer(2)/Integer(3)]))
>>> g = H.fixed_point_set(); g
Geodesic in UHP from -1 to 1
>>> H(g.start()) == g.start()
True
>>> H(g.end()) == g.end()
True
>>> A = UHP.get_isometry(matrix(Integer(2),[Integer(0),Integer(1),Integer(1),Integer(0)]))
>>> A.preserves_orientation()
False
>>> A.fixed_point_set()
Geodesic in UHP from 1 to -1

sage: B = UHP.get_isometry(identity_matrix(2))
sage: B.fixed_point_set()
Traceback (most recent call last):
...
ValueError: the identity transformation fixes the entire hyperbolic plane
>>> from sage.all import *
>>> B = UHP.get_isometry(identity_matrix(Integer(2)))
>>> B.fixed_point_set()
Traceback (most recent call last):
...
ValueError: the identity transformation fixes the entire hyperbolic plane
preserves_orientation()[source]

Return True if self is orientation-preserving and False otherwise.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: A = identity_matrix(2)
sage: UHP.get_isometry(A).preserves_orientation()
True
sage: B = matrix(2,[0,1,1,0])
sage: UHP.get_isometry(B).preserves_orientation()
False
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> A = identity_matrix(Integer(2))
>>> UHP.get_isometry(A).preserves_orientation()
True
>>> B = matrix(Integer(2),[Integer(0),Integer(1),Integer(1),Integer(0)])
>>> UHP.get_isometry(B).preserves_orientation()
False
repelling_fixed_point()[source]

Return the repelling fixed point.

Otherwise, this raises a ValueError.

OUTPUT: a hyperbolic point

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: A = matrix(2,[4,0,0,1/4])
sage: UHP.get_isometry(A).repelling_fixed_point()
Boundary point in UHP 0
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> A = matrix(Integer(2),[Integer(4),Integer(0),Integer(0),Integer(1)/Integer(4)])
>>> UHP.get_isometry(A).repelling_fixed_point()
Boundary point in UHP 0
translation_length()[source]

For hyperbolic elements, return the translation length; otherwise, raise a ValueError.

EXAMPLES:

sage: UHP = HyperbolicPlane().UHP()
sage: UHP.get_isometry(matrix(2,[2,0,0,1/2])).translation_length()
2*arccosh(5/4)
>>> from sage.all import *
>>> UHP = HyperbolicPlane().UHP()
>>> UHP.get_isometry(matrix(Integer(2),[Integer(2),Integer(0),Integer(0),Integer(1)/Integer(2)])).translation_length()
2*arccosh(5/4)

sage: H = UHP.isometry_from_fixed_points(-1,1)
sage: p = UHP.get_point(exp(i*7*pi/8))
sage: Hp = H(p)
sage: bool((UHP.dist(p, Hp) - H.translation_length()) < 10**-9)
True
>>> from sage.all import *
>>> H = UHP.isometry_from_fixed_points(-Integer(1),Integer(1))
>>> p = UHP.get_point(exp(i*Integer(7)*pi/Integer(8)))
>>> Hp = H(p)
>>> bool((UHP.dist(p, Hp) - H.translation_length()) < Integer(10)**-Integer(9))
True
sage.geometry.hyperbolic_space.hyperbolic_isometry.moebius_transform(A, z)[source]

Given a matrix A in \(GL(2, \CC)\) and a point z in the complex plane return the Möbius transformation action of A on z.

INPUT:

  • A – a \(2 \times 2\) invertible matrix over the complex numbers

  • z – a complex number or infinity

OUTPUT: a complex number or infinity

EXAMPLES:

sage: from sage.geometry.hyperbolic_space.hyperbolic_model import moebius_transform
sage: moebius_transform(matrix(2,[1,2,3,4]),2 + I)
-2/109*I + 43/109
sage: y = var('y')
sage: moebius_transform(matrix(2,[1,0,0,1]),x + I*y)
x + I*y
>>> from sage.all import *
>>> from sage.geometry.hyperbolic_space.hyperbolic_model import moebius_transform
>>> moebius_transform(matrix(Integer(2),[Integer(1),Integer(2),Integer(3),Integer(4)]),Integer(2) + I)
-2/109*I + 43/109
>>> y = var('y')
>>> moebius_transform(matrix(Integer(2),[Integer(1),Integer(0),Integer(0),Integer(1)]),x + I*y)
x + I*y

The matrix must be square and \(2 \times 2\):

sage: moebius_transform(matrix([[3,1,2],[1,2,5]]),I)
Traceback (most recent call last):
...
TypeError: A must be an invertible 2x2 matrix over the complex numbers or a symbolic ring

sage: moebius_transform(identity_matrix(3),I)
Traceback (most recent call last):
...
TypeError: A must be an invertible 2x2 matrix over the complex numbers or a symbolic ring
>>> from sage.all import *
>>> moebius_transform(matrix([[Integer(3),Integer(1),Integer(2)],[Integer(1),Integer(2),Integer(5)]]),I)
Traceback (most recent call last):
...
TypeError: A must be an invertible 2x2 matrix over the complex numbers or a symbolic ring

>>> moebius_transform(identity_matrix(Integer(3)),I)
Traceback (most recent call last):
...
TypeError: A must be an invertible 2x2 matrix over the complex numbers or a symbolic ring

The matrix can be symbolic or can be a matrix over the real or complex numbers, but must be provably invertible:

sage: a,b,c,d = var('a,b,c,d')
sage: moebius_transform(matrix(2,[a,b,c,d]),I)
(I*a + b)/(I*c + d)
sage: moebius_transform(matrix(2,[1,b,c,b*c+1]),I)
(b + I)/(b*c + I*c + 1)
sage: moebius_transform(matrix(2,[0,0,0,0]),I)
Traceback (most recent call last):
...
TypeError: A must be an invertible 2x2 matrix over the complex numbers or a symbolic ring
>>> from sage.all import *
>>> a,b,c,d = var('a,b,c,d')
>>> moebius_transform(matrix(Integer(2),[a,b,c,d]),I)
(I*a + b)/(I*c + d)
>>> moebius_transform(matrix(Integer(2),[Integer(1),b,c,b*c+Integer(1)]),I)
(b + I)/(b*c + I*c + 1)
>>> moebius_transform(matrix(Integer(2),[Integer(0),Integer(0),Integer(0),Integer(0)]),I)
Traceback (most recent call last):
...
TypeError: A must be an invertible 2x2 matrix over the complex numbers or a symbolic ring