# JuMP nonlinear optimization constraints broken to O(1e-9)

**URL:** <https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182>\
**Category:** Optimization (Mathematical)\
**Tags:** jump, bug\
**Created:** [January 25, 2022, 4:15pm UTC](https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182 "2022-01-25T16:15:15Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kevin\_Shen1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevin_shen1/32/33160_2.png) [@Kevin\_Shen1](https://discourse.julialang.org/u/Kevin_Shen1)\
**Post date:** [January 25, 2022, 4:15pm UTC](https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182/1 "2022-01-25T16:15:15Z")

</div>

I’m running nonlinear optimization using the Ipopt optimizer. My objective/cost function relies on the constraints being adhered to strictly. However on some iterations the constraint are being broken.

Specifically, my constraints are s.t. the values should be between 0 and 1/0.6 = 1.6666666…

However, in some iterations, the variables have values like:

-7.761358324221462e-9  
1.6666666718748067

crashing the program.

Is this a bug? Is it a problem with JuMP or Ipopt? Is there a workaround?

Code:

```julia
using JuMP
using Ipopt

model = Model(Ipopt.Optimizer)
@variable(model, 0.0 <= ξ[1:6] <= 1.0/0.6)
set_start_value.(ξ, ξ₀)

@constraint(model, dot(ξ, T) == 1)

register(model, :objtv, 6, MyNonLinearObjectiveFn; autodiff=true)
@NLobjective(model, Min, objtv(ξ...))

optimize!(model)

```

---

<div class="post-metadata">

**Author:** ![blob](https://avatars.discourse-cdn.com/v4/letter/b/ebca7d/32.png) [@blob](https://discourse.julialang.org/u/blob)\
**Post date:** [January 25, 2022, 4:42pm UTC](https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182/2 "2022-01-25T16:42:04Z")

</div>

It’s the question of tolerances: [Results NLP problem - #2 by blob](https://discourse.julialang.org/t/results-nlp-problem/71673/2)

As for a workaround - ipopt will always have finite tolerances, so differences will always be possible. If things are crashing, then you are probably requiring stricter tolerances in the objective function than ipopt. But `-7.761358324221462e-9` should really be treated as zero in most applications.

Maybe the performance will be better if you get rid of division:

```julia
@variable(model, 0.0<= 0.6*ξ[1:6] <= 1.0) 

```

Alternatively, if the constraints _must_ be satisfied, you can tighten them:

```julia
@variable(model, 0.00001 <= 0.6*ξ[1:6] <= 1.0-0.00001) ##You can pick a different positive value instead of 0.00001

```

---

<div class="post-metadata">

**Author:** ![cvanaret](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cvanaret/32/11594_2.png) [@cvanaret](https://discourse.julialang.org/u/cvanaret)\
**Post date:** [January 25, 2022, 4:56pm UTC](https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182/3 "2022-01-25T16:56:06Z")

</div>

Alternatively, you can use interval methods ([https://github.com/JuliaIntervals/IntervalOptimisation.jl/blob/master/src/optimise.jl](https://github.com/JuliaIntervals/IntervalOptimisation.jl/blob/master/src/optimise.jl)), provided your problem is not too big (say a few dozen variables) and you can express your functions analytically.

Interval arithmetic was designed to bound roundoff errors. So it never goes out of bounds.

---

<div class="post-metadata">

**Author:** ![Kevin\_Shen1](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevin_shen1/32/33160_2.png) [@Kevin\_Shen1](https://discourse.julialang.org/u/Kevin_Shen1)\
**Post date:** [January 25, 2022, 4:57pm UTC](https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182/4 "2022-01-25T16:57:20Z")

</div>

Makes sense but why isn’t the tolerance built into the JuMP API then? Seems very hacky to add and subtract a small number from your bounds in user-code.

---

<div class="post-metadata">

**Author:** ![blob](https://avatars.discourse-cdn.com/v4/letter/b/ebca7d/32.png) [@blob](https://discourse.julialang.org/u/blob)\
**Post date:** [January 25, 2022, 5:13pm UTC](https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182/5 "2022-01-25T17:13:06Z")

</div>

Constraint tightening is used in optimal control when you really cannot violate constraints, for example due to physical boundaries.

Maybe I am wrong here, but JuMP provides an interface, the tolerances depend on what the user/the solver needs. From Ipopt perspective, `-7.761358324221462e-9` is zero for default tolerances (I think 1e-8?), so this is the value it returned. Other parts of this code crash because for them `-7.761358324221462e-9` is not zero and they cannot accept it. But in general, it is impossible to predict what the user wants/needs, unless they are using specialised solutions, like interval arithmetic.

---

<div class="post-metadata">

**Author:** ![cvanaret](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cvanaret/32/11594_2.png) [@cvanaret](https://discourse.julialang.org/u/cvanaret)\
**Post date:** [January 25, 2022, 5:22pm UTC](https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182/6 "2022-01-25T17:22:36Z")

</div>

Have a look here: [Objective function "limit reached" status in JuMP - #6 by ivborissov](https://discourse.julialang.org/t/objective-function-limit-reached-status-in-jump/39349/6)

---

<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:** [January 25, 2022, 5:33pm UTC](https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182/7 "2022-01-25T17:33:57Z")

</div>

Yes, don’t add hacky epsilons to your code. Ipopt is working as its authors intended by allowing small violations of variable bounds. To get the behavior you want, adjust Ipopt’s `bound_relax_factor` parameter. See the Ipopt.jl readme for examples of setting parameters.

---

<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:** [January 25, 2022, 7:51pm UTC](https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182/8 "2022-01-25T19:51:51Z")

</div>

Just to clarify, this syntax is invalid:

```julia
julia> @variable(model, 0.0<= 0.6*ξ[1:6] <= 1.0)
ERROR: LoadError: Expression 0.6 * ξ[1:6] cannot be used as a name.
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:33
 [2] _get_name(c::Expr)
   @ JuMP.Containers ~/.julia/dev/JuMP/src/Containers/macro.jl:16
 [3] var"@variable"( __source__ ::LineNumberNode, __module__ ::Module, args::Vararg{Any, N} where N)
   @ JuMP ~/.julia/dev/JuMP/src/macros.jl:2045
in expression starting at REPL[4]:1

```

So yes, either make your objective function robust to numerical tolerances, or play with the solver settings.
