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

**URL:** <https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292>\
**Category:** Optimization (Mathematical)\
**Tags:** question, jump, optimization\
**Created:** [May 15, 2024, 9:33am UTC](https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292 "2024-05-15T09:33:42Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [May 15, 2024, 9:33am UTC](https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292/1 "2024-05-15T09:33:42Z")

</div>

To make it more clear, let’s consider an optimization problem of the following standard form:

\begin{equation} \begin{array}{cl} {\min} & {f\_0(x)}\\ {\mathrm{s.t.}} & {f\_i(x)\leqslant 0,\quad i=1,\cdots,m}\\ {} & {h\_i(x)=0,\quad i=1,\cdots,p}\\ \end{array} \end{equation}

Its Lagrangian as we know is

\begin{equation} L(x,\lambda,\nu) = f\_0(x) + \sum\_{i=1}^m\lambda\_if\_i(x) + \sum\_{i=1}^p\nu\_ih\_i(x) \end{equation}

where \lambda and \nu are known as the dual variables of the inequality an equality constraints of the primal problem, and \lambda is required to be nonnegative, i.e., \lambda \succeq 0.

In `JuMP` I see there are [three related functions](https://jump.dev/JuMP.jl/stable/manual/constraints/#constraint_duality) to query the value of the dual variables after the primal model is solved: `dual`, `shadow_price` and `reduced_cost`. But after reading the documentation, I’m still not quite sure about the difference between them, especially the sign issue.

What I most want to confirm is what is the exact way to get the values of \lambda (the dual variable on the inequality constraint) and \nu (the dual variable on the equality constraint).

Thank you in advance!

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [May 15, 2024, 10:12am UTC](https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292/2 "2024-05-15T10:12:41Z")

</div>

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:

- [Constraints · JuMP](https://jump.dev/JuMP.jl/stable/manual/constraints/#constraint_duality)
- [Duality · MathOptInterface](https://jump.dev/MathOptInterface.jl/stable/background/duality/)

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.

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [May 15, 2024, 11:08am UTC](https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292/3 "2024-05-15T11:08:20Z")

</div>

Thank you very much @odow for your very detailed explanation and valuable experience!!! 🤝 🤝

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [August 21, 2024, 10:35am UTC](https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292/4 "2024-08-21T10:35:33Z")

</div>

Hi, Prof. @odow , I have another question about duality but I don’t know if it is appropriate to ask here.

The question is: To solve a convex primal problem `PP` I first derive its dual problem `DP` and then I model and solve the dual problem `DP` using `JuMP`. Now after I obtain the optimal solution of the dual problem `DP`, how can I retrieve the primal solution of some of the primal variables?

I guess maybe the optimal solution of some primal variables correspond to the `dual` value of some constraints in `DP`, but how can I tell what the correspondence is between them?

Suppose the KKT conditions are, if they help:

\begin{eqnarray} f\_i(x)\leqslant 0,&\quad i = 1,\cdots,m\\ h\_i(x) = 0,&\quad i = 1,\cdots,p~~\\ {\lambda}\_i\geqslant 0,&\quad i = 1,\cdots,m\\ {\lambda}\_i f\_i({x}) = 0,&\quad i = 1,\cdots,m\\ \nabla f\_0({x}) + \sum\_{i=1}^m{\lambda}\_i\nabla f\_i({x}) + \sum\_{i=1}^p{\nu}\_i\nabla h\_i({x}) = 0.&\\ \end{eqnarray}

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 21, 2024, 7:16pm UTC](https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292/5 "2024-08-21T19:16:20Z")

</div>

The constraint duals in DP are the primal variable values in PP.

This page might help: [Duality · MathOptInterface](https://jump.dev/MathOptInterface.jl/stable/background/duality/)

Consider also using Dualization.jl

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [August 22, 2024, 1:35am UTC](https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292/6 "2024-08-22T01:35:44Z")

</div>

Many thanks!!! 🤝

---

<div class="post-metadata">

**Author:** ![WuSiren](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wusiren/32/42529_2.png) [@WuSiren](https://discourse.julialang.org/u/WuSiren)\
**Post date:** [August 22, 2024, 10:21am UTC](https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292/7 "2024-08-22T10:21:12Z")

</div>

If a model is `INFEASIBLE`, does the `dual` of its constraints have any explicit meaning?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [August 22, 2024, 5:50pm UTC](https://discourse.julialang.org/t/to-confirm-the-sign-of-the-dual-variable-on-a-constraint-of-jump-model/114292/8 "2024-08-22T17:50:30Z")

</div>

See [Infeasibility certificates · JuMP](https://jump.dev/JuMP.jl/stable/moi/background/infeasibility_certificates/)
