Skip to content

Commit 4dfcec3

Browse files
authored
[Bridges] add support for querying ConstraintConflictStatus (#2839)
1 parent 14d5af5 commit 4dfcec3

File tree

6 files changed

+102
-5
lines changed

6 files changed

+102
-5
lines changed

src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,26 @@ function MOI.get(
5151
return bridge
5252
end
5353

54+
# Needed to avoid an ambiguity with the getter for MOI.Constraint.AbstractBridge
55+
function MOI.get(
56+
model::MOI.ModelLike,
57+
attr::MOI.ConstraintConflictStatus,
58+
bridge::AbstractFunctionConversionBridge,
59+
)
60+
ret = MOI.NOT_IN_CONFLICT
61+
for (F, S) in MOI.Bridges.added_constraint_types(typeof(bridge))
62+
for ci in MOI.get(bridge, MOI.ListOfConstraintIndices{F,S}())
63+
status = MOI.get(model, attr, ci)
64+
if status == MOI.IN_CONFLICT
65+
return status
66+
elseif status == MOI.MAYBE_IN_CONFLICT
67+
ret = status
68+
end
69+
end
70+
end
71+
return ret
72+
end
73+
5474
function MOI.supports(
5575
model::MOI.ModelLike,
5676
attr::MOI.AbstractConstraintAttribute,
@@ -169,6 +189,7 @@ function invariant_under_function_conversion(
169189
MOI.ConstraintPrimalStart,
170190
MOI.ConstraintDual,
171191
MOI.ConstraintDualStart,
192+
MOI.ConstraintConflictStatus,
172193
},
173194
)
174195
return true

src/Bridges/bridge_optimizer.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,11 @@ function MOI.optimize!(b::AbstractBridgeOptimizer)
368368
return
369369
end
370370

371+
function MOI.compute_conflict!(b::AbstractBridgeOptimizer)
372+
MOI.compute_conflict!(b.model)
373+
return
374+
end
375+
371376
function MOI.is_empty(b::AbstractBridgeOptimizer)
372377
return isempty(Variable.bridges(b)) &&
373378
isempty(Constraint.bridges(b)) &&
@@ -1744,6 +1749,25 @@ function MOI.set(
17441749
return throw(MOI.SettingVariableIndexNotAllowed())
17451750
end
17461751

1752+
function MOI.get(
1753+
model::MOI.ModelLike,
1754+
attr::MOI.ConstraintConflictStatus,
1755+
bridge::AbstractBridge,
1756+
)
1757+
ret = MOI.NOT_IN_CONFLICT
1758+
for (F, S) in MOI.Bridges.added_constraint_types(typeof(bridge))
1759+
for ci in MOI.get(bridge, MOI.ListOfConstraintIndices{F,S}())
1760+
status = MOI.get(model, attr, ci)
1761+
if status == MOI.IN_CONFLICT
1762+
return status
1763+
elseif status == MOI.MAYBE_IN_CONFLICT
1764+
ret = status
1765+
end
1766+
end
1767+
end
1768+
return ret
1769+
end
1770+
17471771
## Getting and Setting names
17481772
function MOI.get(
17491773
b::AbstractBridgeOptimizer,

src/Bridges/lazy_bridge_optimizer.jl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,3 @@ function bridging_cost(b::LazyBridgeOptimizer, args...)
607607
end
608608

609609
recursive_model(b::LazyBridgeOptimizer) = b
610-
611-
function MOI.compute_conflict!(model::LazyBridgeOptimizer)
612-
return MOI.compute_conflict!(model.model)
613-
end

test/Bridges/Constraint/ScalarFunctionizeBridge.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,22 @@ function test_supports_ScalarNonlinearFunction()
378378
return
379379
end
380380

381+
function test_issue_2838()
382+
inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}())
383+
model = MOI.Bridges.Constraint.ScalarFunctionize{Float64}(inner)
384+
x = MOI.add_variable(model)
385+
c = MOI.add_constraint(model, x, MOI.GreaterThan(1.0))
386+
F, S = MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}
387+
ci = only(MOI.get(inner, MOI.ListOfConstraintIndices{F,S}()))
388+
for ret in (MOI.NOT_IN_CONFLICT, MOI.IN_CONFLICT, MOI.MAYBE_IN_CONFLICT)
389+
MOI.set(inner, MOI.ConflictCount(), 1)
390+
MOI.set(inner, MOI.ConstraintConflictStatus(), ci, ret)
391+
MOI.compute_conflict!(model)
392+
@test MOI.get(model, MOI.ConstraintConflictStatus(), c) == ret
393+
end
394+
return
395+
end
396+
381397
end # module
382398

383399
TestConstraintFunctionize.runtests()

test/Bridges/lazy_bridge_optimizer.jl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,6 +2288,46 @@ function test_wrong_coefficient_2()
22882288
return
22892289
end
22902290

2291+
MOI.Utilities.@model(
2292+
Model2838,
2293+
(),
2294+
(MOI.GreaterThan,),
2295+
(),
2296+
(),
2297+
(),
2298+
(MOI.ScalarAffineFunction,),
2299+
(),
2300+
()
2301+
)
2302+
2303+
function test_issue_2838()
2304+
inner = MOI.Utilities.MockOptimizer(Model2838{Float64}())
2305+
model = MOI.Bridges.full_bridge_optimizer(inner, Float64)
2306+
x = MOI.add_variables(model, 2)
2307+
f = MOI.Utilities.operate(vcat, Float64, (1.0 * x)...)
2308+
c = MOI.add_constraint(model, f, MOI.Nonnegatives(2))
2309+
F, S = MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}
2310+
ci = MOI.get(inner, MOI.ListOfConstraintIndices{F,S}())
2311+
function cmp(a, b)
2312+
if a == MOI.IN_CONFLICT || b == MOI.IN_CONFLICT
2313+
return MOI.IN_CONFLICT
2314+
elseif a == MOI.MAYBE_IN_CONFLICT || b == MOI.MAYBE_IN_CONFLICT
2315+
return MOI.MAYBE_IN_CONFLICT
2316+
else
2317+
return MOI.NOT_IN_CONFLICT
2318+
end
2319+
end
2320+
list = (MOI.NOT_IN_CONFLICT, MOI.IN_CONFLICT, MOI.MAYBE_IN_CONFLICT)
2321+
for a in list, b in list
2322+
MOI.set(inner, MOI.ConflictCount(), 1)
2323+
MOI.set(inner, MOI.ConstraintConflictStatus(), ci[1], a)
2324+
MOI.set(inner, MOI.ConstraintConflictStatus(), ci[2], b)
2325+
MOI.compute_conflict!(model)
2326+
@test MOI.get(model, MOI.ConstraintConflictStatus(), c) == cmp(a, b)
2327+
end
2328+
return
2329+
end
2330+
22912331
end # module
22922332

22932333
TestBridgesLazyBridgeOptimizer.runtests()

test/General/attributes.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ function test_attributes_integration_compute_conflict_2()
146146
MOI.compute_conflict!(model)
147147
@test MOI.get(model, MOI.ConflictStatus()) == MOI.CONFLICT_FOUND
148148
@test MOI.get(model, MOI.ConflictCount()) == 1
149-
@test_throws ArgumentError MOI.get(model, MOI.ConstraintConflictStatus(), c)
149+
return
150150
end
151151

152152
struct _NoConstraintName <: MOI.AbstractOptimizer end

0 commit comments

Comments
 (0)