Lagrange multipliers (duals) in JuMP 0.19

I have Julia 1.1.1 and JuMP 0.19. I am solving a concave maximization problem with linear constraints with Ipopt. I am confused with what is happening to the signs of the Lagrange multipliers:

The correct multipliers are

[0.20964, -0.0655815]
[2.39447, 2.21215, 2.64144, 2.58729, -1.37699e-6]

where the first vector is corresponds to equality constraints, the second to inequalities (all inequalities are in the form <= ).

If I use dual(), I get these vectors:

[-0.209641, 0.0655802]
[-2.39447, -2.21215, -2.64144, -2.58729, 4.53964e-9]

And if I use shadow_price() I get

[0.209641, 0.0655802]
[2.39447, 2.21215, 2.64144, 2.58729, -4.53964e-9]

I’ve read the documentation a few times, but I find it less than clear, and I still don’t understand what’s happening.
My provisional conclusion is that I should be using the negatives of the duals.
Is this because I’m maximizing? And what about the shadow_prices?

The correct multipliers are

Correct according to which definition ? We use the following definition: Manual · MathOptInterface
The dual does not depend on the objective sense (you can imagine it to be minimization) which is very useful when writing solver wrappers as you can swap the objective without having to worry about changing the dual.
You can see in the manual that the dual of a <= constraint (22) is a nonpositive variable (27) so what Ipopt returns makes sense.

My definition of “correct” is the textbook definition of the multipliers as sensitivity parameters. So with maximizing an objective and inequalities of the form <=, the corresponding multipliers should be >= 0.
I understand that JuMP doesn’t use the textbook definition, and I’m ok with that, as long as I understand what the proper “conversion” is. That’s why I asked if the negative of the dual is the right thing.

My definition of “correct” is the textbook definition of the multipliers as sensitivity parameters

Then the shadow_price should be what you are looking for, the difference in sign for the second equality constraint might be due to the following in JuMP doc: Constraints · JuMP

  • Relaxation of equality constraints (and hence the shadow price) is defined based on which sense of the equality constraint is active.

Yes, thanks, I had noticed that remark in the documentation.
But how do I find out which direction of the equality constraint is active?

See:

julia> using JuMP, Gurobi

julia> model = Model(with_optimizer(Gurobi.Optimizer, OutputFlag=0));
Academic license - for non-commercial use only

julia> @variable(model, x)
x

julia> @constraint(model, con, x == 2)
 con : x = 2.0

julia> @objective(model, Min, x)
x

julia> optimize!(model)
Academic license - for non-commercial use only

julia> shadow_price(con)
-1.0

julia> @objective(model, Max, x)
x

julia> optimize!(model)

julia> shadow_price(con)
1.0

For a fixed problem, the correct multiplier for an equality constraint (according to the defn. I gave) can have either sign.
So it can’t be determined just by whether you’re minimizing or maximizing, which I think is what you are proposing.

What you need seems to be either dual if you are minimizing or -dual if you are maximizing. This is what shadow_price does except that shadow_price also does a correction for equality you don’t need so just use dual and multiply it by -1 if you are maximizing.

Yes, I’ve concluded the same thing. It would be very helpful if the documentation were better as far as this point is concerned …

It would be very helpful if the documentation were better as far as this point is concerned …

You can help edit the documentation!

  1. Go to https://github.com/JuliaOpt/JuMP.jl/blob/master/docs/src/constraints.md
  2. Click the pencil “Edit this file”
  3. Make changes
  4. Scroll to the bottom and follow the steps to “Propose file change”
3 Likes

I was also confused about this some time ago. I remember the documentation mentioned JuMP is using conic dual, which may be different from the textbook dual. Is the sign difference a result of that?

Is the sign difference a result of that?

Yes, exactly.

1 Like

Thanks, I just did that. Do I now need to create a pull request, or am I done?

Oops. I missed a step. Continue and make a pull request.

Ok, I did that. There was one comment on the request last Thursday, to which I replied. Nothing since then. What happens next?

Thanks for your input. I’ve replied to the PR. I believe Miles is on vacation.