in运算符,用于在Dafny中显示奇怪的序列

时间:2019-05-12 18:44:22

标签: seq dafny

我如何帮助Dafny证明以下两个断言是相同的:

# A tibble: 46 x 10
   game_pk atBatIndex launchSpeed launchAngle totalDistance trajectory  hardness location coordX coordY
   <chr>        <int>       <dbl>       <dbl>         <dbl> <chr>       <chr>    <chr>     <dbl>  <dbl>
 1 565711           4        76.6        2.74        188.   ground_ball medium   9         178.   145. 
 2 565711           5       101.        15.4         328.   line_drive  hard     8         145.    62.2
 3 565711           6       103.        29.4         382.   line_drive  medium   9         237.    79.4
 4 565711           8       109.        15.6         319.   line_drive  hard     9         181.   102. 
 5 565711           9        75.8       47.8         239.   fly_ball    medium   7          99.8  103. 
 6 565711          10        91.6       44.1         311.   fly_ball    medium   8         140.    69.3
 7 565711          12        79.1       23.4         246.   line_drive  medium   7          52.3  126. 
 8 565711          13        67.3      -21.3         124.   ground_ball medium   6         108.   156. 
 9 565711          14        89.9      -21.6           7.41 ground_ball medium   6         108.   152. 
10 565711          15       110.        27.7         420.   fly_ball    medium   9         250.    69.0
# … with 36 more rows

而且,Dafny似乎能够证明以下内容相同。为什么会这样?

method foo(xs : seq<int>)
  requires forall x :: x in xs ==> 0 <= x < 5;
{
  assert forall x :: x in xs ==> 0 <= x < 5;
  assert forall i :: 0 <= i < |xs| ==> 0 <= xs[i] < 5;
}

Example on Rise4Fun

1 个答案:

答案 0 :(得分:1)

这与量词触发器有关。您可以在Dafny FAQ中了解有关触发器的更多信息。

在这种情况下,最终断言在您的第一个示例中失败的原因是forall子句中的requires量词,并且第一个断言在x in xs上触发。 1 这意味着将不会在值v上使用此量化事实 ,除非v in xs在验证者的“范围内”。为了证明第二个断言,验证者需要使用值为xs[i]的较早的量化事实,但是xs[i] in xs不在“范围内”。这听起来可能很奇怪,因为xs[i] in xs始终为真,但是事实证明,在没有您的帮助下,验证者无法弄清楚这一点。

因此,要证明第二个断言,您需要以某种方式获得事实xs[i] in xs的范围。一种方法是将断言更改为

assert forall i :: 0 <= i < |xs| ==> xs[i] in xs && 0 <= xs[i] < 5;

(在结论中添加xs[i] in xs)。实际上,一旦证明了该新断言,Dafny便可以然后证明您的第二个断言,因为此新断言是在xs[i]上触发的,它也在第二个断言的“范围内”

最后,您的第二个示例进行验证的原因是因为引入谓词test更改了可用的触发器。现在,forall子句中的requiresx in xs test(x)上都被触发。由于foo已经出现,因此新触发器与test(xs[i])主体中的断言新版本中的匹配。这导致第一个forall被正确实例化,这意味着断言通过。在按摩触发器以使它们执行您想要的操作时,引入这样的无用的命名谓词是一个常见的技巧。


1.通过将鼠标悬停在IDE中的forall上,或通过在命令行上运行带有选项/printTooltips,可以查看正在使用哪些触发器。在第一个示例中的第一个断言,您应该看到类似Selected triggers: {x in xs}的内容。