您正在解决这些问题定期出现一个问题: 我怎么可以混合数据类型和数组(如套,多套或者范围 数据类型)?
如上Z3表示不支持在单个声明混合数据类型 和数组。 一种解决方案是开发用于 混合数据类型+阵列理论定制解算器。 Z3包含用于开发自定义解算器的编程式 API。
开发此示例 以说明编码理论与量词和触发器的功能和限制 仍然有用。 让我通过使用A来简化您的示例。 作为解决方法,您可以定义辅助排序。 解决方法并不理想,但。它说明了一些 公理'黑客'。它依赖于操作语义 如何在搜索过程中实例化量词。
(set-option :model true) ; We are going to display models.
(set-option :auto-config false)
(set-option :mbqi false) ; Model-based quantifier instantiation is too powerful here
(declare-sort SetA) ; Declare a custom fresh sort SetA
(declare-datatypes() ((A f1 (cons (value Int) (a SetA)))))
(define-sort Set (T) (Array T Bool))
然后在(Set A),SetA之间定义双射。
(declare-fun injSA ((Set A)) SetA)
(declare-fun projSA (SetA) (Set A))
(assert (forall ((x SetA)) (= (injSA (projSA x)) x)))
(assert (forall ((x (Set A))) (= (projSA (injSA x)) x)))
这几乎是数据类型声明的状态。 要强制精心foundedness你可以序以A 成员关联,并强制执行组A的成员是在有理有据的排序更小:
(declare-const v Int)
(declare-const s1 SetA)
(declare-const a1 A)
(declare-const sa1 (Set A))
(declare-const s2 SetA)
(declare-const a2 A)
(declare-const sa2 (Set A))
随着公理到目前为止,A1可以成员本身。
(push)
(assert (select sa1 a1))
(assert (= s1 (injSA sa1)))
(assert (= a1 (cons v s1)))
(check-sat)
(get-model)
(pop)
我们现在A.
(declare-fun ord (A) Int)
(assert (forall ((x SetA) (v Int) (a A))
(=> (select (projSA x) a)
(> (ord (cons v x)) (ord a)))))
(assert (forall ((x A)) (> (ord x) 0)))
通过Z3默认量词实例成员的序号关联是基于模式。 上面的第一个量化断言将不会在所有的 相关实例上实例化。人们可以代替断言:
(assert (forall ((x1 SetA) (x2 (Set A)) (v Int) (a A))
(! (=> (and (= (projSA x1) x2) (select x2 a))
(> (ord (cons v x1)) (ord a)))
:pattern ((select x2 a) (cons v x1)))))
公理像这样,使用两种模式(称为多模式) 是相当昂贵的。他们为每对 (选择x2 a)和(cons v x1)
生成实例化。从之前的成员约束现在是不可满足的。
(push)
(assert (select sa1 a1))
(assert (= s1 (injSA sa1)))
(assert (= a1 (cons v s1)))
(check-sat)
(pop)
但是模型不一定能够很好地形成。 该集合的默认值为'true',其中 意味着该模型意味着存在会员周期 ,当没有一个时。
(push)
(assert (not (= (cons v s1) a1)))
(assert (= (projSA s1) sa1))
(assert (select sa1 a1))
(check-sat)
(get-model)
(pop)
我们可以通过使用 下面的方法来强制执行被 数据类型使用的集合是有限的接近更真实的模型。 例如,每当在集合x2, 上进行会员资格检查时,我们强制执行该集合的“默认”值为'false'。
(assert (forall ((x2 (Set A)) (a A))
(! (not (default x2))
:pattern ((select x2 a)))))
可替换地,每当一组在一个数据类型构造发生 它是有限
(assert (forall ((v Int) (x1 SetA))
(! (not (default (projSA x1)))
:pattern ((cons v x1)))))
(push)
(assert (not (= (cons v s1) a1)))
(assert (= (projSA s1) sa1))
(assert (select sa1 a1))
(check-sat)
(get-model)
(pop)
纵观包括额外的公理, Z3产生答案“未知”,此外 模型生成的表明域SetA 是有限的(单身)。所以虽然我们可以修补默认值 ,但这个模型仍然不满足公理。它只满足 公理模实例化。