Scipy optimize.minimize function

老子叫甜甜 提交于 2020-01-17 15:00:29

问题


I try to solve nonlinear programming task using scipy.optimize.minimize

max r
x1**2 + y1**2 <= (1-r)**2
(x1-x2)**2 + (y1-y2)**2 >= 4*r**2
0 <= r <= 1

So I've wrote next code:

r = np.linspace(0, 1, 100)
x1 = np.linspace(0, 1, 100)
y1 = np.linspace(0, 1, 100)
x2 = np.linspace(0, 1, 100)
y2 = np.linspace(0, 1, 100)


fun = lambda r: -r
cons = ({'type': 'ineq',
     'fun': lambda x1, r: [x1[0] ** 2 + x1[1] ** 2 - (1 - r) ** 2],
     'args': (r,)},
    {'type': 'ineq',
     'fun': lambda x2, r: [x2[0] ** 2 + x2[1] ** 2 - (1 - r) ** 2],
     'args': (r,)},
    {'type': 'ineq',
     'fun': lambda x1, x2, r: [(x1[0] - x2[0]) ** 2 + (x1[1] - x2[1]) ** 2 - 4 * r ** 2],
     'args': (x2, r,)})
bnds = ((0, 1), (-1, 1), (-1, 1), (-1, 1), (-1, 1))
x0 = [0, 0, 0, 0, 0]
minimize(fun, x0, bounds=bnds, constraints=cons)

But I've got next error

File "C:\Anaconda2\lib\site-packages\scipy\optimize\slsqp.py", line 377, in _minimize_slsqp
c = concatenate((c_eq, c_ieq))
ValueError: all the input arrays must have same number of dimensions

Please, help me to find out my mistakes and write correct code

UPD: Thx to @unutbu i've understand how to build it correctly.

fun = lambda x: -x[0]
cons = ({'type': 'ineq',
     'fun': lambda x: -x[1] ** 2 - x[2] ** 2 + (1 - x[0]) ** 2},
    {'type': 'ineq',
     'fun': lambda x: -x[3] ** 2 - x[4] ** 2 + (1 - x[0]) ** 2},
    {'type': 'ineq',
     'fun': lambda x: (x[1] - x[3]) ** 2 + (x[1] - x[4]) ** 2 - 4 * x[0] ** 2})
bnds = ((0, 1), (-1, 1), (-1, 1), (-1, 1), (-1, 1))
x0 = [0.5, 0.3, 0.5, 0.3, 0.5]
answer = minimize(fun, x0, bounds=bnds, constraints=cons)

In task of minimization we have to lead constraints to such form:

g(x) >= 0

that's why constraints look like in that way.


回答1:


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.])


来源:https://stackoverflow.com/questions/37777025/scipy-optimize-minimize-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!