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.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.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.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.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.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).