# \[ANN\] ManifoldsBase.jl 1.0

**URL:** https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752
**Category:** Package Announcements
**Created:** [February 10, 2025, 3:45pm UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752 "2025-02-10T15:45:03Z")
**Posts on this page:** 18
**Page:** 1

<div class="post-metadata">

### Author: ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)
#### Post date: [February 10, 2025, 3:45pm UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/1 "2025-02-10T15:45:03Z")

</div>

ManifoldsBase.jl is moving to a stable version 1.0

A few years back, we in [JuliaManifolds](https://github.com/JuliaManifolds) decided, that it would be nice to have a general interface package for the manifolds defined in Manifolds.jl, since that allows

- other packages to use manifolds purely based on a lightweight manifolds API
- other packages to define their own manifolds

Besides Manifolds.jl itself defining manifolds, from the start Manopt.jl was using abstract manifolds to define its optimisation algorithms.  
By now, there are more packages defining their own manifolds, for example the [ExponentialFamilyManifolds.jl](https://github.com/ReactiveBayes/ExponentialFamilyManifolds.jl)  
The API has grown into a very stable state with only one minor change to the exponential map and retractions in the version 1.0. This is mainly in preparation for a next forthcoming package, where we do require a slightly different signature as well. See [our changelog](https://github.com/JuliaManifolds/ManifoldsBase.jl/blob/master/NEWS.md#10-05022025) for a full explanation of the breaking changes.

We will still work on providing a broader interface for more fatures on manifolds covered in the API; still, the current state is considered so stable now, that we are happy to call this version ManifoldsBase.jl 1.0!

---

<div class="post-metadata">

### Author: ![BdeKoning](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bdekoning/32/214557_2.png) [@BdeKoning](https://discourse.julialang.org/u/BdeKoning)
#### Post date: [February 11, 2025, 8:25am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/2 "2025-02-11T08:25:58Z")

</div>

This is very cool! I took a course on differential geometry once but I didn’t think it would quickly become relevant for me again when I took the computational science specialisation afterwards.

What sort of applications is this currently being used for? I suppose General Relativity?

---

<div class="post-metadata">

### Author: ![mateuszbaran](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mateuszbaran/32/221842_2.png) [@mateuszbaran](https://discourse.julialang.org/u/mateuszbaran)
#### Post date: [February 11, 2025, 8:41am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/3 "2025-02-11T08:41:57Z")

</div>

Actually manifolds are a very neat way to describe any structure of continuous data, especially constraints. We can then do optimization and statistics on such data. As a more concrete example, it’s frequently used in robotics and anything that deals with modelling orientations (special orthogonal and special Euclidean groups). Also, subspaces of vector spaces form neat manifolds (Stiefel, Grassman and flag). They are very relevant in statistical modelling.

We don’t do general relativity right now. We are trying to do as much as possible without coordinates, which doesn’t work for GR but is great in other applications. For me working with manifolds is just respecting structure of your data in a very broad sense and not necessarily dealing with curvature (though it’s one of the problems the approach addresses).

---

<div class="post-metadata">

### Author: ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)
#### Post date: [February 11, 2025, 8:42am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/4 "2025-02-11T08:42:34Z")

</div>

My personal main interest is developing optimization algorithm on arbitrary manifolds (see Manopt.jl), which might be beneficial whenever you have a problem naturally defined on a manifold, often a [Sphere](https://juliamanifolds.github.io/Manifolds.jl/stable/manifolds/sphere/), a [Stiefel](https://juliamanifolds.github.io/Manifolds.jl/stable/manifolds/stiefel/) or [Grassmann](https://juliamanifolds.github.io/Manifolds.jl/stable/manifolds/grassmann/) manifold. for these works I do not necessarily directly have an application in mind.  
A main focus I do my research on is the case where the objective you aim to minimise is non smooth, so we do not have a gradient but maybe a sub gradient.

Of course with [Hyperbloic](https://juliamanifolds.github.io/Manifolds.jl/stable/manifolds/hyperbolic/) space anything related to general relativity is also possible, the main areas I have seen (though not yet worked un much) are Model order reduction, especially Hamiltonian systems and the [symplectic Stiefel](https://juliamanifolds.github.io/Manifolds.jl/stable/manifolds/symplecticstiefel/) manifold, but also Density Function theory (cf. DFTK.jl) as problems on Stiefel manifolds,… but to be honest I personally am maybe not the most applied person for that.

If you have applications we are surely interested to help how manifolds can help – for example defining Bézier curves on manifolds is one of our examples, cf. [🚀 Get Started with Manifolds.jl · Manifolds.jl](https://juliamanifolds.github.io/Manifolds.jl/stable/tutorials/getstarted/#Implementing-generic-Functions), which I came to when then even optimising its control points (with respect to a certain objective)

---

<div class="post-metadata">

### Author: ![BdeKoning](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bdekoning/32/214557_2.png) [@BdeKoning](https://discourse.julialang.org/u/BdeKoning)
#### Post date: [February 11, 2025, 8:49am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/5 "2025-02-11T08:49:02Z")

</div>

@kellertuer @mateuszbaran thank you both for your elaborate replies 🙂 I personally am interested in splines and related geometric objects (see my recent package SplineGrids.jl), so if you see possibilities for collaboration there I would love to hear it

---

<div class="post-metadata">

### Author: ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)
#### Post date: [February 11, 2025, 8:53am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/6 "2025-02-11T08:53:50Z")

</div>

Nice! I worked a bit with Bézier curves on manifolds, but also before with (Euclidean) splines in my masters.

As in the linkes example – one can easily generalise e.g. Casteljau’s algorithm to arbitrary manifolds and hence smoothly interpolate data in Hyperbolic space. I know a few works that even try that for multivariate data on grids, but then the tangent spaces and requirements become a bit tricky (cf. [https://epubs.siam.org/doi/10.1137/16M1057978](https://epubs.siam.org/doi/10.1137/16M1057978)). But sure, one could in theory combine manifolds and Splines/Bézier curves.

---

<div class="post-metadata">

### Author: ![RoyiAvital](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/royiavital/32/571_2.png) [@RoyiAvital](https://discourse.julialang.org/u/RoyiAvital)
#### Post date: [February 17, 2025, 5:25pm UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/7 "2025-02-17T17:25:52Z")

</div>

Applications wise, I thought about the application of estimating the Fundamental / Homography matrix.

The problem is given by:

\arg \min\_{\boldsymbol{F}} \sum\_{i} \boldsymbol{x}\_{i}^{T} \boldsymbol{F} \boldsymbol{y}\_{i} \; \text{ subject to } \operatorname{rank} \left( \boldsymbol{F} \right) = 2

Where \boldsymbol{F} \in \mathbb{R}^{3 \times 3}.

I wonder if there is a manifold which forces the rank.  
Could one solve using the current state of the packages?

---

<div class="post-metadata">

### Author: ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)
#### Post date: [February 17, 2025, 6:34pm UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/8 "2025-02-17T18:34:30Z")

</div>

Sure! (Not only with the interface for sure but) We do have the

> **[Fixed-rank matrices · Manifolds.jl](https://juliamanifolds.github.io/Manifolds.jl/stable/manifolds/fixedrankmatrices/)**
>
> Documentation for Manifolds.jl.

in Manifolds.jl. There are even retractions and inverse retractions available as well as gradient and hessian conversions. So (not having tried it but)

- just defining your cost, you could use any derivative-free algorithm from Manopt.jl, but I would recommend
- defining your Euclidean gradient and use [Define objectives in the embedding · Manopt.jl](https://manoptjl.org/stable/tutorials/EmbeddingObjectives/) to convert it – and then run your favourite first-order method; gradient descent or CG or L-BFGS, see the overview at [List of Solvers · Manopt.jl](https://manoptjl.org/stable/solvers/#First-order)

Note. The fixed rand manifold does not have exp/log defined, but the retractions are first-order approximations to that. Similarly parallel\_transport would be the exact mathematical way required for QN, but there is a vector transport that should be taken as an approximation of that automatically instead.

If you get stuck somewhere, maybe open a new topic here, or an issue in one of the packages 🙂

And if you know more about your matrix, for example that it is an orthonormal basis of a 2D subspace (a 3x2 matrix, excluding the one zero eigenspace basically, ±ONB) you can use the [Stiefel · Manifolds.jl](https://juliamanifolds.github.io/Manifolds.jl/stable/manifolds/stiefel/) even, which would be lower in dimension (if that is of interest).

---

<div class="post-metadata">

### Author: ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)
#### Post date: [October 9, 2025, 11:21am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/9 "2025-10-09T11:21:25Z")

</div>

We just released

**ManifoldsBase.jl 2.0**

this week. The major change is, that we reworked the internal traits system, which was previously a bit technical and lead to error messages that were hard to read (even for the developers).

So at JuliaCon 2025s hackathon we decided to rework this. We now have a simpler system of traits, that are used to indicate that a manifold is embedded or which metric it has.

In practice, if you are _using_ manifolds, e.g. like Manopt.jl does, there should be no breaking changes.  
If you _define_ your own manifolds, the overall scheme is now more consistent between metrics, embeddings, maybe even with different embedding types, connections as decorators of a manifold. The one breaking change is possibly to remove the definition of the `active_traits` function.

---

<div class="post-metadata">

### Author: ![fastwave](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fastwave/32/14725_2.png) [@fastwave](https://discourse.julialang.org/u/fastwave)
#### Post date: [October 31, 2025, 11:05am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/10 "2025-10-31T11:05:25Z")

</div>

I’ve tried just removing `active_traits` from my manifolds but then I get lots of undefined or ambiguous function errors. I really do not want to reimplement, when they have worked before? Is there a way to get the same functionality back?

---

<div class="post-metadata">

### Author: ![fastwave](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fastwave/32/14725_2.png) [@fastwave](https://discourse.julialang.org/u/fastwave)
#### Post date: [October 31, 2025, 11:28am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/11 "2025-10-31T11:28:22Z")

</div>

`project!` does not seem to exist anymore for `PowerManifold`?

---

<div class="post-metadata">

### Author: ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)
#### Post date: [October 31, 2025, 11:28am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/12 "2025-10-31T11:28:30Z")

</div>

Hi,  
the active traits were a complicated trait system causing long complicated error messages. That system has been replaced by a simpler system of just a single trait (instead of a whole list).

Usually, all old functionality should be still available completely the same way as before. So I would need a concrete example where and when which kind of code is failing. Note also that a few manifolds have changed their order of parameters, since we unified that to have F first everywhere now.  
But there should not be any regression in funcvtionality. You can also check what we changed in Manifolds.jl when moving from ManifoldsBase 1.0 to 2.0, usually only a few lines.

---

<div class="post-metadata">

### Author: ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)
#### Post date: [October 31, 2025, 11:30am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/13 "2025-10-31T11:30:59Z")

</div>

> [@fastwave](#):
>
> `project!` does not seem to exist anymore for `PowerManifold`?

No, that should still exist, we did not remove it as far as I am aware. Please be more precise where and when what fails, otherwise it is super hard to help when I have to guess what yo might be trying to do?  
Are you implementing a manifold? are you using one?

For the update to ManifoldsBase.jl 2.0 for example this PR is just one manifold where you see differences that were done

> **[Merge pull request #38 from ReactiveBayes/try-to-update-to-manifoldba… ·...](https://github.com/ReactiveBayes/ExponentialFamilyManifolds.jl/commit/5b39a86fcd743586759d550fd4ea481cd7ebbd64)**
>
> …se-2
> 
> fix: try to update to ManifoldBase 2.0

---

<div class="post-metadata">

### Author: ![fastwave](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fastwave/32/14725_2.png) [@fastwave](https://discourse.julialang.org/u/fastwave)
#### Post date: [October 31, 2025, 11:59am UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/14 "2025-10-31T11:59:35Z")

</div>

Many thanks. This is my test case. Now that I look at it even `zero_vector` is missing.

```julia-auto
using ManifoldsBase, Manifolds

struct SkewFunction{m,k,𝔽} <: AbstractDecoratorManifold{𝔽}
    manifold::Euclidean
end

function SkewFunction(m::Int, k::Int; field::AbstractNumbers=ℝ)
    manifold = Euclidean(m, k, field=field)
    return SkewFunction{m,k,field}(manifold)
end

ManifoldsBase.decorated_manifold(M::SkewFunction) = M.manifold
# ManifoldsBase.active_traits(f, ::SkewFunction, args...) = ManifoldsBase.IsExplicitDecorator()

embed(::SkewFunction, p) = p
embed(::SkewFunction, p, X) = X

function get_embedding(M::SkewFunction)
    return M.manifold
end

function ManifoldsBase.get_embedding_type(::SkewFunction)
    return ManifoldsBase.SimpleForwardingType()
end

function Base.zero(M::Euclidean{T,𝔽}) where {T,𝔽}
    if 𝔽 == ℂ
        return zeros(ComplexF64, representation_size(M)...)
    else
        return zeros(representation_size(M)...)
    end
end

function Base.zero(M::SkewFunction)
    return zero(M.manifold)
end

MM = SkewFunction(5, 12)
pp = zero(MM)
XX = zero_vector(MM, pp)
YY = zero_vector(MM, pp)

project!(MM, YY, pp, XX)

```

---

<div class="post-metadata">

### Author: ![fastwave](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fastwave/32/14725_2.png) [@fastwave](https://discourse.julialang.org/u/fastwave)
#### Post date: [October 31, 2025, 12:13pm UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/15 "2025-10-31T12:13:06Z")

</div>

Made it work. Your example really helped.

```julia-auto
using ManifoldsBase, Manifolds

struct SkewFunction{m,k,𝔽} <: AbstractDecoratorManifold{𝔽}
    manifold::Euclidean
end

function SkewFunction(m::Int, k::Int; field::AbstractNumbers=ℝ)
    manifold = Euclidean(m, k, field=field)
    return SkewFunction{m,k,field}(manifold)
end

@inline ManifoldsBase.decorated_manifold(M::SkewFunction) = M.manifold

# Forward all functions by default to the decorated base manifold
@inline ManifoldsBase.get_forwarding_type(::SkewFunction, ::Any) = ManifoldsBase.SimpleForwardingType()
@inline ManifoldsBase.get_forwarding_type(::SkewFunction, ::Any, _) = ManifoldsBase.SimpleForwardingType()

function Base.zero(M::Euclidean{T,𝔽}) where {T,𝔽}
    if 𝔽 == ℂ
        return zeros(ComplexF64, representation_size(M)...)
    else
        return zeros(representation_size(M)...)
    end
end

function Base.zero(M::SkewFunction)
    return zero(M.manifold)
end

MM = SkewFunction(5, 12)
pp = zero(MM)
XX = zero_vector(MM, pp)
YY = zero_vector(MM, pp)

project!(MM, YY, pp, XX)

```

---

<div class="post-metadata">

### Author: ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)
#### Post date: [October 31, 2025, 12:45pm UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/16 "2025-10-31T12:45:47Z")

</div>

Nice. Yes the active traits (since now there is only one trait) is discontinues and we decide “where to forward” things to based on the new function `get_forwarding_type`

I am a bit surprised by your `zero` function, especially it is heavy type piracy if you define that for `Eclidean`. I would kindly ask you to not do that. If so, overwrite `zero_vector` (or `zero_vector!`) for you manifold.

---

<div class="post-metadata">

### Author: ![fastwave](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fastwave/32/14725_2.png) [@fastwave](https://discourse.julialang.org/u/fastwave)
#### Post date: [October 31, 2025, 12:55pm UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/17 "2025-10-31T12:55:15Z")

</div>

Sort of agree about `zero` function. In general, manifolds have no zero element, and I believe that is why you do not define one. I however need a default ‘zero’ to initialise the optimisation. I suppose, I should have used a different name, such as `default_point`. This is different from a zero tangent vector, for which there is `zero_vector`. Will think about it…

---

<div class="post-metadata">

### Author: ![kellertuer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kellertuer/32/220707_2.png) [@kellertuer](https://discourse.julialang.org/u/kellertuer)
#### Post date: [October 31, 2025, 12:57pm UTC](https://discourse.julialang.org/t/ann-manifoldsbase-jl-1-0/125752/18 "2025-10-31T12:57:55Z")

</div>

Well, type piracy (you neither “own” zero nor Euclidean) should not be committed. You could use the `TranslationGroup` from LieGroups.jl (which is nothing else that Euclidean with plus) and use its `identity_element`) - or come up with your own names of course.
