jump-dev/NLopt.jl

LN_COBYLA steps out of bounds

Closed this issue · 6 comments

While running NLopt with LN_COBYLA, the optimization routine violated a lower bound and the program execution stopped. Obviously, this is undesirable behaviour. I also note that this problem occurs sometimes but not always.

Attached is a screenshot that shows the error stack with the bound violation numbers.
0.01 was the lower bound and 1.0 the upper bound. The algorithm assigned a value of 0.00987... to the variable.

Capture

odow commented

Please provide a reproducible example.

eggix commented

I observe the same out-of-bounds behavior. I seems that the problem occurs when the solution is close the boundary. Minimal working example

using NLopt

sol = [0.05, 0.95]

function mini(x, g)
    if !all(0 .≤ x .≤ 1)
        println("out of bounds  ", x)
    end
    return sum((x .- sol) .^ 2)
end

# formulate constraints in form of f(x) ≤ 0
function constraint1(result, x, g)
    result[:] = -x  # 0 ≤ x
end
function constraint2(result, x, g)
    result[:] = x .- 1.0  # x ≤ 1
end

n = 2
opt = Opt(:LN_COBYLA, n)
opt.min_objective = mini
inequality_constraint!(opt, constraint1, zeros(n))
inequality_constraint!(opt, constraint2, zeros(n))
(minf, minx, ret) = optimize(opt, 0.5 * ones(n))

yields

out of bounds  [0.0, 1.0494306750975504]
out of bounds  [-0.04170497206865227, 1.0]
out of bounds  [0.0, 1.0227042205893415]
out of bounds  [-0.02761569933983048, 0.9375]
(1.232595164407831e-32, [0.05, 0.9499999999999998], :ROUNDOFF_LIMITED)

Although I would not regard 0.05 close.
(NLopt is on v0.6.5 and NLopt.version() → v"2.7.1")

odow commented

@eggix: it might step out of bounds during the search, but the final solution respects the bounds?

I still can't reproduce the original error in the first post.

eggix commented

Yes, the final solution respects the bounds. However, in my use case the function I want to minimize is not defined outside the bounds. I hoped the inequality constraints would be an elegant solution to restrict the evaluation of the function to inside the bounds. But it seems this is not the case, and might be outside the scope of the algorithm.

odow commented

You could try pass Inf as the objective value when the solution is out of bounds. But for some algorithms that might cause issues.

In general though, you should expect most algorithms could step out of bounds during the solve, but you can be sure that final solutions respect the bounds.

I don't think there's anything we can/should do at the NLopt.jl level to fix this.

Yes, this is documented.

General inequality constraints may (and often will) be violated at intermediate optimization steps. However, the "box" constraints set by nlopt_set_lower_bounds and nlopt_set_upper_bounds will never be violated at intermediate steps.

So, if you have a function which is not defined for certain values of the variables, I would try to re-parameterize it so that you can express that constraint in terms of box constraints. For example, if you have two variables x,y and your function is only defined for y ≥ x², you can change variables to (x,u) and let y = x²+u, with a box constraint u ≥ 0.