位向量验证取决于函数的参数列表

编程语言 2026-07-09

我有以下Dafny文件:

class Repro {
  var a: bv32

  function myEnc(v: (bv32, bv32), sum: bv32, DUMMY_PLACEHOLDER: bv32): bv32 
  reads this`a
  {
    (((v.1 << 4) + a))
  }

  lemma myEncLemma_fast(v: (bv32, bv32), sum: bv32) {
    assert 
      myEnc(v, sum, a) ==
      (((v.1 << 4) + a));
  }

  lemma myEncLemma_slow(v: (bv32, bv32), sum: bv32) {
    assert 
      myEnc(v, sum, 0) ==
      (((v.1 << 4) + a));
  }
}

输出:

❯ ~/Downloads/dafny/dafny verify --progress Symbol mini_repro.dfy
Verified 0/3 symbols. Waiting for Repro.myEnc to verify.
Verified 1/3 symbols. Waiting for Repro.myEncLemma_fast to verify.
Verified 2/3 symbols. Waiting for Repro.myEncLemma_slow to verify.
mini_repro.dfy(16,8): Error: Verification of 'Repro.myEncLemma_slow' timed out after 30 seconds. (the limit can be increased using --verification-time-limit)
   |
16 |   lemma myEncLemma_slow(v: (bv32, bv32), sum: bv32) {
   |         ^^^^^^^^^^^^^^^


Dafny program verifier finished with 2 verified, 0 errors, 1 time out

如你所见,"fast" 引理可以立即通过验证,而 "slow" 引理则超时。唯一的区别是,在快速引理中通过字段a 提及了堆,而在慢速引理中没有。如果我在所有地方去掉左移运算,慢速引理也会变得像快速引理一样。这究竟怎么回事?在两个引理中用 myEnc 的定义替换,也能让验证更快。不知为何,堆变量的编码似乎干扰了等式证明?

我不确定如何让Dafny生成Boogie/SMT文件。新的CLI似乎并未暴露这个选项。

我正在使用Dafny 4.11.0+fcb2042d6d043a2634f0854338c08feeaaaf4ae2,目前从GitHub发布的最新版本。

解决方案

你需要在引理上指定一个后置条件,否则它们不会真的有用。指定后置条件并验证通过后,你就可以调用它们来应用前置条件和后置条件,从而向验证器证明更强大但并非完全直观的事实。

你可以在这里找到更多示例:https://dev.to/hath995/dafny-programming-language-and-software-verification-system-2afi

module SOBV {
    class Repro {
  var a: bv32

  function myEnc(v: (bv32, bv32), sum: bv32, DUMMY_PLACEHOLDER: bv32): bv32 
  reads this`a
  {
    (((v.1 << 4) + a))
  }

  lemma myEncLemma_fast(v: (bv32, bv32), sum: bv32) {
    assert 
      myEnc(v, sum, a) ==
      (((v.1 << 4) + a));
  }

  lemma extraneous(v: (bv32, bv32), sum: bv32)
    ensures forall ph: bv32 :: true ==> myEnc(v, sum, ph) == myEnc(v, sum, 0)
  {
  }

  lemma bh(v: (bv32, bv32), sum: bv32, placeholder: bv32)
    ensures myEnc(v, sum, placeholder) == myEnc(v, sum, 0)
  {
  }

  lemma myEncLemma_slow(v: (bv32, bv32), sum: bv32) {
    //extraneous(v, sum); //works but is slow
    // bh(v, sum, 0); //same as above
    // bh(v, sum, a); //works quite fast
    assert 
      myEnc(v, sum, 0) ==
      (((v.1 << 4) + a));
  }
    }
}

编辑:另一种方案

 lemma myEncLemma_slow(v: (bv32, bv32), sum: bv32) {
    // extraneous(v, sum);
    calc {
        myEnc(v, sum, 0);
        ((v.1 << 4) + a);
    }
    assert 
      myEnc(v, sum, 0) ==
      (((v.1 << 4) + a));
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章