Skip to content
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

Allow querying conflicts from within JuMP #2300

Merged
merged 14 commits into from
Sep 7, 2020
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Calculus = "0.5"
DataStructures = "0.17"
ForwardDiff = "~0.5.0, ~0.6, ~0.7, ~0.8, ~0.9, ~0.10"
MathOptInterface = "~0.9.11"
MathOptInterface = "~0.9.14"
MutableArithmetics = "0.2"
NaNMath = "0.3"
julia = "1"
Expand Down
26 changes: 25 additions & 1 deletion docs/src/solutions.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ This function will return a `MOI.TerminationStatusCode` `enum`.
MOI.TerminationStatusCode
```

Additionally, we can receive a solver specific string explaning why the
Additionally, we can receive a solver specific string explaining why the
optimization stopped with [`raw_status`](@ref).

## Solution statuses
Expand Down Expand Up @@ -249,6 +249,21 @@ lp_objective_perturbation_range
lp_rhs_perturbation_range
```

## Conflicts

Sometimes, the model you input is infeasible, and some solvers can help you
dourouc05 marked this conversation as resolved.
Show resolved Hide resolved
find the cause of this infeasibility by offering a conflict, i.e. a subset of
dourouc05 marked this conversation as resolved.
Show resolved Hide resolved
the constraints that create this infeasibility.

The function [`compute_conflict!`](@ref) is used to start the computation of
odow marked this conversation as resolved.
Show resolved Hide resolved
dourouc05 marked this conversation as resolved.
Show resolved Hide resolved
a conflict. Once this process is finished, the attribute
[`MOI.ConflictStatus`](@ref) returns a [`MOI.ConflictStatusCode`](@ref).

If there is a conflict, you can query each constraint whether it participates
dourouc05 marked this conversation as resolved.
Show resolved Hide resolved
in the conflict or not using the attribute
[`MOI.ConstraintConflictStatus`](@ref), which returns a
[`MOI.ConflictParticipationStatusCode`](@ref).

dourouc05 marked this conversation as resolved.
Show resolved Hide resolved
## Multiple solutions

Some solvers support returning multiple solutions. You can check how many
Expand Down Expand Up @@ -295,3 +310,12 @@ JuMP.simplex_iterations
JuMP.barrier_iterations
JuMP.node_count
```

```@docs
JuMP.compute_conflict!
MOI.compute_conflict!
MOI.ConflictStatus
MOI.ConflictStatusCode
MOI.ConstraintConflictStatus
MOI.ConflictParticipationStatusCode
```
20 changes: 19 additions & 1 deletion src/optimizer_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ Optimize the model. If an optimizer has not been set yet (see

Keyword arguments `kwargs` are passed to the `optimize_hook`. An error is
thrown if `optimize_hook` is `nothing` and keyword arguments are provided.
```
"""
function optimize!(model::Model,
# TODO: Remove the optimizer_factory and bridge_constraints
Expand Down Expand Up @@ -144,6 +143,25 @@ function optimize!(model::Model,
return
end

"""
compute_conflict!(model::Model)

Compute a conflict if the model is infeasible. If an optimizer has not
been set yet (see [`set_optimizer`](@ref)), a [`NoOptimizer`](@ref)
error is thrown.

The status of the conflict can be checked with the `MOI.ConflictStatus`
model attribute. Then, the status for each constraint can be queried with
the `MOI.ConstraintConflictStatus` attribute.
"""
function compute_conflict!(model::Model)
if mode(model) != DIRECT && MOIU.state(backend(model)) == MOIU.NO_OPTIMIZER
throw(NoOptimizer())
end
MOI.compute_conflict!(backend(model))
return
end

"""
result_count(model::Model)

Expand Down
9 changes: 9 additions & 0 deletions test/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,15 @@ end
function test_copy_model_jump_auto()
copy_model_style_mode(true, MOIU.AUTOMATIC)
end

@testset "Conflict computation" begin
@testset "NoOptimizer()" begin
err = NoOptimizer()
model = Model()
@test_throws err compute_conflict!(model)
end
end

function test_copy_model_base_auto()
copy_model_style_mode(false, MOIU.AUTOMATIC)
end
Expand Down