修改Dafny中的另一个数组后断言失败

时间:2019-04-10 10:43:14

标签: dafny

我在达夫尼遇到一个奇怪的问题。我尝试在此处尽可能提取它:https://rise4fun.com/Dafny/F7sK

问题是,在修改 truthAssignment 之后,即使 stack.valid 不知道 stack.valid 也会失败> truthAssignment

assert stack.valid();
truthAssignment[variable] := 1;
assert stack.valid();  // assertion violation

2 个答案:

答案 0 :(得分:2)

Dafny无法验证断言assert stack.valid();的原因是valid()正文中的最后一个合词:

(forall c :: c in contents ==>
  exists i,j :: 0 <= i < stack.Length 
             && 0 <= j < |stack[i]| 
             && stack[i][j] == c)

它的形式为forall ... exists ...,对于验证者来说很难证明这种条件是不变的。一旦确定这是valid()验证者无法证明的部分(例如,您可以通过手动内联valid()的定义来代替断言来做到),然后解决方案是为验证者提供一些帮助。

当验证者(或人类)试图证明forall c :: P(c)形式的某物时,则组成任意c,然后尝试证明“ {{ 1}}”。 (逻辑学家将此规则称为“通用介绍”。)很简单。然后,为了证明格式为P(c),验证者将寻找“ exists i,j :: Q(i,j)”的见证人。 (这被称为“现有介绍”。)这里,验证者不是特别有创造力,经常需要帮助。有时,您必须自己弄清楚一些Q(i,j)i,然后断言j。在其他时候,只需提及所需的Q(i,j)的某些组成部分,然后验证程序将找出其余的部分。确切地讲,这可能是一个反复试验的过程。

James做出上述补救措施的原因是,它在更新Q(i,j)之后提到了stack.stack[..]。这以使验证者看到光线的方式使验证者挠痒痒。只需编写琐碎证明的断言即可:

truthAssignment[variable] := 1;
在这种情况下,

更新后也可以使用。

Rustan

答案 1 :(得分:1)

以下内容可为我验证:

assert stack.valid();
ghost var old_stack := stack.stack[..];
truthAssignment[variable] := 1;
assert stack.stack[..] == old_stack;
assert stack.valid();

我真的不明白为什么会这样,但是它属于“序列的相等性对达夫尼而言很难”的一般类别。