Вы бы записали сюръективность следующим образом:
N = BitVec('N', 32)
M = BitVec('M', 32)
s = Solver()
s.add(ForAll([N], f(N) != M))
r = s.check()
if r == sat:
print(s.model())
else:
print(r)
К сожалению, добавление кванторов к битовым векторам делает logi c неразрешимым в целом, и z3 просто сдается примерно через 10 секунд на моей машине :
unknown
В общем, добавление квантификаторов только сделает проблему очень сложной для z3 (или любого другого решателя SMT в этом отношении). Ваша исходная кодировка:
solve(N!=M, f(N) == f(M))
, вероятно, лучший способ кодировать эту проблему. Фактически, если вы измените диапазон с 10 на что-то меньшее (я пробовал до 3), z3 сравнительно быстро ответит unsat
. Но очевидно, что время решателя будет go экспоненциально по мере увеличения количества итераций в вашей функции f
.
Решатель SMT, вероятно, не лучший инструмент для доказательства такого свойства. Конечно, вы можете express таких ограничений, но в лучшем случае вы получите unknown
в качестве ответа, а в худшем - oop навсегда. Правильная программа доказательства теорем (например, Isabelle, HOL, Coq, ACL2 и др. c.) Предоставит гораздо лучшую (за счет меньшей автоматизации) платформу для выполнения этих доказательств.