From bff9d1da8add7886fb727d65a1593f504b897bbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 25 Jan 2019 19:19:36 +0100 Subject: [PATCH] Update to Julia v1.0 and MOI v0.8 (#9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 🚚 Rename to MOI_wrapper.jl * ⬆️ Upgrade to Julia v1.0 and MOI v0.8 * 👷 Update Travis script * 👌 Fix default value of x_computed and z_computed * 👌 ALMOST_OPTIMAL -> OTHER_ERROR --- .travis.yml | 14 +- REQUIRE | 7 +- deps/.gitignore | 1 + deps/build.jl | 8 +- src/DSDP.jl | 7 +- ...{DSDPSolverInterface.jl => MOI_wrapper.jl} | 217 +++++++++++------- src/bcone.jl | 2 +- src/dsdp5_API.jl | 6 +- src/lpcone.jl | 14 +- src/sdpcone.jl | 2 +- test/MOI_wrapper.jl | 48 ++++ test/maxcut.jl | 26 +-- test/moi.jl | 13 -- test/options.jl | 6 +- test/runtests.jl | 4 +- 15 files changed, 228 insertions(+), 147 deletions(-) rename src/{DSDPSolverInterface.jl => MOI_wrapper.jl} (55%) create mode 100644 test/MOI_wrapper.jl delete mode 100644 test/moi.jl diff --git a/.travis.yml b/.travis.yml index 6d55bad..8655671 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,26 +4,16 @@ os: - linux - osx julia: - - 0.6 - - nightly + - 1.0 matrix: allow_failures: - julia: nightly notifications: email: false -before_script: - - julia -e 'Pkg.clone("https://github.com/JuliaOpt/MathOptInterface.jl.git")' - - julia -e 'Pkg.clone("https://github.com/JuliaOpt/MathOptInterfaceUtilities.jl.git")' - - julia -e 'Pkg.clone("https://github.com/JuliaOpt/MathOptInterfaceTests.jl.git")' - - julia -e 'Pkg.clone("https://github.com/JuliaOpt/SemidefiniteOptInterface.jl.git")' -# uncomment the following lines to override the default test script -#script: -# - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi -# - julia -e 'Pkg.clone(pwd()); Pkg.build("SDPA"); Pkg.test("SDPA"; coverage=true)' addons: apt_packages: - liblapack-dev - libopenblas-dev after_success: # push coverage results to Coveralls and Codecov - - julia -e 'cd(Pkg.dir("SDPA")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder()); Codecov.submit(Codecov.process_folder())' + - julia -e 'using Pkg; Pkg.add("Coverage"); cd(Pkg.dir("DSDP")); using Coverage; Coveralls.submit(process_folder()); Codecov.submit(process_folder())' diff --git a/REQUIRE b/REQUIRE index b6a9c8f..4e9ef82 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,5 +1,4 @@ -julia 0.6 +julia 1.0 BinDeps -MathOptInterface -MathOptInterfaceTests -SemidefiniteOptInterface +MathOptInterface 0.8 0.9 +SemidefiniteOptInterface 0.5 0.6 diff --git a/deps/.gitignore b/deps/.gitignore index 7a4c356..51efe72 100644 --- a/deps/.gitignore +++ b/deps/.gitignore @@ -2,3 +2,4 @@ deps.jl downloads/* src/* usr/* +build.log diff --git a/deps/build.jl b/deps/build.jl index 3bc9ad1..b893811 100644 --- a/deps/build.jl +++ b/deps/build.jl @@ -1,8 +1,8 @@ -using BinDeps +using Libdl, BinDeps @BinDeps.setup -@static if is_unix() +@static if Sys.isunix() libdsdp = library_dependency("libdsdp", aliases=["libdsdp.a", "libdsdp.so", "libdsdp.dylib"]) end @@ -12,7 +12,7 @@ provides(Sources, URI("http://www.mcs.anl.gov/hs/software/DSDP/$DSDPname.tar.gz" [libdsdp], os = :Unix, unpacked_dir="$DSDPname") patchdir=BinDeps.depsdir(libdsdp) -srcdir = joinpath(patchdir,"src",DSDPname) +srcdir = joinpath(patchdir,"src",DSDPname) libdir = joinpath(srcdir,"lib") usrdir = BinDeps.usrdir(libdsdp) @@ -29,7 +29,7 @@ provides(SimpleBuild, pipeline(`patch -N -p0`, stdin="$patchdir/g2c_2.patch") pipeline(`patch -N -p0`, stdin="$patchdir/shared.patch") pipeline(`patch -N -p0`, stdin="$patchdir/rm.patch") - @static if is_apple() + @static if Sys.isapple() pipeline(`patch -N -p0`, stdin="$patchdir/apple.patch") end `make` diff --git a/src/DSDP.jl b/src/DSDP.jl index 86aed71..1f44100 100644 --- a/src/DSDP.jl +++ b/src/DSDP.jl @@ -1,6 +1,7 @@ module DSDP +using Libdl -if isfile(joinpath(Pkg.dir("DSDP"),"deps","deps.jl")) +if isfile(joinpath(dirname(@__FILE__), "..", "deps", "deps.jl")) include("../deps/deps.jl") else error("DSDP not properly installed. Please run Pkg.build(\"DSDP\")") @@ -17,7 +18,7 @@ macro dsdp_ccall(f, args...) end end -const DSDPT = Ptr{Void} +const DSDPT = Ptr{Nothing} include("dsdp5_enums.jl") include("dsdp5_API.jl") @@ -51,6 +52,6 @@ end # @dsdp_ccall DSDPPrintSolution (Ptr{FILE}, DSDP, SDPCone.SDPConeT, LPCone.LPConeT) arg1 arg2 arg3 arg4 #end -include("DSDPSolverInterface.jl") +include("MOI_wrapper.jl") end diff --git a/src/DSDPSolverInterface.jl b/src/MOI_wrapper.jl similarity index 55% rename from src/DSDPSolverInterface.jl rename to src/MOI_wrapper.jl index 94ecff5..74003eb 100644 --- a/src/DSDPSolverInterface.jl +++ b/src/MOI_wrapper.jl @@ -4,9 +4,7 @@ SDOI = SemidefiniteOptInterface using MathOptInterface MOI = MathOptInterface -export DSDPInstance - -mutable struct DSDPSolverInstance <: SDOI.AbstractSDSolverInstance +mutable struct SDOptimizer <: SDOI.AbstractSDOptimizer dsdp::DSDPT lpcone::LPCone.LPConeT nconstrs::Int @@ -24,16 +22,35 @@ mutable struct DSDPSolverInstance <: SDOI.AbstractSDSolverInstance z_computed::Bool options::Dict{Symbol,Any} - function DSDPSolverInstance(; kwargs...) - m = new(C_NULL, C_NULL, 0, Int[], Int[], C_NULL, 0, Int[], Int[], Cdouble[], - true, true, Cdouble[], true, Dict{Symbol, Any}(kwargs)) - finalizer(m, _free) - m + function SDOptimizer(; kwargs...) + optimizer = new(C_NULL, C_NULL, 0, Int[], Int[], C_NULL, 0, Int[], + Int[], Cdouble[], true, true, Cdouble[], true, + Dict{Symbol, Any}(kwargs)) + finalizer(_free, optimizer) + return optimizer end end -DSDPInstance(; kws...) = SDOI.SDOIInstance(DSDPSolverInstance(; kws...)) +Optimizer(; kws...) = SDOI.SDOIOptimizer(SDOptimizer(; kws...)) + +MOI.get(::SDOptimizer, ::MOI.SolverName) = "DSDP" + +function MOI.empty!(optimizer::SDOptimizer) + _free(optimizer) + optimizer.nconstrs = 0 + optimizer.blkdims = Int[] + optimizer.blk = Int[] + optimizer.nlpdrows = 0 + optimizer.lpdvars = Int[] + optimizer.lpdrows = Int[] + optimizer.lpcoefs = Cdouble[] + + optimizer.x_computed = false + optimizer.y_valid = true + optimizer.y = Cdouble[] + optimizer.z_computed = false +end -function _free(m::DSDPSolverInstance) +function _free(m::SDOptimizer) if m.dsdp != C_NULL Destroy(m.dsdp) m.dsdp = C_NULL @@ -73,18 +90,18 @@ const options = Dict( const options_setters = Dict{Symbol, Function}() -abstract type Option <: MOI.AbstractInstanceAttribute end +abstract type Option <: MOI.AbstractModelAttribute end abstract type GettableOption <: Option end -MOI.canget(solver::DSDPSolverInstance, ::Option) = true -function MOI.set!(m::DSDPSolverInstance, o::Option, val) - # Need to set it in the dictionary so that it is also used when initinstance! is called again +MOI.supports(solver::SDOptimizer, ::Option) = true +function MOI.set(m::SDOptimizer, o::Option, val) + # Need to set it in the dictionary so that it is also used when init! is called again _dict_set!(m.options, o, val) _call_set!(m.dsdp, o, val) end -MOI.get(m::DSDPSolverInstance, o::Option) = _dict_get(m.options, o) -function MOI.get(m::DSDPSolverInstance, o::GettableOption) +MOI.get(m::SDOptimizer, o::Option) = _dict_get(m.options, o) +function MOI.get(m::SDOptimizer, o::GettableOption) if m.dsdp == C_NULL _dict_get(m.options, o) else @@ -128,7 +145,7 @@ for (param, default) in Iterators.flatten((options, gettable_options)) end end -function SDOI.initinstance!(m::DSDPSolverInstance, blkdims::Vector{Int}, nconstrs::Int) +function SDOI.init!(m::SDOptimizer, blkdims::Vector{Int}, nconstrs::Int) _free(m) @assert nconstrs >= 0 m.nconstrs = nconstrs @@ -169,10 +186,10 @@ function SDOI.initinstance!(m::DSDPSolverInstance, blkdims::Vector{Int}, nconstr m.z_computed = false end -function SDOI.setconstraintconstant!(m::DSDPSolverInstance, val, constr::Integer) +function SDOI.setconstraintconstant!(m::SDOptimizer, val, constr::Integer) SetDualObjective(m.dsdp, constr, val) end -function _setcoefficient!(m::DSDPSolverInstance, coef, constr::Integer, blk::Integer, i::Integer, j::Integer) +function _setcoefficient!(m::SDOptimizer, coef, constr::Integer, blk::Integer, i::Integer, j::Integer) if m.blkdims[blk] < 0 @assert i == j push!(m.lpdvars, constr+1) @@ -182,15 +199,15 @@ function _setcoefficient!(m::DSDPSolverInstance, coef, constr::Integer, blk::Int error("TODO") end end -function SDOI.setconstraintcoefficient!(m::DSDPSolverInstance, coef, constr::Integer, blk::Integer, i::Integer, j::Integer) +function SDOI.setconstraintcoefficient!(m::SDOptimizer, coef, constr::Integer, blk::Integer, i::Integer, j::Integer) _setcoefficient!(m, coef, constr, blk, i, j) end -function SDOI.setobjectivecoefficient!(m::DSDPSolverInstance, coef, blk::Integer, i::Integer, j::Integer) +function SDOI.setobjectivecoefficient!(m::SDOptimizer, coef, blk::Integer, i::Integer, j::Integer) # in SDOI, convention is MAX but in DSDP, convention is MIN so we reverse the sign of coef _setcoefficient!(m, -coef, 0, blk, i, j) end -function MOI.optimize!(m::DSDPSolverInstance) +function MOI.optimize!(m::SDOptimizer) if !isempty(m.lpdvars) m.lpcone = CreateLPCone(m.dsdp) LPCone.SetDataSparse(m.lpcone, m.nlpdrows, m.nconstrs+1, m.lpdvars, m.lpdrows, m.lpcoefs) @@ -203,138 +220,172 @@ function MOI.optimize!(m::DSDPSolverInstance) # m.y does not contain the solution y m.y_valid = false m.z_computed = true + + # It seems that calling this later causes segfaults, maybe it can be fixed + # with some `GC.@preserve` somewhere like in + # https://github.com/JuliaOpt/ECOS.jl/pull/63 + # and + # https://github.com/JuliaOpt/SCS.jl/pull/91 + compute_x(m) + compute_z(m) end -function MOI.get(m::DSDPSolverInstance, ::MOI.TerminationStatus) +function MOI.get(m::SDOptimizer, ::MOI.TerminationStatus) + if m.dsdp == C_NULL + return MOI.OPTIMIZE_NOT_CALLED + end status = StopReason(m.dsdp) + compute_x(m) if status == DSDP_CONVERGED - return MOI.Success + sol_status = GetSolutionType(m.dsdp) + if sol_status == DSDP_PDFEASIBLE + return MOI.OPTIMAL + elseif sol_status == DSDP_UNBOUNDED + return MOI.INFEASIBLE + elseif sol_status == DSDP_INFEASIBLE + return MOI.DUAL_INFEASIBLE + elseif sol_status == DSDP_PDUNKNOWN + return MOI.OTHER_ERROR + else + error("Internal library error: status=$sol_status") + end elseif status == DSDP_INFEASIBLE_START - return MOI.OtherError + return MOI.OTHER_ERROR elseif status == DSDP_SMALL_STEPS - return MOI.SlowProgress + return MOI.SLOW_PROGRESS elseif status == DSDP_INDEFINITE_SCHUR_MATRIX - return MOI.NumericalError + return MOI.NUMERICAL_ERROR elseif status == DSDP_MAX_IT - return MOI.IterationLimit + return MOI.ITERATION_LIMIT elseif status == DSDP_NUMERICAL_ERROR - return MOI.NumericalError + return MOI.NUMERICAL_ERROR elseif status == DSDP_UPPERBOUND - return MOI.ObjectiveLimit + return MOI.OBJECTIVE_LIMIT elseif status == DSDP_USER_TERMINATION - return MOI.Interrupted + return MOI.INTERRUPTED elseif status == CONTINUE_ITERATING - return MOI.OtherError + return MOI.OTHER_ERROR else error("Internal library error: status=$status") end end -MOI.canget(m::DSDPSolverInstance, ::MOI.PrimalStatus) = GetSolutionType(m.dsdp) != DSDP_PDUNKNOWN -function MOI.get(m::DSDPSolverInstance, ::MOI.PrimalStatus) +function MOI.get(m::SDOptimizer, ::MOI.PrimalStatus) + if m.dsdp == C_NULL + return MOI.NO_SOLUTION + end compute_x(m) status = GetSolutionType(m.dsdp) if status == DSDP_PDUNKNOWN - return MOI.UnknownResultStatus + return MOI.UNKNOWN_RESULT_STATUS elseif status == DSDP_PDFEASIBLE - return MOI.FeasiblePoint + return MOI.FEASIBLE_POINT elseif status == DSDP_UNBOUNDED - return MOI.InfeasiblePoint + return MOI.INFEASIBLE_POINT elseif status == DSDP_INFEASIBLE - return MOI.InfeasibilityCertificate + return MOI.INFEASIBILITY_CERTIFICATE else error("Internal library error: status=$status") end end -MOI.canget(m::DSDPSolverInstance, ::MOI.DualStatus) = GetSolutionType(m.dsdp) != DSDP_PDUNKNOWN -function MOI.get(m::DSDPSolverInstance, ::MOI.DualStatus) +function MOI.get(m::SDOptimizer, ::MOI.DualStatus) + if m.dsdp == C_NULL + return MOI.NO_SOLUTION + end compute_x(m) status = GetSolutionType(m.dsdp) if status == DSDP_PDUNKNOWN - return MOI.UnknownResultStatus + return MOI.UNKNOWN_RESULT_STATUS elseif status == DSDP_PDFEASIBLE - return MOI.FeasiblePoint + return MOI.FEASIBLE_POINT elseif status == DSDP_UNBOUNDED - return MOI.InfeasibilityCertificate + return MOI.INFEASIBILITY_CERTIFICATE elseif status == DSDP_INFEASIBLE - return MOI.InfeasiblePoint + return MOI.INFEASIBLE_POINT else error("Internal library error: status=$status") end end -function SDOI.getprimalobjectivevalue(m::DSDPSolverInstance) +function SDOI.getprimalobjectivevalue(m::SDOptimizer) -GetPPObjective(m.dsdp) end -function SDOI.getdualobjectivevalue(m::DSDPSolverInstance) +function SDOI.getdualobjectivevalue(m::SDOptimizer) -GetDDObjective(m.dsdp) end -function compute_x(m::DSDPSolverInstance) +abstract type LPBlock <: AbstractMatrix{Cdouble} end +Base.size(x::LPBlock) = (x.dim, x.dim) +function Base.getindex(x::LPBlock, i, j) + if i == j + return get_array(x)[x.offset + i] + else + return zero(Cdouble) + end +end + + +abstract type BlockMat <: SDOI.AbstractBlockMatrix{Cdouble} end +SDOI.nblocks(x::BlockMat) = length(x.optimizer.blk) + +function compute_x(m::SDOptimizer) if !m.x_computed + @assert m.dsdp != C_NULL ComputeX(m.dsdp) m.x_computed = true m.z_computed = false end end -struct LPXBlock <: AbstractMatrix{Cdouble} +struct LPXBlock <: LPBlock lpcone::LPCone.LPConeT + dim::Int offset::Int end -function Base.getindex(x::LPXBlock, i, j) - if i == j - LPCone.GetXArray(x.lpcone)[x.offset+i] - else - zero(Cdouble) - end -end -struct XBlockMat <: AbstractMatrix{Cdouble} - instance::DSDPSolverInstance +get_array(x::LPXBlock) = LPCone.GetXArray(x.lpcone) +struct XBlockMat <: BlockMat + optimizer::SDOptimizer end -function Base.getindex(x::XBlockMat, i) - compute_x(x.instance) - @assert x.instance.blkdims[i] < 0 - LPXBlock(x.instance.lpcone, x.instance.blk[i]) +function SDOI.block(x::XBlockMat, i) + compute_x(x.optimizer) + @assert x.optimizer.blkdims[i] < 0 + LPXBlock(x.optimizer.lpcone, abs(x.optimizer.blkdims[i]), x.optimizer.blk[i]) end -function SDOI.getX(m::DSDPSolverInstance) - XBlockMat(m) +function SDOI.getX(optimizer::SDOptimizer) + XBlockMat(optimizer) end -function SDOI.gety(m::DSDPSolverInstance) +function SDOI.gety(m::SDOptimizer) if !m.y_valid - m.y = Vector{Cdouble}(m.nconstrs) + m.y = Vector{Cdouble}(undef, m.nconstrs) GetY(m.dsdp, m.y) map!(-, m.y, m.y) # The primal objective is Max in SDOI but Min in DSDP end m.y end -function compute_z(m::DSDPSolverInstance) +function compute_z(m::SDOptimizer) if !m.z_computed - ComputeAndFactorS(m.dsdp) + GC.@preserve m begin + ComputeAndFactorS(m.dsdp) + end m.z_computed = true end end -struct LPZBlock <: AbstractMatrix{Cdouble} +struct LPZBlock <: LPBlock lpcone::LPCone.LPConeT + dim::Int offset::Int end -function Base.getindex(z::LPZBlock, i, j) - if i == j - LPCone.GetSArray(z.lpcone)[z.offset+i] - else - zero(Cdouble) - end -end -struct ZBlockMat <: AbstractMatrix{Cdouble} - instance::DSDPSolverInstance +get_array(z::LPZBlock) = LPCone.GetSArray(z.lpcone) +struct ZBlockMat <: BlockMat + optimizer::SDOptimizer end -function Base.getindex(z::ZBlockMat, i) - compute_z(z.instance) - @assert z.instance.blkdims[i] < 0 - LPZBlock(z.instance.lpcone, z.instance.blk[i]) +function SDOI.block(z::ZBlockMat, i) + compute_z(z.optimizer) + @assert z.optimizer.blkdims[i] < 0 + LPZBlock(z.optimizer.lpcone, abs(z.optimizer.blkdims[i]), z.optimizer.blk[i]) end -function SDOI.getZ(m::DSDPSolverInstance) - ZBlockMat(m) +function SDOI.getZ(m::SDOptimizer) + return ZBlockMat(m) end diff --git a/src/bcone.jl b/src/bcone.jl index 5b7597f..6366706 100644 --- a/src/bcone.jl +++ b/src/bcone.jl @@ -3,7 +3,7 @@ export BCone module BCone import ..@dsdp_ccall -const BConeT = Ptr{Void} +const BConeT = Ptr{Nothing} function AllocateBounds(bcone::BConeT, arg2::Integer) @dsdp_ccall BConeAllocateBounds (BConeT, Cint) bcone arg2 diff --git a/src/dsdp5_API.jl b/src/dsdp5_API.jl index 26d5e0a..01b4336 100644 --- a/src/dsdp5_API.jl +++ b/src/dsdp5_API.jl @@ -26,8 +26,10 @@ end function ComputeAndFactorS(dsdp::DSDPT) psdefinite = Ref{DSDPTruth}() - @dsdp_ccall DSDPComputeAndFactorS (DSDPT, Ref{DSDPTruth}) dsdp psdefinite - psdefinite[] + GC.@preserve psdefinite dsdp begin + @dsdp_ccall DSDPComputeAndFactorS (DSDPT, Ref{DSDPTruth}) dsdp psdefinite + return psdefinite[] + end end function Destroy(dsdp::DSDPT) diff --git a/src/lpcone.jl b/src/lpcone.jl index 7e317d2..6d8c1af 100644 --- a/src/lpcone.jl +++ b/src/lpcone.jl @@ -3,7 +3,7 @@ export LPCone module LPCone import ..@dsdp_ccall -const LPConeT = Ptr{Void} +const LPConeT = Ptr{Nothing} function buildlp(nvars, lpdvars, lpdrows, lpcoefs) @assert length(lpdvars) == length(lpdrows) == length(lpcoefs) @@ -12,14 +12,14 @@ function buildlp(nvars, lpdvars, lpdrows, lpcoefs) for var in lpdvars nzin[var] += 1 end - nnzin = [zero(Cint); cumsum(nzin)] + nnzin = Cint[zero(Cint); cumsum(nzin)] @assert nnzin[end] == n idx = map(var -> Int[], 1:nvars) for (i, var) in enumerate(lpdvars) push!(idx[var], i) end - row = Vector{Cint}(n) - aval = Vector{Cdouble}(n) + row = Vector{Cint}(undef, n) + aval = Vector{Cdouble}(undef, n) for var in 1:nvars sort!(idx[var], by=i->lpdrows[i]) row[(nnzin[var]+1):(nnzin[var+1])] = lpdrows[idx[var]] @@ -64,8 +64,10 @@ function GetSArray(lpcone::LPConeT) unsafe_wrap(Array, sout[], n[]) end -function GetDimension(arg1::LPConeT, arg2) - @dsdp_ccall LPConeGetDimension (LPConeT, Ptr{Cint}) arg1 arg2 +function GetDimension(arg1::LPConeT) + dim = Ref{Cint}() + @dsdp_ccall LPConeGetDimension (LPConeT, Ref{Cint}) arg1 dim + return dim[] end function View(lpcone::LPConeT) diff --git a/src/sdpcone.jl b/src/sdpcone.jl index 02bb84a..2e39ba0 100644 --- a/src/sdpcone.jl +++ b/src/sdpcone.jl @@ -3,7 +3,7 @@ export SDPCone module SDPCone import ..@dsdp_ccall -const SDPConeT = Ptr{Void} +const SDPConeT = Ptr{Nothing} function SetBlockSize(sdpcone::SDPConeT, i::Integer, j::Integer) @dsdp_ccall SDPConeSetBlockSize (SDPConeT, Cint, Cint) sdpcone i j diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl new file mode 100644 index 0000000..674969d --- /dev/null +++ b/test/MOI_wrapper.jl @@ -0,0 +1,48 @@ +using MathOptInterface +const MOI = MathOptInterface +const MOIT = MOI.Test +const MOIU = MOI.Utilities +const MOIB = MOI.Bridges + +MOIU.@model(SDModelData, + (), + (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan), + (MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, + MOI.PositiveSemidefiniteConeTriangle), + (), + (MOI.SingleVariable,), + (MOI.ScalarAffineFunction,), + (MOI.VectorOfVariables,), + (MOI.VectorAffineFunction,)) + +const cache = MOIU.UniversalFallback(SDModelData{Float64}()) +const optimizer = MOIU.CachingOptimizer(cache, + DSDP.Optimizer()) +const config = MOIT.TestConfig(atol=1e-6, rtol=1e-6) + +@testset "SolverName" begin + @test MOI.get(optimizer, MOI.SolverName()) == "DSDP" +end + +@testset "Unit" begin + MOIT.unittest(MOIB.SplitInterval{Float64}(optimizer), config, + [# To investigate... + "solve_duplicate_terms_obj", "solve_with_lowerbound", + "solve_blank_obj", "solve_affine_interval", + "solve_singlevariable_obj", "solve_constant_obj", + "solve_affine_deletion_edge_cases", + # Quadratic functions are not supported + "solve_qcp_edge_cases", "solve_qp_edge_cases", + # Integer and ZeroOne sets are not supported + "solve_integer_edge_cases", "solve_objbound_edge_cases"]) +end + +@testset "Continuous Linear" begin + MOIT.contlineartest(MOIB.SplitInterval{Float64}(optimizer), config, + ["linear1", "linear11", "linear12", "linear14"]) +end + +#@testset "Conic tests" begin +# include(joinpath(Pkg.dir("MathOptInterface"), "test", "contconic.jl")) +# contconictest(DSDP.DSDPSolver(printlevel=0), atol=1e-7, rtol=1e-7) +#end diff --git a/test/maxcut.jl b/test/maxcut.jl index 0e431b5..b525527 100644 --- a/test/maxcut.jl +++ b/test/maxcut.jl @@ -10,9 +10,9 @@ signz(t) = t < 0 ? -1 : 1 function MaxCutRandomized(sdpcone::SDPCone.SDPConeT, nnodes::Integer) ymin = Cdouble(0) - vv = Vector{Cdouble}(nnodes) - tt = Vector{Cdouble}(nnodes) - cc = Vector{Cdouble}(nnodes + 2) + vv = Vector{Cdouble}(undef, nnodes) + tt = Vector{Cdouble}(undef, nnodes) + cc = Vector{Cdouble}(undef, nnodes + 2) SDPCone.ComputeXV(sdpcone, 0) for i in 1:nnodes for j in eachindex(vv) @@ -56,7 +56,7 @@ function maxcut(nnodes, edges) yy = zeros(nnodes) indd = zeros(Cint, nnodes + nedges) val = zeros(nnodes+nedges) - indd[nedges+(1:nnodes)] = iptr + indd[nedges .+ (1:nnodes)] = iptr tval = 0.0 for (i, (u, v, w)) in enumerate(edges) indd[i] = di(u, v) @@ -106,14 +106,14 @@ function maxcut(nnodes, edges) end @testset "DSDP MaxCut example" begin - const nnodes = 6 - const edges = [(1, 2, .3) - (1, 4, 2.7) - (1, 6, 1.5) - (2, 3, -1.0) - (2, 5, 1.45) - (3, 4, -0.2) - (4, 5, 1.2) - (5, 6, 2.1)] + nnodes = 6 + edges = [(1, 2, .3) + (1, 4, 2.7) + (1, 6, 1.5) + (2, 3, -1.0) + (2, 5, 1.45) + (3, 4, -0.2) + (4, 5, 1.2) + (5, 6, 2.1)] maxcut(nnodes, edges) end diff --git a/test/moi.jl b/test/moi.jl deleted file mode 100644 index bd08a0b..0000000 --- a/test/moi.jl +++ /dev/null @@ -1,13 +0,0 @@ -using MathOptInterfaceTests -const MOIT = MathOptInterfaceTests - -const solver = () -> DSDP.DSDPInstance() -const config = MOIT.TestConfig(1e-6, 1e-6, true, true, true, true) - -@testset "Linear tests" begin - MOIT.contlineartest(solver, config, ["linear1", "linear11", "linear12"]) -end -#@testset "Conic tests" begin -# include(joinpath(Pkg.dir("MathOptInterface"), "test", "contconic.jl")) -# contconictest(CSDP.CSDPSolver(printlevel=0), atol=1e-7, rtol=1e-7) -#end diff --git a/test/options.jl b/test/options.jl index e4498b5..4752940 100644 --- a/test/options.jl +++ b/test/options.jl @@ -2,11 +2,11 @@ using MathOptInterface const MOI = MathOptInterface using SemidefiniteOptInterface -const SOI = SemidefiniteOptInterface +const SDOI = SemidefiniteOptInterface @testset "Options" begin - instance = DSDP.DSDPSolverInstance() - SOI.initinstance!(instance, [1], 42) + instance = DSDP.SDOptimizer() + SDOI.init!(instance, [1], 42) for (option, default) in Iterators.flatten((DSDP.options, DSDP.gettable_options)) @eval begin @test MOI.get($instance, DSDP.$option()) == $default diff --git a/test/runtests.jl b/test/runtests.jl index f5a9a57..86ef4d0 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,7 +1,7 @@ using DSDP -using Base.Test +using Test include("maxcut.jl") include("build.jl") include("options.jl") -include("moi.jl") +include("MOI_wrapper.jl")