Functions on manifolds

This page collects several basic functions on manifolds.

The exponential map, the logarithmic map, and geodesics

Geodesics are the generalizations of a straight line to manifolds, i.e. their intrinsic acceleration is zero. Together with geodesics one also obtains the exponential map and its inverse, the logarithmic map. Informally speaking, the exponential map takes a vector (think of a direction and a length) at one point and returns another point, which lies towards this direction at distance of the specified length. The logarithmic map does the inverse, i.e. given two points, it tells which vector “points towards” the other point.

Base.expMethod
exp(M::AbstractManifold, p, X)
exp(M::AbstractManifold, p, X, t::Real = 1)

Compute the exponential map of tangent vector X, optionally scaled by t, at point p from the manifold AbstractManifold M, i.e.

\[\exp_p X = γ_{p,X}(1),\]

where $γ_{p,X}$ is the unique geodesic starting in $γ(0)=p$ such that $\dot γ(0) = X$.

See also shortest_geodesic, retract.

Base.logMethod
log(M::AbstractManifold, p, q)

Compute the logarithmic map of point q at base point p on the AbstractManifold M. The logarithmic map is the inverse of the exponential map. Note that the logarithmic map might not be globally defined.

See also inverse_retract.

ManifoldsBase.exp!Method
exp!(M::AbstractManifold, q, p, X)
exp!(M::AbstractManifold, q, p, X, t::Real = 1)

Compute the exponential map of tangent vector X, optionally scaled by t, at point p from the manifold AbstractManifold M. The result is saved to q.

See also exp.

ManifoldsBase.geodesic!Method
geodesic!(M::AbstractManifold, Q, p, X, T::AbstractVector) -> AbstractVector

Get the geodesic with initial point p and velocity X on the AbstractManifold M. A geodesic is a curve of zero acceleration. That is for the curve $γ_{p,X}: I → \mathcal M$, with $γ_{p,X}(0) = p$ and $\dot γ_{p,X}(0) = X$ a geodesic further fulfills

\[∇_{\dot γ_{p,X}(t)} \dot γ_{p,X}(t) = 0,\]

i.e. the curve is acceleration free with respect to the Riemannian metric. This function evaluates the geodeic at time points t fom T in place of Q.

ManifoldsBase.geodesic!Method
geodesic!(M::AbstractManifold, q, p, X, t::Real)

Get the geodesic with initial point p and velocity X on the AbstractManifold M. A geodesic is a curve of zero acceleration. That is for the curve $γ_{p,X}: I → \mathcal M$, with $γ_{p,X}(0) = p$ and $\dot γ_{p,X}(0) = X$ a geodesic further fulfills

\[∇_{\dot γ_{p,X}(t)} \dot γ_{p,X}(t) = 0,\]

i.e. the curve is acceleration free with respect to the Riemannian metric. This function evaluates the geodeic at t in place of q.

ManifoldsBase.geodesic!Method
geodesic!(M::AbstractManifold, p, X) -> Function

Get the geodesic with initial point p and velocity X on the AbstractManifold M. A geodesic is a curve of zero acceleration. That is for the curve $γ_{p,X}: I → \mathcal M$, with $γ_{p,X}(0) = p$ and $\dot γ_{p,X}(0) = X$ a geodesic further fulfills

\[∇_{\dot γ_{p,X}(t)} \dot γ_{p,X}(t) = 0,\]

i.e. the curve is acceleration free with respect to the Riemannian metric. This yields that the curve has constant velocity and is locally distance-minimizing.

This function returns a function (q,t) of (time) t that mutates q`.

ManifoldsBase.geodesicMethod
geodesic(M::AbstractManifold, p, X, T::AbstractVector) -> AbstractVector

Evaluate the geodesic $γ_{p,X}: I → \mathcal M$, with $γ_{p,X}(0) = p$ and $\dot γ_{p,X}(0) = X$ a geodesic further fulfills

\[∇_{\dot γ_{p,X}(t)} \dot γ_{p,X}(t) = 0,\]

at time points t from T.

ManifoldsBase.geodesicMethod
geodesic(M::AbstractManifold, p, X, t::Real)

Evaluate the geodesic $γ_{p,X}: I → \mathcal M$, with $γ_{p,X}(0) = p$ and $\dot γ_{p,X}(0) = X$ a geodesic further fulfills

\[∇_{\dot γ_{p,X}(t)} \dot γ_{p,X}(t) = 0,\]

at time t.

ManifoldsBase.geodesicMethod
geodesic(M::AbstractManifold, p, X) -> Function

Get the geodesic with initial point p and velocity X on the AbstractManifold M. A geodesic is a curve of zero acceleration. That is for the curve $γ_{p,X}: I → \mathcal M$, with $γ_{p,X}(0) = p$ and $\dot γ_{p,X}(0) = X$ a geodesic further fulfills

\[∇_{\dot γ_{p,X}(t)} \dot γ_{p,X}(t) = 0,\]

i.e. the curve is acceleration free with respect to the Riemannian metric. This yields, that the curve has constant velocity that is locally distance-minimizing.

This function returns a function of (time) t.

ManifoldsBase.log!Method
log!(M::AbstractManifold, X, p, q)

Compute the logarithmic map of point q at base point p on the AbstractManifold M. The result is saved to X. The logarithmic map is the inverse of the exp!onential map. Note that the logarithmic map might not be globally defined.

see also log and inverse_retract!,

ManifoldsBase.shortest_geodesic!Method
shortest_geodesic!(M::AbstractManifold, R, p, q, T::AbstractVector) -> AbstractVector

Evaluate a geodesic $γ_{p,q}(t)$ whose length is the shortest path between the points pand q, where $γ_{p,q}(0)=p$ and $γ_{p,q}(1)=q$ at all t from T in place of R. When there are multiple shortest geodesics, a deterministic choice will be taken.

ManifoldsBase.shortest_geodesic!Method
shortest_geodesic!(M::AabstractManifold, r, p, q, t::Real)

Evaluate a geodesic $γ_{p,q}(t)$ whose length is the shortest path between the points pand q, where $γ_{p,q}(0)=p$ and $γ_{p,q}(1)=q$ at t in place of r. When there are multiple shortest geodesics, a deterministic choice will be taken.

ManifoldsBase.shortest_geodesic!Method
shortest_geodesic!(M::AbstractManifold, p, q) -> Function

Get a geodesic $γ_{p,q}(t)$ whose length is the shortest path between the points pand q, where $γ_{p,q}(0)=p$ and $γ_{p,q}(1)=q$. When there are multiple shortest geodesics, a deterministic choice will be returned.

This function returns a function (r,t) -> ... of time t which works in place of r.

Further variants

shortest_geodesic!(M::AabstractManifold, r, p, q, t::Real)
shortest_geodesic!(M::AbstractManifold, R, p, q, T::AbstractVector) -> AbstractVector

mutate (and return) the point r and the vector of points R, respectively, returning the point at time t or points at times t in T along the shortest geodesic.

ManifoldsBase.shortest_geodesicMethod
shortest_geodesic(M::AbstractManifold, p, q, T::AbstractVector) -> AbstractVector

Evaluate a geodesic $γ_{p,q}(t)$ whose length is the shortest path between the points pand q, where $γ_{p,q}(0)=p$ and $γ_{p,q}(1)=q$ at time points T. When there are multiple shortest geodesics, a deterministic choice will be returned.

ManifoldsBase.shortest_geodesicMethod
shortest_geodesic(M::AabstractManifold, p, q, t::Real)

Evaluate a geodesic $γ_{p,q}(t)$ whose length is the shortest path between the points pand q, where $γ_{p,q}(0)=p$ and $γ_{p,q}(1)=q$ at time t. When there are multiple shortest geodesics, a deterministic choice will be returned.

ManifoldsBase.shortest_geodesicMethod
shortest_geodesic(M::AbstractManifold, p, q) -> Function

Get a geodesic $γ_{p,q}(t)$ whose length is the shortest path between the points pand q, where $γ_{p,q}(0)=p$ and $γ_{p,q}(1)=q$. When there are multiple shortest geodesics, a deterministic choice will be returned.

This function returns a function of time, which may be a Real or an AbstractVector.

Parallel transport

While moving vectors from one base point to another is the identity in the Euclidean space – or in other words all tangent spaces (directions one can “walk” into) are the same. This is different on a manifold.

If we have two points $p,q ∈ \mathcal M$, we take a $c: [0,1] → \mathcal M$ connecting the two points, i.e. $c(0) = p$ and $c(1) = q$. this could be a (or the) geodesic. If we further consider a vector field $X: [0,1] → T\mathcal M$, i.e. where $X(t) ∈ T_{c(t)}\mathcal M$. Then the vector field is called parallel if its covariant derivative $\frac{\mathrm{D}}{\mathrm{d}t}X(t) = 0$ for all $t∈ |0,1]$.

If we now impose a value for $X=X(0) ∈ T_p\mathcal M$, we obtain an ODE with an initial condition. The resulting value $X(1) ∈ T_q\mathcal M$ is called the parallel transport of X along $c$ or in case of a geodesic the _parallel transport of X from p to q.

ManifoldsBase.parallel_transport_alongMethod
Y = parallel_transport_along(M::AbstractManifold, p, X, c)

Compute the parallel transport of the vector X from the tangent space at p along the curve c.

To be precise let $c(t)$ be a curve $c(0)=p$ for vector_transport_along $\mathcal P^cY$

THen In the result $Y\in T_p\mathcal M$ is the vector $X$ from the tangent space at $p=c(0)$ to the tangent space at $c(1)$.

Let $Z\colon [0,1] \to T\mathcal M$, $Z(t)\in T_{c(t)}\mathcal M$ be a smooth vector field along the curve $c$ with $Z(0) = Y$, such that $Z$ is parallel, i.e. its covariant derivative $\frac{\mathrm{D}}{\mathrm{d}t}Z$ is zero. Note that such a $Z$ always exists and is unique.

Then the parallel transport is given by $Z(1)$.

Further functions on manifolds

General functions provided by the interface

Base.angleMethod
angle(M::AbstractManifold, p, X, Y)

Compute the angle between tangent vectors X and Y at point p from the AbstractManifold M with respect to the inner product from inner.

Base.copyto!Method
copyto!(M::AbstractManifold, Y, p, X)

Copy the value(s) from X to Y, where both are tangent vectors from the tangent space at p on the AbstractManifold M. This function defaults to calling copyto!(Y, X), but it might be useful to overwrite the function at the level, where also information from p and M can be accessed.

Base.copyto!Method
copyto!(M::AbstractManifold, q, p)

Copy the value(s) from p to q, where both are points on the AbstractManifold M. This function defaults to calling copyto!(q, p), but it might be useful to overwrite the function at the level, where also information from M can be accessed.

Base.isapproxMethod
isapprox(M::AbstractManifold, p, X, Y; kwargs...)

Check if vectors X and Y tangent at p from AbstractManifold M are approximately equal.

Keyword arguments can be used to specify tolerances.

Base.isapproxMethod
isapprox(M::AbstractManifold, p, q; kwargs...)

Check if points p and q from AbstractManifold M are approximately equal.

Keyword arguments can be used to specify tolerances.

ManifoldsBase.allocateMethod
allocate(a)
allocate(a, dims::Integer...)
allocate(a, dims::Tuple)
allocate(a, T::Type)
allocate(a, T::Type, dims::Integer...)
allocate(a, T::Type, dims::Tuple)
allocate(M::AbstractManifold, a)
allocate(M::AbstractManifold, a, dims::Integer...)
allocate(M::AbstractManifold, a, dims::Tuple)
allocate(M::AbstractManifold, a, T::Type)
allocate(M::AbstractManifold, a, T::Type, dims::Integer...)
allocate(M::AbstractManifold, a, T::Type, dims::Tuple)

Allocate an object similar to a. It is similar to function similar, although instead of working only on the outermost layer of a nested structure, it maps recursively through outer layers and calls similar on the innermost array-like object only. Type T is the new number element type number_eltype, if it is not given the element type of a is retained. The dims argument can be given for non-nested allocation and is forwarded to the function similar.

It's behavior can be overriden by a specific manifold, for example power manifold with nested replacing representation can decide that allocate for Array{<:SArray} returns another Array{<:SArray} instead of Array{<:MArray}, as would be done by default.

ManifoldsBase.base_manifoldFunction
base_manifold(M::AbstractManifold, depth = Val(-1))

Return the internally stored AbstractManifold for decorated manifold M and the base manifold for vector bundles or power manifolds. The optional parameter depth can be used to remove only the first depth many decorators and return the AbstractManifold from that level, whether its decorated or not. Any negative value deactivates this depth limit.

ManifoldsBase.distanceMethod
distance(M::AbstractManifold, p, q)

Shortest distance between the points p and q on the AbstractManifold M, i.e.

\[d(p,q) = \inf_{γ} L(γ),\]

where the infimum is over all piecewise smooth curves $γ: [a,b] \to \mathcal M$ connecting $γ(a)=p$ and $γ(b)=q$ and

\[L(γ) = \displaystyle\int_{a}^{b} \lVert \dotγ(t)\rVert_{γ(t)} \mathrm{d}t\]

is the length of the curve $γ$.

If $\mathcal M$ is not connected, i.e. consists of several disjoint components, the distance between two points from different components should be $∞$.

ManifoldsBase.embed!Method
embed!(M::AbstractManifold, Y, p, X)

Embed a tangent vector X at a point p on the AbstractManifold M into the ambient space and return the result in Y. This method is only available for manifolds where implicitly an embedding or ambient space is given. Additionally, embed! includes changing data representation, if applicable, i.e. if the tangents on M are not represented in the same way as tangents on the embedding, the representation is changed accordingly. This is the case for example for Lie groups, when tangent vectors are represented in the Lie algebra. The embedded tangents are then in the tangent spaces of the embedded base points.

The default is set in such a way that it assumes that the points on M are represented in their embedding (for example like the unit vectors in a space to represent the sphere) and hence embedding also for tangent vectors is the identity by default.

See also: EmbeddedManifold, project!

ManifoldsBase.embed!Method
embed!(M::AbstractManifold, q, p)

Embed point p from the AbstractManifold M into an ambient space. This method is only available for manifolds where implicitly an embedding or ambient space is given. Not implementing this function means, there is no proper embedding for your manifold. Additionally, embed might include changing data representation, if applicable, i.e. if points on M are not represented in the same way as their counterparts in the embedding, the representation is changed accordingly.

The default is set in such a way that it assumes that the points on M are represented in their embedding (for example like the unit vectors in a space to represent the sphere) and hence embedding in the identity by default.

If you have more than one embedding, see EmbeddedManifold for defining a second embedding. If your point p is already represented in some embedding, see AbstractDecoratorManifold how you can avoid reimplementing code from the embedded manifold

See also: EmbeddedManifold, project!

ManifoldsBase.embedMethod
embed(M::AbstractManifold, p, X)

Embed a tangent vector X at a point p on the AbstractManifold M into an ambient space. This method is only available for manifolds where implicitly an embedding or ambient space is given. Not implementing this function means, there is no proper embedding for your tangent space(s).

Additionally, embed might include changing data representation, if applicable, i.e. if tangent vectors on M are not represented in the same way as their counterparts in the embedding, the representation is changed accordingly.

The default is set in such a way that memory is allocated and embed!(M, Y, p. X) is called.

If you have more than one embedding, see EmbeddedManifold for defining a second embedding. If your tangent vector X is already represented in some embedding, see AbstractDecoratorManifold how you can avoid reimplementing code from the embedded manifold

See also: EmbeddedManifold, project

ManifoldsBase.embedMethod
embed(M::AbstractManifold, p)

Embed point p from the AbstractManifold M into the ambient space. This method is only available for manifolds where implicitly an embedding or ambient space is given. Additionally, embed includes changing data representation, if applicable, i.e. if the points on M are not represented in the same way as points on the embedding, the representation is changed accordingly.

The default is set in such a way that memory is allocated and embed!(M, q, p) is called.

See also: EmbeddedManifold, project

ManifoldsBase.injectivity_radiusMethod
injectivity_radius(M::AbstractManifold)

Infimum of the injectivity radii injectivity_radius(M,p) of all points p on the AbstractManifold.

injectivity_radius(M::AbstractManifold, p)

Return the distance $d$ such that exp(M, p, X) is injective for all tangent vectors shorter than $d$ (i.e. has an inverse).

injectivity_radius(M::AbstractManifold[, x], method::AbstractRetractionMethod)
injectivity_radius(M::AbstractManifold, x, method::AbstractRetractionMethod)

Distance $d$ such that retract(M, p, X, method) is injective for all tangent vectors shorter than $d$ (i.e. has an inverse) for point p if provided or all manifold points otherwise.

In order to dispatch on different retraction methods, please either implement _injectivity_radius(M[, p], m::T) for your retraction R or specifically injectivity_radius_exp(M[, p]) for the exponential map. By default the variant with a point p assumes that the default (without p) can ve called as a lower bound.

ManifoldsBase.is_pointFunction
is_point(M::AbstractManifold, p, throw_error = false; kwargs...)

Return whether p is a valid point on the AbstractManifold M.

If throw_error is false, the function returns either true or false. If throw_error is true, the function either returns true or throws an error. By default the function calls check_point and checks whether the returned value is nothing or an error.

ManifoldsBase.is_vectorFunction
is_vector(M::AbstractManifold, p, X, throw_error = false, check_base_point=true; kwargs...)

Return whether X is a valid tangent vector at point p on the AbstractManifold M. Returns either true or false.

If throw_error is false, the function returns either true or false. If throw_error is true, the function either returns true or throws an error. By default the function calls check_vector and checks whether the returned value is nothing or an error.

If check_base_point is true, then the point p will be first checked using the check_point function.

ManifoldsBase.mid_point!Method
mid_point!(M::AbstractManifold, q, p1, p2)

Calculate the middle between the two point p1 and p2 from manifold M. By default uses log, divides the vector by 2 and uses exp!. Saves the result in q.

ManifoldsBase.mid_pointMethod
mid_point(M::AbstractManifold, p1, p2)

Calculate the middle between the two point p1 and p2 from manifold M. By default uses log, divides the vector by 2 and uses exp.

ManifoldsBase.riemann_tensorMethod
riemann_tensor(M::AbstractManifold, p, X, Y, Z)

Compute the value of the Riemann tensor $R(X_f,Y_f)Z_f$ at point p, where $X_f$, $Y_f$ and $Z_f$ are vector fields defined by parallel transport of, respectively, X, Y and Z to the desired point. All computations are performed using the connection associated to manifold M.

The formula reads $R(X_f,Y_f)Z_f = \nabla_X\nabla_Y Z - \nabla_Y\nabla_X Z - \nabla_{[X, Y]}Z$, where $[X, Y]$ is the Lie bracket of vector fields.

Note that some authors define this quantity with inverse sign.

ManifoldsBase.zero_vector!Method
zero_vector!(M::AbstractManifold, X, p)

Save to X the tangent vector from the tangent space $T_p\mathcal M$ at p that represents the zero vector, i.e. such that retracting X to the AbstractManifold M at p produces p.

ManifoldsBase.zero_vectorMethod
zero_vector(M::AbstractManifold, p)

Return the tangent vector from the tangent space $T_p\mathcal M$ at p on the AbstractManifold M, that represents the zero vector, i.e. such that a retraction at p produces p.

Internal functions

While you should always add your documentation to functions from the last section, some of the functions dispatch onto functions on layer III. These are the ones you usually implement for your manifold – unless there is no lower level function called, like for the manifold_dimension.

ManifoldsBase._pick_basic_allocation_argumentMethod
_pick_basic_allocation_argument(::AbstractManifold, f, x...)

Pick which one of elements of x should be used as a basis for allocation in the allocate_result(M::AbstractManifold, f, x...) method. This can be specialized to, for example, skip Identity arguments in Manifolds.jl group-related functions.

ManifoldsBase.allocate_resultMethod
allocate_result(M::AbstractManifold, f, x...)

Allocate an array for the result of function f on AbstractManifold M and arguments x... for implementing the non-modifying operation using the modifying operation.

Usefulness of passing a function is demonstrated by methods that allocate results of musical isomorphisms.

ManifoldsBase.allocate_result_typeMethod
allocate_result_type(M::AbstractManifold, f, args::NTuple{N,Any}) where N

Return type of element of the array that will represent the result of function f and the AbstractManifold M on given arguments args (passed as a tuple).

ManifoldsBase.check_pointMethod
check_point(M::AbstractManifold, p; kwargs...) -> Union{Nothing,String}

Return nothing when p is a point on the AbstractManifold M. Otherwise, return an error with description why the point does not belong to manifold M.

By default, check_point returns nothing, i.e. if no checks are implemented, the assumption is to be optimistic for a point not deriving from the AbstractManifoldPoint type.

ManifoldsBase.check_sizeMethod
check_size(M::AbstractManifold, p)
check_size(M::AbstractManifold, p, X)

Check whether p has the right representation_size for a AbstractManifold M. Additionally if a tangent vector is given, both p and X are checked to be of corresponding correct representation sizes for points and tangent vectors on M.

By default, check_size returns nothing, i.e. if no checks are implemented, the assumption is to be optimistic.

ManifoldsBase.check_vectorMethod
check_vector(M::AbstractManifold, p, X; kwargs...) -> Union{Nothing,String}

Check whether X is a valid tangent vector in the tangent space of p on the AbstractManifold M. An implementation does not have to validate the point p. If it is not a tangent vector, an error string should be returned.

By default, check_vector returns nothing, i.e. if no checks are implemented, the assumption is to be optimistic for tangent vectors not deriving from the TVector type.

ManifoldsBase.size_to_tupleMethod
size_to_tuple(::Type{S}) where S<:Tuple

Converts a size given by Tuple{N, M, ...} into a tuple (N, M, ...).

Error Messages

This interface introduces a small set of own error messages.

ManifoldsBase.ComponentManifoldErrorType
CompnentError{I,E} <: Exception

Store an error that occured in a component, where the additional index is stored.

Fields

  • index index where the error occured`
  • error error that occured.
ManifoldsBase.ManifoldDomainErrorType
ManifoldDomainError{<:Exception} <: Exception

An error to represent a nested (Domain) error on a manifold, for example if a point or tangent vector is invalid because its representation in some embedding is already invalid.