To confirm: The sign of the dual variable on a constraint of `JuMP` model

You’re right that that can be a confusing topic. We should probably add more explanation to the JuMP docs.

A key realization is that:

  • The sign convention is arbitrary. I could assume that \lambda was non-positive if I put a - sign in front of the summation
  • JuMP uses the duality conventions from conic duality.

These part of the documentation may be helpful:

The way I remember JuMP.dual is:

  • the sign of JuMP.dual(constraint) does not depend on whether we are minimizing or maximizing
  • the sign of JuMP.dual(constraint) is non-negative for \ge and non-positive for \le

In more detail:

  • the dual of a \le constraint is non-positive, because f(x) \le y is rewritten to f(x) - y \in \mathbb{R}_- (the MOI.Nonpositives cone), and the dual cone of MOI.Nonpositives is MOI.Nonpositives
  • the dual of a \ge constraint is non-negative, because f(x) \ge y is rewritten to f(x) - y \in \mathbb{R}_+ (the MOI.Nonnegatives cone), and the dual cone of MOI.Nonnegatives is MOI.Nonnegatives.
  • the dual of a = constraint is free, because f(x) = y is rewritten to f(x) - y \in {0} (the MOI.Zeros cone), and the dual of the MOI.Zeros cone is MOI.Reals

Notably, this is the opposite to your statement that λ is required to be nonnegative, so to convert to your assumed Lagragian, you need to add - sign.

shadow_price and reduced_cost are mostly useful for people coming from a background in linear programming. There, shadow_price is the change in the objective value as the constraint is relaxed, and the sign depends on whether we are maximizing or minimizing.

2 Likes