Retraction
A retraction is a computationally cheaper alternative to the exponential map for optimization on manifolds. It sacrifices the geodesic property but retains first-order accuracy; sufficient for gradient descent and line search.
Definition
A retraction on $M$ is a smooth map $R : TM \to M$ such that for each $p \in M$ the restriction $R_p : T_pM \to M$ satisfies:
- Consistency: $R_p(0) = p$
- Local rigidity:
Condition 2 means $R_p$ agrees with $\exp_p$ to first order at $p$.
The key implication: using $R$ instead of $\exp$ in Riemannian gradient descent preserves the convergence guarantees while cutting the per-step cost significantly (no transcendental function evaluations on most manifolds).
The Retraction Trait
pub trait Retraction: Manifold {
fn retract(&self, p: &Self::Point, v: &Self::Tangent) -> Self::Point;
fn inverse_retract(
&self,
p: &Self::Point,
q: &Self::Point,
) -> Option<Self::Tangent>;
}Sphere<N>, Euclidean<N>, SO<N>, SE<N>, SPD<N>, Grassmann<N,K>Every type that implements Manifold automatically gets a blanket implementation
via exp/log, so you only need a custom impl when a cheaper retraction exists.
Blanket Implementation
// Provided automatically; no work needed.
impl<M: Manifold> Retraction for M {
fn retract(&self, p: &Self::Point, v: &Self::Tangent) -> Self::Point {
self.exp(p, v)
}
fn inverse_retract(&self, p: &Self::Point, q: &Self::Point) -> Option<Self::Tangent> {
self.log(p, q)
}
}Override this for manifolds where a cheaper retraction exists.
Example: Sphere Projection Retraction
On the projection retraction is:
This costs one vector addition and one normalization; no sin/cos calls.
Both return a point on $S^2$. The projection retraction drifts slightly from the true geodesic endpoint for large steps, but both satisfy the retraction axioms.
use cartan::prelude::*;
use cartan::manifolds::Sphere;
let s2 = Sphere::<3>;
let p = s2.random_point(&mut rand::rng());
let v = s2.random_tangent(&p, &mut rand::rng());
let q_exact = s2.exp(&p, &v); // exact geodesic
let q_retract = s2.retract(&p, &v); // projection (cheaper)
// Both lie on S²:
assert!((q_exact.norm() - 1.0).abs() < 1e-12);
assert!((q_retract.norm() - 1.0).abs() < 1e-12);
// They agree to first order near p:
let small_v = v * 0.001;
let q1 = s2.exp(&p, &small_v);
let q2 = s2.retract(&p, &small_v);
assert!((q1; q2).norm() < 1e-8);Inverse Retraction
inverse_retract(p, q) computes the tangent $v$ such that $R_p(v) = q$.
Returns None at the cut locus (same as log). Used by optimizers that need
to measure displacement in tangent space coordinates.
When to Use a Custom Retraction
| Manifold | Exp cost | Projection retraction cost |
|---|---|---|
| Sphere | sin, cos | normalize (1 sqrt) |
| SO(N) | matrix exponential $O(N^3)$ | QR decomposition $O(N^3)$, smaller constant |
| SPD(N) | symmetric matrix exp | Cholesky-based, cheaper constant |
| Euclidean | trivial | trivial (same as exp) |
For large-scale optimization (e.g. fitting a Fréchet mean over thousands of points), a 2× retraction speedup compounds over many gradient steps.