Вы можете использовать distinct
(см. пример ):
(assert (distinct x1 ... x500))
AFAIK, обычно это внутреннее расширение в последовательности неравенств, как и в случае, представленном вами в ваш пример.
Обсуждение: Ниже следует чисто теоретическое обсуждение эффективности этого кодирования; z3
довольно эффективный SMT-решатель, поэтому вам, возможно, не понадобится делать что-то более сложное, чем просто запустить инструмент.
Отрицание равенства (например, (not (= x y))
) обычно разбивается на пару неравенства:
x < y \/ x > y
Допустим, x < y
и x > y
переименованы B1
и B2
соответственно, в SAT-механизм подается следующее предложение:
B1 \/ B2
Теперь, учитывая вашу проблему, вы получаете сотни этих предложений. Все они связаны друг с другом на уровне Linear Arithmeti c, но не на булевом уровне, на котором работает механизм SAT. Таким образом, механизм SAT может генерировать (значительное) количество противоречивых частичных присвоений истинности, которые обычно нарушают свойство транзитивности оператора <
, например,
x < y /\ y < z /\ z < x
. Эти конфликты будут обнаружены. решателем теории для LRA во время раннего сокращения вызовов и разрешается на логическом уровне путем изучения предложения конфликта, блокирующего недопустимое назначение.
Что можно попробовать:
если ваша проблема допускает такое упрощение (если имена x1 ... x500
могут считаться совершенно произвольными, их можно потом зашифровать ...) , вы можете получить более высокие результаты, навязывая строгий общий порядок по переменным x1 ... x500
, например
x1 < x2 /\ x2 < x3 /\ ... /\ x499 < x500
вы можете попробовать увеличить частоту раннего сокращения вызовов с помощью z3
, если это доступна опция (примечание: я не уверен, как часто z3
выполняет такие вызовы)
вы можете попробовать mcSAT это может хорошо сочетаться с такого рода ограничениями.
РЕДАКТИРОВАТЬ:
Если набор значений, которые могут быть назначены переменные x_i
конечны и несколько ограничены по размеру, вы можете попробовать подсчитать количество переменных x_i
с определенным значением, используя нестандартное расширение z3
для определения ограничений мощности, например,
(assert
((_ at-most 1)
(= x1 0)
(= x2 0)
...
(= x500 0)
)
)
...
% repeat for all possible values
...
Я не уверен относительно влияния этого изменения на производительность. В обычных обстоятельствах это положительно скажется на производительности, поскольку ранее обнаруживаются конфликтующие назначения (см., Например, [1] ). Однако вы имеете дело с довольно большим количеством переменных и большой областью значений-кандидатов для переменных x_i
, поэтому сглаживание поиска на логическом уровне может оказаться излишним.