Hi, I’ve been playing around with MOI bridges, but I can’t get even the simplest thing to work.
Let’s imagine I want to create a bridge that simply ignores any PSD constraints:
module MWE
using MathOptInterface
const MOI = MathOptInterface
struct RemovePSDBridge <: MOI.Bridges.Constraint.AbstractBridge end
function MOI.supports_constraint(::Type{<:RemovePSDBridge},
::Type{<:MOI.AbstractVectorFunction},
::Type{<:MOI.PositiveSemidefiniteConeTriangle})
return true
end
function MOI.Bridges.added_constrained_variable_types(::Type{<:RemovePSDBridge})
Tuple{DataType}[]
end
function MOI.Bridges.added_constraint_types(::Type{<:RemovePSDBridge})
[]
end
function bridge_constraint(::Type{RemovePSDBridge}, model::MOI.ModelLike, f::MOI.AbstractVectorFunction, s::MathOptInterface.PositiveSemidefiniteConeTriangle)
end
end
Then the obvious proof of concept is whether an LP solver accepts it:
using JuMP
using Clp
using MWE
m = Model(Clp.Optimizer)
MOI.Bridges.add_bridge(m.moi_backend.optimizer, MWE.RemovePSDBridge)
@variable m x[1:3]
@objective m Min x[1]
@constraint(m,[x[1] x[2];x[2] x[3]] in JuMP.PSDCone())
optimize!(m)
struct RemovePSDBridge{T} <: MOI.Bridges.Constraint.AbstractBridge
end
function MOI.Bridges.Constraint.concrete_bridge_type(
::Type{<:RemovePSDBridge},
F::Type{<:MOI.AbstractVectorFunction},
S::Type{<:MOI.PositiveSemidefiniteConeTriangle},
)
return RemovePSDBridge{Float64}
end
function MOI.supports_constraint(
::Type{<:RemovePSDBridge},
::Type{<:MOI.AbstractVectorFunction},
::Type{<:MOI.PositiveSemidefiniteConeTriangle},
)
return true
end
function MOI.Bridges.added_constrained_variable_types(::Type{<:RemovePSDBridge})
return Tuple{DataType}[]
end
function MOI.Bridges.added_constraint_types(::Type{<:RemovePSDBridge})
return []
end
function MOI.Bridges.Constraint.bridge_constraint(
::Type{<:RemovePSDBridge},
::MOI.ModelLike,
f::MOI.AbstractVectorFunction,
s::MOI.PositiveSemidefiniteConeTriangle,
)
return RemovePSDBridge{Float64}()
end
# Wrap the optimizer in a single bridge optimizer
opt = () -> MOI.Bridges.Constraint.SingleBridgeOptimizer{RemovePSDBridge{Float64}}(
# Clp doesn't support incremental modification, so we need to wrap it in a cache
MOI.Utilities.CachingOptimizer(
MOI.Utilities.Model{Float64}(),
Clp.Optimizer()
)
)
m = Model(opt)
@variable m x[1:3]
@objective m Min x[1]
@constraint(m,[x[1] x[2];x[2] x[3]] in JuMP.PSDCone())
optimize!(m)
m = Model(Clp.Optimizer)
add_bridge(m, RemovePSDBridge)
@variable m x[1:3]
@objective m Min x[1]
@constraint(m,[x[1] x[2];x[2] x[3]] in JuMP.PSDCone())
optimize!(m)
Much simpler.
creating the model/bridge/cache/model/solver hierarchy
You seem well on your way to understanding what is happening. It is pretty complicated…
the wiki as is, MOI is fairly impenetrable.
Pull requests to improve the documentation (e.g., adding a link to the paper) would be great! We’ve focused on building functionality, and documentation has fallen behind, unfortunately.