在 addConstraint 中使用变量会产生错误的答案,但不使用变量可以正常工作

using a variable in addConstraint produces a wrong answer but not using variables works fine

如果这样做,我的代码可以正常工作

from constraint import *
import itertools
def main():
    problem = Problem()
    x = [0,1,2,3]
    f = list(itertools.product(x,x,x,x))

    problem.addVariable("a", f)

    problem.addConstraint(lambda a: a[0] == a.count(0), "a",)

    problem.addConstraint(lambda a: a[1] == a.count(1), "a",)

    problem.addConstraint(lambda a: a[2] == a.count(2), "a",)

    problem.addConstraint(lambda a: a[3] == a.count(3), "a",)    

    solutions = problem.getSolutions()
    print "Found %d solutions!" % len(solutions)

答案是[{'a': (2, 0, 2, 0)}, {'a': (1, 2, 1, 0)}]

但如果我使用变量,它就会变得混乱

from constraint import *
import itertools
def main():
    problem = Problem()
    x = [0,1,2,3]
    f = list(itertools.product(x,x,x,x))

    problem.addVariable("a", f)

    x = 0
    problem.addConstraint(lambda a: a[x] == a.count(0), "a",)
    x = 1
    problem.addConstraint(lambda a: a[x] == a.count(1), "a",)
    x = 2
    problem.addConstraint(lambda a: a[x] == a.count(2), "a",)

    problem.addConstraint(lambda a: a[3] == a.count(3), "a",)  

    solutions = problem.getSolutions()
    print "Found %d solutions!" % len(solutions)

结果是一个空列表。我希望能够将其置于循环中,但我不知道发生了什么。我可能只是遗漏了一些非常基本的东西,但它只有在我使用实数时才有效

问题是,当您 "add variables" 时,使用 lambda 函数查找的值是 调用的 ,而不是在定义它们时调用的。在这种情况下,我猜他们直到 problem.getSolutions() 才会被调用,这意味着 x 的值在您的每个函数调用中都将是 2 (而不是 012 分别与初始代码相同)。

这是 python 代码中的 very common "gotcha",您可以通过设置默认参数来修复它(因为在创建函数时对这些参数进行一次评估)。

lambda a, x=x: a[x] == a.count(0)