From abd6a94c856d20e5771d46bdf233a54389830929 Mon Sep 17 00:00:00 2001 From: Etienne Kneuss <ekneuss@gmail.com> Date: Wed, 19 Dec 2012 02:26:53 +0100 Subject: [PATCH] Add various benchmarks New Verification Benchmarks: - Addresses - AmortizedQueue - TreeListSet New Synthesis Benchmarks: - List - BinaryTree - AVLTree (incomplete) --- testcases/Addresses.scala | 74 +++++++ testcases/AmortizedQueueStrongSpec.scala | 212 +++++++++++++++++++ testcases/TreeListSetNoDup.scala | 100 +++++++++ testcases/synthesis/cav2013/AVLTree.scala | 90 ++++++++ testcases/synthesis/cav2013/BinaryTree.scala | 61 ++++++ testcases/synthesis/cav2013/List.scala | 64 ++++++ 6 files changed, 601 insertions(+) create mode 100644 testcases/Addresses.scala create mode 100644 testcases/AmortizedQueueStrongSpec.scala create mode 100644 testcases/TreeListSetNoDup.scala create mode 100644 testcases/synthesis/cav2013/AVLTree.scala create mode 100644 testcases/synthesis/cav2013/BinaryTree.scala create mode 100644 testcases/synthesis/cav2013/List.scala diff --git a/testcases/Addresses.scala b/testcases/Addresses.scala new file mode 100644 index 000000000..82e354d76 --- /dev/null +++ b/testcases/Addresses.scala @@ -0,0 +1,74 @@ +import scala.collection.immutable.Set +import leon.Annotations._ +import leon.Utils._ + +object Addresses { + // list of integers + sealed abstract class List + case class Cons(a:Int,b:Int,c:Int, tail:List) extends List + case class Nil() extends List + + def empty() = Set.empty[Int] + + def setA(l:List) : Set[Int] = l match { + case Nil() => empty + case Cons(a,b,c,l1) => Set(a) ++ setA(l1) + } + + def containsA(x:Int,l:List) : Boolean = (l match { + case Nil() => false + case Cons(a,b,c,t) => a==x || containsA(x,t) + }) ensuring (res => res == (setA(l) contains x)) + + def theseAunique1(as:Set[Int],l:List) : Boolean = l match { + case Nil() => true + case Cons(a,b,c,l1) => + theseAunique1(as,l1) && !(as contains a) && (setA(l1) contains a) + } + + def theseAunique2(as:Set[Int],l:List) : Boolean = (l match { + case Nil() => true + case Cons(a,b,c,l1) => + theseAunique2(as,l1) && !(as contains a) && containsA(a,l1) + }) ensuring (res => res==theseAunique1(as,l)) + + def disjoint(x:Set[Int],y:Set[Int]):Boolean = + x.intersect(y).isEmpty + + def uniqueAbsentAs(unique:Set[Int],absent:Set[Int],l:List) : Boolean = (l match { + case Nil() => true + case Cons(a,b,c,l1) => { + !(absent contains a) && + (if (unique contains a) uniqueAbsentAs(unique -- Set(a), absent ++ Set(a), l1) + else uniqueAbsentAs(unique, absent, l1)) + } + }) ensuring (res => theseAunique1(unique,l) && disjoint(setA(l),absent)) + + def allPos(l:List) : Boolean = l match { + case Nil() => true + case Cons(a,b,c,l1) => 0 <= a && 0 <= b && 0 <= c && allPos(l1) + } + + def max(x:Int,y:Int) = if (x <= y) x else y + + def collectA(x:Int,l:List) : (Int,Int,List) = (l match { + case Nil() => (0,0,Nil()) + case Cons(a,b,c,l1) if (a==x) => { + val (b2,c2,l2) = collectA(x,l1) + (max(b,b2),max(c,c2),l2) + } + case Cons(a,b,c,l1) if (a!=x) => { + val (b2,c2,l2) = collectA(x,l1) + (b2,c2,Cons(a,b,c,l2)) + } + }) ensuring (res => { + val (b,c,l1) = res + !setA(l1).contains(x) + }) + + def makeUniqueA(x:Int,l:List) : List = { + require(allPos(l)) + val (b,c,l1) = collectA(x,l) + Cons(x,b,c,l1) + } ensuring(res => theseAunique1(Set(x),res)) +} diff --git a/testcases/AmortizedQueueStrongSpec.scala b/testcases/AmortizedQueueStrongSpec.scala new file mode 100644 index 000000000..410be2255 --- /dev/null +++ b/testcases/AmortizedQueueStrongSpec.scala @@ -0,0 +1,212 @@ +import scala.collection.immutable.Set +import leon.Utils._ +import leon.Annotations._ + +object AmortizedQueue { + sealed abstract class List + case class Cons(head : Int, tail : List) extends List + case class Nil() extends List + + sealed abstract class AbsQueue + case class Queue(front : List, rear : List) extends AbsQueue + + def size(list : List) : Int = (list match { + case Nil() => 0 + case Cons(_, xs) => 1 + size(xs) + }) ensuring(_ >= 0) + + def content(l: List) : Set[Int] = l match { + case Nil() => Set.empty[Int] + case Cons(x, xs) => Set(x) ++ content(xs) + } + + def q2l(queue : AbsQueue) : List = queue match { + case Queue(front, rear) => concat(front, reverse(rear)) + } + + def nth(l:List, n:Int) : Int = { + require(0 <= n && n < size(l)) + l match { + case Cons(x,xs) => + if (n==0) x else nth(xs, n-1) + } + } + + def l2mFrom(k:Int, l:List) : Map[Int,Int] = (l match { + case Nil() => Map[Int,Int]() + case Cons(x,xs) => l2mFrom(k+1,xs).updated(k,x) + }) + + def l2m(l:List) : Map[Int,Int] = l2mFrom(0,l) + + def concat(l1 : List, l2 : List) : List = (l1 match { + case Nil() => l2 + case Cons(x,xs) => Cons(x, concat(xs, l2)) + }) ensuring (res => size(res) == size(l1) + size(l2) && content(res) == content(l1) ++ content(l2)) + + def concatTest(l1 : List, l2 : List, i:Int) : List = ({ + require(0 <= i && i < size(l1) + size(l2)) + l1 match { + case Nil() => l2 + case Cons(x,xs) => Cons(x, + if (i == 0) concat(xs, l2) + else concatTest(xs, l2, i-1)) + } + }) ensuring (res => size(res) == size(l1) + size(l2) && + content(res) == content(l1) ++ content(l2) && + nth(res,i) == (if (i < size(l1)) nth(l1,i) else nth(l2,i-size(l1))) && + res == concat(l1,l2)) + + def nthConcat(l1:List, l2:List, i:Int) : Boolean = { + require(0 <= i && i < size(l1) + size(l2)) + concatTest(l1, l2, i) == concatTest(l1, l2, i) && + nth(concat(l1,l2), i) == (if (i < size(l1)) nth(l1,i) else nth(l2,i-size(l1))) + } holds + + def sameUpto(l1:List, l2:List, k:Int) : Boolean = { + require(0 <= k) + (l1,l2) match { + case (Nil(),Nil()) => true + case (Nil(),_) => false + case (_,Nil()) => false + case (Cons(x,xs),Cons(y,ys)) => { + x==y && (if (k==0) true else sameUpto(xs,ys,k-1)) + } + } + } ensuring(res => !(size(l1)==k && size(l2)==k && res) || l1==l2) + + @induct + def concatAssoc(l1:List, l2:List, l3:List) : Boolean = { + concat(l1, concat(l2,l3)) == concat(concat(l1,l2), l3) + } holds + + def concatCons(x:Int, l2:List, l3:List) : Boolean = { + Cons(x, concat(l2,l3)) == concat(Cons(x,l2), l3) + } holds + + def isAmortized(queue : AbsQueue) : Boolean = queue match { + case Queue(front, rear) => size(front) >= size(rear) + } + + def reverse(l : List) : List = (l match { + case Nil() => Nil() + case Cons(x, xs) => concat(reverse(xs), Cons(x, Nil())) + }) ensuring (res => content(res) == content(l)) + + def revConcatNth(l1:List, l2:List, i:Int) : Boolean = { + require(0 <= i && i < size(l1)+size(l2)) + nth(reverse(concat(l1,l2)),i) == nth(concat(reverse(l2), reverse(l1)),i) + } holds + + def revrev(l:List) : Boolean = { + reverse(reverse(l)) == l + } holds + + def amortizedQueue(front : List, rear : List) : AbsQueue = { + if (size(rear) <= size(front)) + Queue(front, rear) + else + Queue(concat(front, reverse(rear)), Nil()) + } ensuring(res => isAmortized(res) && q2l(Queue(front, rear)) == q2l(res)) + + def isEmpty(queue : AbsQueue) : Boolean = (queue match { + case Queue(Nil(), Nil()) => true + case _ => false + }) ensuring(res => (res == (q2l(queue) == Nil()))) + + def enqueue(queue : AbsQueue, elem : Int) : AbsQueue = (queue match { + case Queue(front, rear) => amortizedQueue(front, Cons(elem, rear)) + }) ensuring(res => isAmortized(res) && q2l(res) == concat(q2l(queue), Cons(elem, Nil()))) + // this did not find a counterexample: + // ensuring(res => isAmortized(res) && q2l(res) == Cons(elem, q2l(queue))) + + def push(queue : AbsQueue, elem : Int) : AbsQueue = (queue match { + case Queue(front, rear) => amortizedQueue(Cons(elem,front), rear) + }) ensuring(res => isAmortized(res) && q2l(res) == Cons(elem, q2l(queue))) + + + // I did not know why this does not type check + def matchQ(queue : AbsQueue) : (Int, AbsQueue) = ({ + require(isAmortized(queue) && !isEmpty(queue)) + queue match { + case Queue(Cons(f, fs), rear) => (f, amortizedQueue(fs, rear)) + } + }) ensuring(res => { + val (f,q) = res + q2l(queue) == Cons(f, q2l(q)) + }) + + def tail(queue : AbsQueue) : AbsQueue = ({ + require(isAmortized(queue) && !isEmpty(queue)) + queue match { + case Queue(Cons(f, fs), rear) => amortizedQueue(fs, rear) + } + }) ensuring(res => isAmortized(res) && (q2l(queue) match { + case Nil() => false + case Cons(_,xs) => q2l(res)==xs + })) + + def front(queue : AbsQueue) : Int = ({ + require(isAmortized(queue) && !isEmpty(queue)) + queue match { + case Queue(Cons(f, _), _) => f + } + }) ensuring(res => q2l(queue) match { + case Nil() => false + case Cons(x,_) => x==res + }) + + // @induct + // def propEnqueue(rear : List, front : List, list : List, elem : Int) : Boolean = { + // require(isAmortized(Queue(front, rear))) + // val queue = Queue(front, rear) + // if (q2l(queue) == list) { + // q2l(enqueue(queue, elem)) == concat(list, Cons(elem, Nil())) + // } else + // true + // } holds + + @induct + def propFront(queue : AbsQueue, list : List, elem : Int) : Boolean = { + require(!isEmpty(queue) && isAmortized(queue)) + if (q2l(queue) == list) { + list match { + case Cons(x, _) => front(queue) == x + } + } else + true + } holds + + @induct + def propTail(rear : List, front : List, list : List, elem : Int) : Boolean = { + require(!isEmpty(Queue(front, rear)) && isAmortized(Queue(front, rear))) + if (q2l(Queue(front, rear)) == list) { + list match { + case Cons(_, xs) => q2l(tail(Queue(front, rear))) == xs + } + } else + true + } // holds + + def enqueueAndFront(queue : AbsQueue, elem : Int) : Boolean = { + if (isEmpty(queue)) + front(enqueue(queue, elem)) == elem + else + true + } holds + + def enqueueDequeueThrice(queue : AbsQueue, e1 : Int, e2 : Int, e3 : Int) : Boolean = { + if (isEmpty(queue)) { + val q1 = enqueue(queue, e1) + val q2 = enqueue(q1, e2) + val q3 = enqueue(q2, e3) + val e1prime = front(q3) + val q4 = tail(q3) + val e2prime = front(q4) + val q5 = tail(q4) + val e3prime = front(q5) + e1 == e1prime && e2 == e2prime && e3 == e3prime + } else + true + } holds +} diff --git a/testcases/TreeListSetNoDup.scala b/testcases/TreeListSetNoDup.scala new file mode 100644 index 000000000..2a208d3d0 --- /dev/null +++ b/testcases/TreeListSetNoDup.scala @@ -0,0 +1,100 @@ +import scala.collection.immutable.Set +import leon.Annotations._ +import leon.Utils._ + +object BinaryTree { + // list of integers + sealed abstract class List + case class Cons(head: Int, tail: List) extends List + case class Nil() extends List + + // set of elements from l + def l2s(l: List): Set[Int] = l match { + case Nil() => Set() + case Cons(i, t) => Set(i) ++ l2s(t) + } + + // list of t, in order, in from of l0 + def seqWith(t:Tree,l0:List) : List = (t match { + case Leaf() => l0 + case Node(l, v, r) => seqWith(l,Cons(v,seqWith(r,l0))) + }) ensuring (res => l2s(res) == t2s(t) ++ l2s(l0)) + + // list of tree t + def t2l(t:Tree) : List = seqWith(t,Nil()) + + // l has no duplicates, nor elements from s + def noDupWith(l:List,s:Set[Int]) : Boolean = l match { + case Nil() => true + case Cons(h,l1) => !s.contains(h) && noDupWith(l1,Set(h) ++ s) + } + + // l has no duplicates + def noDup(l:List): Boolean = noDupWith(l,Set.empty[Int]) + + // removing duplicates from l1 gives l2 + def removeDupGives(l1:List,l2:List) : Boolean = + l2s(l1)==l2s(l2) && noDup(l2) + + def removeDupAnd(l:List,s0:Set[Int]) : List = (l match { + case Nil() => Nil() + case Cons(h,l1) => { + if (s0.contains(h)) removeDupAnd(l1,s0) + else Cons(h,removeDupAnd(l1,Set(h)++s0)) + } + }) ensuring (res => noDupWith(res,s0) && l2s(l) ++ s0 == l2s(res) ++ s0) + + def removeDup(l:List) : List = ({ + removeDupAnd(l,Set.empty[Int]) + }) ensuring (res => removeDupGives(l,res)) + + def revRemoveDupAnd(l:List,s0:Set[Int],l0:List) : List = ({ + require(l2s(l0).subsetOf(s0) && noDup(l0)) + l match { + case Nil() => l0 + case Cons(h,l1) => { + if (s0.contains(h)) revRemoveDupAnd(l1,s0,l0) + else revRemoveDupAnd(l1,Set(h)++s0,Cons(h,l0)) + } + } + }) ensuring (res => noDupWith(res,s0) && l2s(l) ++l2s(l0) ++ s0 == l2s(res) ++ s0) + + def revRemoveDup(l:List) : List = ({ + revRemoveDupAnd( + revRemoveDupAnd(l,Set.empty[Int],Nil()), + Set.empty[Int],Nil()) + }) ensuring (res => removeDupGives(l,res)) + + // tree of integers + sealed abstract class Tree + case class Node(left : Tree, value : Int, right : Tree) extends Tree + case class Leaf() extends Tree + + // set of elements from t + def t2s(t : Tree): Set[Int] = t match { + case Leaf() => Set.empty[Int] + case Node(l, v, r) => t2s(l) ++ Set(v) ++ t2s(r) + } + + // list of elements of t, in order, without duplicates, in front of l0 + def seqNoDup(t:Tree,l0:List,s0:Set[Int]) : (List,Set[Int]) = ({ + require(l2s(l0).subsetOf(s0) && noDup(l0)) + t match { + case Leaf() => (l0,s0) + case Node(l, v, r) => { + val (rl,rs) = seqNoDup(r,l0,s0) + val (l1,s1) = if (rs.contains(v)) (rl,rs) else (Cons(v,rl),Set(v)++rs) + seqNoDup(l,l1,s1) + } + } + }) ensuring (res => { + val (lres,sres) = res + l2s(lres).subsetOf(sres) && + removeDupGives(t2l(t), lres) + }) + + // list of elements of t, without duplicates + def t2lNoDup(t:Tree) : List = ({ + seqNoDup(t,Nil(),Set.empty[Int])._1 + }) ensuring (res => removeDupGives(t2l(t), res)) +} diff --git a/testcases/synthesis/cav2013/AVLTree.scala b/testcases/synthesis/cav2013/AVLTree.scala new file mode 100644 index 000000000..9e40228e1 --- /dev/null +++ b/testcases/synthesis/cav2013/AVLTree.scala @@ -0,0 +1,90 @@ +import scala.collection.immutable.Set +import leon.Annotations._ +import leon.Utils._ + +object AVLTree { + sealed abstract class Tree + case class Node(left : Tree, value : Int, right : Tree) extends Tree + case class Leaf() extends Tree + + def content(t : Tree): Set[Int] = t match { + case Leaf() => Set.empty[Int] + case Node(l, v, r) => content(l) ++ Set(v) ++ content(r) + } + + def height(t: Tree): Int = t match { + case Leaf() => 0 + case Node(l, _, r) => + val lh = height(l) + val rh = height(r) + if (rh > lh) { + rh+1 + } else { + lh+1 + } + } + + def isSortedMinMax(t: Tree, min: Int, max: Int): Boolean = t match { + case Node(l, v, r) => + isSortedMinMax(l, min, v) && + isSortedMinMax(r, v, max) && + v < max && v > min + case _ => true + } + + def isSortedMin(t: Tree, min: Int): Boolean = t match { + case Node(l, v, r) => + isSortedMinMax(l, min, v) && + isSortedMin(r, v) && + v > min + case _ => true + } + + def isSortedMax(t: Tree, max: Int): Boolean = t match { + case Node(l, v, r) => + isSortedMax(l, v) && + isSortedMinMax(r, v, max) && + v < max + case _ => true + } + + def isBalanced(t: Tree): Boolean = t match { + case Node(l, v, r) => + val diff = height(l)-height(r) + + !(diff > 1 || diff < -1) && isBalanced(l) && isBalanced(r) + case Leaf() => + true + } + + def isSorted(t: Tree): Boolean = t match { + case Node(l, v, r) => + isSortedMin(r, v) && + isSortedMax(l, v) + case _ => true + } + + def deleteSynth(in : Tree, v : Int) = choose { + (out : Tree) => content(out) == (content(in) -- Set(v)) + } + + def insertSynth(in : Tree, v : Int) = choose { + (out : Tree) => content(out) == (content(in) ++ Set(v)) + } + + def insertBalancedSynth(in: Tree, v: Int) = choose { + (out : Tree) => isBalanced(in) && (content(out) == (content(in) ++ Set(v))) && isBalanced(out) + } + + def insertSortedSynth(in : Tree, v : Int) = choose { + (out : Tree) => isSorted(in) && (content(out) == (content(in) ++ Set(v))) && isSorted(out) + } + + def deleteSortedSynth(in : Tree, v : Int) = choose { + (out : Tree) => isSorted(in) && (content(out) == (content(in) -- Set(v))) && isSorted(out) + } + + def deleteBalancedSynth(in: Tree, v: Int) = choose { + (out : Tree) => isBalanced(in) && (content(out) == (content(in) -- Set(v))) && isBalanced(out) + } +} diff --git a/testcases/synthesis/cav2013/BinaryTree.scala b/testcases/synthesis/cav2013/BinaryTree.scala new file mode 100644 index 000000000..cbebc3808 --- /dev/null +++ b/testcases/synthesis/cav2013/BinaryTree.scala @@ -0,0 +1,61 @@ +import scala.collection.immutable.Set +import leon.Annotations._ +import leon.Utils._ + +object BinaryTree { + sealed abstract class Tree + case class Node(left : Tree, value : Int, right : Tree) extends Tree + case class Leaf() extends Tree + + def content(t : Tree): Set[Int] = t match { + case Leaf() => Set.empty[Int] + case Node(l, v, r) => content(l) ++ Set(v) ++ content(r) + } + + def isSortedMinMax(t: Tree, min: Int, max: Int): Boolean = t match { + case Node(l, v, r) => + isSortedMinMax(l, min, v) && + isSortedMinMax(r, v, max) && + v < max && v > min + case _ => true + } + + def isSortedMin(t: Tree, min: Int): Boolean = t match { + case Node(l, v, r) => + isSortedMinMax(l, min, v) && + isSortedMin(r, v) && + v > min + case _ => true + } + + def isSortedMax(t: Tree, max: Int): Boolean = t match { + case Node(l, v, r) => + isSortedMax(l, v) && + isSortedMinMax(r, v, max) && + v < max + case _ => true + } + + def isSorted(t: Tree): Boolean = t match { + case Node(l, v, r) => + isSortedMin(r, v) && + isSortedMax(l, v) + case _ => true + } + + def deleteSynth(in : Tree, v : Int) = choose { + (out : Tree) => content(out) == (content(in) -- Set(v)) + } + + def insertSynth(in : Tree, v : Int) = choose { + (out : Tree) => content(out) == (content(in) ++ Set(v)) + } + + def insertSortedSynth(in : Tree, v : Int) = choose { + (out : Tree) => isSorted(in) && (content(out) == (content(in) ++ Set(v))) && isSorted(out) + } + + def deleteSortedSynth(in : Tree, v : Int) = choose { + (out : Tree) => isSorted(in) && (content(out) == (content(in) -- Set(v))) && isSorted(out) + } +} diff --git a/testcases/synthesis/cav2013/List.scala b/testcases/synthesis/cav2013/List.scala new file mode 100644 index 000000000..ce9c60f4e --- /dev/null +++ b/testcases/synthesis/cav2013/List.scala @@ -0,0 +1,64 @@ +import scala.collection.immutable.Set +import leon.Annotations._ +import leon.Utils._ + +object List { + sealed abstract class List + case class Cons(head: Int, tail: List) extends List + case class Nil() extends List + + def size(l: List) : Int = (l match { + case Nil() => 0 + case Cons(_, t) => 1 + size(t) + }) ensuring(res => res >= 0) + + def content(l: List): Set[Int] = l match { + case Nil() => Set.empty[Int] + case Cons(i, t) => Set(i) ++ content(t) + } + + 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)) + } + + def isStrictSorted(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)) + } + + def deleteSynth(in: List, v: Int) = choose { + (out: List) => (content(out) == (content(in) -- Set(v))) + } + + def deleteSortedSynth(in: List, v: Int) = choose { + (out: List) => isSorted(in) && (content(out) == (content(in) -- Set(v))) && isSorted(out) + } + + def insertSynth(in: List, v: Int) = choose { + (out: List) => (content(out) == (content(in) ++ Set(v))) + } + + def insertSortedSynth(in: List, v: Int) = choose { + (out: List) => isSorted(in) && (content(out) == (content(in) ++ Set(v))) && isSorted(out) + } + + def insertStrictSortedSynth(in: List, v: Int) = choose { + (out: List) => isStrictSorted(in) && (content(out) == (content(in) ++ Set(v))) && isStrictSorted(out) + } + + def concatSynth(in1: List, in2: List) = choose { + (out : List) => content(out) == content(in1) ++ content(in2) + } + + def mergeSynth(in1: List, in2: List) = choose { + (out : List) => isSorted(in1) && isSorted(in2) && (content(out) == content(in1) ++ content(in2)) && isSorted(out) + } + + def mergeStrictSynth(in1: List, in2: List) = choose { + (out : List) => isStrictSorted(in1) && isStrictSorted(in2) && (content(out) == content(in1) ++ content(in2)) && isStrictSorted(out) + } + +} -- GitLab