Skip to content

Commit

Permalink
Merge pull request #20 from JuliaOpt/bl/iteration_limit
Browse files Browse the repository at this point in the history
Return ITERATION_LIMIT for noInfo
  • Loading branch information
blegat authored Oct 18, 2019
2 parents 0b0be45 + 7caf4cc commit 3e99417
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 25 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
[compat]
BinaryProvider = "≥ 0.5.3"
CxxWrap = "= 0.8.1"
MathOptInterface = "0.9"
MathOptInterface = "0.9.5"
MathProgBase = "0.7"
SemidefiniteModels = "~0.1.1"
julia = "1"
Expand Down
63 changes: 41 additions & 22 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
blockdims::Vector{Int}
varmap::Vector{Tuple{Int, Int, Int}} # Variable Index vi -> blk, i, j
b::Vector{Cdouble}
problem::SDPAProblem
problem::Union{Nothing, SDPAProblem}
solve_time::Float64
silent::Bool
options::Dict{Symbol, Any}
function Optimizer(; kwargs...)
optimizer = new(
zero(Cdouble), 1, Int[], Tuple{Int, Int, Int}[], Cdouble[],
SDPAProblem(), NaN, false, Dict{Symbol, Any}())
nothing, NaN, false, Dict{Symbol, Any}())
for (key, value) in kwargs
MOI.set(optimizer, MOI.RawParameter(key), value)
end
Expand Down Expand Up @@ -53,18 +53,21 @@ MOI.get(::Optimizer, ::MOI.SolverName) = "SDPA"
# See https://www.researchgate.net/publication/247456489_SDPA_SemiDefinite_Programming_Algorithm_User's_Manual_-_Version_600
# "SDPA (SemiDefinite Programming Algorithm) User's Manual — Version 6.00" Section 6.2
const RAW_STATUS = Dict(
noINFO => "The iteration has exceeded the maxIteration and stopped with no informationon the primal feasibility and the dual feasibility.",
pdOPT => "The normal termination yielding both primal and dual approximate optimal solutions.",
pFEAS => "The primal problem got feasible but the iteration has exceeded the maxIteration and stopped.",
dFEAS => "The dual problem got feasible but the iteration has exceeded the maxIteration and stopped.",
pdFEAS => "Both primal problem and the dual problem got feasible, but the iterationhas exceeded the maxIteration and stopped.",
pdINF => "At least one of the primal problem and the dual problem is expected to be infeasible.",
noINFO => "The iteration has exceeded the maxIteration and stopped with no informationon the primal feasibility and the dual feasibility.",
pdOPT => "The normal termination yielding both primal and dual approximate optimal solutions.",
pFEAS => "The primal problem got feasible but the iteration has exceeded the maxIteration and stopped.",
dFEAS => "The dual problem got feasible but the iteration has exceeded the maxIteration and stopped.",
pdFEAS => "Both primal problem and the dual problem got feasible, but the iterationhas exceeded the maxIteration and stopped.",
pdINF => "At least one of the primal problem and the dual problem is expected to be infeasible.",
pFEAS_dINF => "The primal problem has become feasible but the dual problem is expected to be infeasible.",
pINF_dFEAS => "The dual problem has become feasible but the primal problem is expected to be infeasible.",
pUNBD => "The primal problem is expected to be unbounded.",
dUNBD => "The dual problem is expected to be unbounded.")
pUNBD => "The primal problem is expected to be unbounded.",
dUNBD => "The dual problem is expected to be unbounded.")

function MOI.get(optimizer::Optimizer, ::MOI.RawStatusString)
if optimizer.problem === nothing
return "`MOI.optimize!` not called."
end
return RAW_STATUS[getPhaseValue(optimizer.problem)]
end
function MOI.get(optimizer::Optimizer, ::MOI.SolveTime)
Expand All @@ -84,7 +87,7 @@ function MOI.empty!(optimizer::Optimizer)
empty!(optimizer.blockdims)
empty!(optimizer.varmap)
empty!(optimizer.b)
optimizer.problem = SDPAProblem()
optimizer.problem = nothing
end

function MOI.supports(
Expand Down Expand Up @@ -240,9 +243,12 @@ function MOI.optimize!(m::Optimizer)
end

function MOI.get(m::Optimizer, ::MOI.TerminationStatus)
if m.problem === nothing
return MOI.OPTIMIZE_NOT_CALLED
end
status = getPhaseValue(m.problem)
if status == noINFO
return MOI.OPTIMIZE_NOT_CALLED
return MOI.ITERATION_LIMIT
elseif status == pFEAS
return MOI.SLOW_PROGRESS
elseif status == dFEAS
Expand All @@ -264,7 +270,10 @@ function MOI.get(m::Optimizer, ::MOI.TerminationStatus)
end
end

function MOI.get(m::Optimizer, ::MOI.PrimalStatus)
function MOI.get(m::Optimizer, attr::MOI.PrimalStatus)
if attr.N > MOI.get(m, MOI.ResultCount())
return MOI.NO_SOLUTION
end
status = getPhaseValue(m.problem)
if status == noINFO
return MOI.UNKNOWN_RESULT_STATUS
Expand All @@ -289,7 +298,10 @@ function MOI.get(m::Optimizer, ::MOI.PrimalStatus)
end
end

function MOI.get(m::Optimizer, ::MOI.DualStatus)
function MOI.get(m::Optimizer, attr::MOI.DualStatus)
if attr.N > MOI.get(m, MOI.ResultCount())
return MOI.NO_SOLUTION
end
status = getPhaseValue(m.problem)
if status == noINFO
return MOI.UNKNOWN_RESULT_STATUS
Expand All @@ -314,11 +326,13 @@ function MOI.get(m::Optimizer, ::MOI.DualStatus)
end
end

MOI.get(m::Optimizer, ::MOI.ResultCount) = 1
function MOI.get(m::Optimizer, ::MOI.ObjectiveValue)
MOI.get(m::Optimizer, ::MOI.ResultCount) = m.problem === nothing ? 0 : 1
function MOI.get(m::Optimizer, attr::MOI.ObjectiveValue)
MOI.check_result_index_bounds(m, attr)
return m.objsign * getPrimalObj(m.problem) + m.objconstant
end
function MOI.get(m::Optimizer, ::MOI.DualObjectiveValue)
function MOI.get(m::Optimizer, attr::MOI.DualObjectiveValue)
MOI.check_result_index_bounds(m, attr)
return m.objsign * getDualObj(m.problem) + m.objconstant
end
struct PrimalSolutionMatrix <: MOI.AbstractModelAttribute end
Expand Down Expand Up @@ -365,23 +379,28 @@ function vectorize_block(M::AbstractMatrix{Cdouble}, blk::Integer, s::Type{MOI.P
return v
end

function MOI.get(optimizer::Optimizer, ::MOI.VariablePrimal, vi::MOI.VariableIndex)
function MOI.get(optimizer::Optimizer, attr::MOI.VariablePrimal, vi::MOI.VariableIndex)
MOI.check_result_index_bounds(optimizer, attr)
blk, i, j = varmap(optimizer, vi)
return block(MOI.get(optimizer, PrimalSolutionMatrix()), blk)[i, j]
end

function MOI.get(optimizer::Optimizer, ::MOI.ConstraintPrimal,
function MOI.get(optimizer::Optimizer, attr::MOI.ConstraintPrimal,
ci::MOI.ConstraintIndex{MOI.VectorOfVariables, S}) where S<:SupportedSets
MOI.check_result_index_bounds(optimizer, attr)
return vectorize_block(MOI.get(optimizer, PrimalSolutionMatrix()), block(optimizer, ci), S)
end
function MOI.get(m::Optimizer, ::MOI.ConstraintPrimal, ci::AFFEQ)
function MOI.get(m::Optimizer, attr::MOI.ConstraintPrimal, ci::AFFEQ)
MOI.check_result_index_bounds(m, attr)
return m.b[ci.value]
end

function MOI.get(optimizer::Optimizer, ::MOI.ConstraintDual,
function MOI.get(optimizer::Optimizer, attr::MOI.ConstraintDual,
ci::MOI.ConstraintIndex{MOI.VectorOfVariables, S}) where S<:SupportedSets
MOI.check_result_index_bounds(optimizer, attr)
return vectorize_block(MOI.get(optimizer, DualSlackMatrix()), block(optimizer, ci), S)
end
function MOI.get(optimizer::Optimizer, ::MOI.ConstraintDual, ci::AFFEQ)
function MOI.get(optimizer::Optimizer, attr::MOI.ConstraintDual, ci::AFFEQ)
MOI.check_result_index_bounds(optimizer, attr)
return -MOI.get(optimizer, DualSolutionVector())[ci.value]
end
6 changes: 4 additions & 2 deletions test/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const config = MOIT.TestConfig(atol=1e-3, rtol=1e-3)

@testset "Unit" begin
MOIT.unittest(bridged, config, [
# `NumberOfThreads` not supported.
"number_threads",
# `TimeLimitSec` not supported.
"time_limit_sec",
# SingleVariable objective of bridged variables, will be solved by objective bridges
Expand All @@ -53,9 +55,9 @@ end
end
@testset "Conic tests" begin
MOIT.contconictest(bridged, config, [
"lin3", "soc3",
"lin3", "soc3", "normone2", "norminf2",
# Missing bridges
"rootdets",
# Does not support power and exponential cone
"pow", "logdet", "exp"])
"pow", "dualpow", "logdet", "exp", "dualexp"])
end

0 comments on commit 3e99417

Please sign in to comment.