-
-
Notifications
You must be signed in to change notification settings - Fork 399
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
Support TIME_LIMIT in is_solved_and_feasible #3915
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #3915 +/- ##
=======================================
Coverage 99.58% 99.58%
=======================================
Files 43 43
Lines 6059 6059
=======================================
Hits 6034 6034
Misses 25 25 ☔ View full report in Codecov by Sentry. |
I do not like this. Why I think users needing more details should use the statuses directly. I we end up adding it, I would certainly I prefer |
Don't change the semantics on my account. As long as the documentation is clear, I think this semantics is clean. Reflecting on my confusion. I think the root of the issue here is In the use-case I encountered, what I needed is an |
TIME_LIMIT seems like the one most commonly set by users who expect a solution. ITERATION_LIMIT can happen in interior point-type solvers and tends to indicate failure, not success. NODE_LIMIT and OBJECTIVE_LIMIT are up for debate.
Just define: has_values(model) = primal_status(model) == FEASIBLE_POINT We have Lines 1916 to 1951 in 99cdc4c
but it's not quite the same thing. |
Call conclusions were somewhat inconclusive. @ccoffrin suggested that he really needed only We also see value in "teaching" users that they need to analyze the statuses in more detail. This PR cannot be merged as-is. An alternative is: is_solved_and_feasible(model; allow_time_limit::Bool = false) but this doesn't help cases like with other limits like A second alternative is: is_solved_and_feasible(model; allowed_termination_status = [OPTIMAL, LOCALLY_INFEASIBLE])
is_solved_and_feasible(model; allowed_termination_status = [OPTIMAL, LOCALLY_INFEASIBLE, TIME_LIMIT]) but this requires the user to know the various statuses, and it's a bit cumbersome. And something like this is painful: is_solved_and_feasible(model; additionally_allowed_termination_status = [TIME_LIMIT]) One option is: if is_solved_and_feasible(model) ||
(termination_status(model) == TIME_LIMIT && primal_status(model) == FEASIBLE_POINT)
# ...
end @blegat also sugggested if (is_solved(model) || termination_status(model) == TIME_LIMIT) && is_feasible(model)
# ...
end But this is just adding more complexity when at this point the user really needs to write proper logic for handling the statuses. Yes, this means duplicated code, but that's not the end of the world because it makes things very clear about what is allowed etc. We have https://jump.dev/JuMP.jl/stable/manual/solutions/#Recommended-workflow, which I think stands up pretty well. |
Perhaps this PR can just be closed. #3925 tweaks the docstring of |
src/optimizer_interface.jl
Outdated
@@ -808,29 +808,52 @@ end | |||
model::GenericModel; | |||
allow_local::Bool = true, | |||
allow_almost::Bool = false, | |||
allow_time_limit::Bool = false, |
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 would prefer a list of accepted statuses instead of more keywords
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.
Suggested name for the keyword?
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.
allow_status = ()
, and I would suggest a tuple since it is non-allocating. But accepting any collection that work with in
should be fine
src/optimizer_interface.jl
Outdated
@@ -858,14 +884,16 @@ function is_solved_and_feasible( | |||
dual::Bool = false, | |||
allow_local::Bool = true, | |||
allow_almost::Bool = false, | |||
additional_termination_statuses::Vector{TerminationStatusCode} = TerminationStatusCode[], |
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 do not see a reason to force a Vector, we should at least allow tuples.
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 really want to minimise the number of input types we support. This is part of the MethodError principle. Is there a good argument not to restrict to Vector
? The allocations here are minimal, and checking this status should be so minor in comparison to solving the problem.
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.
additional_termination_statuses::Vector{TerminationStatusCode} = TerminationStatusCode[], | |
additional_termination_statuses::Union{ | |
Vector{TerminationStatusCode}, | |
NTuple{N,TerminationStatusCode}} = (), |
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.
The Method error should be very clear with this suggestion. No weird tuples would be allowed.
Allocations are minimal, but there is no reason for them. Minimal allocations in a loop become big allocations.
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.
Who's calling this in a loop? And if they are, they cache the vector once outside the loop.
I'm also somewhat in favor of just closing this PR and leaving the behavior as-is for now. |
Closing for now. I'll make a mental note to re-open this if the question comes up again in the future. And if you, reader from the future, are interested in this feature, please comment below and I will re-open. |
Originally added in #3668, doesn't look like we discussed
TIME_LIMIT
.But this came up last year in a discussion I had with Simon Bowly, where I thought we did support
TIME_LIMIT
.And then @ccoffrin just asked me about it as well.
I tend to think that most people who set a time limit and get given a feasible solution would say that
is_solved_and_feasible
istrue
.If we decide to add, there's an open question whether we should fold this into
allow_local
, or whether we add a newallow_time_limit
kwarg.