@@ -1345,16 +1345,55 @@ end
1345
1345
function MOI. supports (
1346
1346
b:: AbstractBridgeOptimizer ,
1347
1347
attr:: MOI.AbstractConstraintAttribute ,
1348
- IndexType :: Type{MOI.ConstraintIndex{F,S}} ,
1348
+ :: Type{MOI.ConstraintIndex{F,S}} ,
1349
1349
) where {F,S}
1350
- if is_bridged (b, F, S)
1351
- bridge = Constraint. concrete_bridge_type (b, F, S)
1352
- return MOI. supports (recursive_model (b), attr, bridge)
1353
- elseif F == MOI. Utilities. variable_function_type (S) && is_bridged (b, S)
1354
- bridge = Variable. concrete_bridge_type (b, S)
1355
- return MOI. supports (recursive_model (b), attr, bridge)
1350
+ # !!! warning
1351
+ # This function is slightly confusing, because we need to account for
1352
+ # the different ways in which a constraint might be added.
1353
+ if F == MOI. Utilities. variable_function_type (S)
1354
+ # These are VariableIndex and VectorOfVariable constraints.
1355
+ if is_bridged (b, S)
1356
+ # If S needs to be bridged, it usually means that either there is a
1357
+ # variable bridge, or that there is a free variable followed by a
1358
+ # constraint bridge (i.e., the two cases handled below).
1359
+ #
1360
+ # However, it might be the case, like the tests in
1361
+ # Variable/flip_sign.jl, that the model supports F-in-S constraints,
1362
+ # but force-bridges S sets. If so, we might be in the unusual
1363
+ # situation where we support the attribute if the index was added
1364
+ # via add_constraint, but not if it was added via
1365
+ # add_constrained_variable. Because MOI lacks the ability to tell
1366
+ # which happened just based on the type, we're going to default to
1367
+ # asking the variable bridge, at the risk of a false negative.
1368
+ if is_variable_bridged (b, S)
1369
+ bridge = Variable. concrete_bridge_type (b, S)
1370
+ return MOI. supports (recursive_model (b), attr, bridge)
1371
+ else
1372
+ bridge = Constraint. concrete_bridge_type (b, F, S)
1373
+ return MOI. supports (recursive_model (b), attr, bridge)
1374
+ end
1375
+ else
1376
+ # If S doesn't need to be bridged, it usually means that either the
1377
+ # solver supports add_constrained_variable, or it supports free
1378
+ # variables and add_constraint.
1379
+ #
1380
+ # In some cases, it might be that the solver supports
1381
+ # add_constrained_variable, but ends up bridging add_constraint.
1382
+ # Because MOI lacks the ability to tell which one was called based
1383
+ # on the index type, asking the model might give a false negative
1384
+ # (we support the attribute via add_constrained_variable, but the
1385
+ # bridge doesn't via add_constraint because it will be bridged).
1386
+ return MOI. supports (b. model, attr, MOI. ConstraintIndex{F,S})
1387
+ end
1356
1388
else
1357
- return MOI. supports (b. model, attr, IndexType)
1389
+ # These are normal add_constraints, so we just check if they are
1390
+ # bridged.
1391
+ if is_bridged (b, F, S)
1392
+ bridge = Constraint. concrete_bridge_type (b, F, S)
1393
+ return MOI. supports (recursive_model (b), attr, bridge)
1394
+ else
1395
+ return MOI. supports (b. model, attr, MOI. ConstraintIndex{F,S})
1396
+ end
1358
1397
end
1359
1398
end
1360
1399
0 commit comments