Gradient descent
Manopt.gradient_descent — Function
gradient_descent(M, f, grad_f, p=rand(M); kwargs...)
gradient_descent(M, gradient_objective, p=rand(M); kwargs...)
gradient_descent!(M, f, grad_f, p; kwargs...)
gradient_descent!(M, gradient_objective, p; kwargs...)perform the gradient descent algorithm
\[p_{k+1} = \operatorname{retr}_{p_k}\bigl( -s_k\operatorname{grad}f(p_k) \bigr), \qquad k=0,1,…\]
where $s_k > 0$ denotes a step size.
The algorithm can be performed in-place of p.
Input
M::AbstractManifold: a Riemannian manifold $\mathcal{M}$f: a cost function $f: \mathcal{M}→ ℝ$ implemented as(M, p) -> vgrad_f: the (Riemannian) gradient $\operatorname{grad}f: \mathcal{M} → T\mathcal{M}$ of f as a function(M, p) -> Xor a function(M, X, p) -> XcomputingXin-placep::P: a point on the manifold $\mathcal{M}$
Alternatively to f and grad_f you can provide the corresponding AbstractManifoldFirstOrderObjective gradient_objective directly.
Keyword arguments
callbacks::D = Dict{Symbol,Function}(): provided callback functions given either as a single function(symbol, problem, state, k)called in every hook or as a (vector of) pairs:hook => function, which are processed byprocess_callbacks_arg. As key you can either pass single symbol or an array of symbols to indicate a callback should be added in multiple placesdifferential = missing: specify a specific function to evaluate the differential. By default, $Df(p)[X] = ⟨\operatorname{grad}f(p),X⟩$ is useddirection=IdentityUpdateRule(): specify to perform a certain processing of the direction, for exampleNesterov,MomentumGradientorAverageGradient.evaluation::AbstractEvaluationType=AllocatingEvaluation(): specify whether the functions that return an array, for example a point or a tangent vector, work by allocating their result (AllocatingEvaluation) or whether they modify their input argument to return the result therein (InplaceEvaluation). Since usually the first argument is the manifold, the modified argument is the second. For examplegrad_f(M,p)allocates, butgrad_f!(M, X, p)computes the result in-place ofX.retraction_method::AbstractRetractionMethod=default_retraction_method(M, typeof(p)): a retraction $\operatorname{retr}$ to use, see the section on retractionsstepsize::Stepsize=default_stepsize(M,GradientDescentState; retraction_method=retraction_method): a functor inheriting fromStepsizeto determine a step sizestopping_criterion::StoppingCriterion=StopAfterIteration(200)|StopWhenGradientNormLess(1e-8): a functor indicating that the stopping criterion is fulfilledX::T =zero_vector(M, p): a tangent vector at the point $p$ on the manifold $\mathcal{M}$ storing the gradient at the current iterate
All other keyword arguments are passed to decorate_state! for state decorators or decorate_objective! for objective decorators, respectively.
If you provide the ManifoldFirstOrderObjective directly, the evaluation= keyword is ignored. The decorations are still applied to the objective.
If you activate tutorial mode (cf. is_tutorial_mode), this solver provides additional debug warnings.
Output
The obtained approximate minimizer $p^*$. To obtain the whole final state of the solver, see get_solver_return for details, especially the return_state= keyword.
Manopt.gradient_descent! — Function
gradient_descent(M, f, grad_f, p=rand(M); kwargs...)
gradient_descent(M, gradient_objective, p=rand(M); kwargs...)
gradient_descent!(M, f, grad_f, p; kwargs...)
gradient_descent!(M, gradient_objective, p; kwargs...)perform the gradient descent algorithm
\[p_{k+1} = \operatorname{retr}_{p_k}\bigl( -s_k\operatorname{grad}f(p_k) \bigr), \qquad k=0,1,…\]
where $s_k > 0$ denotes a step size.
The algorithm can be performed in-place of p.
Input
M::AbstractManifold: a Riemannian manifold $\mathcal{M}$f: a cost function $f: \mathcal{M}→ ℝ$ implemented as(M, p) -> vgrad_f: the (Riemannian) gradient $\operatorname{grad}f: \mathcal{M} → T\mathcal{M}$ of f as a function(M, p) -> Xor a function(M, X, p) -> XcomputingXin-placep::P: a point on the manifold $\mathcal{M}$
Alternatively to f and grad_f you can provide the corresponding AbstractManifoldFirstOrderObjective gradient_objective directly.
Keyword arguments
callbacks::D = Dict{Symbol,Function}(): provided callback functions given either as a single function(symbol, problem, state, k)called in every hook or as a (vector of) pairs:hook => function, which are processed byprocess_callbacks_arg. As key you can either pass single symbol or an array of symbols to indicate a callback should be added in multiple placesdifferential = missing: specify a specific function to evaluate the differential. By default, $Df(p)[X] = ⟨\operatorname{grad}f(p),X⟩$ is useddirection=IdentityUpdateRule(): specify to perform a certain processing of the direction, for exampleNesterov,MomentumGradientorAverageGradient.evaluation::AbstractEvaluationType=AllocatingEvaluation(): specify whether the functions that return an array, for example a point or a tangent vector, work by allocating their result (AllocatingEvaluation) or whether they modify their input argument to return the result therein (InplaceEvaluation). Since usually the first argument is the manifold, the modified argument is the second. For examplegrad_f(M,p)allocates, butgrad_f!(M, X, p)computes the result in-place ofX.retraction_method::AbstractRetractionMethod=default_retraction_method(M, typeof(p)): a retraction $\operatorname{retr}$ to use, see the section on retractionsstepsize::Stepsize=default_stepsize(M,GradientDescentState; retraction_method=retraction_method): a functor inheriting fromStepsizeto determine a step sizestopping_criterion::StoppingCriterion=StopAfterIteration(200)|StopWhenGradientNormLess(1e-8): a functor indicating that the stopping criterion is fulfilledX::T =zero_vector(M, p): a tangent vector at the point $p$ on the manifold $\mathcal{M}$ storing the gradient at the current iterate
All other keyword arguments are passed to decorate_state! for state decorators or decorate_objective! for objective decorators, respectively.
If you provide the ManifoldFirstOrderObjective directly, the evaluation= keyword is ignored. The decorations are still applied to the objective.
If you activate tutorial mode (cf. is_tutorial_mode), this solver provides additional debug warnings.
Output
The obtained approximate minimizer $p^*$. To obtain the whole final state of the solver, see get_solver_return for details, especially the return_state= keyword.
State
Manopt.GradientDescentState — Type
GradientDescentState{P,T} <: AbstractGradientSolverStateDescribes the state of a gradient based descent algorithm.
Fields
callbacks::D: provided callback functions given as a dictionary with symbols as keysp::P: a point on the manifold $\mathcal{M}$ storing the current iterateX::T: a tangent vector at the point $p$ on the manifold $\mathcal{M}$ storing the gradient at the current iteratestop::StoppingCriterion: a functor indicating that the stopping criterion is fulfilledstepsize::Stepsize: a functor inheriting fromStepsizeto determine a step sizedirection::DirectionUpdateRule: a processor to handle the obtained gradient and compute a direction to “walk into”.retraction_method::AbstractRetractionMethod: a retraction $\operatorname{retr}$ to use, see the section on retractions
Constructor
GradientDescentState(M::AbstractManifold; kwargs...)Initialize the gradient descent solver state, where
Input
M::AbstractManifold: a Riemannian manifold $\mathcal{M}$
Keyword arguments
direction=IdentityUpdateRule()specify a processor to modify the gradient directioncallbacks::D = Dict{Symbol,Function}(): provided callback functions given as a dictionary with symbols as keysp::P =rand(M): a point on the manifold $\mathcal{M}$ to specify the initial valuestopping_criterion::StoppingCriterion=StopAfterIteration(200)|StopWhenGradientNormLess(1e-8): a functor indicating that the stopping criterion is fulfilledstepsize::Stepsize=default_stepsize(M,GradientDescentState; retraction_method=retraction_method): a functor inheriting fromStepsizeto determine a step sizeretraction_method::AbstractRetractionMethod=default_retraction_method(M, typeof(p)): a retraction $\operatorname{retr}$ to use, see the section on retractionsX::T =zero_vector(M, p): a tangent vector at the point $p$ on the manifold $\mathcal{M}$ to specify the representation of a tangent vector
See also
Direction update rules
A field of the state is the direction, a DirectionUpdateRule, which by default is the IdentityUpdateRule that just evaluates the gradient. The following ones are furthermore available
Manopt.AverageGradient — Method
AverageGradient(; kwargs...)
AverageGradient(M::AbstractManifold; kwargs...)Add an average of gradients to a gradient processor. A set of previous directions (from the inner processor) and the last iterate are stored, average is taken after vector transporting them to the current iterate's tangent space.
Input
M::AbstractManifold: a Riemannian manifold $\mathcal{M}$ (optional)
Keyword arguments
p::P =rand(M): a point on the manifold $\mathcal{M}$ to specify the initial valuedirection=IdentityUpdateRulepreprocess the actual gradient before averaginggradients=[zero_vector(M, p) for _ in 1:n]how to initialize the internal storagen=10number of gradient evaluations to take the mean overvector_transport_method::AbstractVectorTransportMethod=default_vector_transport_method(M, typeof(p)): a vector transport $\mathcal T_{⋅←⋅}$ to use, see the section on vector transports
This function generates a ManifoldDefaultsFactory for AverageGradientRule. For default values that depend on the manifold, this factory postpones the construction until the manifold is available, for example from a corresponding AbstractManoptSolverState.
Manopt.MomentumGradient — Method
MomentumGradient(args...; kwargs...)Append a momentum to a gradient processor.
The last direction and last iterate are stored and the new one is composed as $η_k = m η_{k-1}' + d_k$, where $d_k$ is the current (inner) direction, $η_{k-1}'$ is the last direction transported to the current iterate, and $m$ is the momentum. The step size is not folded into $η_i$, the solver applies it to the returned direction. This is the Riemannian version of gradient descent with momentum, first used in [RMH18, Section 3.1]; see [LS26, Section 6] for a convergence analysis.
Input
M(optional)
Keyword arguments
p::P =rand(M): a point on the manifold $\mathcal{M}$direction=IdentityUpdateRulepreprocess the actual gradient before adding momentumX::T =zero_vector(M, p): a tangent vector at the point $p$ on the manifold $\mathcal{M}$momentum=0.2amount of momentum to usevector_transport_method::AbstractVectorTransportMethod=default_vector_transport_method(M, typeof(p)): a vector transport $\mathcal T_{⋅←⋅}$ to use, see the section on vector transports
This function generates a ManifoldDefaultsFactory for MomentumGradientRule. For default values that depend on the manifold, this factory postpones the construction until the manifold is available, for example from a corresponding AbstractManoptSolverState.
Manopt.Nesterov — Method
Nesterov(; kwargs...)
Nesterov(M::AbstractManifold; kwargs...)Assume $f$ is $L$-Lipschitz and $μ$-strongly convex. Given
- a step size $h_k<\frac{1}{L}$ (from the
GradientDescentState) - a
shrinkageparameter $β_k$ - and a current iterate $p_k$
- as well as the interim values $γ_k$ and $v_k$ from the previous iterate.
This computes a Nesterov type update using the following steps, see [ZS18]
- Compute the positive root $α_k∈(0,1)$ of $α_k^2 = h_k\bigl((1-α_k)γ_k+α_k μ\bigr)$.
- Set $\bar{γ}_{k+1} = (1-α_k)γ_k + α_kμ$
- $y_k = \operatorname{retr}_{p_k}\Bigl(\frac{α_kγ_k}{γ_k + α_kμ}\operatorname{retr}^{-1}_{p_k}v_k \Bigr)$
- $p_{k+1} = \operatorname{retr}_{y_k}(-h_k \operatorname{grad}f(y_k))$
- $v_{k+1} = \operatorname{retr}_{y_k}\Bigl(\frac{(1-α_k)γ_k}{\bar{γ}_{k+1}}\operatorname{retr}_{y_k}^{-1}(v_k) - \frac{α_k}{\bar{γ}_{k+1}}\operatorname{grad}f(y_k) \Bigr)$
- $γ_{k+1} = \frac{1}{1+β_k}\bar{γ}_{k+1}$
Then, with $d = \operatorname{retr}^{-1}_{p_k}p_{k+1}$ the direction from $p_k$ to $p_{k+1}$, the pair $(h_k, -d/h_k)$ is returned, so that the solver's step $\operatorname{retr}_{p_k}(-h_k ⋅ (-d/h_k))$ yields $p_{k+1}$.
Input
M::AbstractManifold: a Riemannian manifold $\mathcal{M}$ (optional)
Keyword arguments
p::P =rand(M): a point on the manifold $\mathcal{M}$ to specify the initial valueγ=0.001μ=0.9shrinkage = k -> 0.8inverse_retraction_method::AbstractInverseRetractionMethod=default_inverse_retraction_method(M, typeof(p)): an inverse retraction $\operatorname{retr}^{-1}$ to use, see the section on retractions and their inversesretraction_method::AbstractRetractionMethod=default_retraction_method(M, typeof(p)): a retraction $\operatorname{retr}$ to use, see the section on retractions
This function generates a ManifoldDefaultsFactory for NesterovRule. For default values that depend on the manifold, this factory postpones the construction until the manifold is available, for example from a corresponding AbstractManoptSolverState.
Manopt.PreconditionedDirection — Method
PreconditionedDirection(preconditioner; kwargs...)
PreconditionedDirection(M::AbstractManifold, preconditioner; kwargs...)Add a preconditioner to a gradient processor following the motivation for optimization, as a linear invertible map $P: T_{p}\mathcal{M} → T_{p}\mathcal{M}$ that usually should be
- symmetric: $⟨X, P(Y)⟩ = ⟨P(X), Y⟩$
- positive definite $⟨X, P(X)⟩ > 0$ for $X$ not the zero-vector
The gradient is then preconditioned as $P(X)$, where $X$ is either the gradient of the objective or the result of a previous (internally stored) gradient processor.
For example if you provide as the preconditioner the inverse of the Hessian $\operatorname{Hess}^{-1} f$, you turn a gradient descent into a Newton method.
Arguments
M::AbstractManifold: a Riemannian manifold $\mathcal{M}$ (optional)preconditioner: preconditioner function, either as a(M, p, X) -> Yallocating or(M, Y, p, X) -> Ymutating function
Keyword arguments
direction=IdentityUpdateRuleinternalDirectionUpdateRuleto determine the gradients to store or aManifoldDefaultsFactorygenerating oneevaluation::AbstractEvaluationType=AllocatingEvaluation(): specify whether the functions that return an array, for example a point or a tangent vector, work by allocating their result (AllocatingEvaluation) or whether they modify their input argument to return the result therein (InplaceEvaluation). Since usually the first argument is the manifold, the modified argument is the second.
This function generates a ManifoldDefaultsFactory for PreconditionedDirectionRule. For default values that depend on the manifold, this factory postpones the construction until the manifold is available, for example from a corresponding AbstractManoptSolverState.
Internal functions
Manopt.AverageGradientRule — Type
AverageGradientRule <: DirectionUpdateRuleAdd an average of gradients to a gradient processor.
A set of previous directions (from the inner processor) and the last iterate are stored. The average is taken after vector transporting them to the current iterate's tangent space.
Fields
gradients: the lastngradient/direction updateslast_iterate: last iterate (needed to transport the gradients)direction: internalDirectionUpdateRuleto determine directions to apply the averaging tovector_transport_method::AbstractVectorTransportMethod: a vector transport $\mathcal T_{⋅←⋅}$ to use, see the section on vector transports
Constructors
AverageGradientRule( M::AbstractManifold; p=rand(M), n::Int=10, direction::Union{<:DirectionUpdateRule,ManifoldDefaultsFactory}=Gradient(), gradients=[zero_vector(M, p) for _ in 1:n], vector_transport_method=default_vector_transport_method(M, typeof(p)))AverageGradientRule(M::AbstractManifold, p; kwargs...)Add average to a gradient problem, where
n: determines the size of averagingdirection: is the internalDirectionUpdateRuleto determine the gradients to storegradients: can be pre-filled with some historyvector_transport_method::AbstractVectorTransportMethod=default_vector_transport_method(M, typeof(p)): a vector transport $\mathcal T_{⋅←⋅}$ to use, see the section on vector transports
Manopt.IdentityUpdateRule — Type
IdentityUpdateRule <: DirectionUpdateRuleThe default gradient direction update is the identity, usually it just evaluates the gradient.
You can also use Gradient() to create the corresponding factory, though this only delays this parameter-free instantiation to later.
Manopt.MomentumGradientRule — Type
MomentumGradientRule <: DirectionUpdateRuleStore the necessary information to compute the MomentumGradient direction update, see [RMH18, LS26].
Fields
p_old::P: a point on the manifold $\mathcal{M}$momentum::Real: factor for the momentumdirection: internalDirectionUpdateRuleto determine directions to add the momentum to.vector_transport_method::AbstractVectorTransportMethod: a vector transport $\mathcal T_{⋅←⋅}$ to use, see the section on vector transportsη_old::T: the momentum direction accumulated so far, that is the direction the rule returned in the last step. Note that this is not the last gradient.
Constructors
MomentumGradientRule(M::AbstractManifold; kwargs...)MomentumGradientRule(M::AbstractManifold, p; kwargs...)Initialize a momentum gradient rule, where p and X are memory for interim values, the latter for the accumulated momentum direction η_old.
Keyword arguments
p::P =rand(M): a point on the manifold $\mathcal{M}$direction=IdentityUpdateRule()momentum=0.2vector_transport_method::AbstractVectorTransportMethod=default_vector_transport_method(M, typeof(p)): a vector transport $\mathcal T_{⋅←⋅}$ to use, see the section on vector transportsX::T =zero_vector(M, p): a tangent vector at the point $p$ on the manifold $\mathcal{M}$
See also
Manopt.NesterovRule — Type
NesterovRule <: DirectionUpdateRuleCompute a Nesterov inspired direction update rule. See Nesterov for details
Fields
γ::Real,μ::Real: coefficients from the last iteratev::P: an interim point to compute the next gradient evaluation pointy_kshrinkage: a functionk -> ...to compute the shrinkage $β_k$ per iteratek.inverse_retraction_method::AbstractInverseRetractionMethod: an inverse retraction $\operatorname{retr}^{-1}$ to use, see the section on retractions and their inversesretraction_method::AbstractRetractionMethod: a retraction $\operatorname{retr}$ to use, see the section on retractions
Constructor
NesterovRule(M::AbstractManifold; kwargs...)NesterovRule(M::AbstractManifold, p; kwargs...)Keyword arguments
p::P =rand(M): a point on the manifold $\mathcal{M}$ to specify the initial valueγ=0.001μ=0.9shrinkage = k -> 0.8inverse_retraction_method::AbstractInverseRetractionMethod=default_inverse_retraction_method(M, typeof(p)): an inverse retraction $\operatorname{retr}^{-1}$ to use, see the section on retractions and their inversesretraction_method::AbstractRetractionMethod=default_retraction_method(M, typeof(p)): a retraction $\operatorname{retr}$ to use, see the section on retractions
See also
Manopt.PreconditionedDirectionRule — Type
PreconditionedDirectionRule <: DirectionUpdateRuleAdd a preconditioning as gradient processor, see PreconditionedDirection for more mathematical background.
Fields
direction: internalDirectionUpdateRuleto determine directions to apply the preconditioning topreconditioner: the preconditioner function
Constructors
PreconditionedDirectionRule( M::AbstractManifold, preconditioner; direction::Union{<:DirectionUpdateRule,ManifoldDefaultsFactory}=IdentityUpdateRule(), evaluation::AbstractEvaluationType=AllocatingEvaluation())Add preconditioning to a gradient problem.
Input
M::AbstractManifold: a Riemannian manifold $\mathcal{M}$preconditioner: preconditioner function, either as a(M, p, X) -> Yallocating or(M, Y, p, X) -> Ymutating function
Keyword arguments
direction=IdentityUpdateRuleinternalDirectionUpdateRuleto determine the gradients to store or aManifoldDefaultsFactorygenerating oneevaluation::AbstractEvaluationType=AllocatingEvaluation(): specify whether the functions that return an array, for example a point or a tangent vector, work by allocating their result (AllocatingEvaluation) or whether they modify their input argument to return the result therein (InplaceEvaluation). Since usually the first argument is the manifold, the modified argument is the second.
Technical details
The gradient_descent solver requires the following functions of a manifold to be available
- A
retract!(M, q, p, X); it is recommended to set thedefault_retraction_methodto a favorite retraction. If this default is set, aretraction_method=does not have to be specified. - By default gradient descent uses
ArmijoLinesearchwhich requiresmax_stepsize(M)to be set and an implementation ofinner(M, p, X, Y). - By default the stopping criterion uses the
normas well, to stop when the norm of the gradient is small, but if you implementedinner, the norm is provided already. - By default the tangent vector storing the gradient is initialized calling
zero_vector(M,p).
Literature
- [LS26]
- F. Leggio and D. Scuppa. Riemannian Gradient Method with Momentum (2026), arXiv:2603.04078 [math.OC].
- [Lue72]
- D. G. Luenberger. The gradient projection method along geodesics. Management Science 18, 620–631 (1972).
- [RMH18]
- S. K. Roy, Z. Mhammedi and M. Harandi. Geometry Aware Constrained Optimization Techniques for Deep Learning. In: 2018 IEEE/CVF Conference on Computer Vision and Pattern Recognition (2018).
- [ZS18]
- H. Zhang and S. Sra. Towards Riemannian accelerated gradient methods, preprint (2018), arXiv:1806.02812.