Skip to content

Commit

Permalink
DeprecatedTest -> Test (#15)
Browse files Browse the repository at this point in the history
* DeprecatedTest -> Test

* Update do MOI v1
  • Loading branch information
blegat authored Feb 26, 2022
1 parent eceba3b commit e9b3f5e
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 88 deletions.
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "SDPT3"
uuid = "e33b2407-87ff-50a0-8b27-f0fe7855237d"
repo = "https://github.com/jump-dev/SDPT3.jl.git"
version = "0.0.3"
version = "0.1.0"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand All @@ -11,8 +11,8 @@ SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[compat]
MATLAB = "0.7, 0.8"
MathOptInterface = "0.10.4"
julia = "1"
MathOptInterface = "1"
julia = "1.6"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
27 changes: 11 additions & 16 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ mutable struct Optimizer <: MOI.AbstractOptimizer

silent::Bool
options::Dict{Symbol, Any}
function Optimizer(; kwargs...)
optimizer = new(
function Optimizer()
return new(
Float64[], VariableInfo[],
Int[], Vector{Int}[], Vector{Float64}[], Vector{Int}[], Vector{Int}[], Vector{Float64}[],
Int[], Vector{Int}[], Vector{Float64}[], Vector{Int}[], Vector{Int}[], Vector{Float64}[],
Expand All @@ -86,20 +86,8 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
Float64[], Float64[], Vector{Float64}[], Vector{Float64}[], # Z
Dict{String, Any}(), Dict{String, Any}(),
nothing, NaN,
false, Dict{Symbol, Any}())
if !isempty(kwargs)
@warn("""Passing optimizer attributes as keyword arguments to
SDPT3.Optimizer is deprecated. Use
MOI.set(model, MOI.RawOptimizerAttribute("key"), value)
or
JuMP.set_optimizer_attribute(model, "key", value)
instead.
""")
end
for (key, value) in kwargs
MOI.set(optimizer, MOI.RawOptimizerAttribute(string(key)), value)
end
return optimizer
false, Dict{Symbol, Any}(),
)
end
end

Expand Down Expand Up @@ -340,6 +328,9 @@ function MOI.add_constraint(optimizer::Optimizer, func::MOI.ScalarAffineFunction
end
push!(optimizer.b, MOI.constant(set))
con = length(optimizer.b)
if isempty(func.terms)
throw(ArgumentError("SDPT3 does not support equality constraints with no term: 0 == $(MOI.constant(set))."))
end
for term in func.terms
info = optimizer.variable_info[term.variable.value]
if info.variable_type == FREE
Expand Down Expand Up @@ -556,11 +547,15 @@ end
MOI.get(::Optimizer, ::MOI.ResultCount) = 1
function MOI.get(optimizer::Optimizer, attr::MOI.ObjectiveValue)
MOI.check_result_index_bounds(optimizer, attr)
# FIXME For `INFEASIBILITY_CERTIFICATE`, SDPT3 just returns infinite values
# See https://github.com/jump-dev/MathOptInterface.jl/issues/1759
sign = sense_to_sign(optimizer.objective_sense)
return sign * optimizer.primal_objective_value + optimizer.objective_constant
end
function MOI.get(optimizer::Optimizer, attr::MOI.DualObjectiveValue)
MOI.check_result_index_bounds(optimizer, attr)
# FIXME For `INFEASIBILITY_CERTIFICATE`, SDPT3 just returns infinite values
# See https://github.com/jump-dev/MathOptInterface.jl/issues/1759
sign = sense_to_sign(optimizer.objective_sense)
return sign * optimizer.dual_objective_value + optimizer.objective_constant
end
Expand Down
3 changes: 3 additions & 0 deletions src/SDPT3.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ function sdpt3(blk::Matrix,
options = Dict{String, Any}(string(key) => value for (key, value) in kws)
@assert all(i -> size(At[i], 2) == length(b), 1:length(At))
@assert length(At) == size(blk, 1)
if isempty(b)
throw(ArgumentError("SDPT3 does not support problems with no constraint."))
end
#@assert all(i -> size(A[i], 1) == dim(blk[i, 1], blk[i, 2]), 1:length(A))
#@assert all(i -> length(C[i], 1) == dim(blk[i, 1], blk[i, 2]), 1:length(A))
# There are 6 output arguments so we use `6` below
Expand Down
201 changes: 132 additions & 69 deletions test/MOI_wrapper.jl
Original file line number Diff line number Diff line change
@@ -1,85 +1,148 @@
using Test
module TestSDPT3

using Test
using MathOptInterface
const MOI = MathOptInterface
const MOIT = MOI.DeprecatedTest
const MOIU = MOI.Utilities
const MOIB = MOI.Bridges

import SDPT3
const OPTIMIZER = SDPT3.Optimizer()
MOI.set(OPTIMIZER, MOI.Silent(), true)

@testset "SolverName" begin
@test MOI.get(OPTIMIZER, MOI.SolverName()) == "SDPT3"
const MOI = MathOptInterface

function runtests()
for name in names(@__MODULE__; all = true)
if startswith("$(name)", "test_")
@testset "$(name)" begin
getfield(@__MODULE__, name)()
end
end
end
return
end

@testset "supports_incremental_interface" begin
@test MOI.supports_incremental_interface(OPTIMIZER)
function test_solver_name()
@test MOI.get(SDPT3.Optimizer(), MOI.SolverName()) == "SDPT3"
end

# UniversalFallback is needed for starting values, even if they are ignored by SDPT3
const CACHE = MOIU.UniversalFallback(MOIU.Model{Float64}())
const CACHED = MOIU.CachingOptimizer(CACHE, OPTIMIZER)
const BRIDGED = MOIB.full_bridge_optimizer(CACHED, Float64)
const CONFIG = MOIT.Config(atol=1e-4, rtol=1e-4)
function test_supports_incremental_interface()
@test MOI.supports_incremental_interface(SDPT3.Optimizer())
end

@testset "Options" begin
optimizer = SDPT3.Optimizer(printlevel = 1)
function test_options()
optimizer = SDPT3.Optimizer()
MOI.set(optimizer, MOI.RawOptimizerAttribute("printlevel"), 1)
@test MOI.get(optimizer, MOI.RawOptimizerAttribute("printlevel")) == 1

param = MOI.RawOptimizerAttribute("bad_option")
err = MOI.UnsupportedAttribute(param)
@test_throws err SDPT3.Optimizer(bad_option = 1)
@test_throws err MOI.set(optimizer, MOI.RawOptimizerAttribute("bad_option"), 1)
end

@testset "Unit" begin
MOIT.unittest(BRIDGED, CONFIG, [
# Need MOI v0.9.5
"solve_result_index",
# Get `termcode` -1, i.e. "relative gap < infeasibility".
"solve_blank_obj",
# Get `termcode` 3, i.e. "norm(X) or norm(Z) diverging".
"solve_affine_equalto",
# Fails because there is no constraint.
"solve_unbounded_model",
# `TimeLimitSec` not supported.
"time_limit_sec",
# `NumberOfThreads` not supported.
"number_threads",
# Integer and ZeroOne sets are not supported
"solve_integer_edge_cases", "solve_objbound_edge_cases",
"solve_zero_one_with_bounds_1",
"solve_zero_one_with_bounds_2",
"solve_zero_one_with_bounds_3"])
end
@testset "Continuous Linear" begin
# See explanation in `MOI/test/Bridges/lazy_bridge_OPTIMIZER.jl`.
# This is to avoid `Variable.VectorizeBridge` which does not support
# `ConstraintSet` modification.
MOIB.remove_bridge(BRIDGED, MOIB.Constraint.ScalarSlackBridge{Float64})
MOIT.contlineartest(BRIDGED, CONFIG, String[
# Throws error: total dimension of C should be > length(b)
"linear15",
"partial_start"
])
end
@testset "Continuous Quadratic" begin
MOIT.contquadratictest(BRIDGED, CONFIG, [
# Non-convex
"ncqcp",
# Quadratic function not strictly convex
"socp"])
end
@testset "Continuous Conic" begin
MOIT.contconictest(BRIDGED, CONFIG, [
# `MOI.OTHER_ERROR`
"lin2f", "geomean3v",
# `MOI.NUMERICAL_ERROR`
"lin4",
# `ExponentialCone` and `PowerCone` not supported.
"exp", "dualexp", "pow", "dualpow", "logdet", "relentr",
# `RootDetConeSquare` -> `RootDetConeTriangle` bridge missing.
"rootdets"
])
function test_runtests()
model = MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
MOI.Bridges.full_bridge_optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
SDPT3.Optimizer(),
),
Float64,
),
# This does not work as with some modifications, the bridges with try
# getting `ConstraintFunction` which is not supported by SDPT3
#MOI.instantiate(SDPT3.Optimizer, with_bridge_type=Float64),
)
# `Variable.ZerosBridge` makes dual needed by some tests fail.
MOI.Bridges.remove_bridge(model.optimizer, MathOptInterface.Bridges.Variable.ZerosBridge{Float64})
MOI.set(model, MOI.Silent(), true)
MOI.Test.runtests(
model,
MOI.Test.Config(
rtol = 1e-4,
atol = 1e-4,
exclude = Any[
MOI.ConstraintBasisStatus,
MOI.VariableBasisStatus,
MOI.ObjectiveBound,
MOI.SolverVersion,
],
),
exclude = String[
# Expected test failures:
#"test_attribute_SolverVersion",
# TODO Remove when https://github.com/jump-dev/MathOptInterface.jl/issues/1758 is fixed
"test_model_copy_to_UnsupportedAttribute",
# `NUMERICAL_ERROR`
"test_conic_linear_INFEASIBLE_2",
"test_solve_DualStatus_INFEASIBILITY_CERTIFICATE_EqualTo_upper",
"test_solve_DualStatus_INFEASIBILITY_CERTIFICATE_EqualTo_lower",
"test_solve_DualStatus_INFEASIBILITY_CERTIFICATE_GreaterThan",
"test_solve_DualStatus_INFEASIBILITY_CERTIFICATE_Interval_upper",
"test_solve_DualStatus_INFEASIBILITY_CERTIFICATE_LessThan",
"test_solve_DualStatus_INFEASIBILITY_CERTIFICATE_VariableIndex_LessThan",
"test_modification_const_vectoraffine_zeros",
"test_constraint_ScalarAffineFunction_EqualTo",
# `OTHER_ERROR`
"test_conic_linear_VectorAffineFunction_2",
"test_conic_GeometricMeanCone_VectorOfVariables_3",
# ArgumentError: SDPT3 does not support problems with no constraint.
"test_solve_optimize_twice",
"test_solve_result_index",
"test_quadratic_nonhomogeneous",
"test_quadratic_integration",
"test_objective_ObjectiveFunction_constant",
"test_objective_ObjectiveFunction_VariableIndex",
"test_objective_FEASIBILITY_SENSE_clears_objective",
"test_modification_transform_singlevariable_lessthan",
"test_modification_set_singlevariable_lessthan",
"test_modification_delete_variables_in_a_batch",
"test_modification_delete_variable_with_single_variable_obj",
"test_modification_const_scalar_objective",
"test_modification_coef_scalar_objective",
"test_attribute_RawStatusString",
"test_attribute_SolveTimeSec",
"test_objective_ObjectiveFunction_blank",
"test_objective_ObjectiveFunction_duplicate_terms",
"test_solve_TerminationStatus_DUAL_INFEASIBLE",
# ArgumentError: SDPT3 does not support equality constraints with no term
"test_linear_VectorAffineFunction_empty_row",
"test_conic_PositiveSemidefiniteConeTriangle",
# FIXME
# Expression: ≈(MOI.get(model, MOI.ConstraintPrimal(), c2), 0, atol = atol, rtol = rtol)
# Evaluated: 1.7999998823840366 ≈ 0 (atol=0.0001, rtol=0.0001)
"test_linear_FEASIBILITY_SENSE",
# FIXME
# Error using pretransfo (line 149)
# Size b mismatch
"test_conic_SecondOrderCone_negative_post_bound_ii",
"test_conic_SecondOrderCone_negative_post_bound_iii",
"test_conic_SecondOrderCone_no_initial_bound",
# TODO SDPT3 just returns an infinite ObjectiveValue
"test_unbounded_MIN_SENSE",
"test_unbounded_MIN_SENSE_offset",
"test_unbounded_MAX_SENSE",
"test_unbounded_MAX_SENSE_offset",
# TODO SDPT3 just returns an infinite DualObjectiveValue
"test_infeasible_MAX_SENSE",
"test_infeasible_MAX_SENSE_offset",
"test_infeasible_MIN_SENSE",
"test_infeasible_MIN_SENSE_offset",
"test_infeasible_affine_MAX_SENSE",
"test_infeasible_affine_MAX_SENSE_offset",
"test_infeasible_affine_MIN_SENSE",
"test_infeasible_affine_MIN_SENSE_offset",
# TODO investigate
"test_conic_GeometricMeanCone_VectorAffineFunction_2",
"test_conic_GeometricMeanCone_VectorOfVariables_2",
"test_objective_qp_ObjectiveFunction_edge_cases",
"test_objective_qp_ObjectiveFunction_zero_ofdiag",
"test_variable_solve_with_lowerbound",
# FIXME
# test_linear_DUAL_INFEASIBLE_2: Test Failed at /home/blegat/.julia/packages/MathOptInterface/IIN1o/src/Test/test_linear.jl:1514
# Expression: MOI.get(model, MOI.TerminationStatus()) == MOI.DUAL_INFEASIBLE || MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE_OR_UNBOUNDED
"test_linear_DUAL_INFEASIBLE_2",
],
)
return
end

end # module

TestSDPT3.runtests()

2 comments on commit e9b3f5e

@blegat
Copy link
Member Author

@blegat blegat commented on e9b3f5e Feb 26, 2022

Choose a reason for hiding this comment

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

@JuliaRegistrator register()

@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/55526

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.1.0 -m "<description of version>" e9b3f5e713beb9222c6a8bbcfc9732368cdae29c
git push origin v0.1.0

Please sign in to comment.