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
21 changes: 21 additions & 0 deletions src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,26 @@ function MOI.get(
return bridge
end

# Needed to avoid an ambiguity with the getter for MOI.Constraint.AbstractBridge
function MOI.get(
model::MOI.ModelLike,
attr::MOI.ConstraintConflictStatus,
bridge::AbstractFunctionConversionBridge,
)
ret = MOI.NOT_IN_CONFLICT
for (F, S) in MOI.Bridges.added_constraint_types(typeof(bridge))
for ci in MOI.get(bridge, MOI.ListOfConstraintIndices{F,S}())
status = MOI.get(model, attr, ci)
if status == MOI.IN_CONFLICT
return status
elseif status == MOI.MAYBE_IN_CONFLICT
ret = status
end
end
end
return ret
end

function MOI.supports(
model::MOI.ModelLike,
attr::MOI.AbstractConstraintAttribute,
Expand Down Expand Up @@ -169,6 +189,7 @@ function invariant_under_function_conversion(
MOI.ConstraintPrimalStart,
MOI.ConstraintDual,
MOI.ConstraintDualStart,
MOI.ConstraintConflictStatus,
},
)
return true
Expand Down
24 changes: 24 additions & 0 deletions src/Bridges/bridge_optimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,11 @@ function MOI.optimize!(b::AbstractBridgeOptimizer)
return
end

function MOI.compute_conflict!(b::AbstractBridgeOptimizer)
MOI.compute_conflict!(b.model)
return
end

function MOI.is_empty(b::AbstractBridgeOptimizer)
return isempty(Variable.bridges(b)) &&
isempty(Constraint.bridges(b)) &&
Expand Down Expand Up @@ -1744,6 +1749,25 @@ function MOI.set(
return throw(MOI.SettingVariableIndexNotAllowed())
end

function MOI.get(
model::MOI.ModelLike,
attr::MOI.ConstraintConflictStatus,
bridge::AbstractBridge,
)
ret = MOI.NOT_IN_CONFLICT
for (F, S) in MOI.Bridges.added_constraint_types(typeof(bridge))
for ci in MOI.get(bridge, MOI.ListOfConstraintIndices{F,S}())
status = MOI.get(model, attr, ci)
if status == MOI.IN_CONFLICT
return status
elseif status == MOI.MAYBE_IN_CONFLICT
ret = status
end
end
end
return ret
end

## Getting and Setting names
function MOI.get(
b::AbstractBridgeOptimizer,
Expand Down
4 changes: 0 additions & 4 deletions src/Bridges/lazy_bridge_optimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,3 @@ function bridging_cost(b::LazyBridgeOptimizer, args...)
end

recursive_model(b::LazyBridgeOptimizer) = b

function MOI.compute_conflict!(model::LazyBridgeOptimizer)
return MOI.compute_conflict!(model.model)
end
16 changes: 16 additions & 0 deletions test/Bridges/Constraint/ScalarFunctionizeBridge.jl
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,22 @@ function test_supports_ScalarNonlinearFunction()
return
end

function test_issue_2838()
inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}())
model = MOI.Bridges.Constraint.ScalarFunctionize{Float64}(inner)
x = MOI.add_variable(model)
c = MOI.add_constraint(model, x, MOI.GreaterThan(1.0))
F, S = MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}
ci = only(MOI.get(inner, MOI.ListOfConstraintIndices{F,S}()))
for ret in (MOI.NOT_IN_CONFLICT, MOI.IN_CONFLICT, MOI.MAYBE_IN_CONFLICT)
MOI.set(inner, MOI.ConflictCount(), 1)
MOI.set(inner, MOI.ConstraintConflictStatus(), ci, ret)
MOI.compute_conflict!(model)
@test MOI.get(model, MOI.ConstraintConflictStatus(), c) == ret
end
return
end

end # module

TestConstraintFunctionize.runtests()
40 changes: 40 additions & 0 deletions test/Bridges/lazy_bridge_optimizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2288,6 +2288,46 @@ function test_wrong_coefficient_2()
return
end

MOI.Utilities.@model(
Model2838,
(),
(MOI.GreaterThan,),
(),
(),
(),
(MOI.ScalarAffineFunction,),
(),
()
)

function test_issue_2838()
inner = MOI.Utilities.MockOptimizer(Model2838{Float64}())
model = MOI.Bridges.full_bridge_optimizer(inner, Float64)
x = MOI.add_variables(model, 2)
f = MOI.Utilities.operate(vcat, Float64, (1.0 * x)...)
c = MOI.add_constraint(model, f, MOI.Nonnegatives(2))
F, S = MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}
ci = MOI.get(inner, MOI.ListOfConstraintIndices{F,S}())
function cmp(a, b)
if a == MOI.IN_CONFLICT || b == MOI.IN_CONFLICT
return MOI.IN_CONFLICT
elseif a == MOI.MAYBE_IN_CONFLICT || b == MOI.MAYBE_IN_CONFLICT
return MOI.MAYBE_IN_CONFLICT
else
return MOI.NOT_IN_CONFLICT
end
end
list = (MOI.NOT_IN_CONFLICT, MOI.IN_CONFLICT, MOI.MAYBE_IN_CONFLICT)
for a in list, b in list
MOI.set(inner, MOI.ConflictCount(), 1)
MOI.set(inner, MOI.ConstraintConflictStatus(), ci[1], a)
MOI.set(inner, MOI.ConstraintConflictStatus(), ci[2], b)
MOI.compute_conflict!(model)
@test MOI.get(model, MOI.ConstraintConflictStatus(), c) == cmp(a, b)
end
return
end

end # module

TestBridgesLazyBridgeOptimizer.runtests()
2 changes: 1 addition & 1 deletion test/General/attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ function test_attributes_integration_compute_conflict_2()
MOI.compute_conflict!(model)
@test MOI.get(model, MOI.ConflictStatus()) == MOI.CONFLICT_FOUND
@test MOI.get(model, MOI.ConflictCount()) == 1
@test_throws ArgumentError MOI.get(model, MOI.ConstraintConflictStatus(), c)
return
end

struct _NoConstraintName <: MOI.AbstractOptimizer end
Expand Down
Loading