Skip to content

Support of bridges with external sets/funcs #510

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Aug 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions src/Bridges/Bridges.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,16 @@ include("singlebridgeoptimizer.jl")
include("lazybridgeoptimizer.jl")

# This is used by JuMP and removes the need to update JuMP everytime a bridge is added
MOIU.@model AllBridgedConstraints () (Interval,) (SecondOrderCone, RotatedSecondOrderCone, GeometricMeanCone, LogDetConeTriangle, RootDetConeTriangle) () () (ScalarAffineFunction,) (VectorOfVariables,) (VectorAffineFunction,)
MOIU.@model(AllBridgedConstraints,
(),
(MOI.Interval,),
(MOI.SecondOrderCone, MOI.RotatedSecondOrderCone, MOI.GeometricMeanCone,
MOI.LogDetConeTriangle, MOI.RootDetConeTriangle),
(),
(),
(MOI.ScalarAffineFunction,),
(MOI.VectorOfVariables,),
(MOI.VectorAffineFunction,))
"""
fullbridgeoptimizer(model::MOI.ModelLike, ::Type{T}) where T

Expand All @@ -44,18 +53,18 @@ function fullbridgeoptimizer(model::MOI.ModelLike, ::Type{T}) where T
end

include("intervalbridge.jl")
@bridge SplitInterval SplitIntervalBridge () (Interval,) () () (SingleVariable,) (ScalarAffineFunction, ScalarQuadraticFunction) () ()
@bridge SplitInterval SplitIntervalBridge () (MOI.Interval,) () () (MOI.SingleVariable,) (MOI.ScalarAffineFunction, MOI.ScalarQuadraticFunction) () ()
include("rsocbridge.jl")
@bridge RSOC RSOCBridge () () (RotatedSecondOrderCone,) () () () (VectorOfVariables,) (VectorAffineFunction,)
@bridge RSOC RSOCBridge () () (MOI.RotatedSecondOrderCone,) () () () (MOI.VectorOfVariables,) (MOI.VectorAffineFunction,)
include("geomeanbridge.jl")
@bridge GeoMean GeoMeanBridge () () (GeometricMeanCone,) () () () (VectorOfVariables,) (VectorAffineFunction,)
@bridge GeoMean GeoMeanBridge () () (MOI.GeometricMeanCone,) () () () (MOI.VectorOfVariables,) (MOI.VectorAffineFunction,)
include("squarepsdbridge.jl")
@bridge SquarePSD SquarePSDBridge () () (PositiveSemidefiniteConeSquare,) () () () (VectorOfVariables,) (VectorAffineFunction, VectorQuadraticFunction)
@bridge SquarePSD SquarePSDBridge () () (MOI.PositiveSemidefiniteConeSquare,) () () () (MOI.VectorOfVariables,) (MOI.VectorAffineFunction, MOI.VectorQuadraticFunction)
include("detbridge.jl")
@bridge LogDet LogDetBridge () () (LogDetConeTriangle,) () () () (VectorOfVariables,) (VectorAffineFunction,)
@bridge RootDet RootDetBridge () () (RootDetConeTriangle,) () () () (VectorOfVariables,) (VectorAffineFunction,)
@bridge LogDet LogDetBridge () () (MOI.LogDetConeTriangle,) () () () (MOI.VectorOfVariables,) (MOI.VectorAffineFunction,)
@bridge RootDet RootDetBridge () () (MOI.RootDetConeTriangle,) () () () (MOI.VectorOfVariables,) (MOI.VectorAffineFunction,)
include("soctopsdbridge.jl")
@bridge SOCtoPSD SOCtoPSDBridge () () (SecondOrderCone,) () () () (VectorOfVariables,) (VectorAffineFunction,)
@bridge RSOCtoPSD RSOCtoPSDBridge () () (RotatedSecondOrderCone,) () () () (VectorOfVariables,) (VectorAffineFunction,)
@bridge SOCtoPSD SOCtoPSDBridge () () (MOI.SecondOrderCone,) () () () (MOI.VectorOfVariables,) (MOI.VectorAffineFunction,)
@bridge RSOCtoPSD RSOCtoPSDBridge () () (MOI.RotatedSecondOrderCone,) () () () (MOI.VectorOfVariables,) (MOI.VectorAffineFunction,)

end # module
7 changes: 3 additions & 4 deletions src/Bridges/singlebridgeoptimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ is_bridged(b::SingleBridgeOptimizer, ::Type{<:MOI.AbstractFunction}, ::Type{<:MO
bridge_type(b::SingleBridgeOptimizer{BT}, F::Type{<:MOI.AbstractFunction}, S::Type{<:MOI.AbstractSet}) where BT = BT

# :((Zeros, SecondOrderCone)) -> (:(MOI.Zeros), :(MOI.SecondOrderCone))
_tuple_prefix_moi(t) = MOIU._moi.(t.args)

"""
macro bridge(modelname, bridge, scalarsets, typedscalarsets, vectorsets, typedvectorsets, scalarfunctions, typedscalarfunctions, vectorfunctions, typedvectorfunctions)
Expand All @@ -39,13 +38,13 @@ will additionally support `ScalarAffineFunction`-in-`Interval`.
"""
macro bridge(modelname, bridge, ss, sst, vs, vst, sf, sft, vf, vft)
bridged_model_name = Symbol(string(modelname) * "Instance")
bridged_funs = :(Union{$(_tuple_prefix_moi(sf)...), $(_tuple_prefix_moi(sft)...), $(_tuple_prefix_moi(vf)...), $(_tuple_prefix_moi(vft)...)})
bridged_sets = :(Union{$(_tuple_prefix_moi(ss)...), $(_tuple_prefix_moi(sst)...), $(_tuple_prefix_moi(vs)...), $(_tuple_prefix_moi(vst)...)})
bridged_funs = :(Union{$((sf.args)...), $((sft.args)...), $((vf.args)...), $((vft.args)...)})
bridged_sets = :(Union{$((ss.args)...), $((sst.args)...), $((vs.args)...), $((vst.args)...)})

esc(quote
$MOIU.@model $bridged_model_name $ss $sst $vs $vst $sf $sft $vf $vft
const $modelname{T, OT<:MOI.ModelLike} = $MOIB.SingleBridgeOptimizer{$bridge{T}, $bridged_model_name{T}, OT}
is_bridged(::$modelname, ::Type{<:$bridged_funs}, ::Type{<:$bridged_sets}) = true
$MOIB.is_bridged(::$modelname, ::Type{<:$bridged_funs}, ::Type{<:$bridged_sets}) = true
supports_bridging_constraint(::$modelname, ::Type{<:$bridged_funs}, ::Type{<:$bridged_sets}) = true
end)
end
25 changes: 11 additions & 14 deletions src/Utilities/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -393,12 +393,12 @@ abstract type Constraints{F} end

abstract type SymbolFS end
struct SymbolFun <: SymbolFS
s::Symbol
s::Union{Symbol, Expr}
typed::Bool
cname::Symbol
end
struct SymbolSet <: SymbolFS
s::Symbol
s::Union{Symbol, Expr}
typed::Bool
end

Expand All @@ -409,11 +409,9 @@ end
# Expr(:., MOI, :($(QuoteNode(s)))) is Expr(:., MOI, :(:EqualTo)) <- what we want

# (MOI, :Zeros) -> :(MOI.Zeros)
_mod(m::Module, s::Symbol) = Expr(:., m, :($(QuoteNode(s))))
# (:Zeros) -> :(MOI.Zeros)
_moi(s::Symbol) = _mod(MOI, s)
_set(s::SymbolSet) = _moi(s.s)
_fun(s::SymbolFun) = _moi(s.s)
_set(s::SymbolSet) = s.s
_fun(s::SymbolFun) = s.s
function _typedset(s::SymbolSet)
if s.typed
:($(_set(s)){T})
Expand All @@ -433,7 +431,7 @@ end
if VERSION >= v"0.7.0-DEV.2813"
using Unicode
end
_field(s::SymbolFS) = Symbol(lowercase(string(s.s)))
_field(s::SymbolFS) = Symbol(replace(lowercase(string(s.s)), "." => "_"))

_getC(s::SymbolSet) = :($MOIU.C{F, $(_typedset(s))})
_getC(s::SymbolFun) = _typedfun(s)
Expand Down Expand Up @@ -578,15 +576,14 @@ macro model(modelname, ss, sst, vs, vst, sf, sft, vf, vft)
end
end

for (func, T) in ((:_add_constraint, CI), (:_modify, CI), (:_delete, CI), (:_getindex, CI), (:_getfunction, CI), (:_getset, CI), (:_getnoc, MOI.NumberOfConstraints))
funct = _mod(MOIU, func)
for (funct, T) in ((:_add_constraint, CI), (:_modify, CI), (:_delete, CI), (:_getindex, CI), (:_getfunction, CI), (:_getset, CI), (:_getnoc, MOI.NumberOfConstraints))
for (c, sets) in ((scname, scalarsets), (vcname, vectorsets))
for s in sets
set = _set(s)
field = _field(s)
code = quote
$code
$funct(model::$c, ci::$T{F, <:$set}, args...) where F = $funct(model.$field, ci, args...)
$MOIU.$funct(model::$c, ci::$T{F, <:$set}, args...) where F = $MOIU.$funct(model.$field, ci, args...)
end
end
end
Expand All @@ -596,12 +593,12 @@ macro model(modelname, ss, sst, vs, vst, sf, sft, vf, vft)
field = _field(f)
code = quote
$code
$funct(model::$modelname, ci::$T{<:$fun}, args...) = $funct(model.$field, ci, args...)
$MOIU.$funct(model::$modelname, ci::$T{<:$fun}, args...) = $MOIU.$funct(model.$field, ci, args...)
end
end
end

return esc(quote
code = quote
$scalarconstraints
function $scname{T, F}() where {T, F}
$scname{T, F}($(_getCV.(scalarsets)...))
Expand All @@ -624,6 +621,6 @@ macro model(modelname, ss, sst, vs, vst, sf, sft, vf, vft)
$MOI.supports_constraint(model::$modelname{T}, ::Type{<:Union{$(_typedfun.(vectorfuns)...)}}, ::Type{<:Union{$(_typedset.(vectorsets)...)}}) where T = true

$code

end)
end
return esc(code)
end
23 changes: 21 additions & 2 deletions test/bridge.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Model not supporting Interval
MOIU.@model SimpleModel () (EqualTo, GreaterThan, LessThan) (Zeros, Nonnegatives, Nonpositives, SecondOrderCone, RotatedSecondOrderCone, GeometricMeanCone, PositiveSemidefiniteConeTriangle, ExponentialCone) () (SingleVariable,) (ScalarAffineFunction, ScalarQuadraticFunction) (VectorOfVariables,) (VectorAffineFunction,)
MOIU.@model(SimpleModel,
(),
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan),
(MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, MOI.SecondOrderCone,
MOI.RotatedSecondOrderCone, MOI.GeometricMeanCone,
MOI.PositiveSemidefiniteConeTriangle, MOI.ExponentialCone),
(),
(MOI.SingleVariable,),
(MOI.ScalarAffineFunction, MOI.ScalarQuadraticFunction),
(MOI.VectorOfVariables,),
(MOI.VectorAffineFunction,))

function test_noc(bridgedmock, F, S, n)
@test MOI.get(bridgedmock, MOI.NumberOfConstraints{F, S}()) == n
Expand Down Expand Up @@ -109,7 +119,16 @@ end
end

# Model not supporting RotatedSecondOrderCone
MOIU.@model NoRSOCModel () (EqualTo, GreaterThan, LessThan, Interval) (Zeros, Nonnegatives, Nonpositives, SecondOrderCone, ExponentialCone, PositiveSemidefiniteConeTriangle) () (SingleVariable,) (ScalarAffineFunction,) (VectorOfVariables,) (VectorAffineFunction,)
MOIU.@model(NoRSOCModel,
(),
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval),
(MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, MOI.SecondOrderCone,
MOI.ExponentialCone, MOI.PositiveSemidefiniteConeTriangle),
(),
(MOI.SingleVariable,),
(MOI.ScalarAffineFunction,),
(MOI.VectorOfVariables,),
(MOI.VectorAffineFunction,))

@testset "LazyBridgeOptimizer" begin
mock = MOIU.MockOptimizer(NoRSOCModel{Float64}())
Expand Down
2 changes: 1 addition & 1 deletion test/cachingoptimizer.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@MOIU.model ModelForCachingOptimizer (ZeroOne, Integer) (EqualTo, GreaterThan, LessThan, Interval) (Zeros, Nonnegatives, Nonpositives, SecondOrderCone, RotatedSecondOrderCone, GeometricMeanCone, ExponentialCone, DualExponentialCone, PositiveSemidefiniteConeTriangle, RootDetConeTriangle, LogDetConeTriangle) () (SingleVariable,) (ScalarAffineFunction,ScalarQuadraticFunction) (VectorOfVariables,) (VectorAffineFunction,)
@MOIU.model ModelForCachingOptimizer (MOI.ZeroOne, MOI.Integer) (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval) (MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, MOI.SecondOrderCone, MOI.RotatedSecondOrderCone, MOI.GeometricMeanCone, MOI.ExponentialCone, MOI.DualExponentialCone, MOI.PositiveSemidefiniteConeTriangle, MOI.RootDetConeTriangle, MOI.LogDetConeTriangle) () (MOI.SingleVariable,) (MOI.ScalarAffineFunction, MOI.ScalarQuadraticFunction) (MOI.VectorOfVariables,) (MOI.VectorAffineFunction,)

@testset "CachingOptimizer Manual mode" begin
m = MOIU.CachingOptimizer(ModelForCachingOptimizer{Float64}(), MOIU.Manual)
Expand Down
10 changes: 9 additions & 1 deletion test/model.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
MOIU.@model LPModel () (EqualTo, GreaterThan, LessThan, Interval) (Zeros, Nonnegatives, Nonpositives) () (SingleVariable,) (ScalarAffineFunction,) (VectorOfVariables,) (VectorAffineFunction,)
MOIU.@model(LPModel,
(),
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval),
(MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives),
(),
(MOI.SingleVariable,),
(MOI.ScalarAffineFunction,),
(MOI.VectorOfVariables,),
(MOI.VectorAffineFunction,))

@testset "Name test" begin
MOIT.nametest(Model{Float64}())
Expand Down
2 changes: 1 addition & 1 deletion test/parser.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ end
@test MOIU.separatelabel(:(con1: [x,y] in S)) == (:con1, :([x,y] in S))
end

@MOIU.model GeneralModel (ZeroOne, Integer) (EqualTo, GreaterThan, LessThan, Interval) (Zeros, Nonnegatives, Nonpositives, SecondOrderCone, RotatedSecondOrderCone, PositiveSemidefiniteConeTriangle) () (SingleVariable,) (ScalarAffineFunction,ScalarQuadraticFunction) (VectorOfVariables,) (VectorAffineFunction,)
@MOIU.model GeneralModel (MOI.ZeroOne, MOI.Integer) (MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval) (MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, MOI.SecondOrderCone, MOI.RotatedSecondOrderCone, MOI.PositiveSemidefiniteConeTriangle) () (MOI.SingleVariable,) (MOI.ScalarAffineFunction, MOI.ScalarQuadraticFunction) (MOI.VectorOfVariables,) (MOI.VectorAffineFunction,)

@testset "loadfromstring" begin
@testset "one variable" begin
Expand Down
32 changes: 23 additions & 9 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,30 @@ end
# Needed by test spread over several files, defining it here make it easier to comment out tests
# Model supporting every MOI functions and sets
MOIU.@model(Model,
(ZeroOne, Integer),
(EqualTo, GreaterThan, LessThan, Interval, Semicontinuous, Semiinteger),
(Reals, Zeros, Nonnegatives, Nonpositives, SecondOrderCone, RotatedSecondOrderCone, GeometricMeanCone, ExponentialCone, DualExponentialCone, PositiveSemidefiniteConeTriangle, PositiveSemidefiniteConeSquare, RootDetConeTriangle, RootDetConeSquare, LogDetConeTriangle, LogDetConeSquare),
(PowerCone, DualPowerCone, SOS1, SOS2),
(SingleVariable,),
(ScalarAffineFunction, ScalarQuadraticFunction),
(VectorOfVariables,),
(VectorAffineFunction, VectorQuadraticFunction))
(MOI.ZeroOne, MOI.Integer),
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval,
MOI.Semicontinuous, MOI.Semiinteger),
(MOI.Reals, MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives,
MOI.SecondOrderCone, MOI.RotatedSecondOrderCone,
MOI.GeometricMeanCone, MOI.ExponentialCone, MOI.DualExponentialCone,
MOI.PositiveSemidefiniteConeTriangle, MOI.PositiveSemidefiniteConeSquare,
MOI.RootDetConeTriangle, MOI.RootDetConeSquare, MOI.LogDetConeTriangle,
MOI.LogDetConeSquare),
(MOI.PowerCone, MOI.DualPowerCone, MOI.SOS1, MOI.SOS2),
(MOI.SingleVariable,),
(MOI.ScalarAffineFunction, MOI.ScalarQuadraticFunction),
(MOI.VectorOfVariables,),
(MOI.VectorAffineFunction, MOI.VectorQuadraticFunction))

# Model supporting only SecondOrderCone as non-LP cone.
@MOIU.model ModelForMock (ZeroOne, Integer) (EqualTo, GreaterThan, LessThan, Interval) (Zeros, Nonnegatives, Nonpositives, SecondOrderCone) () (SingleVariable,) (ScalarAffineFunction, ScalarQuadraticFunction) (VectorOfVariables,) (VectorAffineFunction,)
MOIU.@model(ModelForMock, (MOI.ZeroOne, MOI.Integer),
(MOI.EqualTo, MOI.GreaterThan, MOI.LessThan, MOI.Interval),
(MOI.Zeros, MOI.Nonnegatives, MOI.Nonpositives, MOI.SecondOrderCone),
(),
(MOI.SingleVariable,),
(MOI.ScalarAffineFunction, MOI.ScalarQuadraticFunction),
(MOI.VectorOfVariables,),
(MOI.VectorAffineFunction,))

# Utilities submodule tests
@testset "MOI.Utilities" begin
Expand Down
10 changes: 9 additions & 1 deletion test/universalfallback.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,15 @@ struct UnknownOptimizerAttribute <: MOI.AbstractOptimizerAttribute end

# A few constraint types are supported to test both the fallback and the
# delegation to the internal model
@MOIU.model ModelForUniversalFallback () (LessThan,) () () (SingleVariable,) (ScalarAffineFunction,) () ()
@MOIU.model(ModelForUniversalFallback,
(),
(MOI.LessThan,),
(),
(),
(MOI.SingleVariable,),
(MOI.ScalarAffineFunction,),
(),
())

@testset "UniversalFallback" begin
model = ModelForUniversalFallback{Float64}()
Expand Down