From 5508edcbfd87b9ea160c741a60fee3d09d4c11b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Tue, 28 Sep 2021 16:47:45 +0200 Subject: [PATCH 1/8] remove deprecated calls --- test/runtests.jl | 6 ++++-- test/test_jump.jl | 10 +++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index fc9cf60..a2c8c6d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -15,7 +15,8 @@ const MOIB = MOI.Bridges const FALLBACK_URL = "mosek://solve.mosek.com:30080" using MosekTools -const optimizer = Mosek.Optimizer(fallback = FALLBACK_URL) +const optimizer = Mosek.Optimizer() +MOI.set(optimizer, MOI.RawParameter("fallback"), FALLBACK_URL) MOI.set(optimizer, MOI.Silent(), true) @testset "SolverName" begin @@ -23,7 +24,8 @@ MOI.set(optimizer, MOI.Silent(), true) end @testset "Parameters" begin - optimizer = Mosek.Optimizer(fallback = FALLBACK_URL) + optimizer = Mosek.Optimizer() + MOI.set(optimizer, MOI.RawParameter("fallback"), FALLBACK_URL) @testset "Double Parameter" begin MOI.set(optimizer, MOI.RawParameter("INTPNT_CO_TOL_DFEAS"), 1e-7) @test MOI.get(optimizer, MOI.RawParameter("MSK_DPAR_INTPNT_CO_TOL_DFEAS")) == 1e-7 diff --git a/test/test_jump.jl b/test/test_jump.jl index c82bcb8..807f97c 100644 --- a/test/test_jump.jl +++ b/test/test_jump.jl @@ -7,7 +7,11 @@ include("jump_lp.jl") include("jump_soc.jl") @testset "JuMP tests" begin - test_jump_lp(Mosek.Optimizer(LOG=0)) - test_jump_soc(Mosek.Optimizer(LOG=0)) - test_jump_sdp(Mosek.Optimizer(LOG=0)) + o = Mosek.Optimizer() + MOI.set(o, MOI.RawParameter("LOG"), 0) + test_jump_lp() + MOI.empty!(o) + test_jump_soc(o) + MOI.empty!(o) + test_jump_sdp(o) end From 8978a7dbd532aeeac0b9314a70020092400614ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Tue, 28 Sep 2021 18:10:36 +0200 Subject: [PATCH 2/8] start MOI 10 --- Project.toml | 2 +- src/MosekTools.jl | 22 ++++++------- src/attributes.jl | 48 +++++++++++++-------------- src/constraint.jl | 39 +++++++++++----------- src/objective.jl | 4 +-- src/variable.jl | 2 +- test/runtests.jl | 82 +++++++++++++++++++++++++++++++---------------- test/test_jump.jl | 2 +- 8 files changed, 114 insertions(+), 87 deletions(-) diff --git a/Project.toml b/Project.toml index d7b5229..79db5cd 100644 --- a/Project.toml +++ b/Project.toml @@ -9,7 +9,7 @@ Mosek = "6405355b-0ac2-5fba-af84-adbd65488c0e" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" [compat] -MathOptInterface = "0.9.17" +MathOptInterface = "0.10" Mosek = "1" julia = "1" diff --git a/src/MosekTools.jl b/src/MosekTools.jl index 040ea48..710d060 100644 --- a/src/MosekTools.jl +++ b/src/MosekTools.jl @@ -156,14 +156,14 @@ mutable struct Optimizer <: MOI.AbstractOptimizer if length(kws) > 0 @warn("""Passing optimizer attributes as keyword arguments to Mosek.Optimizer is deprecated. Use - MOI.set(model, MOI.RawParameter("key"), value) + MOI.set(model, MOI.RawOptimizerAttribute("key"), value) or JuMP.set_optimizer_attribute(model, "key", value) instead. """) end for (option, value) in kws - MOI.set(optimizer, MOI.RawParameter(string(option)), value) + MOI.set(optimizer, MOI.RawOptimizerAttribute(string(option)), value) end return optimizer end @@ -205,7 +205,7 @@ function MOI.get(m::Optimizer, p::StringParameter) return str end -function MOI.set(m::Optimizer, p::MOI.RawParameter, value) +function MOI.set(m::Optimizer, p::MOI.RawOptimizerAttribute, value) if p.name == "QUIET" if m.be_quiet != convert(Bool, value) m.be_quiet = !m.be_quiet @@ -239,7 +239,7 @@ function MOI.set(m::Optimizer, p::MOI.RawParameter, value) end end -function MOI.get(m::Optimizer, p::MOI.RawParameter) +function MOI.get(m::Optimizer, p::MOI.RawOptimizerAttribute) if p.name == "QUIET" return m.be_quiet elseif p.name == "fallback" @@ -260,21 +260,21 @@ end MOI.supports(::Optimizer, ::MOI.Silent) = true function MOI.set(model::Optimizer, ::MOI.Silent, value::Bool) - MOI.set(model, MOI.RawParameter("QUIET"), value) + MOI.set(model, MOI.RawOptimizerAttribute("QUIET"), value) end function MOI.get(model::Optimizer, ::MOI.Silent) - MOI.get(model, MOI.RawParameter("QUIET")) + MOI.get(model, MOI.RawOptimizerAttribute("QUIET")) end MOI.supports(::Optimizer, ::MOI.TimeLimitSec) = true function MOI.set(model::Optimizer, ::MOI.TimeLimitSec, value::Real) - MOI.set(model, MOI.RawParameter("MSK_DPAR_OPTIMIZER_MAX_TIME"), value) + MOI.set(model, MOI.RawOptimizerAttribute("MSK_DPAR_OPTIMIZER_MAX_TIME"), value) end function MOI.set(model::Optimizer, ::MOI.TimeLimitSec, ::Nothing) - MOI.set(model, MOI.RawParameter("MSK_DPAR_OPTIMIZER_MAX_TIME"), -1.0) + MOI.set(model, MOI.RawOptimizerAttribute("MSK_DPAR_OPTIMIZER_MAX_TIME"), -1.0) end function MOI.get(model::Optimizer, ::MOI.TimeLimitSec) - value = MOI.get(model, MOI.RawParameter("MSK_DPAR_OPTIMIZER_MAX_TIME")) + value = MOI.get(model, MOI.RawOptimizerAttribute("MSK_DPAR_OPTIMIZER_MAX_TIME")) if value < 0.0 return nothing else @@ -420,7 +420,7 @@ end #function supportsconstraints(m::MosekSolver, constraint_types) :: Bool # for (fun,dom) in constraint_types # if fun in [MOI.ScalarAffineFunction{Float64}, -# MOI.SingleVariable, +# MOI.VariableIndex, # MOI.VectorOfVariables] && # dom in [MOI.GreaterThan{Float64}, # MOI.LessThan{Float64}, @@ -431,7 +431,7 @@ end # MOI.PositiveSemidefiniteConeTriangle, # MOI.PositiveSemidefiniteConeScaled ] # # ok -# elseif dom == MOI.Integer && fun in [MOI.SingleVariable, MOI.VectorOfVariables] +# elseif dom == MOI.Integer && fun in [MOI.VariableIndex, MOI.VectorOfVariables] # # ok # else # return false diff --git a/src/attributes.jl b/src/attributes.jl index 9f20081..7c8830b 100644 --- a/src/attributes.jl +++ b/src/attributes.jl @@ -70,7 +70,7 @@ MOI.get(m::Optimizer,attr::MOI.ObjectiveBound) = getdouinf(m.task,MSK_DINF_MIO_O MOI.get(m::Optimizer,attr::MOI.RelativeGap) = getdouinf(m.task,MSK_DINF_MIO_OBJ_REL_GAP) -MOI.get(m::Optimizer,attr::MOI.SolveTime) = getdouinf(m.task,MSK_DINF_OPTIMIZER_TIME) +MOI.get(m::Optimizer,attr::MOI.SolveTimeSec) = getdouinf(m.task,MSK_DINF_OPTIMIZER_TIME) # NOTE: The MOSEK interface currently only supports Min and Max @@ -152,16 +152,16 @@ function MOI.get(model::Optimizer, return [MOI.ConstraintIndex{F, S}(id) for id in ids] end function MOI.get(model::Optimizer, - ::MOI.NumberOfConstraints{MOI.SingleVariable, S}) where S<:Union{ScalarLinearDomain, + ::MOI.NumberOfConstraints{MOI.VariableIndex, S}) where S<:Union{ScalarLinearDomain, MOI.Integer} - F = MOI.SingleVariable + F = MOI.VariableIndex return count(id -> MOI.is_valid(model, MOI.ConstraintIndex{F, S}(id)), allocatedlist(model.x_block)) end function MOI.get(model::Optimizer, - ::MOI.ListOfConstraintIndices{MOI.SingleVariable, S}) where S<:Union{ScalarLinearDomain, + ::MOI.ListOfConstraintIndices{MOI.VariableIndex, S}) where S<:Union{ScalarLinearDomain, MOI.Integer} - F = MOI.SingleVariable + F = MOI.VariableIndex ids = filter(id -> MOI.is_valid(model, MOI.ConstraintIndex{F, S}(id)), allocatedlist(model.x_block)) return [MOI.ConstraintIndex{F, S}(id) for id in ids] @@ -194,9 +194,9 @@ function MOI.get(model::Optimizer, end function MOI.get(model::Optimizer, - ::MOI.ListOfConstraints) + ::MathOptInterface.ListOfConstraintTypesPresent) list = Tuple{DataType, DataType}[] - F = MOI.SingleVariable + F = MOI.VariableIndex for D in [MOI.LessThan{Float64}, MOI.GreaterThan{Float64}, MOI.EqualTo{Float64}, MOI.Interval{Float64}, MOI.Integer] @@ -262,7 +262,7 @@ end function MOI.get(m::Optimizer, attr::MOI.VariablePrimal, vi::MOI.VariableIndex) MOI.check_result_index_bounds(m, attr) - return variable_primal(m, attr.N, vi) + return variable_primal(m, attr.result_index, vi) end function MOI.get!(output::Vector{Float64}, m::Optimizer, attr::MOI.VariablePrimal, vs::Vector{MOI.VariableIndex}) @@ -285,10 +285,10 @@ end function MOI.get( m ::Optimizer, attr ::MOI.ConstraintPrimal, - ci ::MOI.ConstraintIndex{MOI.SingleVariable,D}) where D + ci ::MOI.ConstraintIndex{MOI.VariableIndex,D}) where D MOI.check_result_index_bounds(m, attr) col = column(m, _variable(ci)) - return m.solutions[attr.N].xx[col.value] + return m.solutions[attr.result_index].xx[col.value] end # Semidefinite domain for a variable @@ -299,7 +299,7 @@ function MOI.get!( ci ::MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}) MOI.check_result_index_bounds(m, attr) - whichsol = getsolcode(m,attr.N) + whichsol = getsolcode(m,attr.result_index) output[1:length(output)] = reorder(getbarxj(m.task, whichsol, ci.value), MOI.PositiveSemidefiniteConeTriangle) end @@ -312,7 +312,7 @@ function MOI.get!( ci ::MOI.ConstraintIndex{MOI.VectorOfVariables,D}) where D MOI.check_result_index_bounds(m, attr) cols = columns(m, ci) - output[1:length(output)] = reorder(m.solutions[attr.N].xx[cols.values], D) + output[1:length(output)] = reorder(m.solutions[attr.result_index].xx[cols.values], D) end function MOI.get(m ::Optimizer, @@ -321,7 +321,7 @@ function MOI.get(m ::Optimizer, MOI.check_result_index_bounds(m, attr) cid = ref2id(ci) subi = getindex(m.c_block,cid) - return m.solutions[attr.N].xc[subi] + return m.solutions[attr.result_index].xc[subi] end function _variable_constraint_dual(sol::MosekSolution, col::ColumnIndex, @@ -335,10 +335,10 @@ function _variable_constraint_dual(sol::MosekSolution, col::ColumnIndex, ::Type{ return -sol.sux[col.value] end function MOI.get(m::Optimizer, attr::MOI.ConstraintDual, - ci::MOI.ConstraintIndex{MOI.SingleVariable, S}) where S <: ScalarLinearDomain + ci::MOI.ConstraintIndex{MOI.VariableIndex, S}) where S <: ScalarLinearDomain MOI.check_result_index_bounds(m, attr) col = column(m, _variable(ci)) - dual = _variable_constraint_dual(m.solutions[attr.N], col, S) + dual = _variable_constraint_dual(m.solutions[attr.result_index], col, S) if getobjsense(m.task) == MSK_OBJECTIVE_SENSE_MINIMIZE return dual else @@ -378,7 +378,7 @@ function MOI.get!( attr ::MOI.ConstraintDual, ci ::MOI.ConstraintIndex{MOI.VectorOfVariables, MOI.PositiveSemidefiniteConeTriangle}) MOI.check_result_index_bounds(m, attr) - whichsol = getsolcode(m,attr.N) + whichsol = getsolcode(m,attr.result_index) # It is in fact a real constraint and cid is the id of an ordinary constraint dual = reorder(getbarsj(m.task, whichsol, ci.value), MOI.PositiveSemidefiniteConeTriangle) @@ -405,9 +405,9 @@ function MOI.get!( idx = reorder(1:length(output), D) if (getobjsense(m.task) == MSK_OBJECTIVE_SENSE_MINIMIZE) - output[idx] = m.solutions[attr.N].snx[cols.values] + output[idx] = m.solutions[attr.result_index].snx[cols.values] else - output[idx] = -m.solutions[attr.N].snx[cols.values] + output[idx] = -m.solutions[attr.result_index].snx[cols.values] end end @@ -420,9 +420,9 @@ function MOI.get(m ::Optimizer, subi = getindex(m.c_block, cid) if getobjsense(m.task) == MSK_OBJECTIVE_SENSE_MINIMIZE - m.solutions[attr.N].y[subi] + m.solutions[attr.result_index].y[subi] else - - m.solutions[attr.N].y[subi] + - m.solutions[attr.result_index].y[subi] end end @@ -502,10 +502,10 @@ function MOI.get(m::Optimizer, attr::MOI.TerminationStatus) end function MOI.get(m::Optimizer, attr::MOI.PrimalStatus) - if attr.N > MOI.get(m, MOI.ResultCount()) + if attr.result_index > MOI.get(m, MOI.ResultCount()) return MOI.NO_SOLUTION end - solsta = m.solutions[attr.N].solsta + solsta = m.solutions[attr.result_index].solsta if solsta == MSK_SOL_STA_UNKNOWN MOI.UNKNOWN_RESULT_STATUS elseif solsta == MSK_SOL_STA_OPTIMAL @@ -532,10 +532,10 @@ function MOI.get(m::Optimizer, attr::MOI.PrimalStatus) end function MOI.get(m::Optimizer,attr::MOI.DualStatus) - if attr.N > MOI.get(m, MOI.ResultCount()) + if attr.result_index > MOI.get(m, MOI.ResultCount()) return MOI.NO_SOLUTION end - solsta = m.solutions[attr.N].solsta + solsta = m.solutions[attr.result_index].solsta if solsta == MSK_SOL_STA_UNKNOWN MOI.UNKNOWN_RESULT_STATUS elseif solsta == MSK_SOL_STA_OPTIMAL diff --git a/src/constraint.jl b/src/constraint.jl index db2f533..8b59276 100644 --- a/src/constraint.jl +++ b/src/constraint.jl @@ -49,7 +49,7 @@ function split_scalar_matrix(m::Optimizer, terms::Vector{MOI.ScalarAffineTerm{Fl push!(sd_coef[mat.matrix], coef) end for term in terms - add(mosek_index(m, term.variable_index), term.coefficient) + add(mosek_index(m, term.variable), term.coefficient) end for j in 1:length(m.sd_dim) if !isempty(sd_row[j]) @@ -224,7 +224,7 @@ function add_variable_constraint(m::Optimizer, col::ColumnIndex, end function get_variable_constraint(m::Optimizer, col::ColumnIndex, - ci::MOI.ConstraintIndex{MOI.SingleVariable, S}) where S + ci::MOI.ConstraintIndex{MOI.VariableIndex, S}) where S return bounds_to_set(S, getvarbound(m.task, col.value)...) end function get_variable_constraint(m::Optimizer, vi::MOI.VariableIndex, @@ -335,9 +335,9 @@ const ScalarLinearDomain = Union{MOI.LessThan{Float64}, ## Add ######################################################################## ############################################################################### -MOI.supports_constraint(::Optimizer, ::Type{<:Union{MOI.SingleVariable, MOI.ScalarAffineFunction}}, ::Type{<:ScalarLinearDomain}) = true +MOI.supports_constraint(::Optimizer, ::Type{<:Union{MOI.VariableIndex, MOI.ScalarAffineFunction}}, ::Type{<:ScalarLinearDomain}) = true MOI.supports_constraint(::Optimizer, ::Type{MOI.VectorOfVariables}, ::Type{<:VectorCone}) = true -MOI.supports_constraint(::Optimizer, ::Type{MOI.SingleVariable}, ::Type{<:MOI.Integer}) = true +MOI.supports_constraint(::Optimizer, ::Type{MOI.VariableIndex}, ::Type{<:MOI.Integer}) = true MOI.supports_add_constrained_variables(::Optimizer, ::Type{MOI.PositiveSemidefiniteConeTriangle}) = true ## Affine Constraints ######################################################### @@ -389,23 +389,24 @@ cone_type(::Type{MOI.RotatedSecondOrderCone}) = MSK_CT_RQUAD function MOI.add_constraint( m :: Optimizer, - xs :: MOI.SingleVariable, + xs :: MOI.VariableIndex, dom :: D) where {D <: MOI.AbstractScalarSet} - msk_idx = mosek_index(m, xs.variable) + msk_idx = mosek_index(m, xs) if !(msk_idx isa ColumnIndex) error("Cannot add $D constraint on a matrix variable") end - if !iszero(incompatible_mask(D) & m.x_constraints[xs.variable.value]) + if !iszero(incompatible_mask(D) & m.x_constraints[xs.value]) error("Cannot put multiple bound sets of the same type on a variable") + # throw(MOI.LowerBoundAlreadySet{?, D}(xs)) # TODO find which set was the initial constraint end - set_flag(m, xs.variable, D) + set_flag(m, xs, D) add_variable_constraint(m, msk_idx, dom) - return MOI.ConstraintIndex{MOI.SingleVariable, D}(xs.variable.value) + return MOI.ConstraintIndex{MOI.VariableIndex, D}(xs.value) end function MOI.add_constraint(m::Optimizer, xs::MOI.VectorOfVariables, @@ -457,22 +458,22 @@ end ## Get ######################################################################## ############################################################################### -_variable(ci::MOI.ConstraintIndex{MOI.SingleVariable}) = MOI.VariableIndex(ci.value) +_variable(ci::MOI.ConstraintIndex{MOI.VariableIndex}) = MOI.VariableIndex(ci.value) function MOI.get(m::Optimizer, ::MOI.ConstraintFunction, - ci::MOI.ConstraintIndex{MOI.SingleVariable}) where S <: ScalarLinearDomain + ci::MOI.ConstraintIndex{MOI.VariableIndex}) where S <: ScalarLinearDomain MOI.throw_if_not_valid(m, ci) - return MOI.SingleVariable(_variable(ci)) + return _variable(ci) end function MOI.get(m::Optimizer, ::MOI.ConstraintSet, - ci::MOI.ConstraintIndex{MOI.SingleVariable, S}) where S <: MOI.Integer + ci::MOI.ConstraintIndex{MOI.VariableIndex, S}) where S <: MOI.Integer MOI.throw_if_not_valid(m, ci) return S() end function MOI.get(m::Optimizer, ::MOI.ConstraintSet, - ci::MOI.ConstraintIndex{MOI.SingleVariable, S}) where S <: ScalarLinearDomain + ci::MOI.ConstraintIndex{MOI.VariableIndex, S}) where S <: ScalarLinearDomain MOI.throw_if_not_valid(m, ci) - sv = MOI.get(m, MOI.ConstraintFunction(), ci) - return get_variable_constraint(m, sv.variable, ci) + vi = MOI.get(m, MOI.ConstraintFunction(), ci) + return get_variable_constraint(m, vi, ci) end function MOI.get(m::Optimizer, ::MOI.ConstraintFunction, @@ -539,7 +540,7 @@ chgbound(bl::Float64,bu::Float64,k::Float64,dom :: MOI.Interval{Float64}) = d function MOI.set(m::Optimizer, ::MOI.ConstraintSet, - ci::MOI.ConstraintIndex{MOI.SingleVariable,D}, + ci::MOI.ConstraintIndex{MOI.VariableIndex,D}, dom::D) where D<:ScalarLinearDomain col = column(m, _variable(ci)) bk, bl, bu = getvarbound(m.task, col.value) @@ -628,14 +629,14 @@ function MOI.delete( end function MOI.is_valid(model::Optimizer, - ci::MOI.ConstraintIndex{MOI.SingleVariable, + ci::MOI.ConstraintIndex{MOI.VariableIndex, S}) where S<:Union{ScalarLinearDomain, MOI.Integer} return allocated(model.x_block, ci.value) && has_flag(model, _variable(ci), S) end function MOI.delete( m::Optimizer, - ci::MOI.ConstraintIndex{MOI.SingleVariable, S}) where S<:Union{ScalarLinearDomain, + ci::MOI.ConstraintIndex{MOI.VariableIndex, S}) where S<:Union{ScalarLinearDomain, MOI.Integer} MOI.throw_if_not_valid(m, ci) delete_name(m, ci) diff --git a/src/objective.jl b/src/objective.jl index 0d37857..af6ac15 100644 --- a/src/objective.jl +++ b/src/objective.jl @@ -18,13 +18,13 @@ function MOI.get(m::Optimizer, return MOI.ScalarAffineFunction(terms, constant) end -const ObjF = Union{MOI.SingleVariable, MOI.ScalarAffineFunction{Float64}} +const ObjF = Union{MOI.VariableIndex, MOI.ScalarAffineFunction{Float64}} MOI.supports(::Optimizer,::MOI.ObjectiveFunction{<:ObjF}) = true MOI.supports(::Optimizer,::MOI.ObjectiveSense) = true function MOI.set(m::Optimizer, ::MOI.ObjectiveFunction, - func::MOI.SingleVariable) + func::MOI.VariableIndex) MOI.set(m, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), convert(MOI.ScalarAffineFunction{Float64}, func)) end diff --git a/src/variable.jl b/src/variable.jl index c8a8019..805687e 100644 --- a/src/variable.jl +++ b/src/variable.jl @@ -179,7 +179,7 @@ function throw_if_cannot_delete(m::Optimizer, vi::MOI.VariableIndex) MOI.EqualTo{Float64}, MOI.Interval{Float64}, MOI.Integer] if has_flag(m, vi, S) - MOI.delete(m, MOI.ConstraintIndex{MOI.SingleVariable, S}(vi.value)) + MOI.delete(m, MOI.ConstraintIndex{MOI.VariableIndex, S}(vi.value)) end end # All bounds have been removed so there can only be not constraint left diff --git a/test/runtests.jl b/test/runtests.jl index a2c8c6d..53c015c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -16,7 +16,7 @@ const FALLBACK_URL = "mosek://solve.mosek.com:30080" using MosekTools const optimizer = Mosek.Optimizer() -MOI.set(optimizer, MOI.RawParameter("fallback"), FALLBACK_URL) +MOI.set(optimizer, MOI.RawOptimizerAttribute("fallback"), FALLBACK_URL) MOI.set(optimizer, MOI.Silent(), true) @testset "SolverName" begin @@ -25,42 +25,42 @@ end @testset "Parameters" begin optimizer = Mosek.Optimizer() - MOI.set(optimizer, MOI.RawParameter("fallback"), FALLBACK_URL) + MOI.set(optimizer, MOI.RawOptimizerAttribute("fallback"), FALLBACK_URL) @testset "Double Parameter" begin - MOI.set(optimizer, MOI.RawParameter("INTPNT_CO_TOL_DFEAS"), 1e-7) - @test MOI.get(optimizer, MOI.RawParameter("MSK_DPAR_INTPNT_CO_TOL_DFEAS")) == 1e-7 - MOI.set(optimizer, MOI.RawParameter("MSK_DPAR_INTPNT_CO_TOL_DFEAS"), 1e-8) - @test MOI.get(optimizer, MOI.RawParameter("MSK_DPAR_INTPNT_CO_TOL_DFEAS")) == 1e-8 + MOI.set(optimizer, MOI.RawOptimizerAttribute("INTPNT_CO_TOL_DFEAS"), 1e-7) + @test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_DPAR_INTPNT_CO_TOL_DFEAS")) == 1e-7 + MOI.set(optimizer, MOI.RawOptimizerAttribute("MSK_DPAR_INTPNT_CO_TOL_DFEAS"), 1e-8) + @test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_DPAR_INTPNT_CO_TOL_DFEAS")) == 1e-8 @testset "with integer value" begin - MOI.set(optimizer, MOI.RawParameter("MSK_DPAR_INTPNT_CO_TOL_DFEAS"), 1) - @test MOI.get(optimizer, MOI.RawParameter("MSK_DPAR_INTPNT_CO_TOL_DFEAS")) == 1 + MOI.set(optimizer, MOI.RawOptimizerAttribute("MSK_DPAR_INTPNT_CO_TOL_DFEAS"), 1) + @test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_DPAR_INTPNT_CO_TOL_DFEAS")) == 1 end end @testset "Integer Parameter" begin - MOI.set(optimizer, MOI.RawParameter("MSK_IPAR_INTPNT_MAX_ITERATIONS"), 100) - @test MOI.get(optimizer, MOI.RawParameter("MSK_IPAR_INTPNT_MAX_ITERATIONS")) == 100 - MOI.set(optimizer, MOI.RawParameter("INTPNT_MAX_ITERATIONS"), 200) - @test MOI.get(optimizer, MOI.RawParameter("MSK_IPAR_INTPNT_MAX_ITERATIONS")) == 200 + MOI.set(optimizer, MOI.RawOptimizerAttribute("MSK_IPAR_INTPNT_MAX_ITERATIONS"), 100) + @test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_IPAR_INTPNT_MAX_ITERATIONS")) == 100 + MOI.set(optimizer, MOI.RawOptimizerAttribute("INTPNT_MAX_ITERATIONS"), 200) + @test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_IPAR_INTPNT_MAX_ITERATIONS")) == 200 @testset "with enum value" begin - MOI.set(optimizer, MOI.RawParameter("MSK_IPAR_OPTIMIZER"), MosekTools.Mosek.MSK_OPTIMIZER_DUAL_SIMPLEX) - @test MOI.get(optimizer, MOI.RawParameter("MSK_IPAR_OPTIMIZER")) == convert(Int32, MosekTools.Mosek.MSK_OPTIMIZER_DUAL_SIMPLEX) + MOI.set(optimizer, MOI.RawOptimizerAttribute("MSK_IPAR_OPTIMIZER"), MosekTools.Mosek.MSK_OPTIMIZER_DUAL_SIMPLEX) + @test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_IPAR_OPTIMIZER")) == convert(Int32, MosekTools.Mosek.MSK_OPTIMIZER_DUAL_SIMPLEX) end end @testset "String Parameter" begin - MOI.set(optimizer, MOI.RawParameter("PARAM_WRITE_FILE_NAME"), "foo.txt") + MOI.set(optimizer, MOI.RawOptimizerAttribute("PARAM_WRITE_FILE_NAME"), "foo.txt") # Needs https://github.com/JuliaOpt/Mosek.jl/pull/174 - #@test MOI.get(optimizer, MOI.RawParameter("MSK_SPAR_PARAM_WRITE_FILE_NAME")) == "foo.txt" - MOI.set(optimizer, MOI.RawParameter("MSK_SPAR_PARAM_WRITE_FILE_NAME"), "bar.txt") - #@test MOI.get(optimizer, MOI.RawParameter("MSK_SPAR_PARAM_WRITE_FILE_NAME")) == "bar.txt" + #@test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_SPAR_PARAM_WRITE_FILE_NAME")) == "foo.txt" + MOI.set(optimizer, MOI.RawOptimizerAttribute("MSK_SPAR_PARAM_WRITE_FILE_NAME"), "bar.txt") + #@test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_SPAR_PARAM_WRITE_FILE_NAME")) == "bar.txt" end @testset "TimeLimitSec" begin - @test MOI.get(optimizer, MOI.RawParameter("MSK_DPAR_OPTIMIZER_MAX_TIME")) == -1 + @test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_DPAR_OPTIMIZER_MAX_TIME")) == -1 @test MOI.get(optimizer, MOI.TimeLimitSec()) === nothing MOI.set(optimizer, MOI.TimeLimitSec(), 1.0) - @test MOI.get(optimizer, MOI.RawParameter("MSK_DPAR_OPTIMIZER_MAX_TIME")) == 1.0 + @test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_DPAR_OPTIMIZER_MAX_TIME")) == 1.0 @test MOI.get(optimizer, MOI.TimeLimitSec()) === 1.0 MOI.set(optimizer, MOI.TimeLimitSec(), nothing) - @test MOI.get(optimizer, MOI.RawParameter("MSK_DPAR_OPTIMIZER_MAX_TIME")) == -1 + @test MOI.get(optimizer, MOI.RawOptimizerAttribute("MSK_DPAR_OPTIMIZER_MAX_TIME")) == -1 @test MOI.get(optimizer, MOI.TimeLimitSec()) === nothing end end @@ -70,19 +70,45 @@ end @test MOIU.supports_default_copy_to(optimizer, true) end -const config = MOIT.TestConfig(atol=1e-3, rtol=1e-3) +const config = MOIT.Config( + Float64, atol=1e-3, rtol=1e-3, + exclude=Any[MOI.ConstraintName], # result in errors for now +) + +@testset "Basic tests" begin + MOIT.runtests(optimizer, config, include=["basic", "linear"], + exclude=["Indicator"], + ) +end + +@testset "Conic problems" begin + MOIT.runtests(optimizer, config, + include=["conic", "SecondOrderCone", "Semidefinite", "Exponential"], + exclude=["Indicator", "basic", "linear"], + ) +end + +@testset "Integer problems" begin + MOIT.runtests(optimizer, config, + include=["Integer", "ZeroOne"], + exclude=[ + "Indicator", "basic", "linear", "conic", "SecondOrderCone", "Semidefinite", + "test_variable_solve_ZeroOne_with_0_upper_bound", "test_variable_solve_ZeroOne_with_upper_bound", # issues/74 + ], + ) +end @testset "Basic" begin @testset "Linear" begin MOIT.basic_constraint_tests( optimizer, config, include=[ - (MOI.SingleVariable, MOI.EqualTo{Float64}), - (MOI.SingleVariable, MOI.LessThan{Float64}), - (MOI.SingleVariable, MOI.GreaterThan{Float64}), - (MOI.SingleVariable, MOI.Interval{Float64}), - (MOI.SingleVariable, MOI.ZeroOne), - (MOI.SingleVariable, MOI.Integer), + (MOI.VariableIndex, MOI.EqualTo{Float64}), + (MOI.VariableIndex, MOI.LessThan{Float64}), + (MOI.VariableIndex, MOI.GreaterThan{Float64}), + (MOI.VariableIndex, MOI.Interval{Float64}), + (MOI.VariableIndex, MOI.ZeroOne), + (MOI.VariableIndex, MOI.Integer), (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}), (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}), (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}), diff --git a/test/test_jump.jl b/test/test_jump.jl index 807f97c..06808e4 100644 --- a/test/test_jump.jl +++ b/test/test_jump.jl @@ -8,7 +8,7 @@ include("jump_soc.jl") @testset "JuMP tests" begin o = Mosek.Optimizer() - MOI.set(o, MOI.RawParameter("LOG"), 0) + MOI.set(o, MOI.RawOptimizerAttribute("LOG"), 0) test_jump_lp() MOI.empty!(o) test_jump_soc(o) From e61110ce76365455a36b0f689dd8eefc4716e332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Wed, 29 Sep 2021 16:51:58 +0200 Subject: [PATCH 3/8] enumerate tests --- src/MosekTools.jl | 2 + src/attributes.jl | 6 +- src/constraint.jl | 1 - test/runtests.jl | 140 ++++++++++++++++++++++------------------------ 4 files changed, 71 insertions(+), 78 deletions(-) diff --git a/src/MosekTools.jl b/src/MosekTools.jl index 710d060..058aee5 100644 --- a/src/MosekTools.jl +++ b/src/MosekTools.jl @@ -282,6 +282,8 @@ function MOI.get(model::Optimizer, ::MOI.TimeLimitSec) end end +MOI.supports_incremental_interface(::Optimizer) = true + function matrix_solution(m::Optimizer, sol) return Vector{Float64}[getbarxj(m.task, sol, j) for j in 1:length(m.sd_dim)] end diff --git a/src/attributes.jl b/src/attributes.jl index 7c8830b..0cb1c21 100644 --- a/src/attributes.jl +++ b/src/attributes.jl @@ -66,11 +66,11 @@ function MOI.get(m::Optimizer, attr::MOI.DualObjectiveValue) return getdualobj(m.task, m.solutions[attr.result_index].whichsol) end -MOI.get(m::Optimizer,attr::MOI.ObjectiveBound) = getdouinf(m.task,MSK_DINF_MIO_OBJ_BOUND) +MOI.get(m::Optimizer, ::MOI.ObjectiveBound) = getdouinf(m.task,MSK_DINF_MIO_OBJ_BOUND) -MOI.get(m::Optimizer,attr::MOI.RelativeGap) = getdouinf(m.task,MSK_DINF_MIO_OBJ_REL_GAP) +MOI.get(m::Optimizer, ::MOI.RelativeGap) = getdouinf(m.task,MSK_DINF_MIO_OBJ_REL_GAP) -MOI.get(m::Optimizer,attr::MOI.SolveTimeSec) = getdouinf(m.task,MSK_DINF_OPTIMIZER_TIME) +MOI.get(m::Optimizer, ::MOI.SolveTimeSec) = getdouinf(m.task,MSK_DINF_OPTIMIZER_TIME) # NOTE: The MOSEK interface currently only supports Min and Max diff --git a/src/constraint.jl b/src/constraint.jl index 8b59276..0a6c01b 100644 --- a/src/constraint.jl +++ b/src/constraint.jl @@ -420,7 +420,6 @@ function MOI.add_constraint(m::Optimizer, xs::MOI.VectorOfVariables, error("Cannot multiple bound sets of the same type to a variable") end - N = MOI.dimension(dom) id = add_cone(m, cols, dom) idx = first(xs.variables).value for vi in xs.variables diff --git a/test/runtests.jl b/test/runtests.jl index 53c015c..6f773a6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -75,7 +75,7 @@ const config = MOIT.Config( exclude=Any[MOI.ConstraintName], # result in errors for now ) -@testset "Basic tests" begin +@testset "Basic and linear tests" begin MOIT.runtests(optimizer, config, include=["basic", "linear"], exclude=["Indicator"], ) @@ -83,7 +83,7 @@ end @testset "Conic problems" begin MOIT.runtests(optimizer, config, - include=["conic", "SecondOrderCone", "Semidefinite", "Exponential"], + include=["conic", "SecondOrderCone", "Semidefinite", "Exponential", "PowerCone"], exclude=["Indicator", "basic", "linear"], ) end @@ -98,37 +98,6 @@ end ) end -@testset "Basic" begin - @testset "Linear" begin - MOIT.basic_constraint_tests( - optimizer, config, - include=[ - (MOI.VariableIndex, MOI.EqualTo{Float64}), - (MOI.VariableIndex, MOI.LessThan{Float64}), - (MOI.VariableIndex, MOI.GreaterThan{Float64}), - (MOI.VariableIndex, MOI.Interval{Float64}), - (MOI.VariableIndex, MOI.ZeroOne), - (MOI.VariableIndex, MOI.Integer), - (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}), - (MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}), - (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}), - (MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) - ]) - end - @testset "Conic" begin - MOIT.basic_constraint_tests( - optimizer, config, - include=[ - (MOI.VectorOfVariables, MOI.ExponentialCone), - (MOI.VectorOfVariables, MOI.DualExponentialCone), - (MOI.VectorOfVariables, MOI.PowerCone{Float64}), - (MOI.VectorOfVariables, MOI.DualPowerCone{Float64}), - (MOI.VectorOfVariables, MOI.SecondOrderCone), - (MOI.VectorOfVariables, MOI.RotatedSecondOrderCone) - ]) - end -end - const bridged = MOIB.full_bridge_optimizer(optimizer, Float64) # Mosek errors during `MOI.set` instead of `MOI.get` when there are duplicates. @@ -138,50 +107,73 @@ const bridged = MOIB.full_bridge_optimizer(optimizer, Float64) @testset "Copy" begin model = MOIB.full_bridge_optimizer(Mosek.Optimizer(), Float64) - MOIT.copytest(bridged, model) -end - -@testset "Start" begin - # TODO this should be checked somewhere in MOI - @test MOI.supports(bridged, MOI.VariablePrimalStart(), MOI.VariableIndex) -end -@testset "Unit" begin - # Mosek does not support names - MOIT.unittest(bridged, config, [ - # TODO - "number_threads", - # Find objective bound of 0.0 which is lower than 4.0 - "solve_objbound_edge_cases", - # Cannot put multiple bound sets of the same type on a variable - "solve_integer_edge_cases", - # Cannot mix `ZeroOne` with `GreaterThan`/`LessThan` - "solve_zero_one_with_bounds_1", - "solve_zero_one_with_bounds_2", - "solve_zero_one_with_bounds_3"]) -end + # linear and basic tests + MOIT.runtests(model, config, + include=["basic", "linear"], + exclude=[ + "Cone", "conic", + "test_basic_ScalarQuadraticFunction_EqualTo", # non-PSD quadratic + "test_basic_ScalarQuadraticFunction_GreaterThan", + "test_basic_ScalarQuadraticFunction_Interval", + "test_basic_ScalarQuadraticFunction_Semi", + "test_basic_ScalarQuadraticFunction_ZeroOne", + "test_basic_ScalarQuadraticFunction_Integer", + "test_basic_VectorQuadraticFunction_Nonnegatives", + "test_basic_VectorQuadraticFunction_Zeros", + ], + ) -@testset "Continuous Linear" begin - MOIT.contlineartest(bridged, config) -end + # conic + MOIT.runtests( + model, config, + include=["conic", "SecondOrderCone", "Semidefinite", "Exponential", "PowerCone", "Cone"], + exclude=[ + "test_basic_VectorAffineFunction_PositiveSemidefiniteConeSquare", # AssertionError: (m.x_sd[ref2id(vi)]).matrix == -1 src/variable.jl:173 + "test_basic_VectorOfVariables_PositiveSemidefiniteConeSquare", + "test_basic_VectorAffineFunction_LogDetConeTriangle", + "test_basic_VectorAffineFunction_NormNuclearCone", + "test_basic_VectorOfVariables_NormNuclearCone", + "test_basic_VectorAffineFunction_NormSpectralCone", + "test_basic_VectorOfVariables_NormSpectralCone", + "test_basic_VectorAffineFunction_RootDetConeTriangle", + "test_basic_VectorOfVariables_RootDetConeTriangle", + "test_basic_VectorAffineFunction_PositiveSemidefiniteConeTriangle", # TODO: implement get ConstraintSet for SAF + "test_basic_VectorOfVariables_PositiveSemidefiniteConeTriangle", + "test_basic_VectorQuadraticFunction_", # not PSD because of equality + "test_basic_VectorOfVariables_LogDetConeTriangle", # Mosek.MosekError(1307, "Variable '' (1) is a member of cone '' (0).") src/msk_functions.jl:477 + ], + ) -@testset "Continuous Quadratic" begin - MOIT.contquadratictest(bridged, config, [ - # Non-convex - "ncqcp", - # QuadtoSOC does not work as the matrix is not SDP - "socp" - ]) -end + # integer + MOIT.runtests(model, config, + include=["Integer", "ZeroOne"], + exclude=[ + "Cone", "conic", + "test_constraint_ZeroOne_bounds", # Cannot put multiple bound sets of the same type on a variable + "test_variable_solve_ZeroOne_with_0_upper_bound", + "test_variable_solve_ZeroOne_with_upper_bound", + "test_basic_ScalarQuadraticFunction_ZeroOne", # non-PSD quadratic + ], + ) -@testset "Continuous Conic" begin - MOIT.contconictest(bridged, config, ["rootdets", "logdet"]) -end + # other attribute tests + MOIT.runtests(model, config, + exclude=[ + "Cone", "conic", "Integer", "ZeroOne", "basic", "linear", + "test_model_ListOfConstraintAttributesSet", # list not properly set + "BoundAlreadySet", # TODO throw error if bound already set + "test_model_ModelFilter_AbstractVariableAttribute", + "test_model_VariableName", # Mosek currently throws when setting twice, not when getting names + "test_model_Name_VariableName_ConstraintName", + "test_model_duplicate_VariableName", + "test_model_VariablePrimalStart", # able to set but not to get VariablePrimalStart + "test_objective_qp_ObjectiveFunction_zero_ofdiag", # MOI.ListOfModelAttributesSet + "test_objective_set_via_modify", + "test_quadratic_nonconvex_constraint_integration", + "test_solve_ObjectiveBound_MAX_SENSE_LP", # ObjectiveBound invalid -@testset "Integer Linear" begin - MOIT.intlineartest(bridged, config, [ - # SOS constraints not supported: - # int2 uses SOS and indicator can be bridged to SOS - "int2", "indicator1", "indicator2", "indicator3", "indicator4" - ]) + ], + ) + @test MOI.supports(model, MOI.VariablePrimalStart(), MOI.VariableIndex) end From 506424938dc6a3f1b5cf67ab09b97f809c7aa15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Wed, 29 Sep 2021 16:57:40 +0200 Subject: [PATCH 4/8] no basis status --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index 6f773a6..022eef7 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -72,7 +72,7 @@ end const config = MOIT.Config( Float64, atol=1e-3, rtol=1e-3, - exclude=Any[MOI.ConstraintName], # result in errors for now + exclude=Any[MOI.ConstraintName, MOI.VariableBasisStatus, MOI.ConstraintBasisStatus], # result in errors for now ) @testset "Basic and linear tests" begin From 8665eceaffa9f035e3e03e9333aec04828537888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Wed, 29 Sep 2021 17:37:13 +0200 Subject: [PATCH 5/8] add quadratic --- test/runtests.jl | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 022eef7..22ce3e2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -76,14 +76,14 @@ const config = MOIT.Config( ) @testset "Basic and linear tests" begin - MOIT.runtests(optimizer, config, include=["basic", "linear"], - exclude=["Indicator"], + MOIT.runtests(optimizer, config, include=["basic", "linear", "quadratic"], + exclude=["Indicator", "Cone", "conic"], ) end @testset "Conic problems" begin MOIT.runtests(optimizer, config, - include=["conic", "SecondOrderCone", "Semidefinite", "Exponential", "PowerCone"], + include=["conic", "SecondOrderCone", "Semidefinite", "Exponential", "PowerCone", "Cone"], exclude=["Indicator", "basic", "linear"], ) end @@ -98,19 +98,13 @@ end ) end -const bridged = MOIB.full_bridge_optimizer(optimizer, Float64) - -# Mosek errors during `MOI.set` instead of `MOI.get` when there are duplicates. -#@testset "Name" begin -# MOIT.nametest(bridged) -#end - -@testset "Copy" begin +@testset "Bridged" begin model = MOIB.full_bridge_optimizer(Mosek.Optimizer(), Float64) + MOI.set(model, MOI.Silent(), true) # linear and basic tests MOIT.runtests(model, config, - include=["basic", "linear"], + include=["basic", "linear", "quadratic"], exclude=[ "Cone", "conic", "test_basic_ScalarQuadraticFunction_EqualTo", # non-PSD quadratic @@ -121,6 +115,7 @@ const bridged = MOIB.full_bridge_optimizer(optimizer, Float64) "test_basic_ScalarQuadraticFunction_Integer", "test_basic_VectorQuadraticFunction_Nonnegatives", "test_basic_VectorQuadraticFunction_Zeros", + "nonconvex", ], ) @@ -141,7 +136,9 @@ const bridged = MOIB.full_bridge_optimizer(optimizer, Float64) "test_basic_VectorAffineFunction_PositiveSemidefiniteConeTriangle", # TODO: implement get ConstraintSet for SAF "test_basic_VectorOfVariables_PositiveSemidefiniteConeTriangle", "test_basic_VectorQuadraticFunction_", # not PSD because of equality + "test_quadratic_SecondOrderCone_basic", "test_basic_VectorOfVariables_LogDetConeTriangle", # Mosek.MosekError(1307, "Variable '' (1) is a member of cone '' (0).") src/msk_functions.jl:477 + "test_conic_LogDetConeTriangle_VectorOfVariables", ], ) From 637928b38828f565fea91b03a3c82de942f70786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Sun, 3 Oct 2021 15:21:38 +0200 Subject: [PATCH 6/8] regroup all runtests --- src/constraint.jl | 4 +++ test/runtests.jl | 62 +++++++++++++++-------------------------------- 2 files changed, 23 insertions(+), 43 deletions(-) diff --git a/src/constraint.jl b/src/constraint.jl index 0a6c01b..94f526a 100644 --- a/src/constraint.jl +++ b/src/constraint.jl @@ -475,6 +475,10 @@ function MOI.get(m::Optimizer, ::MOI.ConstraintSet, return get_variable_constraint(m, vi, ci) end +function MOI.set(::Optimizer, ::MOI.ConstraintFunction, ci::MOI.ConstraintIndex{MOI.VariableIndex}, ::MOI.VariableIndex) + throw(MOI.SettingVariableIndexNotAllowed()) +end + function MOI.get(m::Optimizer, ::MOI.ConstraintFunction, ci::MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64}, <:ScalarLinearDomain}) diff --git a/test/runtests.jl b/test/runtests.jl index 22ce3e2..48b3c94 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -76,24 +76,24 @@ const config = MOIT.Config( ) @testset "Basic and linear tests" begin - MOIT.runtests(optimizer, config, include=["basic", "linear", "quadratic"], - exclude=["Indicator", "Cone", "conic"], - ) -end - -@testset "Conic problems" begin - MOIT.runtests(optimizer, config, - include=["conic", "SecondOrderCone", "Semidefinite", "Exponential", "PowerCone", "Cone"], - exclude=["Indicator", "basic", "linear"], - ) -end - -@testset "Integer problems" begin MOIT.runtests(optimizer, config, - include=["Integer", "ZeroOne"], exclude=[ - "Indicator", "basic", "linear", "conic", "SecondOrderCone", "Semidefinite", - "test_variable_solve_ZeroOne_with_0_upper_bound", "test_variable_solve_ZeroOne_with_upper_bound", # issues/74 + # issues/74, + "test_variable_solve_ZeroOne_with_0_upper_bound", + "test_variable_solve_ZeroOne_with_upper_bound", + "test_linear_Indicator_ON_ONE", + "test_model_ListOfConstraintAttributesSet", # TODO implement + "test_model_LowerBoundAlreadySet", + "test_model_UpperBoundAlreadySet", + "test_model_ModelFilter_AbstractVariableAttribute", + "test_model_VariableName", + "test_model_VariablePrimalStart", + "test_model_copy_to_UnsupportedConstraint", + "test_model_duplicate_VariableName", + "test_modification_incorrect_VariableIndex", + "test_solve_ObjectiveBound_MAX_SENSE_LP", + "test_objective_set_via_modify", + "test_model_VariableIndex_ConstraintName", ], ) end @@ -104,9 +104,7 @@ end # linear and basic tests MOIT.runtests(model, config, - include=["basic", "linear", "quadratic"], exclude=[ - "Cone", "conic", "test_basic_ScalarQuadraticFunction_EqualTo", # non-PSD quadratic "test_basic_ScalarQuadraticFunction_GreaterThan", "test_basic_ScalarQuadraticFunction_Interval", @@ -115,15 +113,8 @@ end "test_basic_ScalarQuadraticFunction_Integer", "test_basic_VectorQuadraticFunction_Nonnegatives", "test_basic_VectorQuadraticFunction_Zeros", - "nonconvex", - ], - ) - - # conic - MOIT.runtests( - model, config, - include=["conic", "SecondOrderCone", "Semidefinite", "Exponential", "PowerCone", "Cone"], - exclude=[ + "test_quadratic_nonconvex_constraint_basic", + "test_quadratic_nonconvex_constraint_integration", "test_basic_VectorAffineFunction_PositiveSemidefiniteConeSquare", # AssertionError: (m.x_sd[ref2id(vi)]).matrix == -1 src/variable.jl:173 "test_basic_VectorOfVariables_PositiveSemidefiniteConeSquare", "test_basic_VectorAffineFunction_LogDetConeTriangle", @@ -139,25 +130,10 @@ end "test_quadratic_SecondOrderCone_basic", "test_basic_VectorOfVariables_LogDetConeTriangle", # Mosek.MosekError(1307, "Variable '' (1) is a member of cone '' (0).") src/msk_functions.jl:477 "test_conic_LogDetConeTriangle_VectorOfVariables", - ], - ) - - # integer - MOIT.runtests(model, config, - include=["Integer", "ZeroOne"], - exclude=[ - "Cone", "conic", "test_constraint_ZeroOne_bounds", # Cannot put multiple bound sets of the same type on a variable "test_variable_solve_ZeroOne_with_0_upper_bound", "test_variable_solve_ZeroOne_with_upper_bound", "test_basic_ScalarQuadraticFunction_ZeroOne", # non-PSD quadratic - ], - ) - - # other attribute tests - MOIT.runtests(model, config, - exclude=[ - "Cone", "conic", "Integer", "ZeroOne", "basic", "linear", "test_model_ListOfConstraintAttributesSet", # list not properly set "BoundAlreadySet", # TODO throw error if bound already set "test_model_ModelFilter_AbstractVariableAttribute", @@ -169,8 +145,8 @@ end "test_objective_set_via_modify", "test_quadratic_nonconvex_constraint_integration", "test_solve_ObjectiveBound_MAX_SENSE_LP", # ObjectiveBound invalid - ], ) + @test MOI.supports(model, MOI.VariablePrimalStart(), MOI.VariableIndex) end From aa7119f697887389cb02b9a61316f201118d0d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Sun, 3 Oct 2021 15:26:27 +0200 Subject: [PATCH 7/8] deprecated call --- src/MosekTools.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MosekTools.jl b/src/MosekTools.jl index 058aee5..711c7eb 100644 --- a/src/MosekTools.jl +++ b/src/MosekTools.jl @@ -406,7 +406,7 @@ MOI.get(::Optimizer, ::MOI.SolverName) = "Mosek" MOIU.supports_default_copy_to(::Optimizer, copy_names::Bool) = true function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike; kws...) - return MOIU.automatic_copy_to(dest, src; kws...) + return MOIU.default_copy_to(dest, src; kws...) end function MOI.write_to_file(m::Optimizer, filename :: String) From 05f91766f5f6e0016495cf1e227b06daf38bf0ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Sun, 3 Oct 2021 16:29:00 +0200 Subject: [PATCH 8/8] cached test --- test/runtests.jl | 54 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 48b3c94..0c92099 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -75,7 +75,7 @@ const config = MOIT.Config( exclude=Any[MOI.ConstraintName, MOI.VariableBasisStatus, MOI.ConstraintBasisStatus], # result in errors for now ) -@testset "Basic and linear tests" begin +@testset "Direct optimizer tests" begin MOIT.runtests(optimizer, config, exclude=[ # issues/74, @@ -98,7 +98,7 @@ const config = MOIT.Config( ) end -@testset "Bridged" begin +@testset "Bridged and cached" begin model = MOIB.full_bridge_optimizer(Mosek.Optimizer(), Float64) MOI.set(model, MOI.Silent(), true) @@ -113,6 +113,22 @@ end "test_basic_ScalarQuadraticFunction_Integer", "test_basic_VectorQuadraticFunction_Nonnegatives", "test_basic_VectorQuadraticFunction_Zeros", + "test_basic_VectorQuadraticFunction_DualExponentialCone", + "test_basic_VectorQuadraticFunction_DualPowerCone", + "test_basic_VectorQuadraticFunction_ExponentialCone", + "test_basic_VectorQuadraticFunction_GeometricMeanCone", + "test_basic_VectorQuadraticFunction_LogDetConeTriangle", + "test_basic_VectorQuadraticFunction_NormInfinityCone", + "test_basic_VectorQuadraticFunction_NormNuclearCone", + "test_basic_VectorQuadraticFunction_NormOneCone", + "test_basic_VectorQuadraticFunction_NormSpectralCone", + "test_basic_VectorQuadraticFunction_PositiveSemidefiniteConeSquare", + "test_basic_VectorQuadraticFunction_PositiveSemidefiniteConeTriangle", + "test_basic_VectorQuadraticFunction_PowerCone", + "test_basic_VectorQuadraticFunction_RelativeEntropyCone", + "test_basic_VectorQuadraticFunction_RootDetConeTriangle", + "test_basic_VectorQuadraticFunction_RotatedSecondOrderCone", + "test_basic_VectorQuadraticFunction_SecondOrderCone", "test_quadratic_nonconvex_constraint_basic", "test_quadratic_nonconvex_constraint_integration", "test_basic_VectorAffineFunction_PositiveSemidefiniteConeSquare", # AssertionError: (m.x_sd[ref2id(vi)]).matrix == -1 src/variable.jl:173 @@ -126,7 +142,6 @@ end "test_basic_VectorOfVariables_RootDetConeTriangle", "test_basic_VectorAffineFunction_PositiveSemidefiniteConeTriangle", # TODO: implement get ConstraintSet for SAF "test_basic_VectorOfVariables_PositiveSemidefiniteConeTriangle", - "test_basic_VectorQuadraticFunction_", # not PSD because of equality "test_quadratic_SecondOrderCone_basic", "test_basic_VectorOfVariables_LogDetConeTriangle", # Mosek.MosekError(1307, "Variable '' (1) is a member of cone '' (0).") src/msk_functions.jl:477 "test_conic_LogDetConeTriangle_VectorOfVariables", @@ -149,4 +164,37 @@ end ) @test MOI.supports(model, MOI.VariablePrimalStart(), MOI.VariableIndex) + + model = MOI.Bridges.full_bridge_optimizer( + MOI.Utilities.CachingOptimizer( + MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()), + Mosek.Optimizer(), + ), + Float64, + ) + MOI.set(model, MOI.Silent(), true) + + MOI.Test.runtests(model, config, + exclude=[ + "test_basic_ScalarQuadraticFunction_EqualTo", # non-PSD quadratic + "test_basic_ScalarQuadraticFunction_GreaterThan", + "test_basic_ScalarQuadraticFunction_Interval", + "test_basic_ScalarQuadraticFunction_Semi", + "test_basic_ScalarQuadraticFunction_ZeroOne", + "test_basic_ScalarQuadraticFunction_Integer", + "test_basic_VectorQuadraticFunction_Nonnegatives", + "test_basic_VectorQuadraticFunction_Zeros", + "test_quadratic_nonconvex_constraint_basic", + "test_quadratic_nonconvex_constraint_integration", + "test_quadratic_SecondOrderCone_basic", + "test_basic_VectorQuadraticFunction_", # not PSD because of equality + "test_basic_VectorOfVariables_LogDetConeTriangle", # Mosek.MosekError(1307, "Variable '' (1) is a member of cone '' (0).") src/msk_functions.jl:477 + "test_conic_LogDetConeTriangle_VectorOfVariables", + "test_constraint_ZeroOne_bounds", + "BoundAlreadySet", # TODO throw error if bound already set + "test_solve_ObjectiveBound_MAX_SENSE_LP", + "test_variable_solve_ZeroOne_with_0_upper_bound", + "test_variable_solve_ZeroOne_with_upper_bound", + ], + ) end