Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SLSQP declares success even if constraints are not met within specified tolerance #552

Closed
arvindv92 opened this issue Apr 10, 2024 · 2 comments

Comments

@arvindv92
Copy link

My use case is a chi-square minimization with multiple nonlinear equality based constraints. I started first with derivative free COBYLA, and then switched to SLSQP with analytical gradients implemented. In both cases, I saw the solvers declaring success even when the constraints had not been with within the specified tolerance, sometimes with very large violations.

To set up a toy test with a known function, I turned to the Rosenbrock function, with a single nonlinear equality constraint (x1^2 + x2^2 = 0), with the constraint intentionally scaled by 1e10 to give a large value. In the example below, I specify a constraint tolerance of 1e-6, and ftol_rel of 1e-4. But the solver exits with a successful status code of 3, with the constraint evaluated at the minimum being 3e-5, which is larger than my specified tolerance.

When I use LN_COBYLA instead of LD_SLSQP with all else being the same, the constraint violation seen on the successful exit (code 3) is even larger, equal to 246. I see that this has been reported before also.

Any advice on how to deal with these issues would be greatly appreciated. Thank you for the work that went into creating and maintaining NLopt!

test_NLopt_Rosenbrock.py:

import nlopt
import numpy as np


def rosenbrock(x, grad):
    if grad.size > 0:
        grad[0] = -400*x[0]*(x[1]-x[0]**2) - 2*(1-x[0])
        grad[1] = 200*(x[1]-x[0]**2)
    func = (100* (x[1]-x[0]**2)**2 + (1-x[0])**2)
    print("func = ", func, "at x[0] = ", x[0], " x[1] = ", x[1])
    return func

def myconstraint(x, grad):
    if grad.size > 0:
        grad[0] = (2*x[0])*1e10
        grad[1] = (2*x[1])*1e10
    return (x[0]**2 + x[1]**2 - 4)*1e10

opt = nlopt.opt(nlopt.LD_SLSQP, 2)
opt.set_min_objective(lambda x,grad: rosenbrock(x, grad))
opt.add_equality_constraint(lambda x,grad: myconstraint(x,grad), 1e-6)
opt.set_ftol_rel(1e-4)

x_fitted = opt.optimize([2.5, 5])
minf = opt.last_optimum_value()
print("optimum at ", x_fitted[0], x_fitted[1])
print("minimum value = ", minf)
print("result code = ", opt.last_optimize_result())

print("constraint at minimum = ", myconstraint(x_fitted, np.zeros(2)))

Output:

$ python -i test_NLopt_Rosenbrock.py 
func =  158.5 at x[0] =  2.5  x[1] =  5.0
func =  146803505608115.06 at x[0] =  -1100.990000000001  x[1] =  554.0200000000002
func =  13389984184.06146 at x[0] =  -107.8490000000001  x[1] =  59.90200000000002
func =  388897.0117672333 at x[0] =  -8.534900000000011  x[1] =  10.490200000000002
func =  1295.2788393920505 at x[0] =  1.3965099999999988  x[1] =  5.5490200000000005
func =  14.422721540390352 at x[0] =  2.189481326672275  x[1] =  5.154492530091245
func =  14.422721540390352 at x[0] =  2.189481326672275  x[1] =  5.154492530091245
func =  17.743208903111793 at x[0] =  1.759845600424561  x[1] =  2.6827397072793495
func =  18.12930562844732 at x[0] =  1.4594550668037019  x[1] =  1.706710064497841
func =  22.524318901599212 at x[0] =  1.107866374815913  x[1] =  1.701843233066463
func =  0.5491729153694156 at x[0] =  1.2788871605734926  x[1] =  1.7042105712502886
func =  0.5491729153694156 at x[0] =  1.2788871605734926  x[1] =  1.7042105712502886
func =  0.06463636845785697 at x[0] =  1.2524573232214695  x[1] =  1.5656465670957493
func =  0.06255671195089194 at x[0] =  1.2499208526432233  x[1] =  1.5613209173824814
func =  0.06226224100407627 at x[0] =  1.249481549024183  x[1] =  1.561664550958314
func =  0.0622534823683728 at x[0] =  1.2493919568480023  x[1] =  1.5617361337032474
func =  0.06225348172981736 at x[0] =  1.2493919133217883  x[1] =  1.561736164313974
optimum at  1.2493919133217883 1.561736164313974
minimum value =  0.06225348172981736
result code =  3
constraint at minimum =  3.552713678800501e-05
@jonmaddock
Copy link

jonmaddock commented Aug 7, 2024

I also have this exact issue: successful termination of SLSQP, but with constraints violated (above their tolerance value). I've also reproduced the example above.

@jschueller
Copy link
Collaborator

jschueller commented Oct 25, 2024

duplicate of #368, fixed in #465

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants