用Z3编码部分映射

用Z3编码部分映射,z3,smt,Z3,Smt,我想在Z3中对部分映射进行编码,支持询问映射是否为某个键定义 它还应该支持操作(update_map m1 m2),该操作使用m2中的映射更新m1,以便m2的映射覆盖m1的映射 我尝试使用数组和自定义的选项数据类型对其进行编码,并公理化地指定了update\u map函数。然而,Z3似乎甚至不能处理我的update\u map规范:它在以下代码中返回unknown: (declare-datatypes (T) ((option None (Some (option-value T))))) (

我想在Z3中对部分映射进行编码,支持询问映射是否为某个键定义

它还应该支持操作
(update_map m1 m2)
,该操作使用
m2
中的映射更新
m1
,以便
m2
的映射覆盖
m1
的映射

我尝试使用数组和自定义的
选项
数据类型对其进行编码,并公理化地指定了
update\u map
函数。然而,Z3似乎甚至不能处理我的
update\u map
规范:它在以下代码中返回
unknown

(declare-datatypes (T) ((option None (Some (option-value T)))))
(define-sort map (K V) (Array K (option V)))

(declare-sort V)
(declare-sort K)

(define-const empty_map (map K V)
  ((as const (Array K (option V))) None))

(define-fun get ((m (map K V)) (k K)) (option V)
  (select m k))

(define-fun put ((m (map K V)) (k K) (v V)) (map K V)
  (store m k (Some v)))

(declare-fun update_map ((map K V) (map K V)) (map K V))

(assert (forall ((m1 (map K V)) (m2 (map K V)) (k K))
    (=> (= (get m2 k) None)
        (= (get (update_map m1 m2) k) (get m1 k)))))
(assert (forall ((m1 (map K V)) (m2 (map K V)) (k K) (v V))
    (=> (= (get m2 k) (Some v))
        (= (get (update_map m1 m2) k) (Some v)))))

(check-sat)
所以我有两个问题:

  • 有没有更好的方法对地图进行编码,使我能够证明关于
    更新地图的事实
  • 有人能分享一些关于Z3为什么不理解这个规范的直觉吗?如中所述,是什么“核心特性”使Z3难以做到这一点?[我已经知道量词被认为是硬的,一阶逻辑是不可判定的,我在寻找更具体的;-)]

  • Z3无法证明可满足性,即无法为您的公式构建模型。不幸的是,我不知道更确切的原因——可能是Z3对数组、量词或组合的模型查找能力受到限制

    如果您最终对寻找模型不感兴趣,而是对反例(unsat核心)感兴趣,那么添加一个不可满足的公式,并尝试获得unsat。例如,尝试以下内容(免责声明:我并没有真正尝试过,但我相信你已经明白了):


    作为在数组顶部对映射进行公理化的替代方法,请查看。这些公理是用Boogie语言提供的,但到Z3的翻译通常是直截了当的。

    Z3无法证明可满足性,即无法为公式构建模型。不幸的是,我不知道更确切的原因——可能是Z3对数组、量词或组合的模型查找能力受到限制

    如果您最终对寻找模型不感兴趣,而是对反例(unsat核心)感兴趣,那么添加一个不可满足的公式,并尝试获得unsat。例如,尝试以下内容(免责声明:我并没有真正尝试过,但我相信你已经明白了):


    作为在数组顶部对映射进行公理化的替代方法,请查看。公理是用Boogie语言提供的,但是到Z3的翻译通常是直接的。

    我尝试了一些查询,比如
    (assert(不是((get(update_-map(put empty_-map 2-2)(put empty_-map 1-1))1))
    ,但总是得到
    未知的
    。实际上,我对寻找作为引理反例的模型很感兴趣,所以我对获得
    sat
    答案感兴趣,然后我进行优化,直到得到
    unsat
    ,在这一点上,我知道我已经证明了我的引理。我试图直接使用Dafny进行这个例子,但第一次尝试时效果不太好,看到这个问题:我尝试了一些查询,比如
    (assert(不是((get(update_-map(put empty_-map 2-2)(put empty_-map 1-1))1))
    ,但总是得到
    未知的
    。实际上,我对寻找作为引理反例的模型很感兴趣,所以我对获得
    sat
    答案很感兴趣,然后我进行优化,直到得到
    unsat
    ,在这一点上我知道我已经证明了我的引理。我试图直接使用Dafny来处理这个例子,但在第一次尝试时效果不太好,请看这个问题:
    (assert (not
      (=
        (get
          (update_map
            (put empty_map 2 -2)
            (put empty_map 1 -1))
          -1))))