我的问题来自large Boogie file。我将在这里解释相关部分。
我为包含7个字段Msg
的邮件声明了新类型tID, stype, bal, acc, mbal, mval, val
。这些字段在Boogie中声明为函数。然后我声明了72个Msg常量M1, ..., M72
和它们的字段的相应值。您可以看到以下示例:
type Msg;
const unique M1: Msg;
function tID (Msg) returns (int);
function stype (Msg) returns (Str);
function bal (Msg) returns (int);
function acc (Msg) returns (Proc);
function mbal (Msg) returns (int);
function mval (Msg) returns (Val);
function val (Msg) returns (Val);
axiom (tID (M1) == 1);
axiom (stype (M1) == s1a);
axiom (bal (M1) == 1);
axiom (acc (M1) == ProcNull);
axiom (mbal (M1) == -2);
axiom (mval (M1) == ValNull);
axiom (val (M1) == ValNull);
其中Proc, Str
是某些类型,s1a, ProcNull, ValNull
是一些常量。然后我宣布一个公理,说明当{且仅{}}的每个字段时,两条消息m1, m2
是相等的。这个公理使用了触发器m1, m2
。
MsgComp(m1, m2)
然后,我声明一个新变量function MsgComp(m1, m2: Msg): bool { true }
axiom (forall m1, m2: Msg :: {MsgComp(m1, m2)}
m1 == m2 <==>
(tID(m1) == tID(m2) && stype(m1) == stype(m2) &&
acc(m1) == acc(m2) && bal(m1) == bal(m2) &&
mbal(m1) == mbal(m2) && mval(m1) == mval(m2) &&
val(m1) == val(m2)));
并为其字段分配任意值,使m
等于m
或M1
。我没有明确说明M2
,但我们可以用上述公理来证明这个断言(第786行)。
m == M1 || m == M2
但是,如果我想检查assert (MsgComp(cMsg, M1) && MsgComp(cMsg, M2) && (cMsg == M1 || cMsg == M2));
是否为m
之一,Boogie会显示相应的断言可能不成立。
M1, ..., M72
我发现,如果我检查最多32个常数的断言,Boogie可以验证它。为什么Boogie或Z3不能用更多的常量来验证它?
答案 0 :(得分:2)
在我的机器上,即使是两个常量的情况,检查也不会成功。
我能够通过将它们更改为以下形式来检查两个检查
assert MsgComp(cMsg, M1) && MsgComp(cMsg, M2) ==> (cMsg == M1 || cMsg == M2);
(请注意,中间的&&
已更改为==>
。)
这也适用于72值的断言。
我不知道为什么这种变化很重要。看起来在触发发生之前忽略或简化了合取。