SMT 证明者产量 'unknown' 尽管有强有力的证明断言

SMT prover yields 'unknown' despite strong proven assertions

假设我们有以下 C 注释代码:

#define L  3
int a[L] = {0};
/*@ requires \valid(a+(0..(L - 1)));
    ensures \forall int j; 0 <= j < L ==> (a[j] == j); */
int main() {
        int i = 0;
        /*@ loop assigns i, a[0..(i-1)];
            loop invariant inv1: 0 <= i <= L;
            loop invariant inv2:
                        \forall int k; 0 <= k < i ==> a[k] == k; 
        */
        while (i < L) {
          a[i] = i;
          i++;
        }
        /*@ assert final_progress:
               \forall int k; 0 < k < L ==> a[k] == a[k-1] + 1; 
            assert final_c: 
               a[2] == a[1] - 1; */
        return 0;
}

为什么 Alt-Ergo/Z3 产生 "unknown" 或 final_c 断言超时,尽管 final_progress 陈述已被证明? 我绝对希望看到 "Not valid" 如此明显(从用户的角度来看)无效的陈述。

$ frama-c -wp -wp-rte -wp-prover z3 test2.c
..
[wp] [z3] Goal typed_main_assert_final_c : Unknown (455ms)

$ frama-c -wp -wp-rte -wp-prover alt-ergo test2.c 
..
[wp] [Alt-Ergo] Goal typed_main_assert_final_c : Timeout

WP 插件不支持将属性(前提条件、后置条件、用户断言)标记为无效。如 WP plugin manual 的第 2.2 节所述,状态是以下之一:

  1. — 未尝试证明。
  2. — 属性 尚未验证。

    此状态表示找不到证明。这可能是因为 属性 实际上无效。

  3. — 属性 有效但具有依赖性。

    如果 WP 插件能够证明 属性 假设一个或多个属性完全有效,您将看到此状态应用于 属性。

  4. — 属性 及其所有依赖项完全有效。

虽然 WP 插件不支持将属性标记为无效,但您可以使用在函数末尾断言 \false 的技巧:

#define L  3
int a[L] = {0};
/*@ requires \valid(a+(0..(L - 1)));
    ensures \forall int j; 0 <= j < L ==> (a[j] == j); */
int main()
{
    int i = 0;
    /*@ loop assigns i, a[0..(i-1)];
        loop invariant inv1: 0 <= i <= L;
        loop invariant inv2: \forall int k; 0 <= k < i ==> a[k] == k; 
    */
    while (i < L) {
        a[i] = i;
        i++;
    }
    //@ assert final_progress: \forall int k; 0 < k < L ==> a[k] == a[k-1] + 1;
    //@ assert final_c: a[2] == a[1] - 1;
    //@ assert false: \false;
    return 0;
}

运行 此代码上的 WP 插件导致:

...
[wp] [Alt-Ergo] Goal typed_main_assert_false : Valid (114ms) (97)
...

如果 WP 插件标记 assert \false 有效(在 GUI 中它将显示为有效但有依赖项)那么你知道有一个无效的 属性.