diff --git a/src/main/java/leon/codegen/runtime/PartialLambda.java b/src/main/java/leon/codegen/runtime/FiniteLambda.java
similarity index 64%
rename from src/main/java/leon/codegen/runtime/PartialLambda.java
rename to src/main/java/leon/codegen/runtime/FiniteLambda.java
index b04036db5e9f81d1eaf7fa2c9a047bfef45a4df8..d249392384c1cf99cf6ebc5ae0677a4a41c73819 100644
--- a/src/main/java/leon/codegen/runtime/PartialLambda.java
+++ b/src/main/java/leon/codegen/runtime/FiniteLambda.java
@@ -4,15 +4,11 @@ package leon.codegen.runtime;
 
 import java.util.HashMap;
 
-public final class PartialLambda extends Lambda {
+public final class FiniteLambda extends Lambda {
   final HashMap<Tuple, Object> mapping = new HashMap<Tuple, Object>();
   private final Object dflt;
 
-  public PartialLambda() {
-    this(null);
-  }
-
-  public PartialLambda(Object dflt) {
+  public FiniteLambda(Object dflt) {
     super();
     this.dflt = dflt;
   }
@@ -26,18 +22,16 @@ public final class PartialLambda extends Lambda {
     Tuple tuple = new Tuple(args);
     if (mapping.containsKey(tuple)) {
       return mapping.get(tuple);
-    } else if (dflt != null) {
-      return dflt;
     } else {
-      throw new LeonCodeGenRuntimeException("Partial function apply on undefined arguments " + tuple);
+      return dflt;
     }
   }
 
   @Override
   public boolean equals(Object that) {
-    if (that != null && (that instanceof PartialLambda)) {
-      PartialLambda l = (PartialLambda) that;
-      return ((dflt != null && dflt.equals(l.dflt)) || (dflt == null && l.dflt == null)) && mapping.equals(l.mapping);
+    if (that != null && (that instanceof FiniteLambda)) {
+      FiniteLambda l = (FiniteLambda) that;
+      return dflt.equals(l.dflt) && mapping.equals(l.mapping);
     } else {
       return false;
     }
diff --git a/src/main/java/leon/codegen/runtime/LeonCodeGenRuntimeHenkinMonitor.java b/src/main/java/leon/codegen/runtime/LeonCodeGenRuntimeHenkinMonitor.java
index 597beec44b6a1a1719909e00ecb7d7916f0c7c03..76030a6129ac4c62115daf62162bffb658c891fd 100644
--- a/src/main/java/leon/codegen/runtime/LeonCodeGenRuntimeHenkinMonitor.java
+++ b/src/main/java/leon/codegen/runtime/LeonCodeGenRuntimeHenkinMonitor.java
@@ -32,8 +32,8 @@ public class LeonCodeGenRuntimeHenkinMonitor extends LeonCodeGenRuntimeMonitor {
 
   public List<Tuple> domain(Object obj, int type) {
     List<Tuple> domain = new LinkedList<Tuple>();
-    if (obj instanceof PartialLambda) {
-      PartialLambda l = (PartialLambda) obj;
+    if (obj instanceof FiniteLambda) {
+      FiniteLambda l = (FiniteLambda) obj;
       for (Tuple key : l.mapping.keySet()) {
         domain.add(key);
       }
diff --git a/src/main/scala/leon/Main.scala b/src/main/scala/leon/Main.scala
index db49d0425e39ac888badb90c97aa7c8432d0ee96..4eb880cee176ce56f74dbf770fb2a540faf16ea2 100644
--- a/src/main/scala/leon/Main.scala
+++ b/src/main/scala/leon/Main.scala
@@ -34,7 +34,7 @@ object Main {
 
   // Add whatever you need here.
   lazy val allComponents : Set[LeonComponent] = allPhases.toSet ++ Set(
-    solvers.z3.FairZ3Component, MainComponent, SharedOptions, solvers.smtlib.SMTLIBCVC4Component, solvers.isabelle.Component
+    solvers.combinators.UnrollingProcedure, MainComponent, SharedOptions, solvers.smtlib.SMTLIBCVC4Component, solvers.isabelle.Component
   )
 
   /*
diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala
index d99a9a1a951edeb2260874d004e911de9628ab7d..d703c736d6c3442ae8ea23710287ba148389d876 100644
--- a/src/main/scala/leon/codegen/CodeGeneration.scala
+++ b/src/main/scala/leon/codegen/CodeGeneration.scala
@@ -74,7 +74,7 @@ trait CodeGeneration {
   private[codegen] val CaseClassClass            = "leon/codegen/runtime/CaseClass"
   private[codegen] val LambdaClass               = "leon/codegen/runtime/Lambda"
   private[codegen] val ForallClass               = "leon/codegen/runtime/Forall"
-  private[codegen] val PartialLambdaClass        = "leon/codegen/runtime/PartialLambda"
+  private[codegen] val FiniteLambdaClass         = "leon/codegen/runtime/FiniteLambda"
   private[codegen] val ErrorClass                = "leon/codegen/runtime/LeonCodeGenRuntimeException"
   private[codegen] val InvalidForallClass        = "leon/codegen/runtime/LeonCodeGenQuantificationException"
   private[codegen] val ImpossibleEvaluationClass = "leon/codegen/runtime/LeonCodeGenEvaluationException"
@@ -1133,21 +1133,16 @@ trait CodeGeneration {
         ch << InvokeVirtual(LambdaClass, "apply", s"([L$ObjectClass;)L$ObjectClass;")
         mkUnbox(app.getType, ch)
 
-      case p @ PartialLambda(mapping, optDflt, _) =>
-        ch << New(PartialLambdaClass) << DUP
-        optDflt match {
-          case Some(dflt) =>
-            mkBoxedExpr(dflt, ch)
-            ch << InvokeSpecial(PartialLambdaClass, constructorName, s"(L$ObjectClass;)V")
-          case None =>
-            ch << InvokeSpecial(PartialLambdaClass, constructorName, "()V")
-        }
+      case p @ FiniteLambda(mapping, dflt, _) =>
+        ch << New(FiniteLambdaClass) << DUP
+        mkBoxedExpr(dflt, ch)
+        ch << InvokeSpecial(FiniteLambdaClass, constructorName, s"(L$ObjectClass;)V")
 
         for ((es,v) <- mapping) {
           ch << DUP
           mkTuple(es, ch)
           mkBoxedExpr(v, ch)
-          ch << InvokeVirtual(PartialLambdaClass, "add", s"(L$TupleClass;L$ObjectClass;)V")
+          ch << InvokeVirtual(FiniteLambdaClass, "add", s"(L$TupleClass;L$ObjectClass;)V")
         }
 
       case l @ Lambda(args, body) =>
@@ -1407,6 +1402,8 @@ trait CodeGeneration {
         ch << InvokeSpecial(ErrorClass, constructorName, "(Ljava/lang/String;)V")
         ch << ATHROW
 
+      case forall @ Forall(fargs, body) =>
+
       case choose: Choose =>
         val prob = synthesis.Problem.fromSpec(choose.pred)
 
diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala
index 18a0b607589f334fa021ab31ab4163201b5ba888..6af6aa9e50686244581de931f793f00c34c94ed9 100644
--- a/src/main/scala/leon/codegen/CompilationUnit.scala
+++ b/src/main/scala/leon/codegen/CompilationUnit.scala
@@ -237,12 +237,8 @@ class CompilationUnit(val ctx: LeonContext,
       }
       m
 
-    case f @ PartialLambda(mapping, dflt, _) =>
-      val l = if (dflt.isDefined) {
-        new leon.codegen.runtime.PartialLambda(dflt.get)
-      } else {
-        new leon.codegen.runtime.PartialLambda()
-      }
+    case f @ FiniteLambda(mapping, dflt, _) =>
+      val l = new leon.codegen.runtime.FiniteLambda(dflt)
 
       for ((ks,v) <- mapping) {
         // Force tuple even with 1/0 elems.
diff --git a/src/main/scala/leon/datagen/VanuatooDataGen.scala b/src/main/scala/leon/datagen/VanuatooDataGen.scala
index af315aacade7e06eeb346dcbb94f56f53f9d5f87..1975400500b741a8fb59fe953b72faf08bf8968e 100644
--- a/src/main/scala/leon/datagen/VanuatooDataGen.scala
+++ b/src/main/scala/leon/datagen/VanuatooDataGen.scala
@@ -131,7 +131,7 @@ class VanuatooDataGen(ctx: LeonContext, p: Program) extends DataGenerator {
           Constructor[Expr, TypeTree](subs, ft, { s =>
             val grouped = s.grouped(from.size + 1).toSeq
             val mapping = grouped.init.map { case args :+ res => (args -> res) }
-            PartialLambda(mapping, Some(grouped.last.last), ft)
+            FiniteLambda(mapping, grouped.last.last, ft)
           }, ft.asString(ctx) + "@" + size)
         }
         constructors += ft -> cs
diff --git a/src/main/scala/leon/evaluators/AngelicEvaluator.scala b/src/main/scala/leon/evaluators/AngelicEvaluator.scala
index 99d704f67c7485ba8e00727c4edcc5d30644b4cc..57f233cf44caa63dd587e0d792eb33ec62b89d55 100644
--- a/src/main/scala/leon/evaluators/AngelicEvaluator.scala
+++ b/src/main/scala/leon/evaluators/AngelicEvaluator.scala
@@ -22,9 +22,6 @@ class AngelicEvaluator(underlying: NDEvaluator)
     case other@(RuntimeError(_) | EvaluatorError(_)) =>
       other.asInstanceOf[Result[Nothing]]
   }
-
-  /** Checks that `model |= expr` and that quantifications are all valid */
-  def check(expr: Expr, model: Model): CheckResult = underlying.check(expr, model)
 }
 
 class DemonicEvaluator(underlying: NDEvaluator)
@@ -42,7 +39,4 @@ class DemonicEvaluator(underlying: NDEvaluator)
     case other@(RuntimeError(_) | EvaluatorError(_)) =>
       other.asInstanceOf[Result[Nothing]]
   }
-
-  /** Checks that `model |= expr` and that quantifications are all valid */
-  def check(expr: Expr, model: Model): CheckResult = underlying.check(expr, model)
-}
\ No newline at end of file
+}
diff --git a/src/main/scala/leon/evaluators/CodeGenEvaluator.scala b/src/main/scala/leon/evaluators/CodeGenEvaluator.scala
index e6bb722aedde0b6faecdcc2bf11651c0a7353859..f63bed50fb2835eca2ebf91102992b0e5951968e 100644
--- a/src/main/scala/leon/evaluators/CodeGenEvaluator.scala
+++ b/src/main/scala/leon/evaluators/CodeGenEvaluator.scala
@@ -38,50 +38,6 @@ class CodeGenEvaluator(ctx: LeonContext, val unit : CompilationUnit) extends Eva
     }
   }
 
-
-  def check(expression: Expr, fullModel: solvers.Model) : CheckResult = {
-    val (_, assign) = fullModel.toSeq.partition {
-      case (id, v) => unit.abstractFunDefs(id)
-    }
-
-    compileExpr(expression, assign.map(_._1)).map { ce =>
-      ctx.timers.evaluators.codegen.runtime.start()
-
-      try {
-        val res = ce.eval(fullModel, check = true)
-
-        if (res == BooleanLiteral(true)) {
-          EvaluationResults.CheckSuccess
-        } else {
-          EvaluationResults.CheckValidityFailure
-        }
-      } catch {
-        case e : ArithmeticException =>
-          EvaluationResults.CheckRuntimeFailure(e.getMessage)
-
-        case e : ArrayIndexOutOfBoundsException =>
-          EvaluationResults.CheckRuntimeFailure(e.getMessage)
-
-        case e : LeonCodeGenRuntimeException =>
-          EvaluationResults.CheckRuntimeFailure(e.getMessage)
-
-        case e : LeonCodeGenEvaluationException =>
-          EvaluationResults.CheckRuntimeFailure(e.getMessage)
-
-        case e : java.lang.ExceptionInInitializerError =>
-          EvaluationResults.CheckRuntimeFailure(e.getException.getMessage) 
-
-        case so : java.lang.StackOverflowError =>
-          EvaluationResults.CheckRuntimeFailure("Stack overflow")
-
-        case e : LeonCodeGenQuantificationException =>
-          EvaluationResults.CheckQuantificationFailure(e.getMessage)
-      } finally {
-        ctx.timers.evaluators.codegen.runtime.stop()
-      }
-    }.getOrElse(EvaluationResults.CheckRuntimeFailure("Couldn't compile expression."))
-  }
-
   def eval(expression: Expr, model: solvers.Model) : EvaluationResult = {
     compile(expression, model.toSeq.map(_._1)).map { e => 
       ctx.timers.evaluators.codegen.runtime.start()
diff --git a/src/main/scala/leon/evaluators/ContextualEvaluator.scala b/src/main/scala/leon/evaluators/ContextualEvaluator.scala
index eb57bbbf3550d8d177f92188d12d1ff3a3abbbd5..76f5c500890135fc7fc7d3e75814c2d92020e2b0 100644
--- a/src/main/scala/leon/evaluators/ContextualEvaluator.scala
+++ b/src/main/scala/leon/evaluators/ContextualEvaluator.scala
@@ -48,30 +48,6 @@ abstract class ContextualEvaluator(ctx: LeonContext, prog: Program, val maxSteps
     }
   }
 
-  def check(ex: Expr, model: Model): CheckResult = {
-    assert(ex.getType == BooleanType, "Can't check non-boolean expression " + ex.asString)
-    try {
-      lastGC = Some(initGC(model, check = true))
-      ctx.timers.evaluators.recursive.runtime.start()
-      val res = e(ex)(initRC(model.toMap), lastGC.get)
-      if (res == BooleanLiteral(true)) EvaluationResults.CheckSuccess
-      else EvaluationResults.CheckValidityFailure
-    } catch {
-      case so: StackOverflowError =>
-        EvaluationResults.CheckRuntimeFailure("Stack overflow")
-      case e @ EvalError(msg) =>
-        EvaluationResults.CheckRuntimeFailure(msg)
-      case e @ RuntimeError(msg) =>
-        EvaluationResults.CheckRuntimeFailure(msg)
-      case jre: java.lang.RuntimeException =>
-        EvaluationResults.CheckRuntimeFailure(jre.getMessage)
-      case qe @ QuantificationError(msg) =>
-        EvaluationResults.CheckQuantificationFailure(msg)
-    } finally {
-      ctx.timers.evaluators.recursive.runtime.stop()
-    }
-  }
-
   protected def e(expr: Expr)(implicit rctx: RC, gctx: GC): Value
 
   def typeErrorMsg(tree : Expr, expected : TypeTree) : String = s"Type error : expected ${expected.asString}, found ${tree.asString} of type ${tree.getType}."
@@ -138,4 +114,4 @@ private[evaluators] trait CEvalHelpers {
 
 
 
-}
\ No newline at end of file
+}
diff --git a/src/main/scala/leon/evaluators/EvaluationResults.scala b/src/main/scala/leon/evaluators/EvaluationResults.scala
index 18f7a0c92d448f98c8f6a271d91e021a649e3b9c..b9cbecdde4cdd31b2b29dcb82fdd23c50aaf9a24 100644
--- a/src/main/scala/leon/evaluators/EvaluationResults.scala
+++ b/src/main/scala/leon/evaluators/EvaluationResults.scala
@@ -15,21 +15,4 @@ object EvaluationResults {
 
   /** Represents an evaluation that failed (in the evaluator). */
   case class EvaluatorError(message : String) extends Result(None)
-
-  /** Results of checking proposition evaluation.
-   *  Useful for verification of model validity in presence of quantifiers. */
-  sealed abstract class CheckResult(val success: Boolean)
-
-  /** Successful proposition evaluation (model |= expr) */
-  case object CheckSuccess extends CheckResult(true)
-
-  /** Check failed with `model |= !expr` */
-  case object CheckValidityFailure extends CheckResult(false)
-
-  /** Check failed due to evaluation or runtime errors.
-   *  @see [[RuntimeError]] and [[EvaluatorError]] */
-  case class CheckRuntimeFailure(msg: String) extends CheckResult(false)
-
-  /** Check failed due to inconsistence of model with quantified propositions. */
-  case class CheckQuantificationFailure(msg: String) extends CheckResult(false)
 }
diff --git a/src/main/scala/leon/evaluators/Evaluator.scala b/src/main/scala/leon/evaluators/Evaluator.scala
index ff0f35f1241547d66f81f0b341fca508276b40ea..400409577ac7aebf490d8a961ac44c67036989c7 100644
--- a/src/main/scala/leon/evaluators/Evaluator.scala
+++ b/src/main/scala/leon/evaluators/Evaluator.scala
@@ -18,7 +18,6 @@ abstract class Evaluator(val context: LeonContext, val program: Program) extends
   type Value
 
   type EvaluationResult = EvaluationResults.Result[Value]
-  type CheckResult = EvaluationResults.CheckResult
 
   /** Evaluates an expression, using [[Model.mapping]] as a valuation function for the free variables. */
   def eval(expr: Expr, model: Model) : EvaluationResult
@@ -31,9 +30,6 @@ abstract class Evaluator(val context: LeonContext, val program: Program) extends
   /** Evaluates a ground expression. */
   final def eval(expr: Expr) : EvaluationResult = eval(expr, Model.empty)
 
-  /** Checks that `model |= expr` and that quantifications are all valid */
-  def check(expr: Expr, model: Model) : CheckResult
-
   /** Compiles an expression into a function, where the arguments are the free variables in the expression.
     * `argorder` specifies in which order the arguments should be passed.
     * The default implementation uses the evaluation function each time, but evaluators are free
diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
index e4eeb2e8ca42220f39a9adb00263196046d91c60..ad705725688dbccc5c858fd745980a9719c0ad53 100644
--- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
@@ -28,7 +28,8 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
   lazy val scalaEv = new ScalacEvaluator(this, ctx, prog)
 
   protected var clpCache = Map[(Choose, Seq[Expr]), Expr]()
-  
+  protected var frlCache = Map[(Forall, Seq[Expr]), Expr]()
+
   private var evaluationFailsOnChoose = false
   /** Sets the flag if when encountering a Choose, it should fail instead of solving it. */
   def setEvaluationFailOnChoose(b: Boolean) = { this.evaluationFailsOnChoose = b; this }
@@ -50,13 +51,10 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
           val newArgs = args.map(e)
           val mapping = l.paramSubst(newArgs)
           e(body)(rctx.withNewVars(mapping), gctx)
-        case PartialLambda(mapping, dflt, _) =>
+        case FiniteLambda(mapping, dflt, _) =>
           mapping.find { case (pargs, res) =>
             (args zip pargs).forall(p => e(Equals(p._1, p._2)) == BooleanLiteral(true))
-          }.map(_._2).orElse(dflt).getOrElse {
-            throw EvalError("Cannot apply partial lambda outside of domain : " +
-              args.map(e(_).asString(ctx)).mkString("(", ", ", ")"))
-          }
+          }.map(_._2).getOrElse(dflt)
         case f =>
           throw EvalError("Cannot apply non-lambda function " + f.asString)
       }
@@ -187,7 +185,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       (lv,rv) match {
         case (FiniteSet(el1, _),FiniteSet(el2, _)) => BooleanLiteral(el1 == el2)
         case (FiniteMap(el1, _, _),FiniteMap(el2, _, _)) => BooleanLiteral(el1.toSet == el2.toSet)
-        case (PartialLambda(m1, d1, _), PartialLambda(m2, d2, _)) => BooleanLiteral(m1.toSet == m2.toSet && d1 == d2)
+        case (FiniteLambda(m1, d1, _), FiniteLambda(m2, d2, _)) => BooleanLiteral(m1.toSet == m2.toSet && d1 == d2)
         case _ => BooleanLiteral(lv == rv)
       }
 
@@ -509,11 +507,78 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       }
       newLambda
 
-    case PartialLambda(mapping, dflt, tpe) =>
-      PartialLambda(mapping.map(p => p._1.map(e) -> e(p._2)), dflt.map(e), tpe)
+    case FiniteLambda(mapping, dflt, tpe) =>
+      FiniteLambda(mapping.map(p => p._1.map(e) -> e(p._2)), e(dflt), tpe)
+
+    case f @ Forall(fargs, body) =>
+
+      implicit val debugSection = utils.DebugSectionVerification
+
+      ctx.reporter.debug("Executing forall!")
+
+      val mapping = variablesOf(f).map(id => id -> rctx.mappings(id)).toMap
+      val context = mapping.toSeq.sortBy(_._1.uniqueName).map(_._2)
+      frlCache.getOrElse((f, context), {
+        val tStart = System.currentTimeMillis
+
+        val solverf = SolverFactory.getFromSettings(ctx, program)
+        val solver  = solverf.getNewSolver()
+
+        try {
+          val cnstr = Not(replaceFromIDs(mapping, body))
+          solver.assertCnstr(cnstr)
+
+          gctx.model match {
+            case pm: HenkinModel =>
+              val quantifiers = fargs.map(_.id).toSet
+              val quorums = extractQuorums(body, quantifiers)
+
+              val domainCnstr = orJoin(quorums.map { quorum =>
+                val quantifierDomains = quorum.flatMap { case (path, caller, args) =>
+                  val matcher = e(expr) match {
+                    case l: Lambda => gctx.lambdas.getOrElse(l, l)
+                    case ev => ev
+                  }
+
+                  val domain = pm.domain(matcher)
+                  args.zipWithIndex.flatMap {
+                    case (Variable(id),idx) if quantifiers(id) =>
+                      Some(id -> domain.map(cargs => path -> cargs(idx)))
+                    case _ => None
+                  }
+                }
+
+                val domainMap = quantifierDomains.groupBy(_._1).mapValues(_.map(_._2).flatten)
+                andJoin(domainMap.toSeq.map { case (id, dom) =>
+                  orJoin(dom.toSeq.map { case (path, value) => and(path, Equals(Variable(id), value)) })
+                })
+              })
+
+              solver.assertCnstr(domainCnstr)
+
+            case _ =>
+          }
+
+          solver.check match {
+            case Some(negRes) =>
+              val total = System.currentTimeMillis-tStart
+              val res = BooleanLiteral(!negRes)
+              ctx.reporter.debug("Verification took "+total+"ms")
+              ctx.reporter.debug("Finished forall evaluation with: "+res)
 
-    case Forall(fargs, body) =>
-      evalForall(fargs.map(_.id).toSet, body)
+              frlCache += (f, context) -> res
+              res
+            case _ =>
+              throw RuntimeError("Timeout exceeded")
+          }
+        } catch {
+          case e: Throwable =>
+            throw EvalError("Runtime verification of forall failed: "+e.getMessage)
+        } finally {
+          solverf.reclaim(solver)
+          solverf.shutdown()
+        }
+      })
 
     case ArrayLength(a) =>
       val FiniteArray(_, _, IntLiteral(length)) = e(a)
@@ -555,6 +620,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       case (l,r) =>
         throw EvalError(typeErrorMsg(l, MapType(r.getType, g.getType)))
     }
+
     case u @ MapUnion(m1,m2) => (e(m1), e(m2)) match {
       case (f1@FiniteMap(ss1, _, _), FiniteMap(ss2, _, _)) =>
         val newSs = ss1 ++ ss2
@@ -563,6 +629,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       case (l, r) =>
         throw EvalError(typeErrorMsg(l, m1.getType))
     }
+
     case i @ MapIsDefinedAt(m,k) => (e(m), e(k)) match {
       case (FiniteMap(ss, _, _), e) => BooleanLiteral(ss.contains(e))
       case (l, r) => throw EvalError(typeErrorMsg(l, m.getType))
@@ -590,7 +657,6 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         val solverf = SolverFactory.getFromSettings(ctx, program)
         val solver  = solverf.getNewSolver()
 
-
         try {
           val eqs = p.as.map {
             case id =>
@@ -719,142 +785,5 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         } yield (caze, r)
     }
   }
-
-
-  protected def evalForall(quants: Set[Identifier], body: Expr, check: Boolean = true)(implicit rctx: RC, gctx: GC): Expr = {
-    val henkinModel: HenkinModel = gctx.model match {
-      case hm: HenkinModel => hm
-      case _ => throw EvalError("Can't evaluate foralls without henkin model")
-}
-
-    val TopLevelAnds(conjuncts) = body
-    e(andJoin(conjuncts.flatMap { conj =>
-      val vars = variablesOf(conj)
-      val quantified = quants.filter(vars)
-
-      extractQuorums(conj, quantified).flatMap { case (qrm, others) =>
-        val quorum = qrm.toList
-
-        if (quorum.exists { case (TopLevelAnds(paths), _, _) =>
-          val p = andJoin(paths.filter(path => (variablesOf(path) & quantified).isEmpty))
-          e(p) == BooleanLiteral(false)
-        }) List(BooleanLiteral(true)) else {
-
-          var mappings: Seq[(Identifier, Int, Int)] = Seq.empty
-          var constraints: Seq[(Expr, Int, Int)] = Seq.empty
-          var equalities: Seq[((Int, Int), (Int, Int))] = Seq.empty
-
-          for (((_, expr, args), qidx) <- quorum.zipWithIndex) {
-            val (qmappings, qconstraints) = args.zipWithIndex.partition {
-              case (Variable(id),aidx) => quantified(id)
-              case _ => false
-            }
-
-            mappings ++= qmappings.map(p => (p._1.asInstanceOf[Variable].id, qidx, p._2))
-            constraints ++= qconstraints.map(p => (p._1, qidx, p._2))
-          }
-
-          val mapping = for ((id, es) <- mappings.groupBy(_._1)) yield {
-            val base :: others = es.toList.map(p => (p._2, p._3))
-            equalities ++= others.map(p => base -> p)
-            (id -> base)
-          }
-
-          def domain(expr: Expr): Set[Seq[Expr]] = henkinModel.domain(e(expr) match {
-            case l: Lambda => gctx.lambdas.getOrElse(l, l)
-            case ev => ev
-          })
-
-          val argSets = quorum.foldLeft[List[Seq[Seq[Expr]]]](List(Seq.empty)) {
-            case (acc, (_, expr, _)) => acc.flatMap(s => domain(expr).map(d => s :+ d))
-          }
-
-          argSets.map { args =>
-            val argMap: Map[(Int, Int), Expr] = args.zipWithIndex.flatMap {
-              case (a, qidx) => a.zipWithIndex.map { case (e, aidx) => (qidx, aidx) -> e }
-            }.toMap
-
-            val map = mapping.map { case (id, key) => id -> argMap(key) }
-            val enabler = andJoin(constraints.map {
-              case (e, qidx, aidx) => Equals(e, argMap(qidx -> aidx))
-            } ++ equalities.map {
-              case (k1, k2) => Equals(argMap(k1), argMap(k2))
-            })
-
-            val ctx = rctx.withNewVars(map)
-            if (e(enabler)(ctx, gctx) == BooleanLiteral(true)) {
-              if (gctx.check) {
-                for ((b,caller,args) <- others if e(b)(ctx, gctx) == BooleanLiteral(true)) {
-                  val evArgs = args.map(arg => e(arg)(ctx, gctx))
-                  if (!domain(caller)(evArgs))
-                    throw QuantificationError("Unhandled transitive implication in " + replaceFromIDs(map, conj))
-                }
-              }
-
-              e(conj)(ctx, gctx)
-            } else {
-              BooleanLiteral(true)
-            }
-          }
-        }
-      }
-    })) match {
-      case res @ BooleanLiteral(true) if check =>
-        if (gctx.check) {
-          checkForall(quants, body) match {
-            case status: ForallInvalid =>
-              throw QuantificationError("Invalid forall: " + status.getMessage)
-            case _ =>
-              // make sure the body doesn't contain matches or lets as these introduce new locals
-              val cleanBody = expandLets(matchToIfThenElse(body))
-              val calls = new CollectorWithPaths[(Expr, Seq[Expr], Seq[Expr])] {
-                def collect(e: Expr, path: Seq[Expr]): Option[(Expr, Seq[Expr], Seq[Expr])] = e match {
-                  case QuantificationMatcher(IsTyped(caller, _: FunctionType), args) => Some((caller, args, path))
-                  case _ => None
-                }
-
-                override def rec(e: Expr, path: Seq[Expr]): Expr = e match {
-                  case l : Lambda => l
-                  case _ => super.rec(e, path)
-                }
-              }.traverse(cleanBody)
-
-              for ((caller, appArgs, paths) <- calls) {
-                val path = andJoin(paths.filter(expr => (variablesOf(expr) & quants).isEmpty))
-                if (e(path) == BooleanLiteral(true)) e(caller) match {
-                  case _: PartialLambda => // OK
-                  case l: Lambda =>
-                    val nl @ Lambda(args, body) = gctx.lambdas.getOrElse(l, l)
-                    val lambdaQuantified = (appArgs zip args).collect {
-                      case (Variable(id), vd) if quants(id) => vd.id
-                    }.toSet
-
-                    if (lambdaQuantified.nonEmpty) {
-                      checkForall(lambdaQuantified, body) match {
-                        case lambdaStatus: ForallInvalid =>
-                          throw QuantificationError("Invalid forall: " + lambdaStatus.getMessage)
-                        case _ => // do nothing
-                      }
-
-                      val axiom = Equals(Application(nl, args.map(_.toVariable)), nl.body)
-                      if (evalForall(args.map(_.id).toSet, axiom, check = false) == BooleanLiteral(false)) {
-                        throw QuantificationError("Unaxiomatic lambda " + l)
-                      }
-                    }
-                  case f =>
-                    throw EvalError("Cannot apply non-lambda function " + f.asString)
-                }
-              }
-          }
-        }
-
-        res
-
-      // `res == false` means the quantification is valid since there effectivelly must
-      // exist an input for which the proposition doesn't hold
-      case res => res
-    }
-  }
-
 }
 
diff --git a/src/main/scala/leon/evaluators/StreamEvaluator.scala b/src/main/scala/leon/evaluators/StreamEvaluator.scala
index 3035e6541e1f48bf51c472415aaafe7b0d1d02b0..feb0dd7f2590674ca231a29a8f7e8ba91945a2e3 100644
--- a/src/main/scala/leon/evaluators/StreamEvaluator.scala
+++ b/src/main/scala/leon/evaluators/StreamEvaluator.scala
@@ -37,12 +37,12 @@ class StreamEvaluator(ctx: LeonContext, prog: Program)
           case l @ Lambda(params, body) =>
             val mapping = l.paramSubst(newArgs)
             e(body)(rctx.withNewVars(mapping), gctx).distinct
-          case PartialLambda(mapping, _, _) =>
+          case FiniteLambda(mapping, dflt, _) =>
             // FIXME
-            mapping.collectFirst {
+            Stream(mapping.collectFirst {
               case (pargs, res) if (newArgs zip pargs).forall { case (f, r) => f == r } =>
                 res
-            }.toStream
+            }.getOrElse(dflt))
           case _ =>
             Stream()
         }
@@ -127,7 +127,7 @@ class StreamEvaluator(ctx: LeonContext, prog: Program)
       Stream(replaceFromIDs(mapping, nl))
 
     // FIXME
-    case PartialLambda(mapping, tpe, df) =>
+    case FiniteLambda(mapping, dflt, tpe) =>
       def solveOne(pair: (Seq[Expr], Expr)) = {
         val (args, res) = pair
         for {
@@ -135,7 +135,7 @@ class StreamEvaluator(ctx: LeonContext, prog: Program)
           r  <- e(res)
         } yield as -> r
       }
-      cartesianProduct(mapping map solveOne) map (PartialLambda(_, tpe, df)) // FIXME!!!
+      cartesianProduct(mapping map solveOne) map (FiniteLambda(_, dflt, tpe)) // FIXME!!!
 
     case f @ Forall(fargs, TopLevelAnds(conjuncts)) =>
       Stream() // FIXME
@@ -337,7 +337,7 @@ class StreamEvaluator(ctx: LeonContext, prog: Program)
       (lv, rv) match {
         case (FiniteSet(el1, _), FiniteSet(el2, _)) => BooleanLiteral(el1 == el2)
         case (FiniteMap(el1, _, _), FiniteMap(el2, _, _)) => BooleanLiteral(el1.toSet == el2.toSet)
-        case (PartialLambda(m1, _, d1), PartialLambda(m2, _, d2)) => BooleanLiteral(m1.toSet == m2.toSet && d1 == d2)
+        case (FiniteLambda(m1, d1, _), FiniteLambda(m2, d2, _)) => BooleanLiteral(m1.toSet == m2.toSet && d1 == d2)
         case _ => BooleanLiteral(lv == rv)
       }
 
diff --git a/src/main/scala/leon/purescala/ExprOps.scala b/src/main/scala/leon/purescala/ExprOps.scala
index 19d20604ddc9ff9c3187c2fe24ee50f46e658850..ce6b7fb4d863f290dd087074e8734cdc6f8b5013 100644
--- a/src/main/scala/leon/purescala/ExprOps.scala
+++ b/src/main/scala/leon/purescala/ExprOps.scala
@@ -884,7 +884,7 @@ object ExprOps extends { val Deconstructor = Operator } with SubTreeOps[Expr] {
       GenericValue(tp, 0)
 
     case ft @ FunctionType(from, to) =>
-      PartialLambda(Seq.empty, Some(simplestValue(to)), ft)
+      FiniteLambda(Seq.empty, simplestValue(to), ft)
 
     case _ => throw LeonFatalError("I can't choose simplest value for type " + tpe)
   }
diff --git a/src/main/scala/leon/purescala/Expressions.scala b/src/main/scala/leon/purescala/Expressions.scala
index 88edef68586474c24e7a13b70a22e9beed7441b8..609f5cda04dcd1a1e5e0e55d1c5f01475236fd94 100644
--- a/src/main/scala/leon/purescala/Expressions.scala
+++ b/src/main/scala/leon/purescala/Expressions.scala
@@ -227,7 +227,7 @@ object Expressions {
     }
   }
 
-  case class PartialLambda(mapping: Seq[(Seq[Expr], Expr)], default: Option[Expr], tpe: FunctionType) extends Expr {
+  case class FiniteLambda(mapping: Seq[(Seq[Expr], Expr)], default: Expr, tpe: FunctionType) extends Expr {
     val getType = tpe
   }
 
diff --git a/src/main/scala/leon/purescala/Extractors.scala b/src/main/scala/leon/purescala/Extractors.scala
index cfa4780efccad338b5df44400b53da7264a2c2d7..00541f4450f40585782d3f6b82d7f7665c78f8cd 100644
--- a/src/main/scala/leon/purescala/Extractors.scala
+++ b/src/main/scala/leon/purescala/Extractors.scala
@@ -52,7 +52,7 @@ object Extractors {
         Some((Seq(a), (es: Seq[Expr]) => ArrayLength(es.head)))
       case Lambda(args, body) =>
         Some((Seq(body), (es: Seq[Expr]) => Lambda(args, es.head)))
-      case PartialLambda(mapping, dflt, tpe) =>
+      case FiniteLambda(mapping, dflt, tpe) =>
         val sze = tpe.from.size + 1
         val subArgs = mapping.flatMap { case (args, v) => args :+ v }
         val builder = (as: Seq[Expr]) => {
@@ -63,10 +63,9 @@ object Extractors {
             case Seq() => Seq.empty
             case _ => sys.error("unexpected number of key/value expressions")
           }
-          val (nas, nd) = if (dflt.isDefined) (as.init, Some(as.last)) else (as, None)
-          PartialLambda(rec(nas), nd, tpe)
+          FiniteLambda(rec(as.init), as.last, tpe)
         }
-        Some((subArgs ++ dflt, builder))
+        Some((subArgs :+ dflt, builder))
       case Forall(args, body) =>
         Some((Seq(body), (es: Seq[Expr]) => Forall(args, es.head)))
 
diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index 44d454a9c0a4f1127ed0533f872c66f1ec6bc067..67296c3dc4f2cc130915d7adfdb3cc186447d7df 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -270,19 +270,15 @@ class PrettyPrinter(opts: PrinterOptions,
       case Lambda(args, body) =>
         optP { p"($args) => $body" }
 
-      case PartialLambda(mapping, dflt, _) =>
+      case FiniteLambda(mapping, dflt, _) =>
         optP {
           def pm(p: (Seq[Expr], Expr)): PrinterHelpers.Printable =
             (pctx: PrinterContext) => p"${purescala.Constructors.tupleWrap(p._1)} => ${p._2}"(pctx)
 
           if (mapping.isEmpty) {
-            p"{}"
+            p"{ * => ${dflt} }"
           } else {
-            p"{ ${nary(mapping map pm)} }"
-          }
-
-          if (dflt.isDefined) {
-            p" getOrElse ${dflt.get}"
+            p"{ ${nary(mapping map pm)}, * => ${dflt} }"
           }
         }
 
diff --git a/src/main/scala/leon/purescala/Quantification.scala b/src/main/scala/leon/purescala/Quantification.scala
index bb5115baab042a1bd524fdb2f73deeabefa59243..3efdc9df7e5b92b0e5d87faf9205c1ef8f3e90af 100644
--- a/src/main/scala/leon/purescala/Quantification.scala
+++ b/src/main/scala/leon/purescala/Quantification.scala
@@ -49,7 +49,7 @@ object Quantification {
     res.filter(ms => ms.forall(m => reverseMap(m) subsetOf ms))
   }
 
-  def extractQuorums(expr: Expr, quantified: Set[Identifier]): Seq[(Set[(Expr, Expr, Seq[Expr])], Set[(Expr, Expr, Seq[Expr])])] = {
+  def extractQuorums(expr: Expr, quantified: Set[Identifier]): Seq[Set[(Expr, Expr, Seq[Expr])]] = {
     object QMatcher {
       def unapply(e: Expr): Option[(Expr, Seq[Expr])] = e match {
         case QuantificationMatcher(expr, args) =>
@@ -65,38 +65,9 @@ object Quantification {
     val allMatchers = CollectorWithPaths { case QMatcher(expr, args) => expr -> args }.traverse(expr)
     val matchers = allMatchers.map { case ((caller, args), path) => (path, caller, args) }.toSet
 
-    val quorums = extractQuorums(matchers, quantified,
+    extractQuorums(matchers, quantified,
       (p: (Expr, Expr, Seq[Expr])) => p._3.collect { case QMatcher(e, a) => (p._1, e, a) }.toSet,
       (p: (Expr, Expr, Seq[Expr])) => p._3.collect { case Variable(id) if quantified(id) => id }.toSet)
-
-    quorums.map(quorum => quorum -> matchers.filter(m => !quorum(m)))
-  }
-
-  def extractModel(
-    asMap: Map[Identifier, Expr],
-    funDomains: Map[Identifier, Set[Seq[Expr]]],
-    typeDomains: Map[TypeTree, Set[Seq[Expr]]],
-    evaluator: DeterministicEvaluator
-  ): Map[Identifier, Expr] = asMap.map { case (id, expr) =>
-    id -> (funDomains.get(id) match {
-      case Some(domain) =>
-        PartialLambda(domain.toSeq.map { es =>
-          val optEv = evaluator.eval(Application(expr, es)).result
-          es -> optEv.getOrElse(scala.sys.error("Unexpectedly failed to evaluate " + Application(expr, es)))
-        }, None, id.getType.asInstanceOf[FunctionType])
-
-      case None => postMap {
-        case p @ PartialLambda(mapping, dflt, tpe) =>
-          Some(PartialLambda(typeDomains.get(tpe) match {
-            case Some(domain) => domain.toSeq.map { es =>
-              val optEv = evaluator.eval(Application(p, es)).result
-              es -> optEv.getOrElse(scala.sys.error("Unexpectedly failed to evaluate " + Application(p, es)))
-            }
-            case _ => Seq.empty
-          }, None, tpe))
-        case _ => None
-      } (expr)
-    })
   }
 
   object HenkinDomains {
@@ -106,8 +77,7 @@ object Quantification {
   class HenkinDomains (val lambdas: Map[Lambda, Set[Seq[Expr]]], val tpes: Map[TypeTree, Set[Seq[Expr]]]) {
     def get(e: Expr): Set[Seq[Expr]] = {
       val specialized: Set[Seq[Expr]] = e match {
-        case PartialLambda(_, Some(dflt), _) => scala.sys.error("No domain for non-partial lambdas")
-        case PartialLambda(mapping, _, _) => mapping.map(_._1).toSet
+        case FiniteLambda(mapping, _, _) => mapping.map(_._1).toSet
         case l: Lambda => lambdas.getOrElse(l, Set.empty)
         case _ => Set.empty
       }
diff --git a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala
index 5f002ccdacb54b16515fa0d54f7573ba2ebc82cb..bba8ba20d9bbf849874052924647d55cb6420d2d 100644
--- a/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala
+++ b/src/main/scala/leon/solvers/combinators/UnrollingSolver.scala
@@ -12,6 +12,7 @@ import purescala.Constructors._
 import purescala.Expressions._
 import purescala.ExprOps._
 import purescala.Types._
+import purescala.TypeOps.bestRealType
 import utils._
 
 import templates._
@@ -168,6 +169,19 @@ trait AbstractUnrollingSolver[T]
   trait ModelWrapper {
     def get(id: Identifier): Option[Expr]
     def eval(elem: T, tpe: TypeTree): Option[Expr]
+
+    private[AbstractUnrollingSolver] def extract(b: T, m: Matcher[T]): Option[Seq[Expr]] = {
+      val QuantificationTypeMatcher(fromTypes, _) = m.tpe
+      val optEnabler = eval(b, BooleanType)
+      optEnabler.filter(_ == BooleanLiteral(true)).flatMap { _ =>
+        val optArgs = (m.args zip fromTypes).map { case (arg, tpe) => eval(arg.encoded, tpe) }
+        if (optArgs.forall(_.isDefined)) {
+          Some(optArgs.map(_.get))
+        } else {
+          None
+        }
+      }
+    }
   }
 
   def solverGetModel: ModelWrapper
@@ -181,21 +195,21 @@ trait AbstractUnrollingSolver[T]
   private def validateModel(model: Model, assumptions: Seq[Expr], silenceErrors: Boolean): Boolean = {
     val expr = andJoin(assumptions ++ constraints)
 
-    evaluator.check(expr, model) match {
-      case EvaluationResults.CheckSuccess =>
+    evaluator.eval(expr, model) match {
+      case EvaluationResults.Successful(BooleanLiteral(true)) =>
         reporter.debug("- Model validated.")
         true
 
-      case EvaluationResults.CheckValidityFailure =>
+      case EvaluationResults.Successful(_) =>
         reporter.debug("- Invalid model.")
         false
 
-      case EvaluationResults.CheckRuntimeFailure(msg) =>
-        emit(silenceErrors)("- Model leads to evaluation error: " + msg)
+      case EvaluationResults.RuntimeError(msg) =>
+        emit(silenceErrors)("- Model leads to runtime error: " + msg)
         false
 
-      case EvaluationResults.CheckQuantificationFailure(msg) =>
-        emit(silenceErrors)("- Model leads to quantification error: " + msg)
+      case EvaluationResults.EvaluatorError(msg) =>
+        emit(silenceErrors)("- Model leads to evaluation error: " + msg)
         false
     }
   }
@@ -203,74 +217,109 @@ trait AbstractUnrollingSolver[T]
   private def getPartialModel: HenkinModel = {
     val wrapped = solverGetModel
 
-    def extract(b: T, m: Matcher[T]): Option[Seq[Expr]] = {
-      val QuantificationTypeMatcher(fromTypes, _) = m.tpe
-      val optEnabler = wrapped.eval(b, BooleanType)
-      optEnabler.filter(_ == BooleanLiteral(true)).flatMap { _ =>
-        val optArgs = (m.args zip fromTypes).map { case (arg, tpe) => wrapped.eval(arg.encoded, tpe) }
-        if (optArgs.forall(_.isDefined)) {
-          Some(optArgs.map(_.get))
-        } else {
-          None
-        }
-      }
-    }
-
-    val (typeInsts, partialInsts, lambdaInsts) = templateGenerator.manager.instantiations
+    val typeInsts = templateGenerator.manager.typeInstantiations
+    val partialInsts = templateGenerator.manager.partialInstantiations
+    val lambdaInsts = templateGenerator.manager.lambdaInstantiations
 
     val typeDomains: Map[TypeTree, Set[Seq[Expr]]] = typeInsts.map {
-      case (tpe, domain) => tpe -> domain.flatMap { case (b, m) => extract(b, m) }.toSet
+      case (tpe, domain) => tpe -> domain.flatMap { case (b, m) => wrapped.extract(b, m) }.toSet
     }
 
     val funDomains: Map[Identifier, Set[Seq[Expr]]] = freeVars.map { case (id, idT) =>
-      id -> partialInsts.get(idT).toSeq.flatten.flatMap { case (b, m) => extract(b, m) }.toSet
+      id -> partialInsts.get(idT).toSeq.flatten.flatMap { case (b, m) => wrapped.extract(b, m) }.toSet
     }
 
     val lambdaDomains: Map[Lambda, Set[Seq[Expr]]] = lambdaInsts.map {
-      case (l, domain) => l -> domain.flatMap { case (b, m) => extract(b, m) }.toSet
+      case (l, domain) => l -> domain.flatMap { case (b, m) => wrapped.extract(b, m) }.toSet
     }
 
-    val model = extractModel(wrapped)
-    val asDMap = purescala.Quantification.extractModel(model.toMap, funDomains, typeDomains, evaluator)
+    val model = new Model(freeVars.toMap.map { case (id, _) =>
+      val value = wrapped.get(id).get
+      id -> (funDomains.get(id) match {
+        case Some(domain) =>
+          val FiniteLambda(_, dflt, tpe) = value
+          FiniteLambda(domain.toSeq.map { es =>
+            val optEv = evaluator.eval(application(value, es)).result
+            es -> optEv.getOrElse(scala.sys.error("Unexpectedly failed to evaluate " + application(value, es)))
+          }, dflt, tpe)
+
+        case None => postMap {
+          case p @ FiniteLambda(mapping, dflt, tpe) =>
+            Some(FiniteLambda(typeDomains.get(tpe) match {
+              case Some(domain) => domain.toSeq.map { es =>
+                val optEv = evaluator.eval(application(value, es)).result
+                es -> optEv.getOrElse(scala.sys.error("Unexpectedly failed to evaluate " + application(value, es)))
+              }
+              case _ => Seq.empty
+            }, dflt, tpe))
+          case _ => None
+        } (value)
+      })
+    })
+
     val domains = new HenkinDomains(lambdaDomains, typeDomains)
-    new HenkinModel(asDMap, domains)
+    new HenkinModel(model.toMap, domains)
   }
 
-  private def getTotalModel(silenceErrors: Boolean = false): (Boolean, Model) = {
-    if (interrupted) {
-      (false, Model.empty)
-    } else {
-      var valid = false
-      var wrapper = solverGetModel
+  private def getTotalModel: Model = {
+    val wrapped = solverGetModel
 
-      val clauses = templateGenerator.manager.checkClauses
-      if (clauses.isEmpty) {
-        valid = true
-      } else {
-        reporter.debug(" - Verifying model transitivity")
+    val typeInsts = templateGenerator.manager.typeInstantiations
+    val partialInsts = templateGenerator.manager.partialInstantiations
 
-        val timer = context.timers.solvers.check.start()
-        solverCheck(clauses) { res =>
-          timer.stop()
+    def extractCond(params: Seq[Identifier], args: Seq[(T, Expr)], structure: Map[T, Identifier]): Seq[Expr] = (params, args) match {
+      case (id +: rparams, (v, arg) +: rargs) =>
+        if (templateGenerator.manager.isQuantifier(v)) {
+          structure.get(v) match {
+            case Some(pid) => Equals(Variable(id), Variable(pid)) +: extractCond(rparams, rargs, structure)
+            case None => extractCond(rparams, rargs, structure + (v -> id))
+          }
+        } else {
+          Equals(Variable(id), arg) +: extractCond(rparams, rargs, structure)
+        }
+      case _ => Seq.empty
+    }
 
-          reporter.debug(" - Finished transitivity check")
+    new Model(freeVars.toMap.map { case (id, idT) =>
+      val value = wrapped.get(id).get
+      id -> (id.getType match {
+        case FunctionType(from, to) =>
+          val params = from.map(tpe => FreshIdentifier("x", tpe, true))
+          val domain = partialInsts.get(idT).orElse(typeInsts.get(bestRealType(id.getType))).toSeq.flatten
+          val conditionals = domain.flatMap { case (b, m) =>
+            wrapped.extract(b, m) match {
+              case Some(args) =>
+                val result = evaluator.eval(application(value, args)).result.getOrElse {
+                  scala.sys.error("Unexpectedly failed to evaluate " + application(value, args))
+                }
 
-          res match {
-            case Some(true) =>
-              wrapper = solverGetModel
-              valid = true
+                val c1 = (params zip args).map(p => Equals(Variable(p._1), p._2))
+                if (m.args.exists(arg => templateGenerator.manager.isQuantifier(arg.encoded))) {
+                  val c2 = extractCond(params, m.args.map(_.encoded) zip args, Map.empty)
+                  Seq(c1 -> result, c2 -> result)
+                } else {
+                  Seq(c1 -> result)
+                }
 
-            case Some(false) =>
-              emit(silenceErrors)(" - Transitivity independence not guaranteed for model")
+              case None => Seq.empty
+            }
+          }
 
-            case None =>
-              emit(silenceErrors)(" - Unknown for transitivity independence!?")
+          val filteredConds = conditionals
+            .foldLeft(Map.empty[Seq[Expr], Expr]) { case (mapping, (conds, result)) =>
+              if (mapping.isDefinedAt(conds)) mapping else mapping + (conds -> result)
+            }
+
+          val rest :+ ((_, dflt)) = filteredConds.toSeq.sortBy(_._1.size)
+          val body = rest.foldLeft(dflt) { case (elze, (conds, res)) =>
+            if (conds.isEmpty) elze else IfExpr(andJoin(conds), res, elze)
           }
-        }
-      }
 
-      (valid, extractModel(wrapper))
-    }
+          Lambda(params.map(ValDef(_)), body)
+
+        case _ => value
+      })
+    })
   }
 
   def genericCheck(assumptions: Set[Expr]): Option[Boolean] = {
@@ -291,9 +340,13 @@ trait AbstractUnrollingSolver[T]
 
     while(!foundDefinitiveAnswer && !interrupted) {
       reporter.debug(" - Running search...")
+      var quantify = false
+
+      def check[R](clauses: Seq[T])(block: Option[Boolean] => R) =
+        if (partialModels) solverCheckAssumptions(clauses)(block) else solverCheck(clauses)(block)
 
       val timer = context.timers.solvers.check.start()
-      solverCheckAssumptions(encodedAssumptions.toSeq ++ unrollingBank.satisfactionAssumptions) { res =>
+      check(encodedAssumptions.toSeq ++ unrollingBank.satisfactionAssumptions) { res =>
         timer.stop()
 
         reporter.debug(" - Finished search with blocked literals")
@@ -303,10 +356,37 @@ trait AbstractUnrollingSolver[T]
             foundAnswer(None)
 
           case Some(true) => // SAT
-            val (stop, model) = if (!partialModels) {
-              getTotalModel(silenceErrors = true)
-            } else {
+            val (stop, model) = if (interrupted) {
+              (true, Model.empty)
+            } else if (partialModels) {
               (true, getPartialModel)
+            } else {
+              val clauses = templateGenerator.manager.checkClauses
+              if (clauses.isEmpty) {
+                (true, extractModel(solverGetModel))
+              } else {
+                reporter.debug(" - Verifying model transitivity")
+
+                val timer = context.timers.solvers.check.start()
+                solverCheck(clauses) { res =>
+                  timer.stop()
+
+                  reporter.debug(" - Finished transitivity check")
+
+                  res match {
+                    case Some(true) =>
+                      (true, getTotalModel)
+
+                    case Some(false) =>
+                      reporter.debug(" - Transitivity not guaranteed for model")
+                      (false, Model.empty)
+
+                    case None =>
+                      reporter.warning(" - Unknown for transitivity!?")
+                      (false, Model.empty)
+                  }
+                }
+              }
             }
 
             if (!interrupted) {
@@ -316,15 +396,7 @@ trait AbstractUnrollingSolver[T]
                   reporter.error(model.asString(context))
                   foundAnswer(None, model)
                 } else {
-                  // further quantifier instantiations are required!
-                  val newClauses = unrollingBank.instantiateQuantifiers
-                  reporter.debug(" - more instantiations")
-
-                  for (cls <- newClauses) {
-                    solverAssert(cls)
-                  }
-
-                  reporter.debug(" - finished instantiating")
+                  quantify = true
                 }
               } else {
                 val valid = !checkModels || validateModel(model, assumptionsSeq, silenceErrors = false)
@@ -366,66 +438,74 @@ trait AbstractUnrollingSolver[T]
                   reporter.fatalError("Can't unroll unsat core for incompatible solver " + name)
               }
             }
+        }
+      }
 
-            if (!interrupted) {
-              if (feelingLucky) {
-                reporter.debug(" - Running search without blocked literals (w/ lucky test)")
-              } else {
-                reporter.debug(" - Running search without blocked literals (w/o lucky test)")
+      if (!quantify && !foundDefinitiveAnswer && !interrupted) {
+        if (feelingLucky) {
+          reporter.debug(" - Running search without blocked literals (w/ lucky test)")
+        } else {
+          reporter.debug(" - Running search without blocked literals (w/o lucky test)")
+        }
+
+        val timer = context.timers.solvers.check.start()
+        solverCheckAssumptions(encodedAssumptions.toSeq ++ unrollingBank.refutationAssumptions) { res2 =>
+          timer.stop()
+
+          reporter.debug(" - Finished search without blocked literals")
+
+          res2 match {
+            case Some(false) =>
+              solverUnsatCore match {
+                case Some(core) =>
+                  val exprCore = encodedCoreToCore(core)
+                  foundAnswer(Some(false), core = exprCore)
+                case None =>
+                  foundAnswer(Some(false))
               }
 
-              val timer = context.timers.solvers.check.start()
-              solverCheckAssumptions(encodedAssumptions.toSeq ++ unrollingBank.refutationAssumptions) { res2 =>
-                timer.stop()
-
-                reporter.debug(" - Finished search without blocked literals")
-
-                res2 match {
-                  case Some(false) =>
-                    solverUnsatCore match {
-                      case Some(core) =>
-                        val exprCore = encodedCoreToCore(core)
-                        foundAnswer(Some(false), core = exprCore)
-                      case None =>
-                        foundAnswer(Some(false))
-                    }
-
-                  case Some(true) =>
-                    if (this.feelingLucky && !interrupted) {
-                      // we might have been lucky :D
-                      val model = extractModel(solverGetModel)
-                      val valid = validateModel(model, assumptionsSeq, silenceErrors = true)
-                      if (valid) foundAnswer(Some(true), model)
-                    }
-
-                  case None =>
-                    foundAnswer(None)
-                }
+            case Some(true) =>
+              if (this.feelingLucky && !interrupted) {
+                // we might have been lucky :D
+                val model = extractModel(solverGetModel)
+                val valid = validateModel(model, assumptionsSeq, silenceErrors = true)
+                if (valid) foundAnswer(Some(true), model)
               }
-            }
 
-            if (interrupted) {
+            case None =>
               foundAnswer(None)
-            }
+          }
+        }
+      }
 
-            if (!foundDefinitiveAnswer) {
-              reporter.debug("- We need to keep going")
+      if (!foundDefinitiveAnswer && !interrupted) {
+        reporter.debug("- We need to keep going")
 
-              // unfolling `unfoldFactor` times
-              for (i <- 1 to unfoldFactor.toInt) {
-                val toRelease = unrollingBank.getBlockersToUnlock
+        if (quantify) {
+          // further quantifier instantiations are required!
+          val newClauses = unrollingBank.instantiateQuantifiers
+          reporter.debug(" - more instantiations")
 
-                reporter.debug(" - more unrollings")
+          for (cls <- newClauses) {
+            solverAssert(cls)
+          }
 
-                val newClauses = unrollingBank.unrollBehind(toRelease)
+          reporter.debug(" - finished instantiating")
+        } else {
+          // unfolling `unfoldFactor` times
+          for (i <- 1 to unfoldFactor.toInt) {
+            val toRelease = unrollingBank.getBlockersToUnlock
 
-                for (ncl <- newClauses) {
-                  solverAssert(ncl)
-                }
-              }
+            reporter.debug(" - more unrollings")
+
+            val newClauses = unrollingBank.unrollBehind(toRelease)
 
-              reporter.debug(" - finished unrolling")
+            for (ncl <- newClauses) {
+              solverAssert(ncl)
             }
+          }
+
+          reporter.debug(" - finished unrolling")
         }
       }
     }
diff --git a/src/main/scala/leon/solvers/combinators/Z3StringCapableSolver.scala b/src/main/scala/leon/solvers/combinators/Z3StringCapableSolver.scala
index 602873aba9df1859650ee94486c59d9487ec7fbd..eea7c80a08dc5c6a05ebb448671b41735ea0c2d8 100644
--- a/src/main/scala/leon/solvers/combinators/Z3StringCapableSolver.scala
+++ b/src/main/scala/leon/solvers/combinators/Z3StringCapableSolver.scala
@@ -128,7 +128,7 @@ trait Z3StringEvaluatingSolver[TUnderlying <: EvaluatingSolver] extends Evaluati
 
 trait Z3StringQuantificationSolver[TUnderlying <: QuantificationSolver] extends QuantificationSolver { self:  Z3StringCapableSolver[TUnderlying] =>
   // Members declared in leon.solvers.QuantificationSolver
-  override def getModel: leon.solvers.HenkinModel = {
+  override def getModel = {
     val model = underlying.getModel
     someConverter map { converter =>
       val ids = model.ids.toSeq
@@ -136,41 +136,39 @@ trait Z3StringQuantificationSolver[TUnderlying <: QuantificationSolver] extends
       import converter.Backward._
       val original_ids = ids.map(convertId)
       val original_exprs = exprs.map{ case e => convertExpr(e)(Map()) }
+
+      model match {
+        case hm: HenkinModel =>
+          val new_domain = new HenkinDomains(
+              hm.doms.lambdas.map(kv =>
+                (convertExpr(kv._1)(Map()).asInstanceOf[Lambda],
+                 kv._2.map(e => e.map(e => convertExpr(e)(Map()))))).toMap,
+              hm.doms.tpes.map(kv =>
+                (convertType(kv._1),
+                 kv._2.map(e => e.map(e => convertExpr(e)(Map()))))).toMap
+              )
       
-      val new_domain = new HenkinDomains(
-          model.doms.lambdas.map(kv =>
-            (convertExpr(kv._1)(Map()).asInstanceOf[Lambda],
-             kv._2.map(e => e.map(e => convertExpr(e)(Map()))))).toMap,
-          model.doms.tpes.map(kv =>
-            (convertType(kv._1),
-             kv._2.map(e => e.map(e => convertExpr(e)(Map()))))).toMap
-          )
-      
-      new HenkinModel(original_ids.zip(original_exprs).toMap, new_domain)
+          new HenkinModel(original_ids.zip(original_exprs).toMap, new_domain)
+        case _ => model
+      }
     } getOrElse model
   }
 }
 
-trait EvaluatorCheckConverter extends DeterministicEvaluator {
-  def converter: Z3StringConversion
-  abstract override def check(expression: Expr, model: solvers.Model) : CheckResult = {
-    val c = converter
-    import c.Backward._  // Because the evaluator is going to be called by the underlying solver, but it will use the original program
-    super.check(convertExpr(expression)(Map()), convertModel(model))
-  }
-}
-
 class ConvertibleCodeGenEvaluator(context: LeonContext, originalProgram: Program, val converter: Z3StringConversion)
-    extends CodeGenEvaluator(context, originalProgram) with EvaluatorCheckConverter {
+    extends CodeGenEvaluator(context, originalProgram) {
+
   override def compile(expression: Expr, args: Seq[Identifier]) : Option[solvers.Model=>EvaluationResult] = {
     import converter._ 
     super.compile(Backward.convertExpr(expression)(Map()), args.map(Backward.convertId))
-    .map(evaluator => (m: Model) => Forward.convertResult(evaluator(Backward.convertModel(m)))
+      .map(evaluator => (m: Model) => Forward.convertResult(evaluator(Backward.convertModel(m)))
     )
   }
 }
 
-class ConvertibleDefaultEvaluator(context: LeonContext, originalProgram: Program, val converter: Z3StringConversion) extends DefaultEvaluator(context, originalProgram) with EvaluatorCheckConverter {
+class ConvertibleDefaultEvaluator(context: LeonContext, originalProgram: Program, val converter: Z3StringConversion)
+    extends DefaultEvaluator(context, originalProgram) {
+
   override def eval(ex: Expr, model: Model): EvaluationResults.Result[Expr] = {
     import converter._
     Forward.convertResult(super.eval(Backward.convertExpr(ex)(Map()), Backward.convertModel(model)))
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
index 87cc849b41d2507d7e0ca53a351b2f605d387b46..03cf3aef32fc59c33283c70cebfa2f918e549e76 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBCVC4Target.scala
@@ -63,7 +63,7 @@ trait SMTLIBCVC4Target extends SMTLIBTarget {
             RawArrayValue(k, Map(), fromSMT(elem, v))
 
           case ft @ FunctionType(from, to) =>
-            PartialLambda(Seq.empty, Some(fromSMT(elem, to)), ft)
+            FiniteLambda(Seq.empty, fromSMT(elem, to), ft)
 
           case MapType(k, v) =>
             FiniteMap(Map(), k, v)
@@ -75,7 +75,7 @@ trait SMTLIBCVC4Target extends SMTLIBTarget {
             RawArrayValue(k, Map(), fromSMT(elem, v))
 
           case ft @ FunctionType(from, to) =>
-            PartialLambda(Seq.empty, Some(fromSMT(elem, to)), ft)
+            FiniteLambda(Seq.empty, fromSMT(elem, to), ft)
 
           case MapType(k, v) =>
             FiniteMap(Map(), k, v)
@@ -88,9 +88,9 @@ trait SMTLIBCVC4Target extends SMTLIBTarget {
             RawArrayValue(k, elems + (fromSMT(key, k) -> fromSMT(elem, v)), base)
 
           case FunctionType(from, v) =>
-            val PartialLambda(mapping, dflt, ft) = fromSMT(arr, otpe)
+            val FiniteLambda(mapping, dflt, ft) = fromSMT(arr, otpe)
             val args = unwrapTuple(fromSMT(key, tupleTypeWrap(from)), from.size)
-            PartialLambda(mapping :+ (args -> fromSMT(elem, v)), dflt, ft)
+            FiniteLambda(mapping :+ (args -> fromSMT(elem, v)), dflt, ft)
 
           case MapType(k, v) =>
             val FiniteMap(elems, k, v) = fromSMT(arr, otpe)
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
index d05b45c35e2e3847be4e1a6650c779de91da91d9..d239de90dd2b7060d92fe407a7070f8a6b88d74d 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBTarget.scala
@@ -206,7 +206,7 @@ trait SMTLIBTarget extends Interruptible {
 
     case ft @ FunctionType(from, to) =>
       val elems = r.elems.toSeq.map { case (k, v) => unwrapTuple(k, from.size) -> v }
-      PartialLambda(elems, Some(r.default), ft)
+      FiniteLambda(elems, r.default, ft)
 
     case MapType(from, to) =>
       // We expect a RawArrayValue with keys in from and values in Option[to],
diff --git a/src/main/scala/leon/solvers/templates/QuantificationManager.scala b/src/main/scala/leon/solvers/templates/QuantificationManager.scala
index 1662596002ac49202f10206cec6a338fc7377116..5262ab9c72aaf3ccc677ad1124ad8a28fd424fa8 100644
--- a/src/main/scala/leon/solvers/templates/QuantificationManager.scala
+++ b/src/main/scala/leon/solvers/templates/QuantificationManager.scala
@@ -11,6 +11,7 @@ import purescala.Constructors._
 import purescala.Expressions._
 import purescala.ExprOps._
 import purescala.Types._
+import purescala.TypeOps._
 import purescala.Quantification.{QuantificationTypeMatcher => QTM}
 
 import Instantiation._
@@ -134,15 +135,23 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
   private val quantifications = new IncrementalSeq[MatcherQuantification]
   private val instCtx         = new InstantiationContext
 
-  private val handled         = new ContextMap
-  private val ignored         = new ContextMap
+  private val ignoredMatchers = new ContextMap
+  private val ignoredSubsts   = new IncrementalMap[MatcherQuantification, MutableSet[(Int, Set[T], Map[T,Arg[T]])]]
+  private val handledSubsts   = new IncrementalMap[MatcherQuantification, MutableSet[(Set[T], Map[T,Arg[T]])]]
 
   private val known           = new IncrementalSet[T]
-  private val lambdaAxioms    = new IncrementalSet[(LambdaTemplate[T], Seq[(Identifier, T)])]
+  private val lambdaAxioms    = new IncrementalSet[((Expr, Seq[T]), Seq[(Identifier, T)])]
   private val templates       = new IncrementalMap[(Expr, Seq[T]), T]
 
   override protected def incrementals: List[IncrementalState] =
-    List(quantifications, instCtx, handled, ignored, known, lambdaAxioms, templates) ++ super.incrementals
+    List(quantifications, instCtx, ignoredMatchers, ignoredSubsts,
+      handledSubsts, known, lambdaAxioms, templates) ++ super.incrementals
+
+  private var currentGen = 0
+  private def minGen = {
+    val gens = ignoredSubsts.toSeq.flatMap(_._2).map(_._1)
+    if (gens.isEmpty) currentGen else gens.min
+  }
 
   private sealed abstract class MatcherKey(val tpe: TypeTree)
   private case class CallerKey(caller: T, tt: TypeTree) extends MatcherKey(tt)
@@ -167,42 +176,45 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
   private val uniformQuantSet: MutableSet[T]                = MutableSet.empty
 
   def isQuantifier(idT: T): Boolean = uniformQuantSet(idT)
-  private def uniformSubst(qs: Seq[(Identifier, T)]): Map[T, T] = {
-    qs.groupBy(_._1.getType).flatMap { case (tpe, qst) =>
+  def uniformQuants(ids: Seq[Identifier]): Seq[T] = {
+    val mapping = ids.groupBy(id => bestRealType(id.getType)).flatMap { case (tpe, idst) =>
       val prev = uniformQuantMap.get(tpe) match {
         case Some(seq) => seq
         case None => Seq.empty
       }
 
-      if (prev.size >= qst.size) {
-        qst.map(_._2) zip prev.take(qst.size)
+      if (prev.size >= idst.size) {
+        idst zip prev.take(idst.size)
       } else {
-        val (handled, newQs) = qst.splitAt(prev.size)
-        val uQs = newQs.map(p => p._2 -> encoder.encodeId(p._1))
+        val (handled, newIds) = idst.splitAt(prev.size)
+        val uIds = newIds.map(id => id -> encoder.encodeId(id))
 
-        uniformQuantMap(tpe) = prev ++ uQs.map(_._2)
-        uniformQuantSet ++= uQs.map(_._2)
+        uniformQuantMap(tpe) = prev ++ uIds.map(_._2)
+        uniformQuantSet ++= uIds.map(_._2)
 
-        (handled.map(_._2) zip prev) ++ uQs
+        (handled zip prev) ++ uIds
       }
     }.toMap
+
+    ids.map(mapping)
+  }
+
+  private def uniformSubst(qs: Seq[(Identifier, T)]): Map[T, T] = {
+    (qs.map(_._2) zip uniformQuants(qs.map(_._1))).toMap
   }
 
   def assumptions: Seq[T] = quantifications.collect { case q: Quantification => q.currentQ2Var }.toSeq
 
-  def instantiations: (Map[TypeTree, Matchers], Map[T, Matchers], Map[Lambda, Matchers]) = {
-    var typeInsts: Map[TypeTree, Matchers] = Map.empty
-    var partialInsts: Map[T, Matchers] = Map.empty
-    var lambdaInsts: Map[Lambda, Matchers] = Map.empty
+  def typeInstantiations: Map[TypeTree, Matchers] = instCtx.map.instantiations.collect {
+    case (TypeKey(tpe), matchers) => tpe -> matchers
+  }
 
-    val instantiations = handled.instantiations ++ instCtx.map.instantiations
-    for ((key, matchers) <- instantiations) key match {
-      case TypeKey(tpe) => typeInsts += tpe -> matchers
-      case CallerKey(caller, _) => partialInsts += caller -> matchers
-      case LambdaKey(lambda, _) => lambdaInsts += lambda -> matchers
-    }
+  def lambdaInstantiations: Map[Lambda, Matchers] = instCtx.map.instantiations.collect {
+    case (LambdaKey(lambda, tpe), matchers) => lambda -> (matchers ++ instCtx.map.get(TypeKey(tpe)).toMatchers)
+  }
 
-    (typeInsts, partialInsts, lambdaInsts)
+  def partialInstantiations: Map[T, Matchers] = instCtx.map.instantiations.collect {
+    case (CallerKey(caller, tpe), matchers) => caller -> (matchers ++ instCtx.map.get(TypeKey(tpe)).toMatchers)
   }
 
   override def registerFree(ids: Seq[(Identifier, T)]): Unit = {
@@ -351,7 +363,7 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
 
   private trait MatcherQuantification {
     val pathVar: (Identifier, T)
-    val quantified: Set[T]
+    val quantifiers: Seq[(Identifier, T)]
     val matchers: Set[Matcher[T]]
     val allMatchers: Map[T, Set[Matcher[T]]]
     val condVars: Map[Identifier, T]
@@ -362,6 +374,7 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
     val applications: Map[T, Set[App[T]]]
     val lambdas: Seq[LambdaTemplate[T]]
 
+    lazy val quantified: Set[T] = quantifiers.map(_._2).toSet
     lazy val start = pathVar._2
 
     private lazy val depth = matchers.map(matcherDepth).max
@@ -455,43 +468,68 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
 
       for (mapping <- mappings(bs, matcher)) {
         val (enablers, subst, isStrict) = extractSubst(mapping)
+
+        if (!skip(subst)) {
+          if (!isStrict) {
+            ignoreSubst(enablers, subst)
+          } else {
+            instantiation ++= instantiateSubst(enablers, subst, strict = true)
+          }
+        }
+      }
+
+      instantiation
+    }
+
+    def instantiateSubst(enablers: Set[T], subst: Map[T, Arg[T]], strict: Boolean = false): Instantiation[T] = {
+      if (handledSubsts(this)(enablers -> subst)) {
+        Instantiation.empty[T]
+      } else {
+        handledSubsts(this) += enablers -> subst
+
+        var instantiation = Instantiation.empty[T]
         val (enabler, optEnabler) = freshBlocker(enablers)
+        if (optEnabler.isDefined) {
+          instantiation = instantiation withClause encoder.mkEquals(enabler, optEnabler.get)
+        }
 
-        val baseSubst = subst ++ instanceSubst(enablers).mapValues(Left(_))
+        val baseSubst = subst ++ instanceSubst(enabler).mapValues(Left(_))
         val (substMap, inst) = Template.substitution(encoder, QuantificationManager.this,
           condVars, exprVars, condTree, Seq.empty, lambdas, baseSubst, pathVar._1, enabler)
+        instantiation ++= inst
 
-        if (!skip(substMap)) {
-          if (optEnabler.isDefined) {
-            instantiation = instantiation withClause encoder.mkEquals(enabler, optEnabler.get)
-          }
+        val msubst = substMap.collect { case (c, Right(m)) => c -> m }
+        val substituter = encoder.substitute(substMap.mapValues(_.encoded))
+        instantiation ++= Template.instantiate(encoder, QuantificationManager.this,
+          clauses, blockers, applications, Seq.empty, Map.empty, lambdas, substMap)
 
-          instantiation ++= inst
-          instantiation ++= Template.instantiate(encoder, QuantificationManager.this,
-            clauses, blockers, applications, Seq.empty, Map.empty[T, Set[Matcher[T]]], lambdas, substMap)
+        for ((b,ms) <- allMatchers; m <- ms) {
+          val sb = enablers ++ (if (b == start) Set.empty else Set(substituter(b)))
+          val sm = m.substitute(substituter, msubst)
 
-          val msubst = substMap.collect { case (c, Right(m)) => c -> m }
-          val substituter = encoder.substitute(substMap.mapValues(_.encoded))
-
-          for ((b,ms) <- allMatchers; m <- ms) {
-            val sb = enablers ++ (if (b == start) Set.empty else Set(substituter(b)))
-            val sm = m.substitute(substituter, msubst)
-
-            if (matchers(m)) {
-              handled += sb -> sm
-            } else if (transMatchers(m) && isStrict) {
-              instantiation ++= instCtx.instantiate(sb, sm)(quantifications.toSeq : _*)
-            } else {
-              ignored += sb -> sm
-            }
+          if (strict && (matchers(m) || transMatchers(m))) {
+            instantiation ++= instCtx.instantiate(sb, sm)(quantifications.toSeq : _*)
+          } else if (!matchers(m)) {
+            ignoredMatchers += sb -> sm
           }
         }
+
+        instantiation
       }
+    }
 
-      instantiation
+    def ignoreSubst(enablers: Set[T], subst: Map[T, Arg[T]]): Unit = {
+      val msubst = subst.collect { case (c, Right(m)) => c -> m }
+      val substituter = encoder.substitute(subst.mapValues(_.encoded))
+      val nextGen = (if (matchers.forall { m =>
+        val sm = m.substitute(substituter, msubst)
+        instCtx(enablers -> sm)
+      }) currentGen + 3 else currentGen + 5)
+
+      ignoredSubsts(this) += ((nextGen, enablers, subst))
     }
 
-    protected def instanceSubst(enablers: Set[T]): Map[T, T]
+    protected def instanceSubst(enabler: T): Map[T, T]
 
     protected def skip(subst: Map[T, Arg[T]]): Boolean = false
   }
@@ -502,7 +540,7 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
     val q2s: (Identifier, T),
     val insts: (Identifier, T),
     val guardVar: T,
-    val quantified: Set[T],
+    val quantifiers: Seq[(Identifier, T)],
     val matchers: Set[Matcher[T]],
     val allMatchers: Map[T, Set[Matcher[T]]],
     val condVars: Map[Identifier, T],
@@ -515,10 +553,10 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
 
     var currentQ2Var: T = qs._2
 
-    protected def instanceSubst(enablers: Set[T]): Map[T, T] = {
+    protected def instanceSubst(enabler: T): Map[T, T] = {
       val nextQ2Var = encoder.encodeId(q2s._1)
 
-      val subst = Map(qs._2 -> currentQ2Var, guardVar -> encodeEnablers(enablers),
+      val subst = Map(qs._2 -> currentQ2Var, guardVar -> enabler,
         q2s._2 -> nextQ2Var, insts._2 -> encoder.encodeId(insts._1))
 
       currentQ2Var = nextQ2Var
@@ -547,7 +585,7 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
     val pathVar: (Identifier, T),
     val blocker: T,
     val guardVar: T,
-    val quantified: Set[T],
+    val quantifiers: Seq[(Identifier, T)],
     val matchers: Set[Matcher[T]],
     val allMatchers: Map[T, Set[Matcher[T]]],
     val condVars: Map[Identifier, T],
@@ -558,11 +596,8 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
     val applications: Map[T, Set[App[T]]],
     val lambdas: Seq[LambdaTemplate[T]]) extends MatcherQuantification {
 
-    protected def instanceSubst(enablers: Set[T]): Map[T, T] = {
-      // no need to add an equality clause here since it is already contained in the Axiom clauses
-      val (newBlocker, optEnabler) = freshBlocker(enablers)
-      val guardT = if (optEnabler.isDefined) encoder.mkAnd(start, optEnabler.get) else start
-      Map(guardVar -> guardT, blocker -> newBlocker)
+    protected def instanceSubst(enabler: T): Map[T, T] = {
+      Map(guardVar -> start, blocker -> enabler)
     }
 
     override protected def skip(subst: Map[T, Arg[T]]): Boolean = {
@@ -599,14 +634,26 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
   }
 
   def instantiateAxiom(template: LambdaTemplate[T], substMap: Map[T, Arg[T]]): Instantiation[T] = {
-    val quantifiers = template.arguments flatMap {
-      case (id, idT) => substMap(idT).left.toOption.map(id -> _)
-    } filter (p => isQuantifier(p._2))
+    def quantifiedMatcher(m: Matcher[T]): Boolean = m.args.exists(a => a match {
+      case Left(v) => isQuantifier(v)
+      case Right(m) => quantifiedMatcher(m)
+    })
+
+    val quantified = template.arguments flatMap {
+      case (id, idT) => substMap(idT) match {
+        case Left(v) if isQuantifier(v) => Some(id)
+        case Right(m) if quantifiedMatcher(m) => Some(id)
+        case _ => None
+      }
+    }
+
+    val quantifiers = quantified zip uniformQuants(quantified)
+    val key = template.key -> quantifiers
 
-    if (quantifiers.isEmpty || lambdaAxioms(template -> quantifiers)) {
+    if (quantifiers.isEmpty || lambdaAxioms(key)) {
       Instantiation.empty[T]
     } else {
-      lambdaAxioms += template -> quantifiers
+      lambdaAxioms += key
       val blockerT = encoder.encodeId(blockerId)
 
       val guard = FreshIdentifier("guard", BooleanType, true)
@@ -676,12 +723,14 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
     var instantiation = Instantiation.empty[T]
 
     for (matchers <- matchQuorums) {
-      val axiom = new LambdaAxiom(pathVar, blocker, guardVar, quantified,
+      val axiom = new LambdaAxiom(pathVar, blocker, guardVar, quantifiers,
         matchers, allMatchers, condVars, exprVars, condTree,
         clauses, blockers, applications, lambdas
       )
 
       quantifications += axiom
+      handledSubsts += axiom -> MutableSet.empty
+      ignoredSubsts += axiom -> MutableSet.empty
 
       val newCtx = new InstantiationContext()
       for ((b,m) <- instCtx.instantiated) {
@@ -722,13 +771,15 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
             template.pathVar,
             template.qs._1 -> newQ,
             template.q2s, template.insts, template.guardVar,
-            quantified, matchers, template.matchers,
+            template.quantifiers, matchers, template.matchers,
             template.condVars, template.exprVars, template.condTree,
             template.clauses map substituter, // one clause depends on 'q' (and therefore 'newQ')
             template.blockers, template.applications, template.lambdas
           )
 
           quantifications += quantification
+          handledSubsts += quantification -> MutableSet.empty
+          ignoredSubsts += quantification -> MutableSet.empty
 
           val newCtx = new InstantiationContext()
           for ((b,m) <- instCtx.instantiated) {
@@ -765,71 +816,108 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage
     instCtx.instantiate(Set(blocker), matcher)(quantifications.toSeq : _*)
   }
 
-  def hasIgnored: Boolean = ignored.nonEmpty
+  def hasIgnored: Boolean = ignoredSubsts.nonEmpty || ignoredMatchers.nonEmpty
 
   def instantiateIgnored: Instantiation[T] = {
     var instantiation = Instantiation.empty[T]
-    for ((b,m) <- ignored.consume) {
+    for ((b,m) <- ignoredMatchers.consume) {
       instantiation ++= instantiateMatcher(b, m)
     }
+
+    val min = minGen
+    val toRelease = quantifications.toList.flatMap { q =>
+      val qsubsts = ignoredSubsts(q)
+      qsubsts.toList.flatMap { case e @ (gen, enablers, subst) =>
+        if (gen == min) {
+          qsubsts -= e
+          Some((q, enablers, subst))
+        } else {
+          None
+        }
+      }
+    }
+
+    for ((q, enablers, subst) <- toRelease) {
+      instantiation ++= q.instantiateSubst(enablers, subst, strict = false)
+    }
+
+    // Note that minGen changed after removing stuff from ignoredSubsts!
+    currentGen = minGen
     instantiation
   }
 
-  private type SetDef = (T, (Identifier, T), (Identifier, T), Seq[T], T, T, T)
-  private val setConstructors: MutableMap[TypeTree, SetDef] = MutableMap.empty
-
   def checkClauses: Seq[T] = {
     val clauses = new scala.collection.mutable.ListBuffer[T]
+    //val keySets = scala.collection.mutable.Map.empty[MatcherKey, T]
+    val keyClause = MutableMap.empty[MatcherKey, (Seq[T], T)]
 
-    for ((key, ctx) <- ignored.instantiations) {
-      val insts = instCtx.map.get(key).toMatchers
-
+    for ((key, ctx) <- ignoredMatchers.instantiations) {
       val QTM(argTypes, _) = key.tpe
-      val tupleType = tupleTypeWrap(argTypes)
-
-      val (guardT, (setPrev, setPrevT), (setNext, setNextT), elems, containsT, emptyT, setT) =
-        setConstructors.getOrElse(tupleType, {
-          val guard = FreshIdentifier("guard", BooleanType)
-          val setPrev = FreshIdentifier("prevSet", SetType(tupleType))
-          val setNext = FreshIdentifier("nextSet", SetType(tupleType))
-          val elems = argTypes.map(tpe => FreshIdentifier("elem", tpe))
-
-          val elemExpr = tupleWrap(elems.map(_.toVariable))
-          val contextExpr = And(
-            Implies(Variable(guard), Equals(Variable(setNext),
-              SetUnion(Variable(setPrev), FiniteSet(Set(elemExpr), tupleType)))),
-            Implies(Not(Variable(guard)), Equals(Variable(setNext), Variable(setPrev))))
-
-          val guardP = guard -> encoder.encodeId(guard)
-          val setPrevP = setPrev -> encoder.encodeId(setPrev)
-          val setNextP = setNext -> encoder.encodeId(setNext)
-          val elemsP = elems.map(e => e -> encoder.encodeId(e))
-
-          val containsT = encoder.encodeExpr(elemsP.toMap + setPrevP)(ElementOfSet(elemExpr, setPrevP._1.toVariable))
-          val emptyT = encoder.encodeExpr(Map.empty)(FiniteSet(Set.empty, tupleType))
-          val contextT = encoder.encodeExpr(Map(guardP, setPrevP, setNextP) ++ elemsP)(contextExpr)
-
-          val setDef = (guardP._2, setPrevP, setNextP, elemsP.map(_._2), containsT, emptyT, contextT)
-          setConstructors += key.tpe -> setDef
-          setDef
-        })
-
-      var prev = emptyT
-      for ((b, m) <- insts.toSeq) {
-        val next = encoder.encodeId(setNext)
-        val argsMap = (elems zip m.args).map { case (idT, arg) => idT -> arg.encoded }
-        val substMap = Map(guardT -> b, setPrevT -> prev, setNextT -> next) ++ argsMap
-        prev = next
-        clauses += encoder.substitute(substMap)(setT)
-      }
 
-      val setMap = Map(setPrevT -> prev)
+      val (values, clause) = keyClause.getOrElse(key, {
+        val insts = instCtx.map.get(key).toMatchers
+
+        val guard = FreshIdentifier("guard", BooleanType)
+        val elems = argTypes.map(tpe => FreshIdentifier("elem", tpe))
+        val values = argTypes.map(tpe => FreshIdentifier("value", tpe))
+        val expr = andJoin(Variable(guard) +: (elems zip values).map(p => Equals(Variable(p._1), Variable(p._2))))
+
+        val guardP = guard -> encoder.encodeId(guard)
+        val elemsP = elems.map(e => e -> encoder.encodeId(e))
+        val valuesP = values.map(v => v -> encoder.encodeId(v))
+        val exprT = encoder.encodeExpr(elemsP.toMap ++ valuesP + guardP)(expr)
+
+        val disjuncts = insts.toSeq.map { case (b, m) =>
+          val subst = (elemsP.map(_._2) zip m.args.map(_.encoded)).toMap + (guardP._2 -> b)
+          encoder.substitute(subst)(exprT)
+        }
+
+        val res = (valuesP.map(_._2), encoder.mkOr(disjuncts : _*))
+        keyClause += key -> res
+        res
+      })
+
       for ((b, m) <- ctx.toSeq) {
-        val substMap = setMap ++ (elems zip m.args).map(p => p._1 -> p._2.encoded)
-        clauses += encoder.substitute(substMap)(encoder.mkImplies(b, containsT))
+        val substMap = (values zip m.args.map(_.encoded)).toMap
+        clauses += encoder.substitute(substMap)(encoder.mkImplies(b, clause))
       }
     }
 
+    for (q <- quantifications) {
+      val guard = FreshIdentifier("guard", BooleanType)
+      val elems = q.quantifiers.map(_._1)
+      val values = elems.map(id => id.freshen)
+      val expr = andJoin(Variable(guard) +: (elems zip values).map(p => Equals(Variable(p._1), Variable(p._2))))
+
+      val guardP = guard -> encoder.encodeId(guard)
+      val elemsP = elems.map(e => e -> encoder.encodeId(e))
+      val valuesP = values.map(v => v -> encoder.encodeId(v))
+      val exprT = encoder.encodeExpr(elemsP.toMap ++ valuesP + guardP)(expr)
+
+      val disjunction = encoder.mkOr(handledSubsts(q).toSeq.map { case (enablers, subst) =>
+        val b = if (enablers.isEmpty) trueT else encoder.mkAnd(enablers.toSeq : _*)
+        val substMap = (elemsP.map(_._2) zip q.quantifiers.map(p => subst(p._2).encoded)).toMap + (guardP._2 -> b)
+        encoder.substitute(substMap)(exprT)
+      } : _*)
+
+      for ((_, enablers, subst) <- ignoredSubsts(q)) {
+        val b = if (enablers.isEmpty) trueT else encoder.mkAnd(enablers.toSeq : _*)
+        val substMap = (valuesP.map(_._2) zip q.quantifiers.map(p => subst(p._2).encoded)).toMap
+        clauses += encoder.substitute(substMap)(encoder.mkImplies(b, disjunction))
+      }
+    }
+
+    for ((key, ctx) <- instCtx.map.instantiations) {
+      val QTM(argTypes, _) = key.tpe
+
+      for {
+        (tpe,idx) <- argTypes.zipWithIndex
+        quants <- uniformQuantMap.get(tpe) if quants.nonEmpty
+        (b, m) <- ctx
+        arg = m.args(idx).encoded if !isQuantifier(arg)
+      } clauses += encoder.mkAnd(quants.map(q => encoder.mkNot(encoder.mkEquals(q, arg))) : _*)
+    }
+
     clauses.toSeq
   }
 }
diff --git a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala
index 2ab8f2b2b52dbf2cc335519e481ed7954e2fa3d6..b9c95ba768064133a64c61ae64efd85360d1fb07 100644
--- a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala
+++ b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala
@@ -398,7 +398,6 @@ class TemplateGenerator[T](val encoder: TemplateEncoder[T],
         }
 
         case c @ Choose(Lambda(params, cond)) =>
-
           val cs = params.map(_.id.freshen.toVariable)
 
           for (c <- cs) {
@@ -411,6 +410,14 @@ class TemplateGenerator[T](val encoder: TemplateEncoder[T],
 
           tupleWrap(cs)
 
+        case FiniteLambda(mapping, dflt, FunctionType(from, to)) =>
+          val args = from.map(tpe => FreshIdentifier("x", tpe))
+          val body = mapping.toSeq.foldLeft(dflt) { case (elze, (exprs, res)) =>
+            IfExpr(andJoin((args zip exprs).map(p => Equals(Variable(p._1), p._2))), res, elze)
+          }
+
+          rec(pathVar, Lambda(args.map(ValDef(_)), body))
+
         case l @ Lambda(args, body) =>
           val idArgs : Seq[Identifier] = lambdaArgs(l)
           val trArgs : Seq[T] = idArgs.map(id => substMap.getOrElse(id, encoder.encodeId(id)))
diff --git a/src/main/scala/leon/solvers/templates/UnrollingBank.scala b/src/main/scala/leon/solvers/templates/UnrollingBank.scala
index 893b39cb82e71bace9f4b26c2696188f825a031f..ce2af7c9e29634ff5a50dc4b493477c63f774229 100644
--- a/src/main/scala/leon/solvers/templates/UnrollingBank.scala
+++ b/src/main/scala/leon/solvers/templates/UnrollingBank.scala
@@ -235,7 +235,8 @@ class UnrollingBank[T <% Printable](ctx: LeonContext, templateGenerator: Templat
   def instantiateQuantifiers: Seq[T] = {
     val (newExprs, callBlocks, appBlocks) = manager.instantiateIgnored
     val blockExprs = freshAppBlocks(appBlocks.keys)
-    val gen = (callInfos.values.map(_._1) ++ appInfos.values.map(_._1)).min
+    val gens = (callInfos.values.map(_._1) ++ appInfos.values.map(_._1))
+    val gen = if (gens.nonEmpty) gens.min else 0
 
     for ((b, newInfos) <- callBlocks) {
       registerCallBlocker(nextGeneration(gen), b, newInfos)
diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
index e2d1ab0fae778878845fa51f85786325a0041c54..f1ee6bfba315c53f4e094a95959039f2c6f7ed72 100644
--- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
+++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
@@ -678,13 +678,13 @@ trait AbstractZ3Solver extends Solver {
                   case None => simplestValue(ft)
                   case Some((_, mapping, elseValue)) =>
                     val leonElseValue = rec(elseValue, tt)
-                    PartialLambda(mapping.flatMap { case (z3Args, z3Result) =>
+                    FiniteLambda(mapping.flatMap { case (z3Args, z3Result) =>
                       if (t == z3Args.head) {
                         List((z3Args.tail zip fts).map(p => rec(p._1, p._2)) -> rec(z3Result, tt))
                       } else {
                         Nil
                       }
-                    }, Some(leonElseValue), ft)
+                    }, leonElseValue, ft)
                 }
               }
 
diff --git a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala
index 812812aa3f4b39a9f3e2994d46080d4b009c0067..7ba4bf9eade43bc1f567e447c067a1e61bf16360 100644
--- a/src/main/scala/leon/solvers/z3/FairZ3Solver.scala
+++ b/src/main/scala/leon/solvers/z3/FairZ3Solver.scala
@@ -35,6 +35,9 @@ class FairZ3Solver(val context: LeonContext, val program: Program)
   protected def hasError   = errors.getB(()) contains true
   protected def addError() = errors += () -> true
 
+  override val name = "Z3-f"
+  override val description = "Fair Z3 Solver"
+
   override protected val reporter = context.reporter
   override def reset(): Unit = super[AbstractZ3Solver].reset()
 
@@ -55,12 +58,14 @@ class FairZ3Solver(val context: LeonContext, val program: Program)
     r
   }
 
+  /*
   override def solverCheckAssumptions[R](assumptions: Seq[Z3AST])(block: Option[Boolean] => R): R = {
     solver.push() // FIXME: remove when z3 bug is fixed
     val res = solver.checkAssumptions(assumptions : _*)
     solver.pop()  // FIXME: remove when z3 bug is fixed
     block(res)
   }
+  */
 
   def solverGetModel: ModelWrapper = new ModelWrapper {
     val model = solver.getModel
diff --git a/src/main/scala/leon/solvers/z3/Z3StringConversion.scala b/src/main/scala/leon/solvers/z3/Z3StringConversion.scala
index 21df018db70935ad63b6c22e7d6bc77894005b23..be5f61fe997c7223fee7ad548c4a700b74597062 100644
--- a/src/main/scala/leon/solvers/z3/Z3StringConversion.scala
+++ b/src/main/scala/leon/solvers/z3/Z3StringConversion.scala
@@ -185,11 +185,11 @@ trait Z3StringConverters  { self: Z3StringConversion =>
         case Variable(id) if bindings contains id => bindings(id).copiedFrom(e)
         case Variable(id) if hasIdConversion(id) => Variable(convertId(id)).copiedFrom(e)
         case Variable(id) => e
-        case pl@PartialLambda(mappings, default, tpe) =>
-          PartialLambda(
+        case pl @ FiniteLambda(mappings, default, tpe) =>
+          FiniteLambda(
               mappings.map(kv => (kv._1.map(argtpe => convertExpr(argtpe)),
                   convertExpr(kv._2))),
-                  default.map(d => convertExpr(d)), convertType(tpe).asInstanceOf[FunctionType])
+                  convertExpr(default), convertType(tpe).asInstanceOf[FunctionType])
         case Lambda(args, body) =>
           println("Converting Lambda :" + e)
           val new_bindings = scala.collection.mutable.ListBuffer[(Identifier, Identifier)]()
@@ -370,4 +370,4 @@ trait Z3StringConverters  { self: Z3StringConversion =>
       case ExprConverted(e) => e
     }
   }
-}
\ No newline at end of file
+}
diff --git a/src/main/scala/leon/synthesis/ExamplesFinder.scala b/src/main/scala/leon/synthesis/ExamplesFinder.scala
index 78a483446624a28482772efe5752a4f6f44e1995..fef98f7d79920b9edcca0e0375a84f253b2f79c6 100644
--- a/src/main/scala/leon/synthesis/ExamplesFinder.scala
+++ b/src/main/scala/leon/synthesis/ExamplesFinder.scala
@@ -25,7 +25,7 @@ class ExamplesFinder(ctx0: LeonContext, program: Program) {
   
   private var keepAbstractExamples = false
   /** If true, will not evaluate examples to check them. */
-  def setKeepAbstractExamples(b: Boolean) = { this.keepAbstractExamples = b; this}
+  def setKeepAbstractExamples(b: Boolean) = { this.keepAbstractExamples = b; this }
   /** Sets if evalution of the result of tests should stop on choose statements.
     * Useful for programming by Example */
   def setEvaluationFailOnChoose(b: Boolean) = { evaluator.setEvaluationFailOnChoose(b); this }