From 19914ddf1d9d94c7dee3f6ddb24b320b9b8dac5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= <benoit.legat@gmail.com> Date: Sun, 10 Mar 2019 23:29:33 +0100 Subject: [PATCH 1/6] Stop creating slacks thanks to bridges --- .gitignore | 1 + src/SemidefiniteOptInterface.jl | 124 +++++++-------- src/constraint.jl | 51 +------ src/mock.jl | 4 +- src/variable.jl | 31 ++-- test/contconic.jl | 257 ++++++++++++++++---------------- test/contlinear.jl | 124 ++++++++------- test/mock_tests_generator.ipynb | 74 +++++---- test/runtests.jl | 17 ++- test/unit.jl | 56 +++---- 10 files changed, 364 insertions(+), 375 deletions(-) diff --git a/.gitignore b/.gitignore index 8c960ec..6014500 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.jl.cov *.jl.*.cov *.jl.mem +.ipynb_checkpoints diff --git a/src/SemidefiniteOptInterface.jl b/src/SemidefiniteOptInterface.jl index d1999e1..a9eb9c1 100644 --- a/src/SemidefiniteOptInterface.jl +++ b/src/SemidefiniteOptInterface.jl @@ -15,10 +15,7 @@ const SVF = MOI.SingleVariable const VVF = MOI.VectorOfVariables const VF = Union{SVF, VVF} const SAF{T} = MOI.ScalarAffineFunction{T} -const VAF{T} = MOI.VectorAffineFunction{T} -const AF{T} = Union{SAF{T}, VAF{T}} const ASF{T} = Union{SVF, SAF{T}} -const AVF{T} = Union{VVF, VAF{T}} const ZS = Union{MOI.EqualTo, MOI.Zeros} const NS = Union{MOI.GreaterThan, MOI.Nonnegatives} @@ -43,7 +40,6 @@ mutable struct SOItoMOIBridge{T, SIT <: AbstractSDOptimizer} <: MOI.AbstractOpti varmap::Vector{Vector{Tuple{Int, Int, Int, T, T}}} # Variable Index vi -> blk, i, j, coef, shift # x = sum coef * block(X, blk)[i, j] + shift zeroblock::Dict{CI, Int} constrmap::Dict{CI, UnitRange{Int}} # Constraint Index ci -> cs - slackmap::Vector{Tuple{Int, Int, Int, T}} # c -> blk, i, j, coef double::Vector{CI} # created when there are two cones for same variable function SOItoMOIBridge{T}(sdoptimizer::SIT) where {T, SIT} new{T, SIT}(sdoptimizer, Dict{Int64, T}(), Dict{Int, T}(), @@ -53,7 +49,6 @@ mutable struct SOItoMOIBridge{T, SIT <: AbstractSDOptimizer} <: MOI.AbstractOpti Vector{Tuple{Int, Int, Int, T}}[], Dict{CI, Int}(), Dict{CI, UnitRange{Int}}(), - Tuple{Int, Int, Int, T}[], CI[]) end end @@ -86,8 +81,7 @@ function MOI.is_empty(optimizer::SOItoMOIBridge) isempty(optimizer.free) && isempty(optimizer.varmap) && isempty(optimizer.zeroblock) && - isempty(optimizer.constrmap) && - isempty(optimizer.slackmap) + isempty(optimizer.constrmap) end function MOI.empty!(optimizer::SOItoMOIBridge{T}) where T for s in optimizer.double @@ -107,37 +101,57 @@ function MOI.empty!(optimizer::SOItoMOIBridge{T}) where T optimizer.varmap = Vector{Tuple{Int, Int, Int, T}}[] optimizer.zeroblock = Dict{CI, Int}() optimizer.constrmap = Dict{CI, UnitRange{Int}}() - optimizer.slackmap = Tuple{Int, Int, Int, T}[] 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) end -function addsetconstant(optimizer::SOItoMOIBridge, ci::CI{<:Any, <:MOI.AbstractScalarSet}, x) - x + optimizer.setconstant[ci.value] +function set_constant(optimizer::SOItoMOIBridge, + ci::CI{<:MOI.AbstractScalarFunction, + <:MOI.AbstractScalarSet}) + return optimizer.setconstant[ci.value] end -function addsetconstant(optimizer::SOItoMOIBridge, ci::CI, x) - x +function set_constant(optimizer::SOItoMOIBridge{T}, ci::CI) where T + return zeros(T, length(optimizer.constrmap[ci])) end function addblkconstant(optimizer::SOItoMOIBridge, ci::CI{<:Any, <:Union{NS, PS}}, x) blk = -ci.value - x .+ optimizer.blkconstant[blk] -end -function addblkconstant(optimizer::SOItoMOIBridge, ci::CI, x) - x + return x .+ optimizer.blkconstant[blk] end +addblkconstant(optimizer::SOItoMOIBridge, ci::CI, x) = x -function MOI.supports(optimizer::SOItoMOIBridge{T}, - ::Union{MOI.ObjectiveSense, - MOI.ObjectiveFunction{<:Union{MOI.SingleVariable, - MOI.ScalarAffineFunction{T}}}}) where T +function MOI.supports( + optimizer::SOItoMOIBridge{T}, + ::Union{MOI.ObjectiveSense, + MOI.ObjectiveFunction{<:Union{MOI.SingleVariable, + MOI.ScalarAffineFunction{T}}}}) where T return true end -function MOI.supports_constraint(::SOItoMOIBridge{T}, - ::Type{<:Union{VF, AF{T}}}, - ::Type{<:SupportedSets}) where T +# Zeros and Nonpositives supports could be removed thanks to variable bridges +# * `VectorOfVariables`-in-`Zeros` would return a `VectorAffineFunction` with +# zero constant and no variable created. +# * `VectorOfVariables`-in-`Nonpositives` would create variables in +# `Nonnegatives` and return a `VectorAffineFunction` containing `-` the +# variables. +function MOI.supports_constraint( + ::SOItoMOIBridge, ::Type{MOI.VectorOfVariables}, + ::Type{<:Union{MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, + MOI.PositiveSemidefiniteConeTriangle}}) + return true +end +# This support could be remove thanks to variable bridges. +# The VectorizeVariableBridge would redirect to the above case and then the +# resulting function would be shifted by the constant. +function MOI.supports_constraint( + ::SOItoMOIBridge{T}, ::Type{MOI.SingleVariable}, + ::Type{<:Union{MOI.EqualTo{T}, MOI.GreaterThan{T}, MOI.LessThan{T}}}) where T + return true +end +function MOI.supports_constraint( + ::SOItoMOIBridge{T}, ::Type{MOI.ScalarAffineFunction{T}}, + ::Type{MOI.EqualTo{T}}) where T return true end @@ -163,10 +177,10 @@ MOI.get(m::SOItoMOIBridge, s::SolverStatus) = MOI.get(m.sdoptimizer, s) MOI.get(m::SOItoMOIBridge, ::MOI.ResultCount) = 1 function _getblock(M, blk::Integer, s::Type{<:Union{NS, ZS}}) - diag(block(M, blk)) + return diag(block(M, blk)) end function _getblock(M, blk::Integer, s::Type{<:PS}) - -diag(block(M, blk)) + return -diag(block(M, blk)) end # Vectorized length for matrix dimension d sympackedlen(d::Integer) = (d*(d+1)) >> 1 @@ -183,20 +197,22 @@ function _getblock(M::AbstractMatrix{T}, blk::Integer, s::Type{<:DS}) where T end end @assert k == n - v + return v end function getblock(M, blk::Integer, s::Type{<:MOI.AbstractScalarSet}) vd = _getblock(M, blk, s) @assert length(vd) == 1 - vd[1] + return vd[1] end function getblock(M, blk::Integer, s::Type{<:MOI.AbstractVectorSet}) - _getblock(M, blk, s) + return _getblock(M, blk, s) end getvarprimal(m::SOItoMOIBridge, blk::Integer, S) = getblock(getX(m.sdoptimizer), blk, S) function getvardual(m::SOItoMOIBridge, blk::Integer, S) - getblock(getZ(m.sdoptimizer), blk, S) + z = getZ(m.sdoptimizer) + b = getblock(z, blk, S) + return getblock(getZ(m.sdoptimizer), blk, S) end function MOI.get(m::SOItoMOIBridge{T}, ::MOI.VariablePrimal, vi::VI) where T @@ -208,41 +224,29 @@ function MOI.get(m::SOItoMOIBridge{T}, ::MOI.VariablePrimal, vi::VI) where T x += block(X, blk)[i, j] * sign(coef) end end - x + return x end function MOI.get(m::SOItoMOIBridge, vp::MOI.VariablePrimal, vi::Vector{VI}) - MOI.get.(m, vp, vi) + return MOI.get.(m, vp, vi) end function _getattribute(m::SOItoMOIBridge, ci::CI{<:ASF}, f) cs = m.constrmap[ci] @assert length(cs) == 1 - f(m, first(cs)) -end -function _getattribute(m::SOItoMOIBridge, ci::CI{<:AVF}, f) - f.(m, m.constrmap[ci]) + return f(m, first(cs)) end - -function getslack(m::SOItoMOIBridge{T}, c::Integer) where T - X = getX(m.sdoptimizer) - blk, i, j, coef = m.slackmap[c] - if iszero(blk) - zero(T) - else - if i != j - coef *= 2 # We should take block(X, blk)[i, j] + block(X, blk)[j, i] but they are equal - end - coef * block(X, blk)[i, j] - end +function _getattribute(m::SOItoMOIBridge, ci::CI{<:VVF}, f) + return f.(m, m.constrmap[ci]) end -function MOI.get(m::SOItoMOIBridge, a::MOI.ConstraintPrimal, ci::CI{F, S}) where {F, S} +function MOI.get(m::SOItoMOIBridge, a::MOI.ConstraintPrimal, + ci::CI{F, S}) where {F, S} if ci.value >= 0 - addsetconstant(m, ci, _getattribute(m, ci, getslack)) + return set_constant(m, ci) else # Variable Function-in-S with S different from Zeros and EqualTo and not a double variable constraint blk = -ci.value - addblkconstant(m, ci, getvarprimal(m, blk, S)) + return addblkconstant(m, ci, getvarprimal(m, blk, S)) end end @@ -254,7 +258,7 @@ function getvardual(m::SOItoMOIBridge{T}, vi::VI) where T z += block(Z, blk)[i, j] * sign(coef) end end - z + return z end getvardual(m::SOItoMOIBridge, f::SVF) = getvardual(m, f.variable) getvardual(m::SOItoMOIBridge, f::VVF) = map(vi -> getvardual(m, vi), f.variables) @@ -263,26 +267,26 @@ getvardual(m::SOItoMOIBridge, f::VVF) = map(vi -> getvardual(m, vi), f.variables #end function MOI.get(m::SOItoMOIBridge, ::MOI.ConstraintDual, ci::CI{<:VF, S}) where S<:SupportedSets if ci.value < 0 - getvardual(m, -ci.value, S) + return getvardual(m, -ci.value, S) else dual = _getattribute(m, ci, getdual) if haskey(m.zeroblock, ci) # ZS - dual + getvardual(m, m.zeroblock[ci], S) + return dual + getvardual(m, m.zeroblock[ci], S) else # var constraint on unfree constraint - dual + return dual end end end function getdual(m::SOItoMOIBridge{T}, c::Integer) where T if c == 0 - zero(T) + return zero(T) else - -gety(m.sdoptimizer)[c] + return -gety(m.sdoptimizer)[c] end end function MOI.get(m::SOItoMOIBridge, ::MOI.ConstraintDual, ci::CI) - _getattribute(m, ci, getdual) + return _getattribute(m, ci, getdual) end function scalevec!(v, c) d = div(isqrt(1+8length(v))-1, 2) @@ -294,11 +298,11 @@ function scalevec!(v, c) end i += j end - v + return v end function MOI.get(m::SOItoMOIBridge{T}, ::MOI.ConstraintDual, - ci::CI{<:AF{T}, DS}) where T - scalevec!(_getattribute(m, ci, getdual), one(T)/2) + ci::CI{<:SAF{T}, DS}) where T + return scalevec!(_getattribute(m, ci, getdual), one(T)/2) end include("sdpa.jl") diff --git a/src/constraint.jl b/src/constraint.jl index d635977..30ec041 100644 --- a/src/constraint.jl +++ b/src/constraint.jl @@ -1,32 +1,5 @@ -function createslack!(m::SOItoMOIBridge{T}, cs, ::ZS) where T - m.slackmap[cs] .= ((0, 0, 0, zero(T)),) -end -function createslack!(m::SOItoMOIBridge, cs, ::S) where S <: Union{NS, PS} - blk = newblock(m, -length(cs)) - for (i, c) in enumerate(cs) - m.slackmap[c] = (blk, i, i, vscaling(S)) - end -end -function createslack!(m::SOItoMOIBridge{T}, cs, ::DS) where T - d = getmatdim(length(cs)) - k = 0 - blk = newblock(m, d) - for i in 1:d - for j in 1:i - k += 1 - m.slackmap[cs[k]] = (blk, i, j, i == j ? one(T) : one(T)/2) - end - end -end - -function createslack!(m::SOItoMOIBridge, ci::CI, f, s) - cs = m.constrmap[ci] - createslack!(m, cs, s) -end - nconstraints(f::Union{SVF, SAF}, s) = 1 nconstraints(f::VVF, s) = length(f.variables) -nconstraints(f::VAF, s) = MOI.output_dimension(f) function _allocate_constraint(m::SOItoMOIBridge, f, s) ci = CI{typeof(f), typeof(s)}(m.nconstrs) @@ -35,27 +8,12 @@ function _allocate_constraint(m::SOItoMOIBridge, f, s) #m.constrmap[ci] = m.nconstrs .+ (1:n) m.constrmap[ci] = (m.nconstrs + 1):(m.nconstrs + n) m.nconstrs += n - resize!(m.slackmap, m.nconstrs) - createslack!(m, ci, f, s) - ci + return ci end -function MOIU.allocate_constraint(m::SOItoMOIBridge, f::AF, s::SupportedSets) +function MOIU.allocate_constraint(m::SOItoMOIBridge, f::SAF, s::SupportedSets) _allocate_constraint(m::SOItoMOIBridge, f, s) end -function loadslack!(m::SOItoMOIBridge, c::Integer) - blk, i, j, coef = m.slackmap[c] - if blk != 0 - @assert !iszero(coef) - setconstraintcoefficient!(m.sdoptimizer, -coef, c, blk, i, j) - end -end -function loadslacks!(m::SOItoMOIBridge, cs) - for c in cs - loadslack!(m, c) - end -end - output_index(::MOI.ScalarAffineTerm) = 1 output_index(t::MOI.VectorAffineTerm) = t.output_index scalar_term(t::MOI.ScalarAffineTerm) = t @@ -64,7 +22,7 @@ scalar_term(t::MOI.VectorAffineTerm) = t.scalar_term _getconstant(m::SOItoMOIBridge, s::MOI.AbstractScalarSet) = MOIU.getconstant(s) _getconstant(m::SOItoMOIBridge{T}, s::MOI.AbstractSet) where T = zero(T) -function loadcoefficients!(m::SOItoMOIBridge, cs::UnitRange, f::AF, s) +function loadcoefficients!(m::SOItoMOIBridge, cs::UnitRange, f::SAF, s) f = MOIU.canonical(f) # sum terms with same variables and same outputindex if !isempty(cs) rhs = _getconstant(m, s) .- MOI._constant(f) @@ -92,10 +50,9 @@ function loadcoefficients!(m::SOItoMOIBridge, cs::UnitRange, f::AF, s) end end -function MOIU.load_constraint(m::SOItoMOIBridge, ci::CI, f::AF, s::SupportedSets) +function MOIU.load_constraint(m::SOItoMOIBridge, ci::CI, f::SAF, s::SupportedSets) setconstant!(m, ci, s) cs = m.constrmap[ci] @assert !isempty(cs) - loadslacks!(m, cs) loadcoefficients!(m, cs, f, s) end diff --git a/src/mock.jl b/src/mock.jl index 5a9065d..2c6c3a4 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 = sum(blk -> Compat.LinearAlgebra.checksquare(block(bm, blk)), - 1:nblocks(bm)) + n = Compat.mapreduce(blk -> Compat.LinearAlgebra.checksquare(block(bm, blk)), + +, 1:nblocks(bm), init=0) return (n, n) end function Base.getindex(bm::AbstractBlockMatrix, i::Integer, j::Integer) diff --git a/src/variable.jl b/src/variable.jl index eea3de4..7bcb2df 100644 --- a/src/variable.jl +++ b/src/variable.jl @@ -6,7 +6,6 @@ function newblock(m::SOItoMOIBridge, n) end isfree(m, v::VI) = v.value in m.free -isfree(m, v::Vector{VI}) = all(isfree.(m, v)) function unfree(m, v) @assert isfree(m, v) delete!(m.free, v.value) @@ -61,20 +60,27 @@ function _constraintvariable!(m::SOItoMOIBridge{T}, vs::VIS, ::DS) where T end _var(f::SVF) = f.variable _var(f::VVF) = f.variables +function _throw_error_if_unfree(m, vi::MOI.VariableIndex) + if !isfree(m, vi) + error("A variable cannot be constrained by multiple ", + "`MOI.SingleVariable` or `MOI.VectorOfVariables` constraints.") + end +end +function _throw_error_if_unfree(m, vis::MOI.Vector) + for vi in vis + _throw_error_if_unfree(m, vi) + end +end function MOIU.allocate_constraint(m::SOItoMOIBridge{T}, f::VF, s::SupportedSets) where T vis = _var(f) - fr = isfree(m, vis) - if fr - blk = _constraintvariable!(m, vis, s) - if isa(s, ZS) - ci = _allocate_constraint(m, f, s) - m.zeroblock[ci] = blk - ci - else - CI{typeof(f), typeof(s)}(-blk) - end + _throw_error_if_unfree(m, vis) + blk = _constraintvariable!(m, vis, s) + if isa(s, ZS) + ci = _allocate_constraint(m, f, s) + m.zeroblock[ci] = blk + return ci else - _allocate_constraint(m, f, s) + return CI{typeof(f), typeof(s)}(-blk) end end @@ -85,7 +91,6 @@ function MOIU.load_constraint(m::SOItoMOIBridge, ci::CI, f::VF, s::SupportedSets setconstant!(m, ci, s) cs = m.constrmap[ci] @assert !isempty(cs) - loadslacks!(m, cs) for k in 1:length(cs) vm = varmap(m, _var(f, k)) # For free variables, the length of vm is 2, clearly not the case here diff --git a/test/contconic.jl b/test/contconic.jl index 78871c6..a833d29 100644 --- a/test/contconic.jl +++ b/test/contconic.jl @@ -1,135 +1,132 @@ -@testset "MOI Continuous Conic" begin - @testset "Linear" begin - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 2.0], [2.8924 0.0; 0.0 1.8924], [2.3501 0.0; 0.0 2.3501], [3.6263 0.0; 0.0 1.6263]], - [3.0, 1.0, -0.0, -2.0, -0.0])) - MOIT.lin1ftest(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 2.0]], - [3.0, 1.0])) - MOIT.lin1vtest(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[16.0], [3.0], [13.9279 0.0; 0.0 17.9279], [14.3814 0.0; 0.0 17.3814], [25.3959 0.0; 0.0 9.3959], [15.8211 0.0; 0.0 15.8211]], - [-7.0, -2.0, 4.0, -7.0, -0.0, 0.0])) - MOIT.lin2ftest(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [16.0], [3.0], [75.9147 0.0; 0.0 79.9147]], - [70.2006, -7.0, -2.0, 4.0])) - MOIT.lin2vtest(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - MOI.INFEASIBLE, - MOI.INFEASIBLE_POINT, - [-0.5, 0.5])) - MOIT.lin3test(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - MOI.INFEASIBLE, - MOI.INFEASIBLE_POINT, - [-1.0])) - MOIT.lin4test(cached_mock_optimizer, config) - end - @testset "SOC" begin - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0 0.7071 0.7071; 0.7071 1.0 -0.0; 0.7071 -0.0 1.0], [2.2375 0.0; 0.0 1.2375], [2.0662 0.0; 0.0 1.3591], [2.0662 0.0; 0.0 1.3591]], - [1.4142, -0.7071, 1.0, -0.3536, 1.0, -0.7071, -0.3536])) - MOIT.soc1ftest(MOIB.SOCtoPSD{Float64}(cached_mock_optimizer), config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0 0.7071 0.7071; 0.7071 1.0 -0.0; 0.7071 -0.0 1.0], [2.2375 0.0; 0.0 1.2375], [2.0662 0.0; 0.0 1.3591], [2.0662 0.0; 0.0 1.3591]], - [1.4142, -0.7071, 1.0, -0.3536, 1.0, -0.7071, -0.3536])) - MOIT.soc1vtest(MOIB.SOCtoPSD{Float64}(cached_mock_optimizer), config) +@testset "Linear" begin + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.0 0 0; 0 0 0; 0 0 2.0], [2.89241 0; 0 1.89241], [2.35008 0; 0 2.35008], [3.62629 0; 0 1.62629]], + [0.0, -2.0, 0.0, 3.0, 1.0])) + MOIT.lin1ftest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.0 0.0 0.0; 0.0 0.0 0.0; 0.0 0.0 2.0]], + [3.0, 1.0])) + MOIT.lin1vtest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[16.0], [3.0], [13.9279 0.0; 0.0 17.9279], [14.3814 0.0; 0.0 17.3814], [25.3959 0.0; 0.0 9.3959], [15.8211 0.0; 0.0 15.8211]], + [-7.0, -2.0, 4.0, 0.0, 0.0, -7.0])) + MOIT.lin2ftest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [16.0], [3.0], [75.9147 0.0; 0.0 79.9147]], + [-7.0, -2.0, 4.0, 70.2306])) + MOIT.lin2vtest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + MOI.INFEASIBLE, MOI.INFEASIBLE_POINT, [-0.5, 0.5])) + MOIT.lin3test(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + MOI.INFEASIBLE, MOI.INFEASIBLE_POINT, [-1.0])) + MOIT.lin4test(bridged, config) +end +@testset "SOC" begin + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.0 0.7071 0.7071; 0.7071 1.0 -0.0; 0.7071 -0.0 1.0], [2.2375 0.0; 0.0 1.2375], [2.0662 0.0; 0.0 1.3591], [2.0662 0.0; 0.0 1.3591]], + [1.4142, -0.7071, 1.0, -0.3536, 1.0, -0.7071, -0.3536])) + MOIT.soc1ftest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.0 0.7071 0.7071; 0.7071 1.0 -0.0; 0.7071 -0.0 1.0], [2.2375 0.0; 0.0 1.2375], [2.0662 0.0; 0.0 1.3591], [2.0662 0.0; 0.0 1.3591]], + [1.4142, -0.7071, 1.0, -0.3536, 1.0, -0.7071, -0.3536])) + MOIT.soc1vtest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [1.0 -0.7071 0.7071; -0.7071 1.0 0.0; 0.7071 0.0 1.0], [0.4046 0.0; 0.0 1.1117], [1.0895 0.0; 0.0 0.3824], [1.3079 0.0; 0.0 0.3079]], + [-1, -√2, -√2/2, -1, -√2/4, 1, √2/2, -√2/4])) + MOIT.soc2ntest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [1.0 -0.7071 0.7071; -0.7071 1.0 0.0; 0.7071 0.0 1.0], [0.4046 0.0; 0.0 1.1117], [1.0895 0.0; 0.0 0.3824], [1.3079 0.0; 0.0 0.3079]], + [1, -√2, -√2/2, -1, -√2/4, 1, √2/2, -√2/4])) + MOIT.soc2ptest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + MOI.INFEASIBLE, + MOI.INFEASIBLE_POINT, + [-1.0, 1.0, -0.5, 1.0, -0.5])) + MOIT.soc3test(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.0 0.8944 0.4472; 0.8944 1.0 0.0; 0.4472 0.0 1.0], [1.9332 0.0; 0.0 0.9332], [1.868 0.0; 0.0 0.9736], [1.5795 0.0; 0.0 1.1323], [1.868 0.0; 0.0 0.9736], [1.5795 0.0; 0.0 1.1323]], + [2.2361, 2.0, 1.0, -1.118, 2.0, -0.8944, 1.0, -0.8944, -0.2236])) + MOIT.soc4test(bridged, config) +end +@testset "RSOC" begin MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [1.0 -0.7071 0.7071; -0.7071 1.0 0.0; 0.7071 0.0 1.0], [0.4046 0.0; 0.0 1.1117], [1.0895 0.0; 0.0 0.3824], [1.3079 0.0; 0.0 0.3079]], - [-1.4142, -1.0, -0.7071, -1.0, -0.3536, 1.0, 0.7071, -0.3536])) - MOIT.soc2ntest(MOIB.SOCtoPSD{Float64}(cached_mock_optimizer), config) + [[0.5 0.7071 0.7071; 0.7071 2.0 0.0; 0.7071 0.0 2.0], [0.8667 0.0; 0.0 0.1596], [0.8667 0.0; 0.0 0.1596]], + [-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], [1.0 -0.7071 0.7071; -0.7071 1.0 0.0; 0.7071 0.0 1.0], [0.4046 0.0; 0.0 1.1117], [1.0895 0.0; 0.0 0.3824], [1.3079 0.0; 0.0 0.3079]], - [-1.4142, 1.0, -0.7071, -1.0, -0.3536, 1.0, 0.7071, -0.3536])) - MOIT.soc2ptest(MOIB.SOCtoPSD{Float64}(cached_mock_optimizer), config) + [[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])) + MOIT.rotatedsoc1vtest(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, MOI.INFEASIBLE, - MOI.INFEASIBLE_POINT, - [-1.0, 1.0, -0.5, 1.0, -0.5])) - MOIT.soc3test(MOIB.SOCtoPSD{Float64}(cached_mock_optimizer), config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0 0.8944 0.4472; 0.8944 1.0 0.0; 0.4472 0.0 1.0], [1.9332 0.0; 0.0 0.9332], [1.868 0.0; 0.0 0.9736], [1.5795 0.0; 0.0 1.1323], [1.868 0.0; 0.0 0.9736], [1.5795 0.0; 0.0 1.1323]], - [2.2361, 2.0, 1.0, -1.118, 2.0, -0.8944, 1.0, -0.8944, -0.2236])) - MOIT.soc4test(MOIB.SOCtoPSD{Float64}(cached_mock_optimizer), config) - end - @testset "RSOC" begin - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.5 0.7071 0.7071; 0.7071 2.0 0.0; 0.7071 0.0 2.0], [0.8667 0.0; 0.0 0.1596], [0.8667 0.0; 0.0 0.1596]], - [-1.4142, 1.0, -0.1768, 1.0, -0.3536, -0.1768])) - MOIT.rotatedsoc1ftest(MOIB.RSOCtoPSD{Float64}(cached_mock_optimizer), 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])) - MOIT.rotatedsoc1vtest(MOIB.RSOCtoPSD{Float64}(cached_mock_optimizer), config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - MOI.INFEASIBLE, - tuple(), - [141.088, -47.8864, 47.5533, -46.2201])) - MOIT.rotatedsoc2test(MOIB.RSOCtoPSD{Float64}(cached_mock_optimizer), config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [3.0], [0.0], [1.0 0.0; 0.0 0.0], [0.7071 1.0 0.0001; 1.0 1.4142 -0.0; 0.0001 -0.0 1.4142], [0.7071 1.7321; 1.7321 4.2426], [4.5908 0.0; 0.0 2.8588]], - [0.0, 0.0, 0.2887, -0.6124, 0.866, -0.3062, 0.0, -0.0001, -0.0, -1.2247, 1.0, -0.2041])) - MOIT.rotatedsoc3test(MOIB.RSOCtoPSD{Float64}(cached_mock_optimizer), config) - 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])) - MOIT.geomean1ftest(MOIB.GeoMean{Float64}(MOIB.RSOCtoPSD{Float64}(cached_mock_optimizer)), 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(MOIB.GeoMean{Float64}(MOIB.RSOCtoPSD{Float64}(cached_mock_optimizer)), config) - end - @testset "PSD" begin - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0 1.0; 1.0 1.0], [2.2633 0.0; 0.0 1.2633], [2.2669 0.0; 0.0 1.2669], [2.2633 0.0; 0.0 1.2633]], - [-2.0, -1.0, 2.0, -1.0])) - MOIT.psdt0ftest(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0 1.0; 1.0 1.0]], - [-2.0])) - MOIT.psdt0vtest(cached_mock_optimizer, config) - # PSD1: see comments in MOI/src/Test/contconic.jl to see where these constants come from - δ = √(1 + (3*√2+2)*√(-116*√2+166) / 14) / 2 - ε = √((1 - 2*(√2-1)*δ^2) / (2-√2)) - y2 = 1 - ε*δ - y1 = 1 - √2*y2 - obj = y1 + y2/2 - k = -2*δ/ε - x2 = ((3-2obj)*(2+k^2)-4) / (4*(2+k^2)-4*√2) - α = √(3-2obj-4x2)/2 - β = k*α - Xv = [α^2, α*β, β^2, α^2, α*β, α^2] - xv = [√2*x2, x2, x2] - cX0 = 1+(√2-1)*y2 - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[Xv[1] Xv[2] Xv[1]; Xv[2] Xv[3] Xv[2]; Xv[1] Xv[2] Xv[1]], - [0.254409 0.179895 0.179895; 0.179895 0.254409 0.0; 0.179895 0.0 0.254409], - [0.349485 0; 0 0.132235], - [0.114062 0; 0 0.374032], - [0.419535 0; 0 0.108444], - [0.313002 0; 0 0.0957514], - [0.114062 0; 0 0.374032], - [0.349485 0; 0 0.132235], - [0.354357 0; 0 0.0999473], - [0.332125 0; 0 0.152231], - [0.332125 0; 0 0.152231]], - [y2*√2-1, -y2, -cX0, -1.35619, -cX0, 2y2, -1.35619, -cX0, -y2/√2, y2, -y2/√2/2, y2, -y2/√2, -y2/√2/2])) - MOIT.psdt1ftest(MOIB.SOCtoPSD{Float64}(cached_mock_optimizer), config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[Xv[1] Xv[2] Xv[1]; Xv[2] Xv[3] Xv[2]; Xv[1] Xv[2] Xv[1]], - [xv[1] xv[2] xv[2]; xv[2] xv[1] 0.0; xv[2] 0.0 xv[1]], - [0.486623 0; 0 0.486623-xv[1]], - [0.4475 0; 0 0.4475-xv[2]], - [0.4475 0; 0 0.4475-xv[2]]], - [y2*√2-1, -y2, -y2/√2, y2, -y2/√2/2, y2, -y2/√2, -y2/√2/2])) - MOIT.psdt1vtest(MOIB.SOCtoPSD{Float64}(cached_mock_optimizer), 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.0, -0.1902, -0.0, 0.126, -0.0, 0.1426, 0.1426, 0.0127, -0.2113, -0.8165, -0.7887])) - MOIT.psdt2test(cached_mock_optimizer, config) - end + tuple(), + [141.088, -47.8864, 47.5533, -46.2201])) + 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, + # it creates a slack +# MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, +# [[0.0], [0.0], [3.0], [0.0], [1.0 0.0; 0.0 0.0], [0.7071 1.0 0.0001; 1.0 1.4142 -0.0; 0.0001 -0.0 1.4142], [0.7071 1.7321; 1.7321 4.2426], [4.5908 0.0; 0.0 2.8588]], +# [0.0, 0.0, 0.2887, -0.6124, 0.866, -0.3062, 0.0, -0.0001, -0.0, -1.2247, 1.0, -0.2041])) +# MOIT.rotatedsoc3test(bridged, config) +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])) + 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 + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.0 1.0; 1.0 1.0], [2.2633 0.0; 0.0 1.2633], [2.2669 0.0; 0.0 1.2669], [2.2633 0.0; 0.0 1.2633]], + [-1.0, 2.0, -1.0, -2.0])) + MOIT.psdt0ftest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.0 1.0; 1.0 1.0]], + [-2.0])) + MOIT.psdt0vtest(bridged, config) + # PSD1: see comments in MOI/src/Test/contconic.jl to see where these constants come from + δ = √(1 + (3*√2+2)*√(-116*√2+166) / 14) / 2 + ε = √((1 - 2*(√2-1)*δ^2) / (2-√2)) + y2 = 1 - ε*δ + y1 = 1 - √2*y2 + obj = y1 + y2/2 + k = -2*δ/ε + x2 = ((3-2obj)*(2+k^2)-4) / (4*(2+k^2)-4*√2) + α = √(3-2obj-4x2)/2 + β = k*α + Xv = [α^2, α*β, β^2, α^2, α*β, α^2] + xv = [√2*x2, x2, x2] + cX0 = 1+(√2-1)*y2 + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[Xv[1] Xv[2] Xv[1]; Xv[2] Xv[3] Xv[2]; Xv[1] Xv[2] Xv[1]], + [0.254409 0.179895 0.179895; 0.179895 0.254409 0.0; 0.179895 0.0 0.254409], + [0.349485 0; 0 0.132235], + [0.114062 0; 0 0.374032], + [0.419535 0; 0 0.108444], + [0.313002 0; 0 0.0957514], + [0.114062 0; 0 0.374032], + [0.349485 0; 0 0.132235], + [0.354357 0; 0 0.0999473], + [0.332125 0; 0 0.152231], + [0.332125 0; 0 0.152231]], + [-cX0, -1.35619, -cX0, 2y2, -1.35619, -cX0, -y2/√2, y2, -y2/√2/2, y2, -y2/√2, -y2/√2/2, y2*√2-1, -y2])) + MOIT.psdt1ftest(bridged, config) + MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[Xv[1] Xv[2] Xv[1]; Xv[2] Xv[3] Xv[2]; Xv[1] Xv[2] Xv[1]], + [xv[1] xv[2] xv[2]; xv[2] xv[1] 0.0; xv[2] 0.0 xv[1]], + [0.486623 0; 0 0.486623-xv[1]], + [0.4475 0; 0 0.4475-xv[2]], + [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])) + MOIT.psdt2test(bridged, config) end diff --git a/test/contlinear.jl b/test/contlinear.jl index ec2b7e4..8380ae3 100644 --- a/test/contlinear.jl +++ b/test/contlinear.jl @@ -1,40 +1,42 @@ @testset "MOI Continuous Linear" begin - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0], [0.0], [0.0]], - [1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[1.0], [0.0], [0.0]], - [1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [1.0], [0.0]], - [2.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [2.0], [0.0]], - [2.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [1.0], [0.0], [0.0]], - [54.4045, 1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [2.0], [0.0]], - [61.2652, 1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [2.0]], - [79.6537, 2.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [1.0], [1.0], [0.0]], - [30.9277, 1.5, -0.5])) - MOIT.linear1test(cached_mock_optimizer, config) + # FIXME `ListOfVariableIndices` is not modified by bridges + # see https://github.com/JuliaOpt/MathOptInterface.jl/issues/693 +# MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, +# [[1.0], [0.0], [0.0]], +# [1.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[1.0], [0.0], [0.0]], +# [1.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[0.0], [0.0], [1.0], [0.0]], +# [2.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[0.0], [0.0], [2.0], [0.0]], +# [2.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[0.0], [1.0], [0.0], [0.0]], +# [54.4045, 1.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[0.0], [2.0], [0.0]], +# [61.2652, 1.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[0.0], [0.0], [2.0]], +# [79.6537, 2.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[0.0], [1.0], [1.0], [0.0]], +# [30.9277, 1.5, -0.5])) +# MOIT.linear1test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[1.0], [0.0], [0.0]], [1.0])) - MOIT.linear2test(cached_mock_optimizer, config) + MOIT.linear2test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[3.0], [0.0]], [-1.0]), (mock) -> MOIU.mock_optimize!(mock, [[0.0], [3.0]], [-0.0])) - MOIT.linear3test(cached_mock_optimizer, config) + MOIT.linear3test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[0.0], [0.0]], [-0.0]), @@ -44,7 +46,7 @@ (mock) -> MOIU.mock_optimize!(mock, [[0.0], [0.0]], [-0.0])) - MOIT.linear4test(cached_mock_optimizer, config) + MOIT.linear4test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[1.3333], [1.3333], [0.0], [0.0]], [0.3333, 0.3333]), @@ -57,7 +59,7 @@ (mock) -> MOIU.mock_optimize!(mock, [[2.0], [0.0]], [0.5])) - MOIT.linear5test(cached_mock_optimizer, config) + MOIT.linear5test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[0.0], [0.0], [0.0 0.0; 0.0 0.0], [0.0 0.0; 0.0 0.0]], [-1.0, 1.0]), @@ -67,7 +69,7 @@ (mock) -> MOIU.mock_optimize!(mock, [[0.0], [0.0], [250.152 0.0; 0.0 150.152], [150.152 0.0; 0.0 250.152]], [-1.0, 1.0])) - MOIT.linear6test(cached_mock_optimizer, config) + MOIT.linear6test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[0.0], [0.0], [0.0 0.0; 0.0 0.0], [0.0 0.0; 0.0 0.0]], [-1.0, 1.0]), @@ -77,59 +79,65 @@ (mock) -> MOIU.mock_optimize!(mock, [[0.0], [0.0], [250.152 0.0; 0.0 150.152], [150.152 0.0; 0.0 250.152]], [-1.0, 1.0])) - MOIT.linear7test(cached_mock_optimizer, config) + MOIT.linear7test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, MOI.INFEASIBLE, tuple(), [1.0])) - MOIT.linear8atest(cached_mock_optimizer, config) + MOIT.linear8atest(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, MOI.DUAL_INFEASIBLE, (MOI.INFEASIBILITY_CERTIFICATE, [[0.7709], [0.2291], [0.3126]]))) - MOIT.linear8btest(cached_mock_optimizer, config) + MOIT.linear8btest(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, MOI.DUAL_INFEASIBLE, (MOI.INFEASIBILITY_CERTIFICATE, [[0.5], [0.5]]))) - MOIT.linear8ctest(cached_mock_optimizer, config) + MOIT.linear8ctest(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[29.0909], [36.3636], [4.5455], [0.0], [0.0001]], [-0.0, 11.3636, 0.8636])) - MOIT.linear9test(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[5.0], [5.0], [5.0], [0.0]], - [-0.0, 1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[2.5], [2.5], [0.0], [5.0]], - [-1.0, 0.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[1.0], [1.0], [0.0], [10.0]], - [-1.0, -0.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[6.0], [6.0], [10.0], [0.0]], - [-0.0, 1.0])) - MOIT.linear10test(MOIB.SplitInterval{Float64}(cached_mock_optimizer), config) + MOIT.linear9test(bridged, config) + # FIXME 5 <= x + y <= 10 is bridged into x + y - z == 0, 5 <= z <= 10 and + # then it tries to add two SingleVariable constraints to `z`. We should drop + # support for MOI.LessThan once variables bridges works. +# MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, +# [[5.0], [5.0], [5.0], [0.0]], +# [-0.0, 1.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[2.5], [2.5], [0.0], [5.0]], +# [-1.0, 0.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[1.0], [1.0], [0.0], [10.0]], +# [-1.0, -0.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[6.0], [6.0], [10.0], [0.0]], +# [-0.0, 1.0])) +# MOIT.linear10test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[1.0], [0.0], [3.2439 0.0; 0.0 2.2439], [3.2439 0.0; 0.0 2.2439]], [0.0, -1.0]), (mock) -> MOIU.mock_optimize!(mock, [[0.0], [1.0], [1.3765 0.0; 0.0 0.8765], [1.3765 0.0; 0.0 0.8765]], [-1.0, 0.0])) - MOIT.linear11test(cached_mock_optimizer, config) + MOIT.linear11test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, MOI.INFEASIBLE, tuple(), [1.0, 3.0])) - MOIT.linear12test(cached_mock_optimizer, config) + MOIT.linear12test(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[24.0266], [27.6758 0.0; 0.0 22.6705], [27.6758 0.0; 0.0 22.6705]], [0.0, 0.0])) - MOIT.linear13test(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.5], [1.0], [0.0], [0.0]], - [2.0, 1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[1.0], [0.0]], - [1.0])) - MOIT.linear14test(cached_mock_optimizer, config) + MOIT.linear13test(bridged, config) + # FIXME z >= 0.0 followed by z <= 1.0. We need to drop support for + # SingleVariable-in-LessThan but we need variable bridge otherwise, + # it creates a slack +# MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, +# [[0.0], [0.5], [1.0], [0.0], [0.0]], +# [2.0, 1.0]), +# (mock) -> MOIU.mock_optimize!(mock, +# [[1.0], [0.0]], +# [1.0])) +# MOIT.linear14test(bridged, config) end diff --git a/test/mock_tests_generator.ipynb b/test/mock_tests_generator.ipynb index 17ba8fc..0b239c2 100644 --- a/test/mock_tests_generator.ipynb +++ b/test/mock_tests_generator.ipynb @@ -9,7 +9,7 @@ "using SemidefiniteOptInterface\n", "const SDOI = SemidefiniteOptInterface\n", "\n", - "using Base.Test\n", + "using Test\n", "\n", "using MathOptInterface\n", "const MOI = MathOptInterface\n", @@ -29,13 +29,15 @@ { "cell_type": "code", "execution_count": null, - "metadata": { - "collapsed": true - }, + "metadata": {}, "outputs": [], "source": [ "const MOIU = MOI.Utilities\n", - "MOIU.@model SDModelData () (EqualTo, GreaterThan, LessThan) (Zeros, Nonnegatives, Nonpositives, PositiveSemidefiniteConeTriangle) () (SingleVariable,) (ScalarAffineFunction,) (VectorOfVariables,) (VectorAffineFunction,)" + "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.VectorOfVariables,), ())" ] }, { @@ -45,10 +47,11 @@ "outputs": [], "source": [ "import CSDP\n", - "optimizer = CSDP.CSDPOptimizer(printlevel=0)\n", + "optimizer = CSDP.Optimizer(printlevel=0)\n", "\n", - "cached_optimizer = MOIU.CachingOptimizer(SDModelData{Float64}(), optimizer)\n", - "bridged_optimizer = MOIB.SplitInterval{Float64}(MOIB.RootDet{Float64}(MOIB.GeoMean{Float64}(MOIB.RSOCtoPSD{Float64}(MOIB.SOCtoPSD{Float64}(cached_optimizer)))))\n", + "cache = MOIU.UniversalFallback(SDModelData{Float64}())\n", + "cached = MOIU.CachingOptimizer(cache, optimizer)\n", + "bridged = MOIB.full_bridge_optimizer(cached, Float64)\n", "\n", "config = MOIT.TestConfig(atol=1e-4, rtol=1e-4)" ] @@ -56,7 +59,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "collapsed": true + }, "outputs": [], "source": [ "function MOI.optimize!(m::SDOI.SOItoMOIBridge)\n", @@ -64,10 +69,10 @@ " X = SDOI.getX(m.sdoptimizer)\n", " println(\"MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock,\")\n", " print( \" \")\n", - " if MOI.get(m, MOI.DualStatus()) == MOI.InfeasibilityCertificate\n", + " if MOI.get(m, MOI.DualStatus()) == MOI.INFEASIBILITY_CERTIFICATE\n", " print(\"tuple()\")\n", " else\n", - " if MOI.get(m, MOI.PrimalStatus()) == MOI.InfeasibilityCertificate\n", + " if MOI.get(m, MOI.PrimalStatus()) == MOI.INFEASIBILITY_CERTIFICATE\n", " print(\"(MOI.InfeasibilityCertificate, \")\n", " end\n", " print( \"[\")\n", @@ -79,11 +84,11 @@ " print(SDOI.block(X, blk))\n", " end\n", " print(\"]\")\n", - " if MOI.get(m, MOI.PrimalStatus()) == MOI.InfeasibilityCertificate\n", + " if MOI.get(m, MOI.PrimalStatus()) == MOI.INFEASIBILITY_CERTIFICATE\n", " print(\")\")\n", " end\n", " end\n", - " if MOI.get(m, MOI.PrimalStatus()) != MOI.InfeasibilityCertificate\n", + " if MOI.get(m, MOI.PrimalStatus()) != MOI.INFEASIBILITY_CERTIFICATE\n", " println(\",\")\n", " print( \" \")\n", " #print(round.(SDOI.gety(m.sdoptimizer), 4))\n", @@ -93,18 +98,6 @@ "end" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "mock = SDOI.MockSDOptimizer{Float64}()\n", - "mock_optimizer = SDOI.SDOIOptimizer(mock, Float64)\n", - "cached_mock_optimizer = MOIU.CachingOptimizer(SDModelData{Float64}(), mock_optimizer)\n", - "config = MOIT.TestConfig(atol=1e-4, rtol=1e-4)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -112,9 +105,9 @@ "outputs": [], "source": [ "function generate_mock_test(testfun)\n", - " testfun(bridged_optimizer, config)\n", - " testcall = replace(string(testfun), \"MathOptInterface.Test\", \"MOIT\")\n", - " println(\"$testcall(cached_mock_optimizer, config)\")\n", + " testfun(bridged, config)\n", + " testcall = replace(string(testfun), \"MathOptInterface.Test\" => \"MOIT\")\n", + " println(\"$testcall(bridged, config)\")\n", "end" ] }, @@ -124,7 +117,7 @@ "metadata": {}, "outputs": [], "source": [ - "generate_mock_test(MOIT.solve_singlevariable_obj)" + "generate_mock_test(MOIT.psdt0ftest)" ] }, { @@ -133,7 +126,7 @@ "metadata": {}, "outputs": [], "source": [ - "for testfun in map(p -> p.second, sort(collect(MOIT.psdttests), by=p->p.first))\n", + "for testfun in map(p -> p.second, sort(collect(MOIT.lintests), by=p->p.first))\n", " generate_mock_test(testfun)\n", "end" ] @@ -146,19 +139,34 @@ }, "outputs": [], "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "mock = SDOI.MockSDOptimizer{Float64}()\n", + "mock_optimizer = SDOI.SDOIOptimizer(mock, Float64)\n", + "cached = MOIU.CachingOptimizer(SDModelData{Float64}(), mock_optimizer)\n", + "bridged = MOIB.full_bridge_optimizer(cached, Float64)\n", + "config = MOIT.TestConfig(atol=1e-4, rtol=1e-4)" + ] } ], "metadata": { "kernelspec": { - "display_name": "Julia 0.6.3", + "display_name": "Julia 1.1.0", "language": "julia", - "name": "julia-0.6" + "name": "julia-1.1" }, "language_info": { "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "0.6.4" + "version": "1.1.0" } }, "nbformat": 4, diff --git a/test/runtests.jl b/test/runtests.jl index dbd2d74..a94698f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,7 +21,7 @@ MOIU.@model(SDModelData, (MOI.SingleVariable,), (MOI.ScalarAffineFunction,), (MOI.VectorOfVariables,), - (MOI.VectorAffineFunction,)) + ()) mock = SDOI.MockSDOptimizer{Float64}() mock_optimizer = SDOI.SDOIOptimizer(mock, Float64) @@ -29,15 +29,18 @@ mock_optimizer = SDOI.SDOIOptimizer(mock, Float64) @test MOIU.supports_allocate_load(mock_optimizer, false) @test !MOIU.supports_allocate_load(mock_optimizer, true) end -cached_mock_optimizer = MOIU.CachingOptimizer(SDModelData{Float64}(), - mock_optimizer) +cached = MOIU.CachingOptimizer(SDModelData{Float64}(), mock_optimizer) +bridged = MOIB.full_bridge_optimizer(cached, Float64) @testset "SolverName" begin - @test MOI.get( mock, MOI.SolverName()) == "MockSD" - @test MOI.get( mock_optimizer, MOI.SolverName()) == "MockSD" - @test MOI.get(cached_mock_optimizer, MOI.SolverName()) == "MockSD" + @test MOI.get(mock, MOI.SolverName()) == "MockSD" + @test MOI.get(mock_optimizer, MOI.SolverName()) == "MockSD" + @test MOI.get(cached, MOI.SolverName()) == "MockSD" + @test MOI.get(bridged, MOI.SolverName()) == "MockSD" end config = MOIT.TestConfig(atol=1e-4, rtol=1e-4) include("unit.jl") include("contlinear.jl") -include("contconic.jl") +@testset "MOI Continuous Conic" begin + include("contconic.jl") +end diff --git a/test/unit.jl b/test/unit.jl index aa1a07a..5018507 100644 --- a/test/unit.jl +++ b/test/unit.jl @@ -1,13 +1,13 @@ @testset "Unit" begin - MOIT.add_variable(cached_mock_optimizer, config) - MOIT.add_variables(cached_mock_optimizer, config) - MOIT.delete_variable(cached_mock_optimizer, config) - MOIT.delete_variable(cached_mock_optimizer, config) - MOIT.feasibility_sense(cached_mock_optimizer, config) - MOIT.getconstraint(cached_mock_optimizer, config) - MOIT.getvariable(cached_mock_optimizer, config) - MOIT.max_sense(cached_mock_optimizer, config) - MOIT.min_sense(cached_mock_optimizer, config) + MOIT.add_variable(bridged, config) + MOIT.add_variables(bridged, config) + MOIT.delete_variable(bridged, config) + MOIT.delete_variable(bridged, config) + MOIT.feasibility_sense(bridged, config) + MOIT.getconstraint(bridged, config) + MOIT.getvariable(bridged, config) + MOIT.max_sense(bridged, config) + MOIT.min_sense(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[0.0], [0.0 0; 0 0.0]], [1.0]), @@ -23,38 +23,44 @@ (mock) -> MOIU.mock_optimize!(mock, [[0.0], [4.47626 0; 0 2.47626]], [1.0])) - MOIT.solve_affine_deletion_edge_cases(cached_mock_optimizer, config) + MOIT.solve_affine_deletion_edge_cases(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[1.72037 0; 0 1.22037]], [-0.5])) - MOIT.solve_affine_equalto(cached_mock_optimizer, config) + MOIT.solve_affine_equalto(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[0.0], [2.10102 0; 0 1.60102]], [-0.5])) - MOIT.solve_affine_greaterthan(cached_mock_optimizer, config) + MOIT.solve_affine_greaterthan(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[3.0], [0.0], [4.88931 0; 0 2.88931]], [0.0, 1.5])) - MOIT.solve_affine_interval(MOIB.SplitInterval{Float64}(cached_mock_optimizer), config) + MOIT.solve_affine_interval(MOIB.SplitInterval{Float64}(bridged), config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[0.0], [2.06719 0; 0 1.56719]], [0.5])) - MOIT.solve_affine_lessthan(cached_mock_optimizer, config) + MOIT.solve_affine_lessthan(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[0.0]], [0.0])) - MOIT.solve_constant_obj(cached_mock_optimizer, config) + MOIT.solve_constant_obj(bridged, config) MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, [[0.0]], [0.0])) - MOIT.solve_singlevariable_obj(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [1.0]], - [0.0])) - MOIT.solve_with_lowerbound(cached_mock_optimizer, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0], [0.0]], - [2.0])) - MOIT.solve_with_upperbound(cached_mock_optimizer, config) - MOIT.variablenames(cached_mock_optimizer, config) + MOIT.solve_singlevariable_obj(bridged, config) + # FIXME x >= 1.0 followed by x <= 2.0. We need to drop support for + # SingleVariable-in-LessThan but we need variable bridge otherwise, + # it creates a slack +# MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, +# [[0.0], [1.0]], +# [0.0])) +# MOIT.solve_with_lowerbound(bridged, config) + # FIXME x <= 1.0 followed by x >= 0.0. We need to drop support for + # SingleVariable-in-LessThan but we need variable bridge otherwise, + # it creates a slack +# MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, +# [[1.0], [0.0]], +# [2.0])) +# MOIT.solve_with_upperbound(bridged, config) + MOIT.variablenames(bridged, config) end From 8345da931c4862fca7a2c0f893836e6586b10d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= <benoit.legat@gmail.com> Date: Sun, 10 Mar 2019 23:39:38 +0100 Subject: [PATCH 2/6] Move testset to runtests.jl --- test/contlinear.jl | 192 ++++++++++++++++++++++----------------------- test/runtests.jl | 8 +- test/unit.jl | 113 +++++++++++++------------- 3 files changed, 157 insertions(+), 156 deletions(-) diff --git a/test/contlinear.jl b/test/contlinear.jl index 8380ae3..99d8802 100644 --- a/test/contlinear.jl +++ b/test/contlinear.jl @@ -1,6 +1,5 @@ -@testset "MOI Continuous Linear" begin - # FIXME `ListOfVariableIndices` is not modified by bridges - # see https://github.com/JuliaOpt/MathOptInterface.jl/issues/693 +# FIXME `ListOfVariableIndices` is not modified by bridges +# see https://github.com/JuliaOpt/MathOptInterface.jl/issues/693 # MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, # [[1.0], [0.0], [0.0]], # [1.0]), @@ -26,81 +25,81 @@ # [[0.0], [1.0], [1.0], [0.0]], # [30.9277, 1.5, -0.5])) # MOIT.linear1test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0], [0.0], [0.0]], - [1.0])) - MOIT.linear2test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[3.0], [0.0]], - [-1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [3.0]], - [-0.0])) - MOIT.linear3test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0]], - [-0.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0]], - [-0.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0]], - [-0.0])) - MOIT.linear4test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.3333], [1.3333], [0.0], [0.0]], - [0.3333, 0.3333]), - (mock) -> MOIU.mock_optimize!(mock, - [[2.0], [0.0], [0.0], [2.0]], - [0.5, -0.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[4.0], [0.0], [0.0]], - [1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[2.0], [0.0]], - [0.5])) - MOIT.linear5test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [0.0 0.0; 0.0 0.0], [0.0 0.0; 0.0 0.0]], - [-1.0, 1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [168.953 0.0; 0.0 68.9528], [107.78 0.0; 0.0 107.78]], - [-1.0, 1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [250.152 0.0; 0.0 150.152], [150.152 0.0; 0.0 250.152]], - [-1.0, 1.0])) - MOIT.linear6test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [0.0 0.0; 0.0 0.0], [0.0 0.0; 0.0 0.0]], - [-1.0, 1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [168.953 0.0; 0.0 68.9528], [107.78 0.0; 0.0 107.78]], - [-1.0, 1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [0.0], [250.152 0.0; 0.0 150.152], [150.152 0.0; 0.0 250.152]], - [-1.0, 1.0])) - MOIT.linear7test(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.0], [0.0], [0.0]], + [1.0])) +MOIT.linear2test(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[3.0], [0.0]], + [-1.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [3.0]], + [-0.0])) +MOIT.linear3test(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [0.0]], + [-0.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [0.0]], + [-0.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [0.0]], + [-0.0])) +MOIT.linear4test(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.3333], [1.3333], [0.0], [0.0]], + [0.3333, 0.3333]), + (mock) -> MOIU.mock_optimize!(mock, + [[2.0], [0.0], [0.0], [2.0]], + [0.5, -0.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[4.0], [0.0], [0.0]], + [1.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[2.0], [0.0]], + [0.5])) +MOIT.linear5test(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [0.0], [0.0 0.0; 0.0 0.0], [0.0 0.0; 0.0 0.0]], + [-1.0, 1.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [0.0], [168.953 0.0; 0.0 68.9528], [107.78 0.0; 0.0 107.78]], + [-1.0, 1.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [0.0], [250.152 0.0; 0.0 150.152], [150.152 0.0; 0.0 250.152]], + [-1.0, 1.0])) +MOIT.linear6test(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [0.0], [0.0 0.0; 0.0 0.0], [0.0 0.0; 0.0 0.0]], + [-1.0, 1.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [0.0], [168.953 0.0; 0.0 68.9528], [107.78 0.0; 0.0 107.78]], + [-1.0, 1.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [0.0], [250.152 0.0; 0.0 150.152], [150.152 0.0; 0.0 250.152]], + [-1.0, 1.0])) +MOIT.linear7test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - MOI.INFEASIBLE, - tuple(), - [1.0])) - MOIT.linear8atest(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - MOI.DUAL_INFEASIBLE, - (MOI.INFEASIBILITY_CERTIFICATE, [[0.7709], [0.2291], [0.3126]]))) - MOIT.linear8btest(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - MOI.DUAL_INFEASIBLE, - (MOI.INFEASIBILITY_CERTIFICATE, [[0.5], [0.5]]))) - MOIT.linear8ctest(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[29.0909], [36.3636], [4.5455], [0.0], [0.0001]], - [-0.0, 11.3636, 0.8636])) - MOIT.linear9test(bridged, config) - # FIXME 5 <= x + y <= 10 is bridged into x + y - z == 0, 5 <= z <= 10 and - # then it tries to add two SingleVariable constraints to `z`. We should drop - # support for MOI.LessThan once variables bridges works. +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + MOI.INFEASIBLE, + tuple(), + [1.0])) +MOIT.linear8atest(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + MOI.DUAL_INFEASIBLE, + (MOI.INFEASIBILITY_CERTIFICATE, [[0.7709], [0.2291], [0.3126]]))) +MOIT.linear8btest(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + MOI.DUAL_INFEASIBLE, + (MOI.INFEASIBILITY_CERTIFICATE, [[0.5], [0.5]]))) +MOIT.linear8ctest(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[29.0909], [36.3636], [4.5455], [0.0], [0.0001]], + [-0.0, 11.3636, 0.8636])) +MOIT.linear9test(bridged, config) +# FIXME 5 <= x + y <= 10 is bridged into x + y - z == 0, 5 <= z <= 10 and +# then it tries to add two SingleVariable constraints to `z`. We should drop +# support for MOI.LessThan once variables bridges works. # MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, # [[5.0], [5.0], [5.0], [0.0]], # [-0.0, 1.0]), @@ -114,25 +113,25 @@ # [[6.0], [6.0], [10.0], [0.0]], # [-0.0, 1.0])) # MOIT.linear10test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.0], [0.0], [3.2439 0.0; 0.0 2.2439], [3.2439 0.0; 0.0 2.2439]], - [0.0, -1.0]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [1.0], [1.3765 0.0; 0.0 0.8765], [1.3765 0.0; 0.0 0.8765]], - [-1.0, 0.0])) - MOIT.linear11test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - MOI.INFEASIBLE, - tuple(), - [1.0, 3.0])) - MOIT.linear12test(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[24.0266], [27.6758 0.0; 0.0 22.6705], [27.6758 0.0; 0.0 22.6705]], - [0.0, 0.0])) - MOIT.linear13test(bridged, config) - # FIXME z >= 0.0 followed by z <= 1.0. We need to drop support for - # SingleVariable-in-LessThan but we need variable bridge otherwise, - # it creates a slack +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.0], [0.0], [3.2439 0.0; 0.0 2.2439], [3.2439 0.0; 0.0 2.2439]], + [0.0, -1.0]), + (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [1.0], [1.3765 0.0; 0.0 0.8765], [1.3765 0.0; 0.0 0.8765]], + [-1.0, 0.0])) +MOIT.linear11test(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + MOI.INFEASIBLE, + tuple(), + [1.0, 3.0])) +MOIT.linear12test(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[24.0266], [27.6758 0.0; 0.0 22.6705], [27.6758 0.0; 0.0 22.6705]], + [0.0, 0.0])) +MOIT.linear13test(bridged, config) +# FIXME z >= 0.0 followed by z <= 1.0. We need to drop support for +# SingleVariable-in-LessThan but we need variable bridge otherwise, +# it creates a slack # MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, # [[0.0], [0.5], [1.0], [0.0], [0.0]], # [2.0, 1.0]), @@ -140,4 +139,3 @@ # [[1.0], [0.0]], # [1.0])) # MOIT.linear14test(bridged, config) -end diff --git a/test/runtests.jl b/test/runtests.jl index a94698f..bd4b48e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -39,8 +39,12 @@ bridged = MOIB.full_bridge_optimizer(cached, Float64) end config = MOIT.TestConfig(atol=1e-4, rtol=1e-4) -include("unit.jl") -include("contlinear.jl") +@testset "Unit" begin + include("unit.jl") +end +@testset "MOI Continuous Linear" begin + include("contlinear.jl") +end @testset "MOI Continuous Conic" begin include("contconic.jl") end diff --git a/test/unit.jl b/test/unit.jl index 5018507..aa3fddb 100644 --- a/test/unit.jl +++ b/test/unit.jl @@ -1,66 +1,65 @@ -@testset "Unit" begin - MOIT.add_variable(bridged, config) - MOIT.add_variables(bridged, config) - MOIT.delete_variable(bridged, config) - MOIT.delete_variable(bridged, config) - MOIT.feasibility_sense(bridged, config) - MOIT.getconstraint(bridged, config) - MOIT.getvariable(bridged, config) - MOIT.max_sense(bridged, config) - MOIT.min_sense(bridged, config) - 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]), - (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]), - (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [4.47626 0; 0 2.47626]], - [1.0])) - MOIT.solve_affine_deletion_edge_cases(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[1.72037 0; 0 1.22037]], - [-0.5])) - MOIT.solve_affine_equalto(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [2.10102 0; 0 1.60102]], - [-0.5])) - MOIT.solve_affine_greaterthan(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[3.0], [0.0], [4.88931 0; 0 2.88931]], - [0.0, 1.5])) - MOIT.solve_affine_interval(MOIB.SplitInterval{Float64}(bridged), config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0], [2.06719 0; 0 1.56719]], - [0.5])) - MOIT.solve_affine_lessthan(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0]], - [0.0])) - MOIT.solve_constant_obj(bridged, config) - MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, - [[0.0]], - [0.0])) - MOIT.solve_singlevariable_obj(bridged, config) - # FIXME x >= 1.0 followed by x <= 2.0. We need to drop support for - # SingleVariable-in-LessThan but we need variable bridge otherwise, - # it creates a slack +MOIT.add_variable(bridged, config) +MOIT.add_variables(bridged, config) +MOIT.delete_variable(bridged, config) +MOIT.delete_variable(bridged, config) +MOIT.feasibility_sense(bridged, config) +MOIT.getconstraint(bridged, config) +MOIT.getvariable(bridged, config) +MOIT.max_sense(bridged, config) +MOIT.min_sense(bridged, config) +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]), + (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]), + (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [4.47626 0; 0 2.47626]], + [1.0])) +MOIT.solve_affine_deletion_edge_cases(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[1.72037 0; 0 1.22037]], + [-0.5])) +MOIT.solve_affine_equalto(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [2.10102 0; 0 1.60102]], + [-0.5])) +MOIT.solve_affine_greaterthan(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[3.0], [0.0], [4.88931 0; 0 2.88931]], + [0.0, 1.5])) +MOIT.solve_affine_interval(MOIB.SplitInterval{Float64}(bridged), config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0], [2.06719 0; 0 1.56719]], + [0.5])) +MOIT.solve_affine_lessthan(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0]], + [0.0])) +MOIT.solve_constant_obj(bridged, config) +MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, + [[0.0]], + [0.0])) +MOIT.solve_singlevariable_obj(bridged, config) +# FIXME x >= 1.0 followed by x <= 2.0. We need to drop support for +# SingleVariable-in-LessThan but we need variable bridge otherwise, +# it creates a slack # MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, # [[0.0], [1.0]], # [0.0])) # MOIT.solve_with_lowerbound(bridged, config) - # FIXME x <= 1.0 followed by x >= 0.0. We need to drop support for - # SingleVariable-in-LessThan but we need variable bridge otherwise, - # it creates a slack +# FIXME x <= 1.0 followed by x >= 0.0. We need to drop support for +# SingleVariable-in-LessThan but we need variable bridge otherwise, +# it creates a slack # MOIU.set_mock_optimize!(mock, (mock) -> MOIU.mock_optimize!(mock, # [[1.0], [0.0]], # [2.0])) # MOIT.solve_with_upperbound(bridged, config) - MOIT.variablenames(bridged, config) +MOIT.variablenames(bridged, config) end From 710137e9e762bfab97a27f3e50eb8a0e036a8eab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= <benoit.legat@gmail.com> Date: Tue, 12 Mar 2019 01:55:29 +0100 Subject: [PATCH 3/6] Remove superfluous end --- test/unit.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit.jl b/test/unit.jl index aa3fddb..4b2e762 100644 --- a/test/unit.jl +++ b/test/unit.jl @@ -62,4 +62,3 @@ MOIT.solve_singlevariable_obj(bridged, config) # [2.0])) # MOIT.solve_with_upperbound(bridged, config) MOIT.variablenames(bridged, config) -end From 0cec4660e0fd3377bd824eab151a8c1755db81e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= <benoit.legat@gmail.com> Date: Tue, 12 Mar 2019 02:30:21 +0100 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=94=A5=20Remove=20dead=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/SemidefiniteOptInterface.jl | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/SemidefiniteOptInterface.jl b/src/SemidefiniteOptInterface.jl index a9eb9c1..369d419 100644 --- a/src/SemidefiniteOptInterface.jl +++ b/src/SemidefiniteOptInterface.jl @@ -288,22 +288,6 @@ end function MOI.get(m::SOItoMOIBridge, ::MOI.ConstraintDual, ci::CI) return _getattribute(m, ci, getdual) end -function scalevec!(v, c) - d = div(isqrt(1+8length(v))-1, 2) - @assert div(d*(d+1), 2) == length(v) - i = 1 - for j in 1:d - for k in i:(i+j-2) - v[k] *= c - end - i += j - end - return v -end -function MOI.get(m::SOItoMOIBridge{T}, ::MOI.ConstraintDual, - ci::CI{<:SAF{T}, DS}) where T - return scalevec!(_getattribute(m, ci, getdual), one(T)/2) -end include("sdpa.jl") include("mock.jl") From 9c8fd10ce9589c23e259fafe715210ec510a14b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= <benoit.legat@gmail.com> Date: Tue, 12 Mar 2019 03:23:44 +0100 Subject: [PATCH 5/6] Simplify code --- src/constraint.jl | 42 +++++++++++++----------------------------- src/variable.jl | 3 +++ 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/src/constraint.jl b/src/constraint.jl index 30ec041..252a73a 100644 --- a/src/constraint.jl +++ b/src/constraint.jl @@ -14,40 +14,24 @@ function MOIU.allocate_constraint(m::SOItoMOIBridge, f::SAF, s::SupportedSets) _allocate_constraint(m::SOItoMOIBridge, f, s) end -output_index(::MOI.ScalarAffineTerm) = 1 -output_index(t::MOI.VectorAffineTerm) = t.output_index -scalar_term(t::MOI.ScalarAffineTerm) = t -scalar_term(t::MOI.VectorAffineTerm) = t.scalar_term - -_getconstant(m::SOItoMOIBridge, s::MOI.AbstractScalarSet) = MOIU.getconstant(s) -_getconstant(m::SOItoMOIBridge{T}, s::MOI.AbstractSet) where T = zero(T) - -function loadcoefficients!(m::SOItoMOIBridge, cs::UnitRange, f::SAF, s) +function loadcoefficients!(m::SOItoMOIBridge, cs::UnitRange, + f::MOI.ScalarAffineFunction, s) f = MOIU.canonical(f) # sum terms with same variables and same outputindex - if !isempty(cs) - rhs = _getconstant(m, s) .- MOI._constant(f) - for t in f.terms - st = scalar_term(t) - if !iszero(st.coefficient) - c = cs[output_index(t)] - for (blk, i, j, coef, shift) in varmap(m, st.variable_index) - if !iszero(blk) - @assert !iszero(coef) - setconstraintcoefficient!(m.sdoptimizer, st.coefficient*coef, c, blk, i, j) - end - if isa(rhs, Vector) - rhs[output_index(t)] -= st.coefficient * shift - else - rhs -= st.coefficient * shift - end + @assert length(cs) == 1 + c = first(cs) + rhs = MOIU.getconstant(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) + if !iszero(blk) + @assert !iszero(coef) + setconstraintcoefficient!(m.sdoptimizer, t.coefficient*coef, c, blk, i, j) end + rhs -= t.coefficient * shift end end - for j in 1:MOI.output_dimension(f) - c = cs[j] - setconstraintconstant!(m.sdoptimizer, rhs[j], c) - end end + setconstraintconstant!(m.sdoptimizer, rhs, c) end function MOIU.load_constraint(m::SOItoMOIBridge, ci::CI, f::SAF, s::SupportedSets) diff --git a/src/variable.jl b/src/variable.jl index 7bcb2df..f38e2de 100644 --- a/src/variable.jl +++ b/src/variable.jl @@ -84,6 +84,9 @@ 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) + _var(f::SVF, j) = f.variable _var(f::VVF, j) = f.variables[j] function MOIU.load_constraint(m::SOItoMOIBridge, ci::CI, f::VF, s::SupportedSets) From 66bde8349667bd65f3d44c640739c72763708950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= <benoit.legat@gmail.com> Date: Tue, 12 Mar 2019 03:26:21 +0100 Subject: [PATCH 6/6] Remove dead code --- src/SemidefiniteOptInterface.jl | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/SemidefiniteOptInterface.jl b/src/SemidefiniteOptInterface.jl index 369d419..c225969 100644 --- a/src/SemidefiniteOptInterface.jl +++ b/src/SemidefiniteOptInterface.jl @@ -250,21 +250,6 @@ function MOI.get(m::SOItoMOIBridge, a::MOI.ConstraintPrimal, end end -function getvardual(m::SOItoMOIBridge{T}, vi::VI) where T - Z = getZ(m.sdoptimizer) - z = zero(T) - for (blk, i, j, coef) in varmap(m, vi) - if blk != 0 - z += block(Z, blk)[i, j] * sign(coef) - end - end - return z -end -getvardual(m::SOItoMOIBridge, f::SVF) = getvardual(m, f.variable) -getvardual(m::SOItoMOIBridge, f::VVF) = map(vi -> getvardual(m, vi), f.variables) -#function MOI.get(m::SOItoMOIBridge, ::MOI.ConstraintDual, ci::CI{<:VF, S}) -# _getattribute(m, ci, getdual) + getvardual(m, MOI.get(m, MOI.ConstraintFunction(), ci)) -#end function MOI.get(m::SOItoMOIBridge, ::MOI.ConstraintDual, ci::CI{<:VF, S}) where S<:SupportedSets if ci.value < 0 return getvardual(m, -ci.value, S)