在我的代码中,我试图编写一个while循环,使用scipy.optimize.minimize使用SQSLP选项更新x的值,因为我有不等式和等式约束。除了更新x之外,这还会导致更新目标函数和约束中的值。
下面是调用在给定x
处更新约束和目标函数的所有函数的部分import numpy as np
from scipy.optimize import minimize
num_vars = 2
num_eq_cons = 1
num_ineq_cons = 1
# return the desired initial value for x
def x_init():
x = np.zeros([num_vars,1], dtype = float)
x[0] = 2
x[1] = 1
return x
# Objective
# needs the current value of x (x_k)
def eval_objective(x):
f = x[0]**2 + x[1]**2
return float(f)
# Inequality Constraints
# need the current value of x (x_k)
def eval_ineq_cons(x):
g = np.zeros([num_ineq_cons,1], dtype = float)
g[0] = x[0]**2 - x[1]
return g
# Equality Constraints
# need the current value of x (x_k)
def eval_eq_cons(x):
h = np.zeros([num_eq_cons, 1], dtype = float)
h[0] = 2 - x[0] - x[1]**2
return h
# Taylor series Approximations
# needs the current value of x
# For objective
def eval_part_obj(x):
dfdx = np.zeros([num_vars,1], dtype = float)
dfdx[0] = 2*x[0]
dfdx[1] = 2*x[1]
return dfdx
# For inequalities
def eval_part_ineq_cons(x):
dgdx = np.zeros([num_ineq_cons, num_vars], dtype = float)
dgdx[0,0] = 2*x[0]
dgdx[0,1] = -1.0
return dgdx
# For equalities
def eval_part_eq_cons(x):
dhdx = np.zeros([num_eq_cons, num_vars], dtype = float)
dhdx[0,0] = -1
dhdx[0,1] = -2*x[1]
return dhdx
x_k = x_init() # Initialization point
f_k = eval_objective(x_k)
dfdx = eval_part_obj(x_k)
g_k = eval_ineq_cons(x_k)
dgdx = eval_part_ineq_cons(x_k)
h_k = eval_eq_cons(x_k)
dhdx = eval_part_eq_cons(x_k)
以下代码是我收到错误的代码:
fun = lambda x_k1: f_k + dfdx[0]*(x_k1[0] - x_k[0]) + dfdx[1]*(x_k1[1] - x_k[1])
cons = ({'type': 'ineq',
'fun': lambda x_k1: g_k + np.dot(dgdx, (x_k1 - x_k)).squeeze(),
'jac': dgdx},
{'type': 'eq',
'fun': lambda x_k1: h_k + np.dot(dhdx, (x_k1 - x_k)).squeeze(),
'jac': dhdx})
bnds = [(.5, 2.5), (0,3)]
res = minimize( fun, x_k, method = 'SLSQP', bounds=bnds, constraints = cons)
print(res)
我获得的错误是:
Traceback (most recent call last):
File "SLPmain.py", line 104, in <module>
res = minimize( fun, x_k, method = 'SLSQP', bounds=bnds, constraints = cons)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/_minimize.py", line 358, in minimize
constraints, **options)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/slsqp.py", line 376, in _minimize_slsqp
for con in cons['eq']])
TypeError: 'numpy.ndarray' object is not callable
如果有更好的方式以更好的方式编写约束和目标函数,请告诉我!
答案 0 :(得分:0)
有两个明显的问题:
1,Jacobians对于不等式和等式约束都是array
而不是callables(函数),因为它们被定义为:
dgdx = eval_part_ineq_cons(x_k)
dhdx = eval_part_eq_cons(x_k)
它们是函数返回(因此array
s)不是函数。
2,约束函数返回不是标量,它们是array
s。 e.g:
g_k + np.dot(dgdx, (x_k1 - x_k)).squeeze()
纠正这种情况的方法取决于你的实际工作问题,还有其他选择:
(g_k + np.dot(dgdx, (x_k1 - x_k)).squeeze()).sum()
或
((g_k + np.dot(dgdx, (x_k1 - x_k)).squeeze())**2).sum() #sum of squares.
不平等约束的同样问题。
我怀疑这是因为fun
被fmin_slsqp
传递给eqcons
而不是f_eqcons
。如果您希望等于约束函数中的所有元素返回== 0,则可能应该直接使用fmin_slsqp
并传递约束函数f_eqcons
。
因此,它可以如下:
cons = ({'type': 'ineq',
'fun': lambda x_k1: (g_k + np.dot(dgdx, (x_k1 - x_k)).squeeze()).sum(),
'jac': eval_part_ineq_cons},
{'type': 'eq',
'fun': lambda x_k1: (h_k + np.dot(dhdx, (x_k1 - x_k)).squeeze()).sum(),
'jac': eval_part_eq_cons})
结果是:
In [31]:
res
Out[31]:
status: 9
success: False
njev: 101
nfev: 1385
fun: array([ 2.69798824])
x: array([ 1.89963627, 0.04972158])
message: 'Iteration limit exceeded'
jac: array([ 4., 2., 0.])
nit: 101
实际上,请注意优化失败。我怀疑当你有Jacobian约束时它不能保证工作。删除Jac,它会起作用(虽然可能不是你想要的方式)。
In [29]:
res
Out[29]:
status: 0
success: True
njev: 11
nfev: 122
fun: array([ 1.33333333])
x: array([ 0.5 , 2.16666667])
message: 'Optimization terminated successfully.'
jac: array([ 4., 2., 0.])
nit: 15