Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
197 views
in Technique[技术] by (71.8m points)

python - Scipy optimize.minimize function

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:Anaconda2libsite-packagesscipyoptimizeslsqp.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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...