Your parameter space appears to be 5-dimensional. A point in your parameter
space would be z = (r, x1, y1, x2, y2)
. Therefore the function to be minimized
-- and also the constraint functions -- should accept a point z
and
return a scalar value.
Thus instead of
fun = lambda r: -r
use
def func(z):
r, x1, y1, x2, y2 = z
return -r
and instead of
lambda x1, r: [x1[0] ** 2 + x1[1] ** 2 - (1 - r) ** 2]
use
def con1(z):
r, x1, y1, x2, y2 = z
return x1**2 + y1**2 - (1-r)**2
and so on.
Note that simple constraints such as 0 <= r <= 1
can be handled by setting the bounds
parameter instead of defining a constraint. And if the bounds for x1
, y1
, x2
, y2
are from -1 to 1, then you might also want change
x1 = np.linspace(0, 1, 100)
...
to
x1 = np.linspace(-1, 1, 100)
...
However, the arrays r
, x1
, y1
, x2
, y2
are not needed to minimize func
, so you could just as well eliminate them from the script entirely.
import numpy as np
import scipy.optimize as optimize
"""
max r
x1**2 + y1**2 <= (1-r)**2
(x1-x2)**2 + (y1-y2)**2 >= 4*r**2
0 <= r <= 1
"""
def func(z):
r, x1, y1, x2, y2 = z
return -r
def con1(z):
r, x1, y1, x2, y2 = z
return x1**2 + y1**2 - (1-r)**2
def con2(z):
r, x1, y1, x2, y2 = z
return 4*r**2 - (x1-x2)**2 - (y1-y2)**2
cons = ({'type': 'ineq', 'fun': con1}, {'type': 'ineq', 'fun': con2},)
bnds = ((0, 1), (-1, 1), (-1, 1), (-1, 1), (-1, 1))
guess = [0, 0, 0, 0, 0]
result = optimize.minimize(func, guess, bounds=bnds, constraints=cons)
print(result)
yields
fun: -1.0
jac: array([-1., 0., 0., 0., 0., 0.])
message: 'Optimization terminated successfully.'
nfev: 14
nit: 2
njev: 2
status: 0
success: True
x: array([ 1., 0., 0., 0., 0.])