From 2a598b2035badcfde878a17682f1fc446c8882cc Mon Sep 17 00:00:00 2001
From: Tihomir Gvero <tihomir.gvero@gmail.com>
Date: Fri, 6 Nov 2009 20:28:58 +0000
Subject: [PATCH] Committing functional data structure examples for Udita.

---
 tests/udita/BinarySearchTreeTest.scala        |  85 ++++++++++
 tests/udita/BinomialHeapTest.scala            | 143 +++++++++++++++++
 tests/udita/LeftistHeapTest.scala             | 101 ++++++++++++
 tests/udita/RedBlackTreeTest.scala            | 135 ++++++++++++++++
 .../SkewBinaryRandomAccessListTest.scala      | 136 ++++++++++++++++
 tests/udita/SplayHeapTest.scala               | 148 ++++++++++++++++++
 6 files changed, 748 insertions(+)
 create mode 100644 tests/udita/BinarySearchTreeTest.scala
 create mode 100644 tests/udita/BinomialHeapTest.scala
 create mode 100644 tests/udita/LeftistHeapTest.scala
 create mode 100644 tests/udita/RedBlackTreeTest.scala
 create mode 100644 tests/udita/SkewBinaryRandomAccessListTest.scala
 create mode 100644 tests/udita/SplayHeapTest.scala

diff --git a/tests/udita/BinarySearchTreeTest.scala b/tests/udita/BinarySearchTreeTest.scala
new file mode 100644
index 000000000..a4d63288e
--- /dev/null
+++ b/tests/udita/BinarySearchTreeTest.scala
@@ -0,0 +1,85 @@
+package udita
+
+import gov.nasa.jpf.jvm.Verify;
+
+object BinarySearchTreeTest  extends Application {
+
+  sealed abstract class BinarySearchTree;
+  case object Empty extends BinarySearchTree;
+  case class Node(left: BinarySearchTree, value:Int, right:BinarySearchTree) extends BinarySearchTree;
+
+  def size(t: BinarySearchTree): Int = t match {
+    case Empty => 0;
+    case Node(left,value,right) => size(left) + 1 + size(right);
+  }
+  
+  def add(x: Int, t:BinarySearchTree):BinarySearchTree =t match {
+    case Empty => Node(Empty,x,Empty);
+    case Node(left,value,right) if (x < value) => Node(add(x,left),value,right);
+    case Node(left,value,right) if (x >= value) => Node(left,value,add(x,right));    
+  }
+  
+  def contains(x :Int, t:BinarySearchTree):Boolean = t match {
+    case Empty => false;
+    case Node(left,value,right) if (x == value) => true;
+    case Node(left,value,right) if (x < value) => contains(x,left);
+    case Node(left,value,right) if (x > value) => contains(x,right);
+  }
+  
+  private def generateBinarySearchTree(treeSize:Int): BinarySearchTree = {
+    val size = Verify.getInt(1, treeSize);
+    val maxNodeValue = size - 1;
+    val t = getSubTree(size, 0, maxNodeValue);
+    System.out.println(t);
+    return t;
+  }
+  
+  private def getSubTree(size:Int, min:Int, max:Int): BinarySearchTree = {
+    if (size == 0) return Empty;
+    if (size == 1) return Node(Empty, Verify.getInt(min,max), Empty);
+
+    val value = Verify.getInt(min,max);
+
+    val leftSize = value - min;
+    val rightSize = size - 1 - leftSize;
+
+    return Node(getSubTree(leftSize, min, value - 1), value, getSubTree(rightSize, value + 1, max));
+  }
+  
+  def content(t:BinarySearchTree):Set[Int] = t match {
+    case Empty => Set.empty;
+    case Node(left,value,right) => (content(left) ++ Set(value) ++ content(right));
+  }
+  
+//  def forallTree(treeSize:Int,property : (BinarySearchTree => Boolean)):Boolean = {
+//      property(generateBinarySearchTree(treeSize));
+//  }
+//  
+//  def forallInt(min:Int, max:Int, property: (Int => Boolean)) : Boolean ={
+//    property(Verify.getInt(min,max));
+//  }
+  
+  //val t = add(17, add(6, add(3, add(5,add(3,Empty)))));
+  
+  //testing tree
+//  System.out.println(t);
+//  System.out.println(content(t));
+//  System.out.println(size(t));
+//  System.out.println(contains(5,t));
+  
+  //testing getInt
+  //assert(forallInt(0,4,(x => forallTree(4,t => content(add(x,t)) == content(t) + x))));
+  
+  def forAll(property:(BinarySearchTree,Int)=> Boolean){
+    assert(property(generateBinarySearchTree(4),Verify.getInt(0,4)));
+  }
+  
+  forAll((t:BinarySearchTree, x:Int) => content(add(x,t)) == content(t) + x);
+  
+  //System.out.println(generateBinarySearchTree(4));
+  //System.out.println("property: "+forallInt(0,4,(x => forallTree(4,t => content(add(x,t)) == content(t) + x))));
+}
+
+
+
+
diff --git a/tests/udita/BinomialHeapTest.scala b/tests/udita/BinomialHeapTest.scala
new file mode 100644
index 000000000..0099f703a
--- /dev/null
+++ b/tests/udita/BinomialHeapTest.scala
@@ -0,0 +1,143 @@
+package udita
+
+import scala.collection.immutable.Multiset;
+import gov.nasa.jpf.jvm.Verify;
+
+object BinomialHeapTest extends Application {
+  sealed case class BinomialHeap(trees:List[BinomialTree]);
+  
+  sealed case class BinomialTree(rank:Int, value:Int, children:List[BinomialTree]);
+  
+  def rankk(t1:BinomialTree):Int = t1 match {
+    case BinomialTree(rank, _, _) => rank;
+  }
+  
+  def root(t1:BinomialTree):Int = t1 match {
+    case BinomialTree(_, value, _) => value;
+  }
+  
+  def link(t1:BinomialTree, t2:BinomialTree):BinomialTree = t1 match {
+    case BinomialTree(rank1,value1,children1) => t2 match {
+      case BinomialTree(rank2,value2,children2) => {
+        if (value1 <= value2) BinomialTree(rank1+1, value1, t2::children1); 
+        else BinomialTree(rank2+1, value2, t1::children2);
+      }
+    }
+  }
+  
+  def insertTree(t:BinomialTree, trees:List[BinomialTree]):List[BinomialTree] = trees match {
+    case Nil => List(t);
+    case t1::ts1 => {
+      if (rankk(t) < rankk(t1)) t::trees;  //bug t::ts1;
+      else insertTree(link(t,t1),ts1);
+    }
+  }
+  
+  def insert(x:Int, trees:List[BinomialTree]):List[BinomialTree] = insertTree(BinomialTree(0,x,Nil), trees);
+  
+  def insert(x:Int, heap:BinomialHeap):BinomialHeap = heap match {
+    case BinomialHeap(ts) => BinomialHeap(insert(x,ts));
+  }                                                                             
+  
+  def merge(ts1:List[BinomialTree],ts2:List[BinomialTree]):List[BinomialTree] = ts1 match {
+    case Nil => ts2;
+    case t1::tss1 => ts2 match {
+      case Nil => ts1;
+      case t2::tss2 => {
+        if (rankk(t1) < rankk(t2)) t1::merge(tss1,ts2);
+        else if (rankk(t2) < rankk(t1)) t2::merge(ts1,tss2);
+        else insertTree(link(t1,t2),merge(tss1,tss2)); 
+      }
+    }
+  }
+  
+  def removeMinTree(ts:List[BinomialTree]):(BinomialTree,List[BinomialTree]) = ts match {
+    case t1::Nil => (t1,Nil);
+    case t1::ts1 => {
+      val (t11,ts11) = removeMinTree(ts1);
+      if (root(t1) <= root(t11)) (t1,ts1);
+      else (t11,t1::ts11);
+    }
+    case Nil => error("removing from empt tree");
+  }
+  
+  def findMin(ts:List[BinomialTree]):Int = {
+    val (t1,_) = removeMinTree(ts);
+    root(t1);
+  }
+  
+  def deleteMin(ts:List[BinomialTree]):List[BinomialTree] ={
+    val (BinomialTree(_,x,ts1),ts2) = removeMinTree(ts);
+    merge(ts1.reverse,ts2);
+  }
+  
+  def deleteMin(heap:BinomialHeap):BinomialHeap = heap match {
+    case BinomialHeap(ts) => BinomialHeap(deleteMin(ts));
+  }
+  
+  def findMin(heap:BinomialHeap):Int = heap match {
+    case BinomialHeap(ts) => findMin(ts);
+  }
+  
+  def generateBinomialTree(rank:Int, min:Int, max:Int): BinomialTree = {
+    if(rank == 0) BinomialTree(rank, Verify.getInt(min,max), Nil);
+    else {
+      val value = Verify.getInt(min,max - rank);
+      var list = List[BinomialTree]();
+      for(i <- 0 until rank) {
+        list = generateBinomialTree(i,value+1,max)::list;
+      }
+      BinomialTree(rank,value,list);
+    }
+  }
+  
+  def generateBinomialHeap(heapSize:Int):BinomialHeap = {
+   var div:Int = heapSize;
+   var list = List[BinomialTree]();
+   var i = 0;
+   while(div > 0) {
+     var mod:Int = div % 2;
+     if (mod == 1) {
+       list= list ::: List(generateBinomialTree(i,0,heapSize));
+     }
+     div = div/2;
+     i+=1;
+   }
+   BinomialHeap(list);
+  }
+
+  def content(t : BinomialHeap): Multiset[Int] = {
+     def inner(t: BinomialTree, mset: Multiset[Int]): Multiset[Int] = t match {
+      case BinomialTree(rank, value, children) => {
+        innerList(children, mset +++ List(value));
+      }
+     }
+     def innerList(ts: List[BinomialTree], mset:Multiset[Int]): Multiset[Int] = ts match {
+       case Nil => mset
+       case t::tss => inner(t, innerList(tss,mset))
+     }
+     t match {
+       case BinomialHeap(ts) => innerList(ts,Multiset.empty[Int]);
+     }
+  }
+  
+  
+  var heap = BinomialHeap(Nil);
+  heap = insert(5,insert(26,insert(1,insert(17,insert(4,heap)))));
+  
+//  System.out.println(heap);
+//  System.out.println(findMin(heap));
+//  System.out.println(deleteMin(heap));
+//  System.out.println(content(heap));
+//  
+//  System.out.println(content(insert(1,heap)) == content(heap) +++ List(1));
+//  System.out.println(generateBinomialHeap(3));
+// 
+                                            
+  def forAll(property : ((BinomialHeap,Int) => Boolean)){
+    assert(property(generateBinomialHeap(4), Verify.getInt(0,4)));
+  }
+
+  forAll((heap, value) => (content(insert(value,heap)) == content(heap) +++ List(value)));
+
+}
diff --git a/tests/udita/LeftistHeapTest.scala b/tests/udita/LeftistHeapTest.scala
new file mode 100644
index 000000000..8e88501df
--- /dev/null
+++ b/tests/udita/LeftistHeapTest.scala
@@ -0,0 +1,101 @@
+package udita
+
+
+import scala.collection.immutable.Multiset;
+import gov.nasa.jpf.jvm.Verify;
+
+object LeftistHeapTest extends Application {
+
+  sealed abstract class Heap{
+    def rankk():Int = this match {
+      case Empty => 0;
+      case Node(rank,_,_,_) => rank;
+    }
+    
+    def insert(x: Int): Heap = {
+      LeftistHeapTest.merge(this, Node(1,x,Empty,Empty))
+    }
+    
+    def findMin(): Int = this match {
+      case Empty => Predef.error(toString());
+      case Node(_,x,_,_) => x
+    }
+    
+//    override def toString(): String = this match {
+//      case Empty => "Empty";
+//      case Node(rank,x,left,right) => "Node("+rank+","+x+","+left+","+right+")";
+//    }
+    
+    //ensuring(res => res == min(content(this).elements.toList))
+    
+    def deleteMin(): Heap = this match {
+      case Empty => Predef.error(toString());
+      case Node(_, _, left: Heap, right: Heap) => LeftistHeapTest.merge(left,right);
+    } 
+    //ensuring(res  => content(res).equals(content(this) - findMin))
+  }
+  
+  case class Node(rank:Int, value:Int, left:Heap, right:Heap) extends Heap;
+  case object Empty extends Heap;
+  
+  def merge(heap1:Heap, heap2:Heap): Heap = heap1 match {
+    case Empty => heap2;
+    case Node(_, value1, left1, right1) => heap2 match {
+      case Empty => heap1;
+      case Node(_, value2, left2, right2) if (value1 <= value2) =>
+        makeAndSwap(left1, value1, merge(right1,heap2));
+      case Node(_, value2, left2, right2) if (value1 > value2) =>
+        makeAndSwap(left2, value2, merge(heap1,right2));
+    }
+  }
+  
+  def makeAndSwap(left:Heap, value:Int, right:Heap): Heap = {
+    if(left.rankk() >= right.rankk()){
+      Node(right.rankk() + 1, value, left, right);
+    } else {
+      Node(left.rankk() + 1, value, right, left);      
+    }
+  }
+  
+  
+  def forAllLeftistHeap(size:Int, property:(Heap=>Boolean)): Boolean = {
+    property(generateLeftistHeap(size));
+  }
+  
+  def generateLeftistHeap(treeSize:Int):Heap = {
+    val size = Verify.getInt(1, treeSize);
+    val maxNodeValue = size - 1;
+    val t = getSubTree(size, -1, maxNodeValue - 1);
+    System.out.println(t);
+    return t;
+  }
+  
+  private def getSubTree(size:Int, min:Int, max:Int): Heap = {
+    if (size == 0) return Empty;
+    if (size == 1) return Node(1, Verify.getInt(min+1,max+1), Empty, Empty);
+
+    val value = Verify.getInt(min+1,max+1);
+    val rightSize = Verify.getInt(0,(size - 1)/2);
+    val leftSize = size - 1 - rightSize;
+    
+    val rightSub = getSubTree(rightSize, value, max);
+    val leftSub = getSubTree(leftSize, value, max);
+    
+    return Node(rightSub.rankk() + 1, value, leftSub, rightSub);
+  }
+  
+  def content(t : Heap): Multiset[Int] = {
+    def inner(t: Heap, mset: Multiset[Int]): Multiset[Int] = t match {
+      case Empty => mset
+      case Node(rank,value,left,right) => inner(right, inner(left, mset +++ List(value)))
+    }
+    inner(t,Multiset.empty[Int]);
+  }
+  
+  def forAll(property : ((Heap,Int) => Boolean)){
+    assert(property(generateLeftistHeap(4), 0));//Verify.getInt(0,4)));
+  }
+
+  forAll((heap: Heap, value: Int) => content(heap.insert(value)) == content(heap) +++ List(value));
+
+}
\ No newline at end of file
diff --git a/tests/udita/RedBlackTreeTest.scala b/tests/udita/RedBlackTreeTest.scala
new file mode 100644
index 000000000..53c64e9e0
--- /dev/null
+++ b/tests/udita/RedBlackTreeTest.scala
@@ -0,0 +1,135 @@
+package udita
+
+import gov.nasa.jpf.jvm.Verify;
+
+object RedBlackTreeTest extends Application {
+  
+  val RED:Boolean = true;
+  val BLACK:Boolean = false; 
+  
+  sealed abstract class Tree
+  case class Empty() extends Tree
+  case class Node(color: Boolean, left: Tree, value: Int, right: Tree) extends Tree
+  
+  
+  def member(x: Int, t:Tree): Boolean = t match {
+    case Empty() => false
+    case Node(_,a,y,b) => 
+      if (x < y) member(x,a)
+      else if (x > y) member(x,b)
+      else true
+  }
+  
+  def insert(x: Int, t: Tree): Tree = {
+    def ins(t: Tree): Tree = t match {
+      case Empty() => Node(RED,Empty(),x,Empty())
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(b))
+    }
+    makeBlack(ins(t))
+  }
+  
+  def balance(c: Boolean, a: Tree, x: Int, b: Tree): Tree = (c,a,x,b) match {
+    case (BLACK,Node(RED,Node(RED,a,xV,b),yV,c),zV,d) => 
+      Node(RED,Node(BLACK,a,xV,b),yV,Node(BLACK,c,zV,d))
+    case (BLACK,Node(RED,a,xV,Node(RED,b,yV,c)),zV,d) => 
+      Node(RED,Node(BLACK,a,xV,b),yV,Node(BLACK,c,zV,d))
+    case (BLACK,a,xV,Node(RED,Node(RED,b,yV,c),zV,d)) => 
+      Node(RED,Node(BLACK,a,xV,b),yV,Node(BLACK,c,zV,d))
+    case (BLACK,a,xV,Node(RED,b,yV,Node(RED,c,zV,d))) => 
+      Node(RED,Node(BLACK,a,xV,b),yV,Node(BLACK,c,zV,d))
+    case (c,a,xV,b) => Node(c,a,xV,b)
+  }
+  
+  /** makeBLACK: Turn a node BLACK. */
+  def makeBlack(n: Tree): Tree = n match {
+    case Node(RED,l,v,r) => Node(BLACK,l,v,r)
+    case _ => n
+  }
+  
+  /* global invariants: 
+   * RED-BLACK trees are binary search trees obeying two key invariants:
+   *
+   * (1) Any path from a root node to a leaf node contains the same number
+   *     of BLACK nodes. (A balancing condition.)
+   *
+   * (2) RED nodes always have BLACK children.
+   *
+   */
+  
+  /* Empty tree are consideRED to be BLACK */
+  def isBLACK(t: Tree): Boolean = t match {
+    case Node(RED,_,_,_) => false
+    case _ => true
+  }
+  
+  
+  def anyPathsContainsSameNumberOfBlackNodes(t: Tree): Boolean = {
+    def blacks(t: Tree, acc: Int): List[Int] = t match {
+      case Empty() => List(acc + 1) // because Empty are assumed to be BLACK
+      case Node(_,l,_,r) => 
+        val upAcc = if(isBLACK(t)) acc + 1 else acc 
+        blacks(l,upAcc) ::: blacks(r,upAcc)  
+    }
+    val paths = blacks(t, 0)
+    
+    if(paths.isEmpty)
+      true
+    else
+      paths.forall(_ == paths.head)
+  } 
+  
+  def areRedNodeChildrenBlack(t: Tree): Boolean = t match {
+    case Node(RED,l,_,r) =>
+      isBLACK(l) && isBLACK(r) &&
+      areRedNodeChildrenBlack(l) && areRedNodeChildrenBlack(r)
+    case Node(BLACK,l,_,r) =>
+      areRedNodeChildrenBlack(l) && areRedNodeChildrenBlack(r)
+    case _ => true
+  }
+  
+  def generateRedBlackTree(treeSize:Int): Tree = {
+    val t = generateBinarySearchTree(treeSize);
+    Verify.ignoreIf(!anyPathsContainsSameNumberOfBlackNodes(t) || !areRedNodeChildrenBlack(t));
+    return t;
+  }
+  
+  private def generateBinarySearchTree(treeSize:Int): Tree = {
+    val size = Verify.getInt(1, treeSize);
+    val maxNodeValue = size - 1;
+    val t = getSubTree(size, 0, maxNodeValue);
+    return t;
+  }
+  
+  private def getSubTree(size:Int, min:Int, max:Int): Tree = {
+    if (size == 0) return Empty();
+    if (size == 1) return Node(Verify.getBoolean(), Empty(), Verify.getInt(min,max), Empty());
+
+    val value = Verify.getInt(min,max);
+
+    val leftSize = value - min;
+    val rightSize = size - 1 - leftSize;
+
+    return Node(Verify.getBoolean(), getSubTree(leftSize, min, value - 1), value, getSubTree(rightSize, value + 1, max));
+  }
+  
+  def content(t:Tree):Set[Int] = t match {
+    case Empty() => Set.empty;
+    case Node(_,left,value,right) => (content(left) ++ Set(value) ++ content(right));
+  }
+  
+  def forAll(property: (Tree,Int) => Boolean){     
+    val t = generateRedBlackTree(4);
+    val x = Verify.getInt(0,4);
+    assert(property(t,x));
+    System.out.println(x+" "+t);
+  }
+  
+  forAll((t:Tree, x:Int)  => ({val t1 = insert(x,t); anyPathsContainsSameNumberOfBlackNodes(t1) && areRedNodeChildrenBlack(t1)}));
+  //forAll{t: Tree => areRedNodeChildrenBlack(t)} //(2)
+
+  //generateRedBlackTree(4);
+
+}
diff --git a/tests/udita/SkewBinaryRandomAccessListTest.scala b/tests/udita/SkewBinaryRandomAccessListTest.scala
new file mode 100644
index 000000000..4f2ff61d2
--- /dev/null
+++ b/tests/udita/SkewBinaryRandomAccessListTest.scala
@@ -0,0 +1,136 @@
+package udita
+
+import scala.collection.immutable.Multiset;
+import gov.nasa.jpf.jvm.Verify;
+
+object SkewBinaryRandomAccessListTest extends Application {
+
+  sealed abstract class Tree
+  case class Leaf(w: Int) extends Tree
+  case class Node(w: Int, left: Tree, right: Tree) extends Tree
+  
+  type RList = List[(Int, Tree)]  
+  
+  val empty = Nil
+  
+  def isEmpty(ts: RList) = ts.isEmpty
+  
+  def cons(w: Int, ts: RList): RList = ts match {
+    case (w1,t1) :: (w2,t2) :: rest if (w1 == w2) => 
+      (1+w1+w2, Node(w,t1,t2)) :: rest
+      
+    case _ => 
+      (1, Leaf(w)) :: ts 
+  }
+  
+  def head(ts: RList): Int = ts match {
+    case Nil => error("head of empty list")
+    case (1, Leaf(x)) :: ts => x
+    case (_, Node(x, _, _)) :: ts => x
+  }
+  
+  def tail(ts: RList): RList = ts match {
+    case Nil => error("tail of empty list")
+    case (1, Leaf(x)) :: ts => ts
+    case (w, Node(x, t1, t2)) :: rest => 
+      (w/2, t1) :: (w/2, t2) :: rest
+  }
+  
+  def lookup(i: Int, ts: RList): Int = ts match {
+    case Nil => error("lookup of empty list")
+    case (w,t) :: ts =>
+      if (i < w) lookupTree(w,i,t)
+      else lookup(i-w, ts)
+  }
+  
+  def lookupTree(w: Int, i: Int, t: Tree): Int = (w,i,t) match {
+    case (1,0, Leaf(x)) => x
+    case tuple @ (1,_,Leaf(x)) => error("lookupTree: error for "+tuple)
+    case (_,0, Node(x,_,_)) => x
+    case (_,_,Node(x,t1,t2)) =>
+      if (i < w/2) lookupTree(w/2,i-1,t1)
+      else lookupTree(w/2,i-1-w/2,t2)
+  }
+  
+  def updateTree(w: Int, i: Int, y: Int, t: Tree): Tree = (w,i,y,t) match {
+    case (1,0,_,Leaf(x)) => Leaf(y)
+    case tuple @ (1,_,_,Leaf(x)) => error("updateTree: Error for "+tuple)
+    case (_,0,_,Node(x,t1,t2)) => Node(y,t1,t2)
+    case (_,_,_,Node(x,t1,t2)) => 
+      if (i <= w/2) Node(x,updateTree(w/2,i-1,y,t1),t2)
+      else Node(x,t1, updateTree(w/2,i-1-w/2,y,t2))
+  } 
+ 
+  
+  def update(i: Int, y: Int, ts: RList): RList = ts match {
+    case Nil => error("update of empty list")
+    case (w,t) :: ts =>
+      if (i < w) (w, updateTree(w,i,y,t)) :: ts
+      else (w,t) :: update(i-w,y,ts)
+  }
+  
+  def incTreeList(ws:List[Int]):List[Int] = ws match {
+    case w1::w2::rest => {
+      if (w1 == w2) (1+w1+w2)::rest;
+      else 1 :: ws;
+    }
+    case _ => 1 :: ws;
+  }
+  
+  def makeSizeList(size:Int):List[Int] = {
+    var list:List[Int] = Nil;
+    for(i <- 0 until size) {
+      list = incTreeList(list);
+    }
+    return list;
+  }
+  
+  def generateSkewBinaryList(maxSize:Int): RList = {
+    val size = Verify.getInt(1, maxSize);
+    val sizeList = makeSizeList(size);
+    val rl = generateAllTrees(sizeList);
+    System.out.println(rl);
+    return rl;
+  }
+  
+  def generateAllTrees(sizeList:List[Int]):RList = sizeList match {
+    case hd::rest =>  List((hd, generateTree(hd))):::generateAllTrees(rest);
+    case Nil => Nil;
+  }
+    
+  private def generateTree(size:Int): Tree = {
+    val maxNodeValue = size - 1;
+    val t = getSubTree(size, 0, 0);//should go up to maxNodeValue
+    //System.out.println(t);
+    return t;
+  }
+  
+  private def getSubTree(size:Int, min:Int, max:Int): Tree = {
+    if (size == 1) return Leaf(Verify.getInt(min,max));
+    val value = Verify.getInt(min,max);
+    val subtreeSize = (size-1) / 2;
+    return Node(value, getSubTree(subtreeSize, min, max), getSubTree(subtreeSize, min, max));
+  }
+
+  def content(t : RList): Multiset[Int] = {
+    def inner(t: Tree, mset: Multiset[Int]): Multiset[Int] = t match {
+      case Leaf(value) => mset +++ List(value);
+      case Node(value, left, right) => inner(right,inner(left, mset +++ List(value)));
+    }
+    def innerList(ts: RList, mset:Multiset[Int]): Multiset[Int] = ts match {
+      case Nil => mset
+      case (w,t)::tss => inner(t, innerList(tss,mset))
+    }   
+    innerList(t,Multiset.empty[Int]);
+  }
+  
+    
+  //generateSkewBinaryList(4);
+  
+  def forAll(property : ((RList,Int) => Boolean)){
+    assert(property(generateSkewBinaryList(4), 4));//Verify.getInt(0,4)));
+  }
+
+  forAll((skew, value) => (content(cons(value,skew)) == content(skew) +++ List(value)));
+
+}
diff --git a/tests/udita/SplayHeapTest.scala b/tests/udita/SplayHeapTest.scala
new file mode 100644
index 000000000..ea31f659d
--- /dev/null
+++ b/tests/udita/SplayHeapTest.scala
@@ -0,0 +1,148 @@
+package udita
+
+import gov.nasa.jpf.jvm.Verify;
+
+object SplayHeapTest extends Application {
+  sealed abstract class Heap
+  case class E() extends Heap
+  case class T(x: Int, a: Heap, b: Heap) extends Heap
+  
+  def isEmpty(h: Heap): Boolean = h.isInstanceOf[E]
+  
+  def partition(pivot: Int, t: Heap): (Heap,Heap) = t match {
+    case E() => (E(),E())
+    case T(x,a,b) =>
+      if(x <= pivot) b match {
+        case E() => (T(x,a,E()),E())
+        case T(y,b1,b2) =>
+          if(y <= pivot) {
+            val (small,big) = partition(pivot,b2)
+            val r1 = T(y,T(x,a,b1),small)
+            val r2 = big
+            (r1,r2)
+          } else  {
+            val (small,big) = partition(pivot,b1)
+            val r1 = T(x, a, small)
+            val r2 = T(y, big, b2)
+            (r1,r2)
+          }
+      } else a match {
+        case E() => (E(), T(x,E(),b))
+        case T(y,a1,a2) =>
+          if(y <= pivot) {
+            val (small,big) = partition(pivot,a2)
+            val r1 = T(y,a1,small)
+            val r2 = T(x,big,b)
+            (r1,r2)
+          } else {
+            val (small,big) = partition(pivot,a1)
+            val r1 = small
+            val r2 = T(y,big,T(x,a2,b))
+            (r1,r2)
+          }
+      }
+  }
+  
+  def insert(x: Int, t: Heap): Heap = {
+    val (a,b) = partition(x,t)
+    T(x,a,b)
+  }
+  
+  def merge(t1: Heap, t2: Heap): Heap = t1 match {
+    case E() => t2
+    case T(x,a,b) =>
+      val (ta,tb) = partition(x,t2)
+      val a1 = merge(ta,a)
+      val b1 = merge(tb,b)
+      T(x,a1,b1)
+  }
+  
+  def deleteMin(t: Heap): Heap = t match {
+    case E() => error("empty")
+    case T(x,E(),b) => b
+    case T(y,T(x,E(),b),c) => T(y,b,c)
+    case T(y,T(x,a,b),c) => T(x,deleteMin(a),T(y,b,c))  
+  }
+  
+  def deleteMin2(t: Heap): (Int,Heap) = t match {  
+    case E() => error("empty")
+    case T(x,E(),b) => (x, b)
+    case T(y,T(x,E(),b),c) => (x,T(y,b,c))
+    case T(y,T(x,a,b),c) =>
+      val (r, a1) = deleteMin2(a)
+      (r,T(x,a1,T(y,b,c)))
+  }
+  
+  def findMin(t: Heap): Int = t match { 
+    case E() => error("empty")
+    case T(x,E(),b) => x
+    case T(x,a,b) => findMin(a)
+  }
+  
+  def findMin2(t: Heap): (Int,Heap) = t match {
+    case E() => error("empty")
+    case T(x,E(),b) => (x, t)
+    case T(x,a,b) =>
+      val (x1, a1) = findMin2(a)
+      (x1,T(x,a1,b))
+  }
+  
+  def app(x: Int, ys: List[Int],  zs: List[Int]): List[Int] = ys match {
+    case Nil => x :: zs
+    case y :: ys => y :: app(x,ys,zs)
+  }
+  
+
+  def to_list(t: Heap): List[Int] = t match { 
+    case E() => Nil
+    case T(x,a,b) => app(x,to_list(a),to_list(b))
+  }
+
+  def check_sorted(xs: List[Int]): Boolean = xs match {
+    case Nil => true
+    case x :: xs =>
+      xs.forall(x <= _) && check_sorted(xs)
+  }
+
+  def to_list2(t: Heap): List[Int] = { 
+    val xs = to_list(t)
+    check_sorted(xs)
+    xs
+  }
+  
+  def generateSplayHeap(treeSize:Int): Heap = {
+    return generateBinarySearchTree(treeSize);
+  }
+  
+  private def generateBinarySearchTree(treeSize:Int): Heap = {
+    val size = Verify.getInt(1, treeSize);
+    val maxNodeValue = size - 1;
+    val t = getSubTree(size, 0, maxNodeValue);
+    return t;
+  }
+  
+  private def getSubTree(size:Int, min:Int, max:Int): Heap = {
+    if (size == 0) return E();
+    if (size == 1) return T(Verify.getInt(min,max), E(), E());
+
+    val value = Verify.getInt(min,max);
+
+    val leftSize = value - min;
+    val rightSize = size - 1 - leftSize;
+
+    return T(value, getSubTree(leftSize, min, value - 1), getSubTree(rightSize, value + 1, max));
+  }
+  
+  def content(t:Heap):Set[Int] = t match {
+    case E() => Set.empty;
+    case T(value,left,right) => (content(left) ++ Set(value) ++ content(right));
+  }
+  
+  def forAll(property: (Heap) => Boolean){     
+    val t = generateSplayHeap(4);
+    assert(property(t));
+    System.out.println(t);
+  }
+  
+  forAll{h: Heap => check_sorted(to_list(h))}
+}
-- 
GitLab