Skip to content
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
22 changes: 22 additions & 0 deletions docs/src/apireference.md
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,28 @@ Moreover, a `LazyBridgeOptimizer` with all the bridges defined in this package c
Bridges.full_bridge_optimizer
```

### Bridge interface

A bridge should implement the following functions to be usable by a bridge optimizer:
```@docs
supports_constraint(::Type{<:Bridges.AbstractBridge}, ::Type{<:AbstractFunction}, ::Type{<:AbstractSet})
Bridges.concrete_bridge_type
Bridges.bridge_constraint
Bridges.added_constraint_types
```

When querying the [`NumberOfVariables`](@ref), [`NumberOfConstraints`](@ref)
and [`ListOfConstraintIndices`](@ref), the variables and constraints created
by the bridges in the underlying model are hidden by the bridge optimizer.
For this purpose, the bridge should provide access to the variables and
constraints it has creates by implemented the following methods of
[`get`](@ref):
```@docs
get(::Bridges.AbstractBridge, ::NumberOfVariables)
get(::Bridges.AbstractBridge, ::NumberOfConstraints)
get(::Bridges.AbstractBridge, ::ListOfConstraintIndices)
```

## Copy utilities

The following utilities can be used to implement [`copy_to`](@ref). See
Expand Down
8 changes: 8 additions & 0 deletions src/Bridges/bridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ These calls are used by the `AbstractBridgeOptimizer` to communicate with the br
"""
abstract type AbstractBridge end

"""
bridge_constraint(BT::Type{<:AbstractBridge}, model::MOI.ModelLike,
func::AbstractFunction, set::MOI.AbstractSet)

Bridge the constraint `func`-in-`set` using bridge `BT` to `model` and returns
a bridge object of type `BT`.
"""
function bridge_constraint end

function MOI.get(::MOI.ModelLike, attr::MOI.AbstractConstraintAttribute,
bridge::AbstractBridge)
Expand Down
2 changes: 1 addition & 1 deletion src/Bridges/bridgeoptimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ function MOI.add_constraint(b::AbstractBridgeOptimizer, f::MOI.AbstractFunction,
BridgeType = concrete_bridge_type(b, typeof(f), typeof(s))
# `add_constraint` might throw an `UnsupportedConstraint` but no
# modification has been done in the previous line
push!(b.bridges, BridgeType(b, f, s))
push!(b.bridges, bridge_constraint(BridgeType, b, f, s))
push!(b.constraint_types, (typeof(f), typeof(s)))
ci = MOI.ConstraintIndex{typeof(f), typeof(s)}(length(b.bridges))
return ci
Expand Down
27 changes: 18 additions & 9 deletions src/Bridges/detbridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,22 @@ struct LogDetBridge{T} <: AbstractBridge
lcindex::Vector{CI{MOI.VectorAffineFunction{T}, MOI.ExponentialCone}}
tlindex::CI{MOI.ScalarAffineFunction{T}, MOI.LessThan{T}}
end
function LogDetBridge{T}(model, f::MOI.VectorOfVariables, s::MOI.LogDetConeTriangle) where T
LogDetBridge{T}(model, MOI.VectorAffineFunction{T}(f), s)
function bridge_constraint(::Type{LogDetBridge{T}}, model,
f::MOI.VectorOfVariables,
s::MOI.LogDetConeTriangle) where T
return bridge_constraint(LogDetBridge{T}, model,
MOI.VectorAffineFunction{T}(f), s)
end
function LogDetBridge{T}(model, f::MOI.VectorAffineFunction{T}, s::MOI.LogDetConeTriangle) where T
function bridge_constraint(::Type{LogDetBridge{T}}, model,
f::MOI.VectorAffineFunction{T},
s::MOI.LogDetConeTriangle) where T
d = s.side_dimension
tu, D, Δ, sdindex = extract_eigenvalues(model, f, d, 2)
t, u = tu
l = MOI.add_variables(model, d)
lcindex = [sublog(model, l[i], u, D[i], T) for i in eachindex(l)]
tlindex = subsum(model, t, l, T)

LogDetBridge(Δ, l, sdindex, lcindex, tlindex)
return LogDetBridge(Δ, l, sdindex, lcindex, tlindex)
end

MOI.supports_constraint(::Type{LogDetBridge{T}}, ::Type{<:Union{MOI.VectorOfVariables, MOI.VectorAffineFunction{T}}}, ::Type{MOI.LogDetConeTriangle}) where T = true
Expand Down Expand Up @@ -170,18 +174,23 @@ struct RootDetBridge{T} <: AbstractBridge
sdindex::CI{MOI.VectorAffineFunction{T}, MOI.PositiveSemidefiniteConeTriangle}
gmindex::CI{MOI.VectorAffineFunction{T}, MOI.GeometricMeanCone}
end
function RootDetBridge{T}(model, f::MOI.VectorOfVariables, s::MOI.RootDetConeTriangle) where T
RootDetBridge{T}(model, MOI.VectorAffineFunction{T}(f), s)
function bridge_constraint(::Type{RootDetBridge{T}}, model,
f::MOI.VectorOfVariables,
s::MOI.RootDetConeTriangle) where T
return bridge_constraint(RootDetBridge{T}, model,
MOI.VectorAffineFunction{T}(f), s)
end
function RootDetBridge{T}(model, f::MOI.VectorAffineFunction{T}, s::MOI.RootDetConeTriangle) where T
function bridge_constraint(::Type{RootDetBridge{T}}, model,
f::MOI.VectorAffineFunction{T},
s::MOI.RootDetConeTriangle) where T
d = s.side_dimension
tu, D, Δ, sdindex = extract_eigenvalues(model, f, d, 1)
t = tu[1]
DF = MOI.VectorAffineFunction{T}(MOI.VectorOfVariables(D))
gmindex = MOI.add_constraint(model, MOIU.operate(vcat, T, t, DF),
MOI.GeometricMeanCone(d+1))

RootDetBridge(Δ, sdindex, gmindex)
return RootDetBridge(Δ, sdindex, gmindex)
end

MOI.supports_constraint(::Type{RootDetBridge{T}}, ::Type{<:Union{MOI.VectorOfVariables, MOI.VectorAffineFunction{T}}}, ::Type{MOI.RootDetConeTriangle}) where T = true
Expand Down
28 changes: 16 additions & 12 deletions src/Bridges/flip_sign_bridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@ struct GreaterToLessBridge{T, F<:MOI.AbstractScalarFunction} <:
FlipSignBridge{T, MOI.GreaterThan{T}, MOI.LessThan{T}, F}
flipped_constraint::CI{F, MOI.LessThan{T}}
end
function GreaterToLessBridge{T, F}(model::MOI.ModelLike,
g::MOI.AbstractScalarFunction,
s::MOI.GreaterThan) where {T, F}
function bridge_constraint(::Type{GreaterToLessBridge{T, F}},
model::MOI.ModelLike,
g::MOI.AbstractScalarFunction,
s::MOI.GreaterThan) where {T, F}
f = MOIU.operate(-, T, g)
flipped_constraint = MOI.add_constraint(model, f, MOI.LessThan(-s.lower))
return GreaterToLessBridge{T, F}(flipped_constraint)
Expand Down Expand Up @@ -115,9 +116,10 @@ struct LessToGreaterBridge{T, F<:MOI.AbstractScalarFunction} <:
FlipSignBridge{T, MOI.LessThan{T}, MOI.GreaterThan{T}, F}
flipped_constraint::CI{F, MOI.GreaterThan{T}}
end
function LessToGreaterBridge{T, F}(model::MOI.ModelLike,
g::MOI.AbstractScalarFunction,
s::MOI.LessThan) where {T, F}
function bridge_constraint(::Type{LessToGreaterBridge{T, F}},
model::MOI.ModelLike,
g::MOI.AbstractScalarFunction,
s::MOI.LessThan) where {T, F}
f = MOIU.operate(-, T, g)
flipped_constraint = MOI.add_constraint(model, f, MOI.GreaterThan(-s.upper))
return LessToGreaterBridge{T, F}(flipped_constraint)
Expand Down Expand Up @@ -151,9 +153,10 @@ struct NonnegToNonposBridge{T, F<:MOI.AbstractVectorFunction} <:
FlipSignBridge{T, MOI.Nonnegatives, MOI.Nonpositives, F}
flipped_constraint::CI{F, MOI.Nonpositives}
end
function NonnegToNonposBridge{T, F}(model::MOI.ModelLike,
g::MOI.AbstractVectorFunction,
s::MOI.Nonnegatives) where {T, F}
function bridge_constraint(::Type{NonnegToNonposBridge{T, F}},
model::MOI.ModelLike,
g::MOI.AbstractVectorFunction,
s::MOI.Nonnegatives) where {T, F}
f = MOIU.operate(-, T, g)
flipped_constraint = MOI.add_constraint(model, f,
MOI.Nonpositives(s.dimension))
Expand All @@ -177,9 +180,10 @@ struct NonposToNonnegBridge{T, F<:MOI.AbstractVectorFunction} <:
FlipSignBridge{T, MOI.Nonpositives, MOI.Nonnegatives, F}
flipped_constraint::CI{F, MOI.Nonnegatives}
end
function NonposToNonnegBridge{T, F}(model::MOI.ModelLike,
g::MOI.AbstractVectorFunction,
s::MOI.Nonpositives) where {T, F}
function bridge_constraint(::Type{NonposToNonnegBridge{T, F}},
model::MOI.ModelLike,
g::MOI.AbstractVectorFunction,
s::MOI.Nonpositives) where {T, F}
f = MOIU.operate(-, T, g)
flipped_constraint = MOI.add_constraint(model, f,
MOI.Nonnegatives(s.dimension))
Expand Down
6 changes: 4 additions & 2 deletions src/Bridges/functionize_bridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ into the constraint `ScalarAffineFunction{T}`-in-`S`.
struct ScalarFunctionizeBridge{T, S} <: AbstractBridge
constraint::CI{MOI.ScalarAffineFunction{T}, S}
end
function ScalarFunctionizeBridge{T, S}(model, f::MOI.SingleVariable, s::S) where {T, S}
function bridge_constraint(::Type{ScalarFunctionizeBridge{T, S}}, model,
f::MOI.SingleVariable, s::S) where {T, S}
constraint = MOI.add_constraint(model, MOI.ScalarAffineFunction{T}(f), s)
return ScalarFunctionizeBridge{T, S}(constraint)
end
Expand Down Expand Up @@ -81,7 +82,8 @@ into the constraint `VectorAffineFunction{T}`-in-`S`.
struct VectorFunctionizeBridge{T, S} <: AbstractBridge
constraint::CI{MOI.VectorAffineFunction{T}, S}
end
function VectorFunctionizeBridge{T, S}(model, f::MOI.VectorOfVariables, s::S) where {T, S}
function bridge_constraint(::Type{VectorFunctionizeBridge{T, S}}, model,
f::MOI.VectorOfVariables, s::S) where {T, S}
constraint = MOI.add_constraint(model, MOI.VectorAffineFunction{T}(f), s)
return VectorFunctionizeBridge{T, S}(constraint)
end
Expand Down
5 changes: 3 additions & 2 deletions src/Bridges/geomeanbridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,9 @@ struct GeoMeanBridge{T, F, G} <: AbstractBridge
tubc::CI{F, MOI.LessThan{T}}
socrc::Vector{CI{G, MOI.RotatedSecondOrderCone}}
end
function GeoMeanBridge{T, F, G}(model, f::MOI.AbstractVectorFunction,
s::MOI.GeometricMeanCone) where {T, F, G}
function bridge_constraint(::Type{GeoMeanBridge{T, F, G}}, model,
f::MOI.AbstractVectorFunction,
s::MOI.GeometricMeanCone) where {T, F, G}
d = s.dimension
n = d-1
l = ilog2(n)
Expand Down
3 changes: 2 additions & 1 deletion src/Bridges/intervalbridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ struct SplitIntervalBridge{T, F<:MOI.AbstractScalarFunction} <: AbstractBridge
lower::CI{F, MOI.GreaterThan{T}}
upper::CI{F, MOI.LessThan{T}}
end
function SplitIntervalBridge{T, F}(model, f::F, s::MOI.Interval{T}) where {T, F}
function bridge_constraint(::Type{SplitIntervalBridge{T, F}}, model, f::F,
s::MOI.Interval{T}) where {T, F}
lower = MOI.add_constraint(model, f, MOI.GreaterThan(s.lower))
upper = MOI.add_constraint(model, f, MOI.LessThan(s.upper))
return SplitIntervalBridge{T, F}(lower, upper)
Expand Down
7 changes: 4 additions & 3 deletions src/Bridges/quadtosocbridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,10 @@ struct QuadtoSOCBridge{T} <: AbstractBridge
less_than::Bool # whether the constraint was ≤ or ≥
set_constant::T # the constant that was on the set
end
function QuadtoSOCBridge{T}(model, func::MOI.ScalarQuadraticFunction{T},
set::Union{MOI.LessThan{T},
MOI.GreaterThan{T}}) where T
function bridge_constraint(::Type{QuadtoSOCBridge{T}}, model,
func::MOI.ScalarQuadraticFunction{T},
set::Union{MOI.LessThan{T},
MOI.GreaterThan{T}}) where T
set_constant = MOI.constant(set)
less_than = set isa MOI.LessThan
Q, index_to_variable_map = matrix_from_quadratic_terms(func.quadratic_terms)
Expand Down
4 changes: 3 additions & 1 deletion src/Bridges/rsocbridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ That means in particular that the norm is of constraint primal and duals are pre
struct RSOCBridge{T, F} <: AbstractBridge
soc::CI{F, MOI.SecondOrderCone}
end
function RSOCBridge{T, F}(model, f::MOI.AbstractVectorFunction, s::MOI.RotatedSecondOrderCone) where {T, F}
function bridge_constraint(::Type{RSOCBridge{T, F}}, model,
f::MOI.AbstractVectorFunction,
s::MOI.RotatedSecondOrderCone) where {T, F}
d = s.dimension
f_scalars = MOIU.eachscalar(f)
t = f_scalars[1]
Expand Down
7 changes: 4 additions & 3 deletions src/Bridges/scalarizebridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ mutable struct ScalarizeBridge{T, F, S} <: AbstractBridge
scalar_constraints::Vector{CI{F, S}}
constants::Vector{T}
end
function ScalarizeBridge{T, F, S}(model::MOI.ModelLike,
f::MOI.AbstractVectorFunction,
set::VectorLinearSet) where {T, F, S}
function bridge_constraint(::Type{ScalarizeBridge{T, F, S}},
model::MOI.ModelLike,
f::MOI.AbstractVectorFunction,
set::VectorLinearSet) where {T, F, S}
dimension = MOI.output_dimension(f)
constants = MOI.constant(f, T)
new_f = MOIU.scalarize(f, true)
Expand Down
6 changes: 4 additions & 2 deletions src/Bridges/slackbridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ struct ScalarSlackBridge{T, F, S} <: AbstractBridge
slack_in_set::CI{MOI.SingleVariable, S}
equality::CI{F, MOI.EqualTo{T}}
end
function ScalarSlackBridge{T, F, S}(model, f::MOI.AbstractScalarFunction, s::S) where {T, F, S}
function bridge_constraint(::Type{ScalarSlackBridge{T, F, S}}, model,
f::MOI.AbstractScalarFunction, s::S) where {T, F, S}
slack = MOI.add_variable(model)
new_f = MOIU.operate(-, T, f, MOI.SingleVariable(slack))
slack_in_set = MOI.add_constraint(model, MOI.SingleVariable(slack), s)
Expand Down Expand Up @@ -115,7 +116,8 @@ struct VectorSlackBridge{T, F, S} <: AbstractBridge
slacks_in_set::CI{MOI.VectorOfVariables, S}
equality::CI{F, MOI.Zeros}
end
function VectorSlackBridge{T, F, S}(model, f::MOI.AbstractVectorFunction, s::S) where {T, F, S}
function bridge_constraint(::Type{VectorSlackBridge{T, F, S}}, model,
f::MOI.AbstractVectorFunction, s::S) where {T, F, S}
d = MOI.dimension(s)
slacks = MOI.add_variables(model, d)
new_f = MOIU.operate(-, T, f, MOI.VectorOfVariables(slacks))
Expand Down
34 changes: 18 additions & 16 deletions src/Bridges/soctopsdbridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ struct SOCtoPSDBridge{T} <: AbstractBridge
dim::Int
cr::CI{MOI.VectorAffineFunction{T}, MOI.PositiveSemidefiniteConeTriangle}
end
function SOCtoPSDBridge{T}(instance, f, s::MOI.SecondOrderCone) where T
function bridge_constraint(::Type{SOCtoPSDBridge{T}}, model, f,
s::MOI.SecondOrderCone) where T
d = MOI.dimension(s)
cr = MOI.add_constraint(instance, _SOCtoPSDaff(f, T), MOI.PositiveSemidefiniteConeTriangle(d))
cr = MOI.add_constraint(model, _SOCtoPSDaff(f, T), MOI.PositiveSemidefiniteConeTriangle(d))
SOCtoPSDBridge(d, cr)
end

Expand All @@ -67,20 +68,20 @@ _SOCtoPSDaff(f::MOI.VectorAffineFunction, ::Type) = _SOCtoPSDaff(f, MOIU.eachsca
MOI.supports_constraint(::Type{SOCtoPSDBridge{T}}, ::Type{<:Union{MOI.VectorOfVariables, MOI.VectorAffineFunction{T}}}, ::Type{MOI.SecondOrderCone}) where T = true
added_constraint_types(::Type{SOCtoPSDBridge{T}}, ::Type{<:Union{MOI.VectorOfVariables, MOI.VectorAffineFunction{T}}}, ::Type{MOI.SecondOrderCone}) where T = [(MOI.VectorAffineFunction{T}, MOI.PositiveSemidefiniteConeTriangle)]

function MOI.get(instance::MOI.AbstractOptimizer, a::MOI.ConstraintPrimal, c::SOCtoPSDBridge)
MOI.get(instance, a, c.cr)[trimap.(1:c.dim, 1)]
function MOI.get(model::MOI.AbstractOptimizer, a::MOI.ConstraintPrimal, c::SOCtoPSDBridge)
MOI.get(model, a, c.cr)[trimap.(1:c.dim, 1)]
end
function MOI.get(instance::MOI.AbstractOptimizer, a::MOI.ConstraintDual, c::SOCtoPSDBridge)
dual = MOI.get(instance, a, c.cr)
function MOI.get(model::MOI.AbstractOptimizer, a::MOI.ConstraintDual, c::SOCtoPSDBridge)
dual = MOI.get(model, a, c.cr)
tdual = sum(i -> dual[trimap(i, i)], 1:c.dim)
[tdual; dual[trimap.(2:c.dim, 1)]*2]
end

MOI.get(::SOCtoPSDBridge{T}, ::MOI.NumberOfConstraints{MOI.VectorAffineFunction{T}, MOI.PositiveSemidefiniteConeTriangle}) where T = 1
MOI.get(b::SOCtoPSDBridge{T}, ::MOI.ListOfConstraintIndices{MOI.VectorAffineFunction{T}, MOI.PositiveSemidefiniteConeTriangle}) where T = [b.cr]

function MOI.delete(instance::MOI.AbstractOptimizer, c::SOCtoPSDBridge)
MOI.delete(instance, c.cr)
function MOI.delete(model::MOI.AbstractOptimizer, c::SOCtoPSDBridge)
MOI.delete(model, c.cr)
end

"""
Expand Down Expand Up @@ -114,9 +115,10 @@ end
MOI.supports_constraint(::Type{RSOCtoPSDBridge{T}}, ::Type{<:Union{MOI.VectorOfVariables, MOI.VectorAffineFunction{T}}}, ::Type{MOI.RotatedSecondOrderCone}) where T = true
added_constraint_types(::Type{RSOCtoPSDBridge{T}}, ::Type{<:Union{MOI.VectorOfVariables, MOI.VectorAffineFunction{T}}}, ::Type{MOI.RotatedSecondOrderCone}) where T = [(MOI.VectorAffineFunction{T}, MOI.PositiveSemidefiniteConeTriangle)]

function RSOCtoPSDBridge{T}(instance, f, s::MOI.RotatedSecondOrderCone) where T
function bridge_constraint(::Type{RSOCtoPSDBridge{T}}, model, f,
s::MOI.RotatedSecondOrderCone) where T
d = MOI.dimension(s)-1
cr = MOI.add_constraint(instance, _RSOCtoPSDaff(f, T), MOI.PositiveSemidefiniteConeTriangle(d))
cr = MOI.add_constraint(model, _RSOCtoPSDaff(f, T), MOI.PositiveSemidefiniteConeTriangle(d))
RSOCtoPSDBridge(d, cr)
end

Expand All @@ -128,20 +130,20 @@ function _RSOCtoPSDaff(f::MOI.VectorAffineFunction, ::Type{T}) where T
_SOCtoPSDaff(f_scalars[[1; 3:n]], g)
end

function MOI.get(instance::MOI.AbstractOptimizer, a::MOI.ConstraintPrimal, c::RSOCtoPSDBridge)
x = MOI.get(instance, MOI.ConstraintPrimal(), c.cr)[[trimap(1, 1); trimap(2, 2); trimap.(2:c.dim, 1)]]
function MOI.get(model::MOI.AbstractOptimizer, a::MOI.ConstraintPrimal, c::RSOCtoPSDBridge)
x = MOI.get(model, MOI.ConstraintPrimal(), c.cr)[[trimap(1, 1); trimap(2, 2); trimap.(2:c.dim, 1)]]
x[2] /= 2 # It is (2u*I)[1,1] so it needs to be divided by 2 to get u
x
end
function MOI.get(instance::MOI.AbstractOptimizer, a::MOI.ConstraintDual, c::RSOCtoPSDBridge)
dual = MOI.get(instance, MOI.ConstraintDual(), c.cr)
function MOI.get(model::MOI.AbstractOptimizer, a::MOI.ConstraintDual, c::RSOCtoPSDBridge)
dual = MOI.get(model, MOI.ConstraintDual(), c.cr)
udual = sum(i -> dual[trimap(i, i)], 2:c.dim)
[dual[1]; 2udual; dual[trimap.(2:c.dim, 1)]*2]
end

MOI.get(::RSOCtoPSDBridge{T}, ::MOI.NumberOfConstraints{MOI.VectorAffineFunction{T}, MOI.PositiveSemidefiniteConeTriangle}) where T = 1
MOI.get(b::RSOCtoPSDBridge{T}, ::MOI.ListOfConstraintIndices{MOI.VectorAffineFunction{T}, MOI.PositiveSemidefiniteConeTriangle}) where T = [b.cr]

function MOI.delete(instance::MOI.AbstractOptimizer, c::RSOCtoPSDBridge)
MOI.delete(instance, c.cr)
function MOI.delete(model::MOI.AbstractOptimizer, c::RSOCtoPSDBridge)
MOI.delete(model, c.cr)
end
7 changes: 3 additions & 4 deletions src/Bridges/squarepsdbridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,9 @@ struct SquarePSDBridge{T, F<:MOI.AbstractVectorFunction,
psd::CI{F, MOI.PositiveSemidefiniteConeTriangle}
sym::Vector{Pair{Tuple{Int, Int}, CI{G, MOI.EqualTo{T}}}}
end
function SquarePSDBridge{T, F, G}(model::MOI.ModelLike, f::F,
s::MOI.PositiveSemidefiniteConeSquare) where {T,
F <: MOI.AbstractVectorFunction,
G <: MOI.AbstractScalarFunction}
function bridge_constraint(::Type{SquarePSDBridge{T, F, G}},
model::MOI.ModelLike, f::F,
s::MOI.PositiveSemidefiniteConeSquare) where {T, F, G}
f_scalars = MOIU.eachscalar(f)
sym = Pair{Tuple{Int, Int}, CI{G, MOI.EqualTo{T}}}[]
dim = s.side_dimension
Expand Down
5 changes: 3 additions & 2 deletions src/Bridges/vectorizebridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ mutable struct VectorizeBridge{T, F, S, G} <: AbstractBridge
vector_constraint::CI{F, S}
set_constant::T # constant in scalar set
end
function VectorizeBridge{T, F, S, G}(model::MOI.ModelLike, g::G,
set::MOI.AbstractScalarSet) where {T, F, S, G}
function bridge_constraint(::Type{VectorizeBridge{T, F, S, G}},
model::MOI.ModelLike, g::G,
set::MOI.AbstractScalarSet) where {T, F, S, G}
set_constant = MOI.constant(set)
h = MOIU.operate(-, T, g, set_constant)
if -set_constant != MOI.constant(h)[1]
Expand Down