Skip to content

Commit

Permalink
Rework LevenbergMarquardt to use the vector function functionality (#432
Browse files Browse the repository at this point in the history
)

* For today just a bit of sketching of ideas and modelling.
* Start reworking the objective and its `get_cost`.
* Start designing the new Jacobian interface.
* start documenting the new model for LM and fixing its structure.
* Implement get_jacobian and get_jacobian! for vector functions.
* Add changelog entry.

---------

Co-authored-by: Mateusz Baran <[email protected]>
  • Loading branch information
kellertuer and mateuszbaran authored Jan 4, 2025
1 parent 41d852d commit 67b2d10
Show file tree
Hide file tree
Showing 25 changed files with 1,041 additions and 499 deletions.
2 changes: 1 addition & 1 deletion .JuliaFormatter.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
style = "blue"
ignore = ["tutorials"]
ignore = ["tutorials", ".git"]
18 changes: 13 additions & 5 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [0.5.5] unreleased

### Added

* the Levenberg-Marquardt algorithm internally uses a `VectorGradientFunction`, which allows
to use a vector of gradients of a function returning all gradients as well for the algorithm
* The `VectorGradientFunction` now also have a `get_jacobian` function

### Changed

* Minimum Julia version is now 1.10 (the LTS which replaced 1.6)
* The vectorial functions had a bug where the original vector function for the mutating case
was not always treated as mutating.

### Removed

Expand All @@ -20,7 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

* An automated detection whether the tutorials are present
if not an also no quarto run is done, an automated `--exlcude-tutorials` option is added.
if not an also no quarto run is done, an automated `--exclude-tutorials` option is added.
* Support for ManifoldDiff 0.4
* icons upfront external links when they link to another package or wikipedia.

Expand All @@ -32,7 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

* stabilize `max_Stepzise` to also work when `injectivity_radius` dos not exist.
* stabilize `max_stepsize` to also work when `injectivity_radius` dos not exist.
It however would warn new users, that activate tutorial mode.
* Start a `ManoptTestSuite` subpackage to store dummy types and common test helpers in.

Expand Down Expand Up @@ -71,8 +79,8 @@ In general we introduce a few factories, that avoid having to pass the manifold

### Changed

* Any `Stepsize` now hase a `Stepsize` struct used internally as the original `struct`s before. The newly exported terms aim to fit `stepsize=...` in naming and create a `ManifoldDefaultsFactory` instead, so that any stepsize can be created without explicitly specifying the manifold.
* `ConstantStepsize` is no longer exported, use `ConstantLength` instead. The length parameter is now a positional argument following the (optonal) manifold. Besides that `ConstantLength` works as before,just that omitting the manifold fills the one specified in the solver now.
* Any `Stepsize` now has a `Stepsize` struct used internally as the original `struct`s before. The newly exported terms aim to fit `stepsize=...` in naming and create a `ManifoldDefaultsFactory` instead, so that any stepsize can be created without explicitly specifying the manifold.
* `ConstantStepsize` is no longer exported, use `ConstantLength` instead. The length parameter is now a positional argument following the (optional) manifold. Besides that `ConstantLength` works as before,just that omitting the manifold fills the one specified in the solver now.
* `DecreasingStepsize` is no longer exported, use `DecreasingLength` instead. `ConstantLength` works as before,just that omitting the manifold fills the one specified in the solver now.
* `ArmijoLinesearch` is now called `ArmijoLinesearchStepsize`. `ArmijoLinesearch` works as before,just that omitting the manifold fills the one specified in the solver now.
* `WolfePowellLinesearch` is now called `WolfePowellLinesearchStepsize`, its constant `c_1` is now unified with Armijo and called `sufficient_decrease`, `c_2` was renamed to `sufficient_curvature`. Besides that, `WolfePowellLinesearch` works as before, just that omitting the manifold fills the one specified in the solver now.
Expand Down Expand Up @@ -134,7 +142,7 @@ In general we introduce a few factories, that avoid having to pass the manifold
* `ExactPenaltyMethodState(M, sub_problem; evaluation=...)` was added and `ExactPenaltyMethodState(M, sub_problem, sub_state; evaluation=...)` now has `p=rand(M)` as keyword argument instead of being the second positional one
* `DifferenceOfConvexState(M, sub_problem; evaluation=...)` was added and `DifferenceOfConvexState(M, sub_problem, sub_state; evaluation=...)` now has `p=rand(M)` as keyword argument instead of being the second positional one
* `DifferenceOfConvexProximalState(M, sub_problem; evaluation=...)` was added and `DifferenceOfConvexProximalState(M, sub_problem, sub_state; evaluation=...)` now has `p=rand(M)` as keyword argument instead of being the second positional one
* bumped `Manifolds.jl`to version 0.10; this mainly means that any algorithm working on a productmanifold and requiring `ArrayPartition` now has to explicitly do `using RecursiveArrayTools`.
* bumped `Manifolds.jl`to version 0.10; this mainly means that any algorithm working on a product manifold and requiring `ArrayPartition` now has to explicitly do `using RecursiveArrayTools`.
### Fixed

* the `AverageGradientRule` filled its internal vector of gradients wrongly – or mixed it up in parallel transport. This is now fixed.
Expand Down
13 changes: 7 additions & 6 deletions docs/src/plans/objective.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ ManifoldCostGradientObjective
```@docs
get_gradient
get_gradients
get_residuals
get_residuals!
```

and internally
Expand All @@ -129,12 +131,6 @@ and internally
get_gradient_function
```

#### Internal helpers

```@docs
get_gradient_from_Jacobian!
```

### Subgradient objective

```@docs
Expand Down Expand Up @@ -262,6 +258,8 @@ Manopt.FunctionVectorialType
#### Access functions

```@docs
Manopt.get_jacobian
Manopt.get_jacobian!
Manopt.get_value
Manopt.get_value_function
Base.length(::VectorGradientFunction)
Expand All @@ -271,6 +269,9 @@ Base.length(::VectorGradientFunction)

```@docs
Manopt._to_iterable_indices
Manopt._change_basis!
Manopt.get_basis
Manopt.get_range
```

### Subproblem objective
Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/ChambollePock.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ The [`ChambollePock`](@ref) solver requires the following functions of a manifol
* A [`retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, q, p, X)`; it is recommended to set the [`default_retraction_method`](@extref `ManifoldsBase.default_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `retraction_method=` or `retraction_method_dual=` (for ``\mathcal N``) does not have to be specified.
* An [`inverse_retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, X, p, q)`; it is recommended to set the [`default_inverse_retraction_method`](@extref `ManifoldsBase.default_inverse_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `inverse_retraction_method=` or `inverse_retraction_method_dual=` (for ``\mathcal N``) does not have to be specified.
* A [`vector_transport_to!`](@extref ManifoldsBase :doc:`vector_transports`)`M, Y, p, X, q)`; it is recommended to set the [`default_vector_transport_method`](@extref `ManifoldsBase.default_vector_transport_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `vector_transport_method=` or `vector_transport_method_dual=` (for ``\mathcal N``) does not have to be specified.
* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.

## Literature

Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/DouglasRachford.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ The [`DouglasRachford`](@ref) solver requires the following functions of a manif

* A [`retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, q, p, X)`; it is recommended to set the [`default_retraction_method`](@extref `ManifoldsBase.default_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `retraction_method=` does not have to be specified.
* An [`inverse_retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, X, p, q)`; it is recommended to set the [`default_inverse_retraction_method`](@extref `ManifoldsBase.default_inverse_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `inverse_retraction_method=` does not have to be specified.
* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.

By default, one of the stopping criteria is [`StopWhenChangeLess`](@ref),
which requires
Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/LevenbergMarquardt.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The [`LevenbergMarquardt`](@ref) solver requires the following functions of a ma

* A [`retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, q, p, X)`; it is recommended to set the [`default_retraction_method`](@extref `ManifoldsBase.default_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `retraction_method=` does not have to be specified.
* the [`norm`](@extref `LinearAlgebra.norm-Tuple{AbstractManifold, Any, Any}`) as well, to stop when the norm of the gradient is small, but if you implemented `inner`, the norm is provided already.
* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.


## Literature
Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/augmented_Lagrangian_method.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ AugmentedLagrangianGrad

The [`augmented_Lagrangian_method`](@ref) solver requires the following functions of a manifold to be available

* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* Everything the subsolver requires, which by default is the [`quasi_Newton`](@ref) method
* A [`zero_vector`](@extref `ManifoldsBase.zero_vector-Tuple{AbstractManifold, Any}`)`(M,p)`.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/difference_of_convex.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ which either requires

* A [`retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, q, p, X)`; it is recommended to set the [`default_retraction_method`](@extref `ManifoldsBase.default_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `retraction_method=` or `retraction_method_dual=` (for ``\mathcal N``) does not have to be specified.
* An [`inverse_retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, X, p, q)`; it is recommended to set the [`default_inverse_retraction_method`](@extref `ManifoldsBase.default_inverse_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `inverse_retraction_method=` or `inverse_retraction_method_dual=` (for ``\mathcal N``) does not have to be specified or the [`distance`](@extref `ManifoldsBase.distance-Tuple{AbstractManifold, Any, Any}`)`(M, p, q)` for said default inverse retraction.
* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* By default the tangent vector storing the gradient is initialized calling [`zero_vector`](@extref `ManifoldsBase.zero_vector-Tuple{AbstractManifold, Any}`)`(M,p)`.
* everything the subsolver requires, which by default is the [`trust_regions`](@ref) or if you do not provide a Hessian [`gradient_descent`](@ref).

Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/exact_penalty_method.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ LogarithmicSumOfExponentials
The [`exact_penalty_method`](@ref) solver requires the following functions of a manifold to be available


* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* Everything the subsolver requires, which by default is the [`quasi_Newton`](@ref) method
* A [`zero_vector`](@extref `ManifoldsBase.zero_vector-Tuple{AbstractManifold, Any}`)`(M,p)`.

Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/particle_swarm.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ The [`particle_swarm`](@ref) solver requires the following functions of a manifo
* A [`vector_transport_to!`](@extref ManifoldsBase :doc:`vector_transports`)`M, Y, p, X, q)`; it is recommended to set the [`default_vector_transport_method`](@extref `ManifoldsBase.default_vector_transport_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `vector_transport_method=` does not have to be specified.
* By default the stopping criterion uses the [`norm`](@extref `LinearAlgebra.norm-Tuple{AbstractManifold, Any, Any}`) as well, to stop when the norm of the gradient is small, but if you implemented `inner`, the norm is provided already.
* Tangent vectors storing the social and cognitive vectors are initialized calling [`zero_vector`](@extref `ManifoldsBase.zero_vector-Tuple{AbstractManifold, Any}`)`(M,p)`.
* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* The [`distance`](@extref `ManifoldsBase.distance-Tuple{AbstractManifold, Any, Any}`)`(M, p, q)` when using the default stopping criterion, which uses [`StopWhenChangeLess`](@ref).

## Literature
Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/primal_dual_semismooth_Newton.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ The [`primal_dual_semismooth_Newton`](@ref) solver requires the following functi
* A [`retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, q, p, X)`; it is recommended to set the [`default_retraction_method`](@extref `ManifoldsBase.default_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `retraction_method=` does not have to be specified.
* An [`inverse_retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, X, p, q)`; it is recommended to set the [`default_inverse_retraction_method`](@extref `ManifoldsBase.default_inverse_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `inverse_retraction_method=` does not have to be specified.
* A [`vector_transport_to!`](@extref ManifoldsBase :doc:`vector_transports`)`M, Y, p, X, q)`; it is recommended to set the [`default_vector_transport_method`](@extref `ManifoldsBase.default_vector_transport_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `vector_transport_method=` does not have to be specified.
* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`get_basis`](@extref `ManifoldsBase.get_basis-Tuple{AbstractManifold, Any, ManifoldsBase.AbstractBasis}`) for the [`DefaultOrthonormalBasis`](@extref `ManifoldsBase.DefaultOrthonormalBasis`) on ``\mathcal M``
* [`exp`](@extref `Base.exp-Tuple{AbstractManifold, Any, Any}`) and [`log`](@extref `Base.log-Tuple{AbstractManifold, Any, Any}`) (on ``\mathcal M``)
* A [`DiagonalizingOrthonormalBasis`](@extref `ManifoldsBase.DiagonalizingOrthonormalBasis`) to compute the differentials of the exponential and logarithmic map
Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/truncated_conjugate_gradient_descent.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ The [`trust_regions`](@ref) solver requires the following functions of a manifol
* if you do not provide a `trust_region_radius=`, then [`injectivity_radius`](@extref `ManifoldsBase.injectivity_radius-Tuple{AbstractManifold}`) on the manifold `M` is required.
* the [`norm`](@extref `LinearAlgebra.norm-Tuple{AbstractManifold, Any, Any}`) as well, to stop when the norm of the gradient is small, but if you implemented `inner`, the norm is provided already.
* A [`zero_vector!`](@extref `ManifoldsBase.zero_vector-Tuple{AbstractManifold, Any}`)`(M,X,p)`.
* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.

## Literature

Expand Down
2 changes: 1 addition & 1 deletion docs/src/solvers/trust_regions.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ The [`trust_regions`](@ref) solver requires the following functions of a manifol
* A [`retract!`](@extref ManifoldsBase :doc:`retractions`)`(M, q, p, X)`; it is recommended to set the [`default_retraction_method`](@extref `ManifoldsBase.default_retraction_method-Tuple{AbstractManifold}`) to a favourite retraction. If this default is set, a `retraction_method=` does not have to be specified.
* By default the stopping criterion uses the [`norm`](@extref `LinearAlgebra.norm-Tuple{AbstractManifold, Any, Any}`) as well, to stop when the norm of the gradient is small, but if you implemented `inner`, the norm is provided already.
* if you do not provide an initial `max_trust_region_radius`, a [`manifold_dimension`](@extref `ManifoldsBase.manifold_dimension-Tuple{AbstractManifold}`) is required.
* A [`copyto!](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* A [`copyto!`](@extref `Base.copyto!-Tuple{AbstractManifold, Any, Any}`)`(M, q, p)` and [`copy`](@extref `Base.copy-Tuple{AbstractManifold, Any}`)`(M,p)` for points.
* By default the tangent vectors are initialized calling [`zero_vector`](@extref `ManifoldsBase.zero_vector-Tuple{AbstractManifold, Any}`)`(M,p)`.


Expand Down
6 changes: 5 additions & 1 deletion src/Manopt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module Manopt
import Base: &, copy, getindex, identity, length, setindex!, show, |
import LinearAlgebra: reflect!
import ManifoldsBase: embed!, plot_slope, prepare_check_result, find_best_slope_window
import ManifoldsBase: base_manifold, base_point
import ManifoldsBase: base_manifold, base_point, get_basis
using ColorSchemes
using ColorTypes
using Colors
Expand Down Expand Up @@ -364,6 +364,8 @@ export get_proximal_map, get_proximal_map!
export get_state,
get_initial_stepsize,
get_iterate,
get_jacobian,
get_jacobian!,
get_gradients,
get_gradients!,
get_manifold,
Expand All @@ -379,6 +381,8 @@ export get_state,
get_differential_dual_prox!,
set_gradient!,
set_iterate!,
get_residuals,
get_residuals!,
linearized_forward_operator,
linearized_forward_operator!,
adjoint_linearized_operator,
Expand Down
Loading

0 comments on commit 67b2d10

Please sign in to comment.