# Manifolds

While the interface ManifoldsBase.jl does not cover concrete manifolds, it provides a few helpers to build or create manifolds based on existing manifolds

## (Abstract) power manifold

A power manifold is constructed like higher dimensional vector spaces are formed from the real line, just that for every point $p = (p_1,\ldots,p_n) ∈ \mathcal M^n$ on the power manifold $\mathcal M^n$ the entries of $p$ are points $p_1,\ldots,p_n ∈ \mathcal M$ on some manifold $\mathcal M$. Note that $n$ can also be replaced by multiple values, such that $p$ is not a vector but a matrix or a multi-index array of points.

ManifoldsBase.NestedReplacingPowerRepresentationType
NestedReplacingPowerRepresentation

Representation of points and tangent vectors on a power manifold using arrays of size equal to TSize of a PowerManifold. Each element of such array stores a single point or tangent vector.

For modifying operations, each element of the outer array is replaced using non-modifying operations, differently than for NestedReplacingPowerRepresentation.

source
ManifoldsBase.PowerManifoldType
PowerManifold{𝔽,TM<:AbstractManifold,TSize<:Tuple,TPR<:AbstractPowerRepresentation} <: AbstractPowerManifold{𝔽,TM}

The power manifold $\mathcal M^{n_1× n_2 × … × n_d}$ with power geometry TSize statically defines the number of elements along each axis.

For example, a manifold-valued time series would be represented by a power manifold with $d$ equal to 1 and $n_1$ equal to the number of samples. A manifold-valued image (for example in diffusion tensor imaging) would be represented by a two-axis power manifold ($d=2$) with $n_1$ and $n_2$ equal to width and height of the image.

While the size of the manifold is static, points on the power manifold would not be represented by statically-sized arrays.

Constructor

PowerManifold(M::PowerManifold, N_1, N_2, ..., N_d)
PowerManifold(M::AbstractManifold, NestedPowerRepresentation(), N_1, N_2, ..., N_d)
M^(N_1, N_2, ..., N_d)

Generate the power manifold $M^{N_1 × N_2 × … × N_d}$. By default, a [PowerManifold](@ref} is expanded further, i.e. for M=PowerManifold(N,3) PowerManifold(M,2) is equivalend to PowerManifold(N,3,2). Points are then 3×2 matrices of points on N. Providing a NestedPowerRepresentation as the second argument to the constructor can be used to nest manifold, i.e. PowerManifold(M,NestedPowerRepresentation(),2) represents vectors of length 2 whose elements are vectors of length 3 of points on N in a nested array representation.

Since there is no default AbstractPowerRepresentation within this interface, the ^ operator is only available for PowerManifolds and concatenates dimensions.

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

Copy the values elementwise, i.e. call copyto!(M.manifold, B, a, A) for all elements A, a and B of X, p, and Y, respectively.

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

Copy the values elementwise, i.e. call copyto!(M.manifold, b, a) for all elements a and b of p and q, respectively.

source
Base.expMethod
exp(M::AbstractPowerManifold, p, X)

Compute the exponential map from p in direction X on the AbstractPowerManifold M, which can be computed using the base manifolds exponential map elementwise.

source
Base.setindex!Method
setindex!(q, p, M::AbstractPowerManifold, i::Union{Integer,Colon,AbstractVector}...)
q[M::AbstractPowerManifold, i...] = p

Set the element(s) at index [i...] of a point q on an AbstractPowerManifold M by linear or multidimensional indexing to q. See also Array Indexing in Julia.

source
Base.viewMethod
view(p, M::AbstractPowerManifold, i::Union{Integer,Colon,AbstractVector}...)

Get the view of the element(s) at index [i...] of a point p on an AbstractPowerManifold M by linear or multidimensional indexing.

source
ManifoldsBase.check_pointMethod
check_point(M::AbstractPowerManifold, p; kwargs...)

Check whether p is a valid point on an AbstractPowerManifold M, i.e. each element of p has to be a valid point on the base manifold. If p is not a point on M a CompositeManifoldError consisting of all error messages of the components, for which the tests fail is returned.

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

source
ManifoldsBase.check_power_sizeMethod
check_power_size(M, p)
check_power_size(M, p, X)

Check whether p hase the right size to represent points on M generically, i.e. just cheking the overall sizes, not the individual ones per manifold

source
ManifoldsBase.check_vectorMethod
check_vector(M::AbstractPowerManifold, p, X; kwargs... )

Check whether X is a tangent vector to p an the AbstractPowerManifold M, i.e. atfer check_point(M, p), and all projections to base manifolds must be respective tangent vectors. If X is not a tangent vector to p on M a CompositeManifoldError consisting of all error messages of the components, for which the tests fail is returned.

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

source
ManifoldsBase.innerMethod
inner(M::AbstractPowerManifold, p, X, Y)

Compute the inner product of X and Y from the tangent space at p on an AbstractPowerManifold M, i.e. for each arrays entry the tangent vector entries from X and Y are in the tangent space of the corresponding element from p. The inner product is then the sum of the elementwise inner products.

source
ManifoldsBase.inverse_retractMethod
inverse_retract(M::AbstractPowerManifold, p, q, m::AbstractInverseRetractionMethod)

Compute the inverse retraction from p with respect to q on an AbstractPowerManifold M using an AbstractInverseRetractionMethod. Then this method is performed elementwise, so the inverse retraction method has to be one that is available on the base AbstractManifold.

source
ManifoldsBase.manifold_dimensionMethod
manifold_dimension(M::PowerManifold)

Returns the manifold-dimension of an PowerManifold M $=\mathcal N = (\mathcal M)^{n_1,…,n_d}$, i.e. with $n=(n_1,…,n_d)$ the array size of the power manifold and $d_{\mathcal M}$ the dimension of the base manifold $\mathcal M$, the manifold is of dimension

$$$\dim(\mathcal N) = \dim(\mathcal M)\prod_{i=1}^d n_i = n_1n_2\cdot…\cdot n_d \dim(\mathcal M).$$$
source
ManifoldsBase.vector_transport_toMethod
vector_transport_to(M::AbstractPowerManifold, p, X, q, method::AbstractVectorTransportMethod)

Compute the vector transport the tangent vector Xat p to q on the PowerManifold M using an AbstractVectorTransportMethod m. This method is performed elementwise, i.e. the method m has to be implemented on the base manifold.

source

## ValidationManifold

ValidationManifold is a simple decorator using the AbstractDecoratorManifold that “decorates” a manifold with tests that all involved points and vectors are valid for the wrapped manifold. For example involved input and output paratemers are checked before and after running a function, repectively. This is done by calling is_point or is_vector whenever applicable.

ManifoldsBase.ValidationManifoldType
ValidationManifold{𝔽,M<:AbstractManifold{𝔽}} <: AbstractDecoratorManifold{𝔽}

A manifold to encapsulate manifolds working on array representations of AbstractManifoldPoints and TVectors in a transparent way, such that for these manifolds it's not necessary to introduce explicit types for the points and tangent vectors, but they are encapsulated/stripped automatically when needed.

This manifold is a decorator for a manifold, i.e. it decorates a AbstractManifold M with types points, vectors, and covectors.

source

## DefaultManifold

DefaultManifold is a simplified version of Euclidean and demonstrates a basic interface implementation. It can be used to perform simple tests. Since when using Manifolds.jl the Euclidean is available, the DefaultManifold itself is not exported.

ManifoldsBase.DefaultManifoldType
DefaultManifold <: AbstractManifold

This default manifold illustrates the main features of the interface and provides a skeleton to build one's own manifold. It is a simplified/shortened variant of Euclidean from Manifolds.jl.

This manifold further illustrates how to type your manifold points and tangent vectors. Note that the interface does not require this, but it might be handy in debugging and educative situations to verify correctness of involved variabes.

source

## Embedded manifold

The embedded manifold is a manifold $\mathcal M$ which is modelled explicitly specifying its embedding $\mathcal N$ in which the points and tangent vectors are represented. Most prominently is_point and is_vector of an embedded manifold are implemented to check whether the point is a valid point in the embedding. This can of course still be extended by further tests. ManifoldsBase.jl provides two possibilities of easily introducing this in order to dispatch some functions to the embedding.

### Implicit case: the IsEmbeddedManifold Trait

For the implicit case, your manifold has to be a subtype of the AbstractDecoratorManifold. Adding a method to the active_traits function for a manifold that returns an AbstractTrait IsEmbeddedManifold, makes that manifold an embedded manifold. You just have to also define get_embedding so that appropriate functions are passed on to that embedding. This is the implicit case, since the manifold type itself does not carry any information about the embedding, just the trait and the function definition do.

### Explicit case: the EmbeddedManifold

The EmbeddedManifold itself is an AbstractDecoratorManifold so it is a case of the implicit embedding itself, but internally stores both the original manifold and the embedding. They are also parameters of the type. This way, an additional embedding of one manifold in another can be modelled. That is, if the manifold is implemented using the implicit embedding approach from before but can also be implemented using a different embedding, then this method should be chosen, since you can dispatch functions that you want to implement in this embedding then on the type which explicitly has the manifold and its embedding as parameters.

Hence this case should be used for any further embedding after the first or if the default implementation works without an embedding and the alternative needs one.

ManifoldsBase.EmbeddedManifoldType
EmbeddedManifold{𝔽, MT <: AbstractManifold, NT <: AbstractManifold} <: AbstractDecoratorManifold{𝔽}

A type to represent an explicit embedding of a AbstractManifold M of type MT embedded into a manifold N of type NT. By default, an embedded manifold is set to be embedded, but neither isometrically embedded nor a submanifold.

Note

This type is not required if a manifold M is to be embedded in one specific manifold N. One can then just implement embed! and project!. You can further pass functions to the embedding, for example, when it is an isometric embedding, by using an AbstractDecoratorManifold. Only for a second –maybe considered non-default– embedding, this type should be considered in order to dispatch on different embed and project methods for different embeddings N.

Fields

• manifold the manifold that is an embedded manifold
• embedding a second manifold, the first one is embedded into

Constructor

EmbeddedManifold(M, N)

Generate the EmbeddedManifold of the AbstractManifold M into the AbstractManifold N.

source
ManifoldsBase.decorated_manifoldMethod
decorated_manifold(M::EmbeddedManifold, d::Val{N} = Val(-1))

Return the manifold of M that is decorated with its embedding. For this specific type the internally stored enhanced manifold M.manifold is returned.

See also base_manifold, where this is used to (potentially) completely undecorate the manifold.

source