【问题标题】:Verifying a Loop Modifies Clause验证循环修改子句
【发布时间】:2021-07-04 20:01:53
【问题描述】:

对,所以我正在尝试验证以下fill() 方法。目前第一个和第三个invariant 子句失败了,我不完全确定为什么。任何想法表示赞赏!

class List {
    var data : int;
    var next : List?;
    ghost var rep : set<List>;

    constructor(d : int) 
    ensures this.valid();
    {
        this.data := d;
        this.next := null;
        this.rep := {this};
    }

    predicate valid() 
    reads this, rep;
    decreases rep + {this};
    {
        this in rep
        && (next != null ==> (
            next in rep
            && next.rep <= rep
            && this !in next.rep 
            && next.valid()            
        ))
    }
} 

method fill(ol : List, on : int) 
requires ol.valid();
requires on >= 0;
modifies ol.rep;
{
    assert ol in ol.rep;
    var n := on;
    var l : List? := ol;
    //    
    //
    while(n >= 0 && l != null) 
    invariant ol.valid();
    invariant (l != null) ==> l.valid();
    invariant (l != null) ==> (l in ol.rep);
    modifies l.rep;
    {
        l.data := n;
        l := l.next;
        n := n - 1;
    }
}

【问题讨论】:

    标签: dafny formal-verification


    【解决方案1】:

    这是一种方法。

    class List {
      var data : int;
      var next : List?;
      ghost var rep : set<List>;
    
      constructor(d : int) 
        ensures valid()
      {
        data := d;
        next := null;
        rep := {this};
      }
    
      predicate valid() 
        reads this, rep
        decreases rep + {this}
      {
        && this in rep
        && (next != null ==> 
            && next in rep
            && next.rep <= rep
            && this !in next.rep 
            && next.valid())
      }
    
      static twostate lemma valid_frame(a: List)
        requires old(a.valid())
        requires forall x | x in old(a.rep) :: unchanged(x`next)
        requires forall x | x in old(a.rep) :: unchanged(x`rep)
        decreases old(a.rep)
        ensures a.valid()
      {}
    } 
    
    method fill(ol : List, on : int) 
      requires ol.valid()
      requires on >= 0
      modifies ol.rep
      ensures ol.valid()
    {
      var n := on;
      var l : List? := ol;
      label L:
      while(n >= 0 && l != null) 
        invariant l != null ==> l.valid()
        invariant l != null ==> l.rep <= old(ol.rep)
        modifies ol.rep`data
      {
        l.data := n;
        l := l.next;
        n := n - 1;
      }
      List.valid_frame@L(ol);
    }
    

    这个证明的基本思想是valid 谓词只依赖于Listnextrep 字段。由于fill 只写入data 字段,它必须保持有效性。

    为了实现这个想法,我们可以在 Dafny 中使用 twostate 引理。将特定旧状态“传递”到此类引理的方法是使用label 功能和@ 的组合。

    【讨论】:

    • 谢谢詹姆斯。这比我预期的要复杂得多。似乎验证起来应该是一件简单的事情。 @L 符号也不适用于我在 VSCode (3.0.0) 下的 Dafny 版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 2016-04-25
    • 1970-01-01
    • 2017-07-24
    • 2019-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多