我使用带有约束的scipy.optimize.minimize。文档中的示例(http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.optimize.minimize.html)用于约束:
cons = ({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + 2},
{'type': 'ineq', 'fun': lambda x: -x[0] - 2 * x[1] + 6},
{'type': 'ineq', 'fun': lambda x: -x[0] + 2 * x[1] + 2})
我想做类似的事情但是在循环中生成这个序列的元素,但是我遇到了麻烦。
我曾尝试将缺点视为一个元组,与上述形式相同:
cons = (,)
for i in range(4):
cons += ({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + i})
但我得到TypeError: unsupported operand type(s) for +=: 'dict' and 'dict'
。
我还尝试使用str
和eval
:
cons = (str({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1]}))
for i in range(3):
cons += (str({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + i + 1}))
cons = eval(cons)
但是那也没有用,我得到像
这样的东西 cons = eval(cons)
。
File "<string>", line 1
{'fun': <function <lambda> at 0x062964F0>, 'type': 'eq'}{'fun': <function <lambda> at 0x062964F0>, 'type': 'eq'}{'fun': <function <lambda> at 0x062964F0>, 'type': 'eq'}{'fun': <function <lambda> at 0x062964F0>, 'type': 'eq'}
^
SyntaxError: invalid syntax
一些帮助会很棒!
答案 0 :(得分:1)
创建元组后,您无法修改其中的元素数量或其顺序。
你可以这样做:
cons = []
for i in range(4):
cons.append({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + i})
这会给你一个词典列表。列表完成后,如果要将其更改为元组,则可以执行以下操作:
cons = tuple(cons)
结果:
>>> cons
({'fun': <function <lambda> at 0x106e2cb18>, 'type': 'ineq'},
{'fun': <function <lambda> at 0x106e2cf50>, 'type': 'ineq'},
{'fun': <function <lambda> at 0x106e335f0>, 'type': 'ineq'},
{'fun': <function <lambda> at 0x106e33cf8>, 'type': 'ineq'})
-
请注意,Raymond Hettinger他自己说not so long ago:
通常,列表用于循环;结构的元组。列表是 同质;元组异构。列表可变长度。
因此,在您的情况下,您可能希望保留列表,除非某些第三方模块需要元组。
答案 1 :(得分:0)
而不是添加dict(括号在这里没有做任何事情):
for i in range(4):
cons += ({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + i})
添加一个元组,在dict之后添加一个逗号:
for i in range(4):
cons += ({'type': 'ineq', 'fun': lambda x: x[0] - 2 * x[1] + i},)
>>> cons
({'fun': <function <lambda> at 0xb746de2c>, 'type': 'ineq'}, {'fun': <function <lambda> at 0xb747656c>, 'type': 'ineq'}, {'fun': <function <lambda> at 0xb74765a4>, 'type': 'ineq'}, {'fun': <function <lambda> at 0xb74765dc>, 'type': 'ineq'})
-
请注意,正如@Jivan在答案中指出的那样,您应该使用列表进行此类工作。
答案 2 :(得分:0)
这是一个较老的问题,但两个提议的解决方案似乎都是错误的。或者我错过了什么?
def generate_constraints_wrong(n_params):
cons = []
for i in range(n_params):
cons.append({'type': 'ineq', 'fun': lambda x: x[i]})
return tuple(cons)
def generate_constraints_wrong2(n_params):
cons = tuple()
for i in range(n_params):
cons += ({'type': 'ineq', 'fun': lambda x: x[i]},)
return cons
def generate_constraints_right(n_params):
# let's create a function generator that uses closure to pass i to the generated function
def wrapper_fun(x, i):
def fun(x):
return x[i]
return fun
cons = []
for i in range(n_params):
f = wrapper_fun(x, i)
cons.append({'type': 'ineq', 'fun': f})
return tuple(cons)
# verify the generated functions
n_params = 3
x = [1,10, 100]
cons1 = generate_constraints_wrong(n_params)
cons2 = generate_constraints_wrong2(n_params)
cons3 = generate_constraints_right(n_params)
print(cons1[0]['fun'](x)) # this should be 1 but instead we end up modifying all of our lambda objects to have the last i
print(cons1[1]['fun'](x))
print(cons2[0]['fun'](x))
print(cons2[1]['fun'](x))
print(cons3[0]['fun'](x))
print(cons3[1]['fun'](x))
打印:
100
100
100
100
1
10
问题是每个lambda的闭包指向对象i,而不是指向特定循环迭代时对象的值。有关更多详情,请参阅 Python lambda closure scoping