如何创建包含一组其他对象的数据类型。基本上,我正在做以下代码:
(define-sort Set(T) (Array Int T))
(declare-datatypes () ((A f1 (cons (value Int) (b (Set B))))
(B f2 (cons (id Int) (a (Set A))))
))
但是Z3告诉我对A和B的未知排序。如果我删除“Set”,它就像指南所说的一样。 我试图使用List,但它不起作用。任何人都知道如何使它工作?
答案 0 :(得分:8)
您正在解决定期提出的问题: 我如何混合数据类型和数组(作为集合,多集或 范围内的数据类型)?
如上所述,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)))
这几乎是数据类型声明所述的内容。 为了强化有根据,您可以将序数与A的成员联系起来 并强制执行SetA的成员在有充分理由的订单中较小:
(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))
到目前为止,公理可以成为一个成员。
(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 是有限的(单身)。所以虽然我们可以修补默认值 这个模型仍然不满足公理。它满足 公理只是模数实例化。
答案 1 :(得分:2)
Z3不支持此功能。您可以在数据类型声明中使用数组,但它们不能包含对您声明的数据类型的“引用”。例如,可以使用(Set Int)
。