// http://leon.epfl.ch/ import leon.Utils._ import leon.Annotations._ object MaxSum { def maxSum(a: Array[Int]): (Int, Int) = { require (a.length > 0) var sum = 0 var max = 0 var i = 0 (while (i < a.length) { if (max < a(i)) max = a(i) sum = sum + a(i) i = i + 1 }) invariant (sum <= i * max && 0 <= i && i <= a.length) (sum, max) } ensuring (res => res._1 <= a.length * res._2) } object IntListExample1 { sealed abstract class IntList case class Cons(head: Int, tail: IntList) extends IntList case class Nil() extends IntList def implies(b1:Boolean, b2:Boolean) = !b1 || b2 def contents(l: IntList): Set[Int] = l match { case Nil() => Set.empty case Cons(x,xs) => contents(xs) ++ Set(x) } def occurs(x:Int, l:IntList):Boolean = { l match { case Nil() => false case Cons(h, t) => (h == x) || occurs(x,t) } } ensuring { res => res == (contents(l) contains x) } def size(l: IntList) : Int = { l match { case Nil() => 0 case Cons(_, t) => 1 + size(t) } } ensuring { res => res >= 0} // } ensuring { res => if (l == Nil()) res == 0 else res > 0} def sizeTailRec(l: IntList) : Int = sizeTailRecAcc(l, 0) def sizeTailRecAcc(l: IntList, acc: Int) : Int = { require(acc >= 0) l match { case Nil() => acc case Cons(_, xs) => sizeTailRecAcc(xs, acc+1) } } ensuring(res => res == size(l) + acc) def sizesAreEquiv(l: IntList) : Boolean = { size(l) == sizeTailRec(l) } ensuring { res => true } //} holds } import leon.Annotations._ import leon.Utils._ object IntListOperations { sealed abstract class IntList case class Cons(head: Int, tail: IntList) extends IntList case class Nil() extends IntList sealed abstract class IntPairList case class IPCons(head: IntPair, tail: IntPairList) extends IntPairList case class IPNil() extends IntPairList sealed abstract class IntPair case class IP(fst: Int, snd: Int) extends IntPair def size(l: IntList) : Int = (l match { case Nil() => 0 case Cons(_, t) => 1 + size(t) }) ensuring(res => res >= 0) def iplSize(l: IntPairList) : Int = (l match { case IPNil() => 0 case IPCons(_, xs) => 1 + iplSize(xs) }) ensuring(_ >= 0) def zip(l1: IntList, l2: IntList) : IntPairList = { // try to comment this and see how pattern-matching becomes // non-exhaustive and post-condition fails require(size(l1) == size(l2)) l1 match { case Nil() => IPNil() case Cons(x, xs) => l2 match { case Cons(y, ys) => IPCons(IP(x, y), zip(xs, ys)) } } } ensuring(iplSize(_) == size(l1)) def sizeTailRec(l: IntList) : Int = sizeTailRecAcc(l, 0) def sizeTailRecAcc(l: IntList, acc: Int) : Int = { require(acc >= 0) l match { case Nil() => acc case Cons(_, xs) => sizeTailRecAcc(xs, acc+1) } } ensuring(res => res == size(l) + acc) def sizesAreEquiv(l: IntList) : Boolean = { size(l) == sizeTailRec(l) } holds def content(l: IntList) : Set[Int] = l match { case Nil() => Set.empty[Int] case Cons(x, xs) => Set(x) ++ content(xs) } def sizeAndContent(l: IntList) : Boolean = { size(l) == 0 || content(l) != Set.empty[Int] } holds def drunk(l : IntList) : IntList = (l match { case Nil() => Nil() case Cons(x,l1) => Cons(x,Cons(x,drunk(l1))) }) ensuring (size(_) == 2 * size(l)) def reverse(l: IntList) : IntList = reverse0(l, Nil()) ensuring(content(_) == content(l)) def reverse0(l1: IntList, l2: IntList) : IntList = (l1 match { case Nil() => l2 case Cons(x, xs) => reverse0(xs, Cons(x, l2)) }) ensuring(content(_) == content(l1) ++ content(l2)) def append(l1 : IntList, l2 : IntList) : IntList = (l1 match { case Nil() => l2 case Cons(x,xs) => Cons(x, append(xs, l2)) }) ensuring(content(_) == content(l1) ++ content(l2)) @induct def nilAppend(l : IntList) : Boolean = (append(l, Nil()) == l) holds @induct def appendAssoc(xs : IntList, ys : IntList, zs : IntList) : Boolean = (append(append(xs, ys), zs) == append(xs, append(ys, zs))) holds def revAuxBroken(l1 : IntList, e : Int, l2 : IntList) : Boolean = { (append(reverse(l1), Cons(e,l2)) == reverse0(l1, l2)) } holds @induct def sizeAppend(l1 : IntList, l2 : IntList) : Boolean = (size(append(l1, l2)) == size(l1) + size(l2)) holds @induct def concat(l1: IntList, l2: IntList) : IntList = concat0(l1, l2, Nil()) ensuring(content(_) == content(l1) ++ content(l2)) @induct def concat0(l1: IntList, l2: IntList, l3: IntList) : IntList = (l1 match { case Nil() => l2 match { case Nil() => reverse(l3) case Cons(y, ys) => { concat0(Nil(), ys, Cons(y, l3)) } } case Cons(x, xs) => concat0(xs, l2, Cons(x, l3)) }) ensuring(content(_) == content(l1) ++ content(l2) ++ content(l3)) } import leon.Annotations._ import leon.Utils._ object InsertionSort { sealed abstract class List case class Cons(head:Int,tail:List) extends List case class Nil() extends List sealed abstract class OptInt case class Some(value: Int) extends OptInt case class None() extends OptInt def size(l : List) : Int = (l match { case Nil() => 0 case Cons(_, xs) => 1 + size(xs) }) ensuring(_ >= 0) def contents(l: List): Set[Int] = l match { case Nil() => Set.empty case Cons(x,xs) => contents(xs) ++ Set(x) } def isSorted(l: List): Boolean = l match { case Nil() => true case Cons(x, Nil()) => true case Cons(x, Cons(y, ys)) => x <= y && isSorted(Cons(y, ys)) } /* Inserting element 'e' into a sorted list 'l' produces a sorted list with * the expected content and size */ def sortedIns(e: Int, l: List): List = { require(isSorted(l)) l match { case Nil() => Cons(e,Nil()) case Cons(x,xs) => if (x <= e) Cons(x,sortedIns(e, xs)) else Cons(e, l) } } ensuring(res => contents(res) == contents(l) ++ Set(e) && isSorted(res) && size(res) == size(l) + 1 ) /* A counterexample is found when we forget to specify the precondition */ def buggySortedIns(e: Int, l: List): List = { l match { case Nil() => Cons(e,Nil()) case Cons(x,xs) => if (x <= e) Cons(x,buggySortedIns(e, xs)) else Cons(e, l) } } ensuring(res => contents(res) == contents(l) ++ Set(e) && isSorted(res) && size(res) == size(l) + 1 ) /* Insertion sort yields a sorted list of same size and content as the input * list */ def sort(l: List): List = (l match { case Nil() => Nil() case Cons(x,xs) => sortedIns(x, sort(xs)) }) ensuring(res => contents(res) == contents(l) && isSorted(res) && size(res) == size(l) ) /* Merges one (unsorted) list into another, sorted, list. */ def mergeInto(l1 : List, l2 : List) : List = { require(isSorted(l2)) l1 match { case Nil() => l2 case Cons(x, xs) => mergeInto(xs, sortedIns(x, l2)) } } ensuring(res => contents(res) == contents(l1) ++ contents(l2) && isSorted(res)) def main(args: Array[String]): Unit = { val ls: List = Cons(5, Cons(2, Cons(4, Cons(5, Cons(1, Cons(8,Nil())))))) println(ls) println(sort(ls)) } }