# Poincare Ball model¶

Poincare ball model is a compact representation of hyperbolic space. To have a nice introduction into this model we should start from simple concepts, putting them all together to build a more complete picture.

## Hyperbolic spaces¶

Hyperbolic space is a constant negative curvature Riemannian manifold. A very simple example of Riemannian manifold with constant, but positive curvature is sphere.

An (N+1)-dimensional hyperboloid spans the manifold that can be embedded into N-dimensional space via projections.

Originally, the distance between points on the hyperboloid is defined as

$d(x, y) = \operatorname{arccosh}(x, y)$

It is difficult to work in (N+1)-dimensional space and there is a range of useful embeddings exist in literature

### Poincare Model¶

Here we go.

First of all we note, that Poincare ball is embedded in a Sphere of radius $$r=1/\sqrt{c}$$, where c is negative curvature. We also note, as $$c$$ goes to $$0$$, we recover infinite radius ball. We should expect this limiting behaviour recovers Euclidean geometry.

To connect Euclidean space with its embedded manifold we need to get $$g_x$$. It is done via conformal factor $$\lambda^c_x$$.

geoopt.manifolds.poincare.math.lambda_x(x, *, c=1.0, keepdim=False, dim=-1)[source]

Compute the conformal factor $$\lambda^c_x$$ for a point on the ball.

$\lambda^c_x = \frac{1}{1 - c \|x\|_2^2}$
Parameters: x (tensor) – point on the Poincare ball c (float|tensor) – ball negative curvature keepdim (bool) – retain the last dim? (default: false) dim (int) – reduction dimension conformal factor tensor

$$\lambda^c_x$$ connects Euclidean inner product with Riemannian one

geoopt.manifolds.poincare.math.inner(x, u, v, *, c=1.0, keepdim=False, dim=-1)[source]

Compute inner product for two vectors on the tangent space w.r.t Riemannian metric on the Poincare ball.

$\langle u, v\rangle_x = (\lambda^c_x)^2 \langle u, v \rangle$
Parameters: x (tensor) – point on the Poincare ball u (tensor) – tangent vector to $$x$$ on Poincare ball v (tensor) – tangent vector to $$x$$ on Poincare ball c (float|tensor) – ball negative curvature keepdim (bool) – retain the last dim? (default: false) dim (int) – reduction dimension inner product tensor
geoopt.manifolds.poincare.math.norm(x, u, *, c=1.0, keepdim=False, dim=-1)[source]

Compute vector norm on the tangent space w.r.t Riemannian metric on the Poincare ball.

$\|u\|_x = \lambda^c_x \|u\|_2$
Parameters: x (tensor) – point on the Poincare ball u (tensor) – tangent vector to $$x$$ on Poincare ball c (float|tensor) – ball negative curvature keepdim (bool) – retain the last dim? (default: false) dim (int) – reduction dimension norm of vector tensor
geoopt.manifolds.poincare.math.egrad2rgrad(x, grad, *, c=1.0, dim=-1)[source]

Translate Euclidean gradient to Riemannian gradient on tangent space of $$x$$.

$\nabla_x = \nabla^E_x / (\lambda_x^c)^2$
Parameters: x (tensor) – point on the Poincare ball grad (tensor) – Euclidean gradient for $$x$$ c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations Riemannian gradient $$u\in T_x\mathbb{D}_c^n$$ tensor

## Math¶

The good thing about Poincare ball is that it forms a Gyrogroup. Minimal definition of a Gyrogroup assumes a binary operation $$*$$ defined that satisfies a set of properties.

Left identity
For every element $$a\in G$$ there exist $$e\in G$$ such that $$e * a = a$$.
Left Inverse
For every element $$a\in G$$ there exist $$b\in G$$ such that $$b * a = e$$
Gyroassociativity
For any $$a,b,c\in G$$ there exist $$gyr[a, b]c\in G$$ such that $$a * (b * c)=(a * b) * gyr[a, b]c$$
Gyroautomorphism
$$gyr[a, b]$$ is a magma automorphism in G
Left loop
$$gyr[a, b] = gyr[a * b, b]$$

As mentioned above, hyperbolic space forms a Gyrogroup equipped with

geoopt.manifolds.poincare.math.mobius_add(x, y, *, c=1.0, dim=-1)[source]

Compute Mobius addition is a special operation in a hyperbolic space.

$x \oplus_c y = \frac{ (1 + 2 c \langle x, y\rangle + c \|y\|^2_2) x + (1 - c \|x\|_2^2) y }{ 1 + 2 c \langle x, y\rangle + c^2 \|x\|^2_2 \|y\|^2_2 }$

In general this operation is not commutative:

$x \oplus_c y \ne y \oplus_c x$

But in some cases this property holds:

• zero vector case
$\mathbf{0} \oplus_c x = x \oplus_c \mathbf{0}$
• zero negative curvature case that is same as Euclidean addition
$x \oplus_0 y = y \oplus_0 x$

Another useful property is so called left-cancellation law:

$(-x) \oplus_c (x \oplus_c y) = y$
Parameters: x (tensor) – point on the Poincare ball y (tensor) – point on the Poincare ball c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations the result of mobius addition tensor
geoopt.manifolds.poincare.math.gyration(a, b, u, *, c=1.0, dim=-1)[source]

Apply gyration $$\operatorname{gyr}[u, v]w$$.

Guration is a special operation in hyperbolic geometry. Addition operation $$\oplus_c$$ is not associative (as mentioned in mobius_add()), but gyroassociative which means

$u \oplus_c (v \oplus_c w) = (u\oplus_c v) \oplus_c \operatorname{gyr}[u, v]w,$

where

$\operatorname{gyr}[u, v]w = \ominus (u \oplus_c v) \oplus (u \oplus_c (v \oplus_c w))$

We can simplify this equation using explicit formula for Mobius addition [1]. Recall

\begin{align}\begin{aligned}\begin{split}A = - c^2 \langle u, w\rangle \langle v, v\rangle + c \langle v, w\rangle + 2 c^2 \langle u, v\rangle \langle v, w\rangle\\ B = - c^2 \langle v, w\rangle \langle u, u\rangle - c \langle u, w\rangle\\ D = 1 + 2 c \langle u, v\rangle + c^2 \langle u, u\rangle \langle v, v\rangle\\\end{split}\\\operatorname{gyr}[u, v]w = w + 2 \frac{A u + B v}{D}\end{aligned}\end{align}
Parameters: a (tensor) – first point on Poincare ball b (tensor) – second point on Poincare ball u (tensor) – vector field for operation c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations the result of automorphism tensor

References

[1] A. A. Ungar (2009), A Gyrovector Space Approach to Hyperbolic Geometry

Using this math, it is possible to define another useful operations

geoopt.manifolds.poincare.math.mobius_sub(x, y, *, c=1.0, dim=-1)[source]

Compute Mobius substraction.

Mobius substraction can be represented via Mobius addition as follows:

$x \ominus_c y = x \oplus_c (-y)$
Parameters: x (tensor) – point on Poincare ball y (tensor) – point on Poincare ball c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations the result of mobius substraction tensor
geoopt.manifolds.poincare.math.mobius_scalar_mul(r, x, *, c=1.0, dim=-1)[source]

Compute left scalar multiplication on the Poincare ball.

$r \otimes_c x = (1/\sqrt{c}) \tanh(r\tanh^{-1}(\sqrt{c}\|x\|_2))\frac{x}{\|x\|_2}$

This operation has properties similar to Euclidean

• n-addition property
$r \otimes_c x = x \oplus_c \dots \oplus_c x$
• Distributive property
$(r_1 + r_2) \otimes_c x = r_1 \otimes_c x \oplus r_2 \otimes_c x$
• Scalar associativity
$(r_1 r_2) \otimes_c x = r_1 \otimes_c (r_2 \otimes_c x)$
• Scaling property
$|r| \otimes_c x / \|r \otimes_c x\|_2 = x/\|x\|_2$
Parameters: r (float|tensor) – scalar for multiplication x (tensor) – point on Poincare ball c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations the result of mobius scalar multiplication tensor
geoopt.manifolds.poincare.math.mobius_pointwise_mul(w, x, *, c=1.0, dim=-1)[source]

Compute a generalization for point-wise multiplication to hyperbolic space.

Mobius pointwise multiplication is defined as follows

$\operatorname{diag}(w) \otimes_c x = (1/\sqrt{c}) \tanh\left( \frac{\|\operatorname{diag}(w)x\|_2}{x}\tanh^{-1}(\sqrt{c}\|x\|_2) \right)\frac{\|\operatorname{diag}(w)x\|_2}{\|x\|_2}$
Parameters: w (tensor) – weights for multiplication (should be broadcastable to x) x (tensor) – point on Poincare ball c (float|tensor) – negative ball curvature dim (int) – reduction dimension for operations Mobius point-wise mul result tensor
geoopt.manifolds.poincare.math.mobius_matvec(m, x, *, c=1.0, dim=-1)[source]

Compute a generalization for matrix-vector multiplication to hyperbolic space.

Mobius matrix vector operation is defined as follows:

$M \otimes_c x = (1/\sqrt{c}) \tanh\left( \frac{\|Mx\|_2}{\|x\|_2}\tanh^{-1}(\sqrt{c}\|x\|_2) \right)\frac{Mx}{\|Mx\|_2}$
Parameters: m (tensor) – matrix for multiplication. Batched matmul is performed if m.dim() > 2, but only last dim reduction is supported x (tensor) – point on Poincare ball c (float|tensor) – negative ball curvature dim (int) – reduction dimension for operations Mobius matvec result tensor
geoopt.manifolds.poincare.math.mobius_fn_apply(fn, x, *args, c=1.0, dim=-1, **kwargs)[source]

Compute a generalization for function application in hyperbolic space.

First, hyperbolic vector is mapped to a Euclidean space via $$\operatorname{Log}^c_0$$ and nonlinear function is applied in this tangent space. The resulting vector is then mapped back with $$\operatorname{Exp}^c_0$$

$f^{\otimes_c}(x) = \operatorname{Exp}^c_0(f(\operatorname{Log}^c_0(y)))$
Parameters: x (tensor) – point on Poincare ball fn (callable) – function to apply c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations Result of function in hyperbolic space tensor
geoopt.manifolds.poincare.math.mobius_fn_apply_chain(x, *fns, c=1.0, dim=-1)[source]

Compute a generalization for sequential function application in hyperbolic space.

First, hyperbolic vector is mapped to a Euclidean space via $$\operatorname{Log}^c_0$$ and nonlinear function is applied in this tangent space. The resulting vector is then mapped back with $$\operatorname{Exp}^c_0$$

$f^{\otimes_c}(x) = \operatorname{Exp}^c_0(f(\operatorname{Log}^c_0(y)))$

The definition of mobius function application allows chaining as

$y = \operatorname{Exp}^c_0(\operatorname{Log}^c_0(y))$

Resulting in

$(f \circ g)^{\otimes_c}(x) = \operatorname{Exp}^c_0((f \circ g) (\operatorname{Log}^c_0(y)))$
Parameters: x (tensor) – point on Poincare ball fns (callable[]) – functions to apply c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations Apply chain result tensor

## Manifold¶

Now we are ready to proceed with studying distances, geodesics, exponential maps and more

geoopt.manifolds.poincare.math.dist(x, y, *, c=1.0, keepdim=False, dim=-1)[source]

Compute geodesic distance on the Poincare ball.

$d_c(x, y) = \frac{2}{\sqrt{c}}\tanh^{-1}(\sqrt{c}\|(-x)\oplus_c y\|_2)$
Parameters: x (tensor) – point on Poincare ball y (tensor) – point on Poincare ball c (float|tensor) – ball negative curvature keepdim (bool) – retain the last dim? (default: false) dim (int) – reduction dimension geodesic distance between $$x$$ and $$y$$ tensor
geoopt.manifolds.poincare.math.dist2plane(x, p, a, *, c=1.0, keepdim=False, signed=False, dim=-1)[source]

Compute geodesic distance from $$x$$ to a hyperbolic hyperplane in Poincare ball.

The distance is computed to a plane that is orthogonal to $$a$$ and contains $$p$$.

To form an intuition what is a hyperbolic hyperplane, let’s first consider Euclidean hyperplane

$H_{a, b} = \left\{ x \in \mathbb{R}^n\;:\;\langle x, a\rangle - b = 0 \right\},$

where $$a\in \mathbb{R}^n\backslash \{\mathbf{0}\}$$ and $$b\in \mathbb{R}^n$$.

This formulation of a hyperplane is hard to generalize, therefore we can rewrite $$\langle x, a\rangle - b$$ utilizing orthogonal completion. Setting any $$p$$ s.t. $$b=\langle a, p\rangle$$ we have

$\begin{split}H_{a, b} = \left\{ x \in \mathbb{R}^n\;:\;\langle x, a\rangle - b = 0 \right\}\\ =H_{a, \langle a, p\rangle} = \tilde{H}_{a, p}\\ = \left\{ x \in \mathbb{R}^n\;:\;\langle x, a\rangle - \langle a, p\rangle = 0 \right\}\\ =\left\{ x \in \mathbb{R}^n\;:\;\langle -p + x, a\rangle = 0 \right\}\\ = p + \{a\}^\perp\end{split}$

Naturally we have a set $$\{a\}^\perp$$ with applied $$+$$ operator to each element. Generalizing a notion of summation to the hyperbolic space we replace $$+$$ with $$\oplus_c$$.

Next, we should figure out what is $$\{a\}^\perp$$ in the Poincare ball.

First thing that we should acknowledge is that notion of orthogonality is defined for vectors in tangent spaces. Let’s consider now $$p\in \mathbb{D}_c^n$$ and $$a\in T_p\mathbb{D}_c^n\backslash \{\mathbf{0}\}$$.

Slightly deviating from traditional notation let’s write $$\{a\}_p^\perp$$ highlighting the tight relationship of $$a\in T_p\mathbb{D}_c^n\backslash \{\mathbf{0}\}$$ with $$p \in \mathbb{D}_c^n$$. We then define

$\{a\}_p^\perp := \left\{ z\in T_p\mathbb{D}_c^n \;:\; \langle z, a\rangle_p = 0 \right\}$

Recalling that a tangent vector $$z$$ for point $$p$$ yields $$x = \operatorname{Exp}^c_p(z)$$ we rewrite the above equation as

$\{a\}_p^\perp := \left\{ x\in \mathbb{D}_c^n \;:\; \langle \operatorname{Log}_p^c(x), a\rangle_p = 0 \right\}$

This formulation is something more pleasant to work with. Putting all together

$\begin{split}\tilde{H}_{a, p}^c = p + \{a\}^\perp_p\\ = \left\{ x \in \mathbb{D}_c^n\;:\;\langle\operatorname{Log}^c_p(x), a\rangle_p = 0 \right\} \\ = \left\{ x \in \mathbb{D}_c^n\;:\;\langle -p \oplus_c x, a\rangle = 0 \right\}\end{split}$

To compute the distance $$d_c(x, \tilde{H}_{a, p}^c)$$ we find

$\begin{split}d_c(x, \tilde{H}_{a, p}^c) = \inf_{w\in \tilde{H}_{a, p}^c} d_c(x, w)\\ = \frac{1}{\sqrt{c}} \sinh^{-1}\left\{ \frac{ 2\sqrt{c} |\langle(-p)\oplus_c x, a\rangle| }{ (1-c\|(-p)\oplus_c x\|^2_2)\|a\|_2 } \right\}\end{split}$
Parameters: x (tensor) – point on Poincare ball a (tensor) – vector on tangent space of $$p$$ p (tensor) – point on Poincare ball lying on the hyperplane c (float|tensor) – ball negative curvature keepdim (bool) – retain the last dim? (default: false) signed (bool) – return signed distance dim (int) – reduction dimension for operations distance to the hyperplane tensor
geoopt.manifolds.poincare.math.parallel_transport(x, y, v, *, c=1.0, dim=-1)[source]

Perform parallel transport on the Poincare ball.

Parallel transport is essential for adaptive algorithms in Riemannian manifolds. For Hyperbolic spaces parallel transport is expressed via gyration.

To recover parallel transport we first need to study isomorphism between gyrovectors and vectors. The reason is that originally, parallel transport is well defined for gyrovectors as

$P_{x\to y}(z) = \operatorname{gyr}[y, -x]z,$

where $$x,\:y,\:z \in \mathbb{D}_c^n$$ and $$\operatorname{gyr}[a, b]c = \ominus (a \oplus_c b) \oplus_c (a \oplus_c (b \oplus_c c))$$

But we want to obtain parallel transport for vectors, not for gyrovectors. The blessing is isomorphism mentioned above. This mapping is given by

$U^c_p \: : \: T_p\mathbb{D}_c^n \to \mathbb{G} = v \mapsto \lambda^c_p v$

Finally, having points $$x,\:y \in \mathbb{D}_c^n$$ and a tangent vector $$u\in T_x\mathbb{D}_c^n$$ we obtain

$\begin{split}P^c_{x\to y}(v) = (U^c_y)^{-1}\left(\operatorname{gyr}[y, -x] U^c_x(v)\right)\\ = \operatorname{gyr}[y, -x] v \lambda^c_x / \lambda^c_y\end{split}$
Parameters: x (tensor) – starting point y (tensor) – end point v (tensor) – tangent vector to be transported c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations transported vector tensor
geoopt.manifolds.poincare.math.geodesic(t, x, y, *, c=1.0, dim=-1)[source]

Compute geodesic at the time point $$t$$.

Geodesic (the shortest) path connecting $$x$$ and $$y$$. The path can be treated as and extension of a line segment between points but in a Riemannian manifold. In Poincare ball model, the path is expressed using Mobius addition and scalar multiplication:

$\gamma_{x\to y}(t) = x \oplus_c r \otimes_c ((-x) \oplus_c y)$

The required properties of this path are the following:

$\begin{split}\gamma_{x\to y}(0) = x\\ \gamma_{x\to y}(1) = y\\ \dot\gamma_{x\to y}(t) = v\end{split}$

Moreover, as geodesic path is not only the shortest path connecting points and Poincare ball. This definition also requires local distance minimization and thus another property appears:

$d_c(\gamma_{x\to y}(t_1), \gamma_{x\to y}(t_2)) = v|t_1-t_2|$

“Natural parametrization” of the curve ensures unit speed geodesics which yields the above formula with $$v=1$$. However, for Poincare ball we can always compute the constant speed $$v$$ from the points that particular path connects:

$v = d_c(\gamma_{x\to y}(0), \gamma_{x\to y}(1)) = d_c(x, y)$
Parameters: t (float|tensor) – travelling time x (tensor) – starting point on Poincare ball y (tensor) – target point on Poincare ball c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations point on the Poincare ball tensor
geoopt.manifolds.poincare.math.geodesic_unit(t, x, u, *, c=1.0, dim=-1)[source]

Compute unit speed geodesic at time $$t$$ starting from $$x$$ with direction $$u/\|u\|_x$$.

$\gamma_{x,u}(t) = x\oplus_c \tanh(t\sqrt{c}/2) \frac{u}{\sqrt{c}\|u\|_2}$
Parameters: t (tensor) – travelling time x (tensor) – initial point u (tensor) – direction c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations the point on geodesic line tensor
geoopt.manifolds.poincare.math.expmap(x, u, *, c=1.0, dim=-1)[source]

Compute exponential map on the Poincare ball.

Exponential map for Poincare ball model. This is tightly related with geodesic(). Intuitively Exponential map is a smooth constant travelling from starting point $$x$$ with speed $$u$$.

A bit more formally this is travelling along curve $$\gamma_{x, u}(t)$$ such that

$\begin{split}\gamma_{x, u}(0) = x\\ \dot\gamma_{x, u}(0) = u\\ \|\dot\gamma_{x, u}(t)\|_{\gamma_{x, u}(t)} = \|u\|_x\end{split}$

The existence of this curve relies on uniqueness of differential equation solution, that is local. For the Poincare ball model the solution is well defined globally and we have.

$\begin{split}\operatorname{Exp}^c_x(u) = \gamma_{x, u}(1) = \\ x\oplus_c \tanh(\sqrt{c}/2 \|u\|_x) \frac{u}{\sqrt{c}\|u\|_2}\end{split}$
Parameters: x (tensor) – starting point on Poincare ball u (tensor) – speed vector on Poincare ball c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations $$\gamma_{x, u}(1)$$ end point tensor
geoopt.manifolds.poincare.math.expmap0(u, *, c=1.0, dim=-1)[source]

Compute exponential map for Poincare ball model from $$0$$.

$\operatorname{Exp}^c_0(u) = \tanh(\sqrt{c}/2 \|u\|_2) \frac{u}{\sqrt{c}\|u\|_2}$
Parameters: u (tensor) – speed vector on Poincare ball c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations $$\gamma_{0, u}(1)$$ end point tensor
geoopt.manifolds.poincare.math.logmap(x, y, *, c=1.0, dim=-1)[source]

Compute logarithmic map for two points $$x$$ and $$y$$ on the manifold.

$\operatorname{Log}^c_x(y) = \frac{2}{\sqrt{c}\lambda_x^c} \tanh^{-1}( \sqrt{c} \|(-x)\oplus_c y\|_2 ) * \frac{(-x)\oplus_c y}{\|(-x)\oplus_c y\|_2}$

The result of Logarithmic map is a vector such that

$y = \operatorname{Exp}^c_x(\operatorname{Log}^c_x(y))$
Parameters: x (tensor) – starting point on Poincare ball y (tensor) – target point on Poincare ball c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations tangent vector that transports $$x$$ to $$y$$ tensor
geoopt.manifolds.poincare.math.logmap0(y, *, c=1.0, dim=-1)[source]

Compute logarithmic map for $$y$$ from $$0$$ on the manifold.

$\operatorname{Log}^c_0(y) = \tanh^{-1}(\sqrt{c}\|y\|_2) \frac{y}{\|y\|_2}$

The result is such that

$y = \operatorname{Exp}^c_0(\operatorname{Log}^c_0(y))$
Parameters: y (tensor) – target point on Poincare ball c (float|tensor) – ball negative curvature dim (int) – reduction dimension for operations tangent vector that transports $$0$$ to $$y$$ tensor

## Stability¶

Numerical stability is a pain in this model. It is strongly recommended to work in float64, so expect adventures in float32 (but this is not certain).

geoopt.manifolds.poincare.math.project(x, *, c=1.0, dim=-1, eps=None)[source]

Safe projection on the manifold for numerical stability.

Parameters: x (tensor) – point on the Poincare ball c (float|tensor) – ball negative curvature dim (int) – reduction dimension to compute norm eps (float) – stability parameter, uses default for dtype if not provided projected vector on the manifold tensor