-
Notifications
You must be signed in to change notification settings - Fork 80
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
Fix bug in setting a negative lower bound of a SOC constrained variable with add_constraints
#302
Fix bug in setting a negative lower bound of a SOC constrained variable with add_constraints
#302
Conversation
…ining a negative lower bound on the `t` variable of a SOC constraint by means of `add_constraints` (GreaterThan) silently corrupted the related `VariableInfo` object, but using `add_constraint` worked.
…d in the last commit. The bug is solved by reworking many methods to work correctly with batch/vector (that is where the bug appeared) and changing single-element methods to wrap arguments and call the batch/vector variant. This way there will exist no difference in behavior between single-element and batch methods.
This is quite complicated, and I'm not suggesting that you need to do this, but a better way might be to use jump-dev/MathOptInterface.jl#1046. Alternatively, we could implement the adding a Thoughts? I should also note, that we went away from wrapping everything in length-1 arrays, because people were using Gurobi.jl in a soft-realtime setting, and didn't want the extra allocations. |
Sincerely, I put a lot of effort on this, and I do not even use SOC constraints (I have learned about them doing this), so I do not think I have the hearth necessary to change the core of the solution, what do you think of a compromise? I get the dedicated single-element methods back without extra allocations, keep the new batch methods, and put comments on both to remember that future changes in one of them need to be replicated at the other. The vector/batch version of add_constraints already existed and was written to be optimized (i.e., do just one or two calls to the batch method of the Gurobi C API), it was just incorrectly written in this specific case, so I imagine there was demand for batch methods too. This way both user cases "pay allocations but do a single call to the API" and "do not pay allocations for single variables (or broadcasted/repeated calls)" are fulfilled. Everyone is happy (ok, I am sure it is not everyone, but this is the closest I can promise). I do not mind if someone changes how exactly SOC works in the future, but for now I would like this to be working to be able to push the PR I am truly interested into. |
So, if I understand the issue, the problem is that function _set_bounds(
model::Optimizer,
indices::Vector{MOI.ConstraintIndex{MOI.SingleVariable, S}},
sets::Vector{S}
) where {S}
lower_columns, lower_values = Int[], Float64[]
upper_columns, upper_values = Int[], Float64[]
for (c, s) in zip(indices, sets)
lower, upper = _bounds(s)
info = _info(model, c)
if lower !== nothing
if info.num_soc_constraints == 0
push!(lower_columns, info.column)
push!(lower_values, lower)
else
_set_variable_lower_bound(model, info, lower)
end
end
if upper !== nothing
push!(upper_columns, info.column)
push!(upper_values, upper)
end
end
if length(lower_columns) > 0
set_dblattrlist!(model.inner, "LB", lower_columns, lower_values)
end
if length(upper_columns) > 0
set_dblattrlist!(model.inner, "UB", upper_columns, upper_values)
end
_require_update(model)
end |
Yes, this also solves the bug (I tested with the commit that introduces the test). At cost of |
Yes. Test from the first commit. Then this instead of the second. Then you can make the bound caching PR :) |
Done. Should I wait it to be merged into master to make the PR from the master commit? I am kinda noobish in terms of git workflow. |
And you post a screenshot of the tests passing please? Probably easiest to wait for this to be merged to master, which I'll do if you confirm tests pass. |
The first commit adds a test uncovering a bug in SOC constraints. The bug was that defining a negative lower bound on the
t
variable of a SOC constraint by means ofadd_constraints
(batch version) silently corrupted the relatedVariableInfo
object, but usingadd_constraint
(single-variable version) worked.The second commit solves the bug by reworking many methods to work correctly with batch/vector (that is where the bug appeared) and changing single-element methods to wrap arguments and call the batch/vector variant. This way there will exist no difference in behavior between single-element and batch methods.
I know it is rude to ping specific people to review (specially in these times of Covid19), but if @odow could review it quickly, I can send a PR tomorrow for the caching of lower and upper bounds that we discussed last week. The bound cache PR was almost ready when I stumbled in this bug, and had to fix it first, before being able to get the caching to work. If the solution is rejected (or needs major changes) then my code for caching bounds would need to be rewritten and, consequently, I prefer to wait the review of this PR before sending the next PR.