Проблемы с добавлением ограничений в цикл

У меня есть это:

      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, 10], [3, 2]]

Но я хочу добавить ограничения в цикл, поэтому я сделал это вместо двух p.addConstraint линии:

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

Я ожидал, что это даст тот же результат, но вместо этого получил следующее:

      [[10, 10], [10, 2], [2, 10], [2, 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, n, c), (str(idx)))
    
l = [list(i.values()) for i in p.getSolutions()]

print(l)

Выход:

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

Мне удалось решить это с помощью eval, но я слышал, что это опасная функция, поэтому стараюсь ее избегать. Но если никто не придумает ничего лучше, я использую вот что:

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

Это не объясняет, почему код в вопросе не работает, и мне все еще любопытно.

Другие вопросы по тегам