用Dafny证明gcd算法

时间:2019-06-25 09:12:00

标签: greatest-common-divisor dafny

我正在尝试与Dafny一起证明gcd算法,但显然不是那么简单。到目前为止,我所拥有的(实际上不是很多)功能规范,Dafny设法证明compute_gcd的行为类似于它。但是,当我删除评论时,[1], [2] and [3] Dafny失败 证明功能规范具有所需的属性:

function gcd(a: int, b: int) : (result : int)
    requires a > 0
    requires b > 0
    // [1] ensures (exists q1:int :: (q1 * result == a))
    // [2] ensures (exists q2:int :: (q2 * result == b))
    // [3] ensures forall d :int, q1:int, q2:int :: ((q1*d==a)&&(q2*d==b)) ==> (exists q3:int :: (0 < q3 <= result) && (q3*d == result))
{
    if (a >  b) then gcd(a-b,b) else
    if (b >  a) then gcd(a,b-a) else a
}

method compute_gcd(a: int, b: int) returns (result: int)
    requires a > 0
    requires b > 0
    ensures result == gcd(a,b)
{
    var x := a;
    var y := b;
    while (x != y)
        decreases x+y
        invariant x > 0
        invariant y > 0
        invariant gcd(x,y) == gcd(a,b)
    {
        if (x > y) { x := x - y; }
        if (y > x) { y := y - x; }
    }
    return x;
}

我朝着正确的方向前进吗? 任何帮助都非常感谢,谢谢!

2 个答案:

答案 0 :(得分:0)

我设法证明了较弱的gcd规范,但是我仍然很难拥有上面的属性[3]

function gcd(a: int, b: int) : (result : int)
    requires a > 0
    requires b > 0
    // [1] ensures (exists q1:int :: (q1 * result == a))
    // [2] ensures (exists q2:int :: (q2 * result == b))
{
    if (a > b) then gcd(a-b,b) else
    if (b > a) then gcd(a,b-a) else a
}

lemma gcd_correct(a: int, b: int)
    requires a > 0
    requires b > 0

    ensures (exists q1:int :: (q1 * gcd(a,b) == a))
    ensures (exists q2:int :: (q2 * gcd(a,b) == b))
{
    if (a > b)
    {
        gcd_correct(a-b, b);
        var q1 :| q1 * gcd(a-b,b) == a-b;
        var q2 :| q2 * gcd(a-b,b) == b;
        assert (q1+q2) * gcd(a,b) == a;
    }
    else if (b > a)
    {
        gcd_correct(a,b-a);
        var q1 :| q1 * gcd(a,b-a) == a;
        var q2 :| q2 * gcd(a,b-a) == b-a;
        assert (q2+q1) * gcd(a,b) == b;
    }
    else
    {
        assert 1 * gcd(a,b) == a;
    }
}

method compute_gcd(a: int, b: int) returns (result: int)
    requires a > 0
    requires b > 0
    ensures result == gcd(a,b)
    ensures (exists q1:int :: (q1 * result == a))
    ensures (exists q2:int :: (q2 * result == b))
{
    var x := a;
    var y := b;
    while (x != y)
        decreases x+y
        invariant x > 0
        invariant y > 0
        invariant gcd(x,y) == gcd(a,b)
    {
        if (x > y) { x := x - y; }
        if (y > x) { y := y - x; }
    }
    gcd_correct(a,b);
    return x;
}

有什么提示吗?

答案 1 :(得分:0)

您可以查看Dafny测试套件(在Test/VerifyThis2015/Problem2.dfy中)的GCD算法,并将其与您的方法进行比较: