在循环中添加约束的问题

问题描述

我有这个:

import constraint

p = constraint.Problem()

t = [0,5]
c = [3,7]

s = range(len(t))
n = 12

p.addVariables([str(i) for i in s],range(n))

p.addConstraint(lambda x: (x+t[0])%n in c,('0'))                              
p.addConstraint(lambda x: (x+t[1])%n in c,('1'))                              

l = [list(i.values()) for i in p.getSolutions()]

print(l)

然后输出

[[7,10],[7,2],[3,2]]

但我想在循环中添加约束,所以我这样做而不是两行p.addConstraint

for i in s:
    p.addConstraint(lambda x: (x+t[i])%n in c,(str(i)))

我希望这会给出相同的输出,但我得到了这个:

[[10,[10,[2,2]]    

我错过了什么?

解决方法

您可以使用创建函数的函数,然后在 for 循环中创建函数并将它们添加为约束。

import constraint

p = constraint.Problem()

t = [0,5]
c = [3,7]

s = range(len(t))
n = 12

p.addVariables([str(i) for i in s],range(n))

def generate_constrained_func(t,n,c):
    def constraint_func(x):
        return ((x+t)%n in c)
    return constraint_func

for idx,t_constraint in enumerate(t):
    p.addConstraint(generate_constrained_func(t_constraint,c),(str(idx)))
    
l = [list(i.values()) for i in p.getSolutions()]

print(l)

输出:

[[7,10],[7,2],[3,2]]
,

我确实设法用 eval 解决了它,但我听说这是一个危险的函数,所以我试图避免它。但如果没有人想出更好的方法,那就是我使用的:

for i in s:
    eval('p.addConstraint(lambda x: (x+t[%d])%%n in c,(str(i)))' % i)

并没有解释为什么问题中的代码不起作用,我仍然对此感到好奇。