Dafny无法证明关于旧状态的真命题

编程语言 2026-07-11

这是我问题的一个最小示例。请考虑下列谓词,以及关于它们的引理:

predicate A() reads *
predicate B() reads *
predicate C()

lemma {:axiom} AimpliesB()
    requires A()
    ensures B()

twostate lemma {:axiom} oldBimpliesC()
    requires old(B())
    ensures C()

由它们,应该可以证明

twostate lemma oldAimpliesC()
    requires old(A())
    ensures C()

但我想写的证明在语法上是无效的:

old(AimpliesB());
oldBimpliesC();

因为Dafny的引理只是幽灵方法(ghost methods),它们不能在旧状态下被调用。但这个限制似乎阻止了Dafny证明某些显而易见的东西。

到目前为止,我唯一的变通办法是把 AimpliesB 重复一次,作为一个怪异、退化的两态引理,只引用旧状态。下面的代码可以验证:

twostate lemma {:axiom} oldAimpliesoldB()
    requires old(A())
    ensures old(B())

twostate lemma oldAimpliesC()
    requires old(A())
    ensures C()
{
    oldAimpliesoldB();
    oldBimpliesC();
}

但这感觉像是在重复编写代码,尤其当该引理并非公理且其主体需要被复制并混杂有 old 表达式时。有没有更好的办法?

解决方案

一种解决方案是创建一个具有 ()-值的函数,其契约与 AimpliesB 相同,可以在旧状态下被调用。这在调用点需要占位变量,代码仅略微显得混乱。

predicate A() reads *
predicate B() reads *
predicate C()

lemma {:axiom} AimpliesB()
    requires A()
    ensures B()

opaque ghost function fAimpliesB(): ()
    reads *
    requires A()
    ensures B()
{
    AimpliesB();
    ()
}

twostate lemma {:axiom} oldBimpliesC()
    requires old(B())
    ensures C()

twostate lemma oldAimpliesC()
    requires old(A())
    ensures C()
{
    var _ := old(fAimpliesB());
    oldBimpliesC();
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章