A Decorator for manifolds
Several properties of a manifold are often implicitly assumed, for example the choice of the (Riemannian) metric or the embedding. The latter shall serve as an example how to either implicitly or explicitly specify the embedding to avoid re-implementations and/or distinguish different embeddings.
The abstract decorator
When first implementing a manifold, it might be beneficial to dispatch certain computations to already existing manifolds. For an embedded manifold that is isometrically embedded this might be the inner the manifold inherits in each tangent space from its embedding.
This means we would like to dispatch the default implementation of a function to some other manifold. We refer to this as implicit decoration, since one can not “see” explicitly that a certain manifold inherits this property. As an example consider the Sphere. At each point the tangent space can be identified with a subspace of the tangent space in the embedding, the Euclidean manifold which the unit vectors of the sphere belong to. Thus every tangent space inherits its metric from the embedding. Since in the default implementation in Manifolds.jl points are represented by unit vectors and tangent vectors at a point as vectors orthogonal to that point, we can just dispatch the inner product to the embedding without having to re-implement this. The manifold using such an implicit dispatch just has to be a subtype of AbstractDecoratorManifold.
Traits with an inheritance hierarchy
The properties mentioned above might form a hierarchy. For embedded manifolds, again, we might have just a manifold whose points are represented in some embedding. If the manifold is even isometrically embedded, it is embedded but also inherits the Riemannian metric by restricting the metric from the embedding to the corresponding tangent space under consideration. But it also inherits the functions defined for the plain embedding, for example checking some conditions for the validity of points and vectors. If it is even a submanifold, also further functions are inherited like the shortest_geodesic.
We use a variation of Tim Holy's Traits Trick (THTT) which takes into account kind of traits.
To be precise we have a generic AbstractForwardingType to indicate that on the decorator manifold we want to (or not want to) forward a certain function. To add more semantics one can use subtypes of this type like AbstractEmbeddedForwardingType to indicate how to forward certain functions for the embedding type.
ManifoldsBase.AbstractDecoratorManifold — TypeAbstractDecoratorManifold{𝔽} <: AbstractManifold{𝔽}Declare a manifold to be an abstract decorator. A manifold which is a subtype of is a decorated manifold, i.e. has
- certain additional properties or
- delegates certain properties to other manifolds.
Most prominently, a manifold might be an embedded manifold, i.e. points on a manifold $\mathcal M$ are represented by (some, maybe not all) points on another manifold $\mathcal N$. Depending on the type of embedding, several functions are dedicated to the embedding. For example if the embedding is isometric, then the inner does not have to be implemented for $\mathcal M$ but can be automatically implemented by deligation to $\mathcal N$.
This is modelled by the AbstractDecoratorManifold and traits. These are mapped to functions, which determine the types of transparencies.
The Manifold decorator
The idea of the decorator for a manifold is to allow to exchange certain functionality by a dispatch layer. For example that for an embedded manifold some functions are passed to the embedding, or that for a metric manifold decorator, all functions unrelated to the metric are passed to the original manifold. The following types, functions, and macros introduce the decorator trait which allows to decorate an arbitrary <:AbstractDecoratorManifold with further features.
ManifoldsBase.AbstractEmbeddedForwardingType — TypeAbstractEmbeddedForwardingTypeAn abstract type to specify the forwarding behaviour of a function when it should forward to the embedding of a manifold.
ManifoldsBase.AbstractEmbeddingDirectness — Typeabstract type AbstractEmbeddingDirectness endSupertype for DirectEmbedding and IndirectEmbedding that indicate whether embed on a manifold is an identity or not.
ManifoldsBase.AbstractEmbeddingType — TypeAbstractEmbeddingTypeWithin all AbstractEmbeddedForwardingTypes this type is used to indicate different kinds of embeddings, for example the default fallback that NotEmbeddedManifoldType a manifold is not embedded, that is is embedded using EmbeddedManifoldType or even specifying further that it is isometrically embedded using IsometricallyEmbeddedManifoldType or as furthermore a submanifold using EmbeddedSubmanifoldType.
ManifoldsBase.AbstractForwardingType — TypeAbstractForwardingTypeAn abstract type to specify the forwarding behaviour of a function for a decorator manifold or a trait within ManifoldsBase.jl.
ManifoldsBase.DirectEmbedding — Typestruct DirectEmbedding <: AbstractEmbeddingDirectness endA struct indicating that embed is an identity function on a manifold.
ManifoldsBase.EmbeddedForwardingType — TypeEmbeddedForwardingType{TED<:AbstractEmbeddingDirectness} <: AbstractEmbeddedForwardingTypeA property of an embedded manifold that indicates that embed and project are available and that a function using this trait type forwards to the embedding. The type parameter TED, a subtype of AbstractEmbeddingDirectness, indicates whether embed on points and tangent vectors needs to be called or is an identity and can be skipped.
ManifoldsBase.EmbeddedManifoldType — TypeEmbeddedManifoldType <: AbstractEmbeddingTypeA property of an embedded manifold that indicates that embed and project are available.
ManifoldsBase.EmbeddedSubmanifoldType — TypeEmbeddedSubmanifoldType <: AbstractEmbeddingTypeA property to determine whether an AbstractDecoratorManifold M is an embedded submanifold. It is a special case of the IsometricallyEmbeddedManifoldType property, i.e. it has all properties of this property.
In this property, additionally to the isometric embedded manifold, all retractions, inverse retractions, and vectors transports, especially exp, log, and parallel_transport_to are passed to the embedding.
ManifoldsBase.IndirectEmbedding — Typestruct IndirectEmbedding <: AbstractEmbeddingDirectness endA struct indicating that embed is not an identity function on a manifold.
ManifoldsBase.IsometricallyEmbeddedManifoldType — TypeIsometricallyEmbeddedManifold <: AbstractEmbeddingTypeA property to determine whether an AbstractDecoratorManifold M is an isometrically embedded manifold.
Here, additionally, metric related functions like inner and norm are passed to the embedding
ManifoldsBase.NotEmbeddedManifoldType — TypeNotEmbeddedManifoldType <: AbstractEmbeddingTypeA property of an embedded manifold that indicates that embed and project are not available.
ManifoldsBase.SimpleForwardingType — TypeSimpleForwardingType <: AbstractForwardingTypeA type that indicates forwarding to the wrapped manifold without any changes.
ManifoldsBase.StopForwardingType — TypeStopForwardingType <: AbstractForwardingTypeA type that indicates that a function should not forward to a certain other manifold, e.g. and embedding. This means that the user is asked to implement this function themselfes.
ManifoldsBase.decorated_manifold — Methoddecorated_manifold(M::AbstractDecoratorManifold)For a manifold M that is decorated with some properties, this function returns the manifold without that manifold, i.e. the manifold that was decorated.
ManifoldsBase.get_embedding — Methodget_embedding(M::AbstractDecoratorManifold)
get_embedding(M::AbstractDecoratorManifold, p)Specify the embedding of a manifold that has abstract decorators. the embedding might depend on a point representation, where different point representations are distinguished as subtypes of AbstractManifoldPoint. A unique or default representation might also just be an AbstractArray.
ManifoldsBase.get_embedding_type — Methodget_embedding_type(M::AbstractManifold)
get_embedding_type(M::AbstractManifold, p)Get embedding type of AbstractManifold M. The returned value is an object of a subtype of AbstractEmbeddingType, either of:
NotEmbeddedManifoldType(default),EmbeddedManifoldType,IsometricallyEmbeddedManifoldType,EmbeddedSubmanifoldType.
Point p can be optionally specified if different point types correspond to different embeddings.
ManifoldsBase.get_forwarding_type — Methodget_forwarding_type(M::AbstractManifold, f)
get_forwarding_type(M::AbstractManifold, f, p)Get the type of forwarding to manifold wrapped by AbstractManifold M, for function f. The returned value is an object of a subtype of AbstractForwardingType.
Point p can be optionally specified if different point types correspond to different representations of the manifold and hence possibly different embeddings.
For an example see the (implicit) embedded manifold.