Нелинейная целочисленная арифметика неразрешима.Это означает, что не существует процедуры принятия решения, которая могла бы решить, что произвольные нелинейные целочисленные ограничения могут быть выполнены.Это то, что z3 говорит вам, когда в ответе на ваш запрос говорит «неизвестно».
Это, конечно, не означает, что на отдельные случаи невозможно ответить.У Z3 есть определенная тактика, которую он применяет для решения таких формул, но он по сути ограничен в том, что он может обрабатывать.Ваша проблема относится к той категории: та, которую Z3 просто не в состоянии решить.
Z3 имеет специальную тактику NRA (нелинейная вещественная арифметика), которую вы можете использовать.Он по существу рассматривает все переменные как вещественные, решает проблему (нелинейная вещественная арифметика разрешима, и z3 может найти все алгебраические вещественные решения), а затем проверяет, являются ли результаты на самом деле целочисленными.Если нет, он пытается другое решение по реалам.Иногда эта тактика может обрабатывать нелинейные целочисленные задачи, если вам удастся найти правильное решение.Вы можете запустить его, используя:
(check-sat-using qfnra)
К сожалению, это не решит вашу конкретную проблему в то время, когда я позволил ему работать.(Более 10 минут.) Маловероятно, что он когда-нибудь найдет правильное решение.
У вас действительно не так много вариантов.Решатели SMT просто не подходят для нелинейных целочисленных задач.Фактически, как я упоминал выше, не существует инструмента, который мог бы обрабатывать произвольные нелинейные целочисленные задачи из-за неразрешимости;но некоторые инструменты работают лучше, чем другие, в зависимости от алгоритмов, которые они используют.
Когда вы говорите z3, что такое a
и b
, вы по существу отбираете большую часть нелинейности, а остальное становитсяпросты в обращении.Вполне возможно, что вы сможете найти последовательность применяемых тактик, которая решит ваш оригинал, но такие приемы очень хрупки на практике и их нелегко обнаружить;поскольку вы по сути вводите эвристику в поиск, и у вас нет большого контроля над тем, как она себя ведет.
Примечание: ваш скрипт может быть немного улучшен.Чтобы выразить, что все числа разные, используйте отдельный предикат:
(assert (distinct (a b c)))
(assert (distinct (d e f)))