Skip to content

Commit

Permalink
Add attributes
Browse files Browse the repository at this point in the history
  • Loading branch information
blegat committed Dec 19, 2023
1 parent 5af0d28 commit 68b0646
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 10 deletions.
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,39 @@ List of supported model attributes:

* [`MOI.ObjectiveSense()`](@ref)

## Algorithm
## Attributes

The algorithm is parametrized by the attributes that can be used both with `JuMP.set_attributes` and `JuMP.get_attributes`
and have the following types and default values:
```julia
rho_f::Cdouble = 1.0e-5
rho_c::Cdouble = 1.0e-1
sigmafac::Cdouble = 2.0
rankreduce::Csize_t = 0
timelim::Csize_t = 3600
printlevel::Csize_t = 1
dthresh_dim::Csize_t = 10
dthresh_dens::Cdouble = 0.75
numbfgsvecs::Csize_t = 4
rankredtol::Cdouble = 2.2204460492503131e-16
gaptol::Cdouble = 1.0e-3
checkbd::Cptrdiff_t = -1
typebd::Cptrdiff_t = 1
maxrank::Function = default_maxrank
```

The following attributes can be also be used both with `JuMP.set_attributes` and `JuMP.get_attributes`, but they are also
modified by `optimize!`:
* `majiter`
* `iter`
* `lambdaupdate`
* `totaltime`
* `sigma`

When they are `set`, it provides the initial value of the algorithm.
With `get`, they provide the value at the end of the algorithm.
`totaltime` is the total time in second. For the other attributes,
their meaning is best described by the following pseudo-code.

Given values of `R`, `lambda` and `sigma`, let
`vio = [dot(A[i], R * R') - b[i]) for i in 1:m]` (`vio[0]` is `dot(C, R * R')` in the C implementation, but we ignore this entry here),
Expand Down Expand Up @@ -96,6 +128,9 @@ for majiter in 1:100_000
if val - 1e10 * abs(origval) > eps()
return
end
if norm(vio) / (norm(b) + 1) <= rho_f || totaltime >= timelim || iter >= 10_000_000
return
end
while norm(G) / (norm(C) + 1) > rho_c / sigma
sigma *= 2
end
Expand Down
41 changes: 32 additions & 9 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
# This file modifies code from SDPAFamily.jl (https://github.com/ericphanson/SDPAFamily.jl/), which is available under an MIT license (see LICENSE).

import MathOptInterface as MOI

const PIECES_MAP = Dict{String,Int}(
"majiter" => 1,
"iter" => 2,
"lambdaupdate" => 3,
"CG" => 4,
"curr_CG" => 5,
"totaltime" => 6,
"sigma" => 7,
"overallsc" => 8,
)

const SupportedSets =
Union{MOI.Nonnegatives,MOI.PositiveSemidefiniteConeTriangle}

Expand Down Expand Up @@ -59,22 +68,29 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
end

function MOI.supports(::Optimizer, param::MOI.RawOptimizerAttribute)
return hasfield(Parameters, Symbol(param.name))
return haskey(PIECES_MAP, param.name) || hasfield(Parameters, Symbol(param.name))
end
function MOI.set(optimizer::Optimizer, param::MOI.RawOptimizerAttribute, value)
if !MOI.supports(optimizer, param)
throw(MOI.UnsupportedAttribute(param))
end
s = Symbol(param.name)
setfield!(optimizer.params, s, convert(fieldtype(Parameters, s), value))
if haskey(PIECES_MAP, param.name)
optimizer.pieces[PIECES_MAP[param.name]] = value
else
s = Symbol(param.name)
setfield!(optimizer.params, s, convert(fieldtype(Parameters, s), value))
end
return
end
function MOI.get(optimizer::Optimizer, param::MOI.RawOptimizerAttribute)
if !MOI.supports(optimizer, param)
throw(MOI.UnsupportedAttribute(param))
end
getfield!(optimizer.params, Symbol(param.name))
return
if haskey(PIECES_MAP, param.name)
return optimizer.pieces[PIECES_MAP[param.name]]
else
return getfield!(optimizer.params, Symbol(param.name))
end
end

MOI.supports(::Optimizer, ::MOI.Silent) = true
Expand Down Expand Up @@ -309,7 +325,7 @@ function MOI.get(optimizer::Optimizer, ::MOI.RawStatusString)
return "majiter = $majiter, iter = $iter, λupdate = $λupdate, CG = $CG, curr_CG = $curr_CG, totaltime = $totaltime, σ = , overallsc = $overallsc"
end
function MOI.get(optimizer::Optimizer, ::MOI.SolveTimeSec)
return optimizer.pieces[6]
return MOI.get(optimizer, MOI.RawOptimizerAttribute("totaltime"))
end

function MOI.is_empty(optimizer::Optimizer)
Expand Down Expand Up @@ -393,6 +409,10 @@ end
function MOI.get(model::Optimizer, ::MOI.TerminationStatus)
if isnothing(model.pieces)
return MOI.OPTIMIZE_NOT_CALLED
elseif MOI.get(model, MOI.SolveTimeSec()) > MOI.get(model, MOI.RawOptimizerAttribute("timelim"))
return MOI.TIME_LIMIT
elseif MOI.get(model, MOI.RawOptimizerAttribute("iter")) > 10_000_000
return MOI.ITERATION_LIMIT
else
return MOI.LOCALLY_SOLVED
end
Expand All @@ -401,8 +421,11 @@ end
function MOI.get(m::Optimizer, attr::MOI.PrimalStatus)
if attr.result_index > MOI.get(m, MOI.ResultCount())
return MOI.NO_SOLUTION
elseif MOI.get(m, MOI.TerminationStatus()) != MOI.LOCALLY_SOLVED
return UNKNOWN_RESULT_STATUS
else
return MOI.FEASIBLE_POINT
end
return MOI.FEASIBLE_POINT
end

function MOI.get(m::Optimizer, attr::MOI.DualStatus)
Expand Down

0 comments on commit 68b0646

Please sign in to comment.