Я смущен и изо всех сил пытаюсь понять, как связаны два разных формата ввода для движка с фиксированной точкой Z3. Краткий пример: предположим, я хочу доказать существование отрицательных чисел. Я объявляю функцию, которая возвращает 1 для неотрицательных чисел и 0 для отрицательных, а затем запрашивает решающую программу об отказе, если есть аргументы, для которых функция возвращает 0. Но есть одно ограничение: я хочу, чтобы решатель отвечал sat
, когда существует хотя бы один отрицательное число и unsat
, если все числа неотрицательны.
Это тривиально с использованием формата declare-rel
и query
:
(declare-rel f (Int Int))
(declare-rel fail ())
(declare-var n Int)
(declare-var m Int)
(rule (=> (< n 0) (f n 0)))
(rule (=> (>= n 0) (f n 1)))
(rule (=> (and (f n m) (= m 0)) fail))
(query fail)
Но при использовании чистого формата SMT-LIB2 (с forall
) это становится непросто. Например, простой
(set-logic HORN)
(declare-fun f (Int Int) Bool)
(declare-fun fail () Bool)
(assert (forall ((n Int))
(=> (< n 0) (f n 0))))
(assert (forall ((n Int))
(=> (>= n 0) (f n 1))))
(assert (forall ((n Int) (m Int))
(=> (and (f n m) (= m 0)) fail)))
(assert (not fail))
(check-sat)
возвращает unsat
. Неудивительно, что изменение (= m 0)
на (= m 1)
приводит к тому же. Мы можем получить sat
, только подразумевая fail
из (= m 2)
. Проблема в том, что я не могу понять, как задать решателю, используя этот формат.
Насколько я понимаю сейчас, при использовании forall
-формы мы можем попросить найти только ∀-решения, т.е. ответ sat
означает, что решателю удалось найти интерпретацию (или инвариант), удовлетворяющую всем утверждениям для всех strong> values, а unsat
означает, что таких функций нет. Другими словами, он пытается доказать, помещая «доказательство» (инвариант) в модель (очевидно, когда sat
).
Напротив, когда query
поиск решения в решателе формата declare-rel
ищет в решении некоторые переменные, точно так же, как ограничения находятся под ∃-квантификатором. Другими словами, это контрпример. Он может вывести инвариант только в случае unsat
.
У меня есть пара вопросов:
- Я правильно понимаю? Я чувствую, что упускаю некоторые ключевые идеи. Например, общее представление о том, как выразить
(query ...)
через(assert (forall ...))
, будет действительно полезным (и ответит на вопрос 2 автоматически). - Есть ли способ решить такие ∃-ограничения (вывод
sat
при обнаружении контрпримера) с помощью чистого формата SMT-LIB2? Если да, то как?