# Getting duals for nonlinear programming problem

**URL:** <https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357>\
**Category:** Optimization (Mathematical)\
**Tags:** history\
**Created:** [June 2, 2018, 2:24am UTC](https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357 "2018-06-02T02:24:55Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![pedroborgesmelo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pedroborgesmelo/32/9459_2.png) [@pedroborgesmelo](https://discourse.julialang.org/u/pedroborgesmelo)\
**Post date:** [June 2, 2018, 2:24am UTC](https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357/1 "2018-06-02T02:24:55Z")

</div>

Hi Guys!

I’m having problems getting the dual variables for a nonlinear problem, with Ipopt as the solver…

I just found this post here of 2015, but not working here and a bit old:  
[https://github.com/JuliaOpt/JuMP.jl/issues/456](https://github.com/JuliaOpt/JuMP.jl/issues/456)

Any updates on the topic?

---

<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:** [June 2, 2018, 2:54am UTC](https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357/2 "2018-06-02T02:54:15Z")

</div>

Have you tried? Works for me:

```julia
julia> using JuMP, Ipopt

julia> m=Model(solver=IpoptSolver())
Feasibility problem with:
 * 0 linear constraints
 * 0 variables
Solver is Ipopt

julia> @variable(m, 0 <= x <= π / 2)
x

julia> c = @constraint(m, x >= π / 3)
x >= 1.0471975511965976

julia> @NLobjective(m, Min, sin(x))

julia> solve(m)
This is Ipopt version 3.12.8, running with linear solver mumps.
... lines omitted ...

julia> getdual(c)
0.5000000071047659

julia> cos(π/3)
0.5000000000000001

```

If you’re having problems, try posting a small reproducible example ([How to create a Minimal, Reproducible Example - Help Center - Stack Overflow](https://stackoverflow.com/help/mcve)).

---

<div class="post-metadata">

**Author:** ![pedroborgesmelo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pedroborgesmelo/32/9459_2.png) [@pedroborgesmelo](https://discourse.julialang.org/u/pedroborgesmelo)\
**Post date:** [June 2, 2018, 1:27pm UTC](https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357/3 "2018-06-02T13:27:29Z")

</div>

Hi Orscar!

Thanks.

Your example works here as well…

Now I realized that my problem is that Ipopt is letting down while solving the problem…

Best,

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [April 20, 2025, 6:36am UTC](https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357/4 "2025-04-20T06:36:00Z")

</div>

Just to leave a note. The code can be renewed to

```julia
julia> import JuMP, Ipopt

julia> begin
           model = JuMP.Model(Ipopt.Optimizer)
               JuMP.set_silent(model)
           JuMP.@variable(model, 0 <= x <= 1. * π)
           JuMP.@constraint(model, c, x >= π / 3)
           JuMP.@objective(model, Min, sin(x))
           JuMP.optimize!(model)
       end

julia> JuMP.solution_summary(model; verbose = true)
solution_summary(; result = 1, verbose = true)
├ solver_name : Ipopt
├ Termination
│ ├ termination_status : LOCALLY_SOLVED
│ ├ result_count : 1
│ └ raw_status : Solve_Succeeded
├ Solution (result = 1)
│ ├ primal_status : FEASIBLE_POINT
│ ├ dual_status : FEASIBLE_POINT
│ ├ objective_value : -2.89073e-08
│ ├ dual_objective_value : -3.14159e+00
│ ├ value
│ │ └ x : 3.14159e+00
│ └ dual
│ └ c : 1.19568e-09
└ Work counters
  ├ solve_time (sec) : 4.48600e+00
  └ barrier_iterations : 8

julia> JuMP.set_start_value(x, (π/3 + π/2) / 2)

julia> JuMP.optimize!(model)

julia> JuMP.solution_summary(model; verbose = true)
solution_summary(; result = 1, verbose = true)
├ solver_name : Ipopt
├ Termination
│ ├ termination_status : LOCALLY_SOLVED
│ ├ result_count : 1
│ └ raw_status : Solve_Succeeded
├ Solution (result = 1)
│ ├ primal_status : FEASIBLE_POINT
│ ├ dual_status : FEASIBLE_POINT
│ ├ objective_value : 8.66025e-01
│ ├ dual_objective_value : 5.23599e-01
│ ├ value
│ │ └ x : 1.04720e+00
│ └ dual
│ └ c : 5.00000e-01
└ Work counters
  ├ solve_time (sec) : 0.00000e+00
  └ barrier_iterations : 7

```

Note that if the starting points was `JuMP.set_start_value(x, π/2 - 0.05)`, then Ipopt would fail to converge to the `π / 3` local minimum, which is not as expected. This suggests that the outcomes (the resulting local minimum) might differ, if you write an algorithm yourself.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [April 20, 2025, 7:06am UTC](https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357/5 "2025-04-20T07:06:45Z")

</div>

I don’t know how Ipopt compute the Lagrangian multiplier of `x >= b`, e.g. (`b = pi / 3`).

I guess that it will first reformulate this constraint as `x == y + b`, where `y >= 0` is an additional ancillary variable. Then it can associate a multiplier `m`, which is free, to `x == y + b`.  
If the final solution suggests that `y == 0` (or almost zero), then it can returns the value of `m`, as the multiplier of `x >= b`. Otherwise, if `y > 0` strictly, then it can returns `0`, as the multiplier of `x >= b`.

If there is anyone who knows this interior-point-method procedure, please tell me🙂

---

<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:** [April 20, 2025, 7:50am UTC](https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357/6 "2025-04-20T07:50:37Z")

</div>

Hi @WalterMadelim, we generally discourage commenting on long dead posts. If we updated every post from 2018 that’d be too much work and people will get unexpected emails.

Your idea for the dual is more or less correct. Theres a paper on Ipopt if you want to go find the details.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [April 24, 2025, 6:27am UTC](https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357/7 "2025-04-24T06:27:04Z")

</div>

Things are clearer to me now. It’s merely about the KKT system of equations.

At a local optimum, which Ipopt ensures, there are 2 possibilities for an inequality constraint

1. it is binding at this local optimum
2. it is nonbinding, i.e. it can be safely removed, concerning only this specific local optimum

If it is the situation 2, then the multiplier returned is simply `0`.  
If it is the situation 1, then that inequality constraint can be deemed a `==` constraint, which owns a normal lagrange multiplier (typically will be nonzero).

---

<div class="post-metadata">

**Author:** ![pedroborgesmelo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/pedroborgesmelo/32/9459_2.png) [@pedroborgesmelo](https://discourse.julialang.org/u/pedroborgesmelo)\
**Post date:** [April 24, 2025, 3:55pm UTC](https://discourse.julialang.org/t/getting-duals-for-nonlinear-programming-problem/11357/8 "2025-04-24T15:55:42Z")

</div>

hello walter..

in general, ipopt ensures only an approximate stationary point.
