From e2654ec40356478d0ecce414cbd096d2cb29b568 Mon Sep 17 00:00:00 2001 From: Philippe Suter <philippe.suter@gmail.com> Date: Wed, 9 Jan 2013 18:56:37 +0100 Subject: [PATCH] Added MergeSort to (verification) regression suite. --- .../purescala/valid/MergeSort.scala | 120 ++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 src/test/resources/regression/verification/purescala/valid/MergeSort.scala diff --git a/src/test/resources/regression/verification/purescala/valid/MergeSort.scala b/src/test/resources/regression/verification/purescala/valid/MergeSort.scala new file mode 100644 index 000000000..c3592319f --- /dev/null +++ b/src/test/resources/regression/verification/purescala/valid/MergeSort.scala @@ -0,0 +1,120 @@ +import leon.Annotations._ +import leon.Utils._ + +object MergeSort { + // Data types + sealed abstract class List + case class Cons(head : Int, tail : List) extends List + case class Nil() extends List + + sealed abstract class LList + case class LCons(head : List, tail : LList) extends LList + case class LNil() extends LList + + def content(list : List) : Set[Int] = list match { + case Nil() => Set.empty[Int] + case Cons(x, xs) => Set(x) ++ content(xs) + } + + def lContent(llist : LList) : Set[Int] = llist match { + case LNil() => Set.empty[Int] + case LCons(x, xs) => content(x) ++ lContent(xs) + } + + def size(list : List) : Int = (list match { + case Nil() => 0 + case Cons(_, xs) => 1 + size(xs) + }) ensuring(_ >= 0) + + def isSorted(list : List) : Boolean = list match { + case Nil() => true + case Cons(_, Nil()) => true + case Cons(x1, Cons(x2, _)) if(x1 > x2) => false + case Cons(_, xs) => isSorted(xs) + } + + def lIsSorted(llist : LList) : Boolean = llist match { + case LNil() => true + case LCons(x, xs) => isSorted(x) && lIsSorted(xs) + } + + def abs(i : Int) : Int = { + if(i < 0) -i else i + } ensuring(_ >= 0) + + def mergeSpec(list1 : List, list2 : List, res : List) : Boolean = { + isSorted(res) && content(res) == content(list1) ++ content(list2) + } + + def mergeFast(list1 : List, list2 : List) : List = { + require(isSorted(list1) && isSorted(list2)) + + (list1, list2) match { + case (_, Nil()) => list1 + case (Nil(), _) => list2 + case (Cons(x, xs), Cons(y, ys)) => + if(x <= y) { + Cons(x, mergeFast(xs, list2)) + } else { + Cons(y, mergeFast(list1, ys)) + } + } + } ensuring(res => mergeSpec(list1, list2, res)) + + def splitSpec(list : List, res : (List,List)) : Boolean = { + val s1 = size(res._1) + val s2 = size(res._2) + abs(s1 - s2) <= 1 && s1 + s2 == size(list) && + content(res._1) ++ content(res._2) == content(list) + } + + def split(list : List) : (List,List) = (list match { + case Nil() => (Nil(), Nil()) + case Cons(x, Nil()) => (Cons(x, Nil()), Nil()) + case Cons(x1, Cons(x2, xs)) => + val (s1,s2) = split(xs) + (Cons(x1, s1), Cons(x2, s2)) + }) ensuring(res => splitSpec(list, res)) + + def sortSpec(in : List, out : List) : Boolean = { + content(out) == content(in) && isSorted(out) + } + + // Not really quicksort, neither mergesort. + def weirdSort(in : List) : List = (in match { + case Nil() => Nil() + case Cons(x, Nil()) => Cons(x, Nil()) + case _ => + val (s1,s2) = split(in) + mergeFast(weirdSort(s1), weirdSort(s2)) + }) ensuring(res => sortSpec(in, res)) + + def toLList(list : List) : LList = (list match { + case Nil() => LNil() + case Cons(x, xs) => LCons(Cons(x, Nil()), toLList(xs)) + }) ensuring(res => lContent(res) == content(list) && lIsSorted(res)) + + def mergeMap(llist : LList) : LList = { + require(lIsSorted(llist)) + + llist match { + case LNil() => LNil() + case o @ LCons(x, LNil()) => o + case LCons(x, LCons(y, ys)) => LCons(mergeFast(x, y), mergeMap(ys)) + } + } ensuring(res => lContent(res) == lContent(llist) && lIsSorted(res)) + + def mergeReduce(llist : LList) : List = { + require(lIsSorted(llist)) + + llist match { + case LNil() => Nil() + case LCons(x, LNil()) => x + case _ => mergeReduce(mergeMap(llist)) + } + } ensuring(res => content(res) == lContent(llist) && isSorted(res)) + + def mergeSort(in : List) : List = { + mergeReduce(toLList(in)) + } ensuring(res => sortSpec(in, res)) +} -- GitLab