Dafny简单断言不成立

时间:2020-06-19 09:50:45

标签: dafny

exercise_1a中可以做些什么来使断言cnt > 0有效?

method exercise_1a(n: int)
    requires n > 0
{
    var idx := 0;
    var cnt := 0;

    while idx < n
        decreases n - idx
    {
        idx := idx + 1; 
        cnt := cnt + 1;
    }

    assert idx > 0; // valid
    assert cnt > 0; // *** invalid ***
}

令人惊讶的是,该版本也使断言idx > 0无效:

method exercise_1b(n: int)
    requires n > 0
{
    var idx := 0;
    var cnt := 0;

    while idx < n && cnt < n
        decreases n - idx
        decreases n - cnt
    {
        idx := idx + 1; 
        cnt := cnt + 1;
    }

    assert idx > 0; // *** invalid ***
    assert cnt > 0; // *** invalid ***
}

1 个答案:

答案 0 :(得分:1)

在您的第一段代码中,当while循环退出时,Dafny只知道!(idx < n)。因此,它可以推断出idx > 0。但是,Dafny目前对cnt变量一无所知,因此您的第二个断言失败。

在第二段代码中,当while循环退出时,Dafny知道的只是!(idx < n && cnt < n)(同样,while循环上条件的否定)。这等效于idx > n || cnt > n。 Dafny可以从那里推断出idx > 0 || cnt > 0,但无法独自证明idx > 0cnt > 0

要解决此问题,您需要在Dafny可以检查然后使用的变量cntidx之间添加一些关系。

    while idx < n && cnt < n 
        decreases n - idx 
        decreases n - cnt 
        invariant idx == cnt 
    {   
        idx := idx + 1;  
        cnt := cnt + 1;
    }   

多余的invariant行告诉Dafny检查idx == cnt将在循环的每次迭代中保持不变,然后可以在末尾使用该事实。但是,除非您告知事实,否则达夫妮不知道要考虑事实idx == cnt

(作为旁注,您会看到Dafny 能够自行确定n > 0while循环的末尾成立,即使您没有像在invariant中那样明确指定它,这是因为n并没有在while循环的主体中进行修改,所以Dafny会自动发现n > 0从一开始。)