我最近在Z3中观察到了几个关于触发的行为,我不明白。不幸的是,这些例子来自大型的Boogie文件,所以我想我现在会抽象地描述它们,只是为了看看是否有明显的答案。但是,如果具体文件会更好,我可以附加它们。在Z3触发问题
基本上有三个问题,虽然第三个可能是第二个的特例。据我的理解,没有预期的行为,但也许我错过了一些东西。任何帮助将不胜感激!
首先:在我的程序琐碎的等式似乎就触发关切地被忽略。例如,如果t1
是应该匹配的模式进行量化公理,如果我加一条线的形式我的不羁程序
然后t1
不不似乎习惯作为触发一个术语用于量化的公理。我明确添加了该行,以便提供t1
作为证明者的触发器,我经常在Boogie程序中执行此操作。
如果不是我引入一个额外的功能,说
function f(x : same_type_as_t1) : bool
{ true }
和现在,而不是添加一行
assert f(t1);
到我的程序,然后t1
确实似乎被用来作为触发Z3。我已经检查过前一个程序的Z3翻译,并且t1
上的(平凡的)等式确实存在于布吉翻译中(即,这不是布吉试图做一些聪明的事情)。
其次:辅助模式似乎不能正常工作。例如,我有一个计划,其中一个公理的形式
axiom (forall ... :: {t1,t2} {t3,t4,t5} .....);
和一种情况,即t3, t4
和t5
都发生了。该程序未能验证,显然是因为该公理没有实例化。但是,如果我将公理改写为
axiom (forall ... :: {t3,t4,t5} {t1,t2} .....);
然后程序验证。在这两种情况下,运行Boogie的时间大约是3秒,模式生存到Z3输出。
三:这很可能是第二个问题的症状,但是我对以下行为感到惊讶:
我写形式的公理
,并在发生t2
和t3
的情况下,第一个公理没有被实例化(我预料它是,因为在第二个公理的实例化后,发生了t1
)。但是,如果我重写为
axiom (forall .. :: {t2,t3} {t1,t2} ....);
axiom (forall ... :: {t2,t4} {t2,t3} ...some expression involving t1...);
那么第一个公理就被实例化了。但是,如果由于某种原因二次模式没有被普遍使用,那么这也将解释这种行为。
如果明确的例子是有用的,我可以附加很长的例子,并可以尝试减少它们(但当然,触发问题有点微妙,所以我可能会失去行为,如果我举例说明太小)。
非常感谢您的任何意见!
亚历夏天
编辑:这里是部分地示出了上述第二和第三行为的例子。我附加了Boogie代码,使其更容易阅读,但如果它更有用,我也可以复制或通过电子邮件发送Z3输入。我已经删除了几乎所有原始的Boogie代码,但似乎很难使其更简单,而不会完全失去行为。
已经低于代码我原来的例子巧妙地表现不同,但我认为这是足够接近。基本上,下面标记为(1)的公理未设法使其第二模式集合匹配。如果我将公理(1)注释掉,而是用(两个当前注释的)公理(2)和(3)替换它们,这两个公理(2)和(3)就是两个模式集合中的每一个的原始副本,然后程序将进行验证。事实上,在这个特殊情况下,有足够的公理(2)。在我原来的代码中(在我将它裁减之前),公理(1)中的两个模式集合的顺序也是足够的,但在我的小代码中似乎不再是这种情况。
type ref;
type HeapType;
function vals1(HeapType, ref) returns (ref);
function vals2(HeapType, ref) returns (ref);
function vals3(HeapType, ref) returns (ref);
function heap_trigger(HeapType) returns (bool);
function trigger1(ref) returns (bool);
function trigger2(ref) returns (bool);
axiom (forall Heap: HeapType, this: ref :: {vals1(Heap, this)} (vals1(Heap, this) == vals3(Heap,this)));
axiom (forall Heap: HeapType, this: ref :: {vals2(Heap, this)} trigger2(this));
// (1)
axiom (forall Heap: HeapType, this: ref :: {vals1(Heap, this)} {trigger1(this), heap_trigger(Heap), trigger2(this)} (vals1(Heap, this) == vals2(Heap, this)));
// (2)
// axiom (forall Heap: HeapType, this: ref :: {trigger1(this), heap_trigger(Heap), trigger2(this)} (vals1(Heap, this) == vals2(Heap, this)));
// (3)
// axiom (forall Heap: HeapType, this: ref :: {vals1(Heap, this)} (vals1(Heap, this) == vals2(Heap, this)));
procedure test(Heap:HeapType, this:ref)
{
assume trigger1(this); assume heap_trigger(Heap);
assert (vals2(Heap, this) == vals3(Heap,this));
}
尊敬的莱昂纳多, 非常感谢您的快速回复。这是非常有用的知道 - 我敢肯定你知道,通过大型示例来追踪触发问题非常困难。有没有可能配置你描述的行为?据我所知,仅仅提到一个术语是匹配模式的充分标准,所以我们(错误地)认为特定的编码问题不是由于触发引起的。其实,我读了你的帖子http://stackoverflow.com/questions/10949633/z3-real-arithmetic-and-statistics,我完全同意 - 我真的不想失去触发器:) – 2012-07-26 16:35:14
我想知道,因为(就像你上面提到的那样),为了触发更多模式而手动引入额外术语的方式都没有保证永远有效,有没有可能有明确的语法来做到这一点?即,我们可以有一种方法来为电子图匹配添加候选词,而不需要在原始问题中给出任何特定的逻辑含义。即使Z3从不改变其简化行为,它也会比引入额外的功能更简单(特别是使用Boogie等类型的语言),并且可能也更易读。 – 2012-07-26 16:53:29
p.s. repro在编辑中添加了上述内容。 – 2012-07-30 09:42:51