Hi cobyqa team!
In a recent bug-report in the scipy repo I've found that the COBYQA optimizer doesn't always seems to respect the specified boundaries. Unfortunately, it was hard to simplify the issue to demonstrate it in an isolated manner, but I've done my best.
The context is a python package that's designed to optimize marine propellers. Each propeller is modeled using a large polynomial function that has been fit on a large set of experimental data. Using these polynomials, the performance of a propeller can be predicted. I've isolated the issue into a specific unit-test:
from propy.wageningen_b import WageningenBPropeller
from scipy.optimize import minimize, Bounds, NonlinearConstraint
from numpy import inf
def test_optimization_max_diameter() -> None:
thrust = 1393000
speed = 8.65
immersion = 3.51
def f_obj(args):
print(f'f_obj({args})')
return WageningenBPropeller(4, *args).losses(speed, thrust)
def f_con(args):
print(f'f_con({args})')
return WageningenBPropeller(4, *args).cavitation_margin(thrust, immersion)
minimize(
method='COBYQA',
fun=f_obj,
x0=(1.0, 0.5, 0.8),
bounds=Bounds(
lb=(0.03, 0.3, 0.5),
ub=(7.0, 1.05, 1.4),
keep_feasible=(True, True, True)
),
constraints=[
NonlinearConstraint(f_con, 0, inf)
],
options={
'disp': True
}
)
assert True
In one of the constraint function evaluations, the second argument of the function (area_ratio) is set to 0.088, which is out of bounds. The output of the function is shown below:
Starting the optimization procedure.
Initial trust-region radius: 1.0.
Final trust-region radius: 1e-06.
Maximum number of function evaluations: 1500.
Maximum number of iterations: 3000.
f_obj([1. 0.675 0.875])
f_obj([ 1.000e+00 6.750e-01 8.750e-01]) = 0.8352655933061457
f_con([1. 0.675 0.875])
f_con([ 1.000e+00 6.750e-01 8.750e-01]) = [-2.418e+01]
f_obj([1.375 0.675 0.875])
f_obj([ 1.375e+00 6.750e-01 8.750e-01]) = 0.780413651409479
f_con([1.375 0.675 0.875])
f_con([ 1.375e+00 6.750e-01 8.750e-01]) = [-1.249e+01]
f_obj([1. 1.05 0.875])
f_obj([ 1.000e+00 1.050e+00 8.750e-01]) = 0.8354762797478886
f_con([1. 1.05 0.875])
f_con([ 1.000e+00 1.050e+00 8.750e-01]) = [-2.383e+01]
f_obj([1. 0.675 1.25 ])
f_obj([ 1.000e+00 6.750e-01 1.250e+00]) = 0.8552303249820229
f_con([1. 0.675 1.25 ])
f_con([ 1.000e+00 6.750e-01 1.250e+00]) = [-2.418e+01]
f_obj([0.625 0.675 0.875])
f_obj([ 6.250e-01 6.750e-01 8.750e-01]) = 0.8939800911425317
f_con([0.625 0.675 0.875])
f_con([ 6.250e-01 6.750e-01 8.750e-01]) = [-6.291e+01]
f_obj([1. 0.3 0.875])
f_obj([ 1.000e+00 3.000e-01 8.750e-01]) = 0.8279419747450552
f_con([1. 0.3 0.875])
f_con([ 1.000e+00 3.000e-01 8.750e-01]) = [-2.454e+01]
f_obj([1. 0.675 0.5 ])
f_obj([ 1.000e+00 6.750e-01 5.000e-01]) = 0.8344755303132483
f_con([1. 0.675 0.5 ])
f_con([ 1.000e+00 6.750e-01 5.000e-01]) = [-2.418e+01]
f_con([1. 0.675 0.875])
f_con([1.375 0.675 0.875])
f_con([1. 1.05 0.875])
f_con([1. 0.675 1.25 ])
f_con([0.625 0.675 0.875])
f_con([1. 0.3 0.875])
f_con([1. 0.675 0.5 ])
f_con([1.375 0.675 0.875])
f_con([1. 0.675 0.875])
f_con([1. 1.05 0.875])
f_con([1. 0.675 1.25 ])
f_con([0.625 0.675 0.875])
f_con([1. 0.3 0.875])
f_con([1. 0.675 0.5 ])
f_obj([1.12373237 0.95273559 0.8562245 ])
f_obj([ 1.124e+00 9.527e-01 8.562e-01]) = 0.817229804956104
f_con([1.12373237 0.95273559 0.8562245 ])
f_con([ 1.124e+00 9.527e-01 8.562e-01]) = [-1.875e+01]
f_con([1.375 0.675 0.875])
f_con([1.12373237 0.95273559 0.8562245 ])
f_obj([0.75573562 1.02487013 0.8562245 ])
f_obj([ 7.557e-01 1.025e+00 8.562e-01]) = 0.8724748922858667
f_con([0.75573562 1.02487013 0.8562245 ])
f_con([ 7.557e-01 1.025e+00 8.562e-01]) = [-4.249e+01]
f_con([1.375 0.675 0.875])
f_con([0.75573562 1.02487013 0.8562245 ])
f_con([1.375 0.675 0.875])
f_con([0.75573562 1.02487013 0.8562245 ])
f_con([1.375 0.675 0.875])
f_con([1. 0.675 0.875])
f_con([1. 1.05 0.875])
f_con([1. 0.675 1.25 ])
f_con([0.75573562 1.02487013 0.8562245 ])
f_con([1. 0.3 0.875])
f_con([1. 0.675 0.5 ])
f_con([1.375 0.675 0.875])
f_con([1. 0.675 0.875])
f_con([1. 1.05 0.875])
f_con([1. 0.675 1.25 ])
f_con([0.75573562 1.02487013 0.8562245 ])
f_con([1. 0.3 0.875])
f_con([1. 0.675 0.5 ])
f_con([1.375 0.675 0.875])
New trust-region radius: 0.037500000000000006.
Number of function evaluations: 9.
Number of iterations: 1.
Least value of f_obj: 0.780413651409479.
Maximum constraint violation: 12.488502981664915.
Corresponding point: [ 1.375e+00 6.750e-01 8.750e-01].
f_obj([1.49745472 0.51161965 0.86225777])
f_obj([ 1.497e+00 5.116e-01 8.623e-01]) = 0.7593384210840486
f_con([1.49745472 0.51161965 0.86225777])
f_con([ 1.497e+00 5.116e-01 8.623e-01]) = [-1.058e+01]
f_con([1.375 0.675 0.875])
f_con([1.49745472 0.51161965 0.86225777])
f_con([1.375 0.675 0.875])
f_con([1.49745472 0.51161965 0.86225777])
f_con([1.375 0.675 0.875])
f_con([1.49745472 0.51161965 0.86225777])
f_con([1.375 0.675 0.875])
f_con([1. 0.675 0.875])
f_con([1. 1.05 0.875])
f_con([1. 0.675 1.25 ])
f_con([1.49745472 0.51161965 0.86225777])
f_con([1. 0.3 0.875])
f_con([1. 0.675 0.5 ])
f_con([1.49745472 0.51161965 0.86225777])
f_con([1. 0.675 0.875])
f_con([1.375 0.675 0.875])
f_con([1. 1.05 0.875])
f_con([1. 0.675 1.25 ])
f_con([1. 0.3 0.875])
f_con([1. 0.675 0.5 ])
f_obj([1.44084474 0.3 0.71284246])
f_obj([ 1.441e+00 3.000e-01 7.128e-01]) = 0.7523410826103512
f_con([1.44084474 0.3 0.71284246])
f_con([ 1.441e+00 3.000e-01 7.128e-01]) = [-1.167e+01]
f_con([1.49745472 0.51161965 0.86225777])
f_con([1.44084474 0.3 0.71284246])
f_obj([1.28109002 0.3 0.71000464])
f_obj([ 1.281e+00 3.000e-01 7.100e-01]) = 0.776183522835638
f_con([1.28109002 0.3 0.71000464])
f_con([ 1.281e+00 3.000e-01 7.100e-01]) = [-1.484e+01]
f_con([1.28109002 0.08838035 0.71000464])
There's a good chance I'm misunderstanding something, or maybe this is a small bug somewhere? Either way, I hope this information is helpful to you. Please let me know if there's any other information you need. Thank you for your help!
Hi cobyqa team!
In a recent bug-report in the scipy repo I've found that the COBYQA optimizer doesn't always seems to respect the specified boundaries. Unfortunately, it was hard to simplify the issue to demonstrate it in an isolated manner, but I've done my best.
The context is a python package that's designed to optimize marine propellers. Each propeller is modeled using a large polynomial function that has been fit on a large set of experimental data. Using these polynomials, the performance of a propeller can be predicted. I've isolated the issue into a specific unit-test:
In one of the constraint function evaluations, the second argument of the function (
area_ratio) is set to0.088, which is out of bounds. The output of the function is shown below:There's a good chance I'm misunderstanding something, or maybe this is a small bug somewhere? Either way, I hope this information is helpful to you. Please let me know if there's any other information you need. Thank you for your help!