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.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
— TypeAbstractPowerRepresentation
An abstract representation type of points and tangent vectors on a power manifold.
Manifolds.ArrayPowerRepresentation
— TypeArrayPowerRepresentation
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.InversePowerRetraction
— TypeInversePowerRetraction{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 AbstractRetractionMethod
s.
Constructor
InversePowerRetraction(inverse_retractions::AbstractInverseRetractionMethod...)
Manifolds.NestedPowerRepresentation
— TypeNestedPowerRepresentation
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.
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). If you specify NestedPowerRepresentation()
, the sizes are not concatenated but you end up with a nested power manifold within a power manifold.
Manifolds.PowerMetric
— TypePowerMetric <: Metric
Represent 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{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 AbstractRetractionMethod
s.
Constructor
PowerRetraction(retraction::AbstractRetractionMethod)
Manifolds.PowerVectorTransport
— TypePowerVectorTransport{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 AbstractVectorTransportMethod
s.
Constructor
PowerVectorTransport(method::AbstractVectorTransportMethod)
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...] = 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.
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
\[\dim(\mathcal N) = \dim(\mathcal M)\prod_{i=1}^d n_i = n_1n_2\cdot…\cdot n_d \dim(\mathcal M).\]
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 X
at 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.