3

I'm running nonlinear optimization using the Ipopt optimizer in JuMP. 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 or 1.6666666718748067

crashing the program.

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

Code:

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)
Kevin
  • 281
  • 2
  • 5
  • Please do not post the same question in multiple places. It just duplicates the work of two people answering: https://discourse.julialang.org/t/jump-nonlinear-optimization-constraints-broken-to-o-1e-9/75182 – Oscar Dowson Jan 25 '22 at 19:52

2 Answers2

2

When working with real numbers using a computer you can never get full precision. Basically what one does in such situation is to apply rounding after getting a solution from the solver (eg. rounding to an integer or a rational number in your case - eg. try something like rationalize(1.6666666718748067, tol=1e-6) since 1e-6 is the default tolerance in Ipopt).

Having that said, you can try playing with Ipopt's precision/tolerance options such as (your code is not complete so I cannot test on your case):

set_optimizer_attribute(model, "constr_viol_tol", 1e-10)
set_optimizer_attribute(model, "acceptable_tol", 1e-10)

You can find more options having _tol suffix in Ipopt documentation and see how they influence the precision of your solution: see https://coin-or.github.io/Ipopt/OPTIONS.html

Przemyslaw Szufel
  • 40,002
  • 3
  • 32
  • 62
0

To add to the answer of Przemyslaw and repeat what Miles said in the Julia discourse, setting the bound_relax_factor to 0 should help to ensure variable value are almost always within or at bounds.

"almost" because Ipopt may choose to relax variable bounds (or constraint sides) during solve again. There is a message "Slack too small, adjusting variable bound" in the log that indicates that this happened. So you want to handle this case in your code and not just "crash".

stefan
  • 799
  • 4
  • 9