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.0which 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.0which 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.0Types and Functions
Manifolds.AbstractPowerManifold — TypeAbstractPowerManifold{𝔽,M,TPR} <: Manifold{𝔽}An abstract Manifold to represent manifolds that are build as powers of another Manifold M with representation type TPR, a subtype of AbstractPowerRepresentation.
Manifolds.AbstractPowerRepresentation — TypeAbstractPowerRepresentationAn abstract representation type of points and tangent vectors on a power manifold.
Manifolds.ArrayPowerRepresentation — TypeArrayPowerRepresentationRepresentation 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.InversePowerRetraction — TypeInversePowerRetraction(inverse_retractions::AbstractInverseRetractionMethod...)Power inverse retraction of inverse_retractions. Works on AbstractPowerManifolds.
Manifolds.NestedPowerRepresentation — TypeNestedPowerRepresentationRepresentation 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.
GraphManifold uses this representation.
Manifolds.PowerBasisData — TypePowerBasisData{TB<:AbstractArray}Data storage for an array of basis data.
Manifolds.PowerFVectorDistribution — TypePowerFVectorDistribution([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.PowerManifold — TypePowerManifold{𝔽,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).
Manifolds.PowerMetric — TypePowerMetric <: MetricRepresent the Metric on an AbstractPowerManifold, i.e. the inner product on the tangent space is the sum of the inner product of each elements tangent space of the power manifold.
Manifolds.PowerPointDistribution — TypePowerPointDistribution(M::AbstractPowerManifold, distribution)Power distribution on manifold M, based on distribution.
Manifolds.PowerRetraction — TypePowerRetraction(retraction::AbstractRetractionMethod)Power retraction based on retraction. Works on AbstractPowerManifolds.
Manifolds.PowerVectorTransport — TypePowerVectorTransport(method::AbstractVectorTransportMethod)Power vector transport method based on method. Works on AbstractPowerManifolds.
Base.exp — Methodexp(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.
Base.getindex — Methodgetindex(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 AbstractPowerManifold M by linear or multidimensional indexing. See also Array Indexing in Julia.
Base.log — Methodlog(M::AbstractPowerManifold, p, q)Compute the logarithmic map from p to q on the AbstractPowerManifold M, which can be computed using the base manifolds logarithmic map elementwise.
Base.setindex! — Methodsetindex!(q, p, M::AbstractPowerManifold, i::Union{Integer,Colon,AbstractVector}...)
q[M::AbstractPowerManifold, i...] = pSet 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.
Base.view — Methodview(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.
LinearAlgebra.norm — Methodnorm(M::AbstractPowerManifold, p, X)Compute the norm of X from the tangent space of p on an AbstractPowerManifold M, i.e. from the element wise norms the Frobenius norm is computed.
Manifolds.flat — Methodflat(M::AbstractPowerManifold, p, X::FVector{TangentSpaceType})use the musical isomorphism to transform the tangent vector X from the tangent space at p on an AbstractPowerManifold M to a cotangent vector. This can be done elementwise for each entry of X (and p).
Manifolds.get_component — Methodget_component(M::AbstractPowerManifold, p, idx...)Get the component of a point p on an AbstractPowerManifold M at index idx.
Manifolds.power_dimensions — Methodpower_dimensions(M::PowerManifold)return the power of M,
Manifolds.set_component! — Methodset_component!(M::AbstractPowerManifold, q, p, idx...)Set the component of a point q on an AbstractPowerManifold M at index idx to p, which itself is a point on the Manifold the power manifold is build on.
Manifolds.sharp — Methodsharp(M::AbstractPowerManifold, p, ξ::FVector{CotangentSpaceType})Use the musical isomorphism to transform the cotangent vector ξ from the tangent space at p on an AbstractPowerManifold M to a tangent vector. This can be done elementwise for every entry of ξ (and p).
ManifoldsBase.check_manifold_point — Methodcheck_manifold_point(M::AbstractProductManifold, 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....
ManifoldsBase.check_tangent_vector — Methodcheck_tangent_vector(M::AbstractPowerManifold, p, X; check_base_point = true, kwargs... )Check whether X is a tangent vector to p an the AbstractPowerManifold M, 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.distance — Methoddistance(M::AbstractPowerManifold, p, q)Compute the distance between q and p on an AbstractPowerManifold, i.e. from the element wise distances the Forbenius norm is computed.
ManifoldsBase.injectivity_radius — Methodinjectivity_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.inner — Methodinner(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.
ManifoldsBase.inverse_retract — Methodinverse_retract(M::AbstractPowerManifold, p, q, m::InversePowerRetraction)Compute the inverse retraction from p with respect to q on an AbstractPowerManifold M 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_dimension — Methodmanifold_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
ManifoldsBase.project — Methodproject(M::AbstractPowerManifold, p, X)Project the point X onto the tangent space at p on the AbstractPowerManifold M by projecting all components.
ManifoldsBase.project — Methodproject(M::AbstractPowerManifold, p)Project the point p from the embedding onto the AbstractPowerManifold M by projecting all components.
ManifoldsBase.retract — Methodretract(M::AbstractPowerManifold, p, X, method::PowerRetraction)Compute the retraction from p with tangent vector X on an AbstractPowerManifold M 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_to — Methodvector_transport_to(M::AbstractPowerManifold, p, X, q, method::PowerVectorTransport)Compute the vector transport the tangent vector Xat p to q on the PowerManifold M using an PowerVectorTransport m. This method is performed elementwise, i.e. the method m has to be implemented on the base manifold.