diff --git a/src/main/scala/leon/solvers/EnumerationSolver.scala b/src/main/scala/leon/solvers/EnumerationSolver.scala
index 35f1ed907decceb84d138914c253eb467040cb2e..39203125c95d2fff859a5046d21180d7b2b37398 100644
--- a/src/main/scala/leon/solvers/EnumerationSolver.scala
+++ b/src/main/scala/leon/solvers/EnumerationSolver.scala
@@ -14,7 +14,7 @@ import purescala.TypeTrees._
 import datagen._
 
 
-class EnumerationSolver(val context: LeonContext, val program: Program) extends Solver with Interruptible {
+class EnumerationSolver(val context: LeonContext, val program: Program) extends Solver with Interruptible with IncrementalSolver with NaiveAssumptionSolver {
   def name = "Enum"
 
   val maxTried = 10000;
@@ -23,14 +23,25 @@ class EnumerationSolver(val context: LeonContext, val program: Program) extends
 
   private var interrupted = false;
 
-  var freeVars    = List[Identifier]()
-  var constraints = List[Expr]()
+  var freeVars    = List[List[Identifier]](Nil)
+  var constraints = List[List[Expr]](Nil)
 
   def assertCnstr(expression: Expr): Unit = {
-    constraints = constraints :+ expression
+    constraints = (constraints.head :+ expression) :: constraints.tail
 
-    val newFreeVars = (variablesOf(expression) -- freeVars).toList
-    freeVars = freeVars ::: newFreeVars
+    val newFreeVars = (variablesOf(expression) -- freeVars.flatten).toList
+
+    freeVars = (freeVars.head ::: newFreeVars) :: freeVars.tail
+  }
+
+  def push() = {
+    freeVars = Nil :: freeVars
+    constraints = Nil :: constraints
+  }
+
+  def pop(lvl: Int) = {
+    freeVars = freeVars.drop(lvl)
+    constraints = constraints.drop(lvl)
   }
 
   private var modelMap = Map[Identifier, Expr]()
@@ -42,12 +53,14 @@ class EnumerationSolver(val context: LeonContext, val program: Program) extends
         None
       } else {
         modelMap = Map()
+        val allFreeVars = freeVars.reverse.flatten
+        val allConstraints = constraints.reverse.flatten
 
-        val it = datagen.get.generateFor(freeVars, And(constraints), 1, maxTried)
+        val it = datagen.get.generateFor(allFreeVars, And(allConstraints), 1, maxTried)
 
         if (it.hasNext) {
           val model = it.next
-          modelMap = (freeVars zip model).toMap
+          modelMap = (allFreeVars zip model).toMap
           Some(true)
         } else {
           None
diff --git a/src/main/scala/leon/solvers/NaiveAssumptionSolver.scala b/src/main/scala/leon/solvers/NaiveAssumptionSolver.scala
new file mode 100644
index 0000000000000000000000000000000000000000..8f20bb51a30376eb158ebddc41ae170ba43d4e8b
--- /dev/null
+++ b/src/main/scala/leon/solvers/NaiveAssumptionSolver.scala
@@ -0,0 +1,31 @@
+/* Copyright 2009-2014 EPFL, Lausanne */
+
+package leon
+package solvers
+
+import utils._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Trees._
+import purescala.Extractors._
+import purescala.TreeOps._
+import purescala.TypeTrees._
+
+trait NaiveAssumptionSolver extends AssumptionSolver {
+  self: IncrementalSolver =>
+
+  var lastBs = Set[Expr]()
+  def checkAssumptions(bs: Set[Expr]): Option[Boolean] = {
+    push()
+    lastBs = bs;
+    assertCnstr(And(bs.toSeq))
+    val res = check
+    pop()
+
+    res
+  }
+
+  def getUnsatCore(): Set[Expr] = {
+    lastBs
+  }
+}
diff --git a/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala b/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala
index 4aa880a7006adc972662083dc3387b7ac56e313c..7ddf0abcde8408ab09e61b326fe2e91acf3c4dba 100644
--- a/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala
+++ b/src/main/scala/leon/solvers/combinators/PortfolioSolver.scala
@@ -18,31 +18,32 @@ import scala.collection.mutable.{Map=>MutableMap}
 
 import ExecutionContext.Implicits.global
 
-class PortfolioSolver(val context: LeonContext, solvers: Seq[SolverFactory[Solver with Interruptible]])
-        extends Solver with Interruptible {
+class PortfolioSolver(val context: LeonContext, solvers: Seq[SolverFactory[AssumptionSolver with IncrementalSolver with Interruptible]])
+        extends Solver with IncrementalSolver with Interruptible with NaiveAssumptionSolver {
 
   val name = "Pfolio"
 
   var constraints = List[Expr]()
 
+  private var modelMap = Map[Identifier, Expr]()
+  private var solversInsts = solvers.map(_.getNewSolver)
+
   def assertCnstr(expression: Expr): Unit = {
-    constraints ::= expression
+    solversInsts.foreach(_.assertCnstr(expression))
   }
 
-  private var modelMap = Map[Identifier, Expr]()
-  private var solversInsts = Seq[Solver with Interruptible]()
+  def push(): Unit = {
+    solversInsts.foreach(_.push())
+  }
+
+  def pop(lvl: Int): Unit = {
+    solversInsts.foreach(_.pop(lvl))
+  }
 
   def check: Option[Boolean] = {
     modelMap = Map()
 
-    // create fresh solvers
-    solversInsts = solvers.map(_.getNewSolver)
-
-    // assert
-    solversInsts.foreach { s =>
-      s.assertCnstr(And(constraints.reverse))
-    }
-
+    context.reporter.debug("Running portfolio check")
     // solving
     val fs = solversInsts.map { s =>
       Future {
@@ -65,19 +66,20 @@ class PortfolioSolver(val context: LeonContext, solvers: Seq[SolverFactory[Solve
     // Block until all solvers finished
     Await.result(Future.fold(fs)(0){ (i, r) => i+1 }, 10.days);
 
-    solversInsts.foreach(_.free)
-
     res
   }
 
-  def getModel: Map[Identifier, Expr] = {
-    modelMap
-  }
-
   def free() = {
+    solversInsts.foreach(_.free)
+    solversInsts = Nil
+    modelMap = Map()
     constraints = Nil
   }
 
+  def getModel: Map[Identifier, Expr] = {
+    modelMap
+  }
+
   def interrupt(): Unit = {
     solversInsts.foreach(_.interrupt())
   }
diff --git a/src/main/scala/leon/synthesis/SynthesisContext.scala b/src/main/scala/leon/synthesis/SynthesisContext.scala
index d5d01b73b038d22b682485439988dbed135b52cf..b699c8bc8a3d7bfe09f5193d28d0c77c8449cc53 100644
--- a/src/main/scala/leon/synthesis/SynthesisContext.scala
+++ b/src/main/scala/leon/synthesis/SynthesisContext.scala
@@ -4,6 +4,7 @@ package leon
 package synthesis
 
 import solvers._
+import solvers.combinators.PortfolioSolver
 import solvers.z3._
 
 import purescala.Trees._
@@ -20,15 +21,29 @@ case class SynthesisContext(
   reporter: Reporter
 ) {
 
+  val allSolvers: Map[String, SolverFactory[SynthesisContext.SynthesisSolver]] = Map(
+    "fairz3" -> SolverFactory(() => new FairZ3Solver(context, program) with TimeoutAssumptionSolver),
+    "enum"   -> SolverFactory(() => new EnumerationSolver(context, program) with TimeoutAssumptionSolver)
+  )
+
+  val solversToUse = allSolvers.filterKeys(options.selectedSolvers)
+
+  val solverFactory: SolverFactory[SynthesisContext.SynthesisSolver] = if (solversToUse.isEmpty) {
+    reporter.fatalError("No solver selected. Aborting")
+  } else if (solversToUse.size == 1) {
+    solversToUse.values.head
+  } else {
+    SolverFactory( () => new PortfolioSolver(context, solversToUse.values.toSeq) with TimeoutAssumptionSolver)
+  }
+
   def newSolver: SynthesisContext.SynthesisSolver = {
-    new FairZ3Solver(context, program) with TimeoutAssumptionSolver
+    solverFactory.getNewSolver()
   }
 
   def newFastSolver: SynthesisContext.SynthesisSolver = {
     new UninterpretedZ3Solver(context, program) with TimeoutAssumptionSolver
   }
 
-  val solverFactory = SolverFactory(() => newSolver)
   val fastSolverFactory = SolverFactory(() => newFastSolver)
 
 }
diff --git a/src/main/scala/leon/synthesis/SynthesisOptions.scala b/src/main/scala/leon/synthesis/SynthesisOptions.scala
index 6287edbdddd7ef0545ab9cc29c86756d509a4b2b..90f0e3c84a39604b970f1af8e1dfaceea8dadb8b 100644
--- a/src/main/scala/leon/synthesis/SynthesisOptions.scala
+++ b/src/main/scala/leon/synthesis/SynthesisOptions.scala
@@ -14,6 +14,7 @@ case class SynthesisOptions(
   rules: Seq[Rule]                    = Rules.all ++ Heuristics.all,
   manualSearch: Boolean               = false,
   searchBound: Option[Int]            = None,
+  selectedSolvers: Set[String]        = Set("fairz3"),
 
   // Cegis related options
   cegisUseUninterpretedProbe: Boolean = false,
diff --git a/src/main/scala/leon/synthesis/SynthesisPhase.scala b/src/main/scala/leon/synthesis/SynthesisPhase.scala
index 47fee50c9ff5c34d3e085e84505ffcb9813221b6..d8756d3c8e10993c5a77eb878fa8815befe5706c 100644
--- a/src/main/scala/leon/synthesis/SynthesisPhase.scala
+++ b/src/main/scala/leon/synthesis/SynthesisPhase.scala
@@ -24,6 +24,7 @@ object SynthesisPhase extends LeonPhase[Program, Program] {
     LeonValueOptionDef("timeout",         "--timeout=T",       "Timeout after T seconds when searching for synthesis solutions .."),
     LeonValueOptionDef("costmodel",       "--costmodel=cm",    "Use a specific cost model for this search"),
     LeonValueOptionDef("functions",       "--functions=f1:f2", "Limit synthesis of choose found within f1,f2,.."),
+    LeonValueOptionDef("solvers",         "--solvers=s1,s2",   "Use solvers s1 and s2 (fairz3,enum)", default = Some("fairz3")),
     // CEGIS options
     LeonFlagOptionDef( "cegis:gencalls",   "--cegis:gencalls",      "Include function calls in CEGIS generators",      true),
     LeonFlagOptionDef( "cegis:unintprobe", "--cegis:unintprobe",    "Check for UNSAT without bloecks and with uninterpreted functions", false),
@@ -36,6 +37,8 @@ object SynthesisPhase extends LeonPhase[Program, Program] {
   def processOptions(ctx: LeonContext): SynthesisOptions = {
     var options = SynthesisOptions()
 
+    val allSolvers = Set("fairz3", "enum")
+
     for(opt <- ctx.options) opt match {
       case LeonFlagOption("manual", v) =>
         options = options.copy(manualSearch = v)
@@ -62,6 +65,13 @@ object SynthesisPhase extends LeonPhase[Program, Program] {
             ctx.reporter.fatalError(errorMsg)
         }
 
+      case LeonValueOption("solvers", ListValue(ss)) =>
+        val unknownSolvers = ss.toSet -- allSolvers
+        if (unknownSolvers.nonEmpty) {
+          ctx.reporter.error("Unknown solver(s): "+unknownSolvers.mkString(", ")+" (Available: "+allSolvers.mkString(", ")+")")
+        }
+        options = options.copy(selectedSolvers = Set() ++ ss)
+
       case v @ LeonValueOption("timeout", _) =>
         v.asInt(ctx).foreach { t =>
           options = options.copy(timeoutMs  = Some(t.toLong))
diff --git a/src/main/scala/leon/synthesis/rules/Ground.scala b/src/main/scala/leon/synthesis/rules/Ground.scala
index 9bfcd0383dba38e115fd4fca3706752ffc3a3757..96a1e125016ae8cc2cca320eb00cbc028bafdbf6 100644
--- a/src/main/scala/leon/synthesis/rules/Ground.scala
+++ b/src/main/scala/leon/synthesis/rules/Ground.scala
@@ -13,23 +13,26 @@ import purescala.Extractors._
 case object Ground extends Rule("Ground") {
   def instantiateOn(sctx: SynthesisContext, p: Problem): Traversable[RuleInstantiation] = {
     if (p.as.isEmpty) {
-
-      val solver = SimpleSolverAPI(new TimeoutSolverFactory(sctx.solverFactory, 5000L))
-
-      val tpe = TupleType(p.xs.map(_.getType))
-
-      val result = solver.solveSAT(p.phi) match {
-        case (Some(true), model) =>
-          val sol = Solution(BooleanLiteral(true), Set(), Tuple(p.xs.map(valuateWithModel(model))).setType(tpe))
-          Some(RuleInstantiation.immediateSuccess(p, this, sol))
-        case (Some(false), model) =>
-          val sol = Solution(BooleanLiteral(false), Set(), Error(p.phi+" is UNSAT!").setType(tpe))
-          Some(RuleInstantiation.immediateSuccess(p, this, sol))
-        case _ =>
-          None
-      }
-
-      result
+      List(new RuleInstantiation(p, this, SolutionBuilder.none, "Ground") {
+        def apply(sctx: SynthesisContext): RuleApplicationResult = {
+          val solver = SimpleSolverAPI(new TimeoutSolverFactory(sctx.solverFactory, 10000L))
+
+          val tpe = TupleType(p.xs.map(_.getType))
+
+          val result = solver.solveSAT(p.phi) match {
+            case (Some(true), model) =>
+              val sol = Solution(BooleanLiteral(true), Set(), Tuple(p.xs.map(valuateWithModel(model))).setType(tpe))
+              RuleSuccess(sol)
+            case (Some(false), model) =>
+              val sol = Solution(BooleanLiteral(false), Set(), Error(p.phi+" is UNSAT!").setType(tpe))
+              RuleSuccess(sol)
+            case _ =>
+              RuleApplicationImpossible
+          }
+
+          result
+        }
+      })
     } else {
       None
     }