Skip to content

Commit

Permalink
JuMP interface (#264)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Ronny Bergmann <[email protected]>
  • Loading branch information
blegat and kellertuer authored Nov 6, 2023
1 parent ee354f9 commit ed8fcef
Show file tree
Hide file tree
Showing 10 changed files with 699 additions and 4 deletions.
8 changes: 7 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable Changes to the Julia package `Manopt.jl` will be documented in this
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

* add `Manopt.JuMP_Optimizer` implementing JuMP's solver interface

## [0.4.41] - 02/11/2023

### Changed
Expand Down Expand Up @@ -370,4 +376,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* the problem now contains a
* `AbstractManoptSolverState` replaces `Options`
* `random_point(M)` is replaced by `rand(M)` from `ManifoldsBase.jl
* `random_tangent(M, p)` is replaced by `rand(M; vector_at=p)`
* `random_tangent(M, p)` is replaced by `rand(M; vector_at=p)`
8 changes: 6 additions & 2 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 <[email protected]>"]
version = "0.4.41"
version = "0.4.42"

[deps]
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
Expand All @@ -22,12 +22,14 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[weakdeps]
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
LRUCache = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637"
LineSearches = "d3d80556-e9d4-5f37-9878-2ab0fcc64255"
Manifolds = "1cead3c2-87b3-11e9-0ccd-23c62b72b94e"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"

[extensions]
ManoptJuMPExt = ["JuMP"]
ManoptLRUCacheExt = "LRUCache"
ManoptLineSearchesExt = "LineSearches"
ManoptManifoldsExt = ["Manifolds"]
Expand All @@ -39,6 +41,7 @@ ColorTypes = "0.9.1, 0.10, 0.11"
Colors = "0.11.2, 0.12"
DataStructures = "0.17, 0.18"
Dates = "1.6"
JuMP = "1.15"
LinearAlgebra = "1.6"
LRUCache = "1.4"
ManifoldDiff = "0.3.8"
Expand All @@ -56,11 +59,12 @@ julia = "1.6"

[extras]
ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
LRUCache = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637"
LineSearches = "d3d80556-e9d4-5f37-9878-2ab0fcc64255"
Manifolds = "1cead3c2-87b3-11e9-0ccd-23c62b72b94e"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test", "ForwardDiff", "Manifolds", "Plots", "LineSearches", "LRUCache"]
test = ["Test", "ForwardDiff", "JuMP", "Manifolds", "Plots", "LineSearches", "LRUCache"]
1 change: 1 addition & 0 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ The following packages are related to `Manopt.jl`

* [`Manifolds.jl`](https://juliamanifolds.github.io/Manifolds.jl/stable/) – a library of manifolds implemented using [`ManifoldsBase.jl`](https://juliamanifolds.github.io/ManifoldsBase.jl/stable/) :octocat: [GitHub repository](https://github.com/JuliaManifolds/Manifolds.jl)
* [`ManifoldsDiff.jl`](https://juliamanifolds.github.io/ManifoldDiff.jl/stable/) – a package to use (Euclidean) AD tools on manifolds, that also provides several differentials and gradients. :octocat: [GitHub repository](https://github.com/JuliaManifolds/ManifoldDiff.jl)
* [`JuMP.jl`](https://jump.dev/) can be used as interface to solve an optimization problem with Manopt. See [usage examples](https://manoptjl.org/stable/extensions/). :octocat: [GitHub repository](https://github.com/jump-dev/JuMP.jl)

## Citation

Expand Down
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"
FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
JLD2 = "033835bb-8acc-5ee8-8aae-3f567f8a3819"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
LRUCache = "8ac3fa9e-de4c-5943-b1dc-09c6b5f20637"
LineSearches = "d3d80556-e9d4-5f37-9878-2ab0fcc64255"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
7 changes: 6 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ end
# (c) load necessary packages for the docs
using Documenter
using DocumenterCitations
using LineSearches, LRUCache, Manopt, Manifolds, Plots
using JuMP, LineSearches, LRUCache, Manopt, Manifolds, Plots

# (d) add contributing.md to docs
generated_path = joinpath(@__DIR__, "src")
Expand Down Expand Up @@ -112,6 +112,11 @@ makedocs(;
),
modules=[
Manopt,
if isdefined(Base, :get_extension)
Base.get_extension(Manopt, :ManoptJuMPExt)
else
Manopt.ManoptJuMPExt
end,
if isdefined(Base, :get_extension)
Base.get_extension(Manopt, :ManoptLineSearchesExt)
else
Expand Down
51 changes: 51 additions & 0 deletions docs/src/extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,54 @@ mid_point
Manopt.max_stepsize(::TangentBundle, ::Any)
Manopt.max_stepsize(::FixedRankMatrices, ::Any)
```

## JuMP.jl

Manopt can be used using the [JuMP.jl](https://github.com/jump-dev/JuMP.jl) interface.
The manifold is provided in the `@variable` macro. Note that until now, only variables (points on manifolds) are supported, that are arrays, i.e. especially structs do not yet work.
The algebraic expression of the objective function is specified in the `@objective` macro.
The `descent_state_type` attribute specifies the solver.

```julia
using JuMP, Manopt, Manifolds
model = Model(Manopt.Optimizer)
# Change the solver with this option, `GradientDescentState` is the default
set_attribute("descent_state_type", GradientDescentState)
@variable(model, U[1:2, 1:2] in Stiefel(2, 2), start = 1.0)
@objective(model, Min, sum((A - U) .^ 2))
optimize!(model)
solution_summary(model)
```

```@docs
Manopt.JuMP_ArrayShape
Manopt.JuMP_VectorizedManifold
MOI.dimension(::Manopt.JuMP_VectorizedManifold)
Manopt.JuMP_Optimizer
MOI.empty!(::Manopt.JuMP_Optimizer)
MOI.supports(::Manopt.JuMP_Optimizer, ::MOI.RawOptimizerAttribute)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.RawOptimizerAttribute)
MOI.set(::Manopt.JuMP_Optimizer, ::MOI.RawOptimizerAttribute, ::Any)
MOI.supports_incremental_interface(::Manopt.JuMP_Optimizer)
MOI.copy_to(::Manopt.JuMP_Optimizer, ::MOI.ModelLike)
MOI.supports_add_constrained_variables(::Manopt.JuMP_Optimizer, ::Type{<:Manopt.JuMP_VectorizedManifold})
MOI.add_constrained_variables(::Manopt.JuMP_Optimizer, ::Manopt.JuMP_VectorizedManifold)
MOI.is_valid(model::Manopt.JuMP_Optimizer, ::MOI.VariableIndex)
MOI.get(model::Manopt.JuMP_Optimizer, ::MOI.NumberOfVariables)
MOI.supports(::Manopt.JuMP_Optimizer, ::MOI.VariablePrimalStart, ::Type{MOI.VariableIndex})
MOI.set(::Manopt.JuMP_Optimizer, ::MOI.VariablePrimalStart, ::MOI.VariableIndex, ::Union{Real,Nothing})
MOI.set(::Manopt.JuMP_Optimizer, ::MOI.ObjectiveSense, ::MOI.OptimizationSense)
MOI.set(::Manopt.JuMP_Optimizer, ::MOI.ObjectiveFunction{F}, ::F) where {F}
MOI.supports(::Manopt.JuMP_Optimizer, ::Union{MOI.ObjectiveSense,MOI.ObjectiveFunction})
JuMP.build_variable(::Function, ::Any, ::Manopt.AbstractManifold)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.ResultCount)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.SolverName)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.ObjectiveValue)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.PrimalStatus)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.DualStatus)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.TerminationStatus)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.SolverVersion)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.ObjectiveSense)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.VariablePrimal, ::MOI.VariableIndex)
MOI.get(::Manopt.JuMP_Optimizer, ::MOI.RawStatusString)
```
Loading

2 comments on commit ed8fcef

@kellertuer
Copy link
Member

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/94824

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.42 -m "<description of version>" ed8fcef49b6f68715e7060ec64a86630387c874e
git push origin v0.4.42

Please sign in to comment.