Power manifold

A power manifold is based on a Manifold$\mathcal M$ to build a $\mathcal M^{n_1 \times n_2 \times \cdots \times n_m}$. In the case where $m=1$ we can represent a manifold-valued vector of data of length $n_1$, for example a time series. The case where $m=2$ is useful for representing manifold-valued matrices of data of size $n_1 \times n_2$, for example certain types of images.

Example

There are two ways to store the data: in a multidimensional array or in a nested array.

Let's look at an example for both. Let $\mathcal M$ be Sphere(2) the 2-sphere and we want to look at vectors of length 4.

For the default, the ArrayPowerRepresentation, we store the data in a multidimensional array,

using Manifolds
M = PowerManifold(Sphere(2), 4)
p = cat([1.0, 0.0, 0.0],
        [1/sqrt(2.0), 1/sqrt(2.0), 0.0],
        [1/sqrt(2.0), 0.0, 1/sqrt(2.0)],
        [0.0, 1.0, 0.0]
    ,dims=2)
3×4 Array{Float64,2}:
 1.0  0.707107  0.707107  0.0
 0.0  0.707107  0.0       1.0
 0.0  0.0       0.707107  0.0

which is a valid point i.e.

is_manifold_point(M, p)
true

This can also be used in combination with HybridArrays.jl and StaticArrays.jl, by setting

using HybridArrays, StaticArrays
q = HybridArray{Tuple{3,StaticArrays.Dynamic()},Float64,2}(p)
3×4 HybridArrays.HybridArray{Tuple{3,StaticArrays.Dynamic()},Float64,2,2,Array{Float64,2}} with indices SOneTo(3)×Base.OneTo(4):
 1.0  0.707107  0.707107  0.0
 0.0  0.707107  0.0       1.0
 0.0  0.0       0.707107  0.0

which is still a valid point on M and PowerManifold works with these, too.

An advantage of this representation is that it is quite efficient, especially when a HybridArray (from the HybridArrays.jl package) is used to represent a point on the power manifold. A disadvantage is not being able to easily identify parts of the multidimensional array that correspond to a single point on the base manifold. Another problem is, that accessing a single point is p[:, 1] which might be unintuitive.

For the NestedPowerRepresentation we can now do

using Manifolds
M = PowerManifold(Sphere(2), NestedPowerRepresentation(), 4)
p = [ [1.0, 0.0, 0.0],
      [1/sqrt(2.0), 1/sqrt(2.0), 0.0],
      [1/sqrt(2.0), 0.0, 1/sqrt(2.0)],
      [0.0, 1.0, 0.0],
    ]
4-element Array{Array{Float64,1},1}:
 [1.0, 0.0, 0.0]
 [0.7071067811865475, 0.7071067811865475, 0.0]
 [0.7071067811865475, 0.0, 0.7071067811865475]
 [0.0, 1.0, 0.0]

which is again a valid point so is_manifold_point(M, p) here also yields true. A disadvantage might be that with nested arrays one loses a little bit of performance. The data however is nicely encapsulated. Accessing the first data item is just p[1].

For accessing points on power manifolds in both representations you can use get_component and set_component! functions. They work work both point representations.

using Manifolds
M = PowerManifold(Sphere(2), NestedPowerRepresentation(), 4)
p = [ [1.0, 0.0, 0.0],
      [1/sqrt(2.0), 1/sqrt(2.0), 0.0],
      [1/sqrt(2.0), 0.0, 1/sqrt(2.0)],
      [0.0, 1.0, 0.0],
    ]
set_component!(M, p, [0.0, 0.0, 1.0], 4)
get_component(M, p, 4)
3-element view(::Array{Float64,1}, :) with eltype Float64:
 0.0
 0.0
 1.0

Types and Functions

Manifolds.ArrayPowerRepresentationType
ArrayPowerRepresentation

Representation of points and tangent vectors on a power manifold using multidimensional arrays where first dimensions are equal to representation_size of the wrapped manifold and the following ones are equal to the number of elements in each direction.

Torus uses this representation.

Manifolds.InversePowerRetractionType
InversePowerRetraction{TR<:AbstractInverseRetractionMethod} <: AbstractInverseRetractionMethod

The InversePowerRetraction avoids ambiguities between dispatching on the AbstractPowerManifold and dispatching on the AbstractInverseRetractionMethod and encapsulates this. This container should only be used in rare cases outside of this package. Usually a subtype of the AbstractPowerManifold should define a way how to treat its AbstractRetractionMethods.

Constructor

InversePowerRetraction(inverse_retractions::AbstractInverseRetractionMethod...)
Manifolds.PowerFVectorDistributionType
PowerFVectorDistribution([type::VectorBundleFibers], [x], distr)

Generates a random vector at a point from vector space (a fiber of a tangent bundle) of type type using the power distribution of distr.

Vector space type and point can be automatically inferred from distribution distr.

Manifolds.PowerManifoldType
PowerManifold{𝔽,TM<:Manifold,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. Operations on small power manifolds might be faster if they are represented as ProductManifold.

Constructor

PowerManifold(M, N_1, N_2, ..., N_d)
PowerManifold(M, 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, the ArrayPowerRepresentation of points and tangent vectors is used, although a different one, for example NestedPowerRepresentation, can be given as the second argument to the constructor. When M is a PowerManifold (not any AbstractPowerManifold) itself, given dimensions will be appended to the dimensions already present, for example PowerManifold(PowerManifold(Sphere(2), 2), 3) is equivalent to PowerManifold(Sphere(2), 2, 3). This feature preserves the representation of the inner power manifold (unless it's explicitly overridden). If you specify NestedPowerRepresentation(), the sizes are not concatenated but you end up with a nested power manifold within a power manifold.

Manifolds.PowerRetractionType
PowerRetraction{TR<:AbstractRetractionMethod} <: AbstractRetractionMethod

The PowerRetraction avoids ambiguities between dispatching on the AbstractPowerManifold and dispatching on the AbstractRetractionMethod and encapsulates this. This container should only be used in rare cases outside of this package. Usually a subtype of the AbstractPowerManifold should define a way how to treat its AbstractRetractionMethods.

Constructor

PowerRetraction(retraction::AbstractRetractionMethod)
Manifolds.PowerVectorTransportType
PowerVectorTransport{TR<:AbstractVectorTransportMethod} <:
   AbstractVectorTransportMethod

The PowerVectorTransport avoids ambiguities between dispatching on the AbstractPowerManifold and dispatching on the AbstractVectorTransportMethod and encapsulates this. This container should only be used in rare cases outside of this package. Usually a subtype of the AbstractPowerManifold should define a way how to treat its AbstractVectorTransportMethods.

Constructor

PowerVectorTransport(method::AbstractVectorTransportMethod)
Base.expMethod
exp(M::AbstractPowerManifold, p, X)

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

Base.getindexMethod
getindex(p, M::AbstractPowerManifold, i::Union{Integer,Colon,AbstractVector}...)
p[M::AbstractPowerManifold, i...]

Access the element(s) at index [i...] of a point p on an AbstractPowerManifoldM by linear or multidimensional indexing. See also Array Indexing in Julia.

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

Compute the logarithmic map from p to q on the AbstractPowerManifoldM, which can be computed using the base manifolds logarithmic map elementwise.

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 AbstractPowerManifoldM by linear or multidimensional indexing to q. See also Array Indexing in Julia.

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 AbstractPowerManifoldM by linear or multidimensional indexing.

LinearAlgebra.normMethod
norm(M::AbstractPowerManifold, p, X)

Compute the norm of X from the tangent space of p on an AbstractPowerManifoldM, i.e. from the element wise norms the Frobenius norm is computed.

Manifolds.flatMethod
flat(M::AbstractPowerManifold, p, X::FVector{TangentSpaceType})

use the musical isomorphism to transform the tangent vector X from the tangent space at p on an AbstractPowerManifoldM to a cotangent vector. This can be done elementwise for each entry of X (and p).

Manifolds.sharpMethod
sharp(M::AbstractPowerManifold, p, ξ::FVector{CotangentSpaceType})

Use the musical isomorphism to transform the cotangent vector ξ from the tangent space at p on an AbstractPowerManifoldM to a tangent vector. This can be done elementwise for every entry of ξ (and p).

ManifoldsBase.check_manifold_pointMethod
check_manifold_point(M::AbstractProductManifold, p; kwargs...)

Check whether p is a valid point on an AbstractPowerManifoldM, 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....

ManifoldsBase.check_tangent_vectorMethod
check_tangent_vector(M::AbstractPowerManifold, p, X; check_base_point = true, kwargs... )

Check whether X is a tangent vector to p an the AbstractPowerManifoldM, i.e. atfer check_manifold_point(M, p), and all projections to base manifolds must be respective tangent vectors. The optional parameter check_base_point indicates, whether to call check_manifold_point for p. 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....

ManifoldsBase.injectivity_radiusMethod
injectivity_radius(M::AbstractPowerManifold[, p])

the injectivity radius on an AbstractPowerManifold is for the global case equal to the one of its base manifold. For a given point p it's equal to the minimum of all radii in the array entries.

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

Compute the inner product of X and Y from the tangent space at p on an AbstractPowerManifoldM, 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.

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

Compute the inverse retraction from p with respect to q on an AbstractPowerManifoldM using an InversePowerRetraction, which by default encapsulates a inverse retraction of the base manifold. Then this method is performed elementwise, so the encapsulated inverse retraction method has to be one that is available on the base Manifold.

ManifoldsBase.manifold_dimensionMethod
manifold_dimension(M::PowerManifold)

Returns the manifold-dimension of an PowerManifoldM$=\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).\]

ManifoldsBase.retractMethod
retract(M::AbstractPowerManifold, p, X, method::PowerRetraction)

Compute the retraction from p with tangent vector X on an AbstractPowerManifoldM using a PowerRetraction, which by default encapsulates a retraction of the base manifold. Then this method is performed elementwise, so the encapsulated retraction method has to be one that is available on the base Manifold.

ManifoldsBase.vector_transport_toMethod
vector_transport_to(M::AbstractPowerManifold, p, X, q, method::PowerVectorTransport)

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