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

Convention for primal/dual objective value? #2593

Closed
mtanneau opened this issue Dec 12, 2024 · 6 comments
Closed

Convention for primal/dual objective value? #2593

mtanneau opened this issue Dec 12, 2024 · 6 comments

Comments

@mtanneau
Copy link
Contributor

This is more of a convention/documentation question than a bug.
I am little confused (as a user and as a solver developer) as to how primal/dual objective values should be interpreted when problems are infeasible / unbounded.

Question: if a primal/dual solution is a ray, is there a JuMP-level convention on the meaning of objective_value and dual_objective_value?

The table below presents the output of a few solvers for the (unbounded) problem $min_{x} { x }$ (see code below for reproducing this table). Note that this problem is primal unbounded / dual infeasible.

solver termination status primal status dual status objective_value dual_objective_value
Gurobi DUAL_INFEASIBLE INFEASIBILITY_CERTIFICATE NO_SOLUTION -1.000e+00 -1.000e+100
HiGHS DUAL_INFEASIBLE FEASIBLE_POINT INFEASIBLE_POINT +0.000e+00 +0.000e+00
Mosek DUAL_INFEASIBLE INFEASIBILITY_CERTIFICATE NO_SOLUTION -1.000e+00 +0.000e+00
Ipopt NORM_LIMIT FEASIBLE_POINT UNKNOWN_RESULT_STATUS -1.834e+20 +0.000e+00
Clarabel DUAL_INFEASIBLE INFEASIBILITY_CERTIFICATE INFEASIBLE_POINT -1.000e+10 +0.000e+00
Tulip DUAL_INFEASIBLE INFEASIBILITY_CERTIFICATE UNKNOWN_RESULT_STATUS -Inf -Inf

using Printf
using JuMP
using Clarabel, Gurobi, HiGHS, Ipopt, Mosek, MosekTools, Tulip

model = Model()
@variable(model, x)
@objective(model, Min, x)

# Disable presolve to avoid early termination with unclear status
grb = MOI.OptimizerWithAttributes(Gurobi.Optimizer, "Presolve" => 0)

# Grab statuses and objective values
for opt in [grb, HiGHS.Optimizer, Mosek.Optimizer, Ipopt.Optimizer, Clarabel.Optimizer, Tulip.Optimizer]
    set_optimizer(model, opt)
    set_silent(model)
    optimize!(model)
    
    tst = termination_status(model)
    pst = primal_status(model)
    dst = dual_status(model)
    
    zp = try objective_value(model) catch err NaN end
    zd = try dual_objective_value(model) catch err NaN end
    s = solver_name(model)
    
    @printf "| %16s | %20s | %28s | %28s | %+8.3e | %+8.3e \n" s tst pst dst zp zd
end
@odow
Copy link
Member

odow commented Dec 12, 2024

See https://jump.dev/MathOptInterface.jl/stable/background/infeasibility_certificates/#Unbounded-problems

Tulip is the only solver that return a clearly "wrong" objective value. We'd need to look at the ray in Clarabel to see if it was wrong.

The dual objective value can be anything, because no solver claims to have found a dual solution. HiGHS and Clarabel should probably return the dual objective of their dual infeasible point. But that's arguably undefined behavior.

@blegat
Copy link
Member

blegat commented Dec 12, 2024

HiGHS and Clarabel should probably return the dual objective of their dual infeasible point. But that's arguably undefined behavior.

I'd say they should yet. The dual objective value is just the objective evaluated at the point. The fact that it's infeasible is irrelevant.

The only gotcha is that if it's a ray then the constant in the objective shouldn't be taken into account.

@mtanneau
Copy link
Contributor Author

mtanneau commented Dec 12, 2024

See https://jump.dev/MathOptInterface.jl/stable/background/infeasibility_certificates/#Unbounded-problems

That's what I was looking for, thanks!

Tulip is the only solver that return a clearly "wrong" objective value

That is because the person who coded this thought that ObjectiveValue should return the optimal value of the problem (which is infinite for infeasible/unbounded problems), not the objective value of the infeasibility ray (which is finite). 🙃

We'd need to look at the ray in Clarabel to see if it was wrong.

Primal solution values:

  • HiGHS: value(x) evaluates to 0.0. Note that HiGHS identifies that the problem is unbounded, but does not return an unbounded ray.
  • Ipopt: value(x) evaluates to a large negative value, same as the primal objective value reported in the table above.
  • All other solvers: value(x) evaluates to -1.0. Tulip and Clarabel have a behavior that's not consistent with the expected behavior.

@odow
Copy link
Member

odow commented Dec 16, 2024

Note that HiGHS identifies that the problem is unbounded, but does not return an unbounded ray.

This should change in the next release of HiGHS 😄

@odow
Copy link
Member

odow commented Dec 16, 2024

Closing because this is documented and tested at the MOI level.

Tulip explicitly excludes the relevant tests:
https://github.com/ds4dm/Tulip.jl/blob/f3df04d8f88cdf2466b886d117e8d28ca537b4a1/test/Interfaces/MOI_wrapper.jl#L32-L34

@odow odow closed this as completed Dec 16, 2024
@mtanneau
Copy link
Contributor Author

Tulip explicitly excludes the relevant tests

Thanks! I'll update Tulip to fix that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants