#optimization #smt #z3py
Вопрос:
У меня возникли проблемы с определением объективной функции в задаче SMT с z3py.
Длинная история, короче говоря, мне нужно оптимизировать размещение небольших блоков внутри доски, которая имеет фиксированную ширину, но переменную высоту.
У меня есть массив координат (представленный массивом целых чисел длиной 2) и список целых чисел (представляющих высоту размещаемого блока).
# [x,y] list of integer variables
P = [[Int("x_%s" % (i 1)), Int("y_%s" % (i 1))]
for i in range(blocks)]
y = [int(b) for a, b in data[2:]]
Я определил целевую функцию следующим образом:
obj= Int(max([P[i][1] y[i] for i in range(blocks)]))
Он вычисляет максимальную высоту доски с учетом начальных координат блоков и их высоты.
Я знаю, что это могло бы быть лучше, но я думаю, что проблема была бы такой же, даже с другим определением.
В любом случае, если я запущу свой код, в строке целевой функции возникнет следующая ошибка:
«вызовите исключение Z3Exception(«Символические выражения не могут быть приведены к конкретным логическим значениям»)».
Во время отладки я видел, что это P[i][1], которое выдает ошибку, и я думаю, что это потому, что программа читает «y_i 3» (например), и они не могут быть добавлены вместе.
Дело в том, что очевидно, что целевая функция зависит от переменных проблемы, так как же я могу избавиться от этой ошибки? Есть ли другое место, где я должен определить целевую функцию, чтобы она ждала создания экземпляра массива P, прежде чем что-либо делать?
Полный код:
from z3 import *
from math import ceil
width = 8
blocks = 4
x = [3,3,5,5]
y = [3,5,3,5]
height = ceil(sum([x[i] * y[i] for i in range(blocks)]) / width) 1
# [blocks x 2] list of integer variables
P = [[Int("x_%s" % (i 1)), Int("y_%s" % (i 1))]
for i in range(blocks)]
# value/ domain constraint
values = [And(0 <= P[i][0], P[i][0] <= width - 1, 0 <= P[i][1], P[i][1] <= height - 1)
for i in range(blocks)]
obj = Int(max([P[i][1] y[i] for i in range(blocks)]))
board_problem = values # other constraints I've not included for brevity
o = Optimize()
o.add(board_problem)
o.minimize(obj)
if (o.check == 'unsat'):
print("The problem is unsatisfiable")
else:
print("Solved")
Комментарии:
1. Пожалуйста, опубликуйте свой код, который вызывает проблему, которую люди могут загрузить непосредственно сами, чтобы увидеть ошибку, которую вы видите. Конечно, чем меньше, тем лучше. То есть вся программа, а не только отдельные строки из нее.
2. Без доступа к
instancestxtins-1.txt
файлу люди не смогут запустить вашу программу. Можете ли вы избавиться от зависимости от этого файла?
Ответ №1:
Проблема здесь в том, что вы вызываете Python max
для символьных значений, который не предназначен для работы с символическими выражениями. Вместо этого определите символическую версию max и используйте ее:
# Return maximum of a vector; error if empty
def symMax(vs):
m = vs[0]
for v in vs[1:]:
m = If(v > m, v, m)
return m
obj = symMax([P[i][1] y[i] for i in range(blocks)])
С учетом этого изменения ваша программа будет работать и печататься Solved
при запуске.