【问题标题】:What does Dafny know about loops with a break?Dafny 对带中断的循环了解多少?
【发布时间】:2020-12-27 05:45:42
【问题描述】:
I am used to loops
while Grd
invariant Inv
{ ..}
assert Inv && !Grd;

Dafny 毫不犹豫地知道 Inv && ! Grd 是真的,但是: Dafny 不会在 break; 命令之后检查循环不变量。因此

method tester(s:seq<int>) returns (r:int) 
ensures r <= 0
{   var i:nat := |s|;
    r := 0;
    while (i > 0)
       decreases i
       invariant r == 0;
    {   i := i -1;
        if s[i]< 0  { r:= s[i]; break;}        
    }    
   // assert r == 0; // invariant dose not hold
}

method Main() {
    var x:int := tester([1,-9,0]);
    print x,"\n";
}

显然,Dafny 明白不变量不再成立。谁能告诉我 dafny 到底知道什么。

【问题讨论】:

    标签: iteration break dafny


    【解决方案1】:

    如果有break语句,则循环后的条件为 Inv &amp;&amp; !Grd 的析取和在 各自的break 语句。

    这是一个更正式的答案:

    在没有任何突然退出循环(如break)的情况下,熟悉的 证明霍尔三元组的方法

    {{ P }}
    while Grd
      invariant Inv
    {
      Body
    }
    {{ Q }}
    

    是为了证明以下三个条件(我是忽略终止):

    1. 检查循环不变量在进入循环时是否成立:
    P ==> Inv
    
    1. 检查循环体是否维护了循环不变量:
    {{ Inv && Grd }}
    Body
    {{ Inv }}
    
    1. 检查不变量和否定保护证明 Q:
    Inv && !Grd ==> Q
    

    让我重新表述条件 1 和 2。为此,我将从 将 while 循环重写为带有中断的永远重复循环:

    loop
      invariant Inv
    {
      if !Grd {
        break;
      }
      Body
    }
    

    (换句话说,我使用loop 作为while true。)以上证明义务1 现在可以改写为证明

    {{ Inv }}
    if !Grd {
      break;
    }
    Body
    {{ Inv }}
    

    不需要在任何到达的路径上进一步证明任何事情 break。 证明义务 2 可以用一种双重方式重新表述:

    {{ Inv }}
    if !Grd {
      break;
    }
    Body
    {{ break: Q }}
    

    我的意思是,如果您到达...Body 的末尾,您无需证明任何事情, 但是您必须在任何break 上证明Q

    Body 包含其他break 语句时,我刚才所说的也适用。这就是 Dafny 处理循环的方式(即条件 0 加上重新表述的条件 1 和 2,加上终止检查)。

    【讨论】:

    • 我应该更频繁地留下未回答的问题。这是一个很好的答案! :)
    猜你喜欢
    • 2020-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2018-08-26
    • 2021-11-17
    • 2015-09-13
    相关资源
    最近更新 更多