Z3: Извлечение значений экзистенциальной модели

Я играю с решателем Z3 QBVF и задаюсь вопросом, можно ли извлечь значения из экзистенциального утверждения. А именно, скажем, у меня есть следующее:

(assert (exists ((x (_ BitVec 16))) (forall ((y (_ BitVec 16))) (bvuge y x))))

В основном это говорит о том, что существует «наименьшее» 16-битное беззнаковое значение. Тогда я могу сказать:

(check-sat)
(get-model)

И Z3-3.0 радостно отвечает:

sat
(model  (define-fun x!0 () (_ BitVec 16)
#x0000)
)

Что действительно круто. Но я хочу иметь возможность извлекать части этой модели с помощью get-value. Неудивительно, что ничего из следующего не работает

(get-value (x))
(get-value (x!0))

В каждом случае Z3 справедливо жалуется, что такой константы нет. Ясно, что у Z3 есть эта информация, о чем свидетельствует ответ на вызов (check-sat). Есть ли способ автоматически получить доступ к экзистенциальному значению через get-value или какой-либо другой механизм?

Спасибо..


person Z3-Experimenter    schedule 24.08.2011    source источник


Ответы (1)


В Z3 get-value позволяет пользователю ссылаться только на «глобальные» объявления. Экзистенциальная переменная x является локальным объявлением. Таким образом, к нему нельзя получить доступ с помощью get-value. По умолчанию Z3 устраняет экзистенциальные переменные, используя процесс, называемый «сколемизацией». Идея состоит в том, чтобы заменить экзистенциальные переменные новыми константами и функциональными символами. Например, формула

exists x. forall y. exists z. P(x, y, z)

превращается в

forall y. P(x!1, y, z!1(y))

Обратите внимание, что z становится функцией, потому что выбор z может зависеть от y. В Википедии есть статья о нормальной форме skolem.

При этом я так и не нашел удовлетворительного решения проблемы, которую вы описали. Например, в формуле может быть много разных экзистенциальных переменных с одинаковыми именами. Таким образом, неясно, как однозначно ссылаться на каждый экземпляр в команде get-value.

Возможный обходной путь для этого ограничения — применить шаг сколемизации «вручную» или, по крайней мере, для тех переменных, значение которых вы хотите узнать. Например,

(assert (exists ((x (_ BitVec 16))) (forall ((y (_ BitVec 16))) (bvuge y x))))

записывается как:

(declare-const x (_ BitVec 16))
(assert (forall ((y (_ BitVec 16))) (bvuge y x)))
(check-sat)
(get-value x)

Если экзистенциальная переменная вложена в универсальный квантификатор, такой как:

(assert (forall ((y (_ BitVec 16))) (exists ((x (_ BitVec 16))) (bvuge y x))))
(check-sat)
(get-model)

Для получения значения x для каждого y можно использовать новую функцию skolem. Приведенный выше пример становится:

(declare-fun sx ((_ BitVec 16)) (_ BitVec 16))
(assert (forall ((y (_ BitVec 16))) (bvuge y (sx y))))
(check-sat)
(get-model)

В этом примере sx — это свежая функция. Модель, созданная Z3, назначит интерпретацию для sx. В версии 3.0 интерпретация является функцией идентификации. Эту функцию можно использовать для получения значения x для каждого y.

person Leonardo de Moura    schedule 24.08.2011
comment
Спасибо, Леонардо. Это особенно хороший трюк, если экзистенциалы предшествуют универсалиям, и в этом случае скулемизация тривиальна. В общем случае вложенных/переменных квантификаторов лучшим решением может быть пометка пользователем каким-либо явным образом, подобно подсказкам в ACL2. Я полагаю, что пользователь должен убедиться, что узлы помечены уникальным образом. Что-то вроде (псевдосинтаксис SMT-Lib2): exists ((x (_ BitVec 16) :model_name "x")) ... Это может нарушить чистую совместимость SMT-Lib, но это может быть хорошим компромиссом, учитывая, что Z3 так или иначе раздвигает границы. - person Z3-Experimenter; 25.08.2011
comment
Спасибо за предложение. Я рассмотрю возможность для будущих версий Z3. Однако пользователь не будет контролировать сигнатуру функционального символа skolem, сгенерированного Z3. Z3 выполняет множество упрощений перед сколемизацией, а шаг сколемизации пытается минимизировать количество зависимостей от универсальных переменных. Я обновил свой ответ примером того, как извлечь экзистенциальную переменную, вложенную в универсальный квантификатор. - person Leonardo de Moura; 25.08.2011