Skip to content

Commit

Permalink
Introduce an EmbeddedObjective (#286)
Browse files Browse the repository at this point in the history
* Introduce a sketch for an EmbeddedObjective.
* Improve a menu entry.
* Apply suggestions from code review
* Fix docs for the object decorator.
* Write the wrapper for the Euclidean Hessian.
* Change the keyword to `objective_type`.
* use embed from ManifoldsBase.
* Constraint gradient conversion.
* Work on the docs.
* Finish the tutorial.
* Test Coverage
* Bump version.

---------

Co-authored-by: Mateusz Baran <mateuszbaran89@gmail.com>
  • Loading branch information
kellertuer and mateuszbaran authored Sep 2, 2023
1 parent 2b3c35f commit b574950
Show file tree
Hide file tree
Showing 24 changed files with 869 additions and 105 deletions.
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "Manopt"
uuid = "0fc0a36d-df90-57f3-8f93-d78a9fc72bb5"
authors = ["Ronny Bergmann <manopt@ronnybergmann.net>"]
version = "0.4.33"
version = "0.4.34"

[deps]
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
Expand Down Expand Up @@ -40,8 +40,8 @@ Colors = "0.11.2, 0.12"
DataStructures = "0.17, 0.18"
LRUCache = "1.4"
ManifoldDiff = "0.2, 0.3.3"
Manifolds = "0.8.69"
ManifoldsBase = "0.14.4"
Manifolds = "0.8.75"
ManifoldsBase = "0.14.10"
PolynomialRoots = "1"
Requires = "0.5, 1"
julia = "1.6"
Expand Down
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,5 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
BenchmarkTools = "1.3"
CondaPkg = "0.2"
Documenter = "0.27"
Manifolds = "0.8.27"
Manifolds = "0.8.75"
ManifoldsBase = "0.13, 0.14"
27 changes: 25 additions & 2 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,29 @@ makedocs(
format=Documenter.HTML(;
mathengine=MathJax3(), prettyurls=get(ENV, "CI", nothing) == "true"
),
modules=[Manopt],
modules=[
Manopt,
if isdefined(Base, :get_extension)
Base.get_extension(Manopt, :ManoptLineSearchesExt)
else
Manopt.ManoptLineSearchesExt
end,
if isdefined(Base, :get_extension)
Base.get_extension(Manopt, :ManoptLRUCacheExt)
else
Manopt.ManoptLRUCacheExt
end,
if isdefined(Base, :get_extension)
Base.get_extension(Manopt, :ManoptManifoldsExt)
else
Manopt.ManoptManifoldsExt
end,
if isdefined(Base, :get_extension)
Base.get_extension(Manopt, :ManoptPlotsExt)
else
Manopt.ManoptPlotsExt
end,
],
authors="Ronny Bergmann and contributors.",
sitename="Manopt.jl",
strict=[
Expand All @@ -86,8 +108,9 @@ makedocs(
"Get started: Optimize!" => "tutorials/Optimize!.md",
"Speedup using Inplace computations" => "tutorials/InplaceGradient.md",
"Use Automatic Differentiation" => "tutorials/AutomaticDifferentiation.md",
"Define Objectives in the Embedding" => "tutorials/EmbeddingObjectives.md",
"Count and use a Cache" => "tutorials/CountAndCache.md",
"Perform Debug Output" => "tutorials/HowToDebug.md",
"Print Debug Output" => "tutorials/HowToDebug.md",
"Record values" => "tutorials/HowToRecord.md",
"Implement a Solver" => "tutorials/ImplementASolver.md",
"Do Contrained Optimization" => "tutorials/ConstrainedOptimization.md",
Expand Down
5 changes: 5 additions & 0 deletions docs/src/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ x_opt = quasi_Newton(
)
```

### Manifolds.jl

```@docs
Manopt.LineSearchesStepsize
mid_point
Manopt.max_stepsize(::TangentBundle, ::Any)
Manopt.max_stepsize(::FixedRankMatrices, ::Any)
```
137 changes: 75 additions & 62 deletions docs/src/plans/objective.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,83 @@ InplaceEvaluation
evaluation_type
```

It sometimes might be nice to set certain parameters within

## Cost Objective
## Decorators for Objectives

An objective can be decorated using the following trait and function to initialize

```@docs
dispatch_objective_decorator
is_objective_decorator
decorate_objective!
```

### [Embedded Objectives](@id ManifoldEmbeddedObjective)

```@docs
EmbeddedManifoldObjective
```

### [Cache Objective](@id CacheSection)

Since single function calls, e.g. to the cost or the gradient, might be expensive,
a simple cache objective exists as a decorator, that caches one cost value or gradient.

It can be activated/used with the `cache=` keyword argument available for every solver.

```@docs
Manopt.reset_counters!
Manopt.objective_cache_factory
```

#### A simple cache

A first generic cache is always available, but it only caches one gradient and one cost function evaluation (for the same point).

```@docs
SimpleManifoldCachedObjective
```

#### A Generic Cache

For the more advanced cache, you need to implement some type of cache yourself, that provides a `get!`
and implement [`init_caches`](@ref).
This is for example provided if you load [`LRUCache.jl`](https://github.com/JuliaCollections/LRUCache.jl). Then you obtain

```@docs
ManifoldCachedObjective
init_caches
```

### [Count Objective](@id ManifoldCountObjective)

```@docs
ManifoldCountObjective
```

### Internal Decorators

```@docs
ReturnManifoldObjective
```

## Specific Objective typed and their access functions

### Cost Objective

```@docs
AbstractManifoldCostObjective
ManifoldCostObjective
```

### Access functions
#### Access functions

```@docs
get_cost
get_cost_function
```

## Gradient Objectives
### Gradient Objectives

```@docs
AbstractManifoldGradientObjective
Expand All @@ -52,61 +112,61 @@ There is also a second variant, if just one function is responsible for computin
ManifoldCostGradientObjective
```

### Access functions
#### Access functions

```@docs
get_gradient
get_gradients
get_gradient_function
```

## Subgradient Objective
### Subgradient Objective

```@docs
ManifoldSubgradientObjective
```

### Access Functions
#### Access Functions

```@docs
get_subgradient
```

## Proximal Map Objective
### Proximal Map Objective

```@docs
ManifoldProximalMapObjective
```

### Access Functions
#### Access Functions

```@docs
get_proximal_map
```


## Hessian Objective
### Hessian Objective

```@docs
ManifoldHessianObjective
```

### Access functions
#### Access functions

```@docs
get_hessian
get_preconditioner
```

## Primal-Dual based Objetives
### Primal-Dual based Objectives

```@docs
AbstractPrimalDualManifoldObjective
PrimalDualManifoldObjective
PrimalDualManifoldSemismoothNewtonObjective
```

### Access functions
#### Access functions

```@docs
adjoint_linearized_operator
Expand All @@ -118,7 +178,7 @@ get_primal_prox
linearized_forward_operator
```

## Constrained Objective
### Constrained Objective

Besides the [`AbstractEvaluationType`](@ref) there is one further property to
distinguish among constraint functions, especially the gradients of the constraints.
Expand All @@ -135,7 +195,7 @@ The [`ConstraintType`](@ref) is a parameter of the corresponding Objective.
ConstrainedManifoldObjective
```

### Access functions
#### Access functions

```@docs
get_constraints
Expand All @@ -152,50 +212,3 @@ get_grad_inequality_constraint!
get_grad_inequality_constraints
get_grad_inequality_constraints!
```

## Decorators for AbstractManoptSolverState

An objective can be decorated using the following trait and function to initialize

```@docs
dispatch_objective_decorator
is_objective_decorator
decorate_objective!
```

### [Cache Objective](@id CacheSection)

Since single function calls, e.g. to the cost or the gradient, might be expensive,
a simple cache objective exists as a decorator, that caches one cost value or gradient.

It can be activated/used with the `cache=` keyword argument available for every solver.

```@docs
Manopt.reset_counters!
Manopt.objective_cache_factory
```

#### A simple cache

A first generic cache is always available, but it only caches one gradient and one cost function evaluation (for the same point).

```@docs
SimpleManifoldCachedObjective
```

#### A Generic Cache

For the more advanced cache, you need to implement some type of cache yourself, that provides a `get!`
and implement [`init_caches`](@ref).
This is for example provided if you load [`LRUCache.jl`](https://github.com/JuliaCollections/LRUCache.jl). Then you obtain

```@docs
ManifoldCachedObjective
init_caches
```

### [Count Objective](@id ManifoldCountObjective)

```@docs
ManifoldCountObjective
```
2 changes: 1 addition & 1 deletion docs/src/plans/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ This might be useful to continue investigation at the current iterate, or to set
```@docs
get_iterate
set_iterate!
get_gradient(::AbstractManifoldGradientObjective)
get_gradient(s::AbstractManoptSolverState)
set_gradient!
```

Expand Down
14 changes: 14 additions & 0 deletions docs/src/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,20 @@ @article{LiuStorey:1991
% --- N
%
%
@article{Nguyen:2023,
DOI = {10.1007/s10957-023-02242-z},
EPRINT = {2009.10159},
EPRINTTYPE = {arXiv},
YEAR = {2023},
MONTH = jun,
PUBLISHER = {Springer Science and Business Media {LLC}},
VOLUME = {198},
NUMBER = {1},
PAGES = {135--164},
AUTHOR = {Du Nguyen},
TITLE = {Operator-Valued Formulas for Riemannian Gradient and Hessian and Families of Tractable Metrics in Riemannian Optimization},
JOURNAL = {Journal of Optimization Theory and Applications}
}
@book{NocedalWright:2006,
ADDRESS = {New York},
AUTHOR = {Nocedal, Jorge and Wright, Steven J.},
Expand Down
11 changes: 10 additions & 1 deletion src/Manopt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
* 🎯 Issues: [github.com/JuliaManifolds/Manopt.jl/issues](https://github.com/JuliaManifolds/Manopt.jl/issues)
"""
module Manopt

import Base: &, copy, getindex, identity, setindex!, show, |
import LinearAlgebra: reflect!
import ManifoldsBase: embed!

using ColorSchemes
using ColorTypes
Expand Down Expand Up @@ -45,7 +47,11 @@ using ManifoldDiff:
differential_shortest_geodesic_startpoint,
differential_shortest_geodesic_startpoint!,
jacobi_field,
jacobi_field!
jacobi_field!,
riemannian_gradient,
riemannian_gradient!,
riemannian_Hessian,
riemannian_Hessian!
using ManifoldsBase:
AbstractBasis,
AbstractDecoratorManifold,
Expand Down Expand Up @@ -78,6 +84,7 @@ using ManifoldsBase:
default_retraction_method,
default_vector_transport_method,
distance,
embed,
embed_project,
embed_project!,
exp,
Expand All @@ -87,6 +94,7 @@ using ManifoldsBase:
get_component,
get_coordinates,
get_coordinates!,
get_embedding,
get_iterator,
get_vector,
get_vector!,
Expand Down Expand Up @@ -206,6 +214,7 @@ export AbstractDecoratedManifoldObjective,
AbstractManifoldObjective,
AbstractPrimalDualManifoldObjective,
ConstrainedManifoldObjective,
EmbeddedManifoldObjective,
ManifoldCountObjective,
NonlinearLeastSquaresObjective,
ManifoldAlternatingGradientObjective,
Expand Down
Loading

2 comments on commit b574950

@kellertuer
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/90698

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.4.34 -m "<description of version>" b574950cf349013232e8ab07fa355046bd90e8d3
git push origin v0.4.34

Please sign in to comment.