有没有办法在scipy.minimize中自动生成多个约束的字典列表?当我使用以下代码时(其中列表约束是同一环上的sage多元多项式列表)
cons = [{'type': 'eq', 'fun': lambda s: ((constraint[0])(*s))},
{'type': 'eq', 'fun': lambda s: ((constraint[1])(*s))},
{'type': 'eq', 'fun': lambda s: ((constraint[2])(*s))},
{'type': 'eq', 'fun': lambda s: ((constraint[3])(*s))}]
y0 = [.5 for xx in x]
bnds = tuple([(0.0, 1.0) for xx in x])
ssoln = scipy.optimize.minimize(HH, y0, jac=dHH, method='SLSQP', bounds=bnds, constraints=cons)
print ssoln
我的输出是
status: 0
success: True
njev: 14
nfev: 22
fun: -2.2669026273652237
x: array([ 0.034829615490635, 0.933405952554424, 0.93340765416238 ,
0.093323548109654, 0.335713397575351, 0.413107862378296])
message: 'Optimization terminated successfully.'
jac: array([-3.321836605297572, 2.640225014918886, 2.640252390205999,
-2.273713195767229, -0.682455873949375, -0.351132324172705, 0. ])
nit: 14
但是,如果我尝试通过
创建利弊cons=[]
for ii in range(len(constraint)):
cons.append({'type': 'eq', 'fun': lambda s: ((constraint[ii])(*s))})
使用
最小化失败status: 6
success: False
njev: 1
nfev: 1
fun: -4.1588830833596715
x: array([ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5])
message: 'Singular matrix C in LSQ subproblem'
jac: array([ 0., 0., 0., 0., 0., 0., 0.])
nit: 1
我的sage多项式的列表,约束可能会在长度方面发生变化,从问题到问题的多项式数量也会发生变化,并且我不想对每个问题进行硬编码,如上面首先给出的那样。有没有办法实现自动化?
以下有效,但据我所知,评估字符串不是最佳做法
str1='{\'type\': \'eq\', \'fun\': lambda s: ((constraint['
str2='])(*s))},'
mystr='['
for ii in range(len(constraint)):
mystr=mystr+str1+str(ii)+str2
mystr=mystr+']'
cons = eval(mystr)
答案 0 :(得分:0)
问题出在你的循环中。 lambda
运算符执行称为 lazy 的评估。在循环结束时,cons的lambda函数将对ii
的最后一个值而不是对每个索引执行该函数。
要执行严格评估,可以使用python partial
模块中的functools
对象(在python 2或python 3中)
以lambda
为例:
constraint = (lambda x: x, lambda x: x**2, lambda x: x**3, lambda x: x**4)
cons=[]
for ii in range(len(constraint)):
# lambda s will evaluate the last value of ii
cons.append({'type': 'eq', 'fun': lambda s: ((constraint[ii])(s))})
print([i['fun'](2) for i in cons])
# The value of ii is 3, so it will always call lambda x: x**4
>> [16, 16, 16, 16]
from functools import partial
def f_constraint(s, index):
return constraint[index](s)
cons=[]
for ii in range(len(constraint)):
# the value of ii is set in each loop
cons.append({'type': 'eq', 'fun': partial(f_constraint, index=ii)})
print([i['fun'](2) for i in cons])
>> [2, 4, 8, 16]
用* s替换s以匹配您的定义:
from functools import partial
def f_constraint(s, index):
return constraint[index](*s)
cons=[]
for ii in range(len(constraint)):
cons.append({'type': 'eq', 'fun': partial(f_constraint, index=ii)})
希望有帮助!