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
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ function bridge_constraint(
) where {T}
fi_s = MOI.Utilities.scalarize(f)
if !iszero(imag(fi_s[1]))
error(
"The epigraph variable `t` in `[t; x] in NormInfinityCone()` " *
"must be real. It is: $(fi_s[1])",
)
msg = "The epigraph variable `t` in `[t; x] in NormInfinityCone()` must be real. It is: $(fi_s[1])"
throw(MOI.AddConstraintNotAllowed{typeof(f),typeof(s)}(msg))
end
t = real(fi_s[1])
cis = MOI.ConstraintIndex{MOI.VectorAffineFunction{T},MOI.SecondOrderCone}[]
Expand Down
9 changes: 4 additions & 5 deletions src/Bridges/Constraint/bridges/IndicatorToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -201,19 +201,18 @@ function _is_binary(model::MOI.ModelLike, x::MOI.VariableIndex)
end

function MOI.Bridges.final_touch(
bridge::IndicatorToMILPBridge{T,F},
bridge::IndicatorToMILPBridge{T,F,A,S},
model::MOI.ModelLike,
) where {T,F}
) where {T,F,A,S}
bounds = Dict{MOI.VariableIndex,NTuple{2,T}}()
scalars = collect(MOI.Utilities.eachscalar(bridge.f))
fi = scalars[2]
ret = MOI.Utilities.get_bounds(model, bounds, fi)
if ret === nothing
throw(MOI.Bridges.BridgeRequiresFiniteDomainError(bridge, fi))
elseif !_is_binary(model, scalars[1])
error(
"Unable to reformulate indicator constraint to a MILP. The indicator variable must be binary.",
)
msg = "Unable to reformulate indicator constraint to a MILP. The indicator variable must be binary."
throw(MOI.AddConstraintNotAllowed{F,MOI.Indicator{A,S}}(msg))
end
if bridge.slack === nothing
# This is the first time calling final_touch
Expand Down
5 changes: 1 addition & 4 deletions src/Bridges/Constraint/bridges/IntegerToZeroOneBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,10 +156,7 @@ function MOI.Bridges.final_touch(
if ret === bridge.last_bounds
return nothing # final_touch already called
elseif ret[1] == typemin(T) || ret[2] == typemax(T)
error(
"Unable to use IntegerToZeroOneBridge because the variable " *
"$(bridge.x) has a non-finite domain",
)
throw(MOI.Bridges.BridgeRequiresFiniteDomainError(bridge, bridge.x))
end
f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(T(1), bridge.x)], T(0))
lb, ub = ceil(Int, ret[1]), floor(Int, ret[2])
Expand Down
12 changes: 6 additions & 6 deletions src/Bridges/Constraint/bridges/QuadtoSOCBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -256,12 +256,12 @@ function _primal_start_or_error(model, attr, v)
var_attr = MOI.VariablePrimalStart()
value = MOI.get(model, MOI.VariablePrimalStart(), v)
if isnothing(value)
error(
"In order to set the `$attr`, the",
"`MOI.Bridges.Constraint.QuadtoSOCBridge` needs to get the ",
"`$var_attr` but it is not set. Set the `$var_attr` first before ",
"setting the `$attr` in order to fix this.",
)
msg =
"In order to set the `$attr`, the " *
"`MOI.Bridges.Constraint.QuadtoSOCBridge` needs to get the " *
"`$var_attr` but it is not set. Set the `$var_attr` first before " *
"setting the `$attr` in order to fix this."
throw(MOI.SetAttributeNotAllowed(attr, msg))
end
return value
end
Expand Down
11 changes: 4 additions & 7 deletions src/Bridges/Constraint/bridges/SplitIntervalBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -230,9 +230,8 @@ function MOI.get(
if bridge.upper !== nothing
return MOI.get(model, attr, bridge.upper)
end
return error(
"Cannot get `$attr` for a constraint in the interval `[-Inf, Inf]`.",
)
msg = "Cannot get `$attr` for a constraint in the interval `[-Inf, Inf]`."
return throw(MOI.GetAttributeNotAllowed(attr, msg))
end

function MOI.set(
Expand Down Expand Up @@ -333,10 +332,8 @@ function MOI.get(
# The only case where the interval `[-∞, ∞]` is allowed is for
# `VariableIndex` constraints but `ConstraintBasisStatus` is not
# defined for `VariableIndex` constraints.
error(
"Cannot get `$attr` for a constraint in the interval " *
"`[-Inf, Inf]`.",
)
msg = "Cannot get `$attr` for a constraint in the interval `[-Inf, Inf]`."
throw(MOI.GetAttributeNotAllowed(attr, msg))
end
return upper_stat
end
Expand Down
17 changes: 9 additions & 8 deletions src/Bridges/Objective/bridges/SlackBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,16 @@ function bridge_objective(
) where {T,F,G<:MOI.AbstractScalarFunction}
slack = MOI.add_variable(model)
f = MOI.Utilities.operate(-, T, func, slack)
if MOI.get(model, MOI.ObjectiveSense()) == MOI.MIN_SENSE
set = MOI.LessThan(zero(T))
elseif MOI.get(model, MOI.ObjectiveSense()) == MOI.MAX_SENSE
set = MOI.GreaterThan(zero(T))
sense = MOI.get(model, MOI.ObjectiveSense())
if sense == MOI.FEASIBILITY_SENSE
msg = "Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when using `MOI.Bridges.Objective.SlackBridge`."
throw(MOI.SetAttributeNotAllowed(MOI.ObjectiveFunction{G}(), msg))
end
set = if sense == MOI.MIN_SENSE
MOI.LessThan(zero(T))
else
error(
"Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when",
" using `MOI.Bridges.Objective.SlackBridge`.",
)
@assert sense == MOI.MAX_SENSE
MOI.GreaterThan(zero(T))
end
constraint = MOI.Utilities.normalize_and_add_constraint(model, f, set)
MOI.set(model, MOI.ObjectiveFunction{MOI.VariableIndex}(), slack)
Expand Down
9 changes: 4 additions & 5 deletions src/Bridges/Objective/bridges/VectorSlackBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -69,15 +69,14 @@ function bridge_objective(
)
sense = MOI.get(model, MOI.ObjectiveSense())
if sense == MOI.FEASIBILITY_SENSE
error(
"Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when",
" using `MOI.Bridges.Objective.VectorSlackBridge`.",
)
msg = "Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when using `MOI.Bridges.Objective.VectorSlackBridge`."
throw(MOI.SetAttributeNotAllowed(MOI.ObjectiveFunction{G}(), msg))
end
slacks = MOI.VectorOfVariables(variables[slacked_objectives])
f = if sense == MOI.MIN_SENSE
MOI.Utilities.operate(-, T, slacks, funcs[slacked_objectives])
elseif sense == MOI.MAX_SENSE
else
@assert sense == MOI.MAX_SENSE
MOI.Utilities.operate(-, T, funcs[slacked_objectives], slacks)
end
set = MOI.Nonnegatives(length(slacked_objectives))
Expand Down
34 changes: 15 additions & 19 deletions src/Bridges/bridge_optimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2032,49 +2032,45 @@ _check_double_single_variable(::AbstractBridgeOptimizer, ::Any, ::Any) = nothing

function MOI.add_constraint(
b::AbstractBridgeOptimizer,
f::MOI.AbstractFunction,
s::MOI.AbstractSet,
)
f::F,
s::S,
) where {F<:MOI.AbstractFunction,S<:MOI.AbstractSet}
if Variable.has_bridges(Variable.bridges(b))
if f isa MOI.VariableIndex
if F <: MOI.VariableIndex
if is_bridged(b, f)
if MOI.is_valid(
b,
MOI.ConstraintIndex{MOI.VariableIndex,typeof(s)}(f.value),
)
ci = MOI.ConstraintIndex{MOI.VariableIndex,S}(f.value)
if MOI.is_valid(b, ci)
# The other constraint could have been through a variable bridge.
error(
"Cannot add two `VariableIndex`-in-`$(typeof(s))`",
" on the same variable $(f).",
)
msg = "Cannot add two `VariableIndex`-in-`$S` on the same variable $f."
throw(MOI.AddConstraintNotAllowed{F,S}(msg))
end
BridgeType = Constraint.concrete_bridge_type(
constraint_scalar_functionize_bridge(b),
typeof(f),
typeof(s),
F,
S,
)
MOI.add_constraint(Variable.bridges(b), f, s)
return add_bridged_constraint(b, BridgeType, f, s)
end
elseif f isa MOI.VectorOfVariables
elseif F <: MOI.VectorOfVariables
if any(vi -> is_bridged(b, vi), f.variables)
BridgeType = Constraint.concrete_bridge_type(
constraint_vector_functionize_bridge(b),
typeof(f),
typeof(s),
F,
S,
)
return add_bridged_constraint(b, BridgeType, f, s)
end
else
f, s = bridged_constraint_function(b, f, s)
end
end
if is_bridged(b, typeof(f), typeof(s))
if is_bridged(b, F, S)
_check_double_single_variable(b, f, s)
# We compute `BridgeType` first as `concrete_bridge_type` calls
# `bridge_type` which might throw an `UnsupportedConstraint` error in
# which case, we do not want any modification to have been done
BridgeType = Constraint.concrete_bridge_type(b, typeof(f), typeof(s))
BridgeType = Constraint.concrete_bridge_type(b, F, S)
# `add_constraint` might throw an `UnsupportedConstraint` but no
# modification has been done in the previous line
return add_bridged_constraint(b, BridgeType, f, s)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ function test_imag_t()
f_x = (1.0 + 2.0im) * x[2] + (3.0 + 4.0im)
f = MOI.Utilities.operate(vcat, Complex{Float64}, f_t, f_x)
@test_throws(
ErrorException(
MOI.AddConstraintNotAllowed{typeof(f),MOI.NormInfinityCone}(
"The epigraph variable `t` in `[t; x] in NormInfinityCone()` " *
"must be real. It is: $f_t",
),
Expand Down
9 changes: 3 additions & 6 deletions test/Bridges/Constraint/IndicatorToMILPBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,10 @@ function test_runtests_error_not_binary()
model = MOI.Bridges.Constraint.IndicatorToMILP{Int}(inner)
x = MOI.add_variables(model, 2)
MOI.add_constraint(model, x[2], MOI.Interval(0, 4))
c = MOI.add_constraint(
model,
MOI.VectorOfVariables(x),
MOI.Indicator{MOI.ACTIVATE_ON_ZERO}(MOI.GreaterThan(2)),
)
set = MOI.Indicator{MOI.ACTIVATE_ON_ZERO}(MOI.GreaterThan(2))
c = MOI.add_constraint(model, MOI.VectorOfVariables(x), set)
@test_throws(
ErrorException(
MOI.AddConstraintNotAllowed{MOI.VectorOfVariables,typeof(set)}(
"Unable to reformulate indicator constraint to a MILP. The indicator variable must be binary.",
),
MOI.Bridges.final_touch(model),
Expand Down
5 changes: 1 addition & 4 deletions test/Bridges/Constraint/IntegerToZeroOneBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,7 @@ function test_finite_domain_error()
model = MOI.Bridges.Constraint.IntegerToZeroOne{Int}(inner)
x, _ = MOI.add_constrained_variable(model, MOI.Integer())
@test_throws(
ErrorException(
"Unable to use IntegerToZeroOneBridge because the variable " *
"$(x) has a non-finite domain",
),
MOI.Bridges.BridgeRequiresFiniteDomainError,
MOI.Bridges.final_touch(model),
)
return
Expand Down
5 changes: 2 additions & 3 deletions test/Bridges/Constraint/QuadtoSOCBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,8 @@ function test_qcp()
S = MOI.GreaterThan{Float64}
ci = first(MOI.get(bridged_mock, MOI.ListOfConstraintIndices{F,S}()))
for attr in [MOI.ConstraintPrimalStart(), MOI.ConstraintDualStart()]
err = ErrorException(
"In order to set the `$attr`, the`MOI.Bridges.Constraint.QuadtoSOCBridge` needs to get the `MathOptInterface.VariablePrimalStart()` but it is not set. Set the `MathOptInterface.VariablePrimalStart()` first before setting the `$attr` in order to fix this.",
)
msg = "In order to set the `$attr`, the `MOI.Bridges.Constraint.QuadtoSOCBridge` needs to get the `MathOptInterface.VariablePrimalStart()` but it is not set. Set the `MathOptInterface.VariablePrimalStart()` first before setting the `$attr` in order to fix this."
err = MOI.SetAttributeNotAllowed(attr, msg)
@test_throws err MOI.set(bridged_mock, attr, ci, 0.0)
end
return
Expand Down
5 changes: 1 addition & 4 deletions test/Bridges/Constraint/SplitIntervalBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -320,10 +320,7 @@ function _test_interval(
MOI.ConstraintPrimalStart(),
MOI.ConstraintBasisStatus(),
]
err = ErrorException(
"Cannot get `$attr` for a constraint " *
"in the interval `[-Inf, Inf]`.",
)
err = MOI.GetAttributeNotAllowed{typeof(attr)}
@test_throws err MOI.get(bridged_mock, attr, ci)
end
@test zero(T) == MOI.get(bridged_mock, MOI.ConstraintDualStart(), ci)
Expand Down
10 changes: 6 additions & 4 deletions test/Bridges/Objective/SlackBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ function test_SlackBridge_ObjectiveSense_error()
model = MOI.Bridges.Objective.Slack{Float64}(inner)
x = MOI.add_variable(model)
f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], 1.2)
attr = MOI.ObjectiveFunction{typeof(f)}()
@test_throws(
ErrorException(
"Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when" *
" using `MOI.Bridges.Objective.SlackBridge`.",
MOI.SetAttributeNotAllowed(
attr,
"Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when " *
"using `MOI.Bridges.Objective.SlackBridge`.",
),
MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f),
MOI.set(model, attr, f),
)
return
end
Expand Down
12 changes: 8 additions & 4 deletions test/Bridges/Objective/VectorSlackBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,11 +115,15 @@ function test_objective_sense_before_function()
model = MOI.Bridges.Objective.VectorSlack{Float64}(inner)
x = MOI.add_variable(model)
f = MOI.Utilities.operate(vcat, Float64, 1.0 * x, 1.0 * x)
err = ErrorException(
"Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when using " *
"`MOI.Bridges.Objective.VectorSlackBridge`.",
attr = MOI.ObjectiveFunction{typeof(f)}()
@test_throws(
MOI.SetAttributeNotAllowed(
attr,
"Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when " *
"using `MOI.Bridges.Objective.VectorSlackBridge`.",
),
MOI.set(model, attr, f),
)
@test_throws err MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
return
end

Expand Down
2 changes: 1 addition & 1 deletion test/Bridges/Variable/VectorizeBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ function test_exp3_with_add_constrained_variable_y()
@test MOI.get(bridged_mock, MOI.ConstraintDual(), ec) ≈
[-1.0, log(5) - 1, 1 / 5]

err = ErrorException(
err = MOI.AddConstraintNotAllowed{MOI.VariableIndex,MOI.LessThan{Float64}}(
"Cannot add two `VariableIndex`-in-`MathOptInterface.LessThan{Float64}`" *
" on the same variable MOI.VariableIndex(-1).",
)
Expand Down
Loading