@@ -1345,16 +1345,55 @@ end
13451345function MOI. supports (
13461346 b:: AbstractBridgeOptimizer ,
13471347 attr:: MOI.AbstractConstraintAttribute ,
1348- IndexType :: Type{MOI.ConstraintIndex{F,S}} ,
1348+ :: Type{MOI.ConstraintIndex{F,S}} ,
13491349) 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
13561388 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
13581397 end
13591398end
13601399
0 commit comments