Dafny归纳引理:无法推断归纳假设的后置条件

时间:2018-06-08 20:04:48

标签: induction dafny

我试图用算术表达式定义一个非常简单的语言的小步骤语义(源代码可用here)。为简单起见,我们假设该语言只允许文字和一元减号(-exp)。

datatype expression = Literal(int) | Minus(expression)

我定义了一个关系e1 --> e2,指定如何从表达式e1执行计算步骤以获取表达式e2。让我们简单地假设这种关系始终存在:

predicate Step(exp: expression, exp': expression) { true }

(任何其他非平凡的关系也会导致我在这里描述的问题)。

现在我定义了一个关系e1 -->* e2,指定在{0}},pg之后,e1可以在零,一个或多个计算步骤后缩减为e2。 11):

inductive predicate StepStar(exp: expression, exp': expression) {
    (exp == exp')
    || (exists exp'': expression :: Step(exp, exp'') && StepStar(exp'', exp'))
}

我想证明-->*在上下文中是封闭的。也就是说,e -->* e'暗示Minus(e) -->* Minus(e')。这可以通过归纳-->*

来证明
inductive lemma StepStarContext(exp1: expression, exp3: expression)
    requires StepStar(exp1, exp3)
    ensures StepStar(Minus(exp1), Minus(exp3)) 
{
    if (exp1 == exp3) {
        // Base case: zero steps.
    } else {
        // Inductive step.

        // We unfold the exp1 -->* exp3 relation into: exp1 --> exp2 -->* exp3.
        var exp2 :| Step(exp1, exp2) && StepStar(exp2, exp3);

        // Apply induction hypothesis on exp2 -->* exp3.
        StepStarContext(exp2, exp3);

        // ASSERTION VIOLATION: 
        // Why Minus(exp2) -->* Minus(exp3) cannot be proved?
        assert StepStar(Minus(exp2), Minus(exp3));
    }
}    

Dafny无法证明最后一个断言,尽管它应该遵循后置条件应用StepStarContext(exp2, exp3)。如果我评论说断言Dafny可以成功地证明这个引理(实际上,Dafny在它的身体是空的时候仍然可以证明它),但是我仍然对它无法证明这个断言的事实感到好奇。我错过了什么吗?

我还得到了Leino论文中描述的前缀引理(参见R. Leino's paper on extreme predicates)。奇怪的是,Dafny不仅在前缀引理中证明了这个断言,而且在归纳引理StepStarContext中也证明了这一断言。为什么呢?

任何帮助都将不胜感激。

Dafny版:2.1.1

1 个答案:

答案 0 :(得分:1)

我已经认识到归纳引理可以通过以下方式消除:

lemma StepStarContext#[_k: ORDINAL](exp1: expression, exp3: expression)
  requires StepStar#[_k](exp1, exp3)
  ensures StepStar(Minus(exp1), Minus(exp3)) 
{
  if (exp1 == exp3) {
     ...
  } else {
    ...
    // Apply induction hypothesis on exp2 -->* exp3.
    StepStarContext(exp2, exp3);

    // ASSERTION VIOLATION: 
    assert StepStar#[_k - 1](Minus(exp2), Minus(exp3));
  }
}    

基本上,不满意的断言要求exp2 -->* exp3的长度为_k - 1,但这不是归纳假设的结果,因为引理的结论说 Minus(exp1) --> Minus(exp3)表示一些推导长度。因此,在归纳假设中,我们不能期望exp2 -->* exp3的长度为_k - 1

按如下所示修正断言之后,

assert exists k' :: StepStar#[k'](Minus(exp2), Minus(exp3));

达夫妮(Dafny)同意。