【问题标题】:Dafny Big-Step- Assert violationDafny Big-Step- 断言违规
【发布时间】:2020-04-29 11:58:34
【问题描述】:

我对 Dafny 有点陌生。我正在尝试为 Dafny 中的 CinK 提供大步语义的可执行规范。

这是我的代码

datatype Id = a | b | c |d |m

//expresions
datatype Exp =
Int(i: int)
| Var(x: Id)
| Bool(b:bool)
| Plus(e1: Exp, e2: Exp)

//statements
datatype Stmt =
Assg(x: Id, e: Exp)



// evaluation of expressiosn
function method val(e: Exp, state: map<Id, int>) : int
decreases  e, state
{
match (e) {
case Int(i) => i
case Bool(b) => if b== true then 1 else 0
case Var(a) => if a in state then state[a] else 0
case Plus(e1, e2) => val(e1, state) + val(e2, state)
}
}


lemma Lemma1(state: map<Id, int>)
requires state == map[a := 2, b := 0]
ensures val(Plus(Var(a), Int(5)), state) == 7
{
}


// statement evaluation
function method bigStep(s: Stmt, state: map<Id, int>) : map<Id, int>
decreases s,state
{
match (s) {
case Assg(x, e) => state[x := val(e, state)]
}

}

function method bigStepStmtlist(s: seq<Stmt>, state: map<Id, int>,pos:int) : map<Id, int>
requires 0 <=pos <= |s|
decreases |s|-pos
{

if(pos==|s|) then state else bigStep(s[pos],bigStepStmtlist(s,state,pos+1)) 

}


method Lemma2(state: map<Id, int>)
{
var state := map[a := 2, b := 0,c:=3,d:=5];
assert bigStep(Assg(b, Plus(Var(a), Int(5))), state) == map[a := 2, b := 7,c:=3,d:=5];
assert bigStep(Assg(b, Int(8)), state) == map[a := 2, b := 8,c:=3,d:=5];

}


method Main() {
var state := map[a := 2, b := 1,m:=0];

var Stmt1 :=Assg(a,Int(1));
var Stmt2 :=Assg(b,Int(2));
var Stmt3 :=Assg(m,Int(3));

var Stmts:= new Stmt[3];
Stmts[0]:=Stmt1;
Stmts[1]:=Stmt2;
Stmts[2]:=Stmt3;

var t:= bigStepStmtlist(Stmts[..],state,0); 

print t;// this will print map[Id.a := 1, Id.b := 2, Id.m := 3]

assert t== map[Id.a := 1, Id.b := 2, Id.m := 3];

}

如果你运行它,你会看到 print t 将打印那个 map[Id.a := 1, Id.b := 2, Id.m := 3] 但我无法通过任何断言达到这一点......

我也尝试使用 while 循环来执行此操作,但似乎它不适用于断言

【问题讨论】:

    标签: dafny


    【解决方案1】:

    Dafny 验证者在进行证明时愿意扩展函数定义,但在一定范围内。如果它没有,那么当你要求它证明一些不成立的东西时,它就不能给你快速的周转。将验证器视为扩展您编写一次的函数的每次出现可能会有所帮助。它实际上做得更多。例如,当函数的参数是文字时,验证器可能会将函数扩展超出正常限制。 (如果您对这种“双轨编码”的细节感兴趣,请参阅 Amin、Leino 和 Rompf,TAP 2014。)

    为了证明您的断言,您必须帮助验证者。在断言之前添加以下证明计算,您的程序将验证:

    calc {
      bigStepStmtlist(Stmts[..], state, 0);
    ==  // def. bigStepStmtlist
      bigStep(Stmts[0], bigStepStmtlist(Stmts[..], state, 1));
    ==  // def. bigStepStmtlist
      bigStep(Stmts[0],
        bigStep(Stmts[1], bigStepStmtlist(Stmts[..], state, 2)));
    ==  // def. bigStepStmtlist
      bigStep(Stmts[0],
        bigStep(Stmts[1],
        bigStep(Stmts[2], bigStepStmtlist(Stmts[..], state, 3))));
    ==  // def. bigStepStmtlist
      bigStep(Stmts[0],
        bigStep(Stmts[1],
        bigStep(Stmts[2], state)));
    ==  // def. Stmts and state
      bigStep(Assg(a, Int(1)),
        bigStep(Assg(b, Int(2)),
        bigStep(Assg(m, Int(3)), map[a := 2, b := 1, m := 0])));
    ==  { assert bigStep(Assg(m, Int(3)), map[a := 2, b := 1, m := 0])
              == map[a := 2, b := 1, m := 0][m := 3]
              == map[a := 2, b := 1, m := 3]; }
      bigStep(Assg(a, Int(1)),
        bigStep(Assg(b, Int(2)), map[a := 2, b := 1, m := 3]));
    ==  { assert bigStep(Assg(b, Int(2)), map[a := 2, b := 1, m := 3])
              == map[a := 2, b := 1, m := 3][b := 2]
              == map[a := 2, b := 2, m := 3]; }
      bigStep(Assg(a, Int(1)), map[a := 2, b := 2, m := 3]);
    ==  { assert bigStep(Assg(a, Int(1)), map[a := 2, b := 2, m := 3])
              == map[a := 2, b := 2, m := 3][a := 1]
              == map[a := 1, b := 2, m := 3]; }
      map[a := 1, b := 2, m := 3];
    }
    

    这是一个详细的证明。您只需提供前几个步骤,其余的由验证者完成。

    我在上面说过,当使用文字参数调用函数时,验证者愿意超出其正常限制。这不适用于calc 语句中的第一个表达式,因为该表达式使用子表达式Stmts[..] 取消引用堆。如果您不需要堆提供的数组,那么使用数学序列会更容易。确实,在节目中

    var stmts := [Assg(a,Int(1)), Assg(b,Int(2)), Assg(m,Int(3))];
    assert bigStepStmtlist(stmts, state, 0) == map[a := 1, b := 2, m := 3];
    

    bigStepStmtList 的所有参数都是文字,因此断言会自动验证。

    鲁斯坦

    【讨论】:

    • 谢谢!我试图用一个while循环来解决这个问题,并尝试使用这种递归方法来验证while ..现在我将永远记住seq和array之间的区别
    • 假设我想将 stmts 中的一个元素修改为 Assg(m,Plus(Var(a),Int(2)) 显然这将输出相同的地图 map[Id.a := 1, Id.b := 2, Id.m := 3] 再次在断言中即使使用 seq 也不起作用...我应该在这里做什么?
    猜你喜欢
    • 2016-03-18
    • 2018-11-23
    • 2017-11-03
    • 2018-10-25
    • 2018-10-10
    • 2020-12-27
    • 2020-03-21
    • 2020-12-18
    • 2021-04-17
    相关资源
    最近更新 更多