dafny : 微軟推出的形式化驗證語言

dafny是一種可驗證的程式語言,由微軟推出,現已經開源。

dafny能夠自我驗證,可以在VS Code中進行開發,在編輯演算法時,寫好前置條件和後置條件,dafny驗證器就能實時驗證演算法是否正確。

在官方的例子中,以Abs絕對值函數來進行說明,程式碼如下:

點擊查看程式碼
method Abs(x: int) returns(y: int)

    ensures y >= 0 && (|| y == x || y == -x)

{

    return if x > 0 then x else -x;

}

Abs是方法名,x為形參,類型為int, y為返回值,類型為int。

Abs沒有前置條件,只有一個後置條件ensures y >= 0 && (|| y == x || y == -x),這樣Abs返回值必須非負且y = x 或者 y = -x,定義了Abs的規約條件。

方法內就是具體的演算法,根據x與0的比較,返回不同的值。

dafny語言裡面有一個非常重要的後置條件寫法,那就是loop。

下面舉一個例子:

Verify the program in Algorithm 1. Note that you cannot change the existing implementation.

Algorithm 1 Find an element in array

點擊查看程式碼
method Find(a: array<int>, v: int) returns(index: int)

    ensures 0 <= index ==> index < a.Length && a[index] == v

    ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != v

{

    var i : int := 0;

    while i < a.Length

        invariant 0 <= i <= a.Length

        invariant forall k :: 0 <= k < i ==> a[k] != v

    {

        if a[i] == v {

            return i;

        }

        i := i + 1;

    }

    return -1;

}

這個演算法是要找數組裡面的某個數,找到了就返回下標,否則返回-1。

這個演算法有兩個後置條件,分比對應找到了目標值和沒有找到目標值,

找到了目標值,返回為非負值,返回值必須小於數組長度且數組對應值與目標值相等。

ensures 0 <= index ==> index < a.Length && a[index] == v

沒有找到目標值,返回為負值,這就意味著數組裡的所有值與目標值都不相等。

ensures index < 0 ==> forall k :: 0 <= k < a.Length ==> a[k] != v

這種寫法用了形式化語言進行了規約。

演算法實現很簡單,while循環需要增加後置條件,

一個是i的範圍,i的初值為0,循環退出時,i的值為數組長度。

invariant 0 <= i <= a.Length

while循環的另外一個後置條件,對於i,數組i前面的數字都與目標值不相等。

invariant forall k :: 0 <= k < i ==> a[k] != v

while循環第二個後置條件,保障了Find函數第二個後置條件。

vscode的編輯器能實時驗證演算法是否正確,這對於編寫dafny程式碼十分有利。