Pymanopt: gradient descent on Riemannian manifolds in Python
Python toolbox for optimization on Riemannian manifolds with support for automatic differentiation
At a glance
- What is it?
- Pymanopt is a Python toolbox for optimization over Riemannian manifolds, where the constraints of the problem live in the geometry of the search space rather than in penalty terms, and it supports automatic differentiation through autograd, JAX, TensorFlow or PyTorch. It is a stable release under the 3-clause BSD licence with a peer reviewed JMLR paper behind it.
- Who is it for?
- Adopt Pymanopt when your optimisation problem has a geometric structure, such as a rotation, a symmetric matrix or a probability simplex, because solving it in the manifold geometry avoids the projection and penalty machinery that unconstrained solvers need on the same problem. Do not adopt it for a plain unconstrained problem, where SciPy solvers are simpler and better tested for the job.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 8 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.
Star history
- pymanopt/pymanopt914 ★ · +1
| Repository | 2026-10-23 | 2026-11-07 |
|---|---|---|
| pymanopt/pymanopt | 913 | 914 |
1 Stars in the last 15 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
What a manifold toolbox changes about the problem
Pymanopt is described as a Python toolbox for optimization on Riemannian manifolds with support for automatic differentiation, and the phrase carries most of the meaning.
Many optimisation problems in science are really geometric problems wearing a Euclidean disguise. A rotation matrix is not a matrix like any other, a symmetric positive definite matrix lives on a cone, and a probability vector lives on a simplex. If you hand any of these to an unconstrained solver and then project the result back, you get a slow, sometimes unreliable procedure that also depends on a projection step that may not even exist in closed form.
A manifold optimiser instead takes the geometry as given. The search space is the manifold, the update is a step along a geodesic, and the constraint is satisfied by construction rather than by penalty or projection.
The library is used for real tasks rather than for demonstrations. The examples directory in the repository covers PCA, dominant eigenvector, dominant invariant subspace and dominant invariant complex subspace, optimal rotations, packing on the sphere, multiple linear regression, low rank matrix approximation, low rank positive semidefinite matrix approximation, rank-k correlation matrix approximation, closest unit norm column approximation, and there is a notebooks/ directory and an advanced/ subdirectory.
That list is the best introduction to what the toolbox is for, because each of those problems has a natural manifold formulation and an awkward Euclidean one.
Automatic differentiation across four backends
The automatic differentiation support is the feature that shapes the whole API, and it is implemented as optional dependencies rather than a hard requirement.
Four backends are offered as extras. The autograd extra requires autograd 1.2 or newer, the jax extra requires jax 0.2.0 or newer together with jaxlib, the tensorflow extra requires TensorFlow 2.0.0 or newer, and the torch extra requires torch 1.0.0 or newer. There is also a backends extra which is simply the package asking for all four.
That structure matters for installation. You install only the framework you already use, and the library picks it up. A user with autograd and a user with PyTorch write the same solver code and get gradients from their own framework, which means the derivative is computed by machinery they already trust and already have debugged.
The core dependencies are deliberately minimal: numpy 2 or newer but below 3, scipy 1.13 or newer but below 2, and packaging. So the base install is small, and the automatic differentiation machinery is opt-in.
The project asks you to refer to the documentation and to a JMLR paper to get started. The paper angle matters: this is a toolbox with a peer reviewed description of its algorithms, and for a numerical library that is a meaningful quality signal, since the solver behaviour is documented in the literature rather than only in the source.
Packaging and the constraints it puts on you
The project file describes a package that is actively maintained and constrained on purpose.
Python is the first constraint. The requires-python field is greater than or equal to 3.11 and below 3.16, and the classifiers list 3.11 through 3.14. So the floor is 3.11 and the ceiling is 3.16, and the classifiers confirm that testing covers up to 3.14.
The build system uses pip 26.2, setuptools 66.1.0 or newer and setuptools-scm with the toml extra, which is the standard way to derive a version number from git tags rather than maintaining it by hand. The version field is listed as dynamic in the project table, which confirms that setuptools-scm is what fills it in.
The licence is the 3-clause BSD, recorded both as text in the project table and as the OSI approved BSD classifier, and the README states the same. The maintainers are Jamie Townsend, Niklas Koep and Sebastian Weichwald.
There is a uv.lock in the repository root, which tells you the project has been developed with uv for reproducible environment resolution, and a .pre-commit-config.yaml for commit time checks.
For a scientific library the development extras show the same care. pytest is pinned at 9.1.1 with pytest-cov at 7.1.0, and there is a separate ci extra pinning the build tooling versions, so a CI run is reproducible rather than tracking the latest release of everything.
The example set as a reading order
The examples directory is the most useful part of the repository for learning, and it is organised so that you can work through it without reading the API docs first.
There is a helper module, examples/_tools.py, that the example scripts share, and an advanced/ subdirectory for the harder cases. The notebooks/ directory holds notebook versions of the geometry, which is the format most people will actually work in.
The individual scripts map cleanly onto the problems. pca.py is the canonical introductory example, since principal component analysis is a projection onto a subspace and therefore a manifold problem in its natural formulation. dominant_eigenvector.py is the same structure with a nonlinear constraint on the eigenvector norm. The two dominant invariant subspace examples, one real and one complex, and dominant_invariant_complex_subspace.py cover the harder versions where the constraint is a subspace rather than a direction. optimal_rotations.py and packing_on_the sphere are the rotation cases, which is where the exponential and logarithm maps really earn their keep.
The low rank family, low rank matrix approximation, low rank positive semidefinite matrix approximation, rank-k correlation matrix approximation and closest unit norm column approximation, all live in the same family of problems and differ only in which structure the matrix is assumed to have.
multiple_linear_regression.py is the one to look at if you want to see how a manifold problem can be framed as least squares on a Stiefel manifold, and it is the closest of the set to a supervised learning task.
What the solver actually needs from a manifold
The design consequence of the whole approach is that a manifold has to provide certain operations, and this is where a user gets either an easy win or a real project.
To take a step on a manifold you need to move a point along the manifold, which means the exponential map. To express the difference between two points as a tangent vector you need the logarithm map. Beyond those two, a manifold typically supplies the tangent space projection and the inner product, and the inner product choice determines which notion of distance the optimiser follows, so two valid implementations of the same manifold can produce different paths.
If the manifold you need is already implemented, this work is done for you. If it is not, you are writing at least the exponential and logarithm maps, and getting the logarithm right is the hard part, because it involves a local inverse of a map that is only defined up to the cut locus.
The project makes this an explicit extension point. The contributing guide is referenced for people who wish to extend Pymanopt's functionality, and the TODO.md file at the repository root tracks the planned work, which usually gives you a sense of which manifolds are missing and therefore whether you should wait or implement one yourself.
The examples are the reference implementations in practice, since they show the interface a manifold has to satisfy and they are runnable rather than merely documented.
Project state, community and what to expect
The version history is steady rather than fast. The listed releases are 2.2.1 from 2024-09-20, 2.2.0 from 2023-09-12 and 2.1.1 from 2023-01-02, so roughly one minor release a year with the occasional patch.
The repository is not archived and the last push was on 2026-10-19, so work continues between releases, and the version on PyPI is what most people will actually install. The project is classified as development status 5, production or stable, and intended audience is science and research.
The project publishes a Zenodo DOI badge, which is the mechanism for citing a software package with a version, and it points to the JMLR paper as the primary reference for the algorithms. The MAINTAINERS and CONTRIBUTORS files are at the repository root.
Support runs through GitHub issues and a Gitter chat room, and the README asks people to report problems, request features, ask for help or leave general comments on either. That is a small project community rather than a large one, so if you hit an edge case in an obscure manifold, expect to be the person who works it out.
Quality signals are visible in the badges: a build status workflow, coverage through Coveralls, a Codacy grade, and CodeQL analysis. There is also a quickstart.py at the repository root, which is a quick way to confirm that the install works before you dig into the examples.
Editorial conclusion
Adopt Pymanopt when your optimisation problem has a geometric structure, such as a rotation, a symmetric matrix or a probability simplex, because solving it in the manifold geometry avoids the projection and penalty machinery that unconstrained solvers need on the same problem. Do not adopt it for a plain unconstrained problem, where SciPy solvers are simpler and better tested for the job. Verify first that you are on Python 3.11 to 3.15, since the package pins that range, that you install the automatic differentiation backend you actually want rather than the aggregate backends extra, and that the manifold you need exists or that you are prepared to implement its exponential and logarithm maps, since those two functions are what the solver actually calls.
Frequently asked questions
What is Pymanopt used for?
Optimization on Riemannian manifolds, where the problem constraints live in the geometry of the search space rather than in penalty terms. The examples cover PCA, dominant eigenvectors, invariant subspaces, optimal rotations, packing on the sphere, multiple linear regression and several low rank matrix approximation problems.
Which automatic differentiation backends does Pymanopt support?
Four, each as an optional dependency: autograd 1.2 or newer, jax 0.2.0 or newer with jaxlib, TensorFlow 2.0.0 or newer, and torch 1.0.0 or newer. There is also a backends extra that installs all four, and the core install only needs numpy, scipy and packaging.
Which Python versions does Pymanopt support?
The project file requires Python greater than or equal to 3.11 and below 3.16, with classifiers for 3.11, 3.12, 3.13 and 3.14. The build uses setuptools-scm, so the version number is derived from git tags rather than maintained by hand.
How do I add a new manifold to Pymanopt?
You supply the geometric operations the solver calls, at minimum the exponential map for stepping along the manifold and the logarithm map for expressing differences as tangent vectors, together with the tangent projection and the inner product. The contributing guide covers the extension process and the examples in the repository serve as reference implementations.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pymanopt-pymanopt)Star history chart for your README
[](https://hysenlabs.com/projects/pymanopt-pymanopt)Was this useful?