Skip to content

Commit

Permalink
Support TIME_LIMIT in is_solved_and_feasible
Browse files Browse the repository at this point in the history
  • Loading branch information
odow committed Jan 28, 2025
1 parent 3b98ac1 commit cfbf1aa
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 7 deletions.
37 changes: 30 additions & 7 deletions src/optimizer_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -808,6 +808,7 @@ end
model::GenericModel;
allow_local::Bool = true,
allow_almost::Bool = false,
allow_time_limit::Bool = false,
dual::Bool = false,
result::Int = 1,
)
Expand All @@ -817,30 +818,50 @@ Return `true` if:
* the [`termination_status`](@ref) is one of:
* [`OPTIMAL`](@ref) (the solver found a global optimum)
* [`LOCALLY_SOLVED`](@ref) (the solver found a local optimum, which may also
be the global optimum, but the solver could not prove so).
be the global optimum, but the solver could not prove so)
* [`TIME_LIMIT`](@ref) (the solver stopped after a user-specified computation
time).
* the [`primal_status`](@ref) of the result index `result` is `FEASIBLE_POINT`.
This function is conservative, in that it returns `false` for situations like
the solver terminating with a feasible solution due to a time limit.
If this function returns `false`, use [`termination_status`](@ref),
[`result_count`](@ref), [`primal_status`](@ref) and [`dual_status`](@ref) to
understand what solutions are available (if any).
See also: [`assert_is_solved_and_feasible`](@ref).
## Keyword arguments
### `allow_local`
If `allow_local = false`, then this function returns `true` only if the
[`termination_status`](@ref) is [`OPTIMAL`](@ref).
### `allow_almost`
If `allow_almost = true`, then the [`termination_status`](@ref) may additionally
be [`ALMOST_OPTIMAL`](@ref) or [`ALMOST_LOCALLY_SOLVED`](@ref) (if `allow_local`),
and the [`primal_status`](@ref) and [`dual_status`](@ref) may additionally be
[`NEARLY_FEASIBLE_POINT`](@ref).
If `dual`, additionally use [`dual_status`](@ref) to check that a dual feasible
point is available.
### `allow_time_limit`
If this function returns `false`, use [`termination_status`](@ref),
[`result_count`](@ref), [`primal_status`](@ref) and [`dual_status`](@ref) to
understand what solutions are available (if any).
If `allow_time_limit = true`, then the [`termination_status`](@ref) may
additionally be [`TIME_LIMIT`](@ref) (the solver stopped after a user-specified
computation time).
### `dual`
If `dual`, additionally check that an optimal dual solution is available via
[`dual_status`](@ref). The `allow_` keywords control both the primal and dual
solutions.
### `result`
The index of the result to query. This value is passed to the `result` keyword
arguments of [`primal_status`](@ref) and [`dual_status`](@ref)
## Example
Expand All @@ -858,14 +879,16 @@ function is_solved_and_feasible(
dual::Bool = false,
allow_local::Bool = true,
allow_almost::Bool = false,
allow_time_limit::Bool = false,
result::Int = 1,
)
status = termination_status(model)
ret =
(status == OPTIMAL) ||
(allow_local && (status == LOCALLY_SOLVED)) ||
(allow_almost && (status == ALMOST_OPTIMAL)) ||
(allow_almost && allow_local && (status == ALMOST_LOCALLY_SOLVED))
(allow_almost && allow_local && (status == ALMOST_LOCALLY_SOLVED)) ||
(allow_time_limit && (status == TIME_LIMIT))
if ret
primal = primal_status(model; result)
ret &=
Expand Down
3 changes: 3 additions & 0 deletions test/test_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1254,6 +1254,7 @@ function test_is_solved_and_feasible()
MOI.ALMOST_OPTIMAL,
MOI.ALMOST_LOCALLY_SOLVED,
MOI.TIME_LIMIT,
MOI.OTHER_ERROR,
]
_global = term == MOI.OPTIMAL
has_local = _global || (term == MOI.LOCALLY_SOLVED)
Expand All @@ -1272,6 +1273,8 @@ function test_is_solved_and_feasible()
MOI.set(mock, MOI.PrimalStatus(), primal)
MOI.set(mock, MOI.DualStatus(), dual)
@test is_solved_and_feasible(model) == (has_local && _primal)
@test is_solved_and_feasible(model; allow_time_limit = true) ==
(has_local && _primal) || (term == MOI.TIME_LIMIT)
@test is_solved_and_feasible(model; dual = true) ==
(has_local && _primal && _dual)
@test is_solved_and_feasible(model; allow_local = false) ==
Expand Down

0 comments on commit cfbf1aa

Please sign in to comment.