-
Notifications
You must be signed in to change notification settings - Fork 92
Supports add constrained variable #1101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Supports add constrained variable #1101
Conversation
Had to add a fallback for now, when `supports_add_constrained_variable` is called with an `AbstractVectorSet`
Filtering `(F, S)` constraints for which `F` is not `VectorOfVariables` or `SingleVariable`
Default values for bridging costs in attributes.jl + using proper function when having to call supports_add_constrained_variable(s)
The implementation looks good, testing now :) |
I wrote a test for supports_add_constrained_variables since the indices of AbstractModel are not unique with constraints on AbstractScalarSet. Should I write my own model to be able to test that or is this test enough? |
dest = ReverseOrderConstrainedVariablesModel() | ||
index_map = MOI.copy_to(dest, src) | ||
@test typeof(c1) == typeof(dest.constraintIndices[1]) | ||
@test typeof(c2) == typeof(dest.constraintIndices[2]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now, if you run the test with dest = full_bridge_optimizer(ReverseOrderConstrainedVariablesModel(), Float64)
or dest = full_bridge_optimizer(OrderConstrainedVariablesModel(), Float64)
, I guess one of the two will fail as with the bridges they both support both constrained variables.
To fix this, we should implement the attribute for LazyBridgeOptimizer
and return the bridge cost.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what you meant here. Could you maybe write the corresponding test and I'd try to make it work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean something like
dest = OrderConstrainedVariablesModel()
bridged_dest = MOI.Bridges.full_bridge_optimizer(dest, Float64)
index_map = MOI.copy_to(bridged_dest, src)
@test typeof(c1) == typeof(dest.constraintIndices[2])
@test typeof(c2) == typeof(dest.constraintIndices[1])
dest = ReverseOrderConstrainedVariablesModel()
bridged_dest = MOI.Bridges.full_bridge_optimizer(dest, Float64)
index_map = MOI.copy_to(bridged_dest, src)
@test typeof(c1) == typeof(dest.constraintIndices[1])
@test typeof(c2) == typeof(dest.constraintIndices[2])
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By trying the following lines:
src = MOIU.Model{Float64}()
a, c1 = MOI.add_constrained_variables(src, MOI.Nonpositives(3))
c2 = MOI.add_constraint(src, a, MOI.Nonnegatives(3))
dest = OrderConstrainedVariablesModel()
bridged_dest = MOI.Bridges.full_bridge_optimizer(dest, Float64)
index_map = MOI.copy_to(bridged_dest, src)
I get an error stating MathOptInterface.UnsupportedConstraint{MathOptInterface.VectorOfVariables,MathOptInterface.Nonpositives}: MathOptInterface.VectorOfVariables-in-MathOptInterface.Nonpositives constraint is not supported by the model.
.
This is because no bridge of type ::Type{MathOptInterface.VectorOfVariables}, ::Type{MathOptInterface.Nonpositives}
exists in the LazyBridgeOptimizer.
I must say I did not really grasp how the bridge types work, and I'm not sure how I should go from here. Maybe that is why the issue was not tagged as a good first issue 😅
I tried implementing the attributes with:
MOI.get(b::LazyBridgeOptimizer, c::MOI.VariableBridgingCost{S}) where S<:MOI.AbstractScalarSet = MOI.get(b.model, c)
MOI.get(b::LazyBridgeOptimizer, c::MOI.VariableBridgingCost{S}) where S<:MOI.AbstractVectorSet = MOI.get(b.model, c)
function MOI.get(b::LazyBridgeOptimizer, c::MOI.ConstraintBridgingCost{F,S}) where {S <: MOI.AbstractSet, F <: MOI.AbstractFunction}
MOI.get(b.model, c)
end
But this did not work better, I think this shows how I don't actually understand how all of this works.
I am trying to tackle #987 with this PR.
As it's my first one, I am still trying to comprehend MOI's overall design and I am aware this PR still has a lot of flaws. I hope you guys will help me correct them.
Here is what issues I still have and where you guys could help me:
get(model, attr)
method in order to be able to give a default value to the newly created attributeVariableBridgingCost
. Not creating an intermediaryget_fallback
method resulted in method ambiguities since model-specific methods were already defined, such asMOI.get(mock::MockOptimizer, attr::MOI.AbstractModelAttribute)
. The issue here is that I still had to define a specific method for the CachingOptimizer, otherwise an error was thrown during the tests when no optimizer was attached (thrown there). I must find a way to get rid of those definitions.lazy_bridge_optimizer.jl
.copy.jl
, since theNLPBlock
assumes no change in the order of the variables, I didn't use any bridging cost for it, am I right?copy.jl
, the copying still takes the vector variables first. I did that to change as little as possible. Should we keep that?ConstraintBridgingCost
too, as @blegat first stated in [RFC] supports_constrained_variable #987, but I'm not sure how I should use it in thedefault_copy_to
function.attributes.jl
, the default values inmodel.jl
.That is a lot of questions, but I hope this PR will eventually be useful.
PS: For now, you can't really use this feature with JuMP, and we will eventually need to add this to JuMP.