【问题标题】:Adding multiple constraints to scipy minimize, autogenerate constraint dictionary list?添加多个约束到 scipy 最小化,自动生成约束字典列表?
【发布时间】:2014-12-26 16:01:53
【问题描述】:

有没有办法在 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 多项式列表(约束)的长度和多项式的数量可能会因问题而异,我不想像上面首先针对每个问题给出的那样对 cons dict 列表进行硬编码。有没有办法实现自动化?

以下工作,但我知道这不是评估字符串的最佳实践

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)

【问题讨论】:

  • 我自己最近也遇到了这个问题。你有没有找到不涉及评估字符串的解决方案?

标签: python numpy scipy sage


【解决方案1】:

问题出在你的循环中。 lambda 运算符执行所谓的 lazy 评估。在循环结束时,lambda cons 对 ii 的最后一个值执行函数,而不是在每个索引上。

要执行严格评估,您可以使用python functools 模块中的partial 对象(在python 2python 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)})

希望对你有帮助!

【讨论】:

    【解决方案2】:
    def wrapper(f, *add_args):
      def inner(*args):
        lt_args=list(args)
        lt_args.extend(add_args)#this arguments will be thus added after so see the positional argument of the parent function to 
        
        return f(*lt_args)
      return inner
    
    
    
    def constraint(M,i):
      global bb
      return M - bb[i] 
    
    lt_fn=[]
    # const=wrapper(const,)
    lt_fn=[wrapper(constraint,i) for i in range(len(bb))]
    
    
    [f(100) for f in lt_fn]
    

    这将像内部(100)内部(100)内部(100)内部(100)内部(100)__>约束(100,0),约束(100,1),约束(100,2),约束(100,3)约束(100,4)

    【讨论】:

      猜你喜欢
      • 2013-12-03
      • 1970-01-01
      • 2016-05-27
      • 1970-01-01
      • 2020-08-08
      • 1970-01-01
      • 2017-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多