Skip to content

Commit 2359497

Browse files
authored
Merge pull request #75 from JuliaOpt/bl/moiv0.6
Updates to MOI v0.6
2 parents 778a09e + 15afd9e commit 2359497

File tree

3 files changed

+37
-73
lines changed

3 files changed

+37
-73
lines changed

REQUIRE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
julia 0.6
22
BinDeps
33
MathProgBase 0.5 0.8
4-
MathOptInterface 0.5.1 0.6
4+
MathOptInterface 0.6 0.7
55
@osx Homebrew
66
Compat 0.68

src/MOIWrapper.jl

Lines changed: 26 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct Solution
1919
end
2020
Solution() = Solution(0, Float64[], Float64[], Float64[], Float64[], NaN, NaN)
2121

22-
# Used to build the data with allocate-load during `copy!`.
22+
# Used to build the data with allocate-load during `copy_to`.
2323
# When `optimize!` is called, a the data is used to build `ECOSMatrix`
2424
# and the `ModelData` struct is discarded
2525
mutable struct ModelData
@@ -61,65 +61,36 @@ end
6161
mutable struct Optimizer <: MOI.AbstractOptimizer
6262
cone::ConeData
6363
maxsense::Bool
64-
data::Union{Nothing, ModelData} # only non-Nothing between MOI.copy! and MOI.optimize!
64+
data::Union{Nothing, ModelData} # only non-Nothing between MOI.copy_to and MOI.optimize!
6565
sol::Solution
6666
options
6767
function Optimizer(; kwargs...)
6868
new(ConeData(), false, nothing, Solution(), kwargs)
6969
end
7070
end
7171

72-
if VERSION >= v"0.7-"
73-
# TODO remove when updating to MOI v0.6
74-
Base.broadcastable(optimizer::Optimizer) = Ref(optimizer)
75-
end
76-
77-
function MOI.isempty(instance::Optimizer)
72+
function MOI.is_empty(instance::Optimizer)
7873
!instance.maxsense && instance.data === nothing
7974
end
8075

8176
function MOI.empty!(instance::Optimizer)
8277
instance.maxsense = false
83-
instance.data = nothing # It should already be nothing except if an error is thrown inside copy!
78+
instance.data = nothing # It should already be nothing except if an error is thrown inside copy_to
8479
end
8580

86-
MOIU.needsallocateload(instance::Optimizer) = true
87-
88-
function MOI.supports(optimizer::Optimizer,
89-
::Union{MOI.ConstraintFunction,
90-
MOI.ConstraintSet},
91-
::Type{<:CI})
92-
return true
93-
end
94-
function MOI.set!(optimizer::Optimizer,
95-
attr::Union{MOI.ConstraintFunction,
96-
MOI.ConstraintSet},
97-
::CI,
98-
value)
99-
throw(MOI.CannotSetAttribute(attr))
100-
end
81+
MOIU.needs_allocate_load(instance::Optimizer) = true
10182

10283
function MOI.supports(::Optimizer,
10384
::Union{MOI.ObjectiveSense,
10485
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}})
10586
return true
10687
end
107-
function MOI.set!(::Optimizer,
108-
attr::Union{MOI.ObjectiveSense,
109-
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}},
110-
value)
111-
throw(MOI.CannotSetAttribute(attr))
112-
end
113-
114-
MOI.supportsconstraint(::Optimizer, ::Type{<:SF}, ::Type{<:SS}) = true
115-
function MOI.addconstraint!(::Optimizer,
116-
func::SF,
117-
set::SS)
118-
throw(MOI.CannotAddConstraint{typeof(func), typeof(set)}())
119-
end
12088

89+
MOI.supports_constraint(::Optimizer, ::Type{<:SF}, ::Type{<:SS}) = true
12190

122-
MOI.copy!(dest::Optimizer, src::MOI.ModelLike; copynames=true) = MOIU.allocateload!(dest, src, copynames)
91+
function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike; copy_names = true)
92+
return MOIU.allocate_load(dest, src, copy_names)
93+
end
12394

12495
using Compat.SparseArrays
12596

@@ -128,33 +99,33 @@ const LPCones = Union{MOI.GreaterThan, MOI.LessThan, MOI.Nonnegatives, MOI.Nonpo
12899

129100
# Computes cone dimensions
130101
constroffset(cone::ConeData, ci::CI{<:MOI.AbstractFunction, <:ZeroCones}) = ci.value
131-
function _allocateconstraint!(cone::ConeData, f, s::ZeroCones)
102+
function _allocate_constraint(cone::ConeData, f, s::ZeroCones)
132103
ci = cone.f
133104
cone.f += MOI.dimension(s)
134105
ci
135106
end
136107
constroffset(cone::ConeData, ci::CI{<:MOI.AbstractFunction, <:LPCones}) = ci.value
137-
function _allocateconstraint!(cone::ConeData, f, s::LPCones)
108+
function _allocate_constraint(cone::ConeData, f, s::LPCones)
138109
ci = cone.l
139110
cone.l += MOI.dimension(s)
140111
ci
141112
end
142113
constroffset(cone::ConeData, ci::CI{<:MOI.AbstractFunction, <:MOI.SecondOrderCone}) = cone.l + ci.value
143-
function _allocateconstraint!(cone::ConeData, f, s::MOI.SecondOrderCone)
114+
function _allocate_constraint(cone::ConeData, f, s::MOI.SecondOrderCone)
144115
push!(cone.qa, s.dimension)
145116
ci = cone.q
146117
cone.q += MOI.dimension(s)
147118
ci
148119
end
149120
constroffset(cone::ConeData, ci::CI{<:MOI.AbstractFunction, <:MOI.ExponentialCone}) = cone.l + cone.q + ci.value
150-
function _allocateconstraint!(cone::ConeData, f, s::MOI.ExponentialCone)
121+
function _allocate_constraint(cone::ConeData, f, s::MOI.ExponentialCone)
151122
ci = 3cone.ep
152123
cone.ep += 1
153124
ci
154125
end
155126
constroffset(instance::Optimizer, ci::CI) = constroffset(instance.cone, ci::CI)
156-
function MOIU.allocateconstraint!(instance::Optimizer, f::F, s::S) where {F <: MOI.AbstractFunction, S <: MOI.AbstractSet}
157-
CI{F, S}(_allocateconstraint!(instance.cone, f, s))
127+
function MOIU.allocate_constraint(instance::Optimizer, f::F, s::S) where {F <: MOI.AbstractFunction, S <: MOI.AbstractSet}
128+
CI{F, S}(_allocate_constraint(instance.cone, f, s))
158129
end
159130

160131
# Build constraint matrix
@@ -173,8 +144,8 @@ constrrows(instance::Optimizer, ci::CI{<:MOI.AbstractVectorFunction, <:MOI.Abstr
173144
matrix(data::ModelData, s::ZeroCones) = data.b, data.IA, data.JA, data.VA
174145
matrix(data::ModelData, s::Union{LPCones, MOI.SecondOrderCone, MOI.ExponentialCone}) = data.h, data.IG, data.JG, data.VG
175146
matrix(instance::Optimizer, s) = matrix(instance.data, s)
176-
MOIU.loadconstraint!(instance::Optimizer, ci, f::MOI.SingleVariable, s) = MOIU.loadconstraint!(instance, ci, MOI.ScalarAffineFunction{Float64}(f), s)
177-
function MOIU.loadconstraint!(instance::Optimizer, ci, f::MOI.ScalarAffineFunction, s::MOI.AbstractScalarSet)
147+
MOIU.load_constraint(instance::Optimizer, ci, f::MOI.SingleVariable, s) = MOIU.load_constraint(instance, ci, MOI.ScalarAffineFunction{Float64}(f), s)
148+
function MOIU.load_constraint(instance::Optimizer, ci, f::MOI.ScalarAffineFunction, s::MOI.AbstractScalarSet)
178149
a = sparsevec(variable_index_value.(f.terms), coefficient.(f.terms))
179150
# sparsevec combines duplicates with + but does not remove zeros created so we call dropzeros!
180151
dropzeros!(a)
@@ -196,7 +167,7 @@ function MOIU.loadconstraint!(instance::Optimizer, ci, f::MOI.ScalarAffineFuncti
196167
append!(J, a.nzind)
197168
append!(V, scalecoef(row, a.nzval, true, s))
198169
end
199-
MOIU.loadconstraint!(instance::Optimizer, ci, f::MOI.VectorOfVariables, s) = MOIU.loadconstraint!(instance, ci, MOI.VectorAffineFunction{Float64}(f), s)
170+
MOIU.load_constraint(instance::Optimizer, ci, f::MOI.VectorOfVariables, s) = MOIU.load_constraint(instance, ci, MOI.VectorAffineFunction{Float64}(f), s)
200171
# SCS orders differently than MOI the second and third dimension of the exponential cone
201172
orderval(val, s) = val
202173
function orderval(val, s::Union{MOI.ExponentialCone, Type{MOI.ExponentialCone}})
@@ -207,7 +178,7 @@ expmap(i) = (1, 3, 2)[i]
207178
function orderidx(idx, s::MOI.ExponentialCone)
208179
expmap.(idx)
209180
end
210-
function MOIU.loadconstraint!(instance::Optimizer, ci, f::MOI.VectorAffineFunction, s::MOI.AbstractVectorSet)
181+
function MOIU.load_constraint(instance::Optimizer, ci, f::MOI.VectorAffineFunction, s::MOI.AbstractVectorSet)
211182
A = sparse(output_index.(f.terms), variable_index_value.(f.terms), coefficient.(f.terms))
212183
# sparse combines duplicates with + but does not remove zeros created so we call dropzeros!
213184
dropzeros!(A)
@@ -229,12 +200,12 @@ function MOIU.loadconstraint!(instance::Optimizer, ci, f::MOI.VectorAffineFuncti
229200
append!(Vs, scalecoef(I, V, true, s))
230201
end
231202

232-
function MOIU.allocatevariables!(instance::Optimizer, nvars::Integer)
203+
function MOIU.allocate_variables(instance::Optimizer, nvars::Integer)
233204
instance.cone = ConeData()
234205
VI.(1:nvars)
235206
end
236207

237-
function MOIU.loadvariables!(instance::Optimizer, nvars::Integer)
208+
function MOIU.load_variables(instance::Optimizer, nvars::Integer)
238209
cone = instance.cone
239210
m = cone.l + cone.q + 3cone.ep
240211
IA = Int[]
@@ -249,13 +220,13 @@ function MOIU.loadvariables!(instance::Optimizer, nvars::Integer)
249220
instance.data = ModelData(m, nvars, IA, JA, VA, b, IG, JG, VG, h, 0., c)
250221
end
251222

252-
function MOIU.allocate!(instance::Optimizer, ::MOI.ObjectiveSense, sense::MOI.OptimizationSense)
223+
function MOIU.allocate(instance::Optimizer, ::MOI.ObjectiveSense, sense::MOI.OptimizationSense)
253224
instance.maxsense = sense == MOI.MaxSense
254225
end
255-
function MOIU.allocate!(::Optimizer, ::MOI.ObjectiveFunction, ::MOI.ScalarAffineFunction) end
226+
function MOIU.allocate(::Optimizer, ::MOI.ObjectiveFunction, ::MOI.ScalarAffineFunction) end
256227

257-
function MOIU.load!(::Optimizer, ::MOI.ObjectiveSense, ::MOI.OptimizationSense) end
258-
function MOIU.load!(instance::Optimizer, ::MOI.ObjectiveFunction, f::MOI.ScalarAffineFunction)
228+
function MOIU.load(::Optimizer, ::MOI.ObjectiveSense, ::MOI.OptimizationSense) end
229+
function MOIU.load(instance::Optimizer, ::MOI.ObjectiveFunction, f::MOI.ScalarAffineFunction)
259230
c0 = Vector(sparsevec(variable_index_value.(f.terms), coefficient.(f.terms), instance.data.n))
260231
instance.data.objconstant = f.constant
261232
instance.data.c = instance.maxsense ? -c0 : c0
@@ -298,7 +269,6 @@ function MOI.optimize!(instance::Optimizer)
298269
end
299270

300271
# Implements getter for result value and statuses
301-
MOI.canget(instance::Optimizer, ::MOI.TerminationStatus) = true
302272
function MOI.get(instance::Optimizer, ::MOI.TerminationStatus)
303273
flag = instance.sol.ret_val
304274
if flag == ECOS.ECOS_OPTIMAL
@@ -316,14 +286,9 @@ function MOI.get(instance::Optimizer, ::MOI.TerminationStatus)
316286
end
317287
end
318288

319-
MOI.canget(instance::Optimizer, ::MOI.ObjectiveValue) = true
320289
MOI.get(instance::Optimizer, ::MOI.ObjectiveValue) = instance.sol.objval
321-
MOI.canget(instance::Optimizer, ::MOI.ObjectiveBound) = true
322290
MOI.get(instance::Optimizer, ::MOI.ObjectiveBound) = instance.sol.objbnd
323291

324-
function MOI.canget(instance::Optimizer, ::MOI.PrimalStatus)
325-
instance.sol.ret_val != ECOS.ECOS_PINF
326-
end
327292
function MOI.get(instance::Optimizer, ::MOI.PrimalStatus)
328293
flag = instance.sol.ret_val
329294
if flag == ECOS.ECOS_OPTIMAL
@@ -342,14 +307,11 @@ function MOI.get(instance::Optimizer, ::MOI.PrimalStatus)
342307
end
343308
# Swapping indices 2 <-> 3 is an involution (it is its own inverse)
344309
const reorderval = orderval
345-
function MOI.canget(instance::Optimizer, ::Union{MOI.VariablePrimal, MOI.ConstraintPrimal}, ::Type{<:MOI.Index})
346-
instance.sol.ret_val != ECOS.ECOS_PINF
347-
end
348310
function MOI.get(instance::Optimizer, ::MOI.VariablePrimal, vi::VI)
349311
instance.sol.primal[vi.value]
350312
end
351313
MOI.get(instance::Optimizer, a::MOI.VariablePrimal, vi::Vector{VI}) = MOI.get.(instance, Ref(a), vi)
352-
# setconstant: Retrieve set constant stored in `ConeData` during `copy!`
314+
# setconstant: Retrieve set constant stored in `ConeData` during `copy_to`
353315
setconstant(instance::Optimizer, offset, ::CI{<:MOI.AbstractFunction, <:MOI.EqualTo}) = instance.cone.eqsetconstant[offset]
354316
setconstant(instance::Optimizer, offset, ::CI) = instance.cone.ineqsetconstant[offset]
355317
_unshift(instance::Optimizer, offset, value, ::CI) = value
@@ -368,9 +330,6 @@ function MOI.get(instance::Optimizer, ::MOI.ConstraintPrimal, ci::CI{<:MOI.Abstr
368330
_unshift(instance, offset, scalecoef(rows, reorderval(instance.sol.slack[offset .+ rows], S), false, S), ci)
369331
end
370332

371-
function MOI.canget(instance::Optimizer, ::MOI.DualStatus)
372-
instance.sol.ret_val != ECOS.ECOS_DINF
373-
end
374333
function MOI.get(instance::Optimizer, ::MOI.DualStatus)
375334
flag = instance.sol.ret_val
376335
if flag == ECOS.ECOS_OPTIMAL
@@ -387,9 +346,6 @@ function MOI.get(instance::Optimizer, ::MOI.DualStatus)
387346
m.solve_stat = MOI.OtherResultStatus
388347
end
389348
end
390-
function MOI.canget(instance::Optimizer, ::MOI.ConstraintDual, ::Type{<:CI})
391-
instance.sol.ret_val != ECOS.ECOS_DINF
392-
end
393349
_dual(instance, ci::CI{<:MOI.AbstractFunction, <:ZeroCones}) = instance.sol.dual_eq
394350
_dual(instance, ci::CI) = instance.sol.dual_ineq
395351
function MOI.get(instance::Optimizer, ::MOI.ConstraintDual, ci::CI{<:MOI.AbstractFunction, S}) where S <: MOI.AbstractSet
@@ -398,5 +354,4 @@ function MOI.get(instance::Optimizer, ::MOI.ConstraintDual, ci::CI{<:MOI.Abstrac
398354
scalecoef(rows, reorderval(_dual(instance, ci)[offset .+ rows], S), false, S)
399355
end
400356

401-
MOI.canget(instance::Optimizer, ::MOI.ResultCount) = true
402357
MOI.get(instance::Optimizer, ::MOI.ResultCount) = 1

test/MOIWrapper.jl

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@ const MOIT = MOI.Test
44
const MOIB = MOI.Bridges
55

66
const MOIU = MOI.Utilities
7-
MOIU.@model ECOSModelData () (EqualTo, GreaterThan, LessThan) (Zeros, Nonnegatives, Nonpositives, SecondOrderCone, ExponentialCone) () (SingleVariable,) (ScalarAffineFunction,) (VectorOfVariables,) (VectorAffineFunction,)
7+
MOIU.@model(ECOSModelData,
8+
(),
9+
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan),
10+
(MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, MOI.SecondOrderCone,
11+
MOI.ExponentialCone),
12+
(),
13+
(MOI.SingleVariable,),
14+
(MOI.ScalarAffineFunction,),
15+
(MOI.VectorOfVariables,),
16+
(MOI.VectorAffineFunction,))
817
const optimizer = MOIU.CachingOptimizer(ECOSModelData{Float64}(), ECOS.Optimizer(verbose=false))
918

1019
# SOC2 requires 1e-4

0 commit comments

Comments
 (0)