假设我有一个计算某事的方法:
method Difference(a: nat, b: nat) returns (c: nat)
ensures a + c == b || b + c == a
{
...
}
别介意现在的实施。如果我可以在Dafny中实现此方法,这意味着对于所有可能的参数 a 和 b ,必须有一些返回值 c 满足后置条件。
换句话说,该方法的主体是建设性证明:
forall a: nat, b: nat :: exists c: nat ::
a + c == b || b + c == a
method Difference(a: nat, b: nat) returns (c: nat)
ensures a + c == b || b + c == a
{
c := if a > b then a - b else b - a;
}
method Main() {
assert forall a: nat, b: nat :: exists c: nat :: // error: assertion violation :(
a + c == b || b + c == a;
}
有没有办法在Dafny中使用这种推理?
答案 0 :(得分:2)
这样做的诀窍:将属性包装在谓词中,并在引理中证明exists
,以便您可以使用assert
提示验证者。
也许有一些方法可以在forall
内提示。
predicate difference_property(a: nat, b: nat, c: nat)
{
a + c == b || b + c == a
}
function difference(a: nat, b: nat): nat
{
if a > b then a - b else b - a
}
lemma main(a: nat, b: nat)
ensures exists c: nat :: difference_property(a, b, c)
{
var c := difference(a, b);
assert difference_property(a, b, c);
}
答案 1 :(得分:1)
forall
声明将这个技巧扩展为“forall
内部的提示”,就像这样
forall a: nat, b: nat
ensures exists c: nat :: difference_property(a, b, c)
{
var c := difference(a, b);
assert difference_property(a, b, c);
}
证明了forall
表达式
forall a: nat, b: nat ::
exists c: nat ::
difference_property(a, b, c)
对于Jason关于在证明中使用适当方法的其他问题,Dafny不支持这一点。实际上,我认为它是不合适的,因为方法可以对堆产生影响,例如。因此,一些证人的建构原则上可能依赖于分配状态甚至修改现有状态。将这种影响内化到逻辑中是可疑的,并且会改变达菲尼的本性。