有序列表的串联证明是不锈钢中的有序列表

时间:2017-03-03 15:00:45

标签: scala formal-verification leon

我有以下代码用于排序我想在Stainless(以前称为Leon)中验证的数组:

import stainless.lang._
import stainless.collection._

object QuickSort {

  def isSorted(list: List[BigInt]): Boolean = list match {
    case Cons(x, xs @ Cons(y, _)) => x <= y && isSorted(xs)
    case _ => true
  }

  def quickSort(list: List[BigInt]): List[BigInt] = (list match {
        case Nil() => Nil[BigInt]()
        case Cons(x, xs) => par(x, Nil(), Nil(), xs)
  }) ensuring { res => isSorted(res) }


  def par(x: BigInt, l: List[BigInt], r: List[BigInt], ls: List[BigInt]): List[BigInt] = {
    require(l.forall(_ <= x) && r.forall(_ >= x))
    ls match {
      case Nil() => quickSort(l) ++ Cons(x, quickSort(r))
      case Cons(x2, xs2) => if (x2 <= x) par(x, Cons(x2, l), r, xs2) else par(x, l, Cons(x2, r), xs2)
    }
  } ensuring {res => isSorted(res)}
}

我有很多指示要从这里开始(因为它没有成功验证)但是在我看来,验证应该成功提供提示,我想知道为什么它没有。我解释一下自己:

显然,为了验证par函数,我需要证明这两个案例分别暗示了isSorted后置条件。现在,由于第二种情况包含递归调用,因此很明显它暗示了后置条件。对于par的第一种情况,我们已经对左右子阵列进行了排序,前提条件告诉我所有元素都是根据枢轴进行排序的。

在我看来,最后一点应该意味着连接列表也是排序的。那为什么不验证呢?怎么能指示不锈钢验证它?我是否需要在长度和尺寸上添加提示以便完成不锈钢的任务?

修改

def concatIsSorted(l1 : List[BigInt],l2 : List[BigInt],pivot : BigInt) : Boolean = {
    require(isSorted(l1) && isSorted(l2) && l1.forall(_ <= pivot) && l2.forall(_ >= pivot))
    isSorted(l1 ++ Cons(pivot,l2)) because{
      l1 match{
        case Nil() => isSorted(Cons(pivot,l2))
        case Cons(h,Nil()) => h <= pivot && isSorted(Cons(pivot,l2))
        case Cons(h,t) => h <= t.head && concatIsSorted(t,l2,pivot)
      }     
    }   
  }.holds

1 个答案:

答案 0 :(得分:2)

由于looks like这是一个家庭作业问题,我将尝试引导您走向解决方案,而不是放弃它。

首先请注意,该程序会验证您是否使用Nil()替换par中的case Nil() => Nil()个案。这表明验证者无法证明quickSort(l) ++ Cons(x, quickSort(r))的结果已排序(但它设法为Nil()执行此操作!)。

如果--debug=verification不足以理解为什么验证者无法证明您认为应该这样做,那么继续进行的方法是引入额外的功能,您可以精确地表达您的期望。例如,如果您定义:

def plusplus(l: List[BigInt], r: List[BigInt]): List[BigInt] = l ++ r

并用你期望验证者证明的东西注释它,即

  • 假设lr已排序且l < r(适用于<的定义)
  • l ++ r的结果已排序

您将看到验证者无法证明此属性,这意味着您需要使用附加辅助函数(前后条件)进一步指导验证。

请注意,此示例取自Dependent Types for Program Termination Verification,阅读本文可能会对您有所帮助。