Hello everyone,

I stumbled on a potential bug in JuMP and its dependencies, however, I wanted to ask this question here first as I am unsure whether this intended behavior and (if not) on which library level this should be repaired.

For reference, I used the following library versions:

GLPK v1.1.3

Gurobi v1.0.2

JuMP v1.19.0

(all examples below assume `using JuMP, GLPK, Gurobi`

)

I observed that there are cases where calling `value(x)`

for a variable `x`

of an **infeasible** model will not throw an error but return some value.

For example, in the case of GLPK this behaviour can be triggered as follows:

```
model = Model(GLPK.Optimizer)
# Create variable x in [-1,1]
@variable(model, -1 <= x <= 1)
# Add constraint that x>=2 (Problem is thus infeasible)
@constraint(model, x >= 2)
optimize!(model)
@assert termination_status(model) == MOI.INFEASIBLE
# This should throw an error but instead returns an error
println(value(x))
```

Obviously, this mistake can be avoided by first checking `has_values(model)`

which correctly tells me that now model assignment exists, but to me it feels wrong that `value`

returns something other than an error â€“ especially given `value`

is only supposed to provide *primal* values.

We can compare this to the behavior of Gurobi on the same problem which produces an error for the same problem:

```
model = Model(Gurobi.Optimizer)
@variable(model, -1 <= x <= 1)
@constraint(model, x >= 2)
optimize!(model)
@assert termination_status(model) == MOI.INFEASIBLE
# This throws an error:
println(value(x))
```

At first, I thought this was therefore only a problem with GLPK, but then I managed to track it to the different outcomes for `MOI.get(model, MOI.ResultCount())`

between the two models: GLPK returns `1`

for this call as it has an infeasibility certificate.

Since `MOI.check_result_index_bounds`

uses `MOI.ResultCount()`

to check if there exists a result, this function does not throw an error and makes it so that `value`

returns something.

On the other hand, ` MOI.get(model, MOI.ResultCount())`

returns `0`

for Gurobi (this problem was solved by Gurobiâ€™s presolve without an infeasibility certificate) and consequently `MOI.check_result_index_bounds`

throws an error.

As a consequence, when we deactivate Gurobiâ€™s presolve (thus ensuring that Gurobi has an infeasibilty certificate) we also get a value from Gurobi:

```
model = Model(Gurobi.Optimizer)
# Deactivate Presolve -> ensures we get an infeasibility certificate
set_attribute(model, "Presolve", 0)
@variable(model, -1 <= x <= 1)
@constraint(model, x >= 2)
optimize!(model)
@assert termination_status(model) == MOI.INFEASIBLE
# This no longer throws an error:
println(value(x))
# Because we now have a positive result count:
@assert MOI.get(model, MOI.ResultCount()) >0
@assert model.moi_backend.optimizer.model.has_infeasibility_cert
```

This leaves me with the following questions:

**Should value be returning values for variables when the problem is infeasible?**

If yes: What is the meaning of those values?

If no: On which level should this be fixed?

- MOIâ€™s
`check_result_index_bounds`

currently calls`get(model, ResultCount())`

maybe thereâ€™s a better way to perform this check? - One could fix . the invocations of
`check_result_index_bounds`

in the individual solver libraries, but this seems like a lot of changes would be necessary and I am not sure which other libraries might have the same issue - One could introduce a check earlier up in the chain (e.g. checking for
`has_values`

upon an invocation of`value`

So far Iâ€™ve only been a JuMP user, so I have not that much knowledge about the inner workings of JuMP. Thus, I thought it best to ask on here which option (if any) is the best way forward.

Thanks in advance,

Samuel