scipy.optimize.minimize_scalar() adding constraint to helper function result inside objective function?
I would also advice you to use minimize. You just have to be aware of the limitations
Constraints definition (only for COBYLA, SLSQP and trust-constr).
And also
Note that COBYLA only supports inequality constraints.
From this we conclude that either SLSQP
or trust-constr
must be choosen.
With trust-constr
the results are fine
res = minimize(func_x, 5, method='SLSQP', bounds=[[-10, 10]],
constraints=[{'type': 'ineq', 'fun': lambda x: 1-func_y(x)}])
print(res.x, res.fun, func_y(res.x), res.success)
res = minimize(func_x, 5, method='SLSQP', bounds=[[-10, 10]],
constraints=[{'type': 'ineq', 'fun': lambda x: func_y(x)-1}])
print(res.x, res.fun, func_y(res.x), res.success)
res = minimize(func_x, 5, method='SLSQP', bounds=[[-10, 10]])
print(res.x, res.fun, func_y(res.x), res.success)
gives
[1.32467216] [-7.4635986] [0.99985257]
[1.59008719] [-10.0354401] [1.89948096]
[1.59008719] [-10.0354401] [1.89948093]
However this type constraints are not working properly for SLSQP
.
Another way to represent constraints is as NonlinearConstraint or LinearConstraint, in that case SLSQP
works fine
res = minimize(func_x, 5, method='trust-constr', bounds=[[-10, 10]],
constraints=[NonlinearConstraint(func_y, lb=1, ub=1.5)])
print(res.x, res.fun, func_y(res.x))
res = minimize(func_x, 5, method='SLSQP', bounds=[[-10, 10]],
constraints=[NonlinearConstraint(func_y, lb=1, ub=1.5)])
print(res.x, res.fun, func_y(res.x))
gives
[1.47559988] [-9.50009675] [1.49970451]
[1.47568652] [-9.50087235] [1.5]
An important detail is that the constraint func_y(x) > 1
splits your domain in two parts, the objective function is better on the left, but the method will probably only explore the part on the right.