我有一个简单的问题。我写了一个简单的程序(使用Z3 NET API)并获得如下输出。
计划(部分):
Sort[] domain = new Sort[3];
domain[0] = intT;
domain[1] = intT;
domain[2] = intT;
FPolicy = z3.MkFuncDecl("FPolicy", domain, boolT);
Term[] args = new Term[3];
args[0] = z3.MkNumeral(0, intT);
args[1] = z3.MkNumeral(1, intT);
args[2] = z3.MkNumeral(30, intT);
z3.AssertCnstr(z3.MkApp(FPolicy, args));
args[1] = z3.MkNumeral(2, intT);
args[2] = z3.MkNumeral(20, intT);
z3.AssertCnstr(z3.MkApp(FPolicy, args));
输出:
FPolicy -> {
0 1 30 -> true
0 2 20 -> true
else -> true
}
我想知道我可以将“else - > true”设为false(即“else - > false”)。
答案 0 :(得分:4)
对于量词免费问题,Z3(3.2)将在else
中更频繁地选择range
值。在range
这里,我指的是Z3分配给特定有限输入值集的有限值集。在我们的示例中,true
中仅出现range
。因此,true
被选为else
值。
对于无量词(和无数组)问题,如果未使用选项:model-compact true
,则else
的值无关紧要。
也就是说,如果公式F
是可满足的,Z3将生成模型M
。然后,如果我们更改else
中任意M
的值,则结果模型M’
仍然是F
的模型。
因此,您可以忽略else
,或假设它是您想要的任何内容,如果输入公式F
无量词,F
不使用数组理论,:model-compact true
未使用。
此属性基于当前在Z3中实现的算法,这可能在将来发生变化。
相反,mhs提供的解决方案不受Z3实施变化的影响。在他的编码中,任何SMT求解器(成功生成模型)都必须使用false
作为函数的值,而不是在量词的前提中未指定的每个点。
另一种选择是使用default
运算符,并使用数组对问题进行编码。
当使用default
运算符时,我们应该将数组视为对:(实际数组,默认值)。
此默认值用于在模型构建期间提供else
值。
Z3还有几个内置公理,用于传播默认值:store
和map
运算符。
以下是使用此方法编码的问题:
(set-option :produce-models true)
(declare-const FPolicy (Array Int Int Int Bool))
(assert (select FPolicy 0 1 30))
(assert (select FPolicy 0 2 20))
(assert (not (default FPolicy)))
(check-sat)
(get-model)
答案 1 :(得分:1)
以下(RiSE4fun link)怎么样?
(set-option :MBQI true)
(declare-fun FPolicy (Int Int Int) Bool)
(assert (forall ((x1 Int) (x2 Int) (x3 Int)) (!
(implies
(not
(or
(and (= x1 0) (= x2 1) (= x3 30))
(and (= x1 0) (= x2 2) (= x3 20))))
(= (FPolicy x1 x2 x3) false))
:pattern (FPolicy x1 x2 x3))))
(assert (FPolicy 0 1 30))
(assert (FPolicy 0 2 20))
(check-sat)
(get-model)
我可以看到的优点是你可以改变它,使得FPolicy(0 1 30)== false而不触及forall-constraint。 明显的缺点是你基本上必须两次提到所有参数元组,并且创建的模型相当复杂。
我期待看到更好的解决方案: - )