# Hyperbolic space

The hyperbolic space can be represented in three different models.

- Hyperboloid which is the default model, i.e. is used when using arbitrary array types for points and tangent vectors
- Poincaré ball with separate types for points and tangent vectors and a visualization for the two-dimensional case
- Poincaré half space with separate types for points and tangent vectors and a visualization for the two-dimensional cae.

In the following the common functions are collected.

A function in this general section uses vectors interpreted as if in the hyperboloid model, and other representations usually just convert to this representation to use these general functions.

`Manifolds.Hyperbolic`

— Type`Hyperbolic{N} <: AbstractDecoratorManifold{ℝ}`

The hyperbolic space $\mathcal H^n$ represented by $n+1$-Tuples, i.e. embedded in the `Lorentz`

ian manifold equipped with the `MinkowskiMetric`

$⟨\cdot,\cdot⟩_{\mathrm{M}}$. The space is defined as

\[\mathcal H^n = \Bigl\{p ∈ ℝ^{n+1}\ \Big|\ ⟨p,p⟩_{\mathrm{M}}= -p_{n+1}^2 + \displaystyle\sum_{k=1}^n p_k^2 = -1, p_{n+1} > 0\Bigr\},.\]

The tangent space $T_p \mathcal H^n$ is given by

\[T_p \mathcal H^n := \bigl\{ X ∈ ℝ^{n+1} : ⟨p,X⟩_{\mathrm{M}} = 0 \bigr\}.\]

Note that while the `MinkowskiMetric`

renders the `Lorentz`

manifold (only) pseudo-Riemannian, on the tangent bundle of the Hyperbolic space it induces a Riemannian metric. The corresponding sectional curvature is $-1$.

If `p`

and `X`

are `Vector`

s of length `n+1`

they are assumed to be a `HyperboloidPoint`

and a `HyperboloidTVector`

, respectively

Other models are the Poincaré ball model, see `PoincareBallPoint`

and `PoincareBallTVector`

, respectiely and the Poincaré half space model, see `PoincareHalfSpacePoint`

and `PoincareHalfSpaceTVector`

, respectively.

**Constructor**

`Hyperbolic(n)`

Generate the Hyperbolic manifold of dimension `n`

.

`Manifolds.HyperboloidPoint`

— Type`HyperboloidPoint <: AbstractManifoldPoint`

In the Hyperboloid model of the `Hyperbolic`

$\mathcal H^n$ points are represented as vectors in $ℝ^{n+1}$ with `MinkowskiMetric`

equal to $-1$.

This representation is the default, i.e. `AbstractVector`

s are assumed to have this repesentation.

`Manifolds.HyperboloidTVector`

— Type`HyperboloidTVector <: TVector`

In the Hyperboloid model of the `Hyperbolic`

$\mathcal H^n$ tangent vctors are represented as vectors in $ℝ^{n+1}$ with `MinkowskiMetric`

$⟨p,X⟩_{\mathrm{M}}=0$ to their base point $p$.

This representation is the default, i.e. vectors are assumed to have this repesentation.

`Manifolds.PoincareBallPoint`

— Type`PoincareBallPoint <: AbstractManifoldPoint`

A point on the `Hyperbolic`

manifold $\mathcal H^n$ can be represented as a vector of norm less than one in $\mathbb R^n$.

`Manifolds.PoincareBallTVector`

— Type`PoincareBallTVector <: TVector`

In the Poincaré ball model of the `Hyperbolic`

$\mathcal H^n$ tangent vectors are represented as vectors in $ℝ^{n}$.

`Manifolds.PoincareHalfSpacePoint`

— Type`PoincareHalfSpacePoint <: AbstractManifoldPoint`

A point on the `Hyperbolic`

manifold $\mathcal H^n$ can be represented as a vector in the half plane, i.e. $x ∈ ℝ^n$ with $x_d > 0$.

`Manifolds.PoincareHalfSpaceTVector`

— Type`PoincareHalfPlaneTVector <: TVector`

In the Poincaré half plane model of the `Hyperbolic`

$\mathcal H^n$ tangent vectors are represented as vectors in $ℝ^{n}$.

`Base.exp`

— Method`exp(M::Hyperbolic, p, X)`

Compute the exponential map on the `Hyperbolic`

space $\mathcal H^n$ emanating from `p`

towards `X`

. The formula reads

\[\exp_p X = \cosh(\sqrt{⟨X,X⟩_{\mathrm{M}}})p + \sinh(\sqrt{⟨X,X⟩_{\mathrm{M}}})\frac{X}{\sqrt{⟨X,X⟩_{\mathrm{M}}}},\]

where $⟨\cdot,\cdot⟩_{\mathrm{M}}$ denotes the `MinkowskiMetric`

on the embedding, the `Lorentz`

ian manifold.

`Base.log`

— Method`log(M::Hyperbolic, p, q)`

Compute the logarithmic map on the `Hyperbolic`

space $\mathcal H^n$, the tangent vector representing the `geodesic`

starting from `p`

reaches `q`

after time 1. The formula reads for $p ≠ q$

\[\log_p q = d_{\mathcal H^n}(p,q) \frac{q-⟨p,q⟩_{\mathrm{M}} p}{\lVert q-⟨p,q⟩_{\mathrm{M}} p \rVert_2},\]

where $⟨\cdot,\cdot⟩_{\mathrm{M}}$ denotes the `MinkowskiMetric`

on the embedding, the `Lorentz`

ian manifold. For $p=q$ the logarihmic map is equal to the zero vector.

`ManifoldsBase.check_point`

— Method`check_point(M::Hyperbolic, p; kwargs...)`

Check whether `p`

is a valid point on the `Hyperbolic`

`M`

.

For the `HyperboloidPoint`

or plain vectors this means that, `p`

is a vector of length $n+1$ with inner product in the embedding of -1, see `MinkowskiMetric`

. The tolerance for the last test can be set using the `kwargs...`

.

For the `PoincareBallPoint`

a valid point is a vector $p ∈ ℝ^n$ with a norm stricly less than 1.

For the `PoincareHalfSpacePoint`

a valid point is a vector from $p ∈ ℝ^n$ with a positive last entry, i.e. $p_n>0$

`ManifoldsBase.check_vector`

— Method`check_vector(M::Hyperbolic{n}, p, X; kwargs... )`

Check whether `X`

is a tangent vector to `p`

on the `Hyperbolic`

`M`

, i.e. after `check_point`

`(M,p)`

, `X`

has to be of the same dimension as `p`

. The tolerance for the last test can be set using the `kwargs...`

.

For a the hyperboloid model or vectors, `X`

has to be orthogonal to `p`

with respect to the inner product from the embedding, see `MinkowskiMetric`

.

For a the Poincaré ball as well as the Poincaré half plane model, `X`

has to be a vector from $ℝ^{n}$.

`ManifoldsBase.injectivity_radius`

— Method```
injectivity_radius(M::Hyperbolic)
injectivity_radius(M::Hyperbolic, p)
```

Return the injectivity radius on the `Hyperbolic`

, which is $∞$.

`ManifoldsBase.is_flat`

— Method`is_flat(::Hyperbolic)`

Return false. `Hyperbolic`

is not a flat manifold.

`ManifoldsBase.manifold_dimension`

— Method`manifold_dimension(M::Hyperbolic)`

Return the dimension of the hyperbolic space manifold $\mathcal H^n$, i.e. $\dim(\mathcal H^n) = n$.

`ManifoldsBase.parallel_transport_to`

— Method`parallel_transport_to(M::Hyperbolic, p, X, q)`

Compute the paralllel transport of the `X`

from the tangent space at `p`

on the `Hyperbolic`

space $\mathcal H^n$ to the tangent at `q`

along the `geodesic`

connecting `p`

and `q`

. The formula reads

\[\mathcal P_{q←p}X = X - \frac{⟨\log_p q,X⟩_p}{d^2_{\mathcal H^n}(p,q)} \bigl(\log_p q + \log_qp \bigr),\]

where $⟨\cdot,\cdot⟩_p$ denotes the inner product in the tangent space at `p`

.

`ManifoldsBase.project`

— Method`project(M::Hyperbolic, p, X)`

Perform an orthogonal projection with respect to the Minkowski inner product of `X`

onto the tangent space at `p`

of the `Hyperbolic`

space `M`

.

The formula reads

\[Y = X + ⟨p,X⟩_{\mathrm{M}} p,\]

where $⟨\cdot, \cdot⟩_{\mathrm{M}}$ denotes the `MinkowskiMetric`

on the embedding, the `Lorentz`

ian manifold.

Projection is only available for the (default) `HyperboloidTVector`

representation, the others don't have such an embedding

`Statistics.mean`

— Method```
mean(
M::Hyperbolic,
x::AbstractVector,
[w::AbstractWeights,]
method = CyclicProximalPointEstimation();
kwargs...,
)
```

Compute the Riemannian `mean`

of `x`

on the `Hyperbolic`

space using `CyclicProximalPointEstimation`

.

## hyperboloid model

`Base.convert`

— Method```
convert(::Type{HyperboloidPoint}, p::PoincareBallPoint)
convert(::Type{AbstractVector}, p::PoincareBallPoint)
```

convert a point `PoincareBallPoint`

`x`

(from $ℝ^n$) from the Poincaré ball model of the `Hyperbolic`

manifold $\mathcal H^n$ to a `HyperboloidPoint`

$π(p) ∈ ℝ^{n+1}$. The isometry is defined by

\[π(p) = \frac{1}{1-\lVert p \rVert^2} \begin{pmatrix}2p_1\\⋮\\2p_n\\1+\lVert p \rVert^2\end{pmatrix}\]

Note that this is also used, when the type to convert to is a vector.

`Base.convert`

— Method```
convert(::Type{HyperboloidPoint}, p::PoincareHalfSpacePoint)
convert(::Type{AbstractVector}, p::PoincareHalfSpacePoint)
```

convert a point `PoincareHalfSpacePoint`

`p`

(from $ℝ^n$) from the Poincaré half plane model of the `Hyperbolic`

manifold $\mathcal H^n$ to a `HyperboloidPoint`

$π(p) ∈ ℝ^{n+1}$.

This is done in two steps, namely transforming it to a Poincare ball point and from there further on to a Hyperboloid point.

`Base.convert`

— Method```
convert(::Type{HyperboloidTVector}, p::PoincareBallPoint, X::PoincareBallTVector)
convert(::Type{AbstractVector}, p::PoincareBallPoint, X::PoincareBallTVector)
```

Convert the `PoincareBallTVector`

`X`

from the tangent space at `p`

to a `HyperboloidTVector`

by computing the push forward of the isometric map, cf. `convert(::Type{HyperboloidPoint}, p::PoincareBallPoint)`

.

The push forward $π_*(p)$ maps from $ℝ^n$ to a subspace of $ℝ^{n+1}$, the formula reads

\[π_*(p)[X] = \begin{pmatrix} \frac{2X_1}{1-\lVert p \rVert^2} + \frac{4}{(1-\lVert p \rVert^2)^2}⟨X,p⟩p_1\\ ⋮\\ \frac{2X_n}{1-\lVert p \rVert^2} + \frac{4}{(1-\lVert p \rVert^2)^2}⟨X,p⟩p_n\\ \frac{4}{(1-\lVert p \rVert^2)^2}⟨X,p⟩ \end{pmatrix}.\]

`Base.convert`

— Method```
convert(::Type{HyperboloidTVector}, p::PoincareHalfSpacePoint, X::PoincareHalfSpaceTVector)
convert(::Type{AbstractVector}, p::PoincareHalfSpacePoint, X::PoincareHalfSpaceTVector)
```

convert a point `PoincareHalfSpaceTVector`

`X`

(from $ℝ^n$) at `p`

from the Poincaré half plane model of the `Hyperbolic`

manifold $\mathcal H^n$ to a `HyperboloidTVector`

$π(p) ∈ ℝ^{n+1}$.

This is done in two steps, namely transforming it to a Poincare ball point and from there further on to a Hyperboloid point.

`Base.convert`

— Method```
convert(
::Type{Tuple{HyperboloidPoint,HyperboloidTVector}}.
(p,X)::Tuple{PoincareBallPoint,PoincareBallTVector}
)
convert(
::Type{Tuple{P,T}},
(p, X)::Tuple{PoincareBallPoint,PoincareBallTVector},
) where {P<:AbstractVector, T <: AbstractVector}
```

Convert a `PoincareBallPoint`

`p`

and a `PoincareBallTVector`

`X`

to a `HyperboloidPoint`

and a `HyperboloidTVector`

simultaneously, see `convert(::Type{HyperboloidPoint}, ::PoincareBallPoint)`

and `convert(::Type{HyperboloidTVector}, ::PoincareBallPoint, ::PoincareBallTVector)`

for the formulae.

`Base.convert`

— Method```
convert(
::Type{Tuple{HyperboloidPoint,HyperboloidTVector},
(p,X)::Tuple{PoincareHalfSpacePoint, PoincareHalfSpaceTVector}
)
convert(
::Type{Tuple{T,T},
(p,X)::Tuple{PoincareHalfSpacePoint, PoincareHalfSpaceTVector}
) where {T<:AbstractVector}
```

convert a point `PoincareHalfSpaceTVector`

`X`

(from $ℝ^n$) at `p`

from the Poincaré half plane model of the `Hyperbolic`

manifold $\mathcal H^n$ to a tuple of a `HyperboloidPoint`

and a `HyperboloidTVector`

$π(p) ∈ ℝ^{n+1}$ simultaneously.

This is done in two steps, namely transforming it to the Poincare ball model and from there further on to a Hyperboloid.

`ManifoldsBase.change_representer`

— Method`change_representer(M::Hyperbolic{n}, ::EuclideanMetric, p, X)`

Change the Eucliden representer `X`

of a cotangent vector at point `p`

. We only have to correct for the metric, which means that the sign of the last entry changes, since for the result $Y$ we are looking for a tangent vector such that

\[ g_p(Y,Z) = -y_{n+1}z_{n+1} + \sum_{i=1}^n y_iz_i = \sum_{i=1}^{n+1} z_ix_i\]

holds, which directly yields $y_i=x_i$ for $i=1,\ldots,n$ and $y_{n+1}=-x_{n+1}$.

`ManifoldsBase.distance`

— Method```
distance(M::Hyperbolic, p, q)
distance(M::Hyperbolic, p::HyperboloidPoint, q::HyperboloidPoint)
```

Compute the distance on the `Hyperbolic`

`M`

, which reads

\[d_{\mathcal H^n}(p,q) = \operatorname{acosh}( - ⟨p, q⟩_{\mathrm{M}}),\]

where $⟨\cdot,\cdot⟩_{\mathrm{M}}$ denotes the `MinkowskiMetric`

on the embedding, the `Lorentz`

ian manifold.

`ManifoldsBase.get_coordinates`

— Method`get_coordinates(M::Hyperbolic, p, X, ::DefaultOrthonormalBasis)`

Compute the coordinates of the vector `X`

with respect to the orthogonalized version of the unit vectors from $ℝ^n$, where $n$ is the manifold dimension of the `Hyperbolic`

`M`

, utting them intop the tangent space at `p`

and orthonormalizing them.

`ManifoldsBase.get_vector`

— Method`get_vector(M::Hyperbolic, p, c, ::DefaultOrthonormalBasis)`

Compute the vector from the coordinates with respect to the orthogonalized version of the unit vectors from $ℝ^n$, where $n$ is the manifold dimension of the `Hyperbolic`

`M`

, utting them intop the tangent space at `p`

and orthonormalizing them.

`ManifoldsBase.inner`

— Method```
inner(M::Hyperbolic{n}, p, X, Y)
inner(M::Hyperbolic{n}, p::HyperboloidPoint, X::HyperboloidTVector, Y::HyperboloidTVector)
```

Cmpute the inner product in the Hyperboloid model, i.e. the `minkowski_metric`

in the embedding. The formula reads

\[g_p(X,Y) = ⟨X,Y⟩_{\mathrm{M}} = -X_{n}Y_{n} + \displaystyle\sum_{k=1}^{n-1} X_kY_k.\]

This employs the metric of the embedding, see `Lorentz`

space.

### Visualization of the Hyperboloid

For the case of `Hyperbolic`

`(2)`

there is plotting available based on a PlottingRecipe. You can easily plot points, connecting geodesics as well as tangent vectors.

The recipes are only loaded if Plots.jl or RecipesBase.jl is loaded.

If we consider a set of points, we can first plot these and their connecting geodesics using the `geodesic_interpolation`

for the points. This variable specifies with how many points a geodesic between two successive points is sampled (per default it's `-1`

, which deactivates geodesics) and the line style is set to be a path.

In general you can plot the surface of the hyperboloid either as wireframe (`wireframe=true`

) additionally specifying `wires`

(or `wires_x`

and `wires_y`

) to change the density of wires and a `wireframe_color`

. The same holds for the plot as a `surface`

(which is `false`

by default) and its `surface_resolution`

(or `surface_resolution_x`

or `surface_resolution_y`

) and a `surface_color`

.

```
using Manifolds, Plots
M = Hyperbolic(2)
pts = [ [0.85*cos(φ), 0.85*sin(φ), sqrt(0.85^2+1)] for φ ∈ range(0,2π,length=11) ]
scene = plot(M, pts; geodesic_interpolation=100)
```

To just plot the points atop, we can just omit the `geodesic_interpolation`

parameter to obtain a scatter plot. Note that we avoid redrawing the wireframe in the following `plot!`

calls.

`plot!(scene, M, pts; wireframe=false)`

We can further generate tangent vectors in these spaces and use a plot for there. Keep in mind that a tangent vector in plotting always requires its base point.

```
pts2 = [ [0.45 .*cos(φ + 6π/11), 0.45 .*sin(φ + 6π/11), sqrt(0.45^2+1) ] for φ ∈ range(0,2π,length=11)]
vecs = log.(Ref(M),pts,pts2)
plot!(scene, M, pts, vecs; wireframe=false)
```