# Result\_dual vs getdual. signs are the opposite

**URL:** <https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355>\
**Category:** Optimization (Mathematical)\
**Created:** [October 15, 2018, 5:41pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355 "2018-10-15T17:41:20Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![chkwon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chkwon/32/3632_2.png) [@chkwon](https://discourse.julialang.org/u/chkwon)\
**Post date:** [October 15, 2018, 5:41pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/1 "2018-10-15T17:41:20Z")

</div>

JuMP v0.19:

```julia
using JuMP, Clp
m = Model(with_optimizer(Clp.Optimizer))
@variable(m, y>=0)
@objective(m, Max, y)
@constraint(m, con, y <= 3)
JuMP.optimize!(m)
pi_val = JuMP.result_dual(con)
@show pi_val

```

I obtained `pi_val = -1.0`

JuMP v0.18:

```julia
using JuMP, Clp
m = Model(solver=ClpSolver())
@variable(m, y>=0)
@objective(m, Max, y)
@constraint(m, con, y <= 3)
solve(m)
pi_val = getdual(con)
@show pi_val

```

I obtained `pi_val = 1.0`

Why does this happen? This is independent from the solvers, so I guess something changed in JuMP or MOI.

---

<div class="post-metadata">

**Author:** ![chkwon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chkwon/32/3632_2.png) [@chkwon](https://discourse.julialang.org/u/chkwon)\
**Post date:** [October 15, 2018, 5:43pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/2 "2018-10-15T17:43:33Z")

</div>

This issue doesn’t seem to happen when minimizing. I guess -1 should be multiplied to the dual value when maximizing?

---

<div class="post-metadata">

**Author:** ![joaquimg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joaquimg/32/223_2.png) [@joaquimg](https://discourse.julialang.org/u/joaquimg)\
**Post date:** [October 15, 2018, 7:45pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/3 "2018-10-15T19:45:59Z")

</div>

This has to do with the duality convention in MOI: [http://www.juliaopt.org/MathOptInterface.jl/stable/apimanual.html#Duals-1](http://www.juliaopt.org/MathOptInterface.jl/stable/apimanual.html#Duals-1)

From the manual:

> An important note for the LP case is that the signs of the feasible duals depend only on the sense of the inequality and not on the objective sense

---

<div class="post-metadata">

**Author:** ![miles.lubin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miles.lubin/32/279_2.png) [@miles.lubin](https://discourse.julialang.org/u/miles.lubin)\
**Post date:** [October 15, 2018, 9:17pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/4 "2018-10-15T21:17:04Z")

</div>

This was announced as a breaking change at [MathOptInterface and upcoming breaking changes in JuMP 0.19](https://discourse.julialang.org/t/mathoptinterface-and-upcoming-breaking-changes-in-jump-0-19/4874) but didn’t make it into the release notes. I’ll add it.

---

<div class="post-metadata">

**Author:** ![chkwon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chkwon/32/3632_2.png) [@chkwon](https://discourse.julialang.org/u/chkwon)\
**Post date:** [October 15, 2018, 9:49pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/5 "2018-10-15T21:49:43Z")

</div>

Thanks @miles.lubin and @joaquimg. I missed the notes.

I think this will make teaching LP courses a little more challenging, as the sign of dual is the opposite of most LP textbooks’ convention (both undergraduate and graduate). And seemingly it weakens the meaning of shadow price. Not sure what can be done though. A training wheel package? Maybe just some additional explanation in the classroom.

---

<div class="post-metadata">

**Author:** ![joaquimg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/joaquimg/32/223_2.png) [@joaquimg](https://discourse.julialang.org/u/joaquimg)\
**Post date:** [October 15, 2018, 10:28pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/6 "2018-10-15T22:28:10Z")

</div>

I see you point, the problem is that solvers are not consistent on what to do with signs of duals.  
We decided to use the conic notation, which makes harder for people learning LP.  
I agree that losing the shadow price interpretation is bad.  
Maybe we can have a `lp_shadow_price` function which returns the modified duals for LPs and breaks on conic problems, just brainstorming…

---

<div class="post-metadata">

**Author:** ![miles.lubin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miles.lubin/32/279_2.png) [@miles.lubin](https://discourse.julialang.org/u/miles.lubin)\
**Post date:** [October 16, 2018, 2:06am UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/7 "2018-10-16T02:06:35Z")

</div>

Yes, the change was for consistency with conic duality. Personally I find the new rule pretty simple to remember since the valid sign of the dual depends only on the sense of the constraint. I might be wrong but I think CVX does the same.

> [@joaquimg](#):
>
> Maybe we can have a `lp_shadow_price` function which returns the modified duals for LPs and breaks on conic problems, just brainstorming…

Sounds reasonable. That could go with a toolkit for teaching LP that also includes sensitivity summaries ([Feature Request: sensitivity summary for LPs · Issue #1332 · jump-dev/JuMP.jl · GitHub](https://github.com/JuliaOpt/JuMP.jl/issues/1332)).

---

<div class="post-metadata">

**Author:** ![NiclasMattsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/niclasmattsson/32/21988_2.png) [@NiclasMattsson](https://discourse.julialang.org/u/NiclasMattsson)\
**Post date:** [October 16, 2018, 10:19am UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/8 "2018-10-16T10:19:57Z")

</div>

> [@miles.lubin](#):
>
> Yes, the change was for consistency with conic duality. Personally I find the new rule pretty simple to remember since the valid sign of the dual depends only on the sense of the constraint. I might be wrong but I think CVX does the same.

I can’t check this myself since I’m traveling and my connection is too shaky, but do you know what duality sign conventions are used in Ampl, GAMS, and the various Python packages? I suspect many JuMP users will have a lot of experience with these environments, and if JuMP behaves differently then this is bound to cause headaches down the road.

If the current definition stays then +1 for providing `lp_shadow_price`.

---

<div class="post-metadata">

**Author:** ![chkwon](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chkwon/32/3632_2.png) [@chkwon](https://discourse.julialang.org/u/chkwon)\
**Post date:** [October 16, 2018, 11:50am UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/9 "2018-10-16T11:50:00Z")

</div>

+1 for LP teaching toolkit or LP toolbox in general. dual + sensitivity + termination status, etc.

Can `result_dual` be `result_conic_dual` and `result_lp_dual`? Would it be too much?

---

<div class="post-metadata">

**Author:** ![miles.lubin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miles.lubin/32/279_2.png) [@miles.lubin](https://discourse.julialang.org/u/miles.lubin)\
**Post date:** [October 16, 2018, 3:02pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/10 "2018-10-16T15:02:25Z")

</div>

We’ll provide `JuMP.shadow_price`. It’s a well-defined concept for LPs, i.e., sensitivity of the objective to an infinitesimal relaxation of the constraint.

You can see where it breaks down with homogeneous (conic) constraints like x \in C for some cone C because it’s more ambiguous about what it means to relax the constraint. Conic duals are based instead on supporting hyperplanes to C.

> [@NiclasMattsson](#):
>
> I can’t check this myself since I’m traveling and my connection is too shaky, but do you know what duality sign conventions are used in Ampl, GAMS, and the various Python packages? I suspect many JuMP users will have a lot of experience with these environments, and if JuMP behaves differently then this is bound to cause headaches down the road.

No, I don’t. I’d be interested to see a survey of how duals are handled across modeling interfaces. This sign change is a result of headaches that already occurred when trying to support conic optimization models (e.g., SOCP, SDP). AFAIK these interfaces have no first-class support for SDP so they’re have less complexity to deal with.

---

<div class="post-metadata">

**Author:** ![miles.lubin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miles.lubin/32/279_2.png) [@miles.lubin](https://discourse.julialang.org/u/miles.lubin)\
**Post date:** [October 27, 2018, 6:08pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/11 "2018-10-27T18:08:38Z")

</div>

Follow-up PR implementing `shadow_price`: [Implement shadow\_price by mlubin · Pull Request #1568 · jump-dev/JuMP.jl · GitHub](https://github.com/JuliaOpt/JuMP.jl/pull/1568).

---

<div class="post-metadata">

**Author:** ![jovansam](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jovansam/32/15023_2.png) [@jovansam](https://discourse.julialang.org/u/jovansam)\
**Post date:** [October 15, 2020, 12:14pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/12 "2020-10-15T12:14:25Z")

</div>

JuMP indeed has annoying shadow price behavior. This issue, first raised by @chkwon also matters in the presence of non-linear models/constraints in JuMP.

The behavior is not there in GAMS. My model is an economic growth model. Took me a while to actually figure out what was going on—kind of annoying as I could have saved time, had I worked right away in GAMS. But I love JuMP/Julia and the flexibility it offers.

I had to re-program everything in GAMS and also derive the complementarity problem to be sure I was not making errors.

Moreover, “JuMP. shadow\_price” does not work with “NLconstraint”. Non linear constraints are the bread and butter of economic modelling. So shadow\_price wont work in this case.

I do not want to come off as ungrateful as I cannot do the great work that is being done and has been done with JuMP. But it would be great to address this issue once and for all. This is likely to affect new users.

I see three ways out. 1) make shadow\_price work with nonlinear constraints, 2) have JuMP be consistent with GAMS/AMPL—may be by first checking if the problem is Max/Min and the multiplying duals/shadow\_prices by -1 for Max. 3) Make it more explicit in the manual what is actually being done by JuMP.dual, in order for people like me to back out the proper shadow prices.

Thanks

---

<div class="post-metadata">

**Author:** ![Henrique\_Becker](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/henrique_becker/32/15443_2.png) [@Henrique\_Becker](https://discourse.julialang.org/u/Henrique_Becker)\
**Post date:** [October 15, 2020, 1:48pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/13 "2020-10-15T13:48:46Z")

</div>

@jovansam has created [a new topic with basically the same text of this post](https://discourse.julialang.org/t/annoying-jump-way-to-deal-with-shadow-prices/48420). Please let us keep this branch of the discussion in a single place and answer to this post [there](https://discourse.julialang.org/t/annoying-jump-way-to-deal-with-shadow-prices/48420).

---

<div class="post-metadata">

**Author:** ![miles.lubin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/miles.lubin/32/279_2.png) [@miles.lubin](https://discourse.julialang.org/u/miles.lubin)\
**Post date:** [October 15, 2020, 1:54pm UTC](https://discourse.julialang.org/t/result-dual-vs-getdual-signs-are-the-opposite/16355/14 "2020-10-15T13:54:00Z")

</div>


