Reputation: 23
my code is working if done like so
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)
the answer would be [{'a': (2, 0, 2, 0)}, {'a': (1, 2, 1, 0)}]
but if I use variables it goes haywire
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)
which results to an empty list. I want to be able to put this in a loop but I don't know what's going on. I may just be missing something very basic but it only works if I use real numbers
Upvotes: 2
Views: 216
Reputation: 309831
The problem is that when you "add variables", the values are looked up with the lambda functions are called, not when they are defined. In this case, I'm guessing they don't get called until problem.getSolutions()
which means that the value of x
will be 2
in each of your function calls (instead of 0
, 1
and 2
respectively as in the initial code).
This is a very common "gotcha" in python code and you can fix it by setting a default argument (as those get evaluated once, when the function is created).
lambda a, x=x: a[x] == a.count(0)
Upvotes: 3