From b1408d30baf31afb4e4b2d434511801c3de412d8 Mon Sep 17 00:00:00 2001
From: "Emmanouil (Manos) Koukoutos" <emmanouil.koukoutos@epfl.ch>
Date: Sun, 2 Nov 2014 20:09:41 +0100
Subject: [PATCH] Repair benchmarks

---
 .../synthesis/repair/HeapSort/HeapSort.scala  |  86 +++++++++++
 .../synthesis/repair/HeapSort/HeapSort1.scala |  86 +++++++++++
 .../synthesis/repair/HeapSort/HeapSort2.scala |  87 +++++++++++
 .../synthesis/repair/HeapSort/HeapSort5.scala |  86 +++++++++++
 .../repair/PropLogic/PropLogic.scala          |  66 ++++++++
 .../repair/PropLogic/PropLogic1.scala         |  66 ++++++++
 .../repair/PropLogic/PropLogic3.scala         |  66 ++++++++
 .../repair/PropLogic/PropLogic4.scala         |  67 ++++++++
 .../repair/PropLogic/PropLogic5.scala         |  66 ++++++++
 .../repair/PropLogic/PropLogic6.scala         |  68 +++++++++
 .../repair/RedBlackTree/RedBlackTree.scala    | 143 +++++++++++++++++
 .../repair/RedBlackTree/RedBlackTree1.scala   | 143 +++++++++++++++++
 .../repair/RedBlackTree/RedBlackTree2.scala   | 143 +++++++++++++++++
 .../repair/RedBlackTree/RedBlackTree3.scala   | 144 ++++++++++++++++++
 .../repair/RedBlackTree/RedBlackTree5.scala   | 144 ++++++++++++++++++
 .../repair/RedBlackTree/RedBlackTree6.scala   | 144 ++++++++++++++++++
 .../repair/RedBlackTree/RedBlackTree7.scala   | 143 +++++++++++++++++
 .../repair/SecondsToTime/SecondsToTime.scala  |  38 +++++
 .../repair/SecondsToTime/SecondsToTime1.scala |  38 +++++
 .../repair/SecondsToTime/SecondsToTime2.scala |  38 +++++
 .../repair/SecondsToTime/SecondsToTime3.scala |  38 +++++
 .../repair/SecondsToTime/SecondsToTime4.scala |  38 +++++
 .../SecondsToTime/SecondsToTimeMod.scala      |  22 +++
 .../SecondsToTime/SecondsToTimeMod1.scala     |  22 +++
 .../SecondsToTime/SecondsToTimeMod2.scala     |  22 +++
 .../repair/SortedList/SortedList.scala        |  51 +++++++
 .../repair/SortedList/SortedList1.scala       |  51 +++++++
 .../repair/SortedList/SortedList2.scala       |  51 +++++++
 .../repair/SortedList/SortedList3.scala       |  51 +++++++
 .../repair/SortedList/SortedList4.scala       |  52 +++++++
 .../repair/SortedList/SortedList5.scala       |  51 +++++++
 .../repair/SortedList/SortedList6.scala       |  51 +++++++
 .../repair/SortedList/SortedList7.scala       |  52 +++++++
 33 files changed, 2414 insertions(+)
 create mode 100644 testcases/synthesis/repair/HeapSort/HeapSort.scala
 create mode 100644 testcases/synthesis/repair/HeapSort/HeapSort1.scala
 create mode 100644 testcases/synthesis/repair/HeapSort/HeapSort2.scala
 create mode 100644 testcases/synthesis/repair/HeapSort/HeapSort5.scala
 create mode 100644 testcases/synthesis/repair/PropLogic/PropLogic.scala
 create mode 100644 testcases/synthesis/repair/PropLogic/PropLogic1.scala
 create mode 100644 testcases/synthesis/repair/PropLogic/PropLogic3.scala
 create mode 100644 testcases/synthesis/repair/PropLogic/PropLogic4.scala
 create mode 100644 testcases/synthesis/repair/PropLogic/PropLogic5.scala
 create mode 100644 testcases/synthesis/repair/PropLogic/PropLogic6.scala
 create mode 100644 testcases/synthesis/repair/RedBlackTree/RedBlackTree.scala
 create mode 100644 testcases/synthesis/repair/RedBlackTree/RedBlackTree1.scala
 create mode 100644 testcases/synthesis/repair/RedBlackTree/RedBlackTree2.scala
 create mode 100644 testcases/synthesis/repair/RedBlackTree/RedBlackTree3.scala
 create mode 100644 testcases/synthesis/repair/RedBlackTree/RedBlackTree5.scala
 create mode 100644 testcases/synthesis/repair/RedBlackTree/RedBlackTree6.scala
 create mode 100644 testcases/synthesis/repair/RedBlackTree/RedBlackTree7.scala
 create mode 100644 testcases/synthesis/repair/SecondsToTime/SecondsToTime.scala
 create mode 100644 testcases/synthesis/repair/SecondsToTime/SecondsToTime1.scala
 create mode 100644 testcases/synthesis/repair/SecondsToTime/SecondsToTime2.scala
 create mode 100644 testcases/synthesis/repair/SecondsToTime/SecondsToTime3.scala
 create mode 100644 testcases/synthesis/repair/SecondsToTime/SecondsToTime4.scala
 create mode 100644 testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod.scala
 create mode 100644 testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod1.scala
 create mode 100644 testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod2.scala
 create mode 100644 testcases/synthesis/repair/SortedList/SortedList.scala
 create mode 100644 testcases/synthesis/repair/SortedList/SortedList1.scala
 create mode 100644 testcases/synthesis/repair/SortedList/SortedList2.scala
 create mode 100644 testcases/synthesis/repair/SortedList/SortedList3.scala
 create mode 100644 testcases/synthesis/repair/SortedList/SortedList4.scala
 create mode 100644 testcases/synthesis/repair/SortedList/SortedList5.scala
 create mode 100644 testcases/synthesis/repair/SortedList/SortedList6.scala
 create mode 100644 testcases/synthesis/repair/SortedList/SortedList7.scala

diff --git a/testcases/synthesis/repair/HeapSort/HeapSort.scala b/testcases/synthesis/repair/HeapSort/HeapSort.scala
new file mode 100644
index 000000000..8cd6b51fa
--- /dev/null
+++ b/testcases/synthesis/repair/HeapSort/HeapSort.scala
@@ -0,0 +1,86 @@
+/* Copyright 2009-2013 EPFL, Lausanne
+ *
+ * Author: Ravi
+ * Date: 20.11.2013
+ **/
+
+import leon.collection._
+import leon._ 
+
+object HeapSort {
+ 
+  sealed abstract class Heap {
+    val rank : Int = this match {
+      case Leaf() => 0
+      case Node(_, l, r) => 
+        1 + max(l.rank, r.rank)
+    }
+  }
+  case class Leaf() extends Heap
+  case class Node(value:Int, left: Heap, right: Heap) extends Heap
+
+  def max(i1 : Int, i2 : Int) = if (i1 >= i2) i1 else i2
+
+  def hasLeftistProperty(h: Heap) : Boolean = h match {
+    case Leaf() => true
+    case Node(_,l,r) => 
+      hasLeftistProperty(l) && 
+      hasLeftistProperty(r) && 
+      l.rank >= r.rank 
+  }
+
+  def heapSize(t: Heap): Int = { t match {
+    case Leaf() => 0
+    case Node(v, l, r) => heapSize(l) + 1 + heapSize(r)
+  }} ensuring(_ >= 0)
+
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    (h1,h2) match {
+      case (Leaf(), _) => h2
+      case (_, Leaf()) => h1
+      case (Node(v1, l1, r1), Node(v2, l2, r2)) =>
+        if(v1 > v2)
+          makeN(v1, l1, merge(r1, h2))
+        else
+          makeN(v2, l2, merge(h1, r2))
+    }
+  } ensuring { res => 
+    hasLeftistProperty(res) && 
+    heapSize(h1) + heapSize(h2) == heapSize(res)
+  }
+
+  private def makeN(value: Int, left: Heap, right: Heap) : Heap = {
+    require(hasLeftistProperty(left) && hasLeftistProperty(right))
+    if(left.rank >= right.rank)
+      Node(value, left, right)
+    else
+      Node(value, right, left)
+  } ensuring { hasLeftistProperty(_) }
+
+  def insert(element: Int, heap: Heap) : Heap = {
+    require(hasLeftistProperty(heap))
+
+    merge(Node(element, Leaf(), Leaf()), heap)
+
+  } ensuring { res =>
+    hasLeftistProperty(res) && 
+    heapSize(res) == heapSize(heap) + 1
+  }
+
+  def findMax(h: Heap) : Option[Int] = {
+    h match {
+      case Node(m,_,_) => Some(m)
+      case Leaf() => None()
+    }
+  }
+
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,l,r) => merge(l, r)
+      case l => l
+    }
+  }
+
+} 
diff --git a/testcases/synthesis/repair/HeapSort/HeapSort1.scala b/testcases/synthesis/repair/HeapSort/HeapSort1.scala
new file mode 100644
index 000000000..c9976e2dd
--- /dev/null
+++ b/testcases/synthesis/repair/HeapSort/HeapSort1.scala
@@ -0,0 +1,86 @@
+/* Copyright 2009-2013 EPFL, Lausanne
+ *
+ * Author: Ravi
+ * Date: 20.11.2013
+ **/
+
+import leon.collection._
+import leon._ 
+
+object HeapSort {
+ 
+  sealed abstract class Heap {
+    val rank : Int = this match {
+      case Leaf() => 0
+      case Node(_, l, r) => 
+        1 + max(l.rank, r.rank)
+    }
+  }
+  case class Leaf() extends Heap
+  case class Node(value:Int, left: Heap, right: Heap) extends Heap
+
+  def max(i1 : Int, i2 : Int) = if (i1 >= i2) i1 else i2
+
+  def hasLeftistProperty(h: Heap) : Boolean = h match {
+    case Leaf() => true
+    case Node(_,l,r) => 
+      hasLeftistProperty(l) && 
+      hasLeftistProperty(r) && 
+      l.rank >= r.rank 
+  }
+
+  def heapSize(t: Heap): Int = { t match {
+    case Leaf() => 0
+    case Node(v, l, r) => heapSize(l) + 1 + heapSize(r)
+  }} ensuring(_ >= 0)
+
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    (h1,h2) match {
+      case (Leaf(), _) => h2
+      case (_, Leaf()) => h1
+      case (Node(v1, l1, r1), Node(v2, l2, r2)) =>
+        if(v1 > v2)
+          makeN(v1, l1, merge(r1, h2))
+        else
+          makeN(v2, r2, merge(h1, l2)) // FIXME: swap l2 and r2
+    }
+  } ensuring { res => 
+    hasLeftistProperty(res) && 
+    heapSize(h1) + heapSize(h2) == heapSize(res)
+  }
+
+  private def makeN(value: Int, left: Heap, right: Heap) : Heap = {
+    require(hasLeftistProperty(left) && hasLeftistProperty(right))
+    if(left.rank >= right.rank)
+      Node(value, left, right)
+    else
+      Node(value, right, left)
+  } ensuring { hasLeftistProperty(_) }
+
+  def insert(element: Int, heap: Heap) : Heap = {
+    require(hasLeftistProperty(heap))
+
+    merge(Node(element, Leaf(), Leaf()), heap)
+
+  } ensuring { res =>
+    hasLeftistProperty(res) && 
+    heapSize(res) == heapSize(heap) + 1
+  }
+
+  def findMax(h: Heap) : Option[Int] = {
+    h match {
+      case Node(m,_,_) => Some(m)
+      case Leaf() => None()
+    }
+  }
+
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,l,r) => merge(l, r)
+      case l => l
+    }
+  }
+
+} 
diff --git a/testcases/synthesis/repair/HeapSort/HeapSort2.scala b/testcases/synthesis/repair/HeapSort/HeapSort2.scala
new file mode 100644
index 000000000..c33921bee
--- /dev/null
+++ b/testcases/synthesis/repair/HeapSort/HeapSort2.scala
@@ -0,0 +1,87 @@
+/* Copyright 2009-2013 EPFL, Lausanne
+ *
+ * Author: Ravi
+ * Date: 20.11.2013
+ **/
+
+import leon.collection._
+import leon._ 
+
+object HeapSort {
+ 
+  sealed abstract class Heap {
+    val rank : Int = this match {
+      case Leaf() => 0
+      case Node(_, l, r) => 
+        1 + max(l.rank, r.rank)
+    }
+  }
+  case class Leaf() extends Heap
+  case class Node(value:Int, left: Heap, right: Heap) extends Heap
+
+  def max(i1 : Int, i2 : Int) = if (i1 >= i2) i1 else i2
+
+  def hasLeftistProperty(h: Heap) : Boolean = h match {
+    case Leaf() => true
+    case Node(_,l,r) => 
+      hasLeftistProperty(l) && 
+      hasLeftistProperty(r) && 
+      l.rank >= r.rank 
+  }
+
+  def heapSize(t: Heap): Int = { t match {
+    case Leaf() => 0
+    case Node(v, l, r) => heapSize(l) + 1 + heapSize(r)
+  }} ensuring(_ >= 0)
+
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    (h1,h2) match {
+      case (Leaf(), _) => h2
+      case (_, Leaf()) => h1
+      case (Node(v1, l1, r1), Node(v2, l2, r2)) =>
+        if(v1 > v2)
+          Node(v1, l1, merge(r1, h2)) // FIXME: Forgot to put the heap of lowest rank on the left 
+                                      //        (failed to use makeN)
+        else
+          Node(v2, l2, merge(h1, r2)) // FIXME: Same as above
+    }
+  } ensuring { res => 
+    hasLeftistProperty(res) && 
+    heapSize(h1) + heapSize(h2) == heapSize(res)
+  }
+/*
+  private def makeN(value: Int, left: Heap, right: Heap) : Heap = {
+    require(hasLeftistProperty(left) && hasLeftistProperty(right))
+    if(left.rank >= right.rank)
+      Node(value, left, right)
+    else
+      Node(value, right, left)
+  } ensuring { hasLeftistProperty(_) }
+*/
+  def insert(element: Int, heap: Heap) : Heap = {
+    require(hasLeftistProperty(heap))
+
+    merge(Node(element, Leaf(), Leaf()), heap)
+
+  } ensuring { res =>
+    hasLeftistProperty(res) && 
+    heapSize(res) == heapSize(heap) + 1
+  }
+
+  def findMax(h: Heap) : Option[Int] = {
+    h match {
+      case Node(m,_,_) => Some(m)
+      case Leaf() => None()
+    }
+  }
+
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,l,r) => merge(l, r)
+      case l => l
+    }
+  }
+
+} 
diff --git a/testcases/synthesis/repair/HeapSort/HeapSort5.scala b/testcases/synthesis/repair/HeapSort/HeapSort5.scala
new file mode 100644
index 000000000..e601a6225
--- /dev/null
+++ b/testcases/synthesis/repair/HeapSort/HeapSort5.scala
@@ -0,0 +1,86 @@
+/* Copyright 2009-2013 EPFL, Lausanne
+ *
+ * Author: Ravi
+ * Date: 20.11.2013
+ **/
+
+import leon.collection._
+import leon._ 
+
+object HeapSort {
+ 
+  sealed abstract class Heap {
+    val rank : Int = this match {
+      case Leaf() => 0
+      case Node(_, l, r) => 
+        1 + max(l.rank, r.rank)
+    }
+  }
+  case class Leaf() extends Heap
+  case class Node(value:Int, left: Heap, right: Heap) extends Heap
+
+  def max(i1 : Int, i2 : Int) = if (i1 >= i2) i1 else i2
+
+  def hasLeftistProperty(h: Heap) : Boolean = h match {
+    case Leaf() => true
+    case Node(_,l,r) => 
+      hasLeftistProperty(l) && 
+      hasLeftistProperty(r) && 
+      l.rank >= r.rank 
+  }
+
+  def heapSize(t: Heap): Int = { t match {
+    case Leaf() => 0
+    case Node(v, l, r) => heapSize(l) + 1 + heapSize(r)
+  }} ensuring(_ >= 0)
+
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    (h1,h2) match {
+      case (Leaf(), _) => h2
+      case (_, Leaf()) => h2 // FIXME: h2 instead of h1
+      case (Node(v1, l1, r1), Node(v2, l2, r2)) =>
+        if(v1 > v2)
+          makeN(v1, l1, merge(r1, h2))
+        else
+          makeN(v2, l2, merge(h1, r2))
+    }
+  } ensuring { res => 
+    hasLeftistProperty(res) && 
+    heapSize(h1) + heapSize(h2) == heapSize(res)
+  }
+
+  private def makeN(value: Int, left: Heap, right: Heap) : Heap = {
+    require(hasLeftistProperty(left) && hasLeftistProperty(right))
+    if(left.rank >= right.rank)
+      Node(value, left, right)
+    else
+      Node(value, right, left)
+  } ensuring { hasLeftistProperty(_) }
+
+  def insert(element: Int, heap: Heap) : Heap = {
+    require(hasLeftistProperty(heap))
+
+    merge(Node(element, Leaf(), Leaf()), heap)
+
+  } ensuring { res =>
+    hasLeftistProperty(res) && 
+    heapSize(res) == heapSize(heap) + 1
+  }
+
+  def findMax(h: Heap) : Option[Int] = {
+    h match {
+      case Node(m,_,_) => Some(m)
+      case Leaf() => None()
+    }
+  }
+
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,l,r) => merge(l, r)
+      case l => l
+    }
+  }
+
+} 
diff --git a/testcases/synthesis/repair/PropLogic/PropLogic.scala b/testcases/synthesis/repair/PropLogic/PropLogic.scala
new file mode 100644
index 000000000..c33b0500e
--- /dev/null
+++ b/testcases/synthesis/repair/PropLogic/PropLogic.scala
@@ -0,0 +1,66 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+
+object SemanticsPreservation { 
+
+  sealed abstract class Formula
+  case class And(lhs : Formula, rhs : Formula) extends Formula
+  case class Or(lhs : Formula, rhs : Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Const(v: Boolean) extends Formula
+  case class Literal(id: Int) extends Formula
+
+  def size(f : Formula) : Int = { f match {
+    case And(l,r) => 1 + size(l) + size(r)
+    case Or(l,r) =>  1 + size(l) + size(r)
+    case Not(e) => 1 + size(e)
+    case _ => 1
+  }} ensuring { _ >= 0 }
+
+  def eval(formula: Formula)(implicit trueVars : Set[Int]): Boolean = formula match {
+    case And(lhs, rhs) => eval(lhs) && eval(rhs)
+    case Or(lhs, rhs)  => eval(lhs) || eval(rhs)
+    case Not(f) => !eval(f)
+    case Const(v) => v
+    case Literal(id) => trueVars contains id
+  }
+
+  def nnf(formula : Formula) : Formula = { formula match {
+    case Not(And(lhs,rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs,rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Const(v)) => Const(!v)
+    case Not(Not(e)) => nnf(e)
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs)  => Or(nnf(lhs), nnf(rhs))
+    case other => other 
+  }} ensuring { isNNF(_) }
+
+  def isNNF(f : Formula) : Boolean = f match {
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case _ => true
+  }
+
+  def partEval(formula : Formula) : Formula = { formula match {
+    case And(Const(false), _ ) => Const(false)
+    case And(_, Const(false)) => Const(false)
+    case And(Const(true), e) => partEval(e)
+    case And(e, Const(true)) => partEval(e)
+    case Or(Const(true), _ ) => Const(true)
+    case Or(_, Const(true)) => Const(true)
+    case Or(Const(false), e) => partEval(e)
+    case Or(e, Const(false)) => partEval(e)
+    case Not(Const(c)) => Const(!c)
+    case other => other
+  }} ensuring { size(_) <= size(formula) }
+
+  
+  @induct
+  def partEvalSound (f : Formula, env : Set[Int]) = {
+    eval(partEval(f))(env) == eval(f)(env)
+  }.holds
+  
+}
diff --git a/testcases/synthesis/repair/PropLogic/PropLogic1.scala b/testcases/synthesis/repair/PropLogic/PropLogic1.scala
new file mode 100644
index 000000000..9668ca1a1
--- /dev/null
+++ b/testcases/synthesis/repair/PropLogic/PropLogic1.scala
@@ -0,0 +1,66 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+
+object SemanticsPreservation { 
+
+  sealed abstract class Formula
+  case class And(lhs : Formula, rhs : Formula) extends Formula
+  case class Or(lhs : Formula, rhs : Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Const(v: Boolean) extends Formula
+  case class Literal(id: Int) extends Formula
+
+  def size(f : Formula) : Int = { f match {
+    case And(l,r) => 1 + size(l) + size(r)
+    case Or(l,r) =>  1 + size(l) + size(r)
+    case Not(e) => 1 + size(e)
+    case _ => 1
+  }} ensuring { _ >= 0 }
+
+  def eval(formula: Formula)(implicit trueVars : Set[Int]): Boolean = formula match {
+    case And(lhs, rhs) => eval(lhs) && eval(rhs)
+    case Or(lhs, rhs)  => eval(lhs) || eval(rhs)
+    case Not(f) => !eval(f)
+    case Const(v) => v
+    case Literal(id) => trueVars contains id
+  }
+
+  def nnf(formula : Formula) : Formula = { formula match {
+    case Not(And(lhs,rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs,rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Const(v)) => Const(!v)
+    case Not(Not(e)) => e // FIXME: should be nnf(e)
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs)  => Or(nnf(lhs), nnf(rhs))
+    case other => other 
+  }} ensuring { isNNF(_) }
+
+  def isNNF(f : Formula) : Boolean = f match {
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case _ => true
+  }
+
+  def partEval(formula : Formula) : Formula = { formula match {
+    case And(Const(false), _ ) => Const(false)
+    case And(_, Const(false)) => Const(false)
+    case And(Const(true), e) => partEval(e)
+    case And(e, Const(true)) => partEval(e)
+    case Or(Const(true), _ ) => Const(true)
+    case Or(_, Const(true)) => Const(true)
+    case Or(Const(false), e) => partEval(e)
+    case Or(e, Const(false)) => partEval(e)
+    case Not(Const(c)) => Const(!c)
+    case other => other
+  }} ensuring { size(_) <= size(formula) }
+
+  
+  @induct
+  def partEvalSound (f : Formula, env : Set[Int]) = {
+    eval(partEval(f))(env) == eval(f)(env)
+  }.holds
+  
+}
diff --git a/testcases/synthesis/repair/PropLogic/PropLogic3.scala b/testcases/synthesis/repair/PropLogic/PropLogic3.scala
new file mode 100644
index 000000000..b905ed40f
--- /dev/null
+++ b/testcases/synthesis/repair/PropLogic/PropLogic3.scala
@@ -0,0 +1,66 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+
+object SemanticsPreservation { 
+
+  sealed abstract class Formula
+  case class And(lhs : Formula, rhs : Formula) extends Formula
+  case class Or(lhs : Formula, rhs : Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Const(v: Boolean) extends Formula
+  case class Literal(id: Int) extends Formula
+
+  def size(f : Formula) : Int = { f match {
+    case And(l,r) => 1 + size(l) + size(r)
+    case Or(l,r) =>  1 + size(l) + size(r)
+    case Not(e) => 1 + size(e)
+    case _ => 1
+  }} ensuring { _ >= 0 }
+
+  def eval(formula: Formula)(implicit trueVars : Set[Int]): Boolean = formula match {
+    case And(lhs, rhs) => eval(lhs) && eval(rhs)
+    case Or(lhs, rhs)  => eval(lhs) || eval(rhs)
+    case Not(f) => !eval(f)
+    case Const(v) => v
+    case Literal(id) => trueVars contains id
+  }
+
+  def nnf(formula : Formula) : Formula = { formula match {
+    case Not(And(lhs,rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs,rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Const(v)) => Const(!v)
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs)  => Or(nnf(lhs), nnf(rhs))
+    // FIXME: forgot to handle the Not(Not(_)) case 
+    case other => other 
+  }} ensuring { isNNF(_) }
+
+  def isNNF(f : Formula) : Boolean = f match {
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case _ => true
+  }
+
+  def partEval(formula : Formula) : Formula = { formula match {
+    case And(Const(false), _ ) => Const(false)
+    case And(_, Const(false)) => Const(false)
+    case And(Const(true), e) => partEval(e)
+    case And(e, Const(true)) => partEval(e)
+    case Or(Const(true), _ ) => Const(true)
+    case Or(_, Const(true)) => Const(true)
+    case Or(Const(false), e) => partEval(e)
+    case Or(e, Const(false)) => partEval(e)
+    case Not(Const(c)) => Const(!c)
+    case other => other
+  }} ensuring { size(_) <= size(formula) }
+
+  
+  @induct
+  def partEvalSound (f : Formula, env : Set[Int]) = {
+    eval(partEval(f))(env) == eval(f)(env)
+  }.holds
+  
+}
diff --git a/testcases/synthesis/repair/PropLogic/PropLogic4.scala b/testcases/synthesis/repair/PropLogic/PropLogic4.scala
new file mode 100644
index 000000000..549b91c45
--- /dev/null
+++ b/testcases/synthesis/repair/PropLogic/PropLogic4.scala
@@ -0,0 +1,67 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+
+object SemanticsPreservation { 
+
+  sealed abstract class Formula
+  case class And(lhs : Formula, rhs : Formula) extends Formula
+  case class Or(lhs : Formula, rhs : Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Const(v: Boolean) extends Formula
+  case class Literal(id: Int) extends Formula
+
+  def size(f : Formula) : Int = { f match {
+    case And(l,r) => 1 + size(l) + size(r)
+    case Or(l,r) =>  1 + size(l) + size(r)
+    case Not(e) => 1 + size(e)
+    case _ => 1
+  }} ensuring { _ >= 0 }
+
+  def eval(formula: Formula)(implicit trueVars : Set[Int]): Boolean = formula match {
+    case And(lhs, rhs) => eval(lhs) && eval(rhs)
+    case Or(lhs, rhs)  => eval(lhs) || eval(rhs)
+    case Not(f) => !eval(f)
+    case Const(v) => v
+    case Literal(id) => trueVars contains id
+  }
+
+  def nnf(formula : Formula) : Formula = { formula match {
+    case Not(And(lhs,rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs,rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Const(v)) => Const(!v)
+    case Not(Not(e)) => nnf(e)
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs)  => Or(nnf(lhs), nnf(rhs))
+    case other => other 
+  }} ensuring { isNNF(_) }
+
+  def isNNF(f : Formula) : Boolean = f match {
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case _ => true
+  }
+
+  def partEval(formula : Formula) : Formula = { formula match {
+    case And(Const(false), _ ) => Const(false)
+    case And(_, Const(false)) => Const(false)
+    case And(Const(true), e) => partEval(e)
+    case And(e, Const(true)) => partEval(e)
+    // FIXME (hard!) : treats Or as And
+    case Or(Const(false), _ ) => Const(false)
+    case Or(_, Const(false)) => Const(false)
+    case Or(Const(true), e) => partEval(e)
+    case Or(e, Const(true)) => partEval(e)
+    case Not(Const(c)) => Const(!c)
+    case other => other
+  }} ensuring { size(_) <= size(formula) }
+
+  
+  @induct
+  def partEvalSound (f : Formula, env : Set[Int]) = {
+    eval(partEval(f))(env) == eval(f)(env)
+  }.holds
+  
+}
diff --git a/testcases/synthesis/repair/PropLogic/PropLogic5.scala b/testcases/synthesis/repair/PropLogic/PropLogic5.scala
new file mode 100644
index 000000000..4b8a2149a
--- /dev/null
+++ b/testcases/synthesis/repair/PropLogic/PropLogic5.scala
@@ -0,0 +1,66 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+
+object SemanticsPreservation { 
+
+  sealed abstract class Formula
+  case class And(lhs : Formula, rhs : Formula) extends Formula
+  case class Or(lhs : Formula, rhs : Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Const(v: Boolean) extends Formula
+  case class Literal(id: Int) extends Formula
+
+  def size(f : Formula) : Int = { f match {
+    case And(l,r) => 1 + size(l) + size(r)
+    case Or(l,r) =>  1 + size(l) + size(r)
+    case Not(e) => 1 + size(e)
+    case _ => 1
+  }} ensuring { _ >= 0 }
+
+  def eval(formula: Formula)(implicit trueVars : Set[Int]): Boolean = formula match {
+    case And(lhs, rhs) => eval(lhs) && eval(rhs)
+    case Or(lhs, rhs)  => eval(lhs) || eval(rhs)
+    case Not(f) => !eval(f)
+    case Const(v) => v
+    case Literal(id) => trueVars contains id
+  }
+
+  def nnf(formula : Formula) : Formula = { formula match {
+    case Not(And(lhs,rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs,rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Const(v)) => Const(!v)
+    case Not(Not(e)) => nnf(e)
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs)  => Or(nnf(lhs), nnf(rhs))
+    case other => other 
+  }} ensuring { isNNF(_) }
+
+  def isNNF(f : Formula) : Boolean = f match {
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case _ => true
+  }
+
+  def partEval(formula : Formula) : Formula = { formula match {
+    case And(Const(false), _ ) => Const(false)
+    case And(_, Const(false)) => Const(false)
+    case And(Const(true), e) => partEval(e)
+    case And(e, Const(true)) => partEval(e)
+    case Or(Const(true), _ ) => Const(true)
+    case Or(_, Const(true)) => Const(true)
+    case Or(Const(false), e) => partEval(e)
+    case Or(e, Const(false)) => partEval(e)
+    case Not(Const(c)) => Const(c) // FIXME should be !c
+    case other => other
+  }} ensuring { size(_) <= size(formula) }
+
+  
+  @induct
+  def partEvalSound (f : Formula, env : Set[Int]) = {
+    eval(partEval(f))(env) == eval(f)(env)
+  }.holds
+  
+}
diff --git a/testcases/synthesis/repair/PropLogic/PropLogic6.scala b/testcases/synthesis/repair/PropLogic/PropLogic6.scala
new file mode 100644
index 000000000..12791f753
--- /dev/null
+++ b/testcases/synthesis/repair/PropLogic/PropLogic6.scala
@@ -0,0 +1,68 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+
+object SemanticsPreservation { 
+
+  sealed abstract class Formula
+  case class And(lhs : Formula, rhs : Formula) extends Formula
+  case class Or(lhs : Formula, rhs : Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Const(v: Boolean) extends Formula
+  case class Literal(id: Int) extends Formula
+
+  def size(f : Formula) : Int = { f match {
+    case And(l,r) => 1 + size(l) + size(r)
+    case Or(l,r) =>  1 + size(l) + size(r)
+    case Not(e) => 1 + size(e)
+    case _ => 1
+  }} ensuring { _ >= 0 }
+
+  def eval(formula: Formula)(implicit trueVars : Set[Int]): Boolean = formula match {
+    case And(lhs, rhs) => eval(lhs) && eval(rhs)
+    case Or(lhs, rhs)  => eval(lhs) || eval(rhs)
+    case Not(f) => !eval(f)
+    case Const(v) => v
+    case Literal(id) => trueVars contains id
+  }
+
+  def nnf(formula : Formula) : Formula = { formula match {
+    case Not(And(lhs,rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs,rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Const(v)) => Const(!v)
+    case Not(Not(e)) => nnf(e)
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs)  => Or(nnf(lhs), nnf(rhs))
+    case other => other 
+  }} ensuring { isNNF(_) }
+
+  def isNNF(f : Formula) : Boolean = f match {
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case _ => true
+  }
+
+  def partEval(formula : Formula) : Formula = { formula match {
+    case And(Const(false), _ ) => Const(false)
+    case And(_, Const(false)) => Const(false)
+    case And(Const(true), e) => partEval(e)
+    case And(e, Const(true)) => partEval(e)
+    case Or(Const(true), _ ) => Const(true)
+    case Or(_, Const(true)) => Const(true)
+    case Or(Const(false), e) => partEval(e)
+    case Or(e, Const(false)) => partEval(e)
+    case Not(Const(c)) => Const(!c)
+    case other => other
+  }} ensuring { size(_) < size(formula) } 
+  // FIXME: should be <=
+  // Can you realize you cannot fix this without breaking partEvalSound? 
+
+  
+  @induct
+  def partEvalSound (f : Formula, env : Set[Int]) = {
+    eval(partEval(f))(env) == eval(f)(env)
+  }.holds
+  
+}
diff --git a/testcases/synthesis/repair/RedBlackTree/RedBlackTree.scala b/testcases/synthesis/repair/RedBlackTree/RedBlackTree.scala
new file mode 100644
index 000000000..a63a70ce7
--- /dev/null
+++ b/testcases/synthesis/repair/RedBlackTree/RedBlackTree.scala
@@ -0,0 +1,143 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+//  def buggyAdd(x: Int, t: Tree): Tree = {
+//    require(redNodesHaveBlackChildren(t))
+//    // makeBlack(ins(x, t))
+//    ins(x, t)
+//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(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 Node(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 Node(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 Node(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 Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(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 Node(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 Node(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 Node(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))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/synthesis/repair/RedBlackTree/RedBlackTree1.scala b/testcases/synthesis/repair/RedBlackTree/RedBlackTree1.scala
new file mode 100644
index 000000000..9480a1686
--- /dev/null
+++ b/testcases/synthesis/repair/RedBlackTree/RedBlackTree1.scala
@@ -0,0 +1,143 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+//  def buggyAdd(x: Int, t: Tree): Tree = {
+//    require(redNodesHaveBlackChildren(t))
+//    // makeBlack(ins(x, t))
+//    ins(x, t)
+//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(Black,Node(Red,Node(Red,a,xV,b),yV,c),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Red,c,zV,d)) // FIXME: Last Red should be Black
+      case Node(Black,Node(Red,a,xV,Node(Red,b,yV,c)),zV,d) => 
+        Node(Red,Node(Black,a,xV,b),yV,Node(Red,c,zV,d)) // FIXME: as above
+      case Node(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 Node(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 Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(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 Node(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 Node(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 Node(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))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/synthesis/repair/RedBlackTree/RedBlackTree2.scala b/testcases/synthesis/repair/RedBlackTree/RedBlackTree2.scala
new file mode 100644
index 000000000..6aa63cefd
--- /dev/null
+++ b/testcases/synthesis/repair/RedBlackTree/RedBlackTree2.scala
@@ -0,0 +1,143 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  Node(c, ins(x, a), y, b) // FIXME : forgot to balance
+        else if (x == y) Node(c,a,y,b)
+        else             Node(c,a,y,ins(x, b)) // FIXME : as above
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+//  def buggyAdd(x: Int, t: Tree): Tree = {
+//    require(redNodesHaveBlackChildren(t))
+//    // makeBlack(ins(x, t))
+//    ins(x, t)
+//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(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 Node(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 Node(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 Node(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 Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(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 Node(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 Node(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 Node(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))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/synthesis/repair/RedBlackTree/RedBlackTree3.scala b/testcases/synthesis/repair/RedBlackTree/RedBlackTree3.scala
new file mode 100644
index 000000000..1bad0be29
--- /dev/null
+++ b/testcases/synthesis/repair/RedBlackTree/RedBlackTree3.scala
@@ -0,0 +1,144 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+//  def buggyAdd(x: Int, t: Tree): Tree = {
+//    require(redNodesHaveBlackChildren(t))
+//    // makeBlack(ins(x, t))
+//    ins(x, t)
+//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(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 Node(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 Node(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 Node(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 Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
+
+  // FIXME : says buggy, so I uncommented it!
+  def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    Node(c,a,x,b) match {
+      case Node(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 Node(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 Node(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 Node(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))
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/synthesis/repair/RedBlackTree/RedBlackTree5.scala b/testcases/synthesis/repair/RedBlackTree/RedBlackTree5.scala
new file mode 100644
index 000000000..bea0f7bbc
--- /dev/null
+++ b/testcases/synthesis/repair/RedBlackTree/RedBlackTree5.scala
@@ -0,0 +1,144 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+//  def buggyAdd(x: Int, t: Tree): Tree = {
+//    require(redNodesHaveBlackChildren(t))
+//    // makeBlack(ins(x, t))
+//    ins(x, t)
+//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(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 Node(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 Node(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))
+      // FIXME: forgot this case
+      //case Node(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 Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(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 Node(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 Node(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 Node(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))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/synthesis/repair/RedBlackTree/RedBlackTree6.scala b/testcases/synthesis/repair/RedBlackTree/RedBlackTree6.scala
new file mode 100644
index 000000000..865c320ab
--- /dev/null
+++ b/testcases/synthesis/repair/RedBlackTree/RedBlackTree6.scala
@@ -0,0 +1,144 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r)
+      case _ => n
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+ 
+  // FIXME: uncommented this
+  def buggyAdd(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t))
+    // makeBlack(ins(x, t))
+    ins(x, t)
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(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 Node(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 Node(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 Node(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 Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(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 Node(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 Node(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 Node(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))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/synthesis/repair/RedBlackTree/RedBlackTree7.scala b/testcases/synthesis/repair/RedBlackTree/RedBlackTree7.scala
new file mode 100644
index 000000000..ff1284dae
--- /dev/null
+++ b/testcases/synthesis/repair/RedBlackTree/RedBlackTree7.scala
@@ -0,0 +1,143 @@
+import leon._ 
+import lang._
+import annotation._
+
+object RedBlackTree { 
+  sealed abstract class Color
+  case object Red extends Color
+  case object Black extends Color
+ 
+  sealed abstract class Tree
+  case object Empty extends Tree
+  case class Node(color: Color, left: Tree, value: Int, right: Tree) extends Tree
+
+  def content(t: Tree) : Set[Int] = t match {
+    case Empty => Set.empty
+    case Node(_, l, v, r) => content(l) ++ Set(v) ++ content(r)
+  }
+
+  def size(t: Tree) : Int = t match {
+    case Empty => 0
+    case Node(_, l, v, r) => size(l) + 1 + size(r)
+  }
+
+  /* We consider leaves to be black by definition */
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black,_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(Black, l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red, l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty => true
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case Empty => true
+  }
+
+  def blackHeight(t : Tree) : Int = t match {
+    case Empty => 1
+    case Node(Black, l, _, _) => blackHeight(l) + 1
+    case Node(Red, l, _, _) => blackHeight(l)
+  }
+ 
+    
+  // <<insert element x into the tree t>>
+  def ins(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+    t match {
+      case Empty => Node(Red,Empty,x,Empty)
+      case Node(c,a,y,b) =>
+        if      (x < y)  balance(c, ins(x, a), y, b)
+        else if (x == y) Node(c,a,y,b)
+        else             balance(c,a,y,ins(x, b))
+    }
+  } ensuring (res => 
+    content(res) == content(t) ++ Set(x) && 
+    size(t) <= size(res) && 
+    size(res) <= size(t) + 1 && 
+    redDescHaveBlackChildren(res) && 
+    blackBalanced(res) 
+  )
+
+  def makeBlack(n: Tree): Tree = {
+    require(redDescHaveBlackChildren(n) && blackBalanced(n) )
+    n match {
+      case Node(Red,l,v,r) => Node(Black,l,v,r) 
+      case Node(Black,l,v,r) => Node(Red,l,v,r) // FIXME : Red instead of Black
+    }
+  } ensuring(res => redNodesHaveBlackChildren(res) && blackBalanced(res) )
+
+  def add(x: Int, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    makeBlack(ins(x, t))
+  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res) && blackBalanced(res) )
+  
+//  def buggyAdd(x: Int, t: Tree): Tree = {
+//    require(redNodesHaveBlackChildren(t))
+//    // makeBlack(ins(x, t))
+//    ins(x, t)
+//  } ensuring (res => content(res) == content(t) ++ Set(x) && redNodesHaveBlackChildren(res))
+  
+  def balance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+    // require(
+    //   Node(c,a,x,b) match {
+    //     case Node(Black,Node(Red,Node(Red,a,_,b),_,c),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,Node(Red,a,_,Node(Red,b,_,c)),_,d) =>
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,Node(Red,b,_,c),_,d)) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case Node(Black,a,_,Node(Red,b,_,Node(Red,c,_,d))) => 
+    //       redNodesHaveBlackChildren(a) &&
+    //       redNodesHaveBlackChildren(b) &&
+    //       redNodesHaveBlackChildren(c) &&
+    //       redNodesHaveBlackChildren(d)
+    //     case t => redDescHaveBlackChildren(t)
+    //   }
+    // )
+    Node(c,a,x,b) match {
+      case Node(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 Node(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 Node(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 Node(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 Node(c,a,xV,b) => Node(c,a,xV,b)
+    }
+  } ensuring (res => content(res) == content(Node(c,a,x,b)) )// && redDescHaveBlackChildren(res))
+
+  // def buggyBalance(c: Color, a: Tree, x: Int, b: Tree): Tree = {
+  //   Node(c,a,x,b) match {
+  //     case Node(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 Node(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 Node(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 Node(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))
+  //   }
+  // } ensuring (res => content(res) == content(Node(c,a,x,b)) ) // && redDescHaveBlackChildren(res))
+
+}
diff --git a/testcases/synthesis/repair/SecondsToTime/SecondsToTime.scala b/testcases/synthesis/repair/SecondsToTime/SecondsToTime.scala
new file mode 100644
index 000000000..151b6c51a
--- /dev/null
+++ b/testcases/synthesis/repair/SecondsToTime/SecondsToTime.scala
@@ -0,0 +1,38 @@
+
+object SecondsToTime {
+
+  def toSecs(h: Int, m: Int, s: Int) = h * 3600 + m * 60 + s
+  def prop(t: Int, h: Int, m: Int, s: Int) : Boolean = 
+    toSecs(h, m, s) == t && 
+    m >= 0 && m < 60 && 
+    s >= 0 && s < 60 
+
+  def secondsToTime(total : Int) = {
+    require(total >= 0)
+    rec(total, total, 0, 0)
+  } ensuring(_ match { case (h,m,s) => prop(total, h, m, s) })
+
+  def rec(total : Int, r : Int, h : Int, m : Int) : (Int, Int, Int) = {
+    require(
+      total == toSecs(h, m, r) && 
+      m >= 0 && m < 60 && 
+      h >= 0 && r >= 0 &&
+      (m == 0 || r + m * 60 < 3600)
+    )
+
+    if(r >= 3600) {
+      rec(total, r - 3600, h + 1, m)
+    } else if(r >= 60) {
+      rec(total, r - 60, h, m + 1)
+    } else {
+      (h, m, r)
+    }
+  } ensuring { res =>
+    val (h,m,s) = res
+    prop(total, h, m, s) 
+  } 
+
+
+
+
+}
diff --git a/testcases/synthesis/repair/SecondsToTime/SecondsToTime1.scala b/testcases/synthesis/repair/SecondsToTime/SecondsToTime1.scala
new file mode 100644
index 000000000..8396cece5
--- /dev/null
+++ b/testcases/synthesis/repair/SecondsToTime/SecondsToTime1.scala
@@ -0,0 +1,38 @@
+
+object SecondsToTime {
+
+  def toSecs(h: Int, m: Int, s: Int) = h * 3600 + m * 60 + s
+  def prop(t: Int, h: Int, m: Int, s: Int) : Boolean = 
+    toSecs(h, m, s) == t && 
+    m >= 0 && m < 60 && 
+    s >= 0 && s < 60 
+
+  def secondsToTime(total : Int) = {
+    require(total >= 0)
+    rec(total, total, 0, 0)
+  } ensuring(_ match { case (h,m,s) => prop(total, h, m, s) })
+
+  def rec(total : Int, r : Int, h : Int, m : Int) : (Int, Int, Int) = {
+    require(
+      total == toSecs(h, m, r) && 
+      m >= 0 && m < 60 && 
+      h >= 0 && r >= 0 &&
+      (m == 0 || r + m * 60 < 3600)
+    )
+
+    if(r >= 3600) {
+      rec(total, r - 3600, h , m) // FIXME: Should be h+1
+    } else if(r >= 60) {
+      rec(total, r - 60, h, m + 1)
+    } else {
+      (h, m, r)
+    }
+  } ensuring { res =>
+    val (h,m,s) = res
+    prop(total, h, m, s) 
+  } 
+
+
+
+
+}
diff --git a/testcases/synthesis/repair/SecondsToTime/SecondsToTime2.scala b/testcases/synthesis/repair/SecondsToTime/SecondsToTime2.scala
new file mode 100644
index 000000000..9a9aa90fc
--- /dev/null
+++ b/testcases/synthesis/repair/SecondsToTime/SecondsToTime2.scala
@@ -0,0 +1,38 @@
+
+object SecondsToTime {
+
+  def toSecs(h: Int, m: Int, s: Int) = h * 3600 + m * 60 + s
+  def prop(t: Int, h: Int, m: Int, s: Int) : Boolean = 
+    toSecs(h, m, s) == t && 
+    m >= 0 && m < 60 && 
+    s >= 0 && s < 60 
+
+  def secondsToTime(total : Int) = {
+    require(total >= 0)
+    rec(total, total, 0, 0)
+  } ensuring(_ match { case (h,m,s) => prop(total, h, m, s) })
+
+  def rec(total : Int, r : Int, h : Int, m : Int) : (Int, Int, Int) = {
+    require(
+      total == toSecs(h, m, r) && 
+      m >= 0 && m < 60 && 
+      h >= 0 && r >= 0 &&
+      (m == 0 || r + m * 60 < 3600)
+    )
+
+    if(r >= 3600) {
+      rec(total, r - 3600, h + 1, m)
+    } else if(r >= 60) {
+      rec(total, r - 60, h, m )// FIXME : Should be m + 1
+    } else {
+      (h, m, r)
+    }
+  } ensuring { res =>
+    val (h,m,s) = res
+    prop(total, h, m, s) 
+  } 
+
+
+
+
+}
diff --git a/testcases/synthesis/repair/SecondsToTime/SecondsToTime3.scala b/testcases/synthesis/repair/SecondsToTime/SecondsToTime3.scala
new file mode 100644
index 000000000..3b23952e8
--- /dev/null
+++ b/testcases/synthesis/repair/SecondsToTime/SecondsToTime3.scala
@@ -0,0 +1,38 @@
+
+object SecondsToTime {
+
+  def toSecs(h: Int, m: Int, s: Int) = h * 3600 + m * 60 + s
+  def prop(t: Int, h: Int, m: Int, s: Int) : Boolean = 
+    toSecs(h, m, s) == t && 
+    m >= 0 && m < 60 && 
+    s >= 0 && s < 60 
+
+  def secondsToTime(total : Int) = {
+    require(total >= 0)
+    rec(total, total, 0, 0)
+  } ensuring(_ match { case (h,m,s) => prop(total, h, m, s) })
+
+  def rec(total : Int, r : Int, h : Int, m : Int) : (Int, Int, Int) = {
+    require(
+      total == toSecs(h, m, r) && 
+      m >= 0 && m < 60 && 
+      h >= 0 && r >= 0 &&
+      (m == 0 || r + m * 60 < 3600)
+    )
+
+    if(r >= 3600) {
+      rec(total, r - 3600, h + 1, m)
+    } else if(r > 60) { // FIXME (hard!) condition should be >=
+      rec(total, r - 60, h, m + 1)
+    } else {
+      (h, m, r)
+    }
+  } ensuring { res =>
+    val (h,m,s) = res
+    prop(total, h, m, s) 
+  } 
+
+
+
+
+}
diff --git a/testcases/synthesis/repair/SecondsToTime/SecondsToTime4.scala b/testcases/synthesis/repair/SecondsToTime/SecondsToTime4.scala
new file mode 100644
index 000000000..31843a58c
--- /dev/null
+++ b/testcases/synthesis/repair/SecondsToTime/SecondsToTime4.scala
@@ -0,0 +1,38 @@
+
+object SecondsToTime {
+
+  def toSecs(h: Int, m: Int, s: Int) = h * 3600 + m * 60 + s
+  def prop(t: Int, h: Int, m: Int, s: Int) : Boolean = 
+    toSecs(h, m, s) == t && 
+    m >= 0 && m < 60 && 
+    s >= 0 && s < 60 
+
+  def secondsToTime(total : Int) = {
+    require(total >= 0)
+    rec(total, total, 0, 0)
+  } ensuring(_ match { case (h,m,s) => prop(total, h, m, s) })
+
+  def rec(total : Int, r : Int, h : Int, m : Int) : (Int, Int, Int) = {
+    require(
+      total == toSecs(h, m, r) && 
+      m >= 0 && m < 60 && 
+      h >= 0 && r >= 0 &&
+      (m == 0 || r + m * 60 < 3600)
+    )
+
+    if(r >= 3600) {
+      rec(total, r - 3600, h + 1, m)
+    } else if(r >= 60) {
+      rec(total, r - 60, h, m + 1)
+    } else {
+      (r, m, h) // FIXME: flipped the order in the tuple
+    }
+  } ensuring { res =>
+    val (h,m,s) = res
+    prop(total, h, m, s) 
+  } 
+
+
+
+
+}
diff --git a/testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod.scala b/testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod.scala
new file mode 100644
index 000000000..32e486119
--- /dev/null
+++ b/testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod.scala
@@ -0,0 +1,22 @@
+
+object SecondsToTime {
+
+  def toSecs(h: Int, m: Int, s: Int) = h * 3600 + m * 60 + s
+  def prop(t: Int, h: Int, m: Int, s: Int) : Boolean = 
+    toSecs(h, m, s) == t && 
+    m >= 0 && m < 60 && 
+    s >= 0 && s < 60 
+
+  def secondsToTime(total : Int) = {
+    require(total >= 0)
+    val h = total / 3600
+    val rest = total % 3600
+    val m = rest / 60
+    val s = rest % 60
+    (h,m,s)
+  } ensuring { _ match { case (h,m,s) =>
+    prop(total, h, m, s)
+  }}
+
+
+}
diff --git a/testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod1.scala b/testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod1.scala
new file mode 100644
index 000000000..7df923d6b
--- /dev/null
+++ b/testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod1.scala
@@ -0,0 +1,22 @@
+
+object SecondsToTime {
+
+  def toSecs(h: Int, m: Int, s: Int) = h * 3600 + m * 60 + s
+  def prop(t: Int, h: Int, m: Int, s: Int) : Boolean = 
+    toSecs(h, m, s) == t && 
+    m >= 0 && m < 60 && 
+    s >= 0 && s < 60 
+
+  def secondsToTime(total : Int) = {
+    require(total >= 0)
+    val h = total / 3600
+    val rest = total % 3600
+    val m = rest / 60
+    val s = rest / 60 // FIXME : / instead of %
+    (h,m,s)
+  } ensuring { _ match { case (h,m,s) =>
+    prop(total, h, m, s)
+  }}
+
+
+}
diff --git a/testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod2.scala b/testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod2.scala
new file mode 100644
index 000000000..d54d58666
--- /dev/null
+++ b/testcases/synthesis/repair/SecondsToTime/SecondsToTimeMod2.scala
@@ -0,0 +1,22 @@
+
+object SecondsToTime {
+
+  def toSecs(h: Int, m: Int, s: Int) = h * 3600 + m * 60 + s
+  def prop(t: Int, h: Int, m: Int, s: Int) : Boolean = 
+    toSecs(h, m, s) == t && 
+    m >= 0 && m < 60 && 
+    s >= 0 && s < 60 
+
+  def secondsToTime(total : Int) = {
+    require(total >= 0)
+    val h = total / 3600
+    val rest = total % 3600
+    val m = rest / 60
+    val s = total % 60 // FIXME: total instead of rest
+    (h,m,s)
+  } ensuring { _ match { case (h,m,s) =>
+    prop(total, h, m, s)
+  }}
+
+
+}
diff --git a/testcases/synthesis/repair/SortedList/SortedList.scala b/testcases/synthesis/repair/SortedList/SortedList.scala
new file mode 100644
index 000000000..1b79edd82
--- /dev/null
+++ b/testcases/synthesis/repair/SortedList/SortedList.scala
@@ -0,0 +1,51 @@
+import leon.collection._
+import leon.lang.synthesis._
+
+object SortedList {
+
+  def isSorted(l : List[Int]) : Boolean = l match {
+    case Cons(h1, tl@Cons(h2, _)) => h1 <= h2 && isSorted(tl)
+    case _ => true
+  }
+
+  def merge(l1 : List[Int], l2 : List[Int]) : List[Int] = { 
+    require(isSorted(l1) && isSorted(l2))
+    (l1, l2) match {
+      case (Nil(), _) => l2
+      case (_, Nil()) => l1
+      case (Cons(h1, t1), Cons(h2,t2)) =>
+        if (h1 <= h2) 
+          Cons(h1, merge(t1,l2))
+        else 
+          Cons(h2, merge(l1,t2))
+    }
+  } ensuring { res =>
+    isSorted(res) && (res.content == l1.content ++ l2.content)
+  }
+
+  
+  def split(l : List[Int]) : (List[Int], List[Int]) = { l match {
+    case Cons(h1, Cons(h2, tl)) => 
+      val (t1,t2) = split(tl)
+      ( Cons(h1,t1), Cons(h2,t2) )
+    case _ => (l, Nil[Int]())
+  }} ensuring { res =>
+    val (res1,res2) = res
+    res1.content ++ res2.content == l.content &&
+    res1.size + res2.size == l.size &&
+    res1.size <= res2.size + 1 &&
+    res1.size >= res2.size - 1
+  }
+
+  def mergeSort(l : List[Int]) : List[Int] = { l match {
+    case Nil() => l 
+    case Cons(_, Nil()) => l
+    case _ => 
+      val (l1, l2) = split(l)
+      merge(mergeSort(l1),mergeSort(l2))
+  }} ensuring { res =>
+    res.content == l.content &&
+    isSorted(res)
+  }
+
+}
diff --git a/testcases/synthesis/repair/SortedList/SortedList1.scala b/testcases/synthesis/repair/SortedList/SortedList1.scala
new file mode 100644
index 000000000..39ca45d49
--- /dev/null
+++ b/testcases/synthesis/repair/SortedList/SortedList1.scala
@@ -0,0 +1,51 @@
+import leon.collection._
+import leon.lang.synthesis._
+
+object SortedList {
+
+  def isSorted(l : List[Int]) : Boolean = l match {
+    case Cons(h1, tl@Cons(h2, _)) => h1 <= h2 && isSorted(tl)
+    case _ => true
+  }
+
+  def merge(l1 : List[Int], l2 : List[Int]) : List[Int] = { 
+    require(isSorted(l1) && isSorted(l2))
+    (l1, l2) match {
+      case (Nil(), _) => l2
+      case (_, Nil()) => l1
+      case (Cons(h1, t1), Cons(h2,t2)) =>
+        if (h1 <= h2) 
+          Cons(h1, merge(t1,l2))
+        else 
+          Cons(h2, merge(l1,t2))
+    }
+  } ensuring { res =>
+    isSorted(res) && (res.content == l1.content ++ l2.content)
+  }
+
+  
+  def split(l : List[Int]) : (List[Int], List[Int]) = { l match {
+    case Cons(h1, Cons(h2, tl)) => 
+      val (t1,t2) = split(tl)
+      ( Cons(h1,t1), Cons(h2,t2) )
+    case _ => (l, Nil[Int]())
+  }} ensuring { res =>
+    val (res1,res2) = res
+    res1.content ++ res2.content == l.content &&
+    res1.size + res2.size == l.size &&
+    res1.size <= res2.size + 1 &&
+    res1.size >= res2.size - 1
+  }
+
+  def mergeSort(l : List[Int]) : List[Int] = { l match {
+    case Nil() => l 
+    case Cons(_, Nil()) => l
+    case _ => 
+      val (l1, l2) = split(l)
+      merge(l1,l2) // FIXME: Forgot to mergeSort l1 and l2
+  }} ensuring { res =>
+    res.content == l.content &&
+    isSorted(res)
+  }
+
+}
diff --git a/testcases/synthesis/repair/SortedList/SortedList2.scala b/testcases/synthesis/repair/SortedList/SortedList2.scala
new file mode 100644
index 000000000..0219d16f3
--- /dev/null
+++ b/testcases/synthesis/repair/SortedList/SortedList2.scala
@@ -0,0 +1,51 @@
+import leon.collection._
+import leon.lang.synthesis._
+
+object SortedList {
+
+  def isSorted(l : List[Int]) : Boolean = l match {
+    case Cons(h1, tl@Cons(h2, _)) => h1 <= h2 && isSorted(tl)
+    case _ => true
+  }
+
+  def merge(l1 : List[Int], l2 : List[Int]) : List[Int] = { 
+    require(isSorted(l1) && isSorted(l2))
+    (l1, l2) match {
+      case (Nil(), _) => l2
+      case (_, Nil()) => l1
+      case (Cons(h1, t1), Cons(h2,t2)) =>
+        if (h1 <= h2) 
+          Cons(h1, merge(t1,l2))
+        else 
+          Cons(h1, merge(l1,t2)) // FIXME: h1 instead of h2
+    }
+  } ensuring { res =>
+    isSorted(res) && (res.content == l1.content ++ l2.content)
+  }
+
+  
+  def split(l : List[Int]) : (List[Int], List[Int]) = { l match {
+    case Cons(h1, Cons(h2, tl)) => 
+      val (t1,t2) = split(tl)
+      ( Cons(h1,t1), Cons(h2,t2) )
+    case _ => (l, Nil[Int]())
+  }} ensuring { res =>
+    val (res1,res2) = res
+    res1.content ++ res2.content == l.content &&
+    res1.size + res2.size == l.size &&
+    res1.size <= res2.size + 1 &&
+    res1.size >= res2.size - 1
+  }
+
+  def mergeSort(l : List[Int]) : List[Int] = { l match {
+    case Nil() => l 
+    case Cons(_, Nil()) => l
+    case _ => 
+      val (l1, l2) = split(l)
+      merge(mergeSort(l1),mergeSort(l2))
+  }} ensuring { res =>
+    res.content == l.content &&
+    isSorted(res)
+  }
+
+}
diff --git a/testcases/synthesis/repair/SortedList/SortedList3.scala b/testcases/synthesis/repair/SortedList/SortedList3.scala
new file mode 100644
index 000000000..175683215
--- /dev/null
+++ b/testcases/synthesis/repair/SortedList/SortedList3.scala
@@ -0,0 +1,51 @@
+import leon.collection._
+import leon.lang.synthesis._
+
+object SortedList {
+
+  def isSorted(l : List[Int]) : Boolean = l match {
+    case Cons(h1, tl@Cons(h2, _)) => h1 <= h2 && isSorted(tl)
+    case _ => true
+  }
+
+  def merge(l1 : List[Int], l2 : List[Int]) : List[Int] = { 
+    require(isSorted(l1) && isSorted(l2))
+    (l1, l2) match {
+      case (Nil(), _) => l2
+      case (_, Nil()) => l1
+      case (Cons(h1, t1), Cons(h2,t2)) =>
+        //if (h1 <= h2) // FIXME : didn't EqSplit here
+          Cons(h1, merge(t1,l2))
+        //else 
+          //Cons(h2, merge(l1,t2))
+    }
+  } ensuring { res =>
+    isSorted(res) && (res.content == l1.content ++ l2.content)
+  }
+
+  
+  def split(l : List[Int]) : (List[Int], List[Int]) = { l match {
+    case Cons(h1, Cons(h2, tl)) => 
+      val (t1,t2) = split(tl)
+      ( Cons(h1,t1), Cons(h2,t2) )
+    case _ => (l, Nil[Int]())
+  }} ensuring { res =>
+    val (res1,res2) = res
+    res1.content ++ res2.content == l.content &&
+    res1.size + res2.size == l.size &&
+    res1.size <= res2.size + 1 &&
+    res1.size >= res2.size - 1
+  }
+
+  def mergeSort(l : List[Int]) : List[Int] = { l match {
+    case Nil() => l 
+    case Cons(_, Nil()) => l
+    case _ => 
+      val (l1, l2) = split(l)
+      merge(mergeSort(l1),mergeSort(l2))
+  }} ensuring { res =>
+    res.content == l.content &&
+    isSorted(res)
+  }
+
+}
diff --git a/testcases/synthesis/repair/SortedList/SortedList4.scala b/testcases/synthesis/repair/SortedList/SortedList4.scala
new file mode 100644
index 000000000..4a2ba301c
--- /dev/null
+++ b/testcases/synthesis/repair/SortedList/SortedList4.scala
@@ -0,0 +1,52 @@
+import leon.collection._
+import leon.lang.synthesis._
+
+object SortedList {
+
+  def isSorted(l : List[Int]) : Boolean = l match {
+    case Cons(h1, tl@Cons(h2, _)) => h1 <= h2 && isSorted(tl)
+    case _ => true
+  }
+
+  def merge(l1 : List[Int], l2 : List[Int]) : List[Int] = { 
+    require(isSorted(l1) && isSorted(l2))
+    (l1, l2) match {
+      case (Nil(), _) => l2
+      case (_, Nil()) => l1
+      case (Cons(h1, t1), Cons(h2,t2)) =>
+        if (h1 <= h2) 
+          Cons(h1, merge(t1,l2))
+        else 
+          Cons(h2, merge(l1,t2))
+    }
+  } ensuring { res =>
+    isSorted(res) && (res.content == l1.content ++ l2.content)
+  }
+
+  
+  def split(l : List[Int]) : (List[Int], List[Int]) = { l match {
+    case Cons(h1, tl) => 
+      val (t1,t2) = split(tl)
+      ( Cons(h1,t1), t2 )
+      // FIXME (hard) : this is nonsense, just places everything on the first list
+    case _ => (l, Nil[Int]())
+  }} ensuring { res =>
+    val (res1,res2) = res
+    res1.content ++ res2.content == l.content &&
+    res1.size + res2.size == l.size &&
+    res1.size <= res2.size + 1 &&
+    res1.size >= res2.size - 1
+  }
+
+  def mergeSort(l : List[Int]) : List[Int] = { l match {
+    case Nil() => l 
+    case Cons(_, Nil()) => l
+    case _ => 
+      val (l1, l2) = split(l)
+      merge(mergeSort(l1),mergeSort(l2))
+  }} ensuring { res =>
+    res.content == l.content &&
+    isSorted(res)
+  }
+
+}
diff --git a/testcases/synthesis/repair/SortedList/SortedList5.scala b/testcases/synthesis/repair/SortedList/SortedList5.scala
new file mode 100644
index 000000000..b0310ae8c
--- /dev/null
+++ b/testcases/synthesis/repair/SortedList/SortedList5.scala
@@ -0,0 +1,51 @@
+import leon.collection._
+import leon.lang.synthesis._
+
+object SortedList {
+
+  def isSorted(l : List[Int]) : Boolean = l match {
+    case Cons(h1, tl@Cons(h2, _)) => h1 <= h2 && isSorted(tl)
+    case _ => true
+  }
+
+  def merge(l1 : List[Int], l2 : List[Int]) : List[Int] = { 
+    require(isSorted(l1) && isSorted(l2))
+    (l1, l2) match {
+      case (Nil(), _) => l2
+      case (_, Nil()) => l1
+      case (Cons(h1, t1), Cons(h2,t2)) =>
+        if (h1 <= h2) 
+          Cons(h1, merge(t1,l2))
+        else 
+          Cons(h2, merge(l1,t2))
+    }
+  } ensuring { res =>
+    isSorted(res) && (res.content == l1.content ++ l2.content)
+  }
+
+  
+  def split(l : List[Int]) : (List[Int], List[Int]) = { l match {
+    case Cons(h1, Cons(h2, tl)) => 
+      val (t1,t2) = split(tl)
+      ( t1, Cons(h2,t2) ) // FIXME: t1 should be h1 :: t1
+    case _ => (l, Nil[Int]())
+  }} ensuring { res =>
+    val (res1,res2) = res
+    res1.content ++ res2.content == l.content &&
+    res1.size + res2.size == l.size &&
+    res1.size <= res2.size + 1 &&
+    res1.size >= res2.size - 1
+  }
+
+  def mergeSort(l : List[Int]) : List[Int] = { l match {
+    case Nil() => l 
+    case Cons(_, Nil()) => l
+    case _ => 
+      val (l1, l2) = split(l)
+      merge(mergeSort(l1),mergeSort(l2))
+  }} ensuring { res =>
+    res.content == l.content &&
+    isSorted(res)
+  }
+
+}
diff --git a/testcases/synthesis/repair/SortedList/SortedList6.scala b/testcases/synthesis/repair/SortedList/SortedList6.scala
new file mode 100644
index 000000000..523cee08c
--- /dev/null
+++ b/testcases/synthesis/repair/SortedList/SortedList6.scala
@@ -0,0 +1,51 @@
+import leon.collection._
+import leon.lang.synthesis._
+
+object SortedList {
+
+  def isSorted(l : List[Int]) : Boolean = l match {
+    case Cons(h1, tl@Cons(h2, _)) => h1 <= h2 && isSorted(tl)
+    case _ => true
+  }
+
+  def merge(l1 : List[Int], l2 : List[Int]) : List[Int] = { 
+    require(isSorted(l1) && isSorted(l2))
+    (l1, l2) match {
+      case (Nil(), _) => l2
+      case (_, Nil()) => l1
+      case (Cons(h1, t1), Cons(h2,t2)) =>
+        if (h1 <= h2) 
+          Cons(h1, merge(t1,l2))
+        else 
+          Cons(h2, merge(t1,t2)) // FIXME : t1 instead l1
+    }
+  } ensuring { res =>
+    isSorted(res) && (res.content == l1.content ++ l2.content)
+  }
+
+  
+  def split(l : List[Int]) : (List[Int], List[Int]) = { l match {
+    case Cons(h1, Cons(h2, tl)) => 
+      val (t1,t2) = split(tl)
+      ( Cons(h1,t1), Cons(h2,t2) )
+    case _ => (l, Nil[Int]())
+  }} ensuring { res =>
+    val (res1,res2) = res
+    res1.content ++ res2.content == l.content &&
+    res1.size + res2.size == l.size &&
+    res1.size <= res2.size + 1 &&
+    res1.size >= res2.size - 1
+  }
+
+  def mergeSort(l : List[Int]) : List[Int] = { l match {
+    case Nil() => l 
+    case Cons(_, Nil()) => l
+    case _ => 
+      val (l1, l2) = split(l)
+      merge(mergeSort(l1),mergeSort(l2))
+  }} ensuring { res =>
+    res.content == l.content &&
+    isSorted(res)
+  }
+
+}
diff --git a/testcases/synthesis/repair/SortedList/SortedList7.scala b/testcases/synthesis/repair/SortedList/SortedList7.scala
new file mode 100644
index 000000000..fbd78cf8e
--- /dev/null
+++ b/testcases/synthesis/repair/SortedList/SortedList7.scala
@@ -0,0 +1,52 @@
+import leon.collection._
+import leon.lang.synthesis._
+
+object SortedList {
+
+  def isSorted(l : List[Int]) : Boolean = l match {
+    case Cons(h1, tl@Cons(h2, _)) => h1 <= h2 && isSorted(tl)
+    case _ => true
+  }
+
+  def merge(l1 : List[Int], l2 : List[Int]) : List[Int] = { 
+    require(isSorted(l1) && isSorted(l2))
+    (l1, l2) match {
+      case (Nil(), _) => l2
+      case (_, Nil()) => l1
+      case (Cons(h1, t1), Cons(h2,t2)) =>
+        if (h1 <= h2) 
+          // FIXME : swap the branches
+          Cons(h2, merge(l1,t2))
+        else 
+          Cons(h1, merge(t1,l2))
+    }
+  } ensuring { res =>
+    isSorted(res) && (res.content == l1.content ++ l2.content)
+  }
+
+  
+  def split(l : List[Int]) : (List[Int], List[Int]) = { l match {
+    case Cons(h1, Cons(h2, tl)) => 
+      val (t1,t2) = split(tl)
+      ( Cons(h1,t1), Cons(h2,t2) )
+    case _ => (l, Nil[Int]())
+  }} ensuring { res =>
+    val (res1,res2) = res
+    res1.content ++ res2.content == l.content &&
+    res1.size + res2.size == l.size &&
+    res1.size <= res2.size + 1 &&
+    res1.size >= res2.size - 1
+  }
+
+  def mergeSort(l : List[Int]) : List[Int] = { l match {
+    case Nil() => l 
+    case Cons(_, Nil()) => l
+    case _ => 
+      val (l1, l2) = split(l)
+      merge(mergeSort(l1),mergeSort(l2))
+  }} ensuring { res =>
+    res.content == l.content &&
+    isSorted(res)
+  }
+
+}
-- 
GitLab