diff --git a/.travis.yml b/.travis.yml index 83b8f03..c014dfc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,10 +10,7 @@ notifications: email: false git: depth: 99999999 - +before_script: + - julia -e 'using Pkg; Pkg.add(PackageSpec(name="MathOptInterface", rev="master"))' after_success: - julia -e 'import Pkg; Pkg.add("Coverage"); using Coverage; Codecov.submit(process_folder()); Coveralls.submit(process_folder())' - # push coverage results to Coveralls - - julia -e 'cd(Pkg.dir("SemidefiniteOptInterface")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(Coveralls.process_folder())' - # push coverage results to Codecov - - julia -e 'cd(Pkg.dir("SemidefiniteOptInterface")); Pkg.add("Coverage"); using Coverage; Codecov.submit(Codecov.process_folder())' diff --git a/Project.toml b/Project.toml index f163ff2..a34173b 100644 --- a/Project.toml +++ b/Project.toml @@ -4,10 +4,11 @@ repo = "https://github.com/JuliaOpt/SemidefiniteOptInterface.jl.git" version = "0.6.0" [deps] +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" [compat] -MathOptInterface = "0.8" +MathOptInterface = "0.9" julia = "1" [extras] diff --git a/src/SemidefiniteOptInterface.jl b/src/SemidefiniteOptInterface.jl index c225969..5d11846 100644 --- a/src/SemidefiniteOptInterface.jl +++ b/src/SemidefiniteOptInterface.jl @@ -4,18 +4,16 @@ using MathOptInterface const MOI = MathOptInterface const MOIU = MOI.Utilities -using Compat -using Compat.LinearAlgebra # for diag +using LinearAlgebra # for diag abstract type AbstractSDOptimizer <: MOI.AbstractOptimizer end include("interface.jl") -const SVF = MOI.SingleVariable const VVF = MOI.VectorOfVariables -const VF = Union{SVF, VVF} +const VF = Union{MOI.SingleVariable, VVF} const SAF{T} = MOI.ScalarAffineFunction{T} -const ASF{T} = Union{SVF, SAF{T}} +const ASF{T} = Union{MOI.SingleVariable, SAF{T}} const ZS = Union{MOI.EqualTo, MOI.Zeros} const NS = Union{MOI.GreaterThan, MOI.Nonnegatives} @@ -64,9 +62,16 @@ SDOIOptimizer(sdoptimizer::AbstractSDOptimizer, T=Float64) = SOItoMOIBridge{T}(s include("load.jl") -function MOI.get(optimizer::SOItoMOIBridge, attr::MOI.SolverName) +function MOI.supports(optimizer::SOItoMOIBridge, attr::MOI.AbstractOptimizerAttribute) + return MOI.supports(optimizer.sdoptimizer, attr) +end +function MOI.get(optimizer::SOItoMOIBridge, attr::MOI.AbstractOptimizerAttribute) return MOI.get(optimizer.sdoptimizer, attr) end +function MOI.set(optimizer::SOItoMOIBridge, + attr::MOI.AbstractOptimizerAttribute, value) + return MOI.set(optimizer.sdoptimizer, attr, value) +end function MOI.is_empty(optimizer::SOItoMOIBridge) isempty(optimizer.double) && @@ -105,7 +110,7 @@ end function setconstant!(optimizer::SOItoMOIBridge, ci::CI, s) end function setconstant!(optimizer::SOItoMOIBridge, ci::CI, s::MOI.AbstractScalarSet) - optimizer.setconstant[ci.value] = MOIU.getconstant(s) + optimizer.setconstant[ci.value] = MOI.constant(s) end function set_constant(optimizer::SOItoMOIBridge, ci::CI{<:MOI.AbstractScalarFunction, @@ -164,15 +169,16 @@ MOI.optimize!(m::SOItoMOIBridge) = MOI.optimize!(m.sdoptimizer) # Objective -function MOI.get(m::SOItoMOIBridge, ::MOI.ObjectiveValue) - m.objshift + m.objsign * getprimalobjectivevalue(m.sdoptimizer) + m.objconstant +function MOI.get(m::SOItoMOIBridge, attr::Union{MOI.ObjectiveValue, MOI.DualObjectiveValue}) + return m.objshift + m.objsign * MOI.get(m.sdoptimizer, attr) + m.objconstant end # Attributes - -const SolverStatus = Union{MOI.TerminationStatus, MOI.PrimalStatus, MOI.DualStatus} -MOI.get(m::SOItoMOIBridge, s::SolverStatus) = MOI.get(m.sdoptimizer, s) - +function MOI.get(m::SOItoMOIBridge, + attr::Union{MOI.RawStatusString, MOI.TerminationStatus, + MOI.PrimalStatus, MOI.DualStatus, MOI.SolveTime}) + return MOI.get(m.sdoptimizer, attr) +end MOI.get(m::SOItoMOIBridge, ::MOI.ResultCount) = 1 @@ -186,7 +192,7 @@ end sympackedlen(d::Integer) = (d*(d+1)) >> 1 function _getblock(M::AbstractMatrix{T}, blk::Integer, s::Type{<:DS}) where T B = block(M, blk) - d = Compat.LinearAlgebra.checksquare(B) + d = LinearAlgebra.checksquare(B) n = sympackedlen(d) v = Vector{T}(undef, n) k = 0 diff --git a/src/constraint.jl b/src/constraint.jl index 252a73a..3c725f4 100644 --- a/src/constraint.jl +++ b/src/constraint.jl @@ -1,4 +1,4 @@ -nconstraints(f::Union{SVF, SAF}, s) = 1 +nconstraints(f::Union{MOI.SingleVariable, SAF}, s) = 1 nconstraints(f::VVF, s) = length(f.variables) function _allocate_constraint(m::SOItoMOIBridge, f, s) @@ -19,7 +19,7 @@ function loadcoefficients!(m::SOItoMOIBridge, cs::UnitRange, f = MOIU.canonical(f) # sum terms with same variables and same outputindex @assert length(cs) == 1 c = first(cs) - rhs = MOIU.getconstant(s) - MOI._constant(f) + rhs = MOI.constant(s) - MOI.constant(f) for t in f.terms if !iszero(t.coefficient) for (blk, i, j, coef, shift) in varmap(m, t.variable_index) diff --git a/src/interface.jl b/src/interface.jl index 3b08ad3..4ad3989 100644 --- a/src/interface.jl +++ b/src/interface.jl @@ -95,17 +95,3 @@ function gety end Returns the solution Z. """ function getZ end - -""" - getprimalobjectivevalue(optimizer::AbstractSDOptimizer) - -Returns the primal objective value. -""" -function getprimalobjectivevalue end - -""" - getdualobjectivevalue(optimizer::AbstractSDOptimizer) - -Returns the dual objective value. -""" -function getdualobjectivevalue end diff --git a/src/mock.jl b/src/mock.jl index 2c6c3a4..55e947d 100644 --- a/src/mock.jl +++ b/src/mock.jl @@ -6,8 +6,8 @@ nblocks(bm::BlockMatrix) = length(bm.blocks) block(bm::BlockMatrix, i::Integer) = bm.blocks[i] function Base.size(bm::AbstractBlockMatrix) - n = Compat.mapreduce(blk -> Compat.LinearAlgebra.checksquare(block(bm, blk)), - +, 1:nblocks(bm), init=0) + n = mapreduce(blk -> LinearAlgebra.checksquare(block(bm, blk)), + +, 1:nblocks(bm), init=0) return (n, n) end function Base.getindex(bm::AbstractBlockMatrix, i::Integer, j::Integer) @@ -121,7 +121,7 @@ MOI.set(mock::MockSDOptimizer, ::MOI.DualStatus, value::MOI.ResultStatusCode) = getX(mock::MockSDOptimizer) = mock.X getZ(mock::MockSDOptimizer) = mock.Z gety(mock::MockSDOptimizer) = mock.y -function getprimalobjectivevalue(mock::MockSDOptimizer{T}) where T +function MOI.get(mock::MockSDOptimizer{T}, ::MOI.ObjectiveValue) where T v = zero(T) for (α, blk, i, j) in mock.objective_coefficients v += α * block(mock.X, blk)[i, j] @@ -129,14 +129,14 @@ function getprimalobjectivevalue(mock::MockSDOptimizer{T}) where T v += α * block(mock.X, blk)[j, i] end end - v + return v end -function getdualobjectivevalue(mock::MockSDOptimizer{T}) where T +function MOI.get(mock::MockSDOptimizer{T}, ::MOI.DualObjectiveValue) where T v = zero(T) for c in 1:mock.nconstrs v += mock.constraint_constants[c] * mock.y[c] end - v + return v end function MOI.optimize!(mock::MockSDOptimizer) diff --git a/src/variable.jl b/src/variable.jl index f38e2de..6be0bdf 100644 --- a/src/variable.jl +++ b/src/variable.jl @@ -14,7 +14,7 @@ end function _constraintvariable!(m::SOItoMOIBridge{T}, vs::VIS, s::ZS) where T blk = newblock(m, -_length(vs)) for (i, v) in _enumerate(vs) - setvarmap!(m, v, (blk, i, i, one(T), _getconstant(m, s))) + setvarmap!(m, v, (blk, i, i, one(T), _constant(m, s))) unfree(m, v) end blk @@ -27,7 +27,7 @@ _enumerate(vi::VI) = enumerate((vi,)) _enumerate(vi::Vector{VI}) = enumerate(vi) function _constraintvariable!(m::SOItoMOIBridge, vs::VIS, s::S) where S<:Union{NS, PS} blk = newblock(m, -_length(vs)) - cst = _getconstant(m, s) + cst = _constant(m, s) m.blkconstant[blk] = cst for (i, v) in _enumerate(vs) setvarmap!(m, v, (blk, i, i, vscaling(S), cst)) @@ -58,7 +58,7 @@ function _constraintvariable!(m::SOItoMOIBridge{T}, vs::VIS, ::DS) where T end blk end -_var(f::SVF) = f.variable +_var(f::MOI.SingleVariable) = f.variable _var(f::VVF) = f.variables function _throw_error_if_unfree(m, vi::MOI.VariableIndex) if !isfree(m, vi) @@ -84,10 +84,10 @@ function MOIU.allocate_constraint(m::SOItoMOIBridge{T}, f::VF, s::SupportedSets) end end -_getconstant(m::SOItoMOIBridge, s::MOI.AbstractScalarSet) = MOIU.getconstant(s) -_getconstant(m::SOItoMOIBridge{T}, s::MOI.AbstractSet) where T = zero(T) +_constant(m::SOItoMOIBridge, s::MOI.AbstractScalarSet) = MOI.constant(s) +_constant(m::SOItoMOIBridge{T}, s::MOI.AbstractSet) where T = zero(T) -_var(f::SVF, j) = f.variable +_var(f::MOI.SingleVariable, j) = f.variable _var(f::VVF, j) = f.variables[j] function MOIU.load_constraint(m::SOItoMOIBridge, ci::CI, f::VF, s::SupportedSets) if ci.value >= 0 # i.e. s is ZS or _var(f) wasn't free at allocate_constraint @@ -101,7 +101,7 @@ function MOIU.load_constraint(m::SOItoMOIBridge, ci::CI, f::VF, s::SupportedSets (blk, i, j, coef, shift) = first(vm) c = cs[k] setconstraintcoefficient!(m.sdoptimizer, coef, c, blk, i, j) - setconstraintconstant!(m.sdoptimizer, _getconstant(m, s) - coef * shift, c) + setconstraintconstant!(m.sdoptimizer, _constant(m, s) - coef * shift, c) end end end diff --git a/test/contconic.jl b/test/contconic.jl index a833d29..41a6018 100644 --- a/test/contconic.jl +++ b/test/contconic.jl @@ -55,13 +55,13 @@ end [-1.4142, 1.0, -0.1768, 1.0, -0.3536, -0.1768])) MOIT.rotatedsoc1ftest(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [0.5 0.7071 0.7071; 0.7071 2.0 0.0; 0.7071 0.0 2.0], [2.6164 0.0; 0.0 1.9093], [2.6164 0.0; 0.0 1.9093]], - [5183.15, 5182.44, -1.4142, 1.0, -0.1768, 1.0, -0.3536, -0.1768])) + [[0.5 1/√2 1/√2; 1/√2 2.0 0.0; 1/√2 0.0 2.0], [0.0], [0.0], [3.65568 0; 0 2.94857], [3.65568 0; 0 2.94857]], + [-√2, 1.0, -0.176777, 1.0, -0.353555, -0.176777, 2189.72, 2189.01])) MOIT.rotatedsoc1vtest(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, MOI.INFEASIBLE, tuple(), - [141.088, -47.8864, 47.5533, -46.2201])) + [-47.8864, 47.5533, -46.2201, 141.088])) MOIT.rotatedsoc2test(bridged, config) # FIXME u >= 0.0 followed by u <= ub. We need to drop support for # SingleVariable-in-LessThan but we need variable bridge otherwise, @@ -73,12 +73,14 @@ end end @testset "GeoMean" begin MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [1.4142 2.0; 2.0 2.8284], [1.0 1.4142; 1.4142 2.0], [1.0 1.4142; 1.4142 2.0], [1.8324 0.0; 0.0 0.8324], [1.7758 0.0; 0.0 0.7758], [1.7772 0.0; 0.0 0.7772], [1.7728 0.0; 0.0 0.7728], [2.5017 0.0; 0.0 0.5017], [2.0744 0.0; 0.0 0.6602], [2.0671 0.0; 0.0 0.6529]], - [1.0, 0.3333, -0.4714, 0.6667, -0.2357, -0.3333, 0.4714, -0.1667, -0.3333, 0.4714, -0.1667])) + [[√2 2.0; 2.0 2*√2], [1.0 √2; √2 2.0], [1.0 √2; √2 2.0], [0.0], [0.0], + [1.83238 0; 0 0.832376], [1.77579 0; 0 0.775793], + [1.77719 0; 0 0.777194], [1.77283 0; 0 0.772829], + [2.50173 0; 0 0.501735], [2.07437 0; 0 0.660159], + [2.06708 0; 0 0.652869]], + [1.0, -0.471405, 2/3, -0.235702, -1/3, 0.471405, -1/6, -1/3, 0.471405, + -1/6, 1/3])) MOIT.geomean1ftest(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [1.4142 2.0; 2.0 2.8284], [1.0 1.4142; 1.4142 2.0], [1.0 1.4142; 1.4142 2.0], [1.8324 0.0; 0.0 0.8324], [1.7758 0.0; 0.0 0.7758], [1.7772 0.0; 0.0 0.7772], [1.7728 0.0; 0.0 0.7728], [2.5017 0.0; 0.0 0.5017], [2.0744 0.0; 0.0 0.6602], [2.0671 0.0; 0.0 0.6529]], - [1.0, 0.3333, -0.4714, 0.6667, -0.2357, -0.3333, 0.4714, -0.1667, -0.3333, 0.4714, -0.1667])) MOIT.geomean1vtest(bridged, config) end @testset "PSD" begin @@ -125,8 +127,11 @@ end [0.4475 0; 0 0.4475-xv[2]]], [-y2/√2, y2, -y2/√2/2, y2, -y2/√2, -y2/√2/2, y2*√2-1, -y2])) MOIT.psdt1vtest(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [20/3 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 10/3 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0; 0.0 0.0 0.0 0.0 0.0 0.0], [4.0981 -2.1213; -2.1213 1.0981], [7.3275 0.0; 0.0 0.6608], [1.7945 0.0; 0.0 1.7945], [4.1881 0.0; 0.0 0.8547], [1.7945 0.0; 0.0 1.7945], [1.7945 0.0; 0.0 1.7945], [1.7945 0.0; 0.0 1.7945], [2.8504 0.0; 0.0 0.9485]], - [-0.190192, 0, 0.125977, 0, 0.142644, 0.142644, 0.0127405, -0.211325, -0.816497, -0.788675, 0])) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[20/3 0 0 0 0 0; 0 0 0 0 0 0; 0 0 10/3 0 0 0; 0 0 0 0 0 0; 0 0 0 0 0 0; 0 0 0 0 0 0], + [4.09808 -2.12132; -2.12132 1.09808], [0.0], [7.32746 0; 0 0.660794], + [1.79451 0; 0 1.79451], [4.18806 0; 0 0.854733], [1.79451 0; 0 1.79451], + [1.79451 0; 0 1.79451], [1.79451 0; 0 1.79451], [2.85043 0; 0 0.94851]], + [-0.190192, 0.0, 0.125977, 0.0, 0.142644, 0.142644, 0.0127405, -0.211325, -0.816497, -0.788675, 0.0])) MOIT.psdt2test(bridged, config) end diff --git a/test/mock_tests_generator.ipynb b/test/mock_tests_generator.ipynb index 0b239c2..95ec398 100644 --- a/test/mock_tests_generator.ipynb +++ b/test/mock_tests_generator.ipynb @@ -29,14 +29,16 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "const MOIU = MOI.Utilities\n", "MOIU.@model(SDModelData,\n", " (), (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan),\n", " (MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, MOI.PositiveSemidefiniteConeTriangle), (),\n", - " (MOI.SingleVariable,), (MOI.ScalarAffineFunction,),\n", + " (), (MOI.ScalarAffineFunction,),\n", " (MOI.VectorOfVariables,), ())" ] }, @@ -117,13 +119,15 @@ "metadata": {}, "outputs": [], "source": [ - "generate_mock_test(MOIT.psdt0ftest)" + "generate_mock_test(MOIT.geomean1vtest)" ] }, { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "for testfun in map(p -> p.second, sort(collect(MOIT.lintests), by=p->p.first))\n", @@ -166,7 +170,7 @@ "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.1.0" + "version": "1.1.1" } }, "nbformat": 4, diff --git a/test/runtests.jl b/test/runtests.jl index bd4b48e..d97f904 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,8 +1,7 @@ using SemidefiniteOptInterface const SDOI = SemidefiniteOptInterface -using Compat -using Compat.Test +using Test using MathOptInterface const MOI = MathOptInterface @@ -13,15 +12,10 @@ include("sdpa.jl") const MOIU = MOI.Utilities MOIU.@model(SDModelData, - (), - (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan), + (), (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan), (MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, - MOI.PositiveSemidefiniteConeTriangle), - (), - (MOI.SingleVariable,), - (MOI.ScalarAffineFunction,), - (MOI.VectorOfVariables,), - ()) + MOI.PositiveSemidefiniteConeTriangle), (), + (), (MOI.ScalarAffineFunction,), (MOI.VectorOfVariables,), ()) mock = SDOI.MockSDOptimizer{Float64}() mock_optimizer = SDOI.SDOIOptimizer(mock, Float64) diff --git a/test/unit.jl b/test/unit.jl index 4b2e762..8a1eac0 100644 --- a/test/unit.jl +++ b/test/unit.jl @@ -11,13 +11,13 @@ MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[0.0], [0.0 0; 0 0.0]], [1.0]), (mock) -> MOIU.mock_optimize!(mock, - [[1.0], [0.0], [0.624034 0; 0 0.624034]], - [0.0, 1.0]), + [[0.0], [1.0], [0.624034 0; 0 0.624034]], + [1.0, 0.0]), (mock) -> MOIU.mock_optimize!(mock, [[0.0], [2.73683 0; 0 1.73683]], [1.0]), (mock) -> MOIU.mock_optimize!(mock, - [[1.88804e-9], [1.0], [3.25375 0; 0 2.25375]], + [[1.0], [0.0], [3.25375 0; 0 2.25375]], [1.0, 0.0]), (mock) -> MOIU.mock_optimize!(mock, [[0.0], [4.47626 0; 0 2.47626]],