Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions docs/src/manual/solutions.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,51 @@ non-global tree search solvers like
| Completed a non-global tree search (no solution found) | `LOCALLY_INFEASIBLE` | 0 | `NO_SOLUTION` | `NO_SOLUTION` |
| Iteration limit | `ITERATION_LIMIT` | 1 | * | * |
| Diverging iterates | `NORM_LIMIT` or `OBJECTIVE_LIMIT` | 1 | * | * |

## Querying solution attributes

Some solvers will not implement every solution attribute. Therefore, a call like
`MOI.get(model, MOI.SolveTimeSec())` may throw an [`UnsupportedAttribute`](@ref)
error.

If you need to write code that is agnostic to the solver (for example, you are
writing a library that an end-user passes their choice of solver to), you can
work-around this problem using a `try-catch`:
```julia
function get_solve_time(model)
try
return MOI.get(model, MOI.SolveTimeSec())
catch err
if err isa MOI.UnsupportedAttribute
return NaN # Solver doesn't support. Return a placeholder value.
end
rethrow(err) # Something else went wrong. Rethrow the error
end
end
```

If, _after careful profiling_, you find that the `try-catch` is taking a
significant portion of your runtime, you can improve performance by caching the
result of the `try-catch`:
```julia
mutable struct CachedSolveTime{M}
model::M
supports_solve_time::Bool
CachedSolveTime(model::M) where {M} = new(model, true)
end

function get_solve_time(model::CachedSolveTime)
if !model.supports_solve_time
return NaN
end
try
return MOI.get(model, MOI.SolveTimeSec())
catch err
if err isa MOI.UnsupportedAttribute
model.supports_solve_time = false
return NaN
end
rethrow(err) # Something else went wrong. Rethrow the error
end
end
```