不同的“排序”谓词在Dafny中应等效

问题描述 投票:3回答:1

根据Automating Induction with an SMT Solver,以下内容应适用于达夫尼:

ghost method AdjacentImpliesTransitive(s: seq<int>)
requires ∀ i • 1 ≤ i < |s| ==> s[i-1] ≤ s[i];
ensures ∀ i,j {:induction j} • 0 ≤ i < j < |s| ==> s[i] ≤ s[j];
{ }

但是Dafny拒绝了它(至少在我的桌面和在线的Dafny中拒绝了)。也许有些改变。

问题:

Q1。为什么?

Q2。是否真的需要对j或对i和j都进行归纳?我认为对seq长度的归纳应该足够。

无论如何,我对以下内容更感兴趣:我想通过人工归纳来证明这一点,以供学习。在纸上,我认为对seq长度的感应就足够了。现在,我正在尝试在Dafny上执行此操作:

lemma {:induction false} AdjacentImpliesTransitive(s: seq<int>)
   ensures forall i :: 0 <= i <= |s|-2 ==> s[i] <= s[i+1] ==> forall l, r :: 0 <= l < r <= |s|-1 ==> s[l] <= s[r]
   decreases s
{
   if |s| == 0
   { 
     //explicit calc proof, not neccesary
     calc {
        (forall i :: 0 <= i <= 0-2 ==> s[i] <= s[i+1]) ==> (forall l, r :: 0 <= l < r <= 0-1 ==> s[l] <= s[r]);
     ==
        (forall i :: false ==> s[i] <= s[i+1])  ==>  (forall l, r :: false ==> s[l] <= s[r]);
     ==
        true ==> true;
     == 
        true;
     }
   } 
   else if |s| == 1
   { 
     //trivial for dafny
   }  
   else {

     AdjacentImpliesTransitive(s[..|s|-1]);
     assert (forall i :: 0 <= i <= |s|-3 ==> s[i] <= s[i+1]) ==> (forall l, r :: 0 <= l < r <= |s|-2 ==> s[l] <= s[r]);
    //What??

   }
}

我陷入了最后一种情况。我不知道如何将计算证明样式(如基本情况下的样式)与归纳炒作结合在一起。

也许是棘手的含义。在纸上(一种“非正式”证明),当我们需要通过归纳来证明蕴涵p(n) ==> q(n)时,我们会得到类似:

Hyp:p(k-1) ==> q(k-1)

Tesis:p(k) ==> q(k)

但是随后证明:

(p(k-1) ==> q(k-1) && p(k)) ==> q(k)

Q3。我的方法有意义吗?我们如何在dafny中进行这种归纳?

theorem-proving induction dafny
1个回答
0
投票

我不知道Q1Q2的答案。但是,如果在归纳情况下添加assert s[|s|-2] <= s[|s|-1],则归纳证明会通过(不需要其他断言)。这是完整的证明:

lemma {:induction false} AdjacentImpliesTransitive(s: seq<int>)
   requires forall i :: 0 <= i <= |s|-2 ==> s[i] <= s[i+1]
   ensures forall l, r :: 0 <= l < r <= |s|-1 ==> s[l] <= s[r]
   decreases s
{
   if |s| == 0
   { 
     //explicit calc proof, not neccesary
     calc {
        (forall i :: 0 <= i <= 0-2 ==> s[i] <= s[i+1]) ==> (forall l, r :: 0 <= l < r <= 0-1 ==> s[l] <= s[r]);
     ==
        (forall i :: false ==> s[i] <= s[i+1])  ==>  (forall l, r :: false ==> s[l] <= s[r]);
     ==
        true ==> true;
     == 
        true;
     }
   } 
   else if |s| == 1
   { 
     //trivial for dafny
   }  
   else {

     AdjacentImpliesTransitive(s[..|s|-1]);
     assert s[|s|-2] <= s[|s|-1];

   }
}

出于某种原因,我不得不将您的ensures子句分为requiresensures子句。否则,Dafny抱怨undeclared identifier: _t#0#0。我不知道那是什么意思。

而且,如果很有趣,这是一个简短的证明:

lemma AdjacentImpliesTransitive(s: seq<int>)
requires forall i | 1 <= i < |s| :: s[i-1] <= s[i]
ensures forall i,j | 0 <= i < j < |s| :: s[i] <= s[j]
decreases s
{
  if |s| < 2
  {
    assert forall i,j | 0 <= i < j < |s| :: s[i] <= s[j];
  } else {
    AdjacentImpliesTransitive(s[..|s|-1]);
    assert s[|s|-2] <= s[|s|-1];
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.