diff --git a/src/main/scala/leon/datagen/NaiveDataGen.scala b/src/main/scala/leon/datagen/NaiveDataGen.scala
index b1727fb71926e8e067d687a3bb62a42b78f5198f..d65e5ce1d7fb1312f3009b600eaae79dc82f0324 100644
--- a/src/main/scala/leon/datagen/NaiveDataGen.scala
+++ b/src/main/scala/leon/datagen/NaiveDataGen.scala
@@ -8,6 +8,7 @@ import purescala.Trees._
 import purescala.TreeOps._
 import purescala.TypeTrees._
 import purescala.Definitions._
+import utils.StreamUtils._
 
 import evaluators._
 
@@ -18,54 +19,15 @@ import scala.collection.mutable.{Map=>MutableMap}
   * e.g. by passing trees representing variables for the "bounds". */
 class NaiveDataGen(ctx: LeonContext, p: Program, evaluator: Evaluator, _bounds : Option[Map[TypeTree,Seq[Expr]]] = None) extends DataGenerator {
 
-  private val defaultBounds : Map[TypeTree,Seq[Expr]] = Map(
-    Int32Type -> Seq(IntLiteral(0), IntLiteral(1), IntLiteral(-1))
-  )
-
-  val bounds = _bounds.getOrElse(defaultBounds)
-
-  private val boolStream : Stream[Expr] =
-    Stream.cons(BooleanLiteral(true), Stream.cons(BooleanLiteral(false), Stream.empty))
-
-  class VectorizedStream[T](initial : Stream[T]) {
-    private def mkException(i : Int) = new IndexOutOfBoundsException("Can't access VectorizedStream at : " + i)
-    private def streamHeadIndex : Int = indexed.size
-    private var stream  : Stream[T] = initial
-    private var indexed : Vector[T] = Vector.empty
-
-    def apply(index : Int) : T = {
-      if(index < streamHeadIndex) {
-        indexed(index)
-      } else {
-        val diff = index - streamHeadIndex // diff >= 0
-        var i = 0
-        while(i < diff) {
-          if(stream.isEmpty) throw mkException(index)
-          indexed = indexed :+ stream.head
-          stream  = stream.tail
-          i += 1
-        }
-        // The trick is *not* to read past the desired element. Leave it in the
-        // stream, or it will force the *following* one...
-        stream.headOption.getOrElse { throw mkException(index) }
-      }
-    }
-  }
-
-  private def intStream : Stream[Expr] = Stream.cons(IntLiteral(0), intStream0(1))
-  private def intStream0(n : Int) : Stream[Expr] = Stream.cons(IntLiteral(n), intStream0(if(n > 0) -n else -(n-1)))
+  val bounds = _bounds.getOrElse(Map())
 
   private def tpStream(tp: TypeParameter, i: Int = 1): Stream[Expr] = Stream.cons(GenericValue(tp, i), tpStream(tp, i+1))
 
-  def natStream : Stream[Expr] = natStream0(0)
-  private def natStream0(n : Int) : Stream[Expr] = Stream.cons(IntLiteral(n), natStream0(n+1))
-
   private val streamCache : MutableMap[TypeTree,Stream[Expr]] = MutableMap.empty
-
-  def generate(tpe : TypeTree, bounds : Map[TypeTree,Seq[Expr]] = defaultBounds) : Stream[Expr] = {
+  def generate(tpe : TypeTree) : Stream[Expr] = {
     try {
       streamCache.getOrElse(tpe, {
-        val s = generate0(tpe, bounds)
+        val s = generate0(tpe)
         streamCache(tpe) = s
         s
       })
@@ -75,20 +37,19 @@ class NaiveDataGen(ctx: LeonContext, p: Program, evaluator: Evaluator, _bounds :
     }
   }
 
-  // TODO We should make sure the cache depends on the bounds (i.e. is not reused for different bounds.)
-  private def generate0(tpe : TypeTree, bounds : Map[TypeTree,Seq[Expr]]) : Stream[Expr] = bounds.get(tpe).map(_.toStream).getOrElse {
+  private def generate0(tpe: TypeTree): Stream[Expr] = bounds.get(tpe).map(_.toStream).getOrElse {
     tpe match {
       case BooleanType =>
-        boolStream
+        BooleanLiteral(true) #:: BooleanLiteral(false) #:: Stream.empty
 
       case Int32Type =>
-        intStream
+        IntLiteral(0) #:: IntLiteral(1) #:: IntLiteral(-1) #:: Stream.empty
 
       case tp: TypeParameter =>
         tpStream(tp)
 
       case TupleType(bses) =>
-        naryProduct(bses.map(generate(_, bounds))).map(Tuple)
+        cartesianProduct(bses.map(generate(_))).map(Tuple)
 
       case act : AbstractClassType =>
         // We prioritize base cases among the children.
@@ -100,12 +61,12 @@ class NaiveDataGen(ctx: LeonContext, p: Program, evaluator: Evaluator, _bounds :
 
         // The stream for leafs...
         val leafsStream = leafs.toStream.flatMap { cct =>
-          generate(cct, bounds)
+          generate(cct)
         }
 
         // ...to which we append the streams for constructors.
         leafsStream.append(interleave(conss.map { cct =>
-          generate(cct, bounds)
+          generate(cct)
         }))
 
       case cct : CaseClassType =>
@@ -113,115 +74,31 @@ class NaiveDataGen(ctx: LeonContext, p: Program, evaluator: Evaluator, _bounds :
           Stream.cons(CaseClass(cct, Nil), Stream.empty)
         } else {
           val fieldTypes = cct.fieldsTypes
-          val subStream = naryProduct(fieldTypes.map(generate(_, bounds)))
-          subStream.map(prod => CaseClass(cct, prod))
+          cartesianProduct(fieldTypes.map(generate(_))).map(CaseClass(cct, _))
         }
 
       case _ => Stream.empty
     }
   }
 
-  //def findModels(expr : Expr, maxModels : Int, maxTries : Int, bounds : Map[TypeTree,Seq[Expr]] = defaultBounds, forcedFreeVars: Option[Seq[Identifier]] = None) : Stream[Map[Identifier,Expr]] = {
   def generateFor(ins: Seq[Identifier], satisfying: Expr, maxValid : Int, maxEnumerated : Int) : Iterator[Seq[Expr]] = {
-    evaluator.compile(satisfying, ins).map { evalFun =>
-      val sat = EvaluationResults.Successful(BooleanLiteral(true))
-
-      naryProduct(ins.map(id => generate(id.getType, bounds)))
-        .take(maxEnumerated)
-        .takeWhile(s => !interrupted.get)
-        .filter{s => evalFun(s) == sat }
-        .take(maxValid)
-        .iterator
-
-    } getOrElse {
-      Stream.empty.iterator
-    }
-  }
-
-  // The following are stream utilities.
-
-  // Takes a series of streams and merges them, round-robin style.
-  private def interleave[T](streams : Seq[Stream[T]]) : Stream[T] = int0(streams)
-  private def int0[T](streams : Seq[Stream[T]]) : Stream[T] = {
-    var ss = streams
-    while(!ss.isEmpty && ss.head.isEmpty) {
-      ss = ss.tail
-    }
-    if(ss.isEmpty) return Stream.empty
-    if(ss.size == 1) return ss(0)
-    // TODO: This circular-shifts the list. I'd be interested in a constant time
-    // operation. Perhaps simply by choosing the right data-structure?
-    Stream.cons(ss.head.head, interleave(ss.tail :+ ss.head.tail))
-  }
-
-  // Takes a series of streams and enumerates their cartesian product.
-  private def naryProduct[T](streams : Seq[Stream[T]]) : Stream[List[T]] = {
-    val dimensions = streams.size
-    val vectorizedStreams = streams.map(new VectorizedStream(_))
-
-    if(dimensions == 0)
-      return Stream.cons(Nil, Stream.empty)
-
-    if(streams.exists(_.isEmpty))
-      return Stream.empty
-
-    val indices = if(streams.forall(_.hasDefiniteSize)) {
-      val max = streams.map(_.size).max
-      diagCount(dimensions).take(max)
+    val filtering = if (satisfying == BooleanLiteral(true)) {
+      { (e: Seq[Expr]) => true }
     } else {
-      diagCount(dimensions)
-    }
-
-    var allReached : Boolean = false
-    val bounds : Array[Int] = Array.fill(dimensions)(Int.MaxValue)
-
-    indices.takeWhile(_ => !allReached).flatMap { indexList =>
-      var d = 0
-      var continue = true
-      var is = indexList
-      var ss = vectorizedStreams.toList
+      evaluator.compile(satisfying, ins).map { evalFun =>
+        val sat = EvaluationResults.Successful(BooleanLiteral(true))
 
-      if(indexList.sum >= bounds.max) {
-        allReached = true
+        { (e: Seq[Expr]) => evalFun(e) == sat }
+      } getOrElse {
+        { (e: Seq[Expr]) => false }
       }
-
-      var tuple : List[T] = Nil
-
-      while(continue && d < dimensions) {
-        var i = is.head
-        if(i > bounds(d)) {
-          continue = false
-        } else try {
-          // TODO can we speed up by caching the random access into
-          // the stream in an indexedSeq? After all, `i` increases
-          // slowly.
-          tuple = (ss.head)(i) :: tuple
-          is = is.tail
-          ss = ss.tail
-          d += 1
-        } catch {
-          case e : IndexOutOfBoundsException =>
-            bounds(d) = i - 1
-            continue = false
-        }
-      }
-      if(continue) Some(tuple.reverse) else None
     }
-  }
 
-  // Utility function for n-way cartesian product.
-  // Counts over indices in `dim` dimensions in a fair, diagonal, way.
-  private def diagCount(dim : Int) : Stream[List[Int]] = diag0(dim, 0)
-  private def diag0(dim : Int, nextSum : Int) : Stream[List[Int]] = summingTo(nextSum, dim).append(diag0(dim, nextSum + 1))
-  // All tuples of dimension `n` whose sum is `sum`.
-  private def summingTo(sum : Int, n : Int) : Stream[List[Int]] = {
-    // assert(sum >= 0)
-    if(sum < 0) {
-      Stream.empty
-    } else if(n == 1) {
-      Stream.cons(sum :: Nil, Stream.empty) 
-    } else {
-      (0 to sum).toStream.flatMap(fst => summingTo(sum - fst, n - 1).map(fst :: _))
-    }
+    cartesianProduct(ins.map(id => generate(id.getType)))
+      .take(maxEnumerated)
+      .takeWhile(s => !interrupted.get)
+      .filter{filtering}
+      .take(maxValid)
+      .iterator
   }
 }
diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala
index bf5efce46c23be9074ac4c08c13ced0a7cc51e16..8803ae47dc84f96f169e800e0bd89e1d26fc7e24 100644
--- a/src/main/scala/leon/purescala/Extractors.scala
+++ b/src/main/scala/leon/purescala/Extractors.scala
@@ -8,6 +8,7 @@ import Trees._
 object Extractors {
   import Common._
   import TypeTrees._
+  import TypeTreeOps._
   import Definitions._
   import Extractors._
   import TreeOps._
@@ -108,7 +109,15 @@ object Extractors {
             case ((keys, values, isKey), rExpr) => if(isKey) (rExpr::keys, values, false) else (keys, rExpr::values, true)
           }
           assert(isKey)
-          FiniteMap(keys.zip(values))
+          val tpe = (keys, values) match {
+            case (Seq(), Seq()) => expr.getType
+            case _ =>
+              MapType(
+                leastUpperBound(keys.map(_.getType)).get,
+                leastUpperBound(values.map(_.getType)).get
+              )
+          }
+          FiniteMap(keys.zip(values)).setType(tpe)
         }
         Some((subArgs, builder))
       }
diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala
index 6065fc172bd8bedf7b9f0c90d6476479f221b8e7..e0557a3d82e4ad239c9e995e333237ef53ff3c04 100644
--- a/src/main/scala/leon/purescala/TreeOps.scala
+++ b/src/main/scala/leon/purescala/TreeOps.scala
@@ -689,8 +689,8 @@ object TreeOps {
       
       case TuplePattern(_, subps) =>
         val TupleType(subts) = in.getType
-        val subExprs = (subps zip subts) map {
-          case (p, t) => p.binder.getOrElse(FreshIdentifier("b", true).setType(t)).toVariable
+        val subExprs = (subps zip subts).zipWithIndex map {
+          case ((p, t), index) => p.binder.map(_.toVariable).getOrElse(TupleSelect(in, index+1))
         }
 
         // Special case to get rid of (a,b) match { case (c,d) => .. }
@@ -706,8 +706,8 @@ object TreeOps {
         })
 
       case CaseClassPattern(_, cct, subps) =>
-        val subExprs = (subps zip cct.fieldsTypes) map {
-          case (p, t) => p.binder.getOrElse(FreshIdentifier("b", true).setType(t)).toVariable
+        val subExprs = (subps zip cct.fields) map {
+          case (p, f) => p.binder.map(_.toVariable).getOrElse(CaseClassSelector(cct, in, f.id))
         }
         
         // Special case to get rid of Cons(a,b) match { case Cons(c,d) => .. }
diff --git a/src/main/scala/leon/refactor/Repairman.scala b/src/main/scala/leon/refactor/Repairman.scala
index 71b08a49cb422687fd34a1e04781ee1351be4252..8b4ea7c175b99a6a2c78e949509cd4f44cdbe462 100644
--- a/src/main/scala/leon/refactor/Repairman.scala
+++ b/src/main/scala/leon/refactor/Repairman.scala
@@ -23,6 +23,8 @@ import synthesis._
 class Repairman(ctx: LeonContext, program: Program, fd: FunDef) {
   val reporter = ctx.reporter
 
+  implicit val debugSection = DebugSectionRefactor
+
   var testBank = List[Example]()
 
   var solutions: List[(Solution, Expr, List[FunDef])] = Nil
@@ -45,7 +47,11 @@ class Repairman(ctx: LeonContext, program: Program, fd: FunDef) {
         tupleWrap(ins) -> tupleWrap(outs)
     }.toList).setType(MapType(argsWrapped.getType, out.getType))
 
-    val passes = FunctionInvocation(tfd, Seq(argsWrapped, out.toVariable, testsExpr))
+    val passes = if (testsExpr.singletons.nonEmpty) {
+      FunctionInvocation(tfd, Seq(argsWrapped, out.toVariable, testsExpr))
+    } else {
+      BooleanLiteral(true)
+    }
 
     // Compute guide implementation
     val gexpr = fd.body.get
@@ -58,8 +64,8 @@ class Repairman(ctx: LeonContext, program: Program, fd: FunDef) {
     val term = FunctionInvocation(termfd.typed(Seq(fd.returnType)), Seq(withinCall))
 
     val spec = And(Seq(
-      fd.postcondition.map(_._2).getOrElse(BooleanLiteral(true))
- //     passes
+      fd.postcondition.map(_._2).getOrElse(BooleanLiteral(true)),
+      passes
     ))
 
     val pc = And(Seq(
@@ -211,6 +217,7 @@ class Repairman(ctx: LeonContext, program: Program, fd: FunDef) {
     val tests = new NaiveDataGen(ctx, program, evaluator)
 
     val pre = fd.precondition.getOrElse(BooleanLiteral(true))
+
     val inputs = tests.generateFor(fd.params.map(_.id), pre, 30, 10000).toList
 
     testBank ++= inputs.map { i =>
@@ -232,4 +239,5 @@ class Repairman(ctx: LeonContext, program: Program, fd: FunDef) {
   }
 
   discoverTests()
+
 }
diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala
index fae464a790c904b5e14d50f98b12a466bebbf22d..9623624af94dc495cbe1edc335ba4cde5fca0197 100644
--- a/src/main/scala/leon/synthesis/Rules.scala
+++ b/src/main/scala/leon/synthesis/Rules.scala
@@ -38,18 +38,17 @@ object Rules {
     //AngelicHoles // @EK: Disabled now as it is explicit with withOracle { .. }
   )
 
-  def getInstantiations(sctx: SynthesisContext, problem: Problem) = {
-    val sub = sctx.rules.flatMap { r =>
-      r.instantiateOn(sctx, problem)
-    }
+  def getInstantiations(sctx: SynthesisContext, problem: Problem): List[RuleInstantiation] = {
 
-    val res = sub.groupBy(_.priority).toSeq.sortBy(_._1)
+    val rulesPrio = sctx.rules.groupBy(_.priority).toSeq.sortBy(_._1)
 
-    if (res.nonEmpty) {
-      res.head._2.toList
-    } else {
-      Nil
+    for ((_, rs) <- rulesPrio) {
+      val results = rs.flatMap(_.instantiateOn(sctx, problem)).toList
+      if (results.nonEmpty) {
+        return results;
+      }
     }
+    Nil
   }
 }
 
diff --git a/src/main/scala/leon/synthesis/rules/Cegis.scala b/src/main/scala/leon/synthesis/rules/Cegis.scala
index e00c5f5d77fd490035aa4d40afd15280b4c8ef22..160f3ec13e5a2c97783f5bed15f3179318600995 100644
--- a/src/main/scala/leon/synthesis/rules/Cegis.scala
+++ b/src/main/scala/leon/synthesis/rules/Cegis.scala
@@ -4,6 +4,7 @@ package leon
 package synthesis
 package rules
 
+import leon.utils.StreamUtils
 import solvers._
 import solvers.z3._
 
@@ -18,7 +19,7 @@ import purescala.Extractors._
 import purescala.ScalaPrinter
 import utils.Helpers._
 
-import scala.collection.mutable.{Map=>MutableMap}
+import scala.collection.mutable.{HashMap=>MutableMap, ArrayBuffer}
 
 import evaluators._
 import datagen._
@@ -34,11 +35,10 @@ case object CEGIS extends Rule("CEGIS") {
     val useUninterpretedProbe = sctx.options.cegisUseUninterpretedProbe
     val useUnsatCores         = sctx.options.cegisUseUnsatCores
     val useOptTimeout         = sctx.options.cegisUseOptTimeout
-    val useFunGenerators      = sctx.options.cegisGenerateFunCalls
-    val useBPaths             = sctx.options.cegisUseBPaths
     val useVanuatoo           = sctx.options.cegisUseVanuatoo
     val useCETests            = sctx.options.cegisUseCETests
     val useCEPruning          = sctx.options.cegisUseCEPruning
+
     // Limits the number of programs CEGIS will specifically test for instead of reasonning symbolically
     val testUpTo              = 5
     val useBssFiltering       = sctx.options.cegisUseBssFiltering
@@ -48,38 +48,56 @@ case object CEGIS extends Rule("CEGIS") {
 
     val interruptManager      = sctx.context.interruptManager
 
-    val grammar = new ExpressionGrammar(sctx, p)
-
     class NonDeterministicProgram(val p: Problem,
                                   val initGuard: Identifier) {
 
-      //var program: Expr = BooleanLiteral(true)
+      val grammar = new ExpressionGrammar(sctx, p)
 
       // b -> (c, ex) means the clause b => c == ex
       var mappings: Map[Identifier, (Identifier, Expr)] = Map()
 
-      // b -> Set(c1, c2) means c1 and c2 are uninterpreted behing b, requires b to be closed
+      // b -> Set(c1, c2) means c1 and c2 are uninterpreted behind b, requires b to be closed
       private var guardedTerms: Map[Identifier, Set[Identifier]] = Map(initGuard -> p.xs.toSet)
 
-
       def isBClosed(b: Identifier) = guardedTerms.contains(b)
 
-      // b -> Map(c1 -> Set(b2, b3), c2 -> Set(b4, b5)) means b protects c1 (with sub alternatives b2/b3), and c2 (with sub b4/b5)
+      /**
+       * Stores which b's guard which c's, which then are represented by which
+       * b's:
+       *
+       * b -> Map(c1 -> Set(b2, b3),
+       *          c2 -> Set(b4, b5))
+       *
+       * means b protects c1 (with sub alternatives b2/b3), and c2 (with sub b4/b5)
+       */
       private var bTree = Map[Identifier, Map[Identifier, Set[Identifier]]]( initGuard -> p.xs.map(_ -> Set[Identifier]()).toMap)
 
+      /**
+       * Computes dependencies of c's
+       *
+       * Assuming encoding:
+       * b1 => c == F(c2, c3)
+       * b2 => c == F(c4, c5)
+       *
+       * will be represented here as c -> Set(c2, c3, c4, c5)
+       */
+      private var cChildren: Map[Identifier, Set[Identifier]] = Map().withDefaultValue(Set())
+
       // Returns all possible assignments to Bs in order to enumerate all possible programs
-      def allPrograms(): Set[Set[Identifier]] = {
+      def allPrograms(): Traversable[Set[Identifier]] = {
         def allChildPaths(b: Identifier): Stream[Set[Identifier]] = {
           if (isBClosed(b)) {
             Stream.empty
           } else {
             bTree.get(b) match {
               case Some(cToBs) =>
-                val streams = cToBs.values.map { children =>
+                val streams = cToBs.values.toSeq.map { children =>
                   children.toStream.flatMap(c => allChildPaths(c).map(l => l + b))
                 }
 
-                streams.reduceLeft{ (s1: Stream[Set[Identifier]], s2: Stream[Set[Identifier]]) => for(p1 <- s1; p2 <- s2) yield { p1 ++ p2 } }
+                StreamUtils.cartesianProduct(streams).map { ls =>
+                  ls.foldLeft(Set[Identifier]())(_ ++ _)
+                }
               case None =>
                 Stream.cons(Set(b), Stream.empty)
             }
@@ -93,10 +111,6 @@ case object CEGIS extends Rule("CEGIS") {
        * Compilation/Execution of programs
        */
 
-      // b1 => c == F(c2, c3) OR b2 => c == F(c4, c5) is represented here as c -> Set(c2, c3, c4, c5)
-      private var cChildren: Map[Identifier, Set[Identifier]] = Map().withDefaultValue(Set())
-
-
       type EvaluationResult = EvaluationResults.Result
 
       private var triedCompilation = false
@@ -159,7 +173,7 @@ case object CEGIS extends Rule("CEGIS") {
         // Map each x generated by the program to fresh xs passed as argument
         val newXs = p.xs.map(x => x -> FreshIdentifier(x.name, true).setType(x.getType))
 
-        val baseExpr = p.phi
+        val baseExpr = removeWitnesses(sctx.program)(p.phi)
 
         bssOrdered = bss.toSeq.sortBy(_.id)
 
@@ -235,6 +249,10 @@ case object CEGIS extends Rule("CEGIS") {
 
       }
 
+      /**
+       * Shrinks the non-deterministic program to the provided set of
+       * alternatives only
+       */
       def filterFor(remainingBss: Set[Identifier]): Seq[Expr] = {
         val filteredBss = remainingBss + initGuard
 
@@ -283,14 +301,18 @@ case object CEGIS extends Rule("CEGIS") {
         (pathConstraints ++ impliess).toSeq
       }
 
-      def unroll: (List[Expr], Set[Identifier]) = {
+      def unroll(finalUnrolling: Boolean): (List[Expr], Set[Identifier]) = {
         var newClauses      = List[Expr]()
         var newGuardedTerms = Map[Identifier, Set[Identifier]]()
         var newMappings     = Map[Identifier, (Identifier, Expr)]()
 
+
         for ((parentGuard, recIds) <- guardedTerms; recId <- recIds) {
 
-          val alts = grammar.getGenerators(recId.getType)
+          var alts = grammar.getGenerators(recId.getType)
+          if (finalUnrolling) {
+            alts = alts.filter(_.subTrees.isEmpty)
+          }
 
           val altsWithBranches = alts.map(alt => FreshIdentifier("B", true).setType(BooleanType) -> alt)
 
@@ -305,8 +327,15 @@ case object CEGIS extends Rule("CEGIS") {
 
           val pre = And(Seq(Or(failedPath +: bvs), Implies(failedPath, And(bvs.map(Not(_))))) ++ distinct)
 
+          var cBankCache = Map[TypeTree, Stream[Identifier]]()
+          def freshC(t: TypeTree): Stream[Identifier] = Stream.cons(FreshIdentifier("c", true).setType(t), freshC(t))
+          def getC(t: TypeTree, index: Int) = cBankCache.getOrElse(t, {
+            cBankCache += t -> freshC(t)
+            cBankCache(t)
+          })(index)
+
           val cases = for((bid, gen) <- altsWithBranches.toList) yield { // b1 => E(gen1, gen2)     [b1 -> {gen1, gen2}]
-            val rec = gen.subTrees.map(FreshIdentifier("c", true).setType(_))
+            val rec = for ((t, i) <- gen.subTrees.zipWithIndex) yield { getC(t, i) }
             val ex = gen.builder(rec.map(_.toVariable))
 
             if (!rec.isEmpty) {
@@ -325,6 +354,11 @@ case object CEGIS extends Rule("CEGIS") {
           newClauses = newClauses ::: pre :: cases
         }
 
+        sctx.reporter.ifDebug { printer =>
+          printer("Grammar so far:");
+          grammar.printGrammar(printer)
+        }
+
         //program  = And(program :: newClauses)
 
         mappings = mappings ++ newMappings
@@ -352,31 +386,33 @@ case object CEGIS extends Rule("CEGIS") {
         val initGuard = FreshIdentifier("START", true).setType(BooleanType)
 
         val ndProgram = new NonDeterministicProgram(p, initGuard)
-        var unrolings = 0
+        var unrolings = 1
         val maxUnrolings = 3
 
         val exSolverTo  = 2000L
         val cexSolverTo = 2000L
 
-        var baseExampleInputs: Seq[Seq[Expr]] = Seq()
+        var baseExampleInputs: ArrayBuffer[Seq[Expr]] = new ArrayBuffer[Seq[Expr]]()
 
         // We populate the list of examples with a predefined one
         sctx.reporter.debug("Acquiring list of examples")
 
         baseExampleInputs ++= p.getTests(sctx).map(_.ins).toSet
 
-        if (p.pc == BooleanLiteral(true)) {
-          baseExampleInputs = p.as.map(a => simplestValue(a.getType)) +: baseExampleInputs
+        val safePc = removeWitnesses(sctx.program)(p.pc)
+
+        if (safePc == BooleanLiteral(true)) {
+          baseExampleInputs += p.as.map(a => simplestValue(a.getType))
         } else {
           val solver = sctx.newSolver.setTimeout(exSolverTo)
 
-          solver.assertCnstr(p.pc)
+          solver.assertCnstr(safePc)
 
           try {
             solver.check match {
               case Some(true) =>
                 val model = solver.getModel
-                baseExampleInputs = p.as.map(a => model.getOrElse(a, simplestValue(a.getType))) +: baseExampleInputs
+                baseExampleInputs += p.as.map(a => model.getOrElse(a, simplestValue(a.getType)))
 
               case Some(false) =>
                 return RuleFailed()
@@ -396,25 +432,37 @@ case object CEGIS extends Rule("CEGIS") {
           }
         }
 
+        /**
+         * We generate tests for discarding potential programs
+         */
         val inputIterator: Iterator[Seq[Expr]] = if (useVanuatoo) {
-          new VanuatooDataGen(sctx.context, sctx.program).generateFor(p.as, p.pc, 20, 3000)
+          new VanuatooDataGen(sctx.context, sctx.program).generateFor(p.as, safePc, 20, 3000)
         } else {
-          new NaiveDataGen(sctx.context, sctx.program, evaluator).generateFor(p.as, p.pc, 20, 1000)
+          new NaiveDataGen(sctx.context, sctx.program, evaluator).generateFor(p.as, safePc, 20, 1000)
         }
 
         val cachedInputIterator = new Iterator[Seq[Expr]] {
           def next() = {
             val i = inputIterator.next()
-            baseExampleInputs = i +: baseExampleInputs
+            baseExampleInputs += i
             i
           }
 
           def hasNext() = inputIterator.hasNext
         }
 
+        val failedTestsStats = new MutableMap[Seq[Expr], Int]().withDefaultValue(0)
+
         def hasInputExamples() = baseExampleInputs.size > 0 || cachedInputIterator.hasNext
 
-        def allInputExamples() = baseExampleInputs.iterator ++ cachedInputIterator
+        var n = 1;
+        def allInputExamples() = {
+          if (n % 1000 == 0) {
+            baseExampleInputs = baseExampleInputs.sortBy(e => -failedTestsStats(e))
+          }
+          n += 1
+          baseExampleInputs.iterator ++ cachedInputIterator
+        }
 
         def checkForPrograms(programs: Set[Set[Identifier]]): RuleApplication = {
           for (prog <- programs) {
@@ -422,7 +470,7 @@ case object CEGIS extends Rule("CEGIS") {
             val res = Equals(Tuple(p.xs.map(Variable(_))), expr)
 
             val solver3 = sctx.newSolver.setTimeout(cexSolverTo)
-            solver3.assertCnstr(And(p.pc :: res :: Not(p.phi) :: Nil))
+            solver3.assertCnstr(And(safePc :: res :: Not(p.phi) :: Nil))
 
             try {
               solver3.check match {
@@ -444,8 +492,8 @@ case object CEGIS extends Rule("CEGIS") {
         // Keep track of collected cores to filter programs to test
         var collectedCores = Set[Set[Identifier]]()
 
-        val initExClause = And(p.pc :: p.phi :: Variable(initGuard) :: Nil)
-        val initCExClause = And(p.pc :: Not(p.phi) :: Variable(initGuard) :: Nil)
+        val initExClause = And(safePc :: p.phi :: Variable(initGuard) :: Nil)
+        val initCExClause = And(safePc :: Not(p.phi) :: Variable(initGuard) :: Nil)
 
         // solver1 is used for the initial SAT queries
         var solver1 = sctx.newSolver.setTimeout(exSolverTo)
@@ -466,7 +514,7 @@ case object CEGIS extends Rule("CEGIS") {
             var bssAssumptions = Set[Identifier]()
 
             if (!didFilterAlready) {
-              val (clauses, closedBs) = ndProgram.unroll
+              val (clauses, closedBs) = ndProgram.unroll(unrolings == maxUnrolings)
 
               bssAssumptions = closedBs
 
@@ -486,7 +534,7 @@ case object CEGIS extends Rule("CEGIS") {
 
             // Compute all programs that have not been excluded yet
             var prunedPrograms: Set[Set[Identifier]] = if (useCEPruning) {
-                ndProgram.allPrograms.filterNot(p => collectedCores.exists(c => c.subsetOf(p)))
+                ndProgram.allPrograms.filterNot(p => collectedCores.exists(c => c.subsetOf(p))).toSet
               } else {
                 Set()
               }
@@ -495,26 +543,33 @@ case object CEGIS extends Rule("CEGIS") {
 
             sctx.reporter.debug("#Programs: "+prunedPrograms.size)
 
+            var wrongPrograms = Set[Set[Identifier]]();
+
             // We further filter the set of working programs to remove those that fail on known examples
             if (useCEPruning && hasInputExamples() && ndProgram.canTest()) {
 
               for (p <- prunedPrograms if !interruptManager.isInterrupted()) {
-                if (!allInputExamples().forall(ndProgram.testForProgram(p))) {
-                  // This program failed on at least one example
-                  solver1.assertCnstr(Not(And(p.map(Variable(_)).toSeq)))
-                  prunedPrograms -= p
+                var valid = true
+                val examples = allInputExamples()
+                while(valid && examples.hasNext) {
+                  val e = examples.next()
+                  println("Running on "+e)
+                  if (!ndProgram.testForProgram(p)(e)) {
+                    failedTestsStats(e) += 1
+                    wrongPrograms += p
+                    prunedPrograms -= p
+                    valid = false;
+                  }
+                  println("Done")
                 }
-              }
 
-              if (prunedPrograms.isEmpty) {
-                needMoreUnrolling = true
+                if (wrongPrograms.size % 1000 == 0) {
+                  sctx.reporter.debug("..."+wrongPrograms.size)
+                }
               }
-
-              //println("Passing tests: "+prunedPrograms.size)
             }
 
             val nPassing = prunedPrograms.size
-
             sctx.reporter.debug("#Programs passing tests: "+nPassing)
 
             if (nPassing == 0) {
@@ -525,6 +580,9 @@ case object CEGIS extends Rule("CEGIS") {
                 case rs: RuleClosed =>
                   result = Some(rs)
                 case _ =>
+                  wrongPrograms.foreach { p =>
+                    solver1.assertCnstr(Not(And(p.map(Variable(_)).toSeq)))
+                  }
               }
             } else if (((nPassing < allPrograms*filterThreshold) || didFilterAlready) && useBssFiltering) {
               // We filter the Bss so that the formula we give to z3 is much smalled
@@ -548,6 +606,10 @@ case object CEGIS extends Rule("CEGIS") {
 
               solver1.assertCnstr(clause)
               solver2.assertCnstr(clause)
+            } else {
+              wrongPrograms.foreach { p =>
+                solver1.assertCnstr(Not(And(p.map(Variable(_)).toSeq)))
+              }
             }
 
             val bss = ndProgram.bss
@@ -592,7 +654,7 @@ case object CEGIS extends Rule("CEGIS") {
 
                         val newCE = p.as.map(valuateWithModel(invalidModel))
 
-                        baseExampleInputs = newCE +: baseExampleInputs
+                        baseExampleInputs += newCE
 
                         // Retest whether the newly found C-E invalidates all programs
                         if (useCEPruning && ndProgram.canTest) {
@@ -674,7 +736,7 @@ case object CEGIS extends Rule("CEGIS") {
             }
 
             unrolings += 1
-          } while(unrolings < maxUnrolings && result.isEmpty && !interruptManager.isInterrupted())
+          } while(unrolings <= maxUnrolings && result.isEmpty && !interruptManager.isInterrupted())
 
           result.getOrElse(RuleFailed())
 
diff --git a/src/main/scala/leon/synthesis/rules/GuidedCloser.scala b/src/main/scala/leon/synthesis/rules/GuidedCloser.scala
index d38be690679b53c59e0efa96d74f72a025659969..eb4843903ba4f9f06d8b8d26f679fddeacc1651e 100644
--- a/src/main/scala/leon/synthesis/rules/GuidedCloser.scala
+++ b/src/main/scala/leon/synthesis/rules/GuidedCloser.scala
@@ -40,7 +40,6 @@ case object GuidedCloser extends NormalizingRule("Guided Closer") {
       solver.assertCnstr(vc)
       val osol = solver.check match {
         case Some(false) =>
-          println("==== UNSAT ===")
           Some(Solution(BooleanLiteral(true), Set(), wrappedE, true))
 
         case None =>
diff --git a/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala b/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala
index c2e5d2c0cb2b55984a8f8d528853226feb878047..fe63e4ce5b83032b2e13f2309b30df0fdb1f6e0f 100644
--- a/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala
+++ b/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala
@@ -151,7 +151,7 @@ class ExpressionGrammar(ctx: LeonContext, prog: Program, inputs: Seq[Expr], curr
       }
     }
 
-    val funcs = visibleFunDefsFromMain(prog).toSeq.flatMap(getCandidates)
+    val funcs = functionsAvailable(prog).toSeq.flatMap(getCandidates)
 
     funcs.map{ tfd =>
       Generator[TypeTree, Expr](tfd.params.map(_.tpe), { sub => FunctionInvocation(tfd, sub) })
@@ -170,12 +170,12 @@ class ExpressionGrammar(ctx: LeonContext, prog: Program, inputs: Seq[Expr], curr
     }
   }
 
-  def printGrammar() {
+  def printGrammar(printer: String => Unit) {
     for ((t, gs) <- cache; g <- gs) {
       val subs = g.subTrees.map { tpe => FreshIdentifier(tpe.toString).setType(tpe).toVariable }
       val gen = g.builder(subs)
 
-      println(f"$t%30s ::= "+gen)
+      printer(f"$t%30s ::= "+gen)
     }
   }
 }
diff --git a/src/main/scala/leon/utils/StreamUtils.scala b/src/main/scala/leon/utils/StreamUtils.scala
index a0806f5c53968a900357e14688a3bbf2fefa27a7..cfc8d574546b76cdae92660be56063ffcaf58636 100644
--- a/src/main/scala/leon/utils/StreamUtils.scala
+++ b/src/main/scala/leon/utils/StreamUtils.scala
@@ -3,6 +3,19 @@
 package leon.utils
 
 object StreamUtils {
+  def interleave[T](streams : Seq[Stream[T]]) : Stream[T] = {
+    var ss = streams
+    while(!ss.isEmpty && ss.head.isEmpty) {
+      ss = ss.tail
+    }
+    if(ss.isEmpty) return Stream.empty
+    if(ss.size == 1) return ss(0)
+
+    // TODO: This circular-shifts the list. I'd be interested in a constant time
+    // operation. Perhaps simply by choosing the right data-structure?
+    Stream.cons(ss.head.head, interleave(ss.tail :+ ss.head.tail))
+  }
+
   def cartesianProduct[T](streams : Seq[Stream[T]]) : Stream[List[T]] = {
     val dimensions = streams.size
     val vectorizedStreams = streams.map(new VectorizedStream(_))
diff --git a/testcases/synthesis/repair/HeapSort/HeapSort2.scala b/testcases/synthesis/repair/HeapSort/HeapSort2.scala
index c33921bee19b368bd21a2308e63a8da6835c9e59..706d47074be2cfe83a651a0a7fce54e442a6b35e 100644
--- a/testcases/synthesis/repair/HeapSort/HeapSort2.scala
+++ b/testcases/synthesis/repair/HeapSort/HeapSort2.scala
@@ -50,7 +50,7 @@ object HeapSort {
     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)
@@ -58,7 +58,7 @@ object HeapSort {
     else
       Node(value, right, left)
   } ensuring { hasLeftistProperty(_) }
-*/
+
   def insert(element: Int, heap: Heap) : Heap = {
     require(hasLeftistProperty(heap))
 
diff --git a/testcases/synthesis/repair/PropLogic/PropLogic1.scala b/testcases/synthesis/repair/PropLogic/PropLogic1.scala
index 9668ca1a1bbfd288d27ca65728077e196c2ce3ba..8ff0b9f158014010b928fb838a3e8e28a20c9a0f 100644
--- a/testcases/synthesis/repair/PropLogic/PropLogic1.scala
+++ b/testcases/synthesis/repair/PropLogic/PropLogic1.scala
@@ -5,11 +5,11 @@ 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
+  case class Not(f: Formula) extends Formula
+  case class And(lhs : Formula, rhs : Formula) extends Formula
+  case class Or(lhs : Formula, rhs : Formula) extends Formula
 
   def size(f : Formula) : Int = { f match {
     case And(l,r) => 1 + size(l) + size(r)
@@ -33,7 +33,7 @@ object SemanticsPreservation {
     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 
+    case other => other
   }} ensuring { isNNF(_) }
 
   def isNNF(f : Formula) : Boolean = f match {