如何证明莱昂的名单大小?

时间:2015-04-23 18:20:37

标签: scala leon

我试图证明列表中的大小(元素数量)是非负的,但莱昂未能证明它 - 它只是超时。莱昂真的没有能力证明这个属性,还是我错误地使用它?我的出发点是我在文章“莱昂验证系统概述”中读到的一个函数。

import leon.lang._
import leon.annotation._

object ListSize {
  sealed abstract class List
  case class Cons(head: Int, tail: List) extends List
  case object Nil extends List

  def size(l: List) : Int = (l match {
    case Nil => 0
    case Cons(_, t) => 1 + size(t)
  }) ensuring(_ >= 0)
}

2 个答案:

答案 0 :(得分:6)

Leon的早期版本将Scala的Int类型视为数学,无界,整数。最新版本将Int的值视为带符号的32位向量,并且需要使用BigInt来表示无界整数。

在提供的示例中,Leon超时尝试构建一个大小为Int.MaxValue的列表,这是一个反例,它将证明后置条件不适用于有界整数。

如果您将size的返回类型更改为BigInt,程序会按预期进行验证。

答案 1 :(得分:0)

以前的答案是正确的,但是如果我们希望使用 Int 而不是 BigInt 并且感觉合理列表的大小是非负的,则对我们没有帮助。以下简单的技巧可以解决这个问题并在不锈钢中起作用:

def listLength(l: List[T]): Int = {
    l match {
        case head :: tl => {
            val tlLen = listLength(tl)
            if(tlLen < Int.MaxValue) {
                tlLen + 1
            } else {
                0
            }
        }
        case Nil() => 0
    }
} ensuring(0 <= _)

例如,参见 https://github.com/epfl-lara/bolts/blob/master/data-structures/seqs/ArrayList.scala 的 Bolts 存储库中的 https://stainless.epfl.ch/