Различные способы аксиоматизации содержащей функции для списков Z3

Аксиоматизация операции contains в списках (в Rise4Fun) как

(declare-fun Seq.in ((List Int) Int) Bool)

(assert (forall ((e Int))
  (not (Seq.in nil e))))

(assert (forall ((xs (List Int)) (e Int))
  (iff
    (not (= xs nil))
    (=
      (Seq.in xs e)
      (or
        (= e (head xs))
        (Seq.in (tail xs) e))))))

позволяет Z3 4.0 опровергнуть утверждение

(declare-const x Int)
(assert (Seq.in nil x))
(check-sat) ; UNSAT, as expected

В моих глазах эквивалентная аксиоматизация

(assert (forall ((xs (List Int)) (e Int))
  (ite (= xs nil)
    (= (Seq.in xs e) false)
    (=
      (Seq.in xs e)
      (or
        (= e (head xs))
        (Seq.in (tail xs) e))))))

приводит к unknown.

Может ли это быть проблемой с триггерами или есть что-то особенное для домена List, что может объяснить разницу в поведении?


person Malte Schwerhoff    schedule 20.06.2012    source источник
comment
Я не могу воспроизвести описанное вами поведение. Оба примера вернули мне unsat. Вот примеры: rise4fun.com/Z3/MPSp, rise4fun.com/Z3/1fxc   -  person Leonardo de Moura    schedule 20.06.2012
comment
Не обращайте внимания на комментарий выше. Я не заметил, что вы отключили движок :mbqi.   -  person Leonardo de Moura    schedule 20.06.2012


Ответы (1)


Ваш скрипт наrise4fun отключает движок :mbqi. Таким образом, Z3 попытается решить проблемы, используя только E-сопоставление. Когда шаблоны (также известные как триггеры) не предоставляются, Z3 выводит триггеры для нас. Z3 использует множество эвристик для определения шаблонов/триггеров. Один из них имеет отношение к вашему сценарию и объясняет, что происходит. Z3 никогда не выберет паттерн/триггер, создающий «совпадающую петлю». Мы говорим, что шаблон/триггер P создает цикл сопоставления для квантификатора Q, когда экземпляр Q создает новое сопоставление для P. Давайте рассмотрим квантификатор

(assert (forall ((xs (List Int)) (e Int))
  (ite (= xs nil)
    (= (Seq.in xs e) false)
    (=
      (Seq.in xs e)
      (or
        (= e (head xs))
        (Seq.in (tail xs) e))))))

Z3 не выберет (Seq.in xs e) в качестве шаблона/триггера для этого квантификатора, потому что это создаст соответствующий цикл. Предположим, у нас есть основной термин (Seq.in a b). Этот термин соответствует шаблону (Seq.in xs e). Создание экземпляра квантификатора с a приведет к b созданию термина (Seq.in (tail a) b), который также соответствует шаблону (Seq.in xs e). Создание квантификатора с (tail a) и b даст терм (Seq.in (tail (tail a)) b), который также соответствует шаблону (Seq.in xs e) и так далее.

Во время поиска Z3 будет блокировать совпадающие циклы, используя несколько порогов. Однако, как правило, страдает производительность. Таким образом, по умолчанию Z3 не будет выбирать (Seq.in xs e) в качестве шаблона. Вместо этого он выберет (Seq.in (tail xs) e). Этот шаблон не создает цикл сопоставления, но также не позволяет Z3 доказать, что второй и третий запросы неудовлетворительны. Любые ограничения механизма E-сопоставления обычно обрабатываются механизмом :mbqi. Однако в вашем скрипте :mbqi отключено.

Если вы предоставите шаблоны для второго и третьего запросов в вашем скрипте. Z3 докажет, что все примеры равны unsat. Вот ваш пример с явными шаблонами/триггерами:

http://rise4fun.com/Z3/DkZd

Первый пример выполняется даже без использования шаблонов, поскольку для доказательства того, что пример равен unsat, требуется только первый квантификатор.

(assert (forall ((e Int))
  (not (Seq.in nil e))))

Обратите внимание, что (Seq.in nil e) является идеальным образцом для этого квантификатора, и он выбран Z3.

person Leonardo de Moura    schedule 20.06.2012
comment
Большое спасибо за объяснение этого, я не знал, что Z3 будет избегать шаблонов, которые приводят к совпадению циклов. Можно ли увидеть шаблоны, которые выбирает Z3, если они не предоставлены, например, распечатав их на stdio? - person Malte Schwerhoff; 22.06.2012
comment
Неа. В Z3 4.0 нет хорошего способа получить предполагаемые закономерности. Согласен, это полезная информация. Я добавлю эту функцию для следующего выпуска. - person Leonardo de Moura; 22.06.2012