From 60b23c5ad5687ecbda2add241cd42e69e4d99b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 15 Jul 2021 23:44:19 -0400 Subject: [PATCH 1/9] Fix StackOverflow with self-loop bridges --- src/Bridges/Constraint/set_map.jl | 10 ++ .../Constraint/single_bridge_optimizer.jl | 2 + .../Variable/single_bridge_optimizer.jl | 2 + src/Bridges/bridge_optimizer.jl | 28 +++- src/Bridges/lazy_bridge_optimizer.jl | 2 + test/Bridges/bridge_optimizer.jl | 41 ++++++ test/Bridges/identity_bridge.jl | 120 ++++++++++++++++++ 7 files changed, 200 insertions(+), 5 deletions(-) create mode 100644 test/Bridges/identity_bridge.jl diff --git a/src/Bridges/Constraint/set_map.jl b/src/Bridges/Constraint/set_map.jl index a9720c1c55..2240be3d6e 100644 --- a/src/Bridges/Constraint/set_map.jl +++ b/src/Bridges/Constraint/set_map.jl @@ -92,6 +92,16 @@ function MOI.get( return MOIU.convert_approx(G, func) end +function MOI.set( + model::MOI.ModelLike, + attr::MOI.ConstraintFunction, + bridge::SetMapBridge{T,S2,S1,F,G}, + func::G, +) where {T,S2,S1,F,G} + MOI.set(model, attr, bridge.constraint, map_function(typeof(bridge), func)) + return +end + function MOI.get( model::MOI.ModelLike, attr::MOI.ConstraintSet, diff --git a/src/Bridges/Constraint/single_bridge_optimizer.jl b/src/Bridges/Constraint/single_bridge_optimizer.jl index 48b1987e1e..caa76d8612 100644 --- a/src/Bridges/Constraint/single_bridge_optimizer.jl +++ b/src/Bridges/Constraint/single_bridge_optimizer.jl @@ -103,3 +103,5 @@ function MOIB.bridge_type( end MOIB.bridging_cost(::SingleBridgeOptimizer, args...) = 1.0 + +MOIB.recursive_model(b::SingleBridgeOptimizer) = b.model diff --git a/src/Bridges/Variable/single_bridge_optimizer.jl b/src/Bridges/Variable/single_bridge_optimizer.jl index 01b3bd35f6..9f216ee055 100644 --- a/src/Bridges/Variable/single_bridge_optimizer.jl +++ b/src/Bridges/Variable/single_bridge_optimizer.jl @@ -82,3 +82,5 @@ function MOIB.bridge_type( end MOIB.bridging_cost(::SingleBridgeOptimizer, args...) = 1.0 + +MOIB.recursive_model(b::SingleBridgeOptimizer) = b.model diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index 11e5c0e7ed..c05c1d8099 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -15,6 +15,8 @@ abstract type AbstractBridgeOptimizer <: MOI.AbstractOptimizer end # AbstractBridgeOptimizer interface +function recursive_model end + function supports_constraint_bridges end """ @@ -1128,7 +1130,11 @@ function MOI.get( if is_variable_bridged(b, ci) return Variable.function_for(Variable.bridges(b), ci) else - func = call_in_context(b, ci, br -> MOI.get(b, attr, br)) + func = call_in_context( + b, + ci, + br -> MOI.get(recursive_model(b), attr, br), + ) return unbridged_constraint_function(b, func) end else @@ -1180,7 +1186,11 @@ function MOI.get( ) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - set = call_in_context(b, ci, bridge -> MOI.get(b, attr, bridge)) + set = call_in_context( + b, + ci, + bridge -> MOI.get(recursive_model(b), attr, bridge), + ) else set = MOI.get(b.model, attr, ci) end @@ -1209,7 +1219,11 @@ function MOI.get( ) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - func = call_in_context(b, ci, bridge -> MOI.get(b, attr, bridge)) + func = call_in_context( + b, + ci, + bridge -> MOI.get(recursive_model(b), attr, bridge), + ) else func = MOI.get(b.model, attr, ci) end @@ -1242,7 +1256,11 @@ function _set_substituted( ) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - call_in_context(b, ci, bridge -> MOI.set(b, attr, bridge, value)) + call_in_context( + b, + ci, + bridge -> MOI.set(recursive_model(b), attr, bridge, value), + ) else MOI.set(b.model, attr, ci, value) end @@ -1424,7 +1442,7 @@ function MOI.supports_constraint( end function add_bridged_constraint(b, BridgeType, f, s) - bridge = Constraint.bridge_constraint(BridgeType, b, f, s) + bridge = Constraint.bridge_constraint(BridgeType, recursive_model(b), f, s) ci = Constraint.add_key_for_bridge(Constraint.bridges(b), bridge, f, s) Variable.register_context(Variable.bridges(b), ci) return ci diff --git a/src/Bridges/lazy_bridge_optimizer.jl b/src/Bridges/lazy_bridge_optimizer.jl index 2b594d0750..675da1a611 100644 --- a/src/Bridges/lazy_bridge_optimizer.jl +++ b/src/Bridges/lazy_bridge_optimizer.jl @@ -513,6 +513,8 @@ function bridging_cost(b::LazyBridgeOptimizer, args...) return bridging_cost(b.graph, node(b, args...)) end +MOIB.recursive_model(b::SingleBridgeOptimizer) = b + function MOI.compute_conflict!(model::LazyBridgeOptimizer) return MOI.compute_conflict!(model.model) end diff --git a/test/Bridges/bridge_optimizer.jl b/test/Bridges/bridge_optimizer.jl index b2c6875875..a42d85b330 100644 --- a/test/Bridges/bridge_optimizer.jl +++ b/test/Bridges/bridge_optimizer.jl @@ -19,6 +19,47 @@ end include("utilities.jl") +include("identity_bridge.jl") + +function test_recursive_model_variable(::Type{T}) where {T} + model = MOIU.UniversalFallback(MOIU.Model{T}()) + b = MOIB.Variable.SingleBridgeOptimizer{IdentityBridges.VariableBridge{T}}( + model, + ) + x, cx = MOI.add_constrained_variable(b, MOI.EqualTo(one(T))) + @test MOIB.is_bridged(b, x) + @test MOIB.is_bridged(b, cx) +end + +test_recursive_model_variable(Int) + +function test_recursive_model_constraint(::Type{T}) where {T} + model = MOIU.UniversalFallback(MOIU.Model{T}()) + b = MOIB.Constraint.SingleBridgeOptimizer{ + IdentityBridges.ConstraintBridge{T}, + }( + model, + ) + x = MOI.add_variable(b) + fx = MOI.SingleVariable(x) + func = one(T) * fx + set = MOI.EqualTo(zero(T)) + c = MOI.add_constraint(b, func, set) + @test MOIB.is_bridged(b, c) + @test MOI.get(b, MOI.ConstraintFunction(), c) ≈ func + new_func = T(2) * fx + MOI.set(b, MOI.ConstraintFunction(), c, new_func) + @test MOI.get(b, MOI.ConstraintFunction(), c) == new_func + @test MOI.get(b, MOI.ConstraintSet(), c) == set + new_set = MOI.EqualTo(one(T)) + MOI.set(b, MOI.ConstraintSet(), c, new_set) + @test MOI.get(b, MOI.ConstraintSet(), c) == new_set + MOI.set(b, MOI.ConstraintDualStart(), c, one(T)) + @test MOI.get(b, MOI.ConstraintDualStart(), c) == one(T) +end + +test_recursive_model_constraint(Int) + struct DummyModelAttribute <: MOI.AbstractModelAttribute end struct DummyEvaluator <: MOI.AbstractNLPEvaluator end struct DummyVariableAttribute <: MOI.AbstractVariableAttribute end diff --git a/test/Bridges/identity_bridge.jl b/test/Bridges/identity_bridge.jl new file mode 100644 index 0000000000..aeb13d0044 --- /dev/null +++ b/test/Bridges/identity_bridge.jl @@ -0,0 +1,120 @@ +# Dummy bridges used for testing +module IdentityBridges + +import MathOptInterface +const MOI = MathOptInterface +const MOIB = MOI.Bridges +const MOIBV = MOIB.Variable +const MOIBC = MOIB.Constraint + +const F{T} = MOI.ScalarAffineFunction{T} +const S{T} = MOI.EqualTo{T} + +struct VariableBridge{T} <: MOIBV.AbstractBridge + variables::Vector{MOI.VariableIndex} + constraint::MOI.ConstraintIndex{MOI.SingleVariable,S{T}} +end + +function MOIBV.bridge_constrained_variable( + ::Type{VariableBridge{T}}, + model::MOI.ModelLike, + set::S{T}, +) where {T} + variable, constraint = MOI.add_constrained_variable(model, set) + return VariableBridge{T}(variable, constraint) +end + +function MOIBV.supports_constrained_variable( + ::Type{VariableBridge{T}}, + ::Type{S{T}}, +) where {T} + return true +end + +function MOIB.added_constrained_variable_types( + ::Type{VariableBridge{T}}, +) where {T} + return [(S{T},)] +end + +function MOIB.added_constraint_types(::Type{<:VariableBridge}) + return Tuple{DataType,DataType}[] +end + +# Attributes, Bridge acting as a model +MOI.get(bridge::VariableBridge, ::MOI.NumberOfVariables) = 1 +MOI.get(bridge::VariableBridge, ::MOI.ListOfVariableIndices) = [bridge.variable] + +function MOI.get( + bridge::VariableBridge, + ::MOI.NumberOfConstraints{MOI.VectorOfVariables,MOI.RotatedSecondOrderCone}, +) + return 1 +end + +function MOI.get( + bridge::VariableBridge, + ::MOI.ListOfConstraintIndices{ + MOI.VectorOfVariables, + MOI.RotatedSecondOrderCone, + }, +) + return [bridge.constraint] +end + +# References +function MOI.delete(model::MOI.ModelLike, bridge::VariableBridge) + MOI.delete(model, bridge.variable) + return +end + +# Attributes, Bridge acting as a constraint + +function MOI.get( + model::MOI.ModelLike, + attr::MOI.ConstraintSet, + bridge::VariableBridge{T}, +) where {T} + return MOI.get(model, attr, bridge.constraint) +end + +function MOI.get( + model::MOI.ModelLike, + attr::Union{MOI.ConstraintPrimal,MOI.ConstraintDual}, + bridge::VariableBridge, +) + return MOI.get(model, attr, bridge.constraint) +end + +function MOI.get( + model::MOI.ModelLike, + attr::MOI.VariablePrimal, + bridge::VariableBridge, +) + return MOI.get(model, attr, bridge.variable) +end + +function MOIB.bridged_function(bridge::VariableBridge{T}) where {T} + return MOI.SingleVariable(bridge.variable) +end + +function unbridged_map( + bridge::VariableBridge{T}, + vi::MOI.VariableIndex, +) where {T} + func = convert(F{T}, MOI.SingleVariable(vi)) + return (bridge.variable => func,) +end + +struct ConstraintBridge{T} <: MOIBC.SetMapBridge{T,S{T},S{T},F{T},F{T}} + constraint::MOI.ConstraintIndex{F{T},S{T}} +end + +MOIBC.map_set(::Type{<:ConstraintBridge}, set::S) = set +MOIBC.inverse_map_set(::Type{<:ConstraintBridge}, set::S) = set +MOIBC.map_function(::Type{<:ConstraintBridge}, func) = func +MOIBC.inverse_map_function(::Type{<:ConstraintBridge}, func) = func +MOIBC.adjoint_map_function(::Type{<:ConstraintBridge}, func) = func +MOIBC.inverse_adjoint_map_function(::Type{<:ConstraintBridge}, func) = func + +end From d26446a69844411919362adf9676ea7b77dc56ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sun, 18 Jul 2021 23:02:34 -0400 Subject: [PATCH 2/9] Fixes and add Objective --- src/Bridges/Constraint/set_map.jl | 30 +++- .../Objective/single_bridge_optimizer.jl | 2 + src/Bridges/Variable/set_map.jl | 43 +++++- src/Bridges/bridge_optimizer.jl | 109 +++++++-------- src/Bridges/lazy_bridge_optimizer.jl | 2 +- test/Bridges/bridge_optimizer.jl | 105 ++++++++------ test/Bridges/identity_bridge.jl | 128 +++++++----------- 7 files changed, 235 insertions(+), 184 deletions(-) diff --git a/src/Bridges/Constraint/set_map.jl b/src/Bridges/Constraint/set_map.jl index 2240be3d6e..29cfe88fc2 100644 --- a/src/Bridges/Constraint/set_map.jl +++ b/src/Bridges/Constraint/set_map.jl @@ -98,7 +98,7 @@ function MOI.set( bridge::SetMapBridge{T,S2,S1,F,G}, func::G, ) where {T,S2,S1,F,G} - MOI.set(model, attr, bridge.constraint, map_function(typeof(bridge), func)) + MOI.set(model, attr, bridge.constraint, MOIB.map_function(typeof(bridge), func)) return end @@ -174,14 +174,34 @@ function MOI.set( return end +# By linearity of the map, we can just change the constant/coefficient +function _map_change(::Type{BT}, change::MOI.ScalarConstantChange) where {BT} + constant = MOIB.map_function(BT, change.new_constant) + return MOI.ScalarConstantChange(constant) +end +function _map_change(::Type{BT}, change::MOI.VectorConstantChange) where {BT} + constant = MOIB.map_function(BT, change.new_constant) + return MOI.VectorConstantChange(constant) +end +function _map_change(::Type{BT}, change::MOI.ScalarCoefficientChange) where {BT} + coefficient = MOIB.map_function(BT, change.new_coefficient) + return MOI.ScalarCoefficientChange(change.variable, coefficient) +end +function _map_change(::Type{BT}, change::MOI.MultirowChange) where {BT} + # It is important here that `change.new_coefficients` contains + # the complete new sparse column associated to the variable. + # Calling modify twice with part of the column won't work since + # the linear map might reset all the column each time. + coefficients = MOIB.map_function(BT, change.new_coefficients) + return MOI.MultirowChange(change.variable, coefficients) +end + function MOI.modify( model::MOI.ModelLike, bridge::SetMapBridge, - change::MOI.VectorConstantChange, + change::MOI.AbstractFunctionModification, ) - # By linearity of the map, we can just change the constant - constant = MOIB.map_function(typeof(bridge), change.new_constant) - MOI.modify(model, bridge.constraint, MOI.VectorConstantChange(constant)) + MOI.modify(model, bridge.constraint, _map_change(typeof(bridge), change)) return end diff --git a/src/Bridges/Objective/single_bridge_optimizer.jl b/src/Bridges/Objective/single_bridge_optimizer.jl index 048c220192..c553585590 100644 --- a/src/Bridges/Objective/single_bridge_optimizer.jl +++ b/src/Bridges/Objective/single_bridge_optimizer.jl @@ -70,3 +70,5 @@ function MOIB.bridge_type( ) where {BT} return BT end + +MOIB.recursive_model(b::SingleBridgeOptimizer) = b.model diff --git a/src/Bridges/Variable/set_map.jl b/src/Bridges/Variable/set_map.jl index 86bc8e6b18..917597cae1 100644 --- a/src/Bridges/Variable/set_map.jl +++ b/src/Bridges/Variable/set_map.jl @@ -23,13 +23,21 @@ bridge. """ abstract type SetMapBridge{T,S1,S2} <: AbstractBridge end +function _add_constrained_var(model, set::MOI.AbstractScalarSet) + return MOI.add_constrained_variable(model, set) +end + +function _add_constrained_var(model, set::MOI.AbstractVectorSet) + return MOI.add_constrained_variables(model, set) +end + function bridge_constrained_variable( BT::Type{<:SetMapBridge{T,S1,S2}}, model::MOI.ModelLike, set::S2, ) where {T,S1,S2} variables, constraint = - MOI.add_constrained_variables(model, MOIB.inverse_map_set(BT, set)) + _add_constrained_var(model, MOIB.inverse_map_set(BT, set)) return BT(variables, constraint) end @@ -88,7 +96,17 @@ function MOI.get( end # References -function MOI.delete(model::MOI.ModelLike, bridge::SetMapBridge) +function MOI.delete( + model::MOI.ModelLike, + bridge::SetMapBridge{T,S1,S2}, +) where {T,S1,S2<:MOI.AbstractScalarSet} + MOI.delete(model, bridge.variable) + return +end +function MOI.delete( + model::MOI.ModelLike, + bridge::SetMapBridge{T,S1,S2}, +) where {T,S1,S2<:MOI.AbstractVectorSet} MOI.delete(model, bridge.variables) return end @@ -104,6 +122,17 @@ function MOI.get( return MOIB.map_set(typeof(bridge), set) end +function MOI.set( + model::MOI.ModelLike, + attr::MOI.ConstraintSet, + bridge::SetMapBridge{T,S1}, + set::S1, +) where {T,S1} + mapped = MOIB.inverse_map_set(typeof(bridge), set) + MOI.set(model, attr, bridge.constraint, mapped) + return +end + function MOI.get( model::MOI.ModelLike, attr::MOI.ConstraintPrimal, @@ -164,6 +193,16 @@ function MOIB.bridged_function( return convert(MOI.ScalarAffineFunction{T}, func) end +function unbridged_map( + bridge::SetMapBridge{T}, + vi::MOI.VariableIndex, +) where {T} + F = MOI.ScalarAffineFunction{T} + func = MOI.SingleVariable(vi) + mapped = MOIB.inverse_map_function(typeof(bridge), func) + return Pair{MOI.VariableIndex,F}[bridge.variable => mapped] +end + function unbridged_map( bridge::SetMapBridge{T}, vis::Vector{MOI.VariableIndex}, diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index c05c1d8099..4a568a24c4 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -295,6 +295,33 @@ function call_in_context( end end +function call_in_context( + f::F, + b::AbstractBridgeOptimizer, + index::MOI.Index, + attr::MOI.AnyAttribute, + args::Vararg{Any,N}, +) where {F<:Union{typeof(MOI.get),typeof(MOI.set)},N} + return call_in_context( + b, + index, + bridge -> f(recursive_model(b), attr, bridge, args...), + ) +end + +function call_in_context( + f::F, + b::AbstractBridgeOptimizer, + index::MOI.Index, + args::Vararg{Any,N}, +) where {F<:Function,N} + return call_in_context( + b, + index, + bridge -> f(recursive_model(b), bridge, args...), + ) +end + function _functionize_bridge(b::AbstractBridgeOptimizer, bridge_type) func, name = _func_name(bridge_type) return error( @@ -453,11 +480,7 @@ function _delete_variables_in_vector_of_variables_constraint( i = findfirst(isequal(vi), variables) if i !== nothing if MOI.supports_dimension_update(S) - call_in_context( - b, - ci, - bridge -> MOI.delete(b, bridge, IndexInVector(i)), - ) + call_in_context(MOI.delete, b, ci, IndexInVector(i)) else MOIU.throw_delete_variable_in_vov(vi) end @@ -506,7 +529,7 @@ function MOI.delete(b::AbstractBridgeOptimizer, vis::Vector{MOI.VariableIndex}) end if all(vi -> is_bridged(b, vi), vis) && Variable.has_keys(Variable.bridges(b), vis) - call_in_context(b, first(vis), bridge -> MOI.delete(b, bridge)) + call_in_context(MOI.delete, b, first(vis)) b.name_to_var = nothing for vi in vis delete!(b.var_to_name, vi) @@ -535,16 +558,12 @@ function MOI.delete(b::AbstractBridgeOptimizer, vi::MOI.VariableIndex) if MOI.supports_dimension_update( Variable.constrained_set(Variable.bridges(b), vi), ) - call_in_context( - b, - vi, - bridge -> MOI.delete(b, bridge, _index(b, vi)...), - ) + call_in_context(MOI.delete, b, vi, _index(b, vi)...) else MOIU.throw_delete_variable_in_vov(vi) end else - call_in_context(b, vi, bridge -> MOI.delete(b, bridge)) + call_in_context(MOI.delete, b, vi) ci = Variable.constraint(Variable.bridges(b), vi) b.name_to_con = nothing delete!(b.con_to_name, ci) @@ -560,7 +579,7 @@ end function MOI.delete(b::AbstractBridgeOptimizer, ci::MOI.ConstraintIndex) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - br = bridge(b, ci) + bridge = Constraint.bridges(b)[ci] if is_variable_bridged(b, ci) error( "Cannot delete constraint index of bridged constrained", @@ -573,7 +592,7 @@ function MOI.delete(b::AbstractBridgeOptimizer, ci::MOI.ConstraintIndex) Variable.call_in_context( Variable.bridges(b), ci, - () -> MOI.delete(b, br), + () -> MOI.delete(recursive_model(b), bridge), ) b.name_to_con = nothing delete!(b.con_to_name, ci) @@ -907,7 +926,7 @@ function MOI.get( ) where {F} obj_attr = MOI.ObjectiveFunction{F}() if is_bridged(b, obj_attr) - return MOI.get(b, attr, bridge(b, obj_attr)) + return MOI.get(recursive_model(b), attr, bridge(b, obj_attr)) else return MOI.get(b.model, MOI.ObjectiveValue(attr.result_index)) end @@ -936,7 +955,7 @@ end function MOI.get(b::AbstractBridgeOptimizer, attr::MOI.ObjectiveFunction) value = if is_bridged(b, attr) - MOI.get(b, attr, bridge(b, attr)) + MOI.get(recursive_model(b), attr, bridge(b, attr)) else MOI.get(b.model, attr) end @@ -954,7 +973,7 @@ function MOI.set( _delete_objective_bridges(b) else for bridge in values(Objective.bridges(b)) - MOI.set(b, attr, bridge, value) + MOI.set(recursive_model(b), attr, bridge, value) end end end @@ -962,7 +981,7 @@ function MOI.set( end function _bridge_objective(b, BridgeType, func) - bridge = Objective.bridge_objective(BridgeType, b, func) + bridge = Objective.bridge_objective(BridgeType, recursive_model(b), func) Objective.add_key_for_bridge(Objective.bridges(b), bridge, func) return end @@ -1015,7 +1034,7 @@ function MOI.modify( if is_bridged(b, change) modify_bridged_change(b, obj, change) elseif is_bridged(b, obj) - MOI.modify(b, bridge(b, obj), change) + MOI.modify(recursive_model(b), bridge(b, obj), change) else MOI.modify(b.model, obj, change) end @@ -1038,11 +1057,7 @@ function MOI.get( index::MOI.VariableIndex, ) if is_bridged(b, index) - value = call_in_context( - b, - index, - bridge -> MOI.get(b, attr, bridge, _index(b, index)...), - ) + value = call_in_context(MOI.get, b, index, attr, _index(b, index)...) else value = MOI.get(b.model, attr, index) end @@ -1077,11 +1092,7 @@ function MOI.set( ) value = bridged_function(b, value) if is_bridged(b, index) - call_in_context( - b, - index, - bridge -> MOI.set(b, attr, bridge, value, _index(b, index)...), - ) + call_in_context(MOI.set, b, index, attr, value, _index(b, index)...) else MOI.set(b.model, attr, index, value) end @@ -1130,11 +1141,7 @@ function MOI.get( if is_variable_bridged(b, ci) return Variable.function_for(Variable.bridges(b), ci) else - func = call_in_context( - b, - ci, - br -> MOI.get(recursive_model(b), attr, br), - ) + func = call_in_context(MOI.get, b, ci, attr) return unbridged_constraint_function(b, func) end else @@ -1159,7 +1166,7 @@ function MOI.get( ) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - return call_in_context(b, ci, bridge -> MOI.get(b, attr, bridge)) + return call_in_context(MOI.get, b, ci, attr) else return MOI.get(b.model, attr, ci) end @@ -1186,11 +1193,7 @@ function MOI.get( ) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - set = call_in_context( - b, - ci, - bridge -> MOI.get(recursive_model(b), attr, bridge), - ) + set = call_in_context(MOI.get, b, ci, attr) else set = MOI.get(b.model, attr, ci) end @@ -1198,11 +1201,7 @@ function MOI.get( # The function constant of the bridged function was moved to the set, # we need to remove it. if is_bridged(b, ci) - func = call_in_context( - b, - ci, - bridge -> MOI.get(b, MOI.ConstraintFunction(), bridge), - ) + func = call_in_context(MOI.get, b, ci, MOI.ConstraintFunction()) else func = MOI.get(b.model, MOI.ConstraintFunction(), ci) end @@ -1219,11 +1218,7 @@ function MOI.get( ) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - func = call_in_context( - b, - ci, - bridge -> MOI.get(recursive_model(b), attr, bridge), - ) + func = call_in_context(MOI.get, b, ci, attr) else func = MOI.get(b.model, attr, ci) end @@ -1256,11 +1251,7 @@ function _set_substituted( ) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - call_in_context( - b, - ci, - bridge -> MOI.set(recursive_model(b), attr, bridge, value), - ) + call_in_context(MOI.set, b, ci, attr, value) else MOI.set(b.model, attr, ci, value) end @@ -1625,7 +1616,7 @@ function MOI.modify( modify_bridged_change(b, ci, change) else if is_bridged(b, ci) - call_in_context(b, ci, bridge -> MOI.modify(b, bridge, change)) + call_in_context(MOI.modify, b, ci, change) else MOI.modify(b.model, ci, change) end @@ -1720,7 +1711,11 @@ function MOI.add_constrained_variable( BridgeType = Variable.concrete_bridge_type(b, typeof(set)) return Variable.add_key_for_bridge( Variable.bridges(b), - () -> Variable.bridge_constrained_variable(BridgeType, b, set), + () -> Variable.bridge_constrained_variable( + BridgeType, + recursive_model(b), + set, + ), set, ) else diff --git a/src/Bridges/lazy_bridge_optimizer.jl b/src/Bridges/lazy_bridge_optimizer.jl index 675da1a611..fbdd4a2e9c 100644 --- a/src/Bridges/lazy_bridge_optimizer.jl +++ b/src/Bridges/lazy_bridge_optimizer.jl @@ -513,7 +513,7 @@ function bridging_cost(b::LazyBridgeOptimizer, args...) return bridging_cost(b.graph, node(b, args...)) end -MOIB.recursive_model(b::SingleBridgeOptimizer) = b +recursive_model(b::LazyBridgeOptimizer) = b function MOI.compute_conflict!(model::LazyBridgeOptimizer) return MOI.compute_conflict!(model.model) diff --git a/test/Bridges/bridge_optimizer.jl b/test/Bridges/bridge_optimizer.jl index a42d85b330..c5fc1dcfeb 100644 --- a/test/Bridges/bridge_optimizer.jl +++ b/test/Bridges/bridge_optimizer.jl @@ -19,47 +19,6 @@ end include("utilities.jl") -include("identity_bridge.jl") - -function test_recursive_model_variable(::Type{T}) where {T} - model = MOIU.UniversalFallback(MOIU.Model{T}()) - b = MOIB.Variable.SingleBridgeOptimizer{IdentityBridges.VariableBridge{T}}( - model, - ) - x, cx = MOI.add_constrained_variable(b, MOI.EqualTo(one(T))) - @test MOIB.is_bridged(b, x) - @test MOIB.is_bridged(b, cx) -end - -test_recursive_model_variable(Int) - -function test_recursive_model_constraint(::Type{T}) where {T} - model = MOIU.UniversalFallback(MOIU.Model{T}()) - b = MOIB.Constraint.SingleBridgeOptimizer{ - IdentityBridges.ConstraintBridge{T}, - }( - model, - ) - x = MOI.add_variable(b) - fx = MOI.SingleVariable(x) - func = one(T) * fx - set = MOI.EqualTo(zero(T)) - c = MOI.add_constraint(b, func, set) - @test MOIB.is_bridged(b, c) - @test MOI.get(b, MOI.ConstraintFunction(), c) ≈ func - new_func = T(2) * fx - MOI.set(b, MOI.ConstraintFunction(), c, new_func) - @test MOI.get(b, MOI.ConstraintFunction(), c) == new_func - @test MOI.get(b, MOI.ConstraintSet(), c) == set - new_set = MOI.EqualTo(one(T)) - MOI.set(b, MOI.ConstraintSet(), c, new_set) - @test MOI.get(b, MOI.ConstraintSet(), c) == new_set - MOI.set(b, MOI.ConstraintDualStart(), c, one(T)) - @test MOI.get(b, MOI.ConstraintDualStart(), c) == one(T) -end - -test_recursive_model_constraint(Int) - struct DummyModelAttribute <: MOI.AbstractModelAttribute end struct DummyEvaluator <: MOI.AbstractNLPEvaluator end struct DummyVariableAttribute <: MOI.AbstractVariableAttribute end @@ -744,6 +703,70 @@ function test_get_ObjectiveFunctionType() return end +function test_recursive_model_variable(::Type{T} = Int) where {T} + model = MOIU.UniversalFallback(MOIU.Model{T}()) + BT = IdentityBridges.VariableBridge{T} + b = MOIB.Variable.SingleBridgeOptimizer{BT}(model) + x, cx = MOI.add_constrained_variable(b, MOI.EqualTo(one(T))) + @test MOIB.is_bridged(b, x) + @test MOIB.is_bridged(b, cx) + @test MOI.get(b, MOI.ConstraintFunction(), cx) == MOI.SingleVariable(x) + @test MOI.get(b, MOI.ConstraintSet(), cx) == MOI.EqualTo(one(T)) + MOI.set(b, MOI.ConstraintSet(), cx, MOI.EqualTo(zero(T))) + @test MOI.get(b, MOI.ConstraintSet(), cx) == MOI.EqualTo(zero(T)) + @test MOI.is_valid(b, x) + MOI.delete(b, x) + @test !MOI.is_valid(b, x) +end + +function test_recursive_model_constraint(::Type{T} = Int) where {T} + model = MOIU.UniversalFallback(MOIU.Model{T}()) + BT = IdentityBridges.ConstraintBridge{T} + b = MOIB.Constraint.SingleBridgeOptimizer{BT}(model) + x = MOI.add_variable(b) + fx = MOI.SingleVariable(x) + func = one(T) * fx + set = MOI.EqualTo(zero(T)) + c = MOI.add_constraint(b, func, set) + @test MOIB.is_bridged(b, c) + @test MOI.get(b, MOI.ConstraintFunction(), c) ≈ func + new_func = T(2) * fx + MOI.set(b, MOI.ConstraintFunction(), c, new_func) + @test MOI.get(b, MOI.ConstraintFunction(), c) == new_func + MOI.modify(b, c, MOI.ScalarCoefficientChange(x, T(3))) + @test MOI.get(b, MOI.ConstraintFunction(), c) ≈ T(3) * fx + MOI.modify(b, c, MOI.ScalarConstantChange(T(-1))) + @test MOI.get(b, MOI.ConstraintFunction(), c) ≈ T(3) * fx + T(-1) + @test MOI.get(b, MOI.ConstraintSet(), c) == set + new_set = MOI.EqualTo(one(T)) + MOI.set(b, MOI.ConstraintSet(), c, new_set) + @test MOI.get(b, MOI.ConstraintSet(), c) == new_set + MOI.set(b, MOI.ConstraintDualStart(), c, one(T)) + @test MOI.get(b, MOI.ConstraintDualStart(), c) == one(T) + @test MOI.is_valid(b, c) + MOI.delete(b, c) + @test !MOI.is_valid(b, c) +end + +function test_recursive_model_objective(::Type{T} = Int) where {T} + model = MOIU.UniversalFallback(MOIU.Model{T}()) + BT = IdentityBridges.ObjectiveBridge{T} + b = MOIB.Objective.SingleBridgeOptimizer{BT}(model) + x = MOI.add_variable(b) + fx = MOI.SingleVariable(x) + func = one(T) * fx + MOI.set(b, MOI.ObjectiveSense(), MOI.MIN_SENSE) + @test !MOIB.is_objective_bridged(b) + attr = MOI.ObjectiveFunction{typeof(func)}() + MOI.set(b, attr, func) + @test MOIB.is_objective_bridged(b) + @test MOI.get(b, attr) ≈ func + attr = MOI.ObjectiveFunction{typeof(fx)}() + MOI.set(b, attr, fx) + @test !MOIB.is_objective_bridged(b) + @test MOI.get(b, attr) ≈ fx +end + end # module TestBridgeOptimizer.runtests() diff --git a/test/Bridges/identity_bridge.jl b/test/Bridges/identity_bridge.jl index aeb13d0044..9a365f0e78 100644 --- a/test/Bridges/identity_bridge.jl +++ b/test/Bridges/identity_bridge.jl @@ -4,117 +4,89 @@ module IdentityBridges import MathOptInterface const MOI = MathOptInterface const MOIB = MOI.Bridges -const MOIBV = MOIB.Variable -const MOIBC = MOIB.Constraint const F{T} = MOI.ScalarAffineFunction{T} const S{T} = MOI.EqualTo{T} -struct VariableBridge{T} <: MOIBV.AbstractBridge - variables::Vector{MOI.VariableIndex} +struct VariableBridge{T} <: MOIB.Variable.SetMapBridge{T,S{T},S{T}} + variable::MOI.VariableIndex constraint::MOI.ConstraintIndex{MOI.SingleVariable,S{T}} end -function MOIBV.bridge_constrained_variable( - ::Type{VariableBridge{T}}, +struct ConstraintBridge{T} <: + MOIB.Constraint.SetMapBridge{T,S{T},S{T},F{T},F{T}} + constraint::MOI.ConstraintIndex{F{T},S{T}} +end + +const IdentityBridge{T} = Union{VariableBridge{T},ConstraintBridge{T}} + +MOIB.map_set(::Type{<:IdentityBridge}, set::S) = set +MOIB.inverse_map_set(::Type{<:IdentityBridge}, set::S) = set +MOIB.map_function(::Type{<:IdentityBridge}, func) = func +MOIB.inverse_map_function(::Type{<:IdentityBridge}, func) = func +MOIB.adjoint_map_function(::Type{<:IdentityBridge}, func) = func +MOIB.inverse_adjoint_map_function(::Type{<:IdentityBridge}, func) = func + +struct ObjectiveBridge{T} <: MOIB.Objective.AbstractBridge end + +function MOIB.Objective.bridge_objective( + ::Type{ObjectiveBridge{T}}, model::MOI.ModelLike, - set::S{T}, + func::F{T}, ) where {T} - variable, constraint = MOI.add_constrained_variable(model, set) - return VariableBridge{T}(variable, constraint) + MOI.set(model, MOI.ObjectiveFunction{F}(), func) + return ObjectiveBridge{T}() end -function MOIBV.supports_constrained_variable( - ::Type{VariableBridge{T}}, - ::Type{S{T}}, +function MOIB.Objective.supports_objective_function( + ::Type{ObjectiveBridge{T}}, + ::Type{F{T}}, ) where {T} return true end -function MOIB.added_constrained_variable_types( - ::Type{VariableBridge{T}}, -) where {T} - return [(S{T},)] +function MOIB.added_constrained_variable_types(::Type{<:ObjectiveBridge}) + return Tuple{DataType}[] end -function MOIB.added_constraint_types(::Type{<:VariableBridge}) +function MOIB.added_constraint_types(::Type{<:ObjectiveBridge}) return Tuple{DataType,DataType}[] end -# Attributes, Bridge acting as a model -MOI.get(bridge::VariableBridge, ::MOI.NumberOfVariables) = 1 -MOI.get(bridge::VariableBridge, ::MOI.ListOfVariableIndices) = [bridge.variable] - -function MOI.get( - bridge::VariableBridge, - ::MOI.NumberOfConstraints{MOI.VectorOfVariables,MOI.RotatedSecondOrderCone}, -) - return 1 +function MOIB.set_objective_function_type(::Type{ObjectiveBridge{T}}) where {T} + return F{T} end -function MOI.get( - bridge::VariableBridge, - ::MOI.ListOfConstraintIndices{ - MOI.VectorOfVariables, - MOI.RotatedSecondOrderCone, - }, -) - return [bridge.constraint] +# Attributes, Bridge acting as a model +function MOI.get(::ObjectiveBridge, ::MOI.NumberOfVariables) + return 0 end -# References -function MOI.delete(model::MOI.ModelLike, bridge::VariableBridge) - MOI.delete(model, bridge.variable) - return +function MOI.get(::ObjectiveBridge, ::MOI.ListOfVariableIndices) + return MOI.VariableIndex[] end -# Attributes, Bridge acting as a constraint - -function MOI.get( - model::MOI.ModelLike, - attr::MOI.ConstraintSet, - bridge::VariableBridge{T}, -) where {T} - return MOI.get(model, attr, bridge.constraint) -end +# No variables or constraints are created in this bridge so there is nothing to +# delete. +MOI.delete(model::MOI.ModelLike, bridge::ObjectiveBridge) = nothing -function MOI.get( - model::MOI.ModelLike, - attr::Union{MOI.ConstraintPrimal,MOI.ConstraintDual}, - bridge::VariableBridge, +function MOI.set( + ::MOI.ModelLike, + ::MOI.ObjectiveSense, + ::ObjectiveBridge, + ::MOI.OptimizationSense, ) - return MOI.get(model, attr, bridge.constraint) + # `ObjectiveBridge` is sense agnostic, therefore, we don't need to change + # anything. + return end function MOI.get( model::MOI.ModelLike, - attr::MOI.VariablePrimal, - bridge::VariableBridge, -) - return MOI.get(model, attr, bridge.variable) -end - -function MOIB.bridged_function(bridge::VariableBridge{T}) where {T} - return MOI.SingleVariable(bridge.variable) -end - -function unbridged_map( - bridge::VariableBridge{T}, - vi::MOI.VariableIndex, + attr::Union{MOIB.ObjectiveFunctionValue{F{T}},MOI.ObjectiveFunction{F{T}}}, + ::ObjectiveBridge{T}, ) where {T} - func = convert(F{T}, MOI.SingleVariable(vi)) - return (bridge.variable => func,) + return MOI.get(model, attr) end -struct ConstraintBridge{T} <: MOIBC.SetMapBridge{T,S{T},S{T},F{T},F{T}} - constraint::MOI.ConstraintIndex{F{T},S{T}} -end - -MOIBC.map_set(::Type{<:ConstraintBridge}, set::S) = set -MOIBC.inverse_map_set(::Type{<:ConstraintBridge}, set::S) = set -MOIBC.map_function(::Type{<:ConstraintBridge}, func) = func -MOIBC.inverse_map_function(::Type{<:ConstraintBridge}, func) = func -MOIBC.adjoint_map_function(::Type{<:ConstraintBridge}, func) = func -MOIBC.inverse_adjoint_map_function(::Type{<:ConstraintBridge}, func) = func - end From c5f6b92d9ddb0fbd60c09d70f6dc544c2e38e98d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Mon, 19 Jul 2021 21:27:02 -0400 Subject: [PATCH 3/9] Fix for Objective bridge --- src/Bridges/bridge_optimizer.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index 4a568a24c4..04554a2d6d 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -920,10 +920,16 @@ struct ObjectiveFunctionValue{F<:MOI.AbstractScalarFunction} result_index::Int end +# `recursive_model(b::Objective.SingleBridgeOptimizer)` returns +# `b.model` so any model should implement `ObjectiveFunctionValue`. +function MOI.get(model::MOI.ModelLike, attr::ObjectiveFunctionValue) + return MOI.get(model, MOI.ObjectiveValue()) +end + function MOI.get( b::AbstractBridgeOptimizer, attr::ObjectiveFunctionValue{F}, -) where {F} +) where {F<:MOI.AbstractScalarFunction} # Need `<:` to avoid ambiguity obj_attr = MOI.ObjectiveFunction{F}() if is_bridged(b, obj_attr) return MOI.get(recursive_model(b), attr, bridge(b, obj_attr)) From 19cfe771a6a81a96098725817e15cf10f8e5b6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 20 Jul 2021 17:40:29 -0400 Subject: [PATCH 4/9] Fixes --- src/Bridges/Constraint/set_map.jl | 9 +++++++-- src/Bridges/Variable/set_map.jl | 5 +---- src/Bridges/bridge_optimizer.jl | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Bridges/Constraint/set_map.jl b/src/Bridges/Constraint/set_map.jl index 29cfe88fc2..d023223d34 100644 --- a/src/Bridges/Constraint/set_map.jl +++ b/src/Bridges/Constraint/set_map.jl @@ -98,7 +98,12 @@ function MOI.set( bridge::SetMapBridge{T,S2,S1,F,G}, func::G, ) where {T,S2,S1,F,G} - MOI.set(model, attr, bridge.constraint, MOIB.map_function(typeof(bridge), func)) + MOI.set( + model, + attr, + bridge.constraint, + MOIB.map_function(typeof(bridge), func), + ) return end @@ -201,7 +206,7 @@ function MOI.modify( bridge::SetMapBridge, change::MOI.AbstractFunctionModification, ) - MOI.modify(model, bridge.constraint, _map_change(typeof(bridge), change)) + MOI.modify(model, bridge.constraint, _map_change(typeof(bridge), change)) return end diff --git a/src/Bridges/Variable/set_map.jl b/src/Bridges/Variable/set_map.jl index 917597cae1..bf2f6b7baa 100644 --- a/src/Bridges/Variable/set_map.jl +++ b/src/Bridges/Variable/set_map.jl @@ -193,10 +193,7 @@ function MOIB.bridged_function( return convert(MOI.ScalarAffineFunction{T}, func) end -function unbridged_map( - bridge::SetMapBridge{T}, - vi::MOI.VariableIndex, -) where {T} +function unbridged_map(bridge::SetMapBridge{T}, vi::MOI.VariableIndex) where {T} F = MOI.ScalarAffineFunction{T} func = MOI.SingleVariable(vi) mapped = MOIB.inverse_map_function(typeof(bridge), func) diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index 04554a2d6d..1163619884 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -579,7 +579,7 @@ end function MOI.delete(b::AbstractBridgeOptimizer, ci::MOI.ConstraintIndex) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - bridge = Constraint.bridges(b)[ci] + bridge = bridge(b, ci) if is_variable_bridged(b, ci) error( "Cannot delete constraint index of bridged constrained", @@ -923,7 +923,7 @@ end # `recursive_model(b::Objective.SingleBridgeOptimizer)` returns # `b.model` so any model should implement `ObjectiveFunctionValue`. function MOI.get(model::MOI.ModelLike, attr::ObjectiveFunctionValue) - return MOI.get(model, MOI.ObjectiveValue()) + return MOI.get(model, MOI.ObjectiveValue(attr.result_index)) end function MOI.get( From f40ceaad8e312d4452fd9d348518ed4652ab0463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 28 Jul 2021 19:30:15 +0200 Subject: [PATCH 5/9] Fix --- src/Bridges/bridge_optimizer.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index 1163619884..9be95eefec 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -579,7 +579,7 @@ end function MOI.delete(b::AbstractBridgeOptimizer, ci::MOI.ConstraintIndex) if is_bridged(b, ci) MOI.throw_if_not_valid(b, ci) - bridge = bridge(b, ci) + br = bridge(b, ci) if is_variable_bridged(b, ci) error( "Cannot delete constraint index of bridged constrained", @@ -592,7 +592,7 @@ function MOI.delete(b::AbstractBridgeOptimizer, ci::MOI.ConstraintIndex) Variable.call_in_context( Variable.bridges(b), ci, - () -> MOI.delete(recursive_model(b), bridge), + () -> MOI.delete(recursive_model(b), br), ) b.name_to_con = nothing delete!(b.con_to_name, ci) From 3f2e9ed17877631db7d3b818f9594d5ea48927c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 28 Jul 2021 19:36:37 +0200 Subject: [PATCH 6/9] Add identity_bridge --- test/Bridges/bridge_optimizer.jl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/Bridges/bridge_optimizer.jl b/test/Bridges/bridge_optimizer.jl index c5fc1dcfeb..56b7349c50 100644 --- a/test/Bridges/bridge_optimizer.jl +++ b/test/Bridges/bridge_optimizer.jl @@ -703,6 +703,8 @@ function test_get_ObjectiveFunctionType() return end +include("identity_bridge.jl") + function test_recursive_model_variable(::Type{T} = Int) where {T} model = MOIU.UniversalFallback(MOIU.Model{T}()) BT = IdentityBridges.VariableBridge{T} From 007110226d41ca736a8af15939395414a0564b63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 28 Jul 2021 19:37:13 +0200 Subject: [PATCH 7/9] Fix format --- src/Bridges/Variable/set_map.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bridges/Variable/set_map.jl b/src/Bridges/Variable/set_map.jl index bf2f6b7baa..0f86f7fa96 100644 --- a/src/Bridges/Variable/set_map.jl +++ b/src/Bridges/Variable/set_map.jl @@ -197,7 +197,7 @@ function unbridged_map(bridge::SetMapBridge{T}, vi::MOI.VariableIndex) where {T} F = MOI.ScalarAffineFunction{T} func = MOI.SingleVariable(vi) mapped = MOIB.inverse_map_function(typeof(bridge), func) - return Pair{MOI.VariableIndex,F}[bridge.variable => mapped] + return Pair{MOI.VariableIndex,F}[bridge.variable=>mapped] end function unbridged_map( From 51d1f3eb58b842c93d8e4f5a42acda434ca5847f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 28 Jul 2021 21:15:35 +0200 Subject: [PATCH 8/9] MOIU -> MOI.Utilities --- test/Bridges/bridge_optimizer.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Bridges/bridge_optimizer.jl b/test/Bridges/bridge_optimizer.jl index 56b7349c50..386ef5d7ab 100644 --- a/test/Bridges/bridge_optimizer.jl +++ b/test/Bridges/bridge_optimizer.jl @@ -706,7 +706,7 @@ end include("identity_bridge.jl") function test_recursive_model_variable(::Type{T} = Int) where {T} - model = MOIU.UniversalFallback(MOIU.Model{T}()) + model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{T}()) BT = IdentityBridges.VariableBridge{T} b = MOIB.Variable.SingleBridgeOptimizer{BT}(model) x, cx = MOI.add_constrained_variable(b, MOI.EqualTo(one(T))) @@ -722,7 +722,7 @@ function test_recursive_model_variable(::Type{T} = Int) where {T} end function test_recursive_model_constraint(::Type{T} = Int) where {T} - model = MOIU.UniversalFallback(MOIU.Model{T}()) + model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{T}()) BT = IdentityBridges.ConstraintBridge{T} b = MOIB.Constraint.SingleBridgeOptimizer{BT}(model) x = MOI.add_variable(b) @@ -751,7 +751,7 @@ function test_recursive_model_constraint(::Type{T} = Int) where {T} end function test_recursive_model_objective(::Type{T} = Int) where {T} - model = MOIU.UniversalFallback(MOIU.Model{T}()) + model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{T}()) BT = IdentityBridges.ObjectiveBridge{T} b = MOIB.Objective.SingleBridgeOptimizer{BT}(model) x = MOI.add_variable(b) From 51bade98e46abc7fc6f1c67ec5afec6dddaa4447 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 29 Jul 2021 10:42:48 +0200 Subject: [PATCH 9/9] MOIB -> MOI.Bridges --- test/Bridges/bridge_optimizer.jl | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/Bridges/bridge_optimizer.jl b/test/Bridges/bridge_optimizer.jl index 386ef5d7ab..edef17256d 100644 --- a/test/Bridges/bridge_optimizer.jl +++ b/test/Bridges/bridge_optimizer.jl @@ -708,10 +708,10 @@ include("identity_bridge.jl") function test_recursive_model_variable(::Type{T} = Int) where {T} model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{T}()) BT = IdentityBridges.VariableBridge{T} - b = MOIB.Variable.SingleBridgeOptimizer{BT}(model) + b = MOI.Bridges.Variable.SingleBridgeOptimizer{BT}(model) x, cx = MOI.add_constrained_variable(b, MOI.EqualTo(one(T))) - @test MOIB.is_bridged(b, x) - @test MOIB.is_bridged(b, cx) + @test MOI.Bridges.is_bridged(b, x) + @test MOI.Bridges.is_bridged(b, cx) @test MOI.get(b, MOI.ConstraintFunction(), cx) == MOI.SingleVariable(x) @test MOI.get(b, MOI.ConstraintSet(), cx) == MOI.EqualTo(one(T)) MOI.set(b, MOI.ConstraintSet(), cx, MOI.EqualTo(zero(T))) @@ -724,13 +724,13 @@ end function test_recursive_model_constraint(::Type{T} = Int) where {T} model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{T}()) BT = IdentityBridges.ConstraintBridge{T} - b = MOIB.Constraint.SingleBridgeOptimizer{BT}(model) + b = MOI.Bridges.Constraint.SingleBridgeOptimizer{BT}(model) x = MOI.add_variable(b) fx = MOI.SingleVariable(x) func = one(T) * fx set = MOI.EqualTo(zero(T)) c = MOI.add_constraint(b, func, set) - @test MOIB.is_bridged(b, c) + @test MOI.Bridges.is_bridged(b, c) @test MOI.get(b, MOI.ConstraintFunction(), c) ≈ func new_func = T(2) * fx MOI.set(b, MOI.ConstraintFunction(), c, new_func) @@ -753,19 +753,19 @@ end function test_recursive_model_objective(::Type{T} = Int) where {T} model = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{T}()) BT = IdentityBridges.ObjectiveBridge{T} - b = MOIB.Objective.SingleBridgeOptimizer{BT}(model) + b = MOI.Bridges.Objective.SingleBridgeOptimizer{BT}(model) x = MOI.add_variable(b) fx = MOI.SingleVariable(x) func = one(T) * fx MOI.set(b, MOI.ObjectiveSense(), MOI.MIN_SENSE) - @test !MOIB.is_objective_bridged(b) + @test !MOI.Bridges.is_objective_bridged(b) attr = MOI.ObjectiveFunction{typeof(func)}() MOI.set(b, attr, func) - @test MOIB.is_objective_bridged(b) + @test MOI.Bridges.is_objective_bridged(b) @test MOI.get(b, attr) ≈ func attr = MOI.ObjectiveFunction{typeof(fx)}() MOI.set(b, attr, fx) - @test !MOIB.is_objective_bridged(b) + @test !MOI.Bridges.is_objective_bridged(b) @test MOI.get(b, attr) ≈ fx end