diff --git a/build.sbt b/build.sbt
index 0c1f4400527fe9f724082d5c83f77bb84a38d141..9b0df3e328387f6987f285e165c42f94d3182b07 100644
--- a/build.sbt
+++ b/build.sbt
@@ -16,8 +16,6 @@ scalacOptions ++= Seq(
 
 scalacOptions in (Compile, doc) ++= Seq("-doc-root-content", baseDirectory.value+"/src/main/scala/root-doc.txt")
 
-javacOptions += "-Xlint:unchecked"
-
 site.settings
 
 site.sphinxSupport()
@@ -50,82 +48,12 @@ libraryDependencies ++= Seq(
   //"com.regblanc" %% "scala-smtlib" % "0.2"
 )
 
-lazy val nParallel = {
-  val p = System.getProperty("parallel")
-  if (p ne null) {
-    try {
-      p.toInt
-    } catch {
-      case nfe: NumberFormatException =>
-        1
-    }
-  } else {
-    1
-  }
-}
-
-sourceGenerators in Compile <+= Def.task {
-  val build = (sourceManaged in Compile).value / "inox" / "Build.scala";
-  IO.write(build, s"""|package inox
-                      |
-                      |object Build {
-                      |  val baseDirectory = \"\"\"${baseDirectory.value.toString}\"\"\"
-                      |}""".stripMargin)
-  Seq(build)
-}
-
-
-sourcesInBase in Compile := false
-
 Keys.fork in run := true
 
-
-lazy val testSettings = Seq(
-    //Keys.fork := true,
-    logBuffered := (nParallel > 1),
-    parallelExecution := (nParallel > 1)
-    //testForkedParallel := true,
-    //javaOptions ++= Seq("-Xss64M", "-Xmx4G")
-)
-
-concurrentRestrictions in Global += Tags.limit(Tags.Test, nParallel)
-
 testOptions in Test := Seq(Tests.Argument("-oDF"))
 
 testOptions in IntegrationTest := Seq(Tests.Argument("-oDF"))
 
-// Integration Tests
-//lazy val IntegrTest = config("integration") extend(Test)
-
-//testOptions in IntegrTest := Seq(Tests.Argument("-oDF"), Tests.Filter(_ startsWith "inox.integration."))
-
-
-def regressionFilter(name: String, native: Boolean = false): Boolean = name.startsWith("inox.regression") && (name.endsWith("NativeZ3") == native)
-
-// Regression Tests
-lazy val RegressionTest = config("regression") extend(Test)
-
-testOptions in RegressionTest := Seq(Tests.Argument("-oDF"), Tests.Filter(regressionFilter(_)))
-
-// Regression Tests that heavily depend on native Z3
-lazy val NativeZ3RegressionTest = config("native") extend(Test)
-
-testOptions in NativeZ3RegressionTest := Seq(Tests.Argument("-oDF"), Tests.Filter(regressionFilter(_, native = true)))
-
-parallelExecution in NativeZ3RegressionTest := false
-
-logBuffered in NativeZ3RegressionTest := false
-
-
-// Isabelle Tests
-lazy val IsabelleTest = config("isabelle") extend(Test)
-
-testOptions in IsabelleTest := Seq(Tests.Argument("-oDF"), Tests.Filter(_ startsWith "inox.isabelle."))
-
-parallelExecution in IsabelleTest := false
-fork in IsabelleTest := true
-
-
 def ghProject(repo: String, version: String) = RootProject(uri(s"${repo}#${version}"))
 
 lazy val bonsai      = ghProject("git://github.com/colder/bonsai.git",     "10eaaee4ea0ff6567f4f866922cb871bae2da0ac")
@@ -134,6 +62,10 @@ lazy val scalaSmtlib = ghProject("git://github.com/regb/scala-smtlib.git", "8883
 lazy val root = (project in file("."))
   .configs(IntegrationTest)
   .settings(Defaults.itSettings : _*)
+  .settings(inConfig(IntegrationTest)(Defaults.testTasks ++ Seq(
+    logBuffered := false,
+    parallelExecution := false
+  )) : _*)
   .dependsOn(bonsai)
   .dependsOn(scalaSmtlib)
 
diff --git a/src/it/scala/inox/solvers/unrolling/AssociativeQuantifiersSuite.scala b/src/it/scala/inox/solvers/unrolling/AssociativeQuantifiersSuite.scala
index df07e5468621937b44387befe2445f9878763af4..5385e3a88a3b48cee3e321ed2132eed455699410 100644
--- a/src/it/scala/inox/solvers/unrolling/AssociativeQuantifiersSuite.scala
+++ b/src/it/scala/inox/solvers/unrolling/AssociativeQuantifiersSuite.scala
@@ -35,7 +35,7 @@ class AssociativeQuantifiersSuite extends SolvingTestSuite {
     isRotateID      -> isRotate
   ), Map.empty)
 
-  ignore("Pair of associative ==> associative pair") { ctx => 
+  test("Pair of associative ==> associative pair") { ctx => 
     val program = InoxProgram(ctx, symbols)
 
     val (aT,bT) = (T("A"), T("B"))
@@ -47,7 +47,7 @@ class AssociativeQuantifiersSuite extends SolvingTestSuite {
     assert(SimpleSolverAPI(SolverFactory.default(program)).solveSAT(clause).isUNSAT)
   }
 
-  ignore("Commutative and rotate ==> associative") { ctx =>
+  test("Commutative and rotate ==> associative") { ctx =>
     val program = InoxProgram(ctx, symbols)
 
     val aT = T("A")
@@ -57,7 +57,7 @@ class AssociativeQuantifiersSuite extends SolvingTestSuite {
     assert(SimpleSolverAPI(SolverFactory.default(program)).solveSAT(clause).isUNSAT)
   }
 
-  ignore("Commutative and rotate ==> associative (integer type)") { ctx =>
+  test("Commutative and rotate ==> associative (integer type)") { ctx =>
     val program = InoxProgram(ctx, symbols)
 
     val f = ("f" :: ((IntegerType, IntegerType) =>: IntegerType)).toVariable
@@ -66,7 +66,7 @@ class AssociativeQuantifiersSuite extends SolvingTestSuite {
     assert(SimpleSolverAPI(SolverFactory.default(program)).solveSAT(clause).isUNSAT)
   }
 
-  ignore("Associatve =!=> commutative") { ctx =>
+  test("Associatve =!=> commutative") { ctx =>
     val program = InoxProgram(ctx, symbols)
 
     val aT = T("A")
@@ -76,7 +76,7 @@ class AssociativeQuantifiersSuite extends SolvingTestSuite {
     assert(SimpleSolverAPI(SolverFactory.default(program)).solveSAT(clause).isSAT)
   }
 
-  ignore("Commutative =!=> associative") { ctx =>
+  test("Commutative =!=> associative") { ctx =>
     val program = InoxProgram(ctx, symbols)
 
     val aT = T("A")
diff --git a/src/it/scala/inox/solvers/unrolling/InductiveUnrollingSuite.scala b/src/it/scala/inox/solvers/unrolling/InductiveUnrollingSuite.scala
index aabaeca997e6987049c42b20c8222b87b32a9376..5484297fd89083e9f2779377fa04fbdd8e1d76d8 100644
--- a/src/it/scala/inox/solvers/unrolling/InductiveUnrollingSuite.scala
+++ b/src/it/scala/inox/solvers/unrolling/InductiveUnrollingSuite.scala
@@ -8,6 +8,110 @@ class InductiveUnrollingSuite extends SolvingTestSuite {
   import trees._
   import dsl._
 
-  
+  val listID = FreshIdentifier("List")
+  val consID = FreshIdentifier("Cons")
+  val nilID  = FreshIdentifier("Nil")
+
+  val head = FreshIdentifier("head")
+  val tail = FreshIdentifier("tail")
+
+  val List = mkAbstractClass(listID)("A")(Seq(consID, nilID))
+  val Nil  = mkCaseClass(nilID)("A")(Some(listID))(_ => Seq.empty)
+  val Cons = mkCaseClass(consID)("A")(Some(listID)) {
+    case Seq(aT) => Seq(ValDef(head, aT), ValDef(tail, T(listID)(aT)))
+  }
+
+  val sizeID = FreshIdentifier("size")
+  val sizeFd = mkFunDef(sizeID)("A") { case Seq(aT) => (
+    Seq("l" :: T(listID)(aT)), IntegerType, { case Seq(l) =>
+      if_ (l.isInstOf(T(consID)(aT))) {
+        E(BigInt(1)) + let("res" :: IntegerType, E(sizeID)(aT)(l.asInstOf(T(consID)(aT)).getField(tail))) {
+          res => Assume(res >= E(BigInt(0)), res)
+        }
+      } else_ {
+        E(BigInt(0))
+      }
+    })
+  }
+
+  val appendID = FreshIdentifier("append")
+  val append = mkFunDef(appendID)("A") { case Seq(aT) => (
+    Seq("l1" :: T(listID)(aT), "l2" :: T(listID)(aT)), T(listID)(aT), { case Seq(l1, l2) =>
+      if_ (l1.isInstOf(T(consID)(aT))) {
+        let("c" :: T(listID)(aT), l1.asInstOf(T(consID)(aT))) { c =>
+          T(consID)(aT)(c.getField(head), E(appendID)(aT)(c.getField(tail), l2))
+        }
+      } else_ {
+        l2
+      }
+    })
+  }
+
+  val flatMapID = FreshIdentifier("flatMap")
+  val flatMap = mkFunDef(flatMapID)("A","B") { case Seq(aT, bT) => (
+    Seq("l" :: T(listID)(aT), "f" :: (aT =>: T(listID)(bT))), T(listID)(bT), { case Seq(l, f) =>
+      if_ (l.isInstOf(T(consID)(aT))) {
+        let("c" :: T(consID)(aT), l.asInstOf(T(consID)(aT))) { c =>
+          append(bT)(f(c.getField(head)), E(flatMapID)(aT,bT)(c.getField(tail), f))
+        }
+      } else_ {
+        T(nilID)(bT)()
+      }
+    })
+  }
+
+  val assocID = FreshIdentifier("associative_lemma")
+  val associative = mkFunDef(assocID)("A","B","C") { case Seq(aT, bT, cT) => (
+    Seq("l1" :: T(listID)(aT), "l2" :: T(listID)(bT), "l3" :: T(listID)(cT),
+      "f" :: (aT =>: T(listID)(bT)), "g" :: (bT =>: T(listID)(cT))), BooleanType,
+      { case Seq(l1, l2, l3, f, g) =>
+        (if_ (l3.isInstOf(T(consID)(cT))) {
+          Assume(E(assocID)(aT, bT, cT)(l1, l2, l3.asInstOf(T(consID)(cT)).getField(tail), f, g), E(true))
+        } else_ {
+          if_ (l2.isInstOf(T(consID)(bT))) {
+            let("c" :: T(consID)(bT), l2.asInstOf(T(consID)(bT))) { c =>
+              Assume(E(assocID)(aT, bT, cT)(l1, c.getField(tail), g(c.getField(head)), f, g), E(true))
+            }
+          } else_ {
+            if_ (l1.isInstOf(T(consID)(aT))) {
+              let("c" :: T(consID)(aT), l1.asInstOf(T(consID)(aT))) { c =>
+                Assume(E(assocID)(aT, bT, cT)(c.getField(tail), f(c.getField(head)), T(nilID)(cT)(), f, g), E(true))
+              }
+            } else_ {
+              E(true)
+            }
+          }
+        }) && append(cT)(l3, flatMap(bT,cT)(append(bT)(l2, flatMap(aT,bT)(l1, f)), g)) ===
+          append(cT)(append(cT)(l3, flatMap(bT,cT)(l2, g)), flatMap(aT,cT)(l1, \("x" :: aT) { x =>
+            flatMap(bT,cT)(f(x), g)
+          }))
+      })
+  }
+
+  val symbols = new Symbols(
+    Map(sizeID -> sizeFd, appendID -> append, flatMapID -> flatMap, assocID -> associative),
+    Map(listID -> List, consID -> Cons, nilID -> Nil)
+  )
+
+  test("size(x) == 0 is satisfiable") { ctx =>
+    val program = InoxProgram(ctx, symbols)
+    val vd = "x" :: T(listID)(IntegerType)
+    val clause = sizeFd(IntegerType)(vd.toVariable) === E(BigInt(0))
+
+    assert(SimpleSolverAPI(SolverFactory.default(program)).solveSAT(clause).isSAT)
+  }
+
+  test("size(x) < 0 is unsatisfiable") { ctx =>
+    val program = InoxProgram(ctx, symbols)
+    val vd = "x" :: T(listID)(IntegerType)
+    val clause = sizeFd(IntegerType)(vd.toVariable) < E(BigInt(0))
+
+    assert(SimpleSolverAPI(SolverFactory.default(program)).solveSAT(clause).isUNSAT)
+  }
+
+  test("flatMap is associative") { ctx =>
+    val program = InoxProgram(ctx, symbols)
+    assert(SimpleSolverAPI(SolverFactory.default(program)).solveSAT(Not(associative.fullBody)).isUNSAT)
+  }
 
 }
diff --git a/src/it/scala/inox/solvers/unrolling/SimpleUnrollingSuite.scala b/src/it/scala/inox/solvers/unrolling/SimpleUnrollingSuite.scala
index 24d46a798a0dacda2d523883bb6fb46813b9dd51..dcc1bcaa286dbf294054d3f967c1d52c014c1a66 100644
--- a/src/it/scala/inox/solvers/unrolling/SimpleUnrollingSuite.scala
+++ b/src/it/scala/inox/solvers/unrolling/SimpleUnrollingSuite.scala
@@ -69,7 +69,7 @@ class SimpleUnrollingSuite extends SolvingTestSuite {
     SimpleSolverAPI(SolverFactory.default(program)).solveSAT(clause) match {
       case SatWithModel(model) =>
         symbols.valuateWithModel(model)(vd) match {
-          case CaseClass(ClassType(`nilID`, Seq(tp)), Seq()) =>
+          case CaseClass(ClassType(`nilID`, Seq(`tp`)), Seq()) =>
             // success!!
           case r =>
             fail("Unexpected valuation: " + r)
diff --git a/src/main/scala/inox/ast/DSL.scala b/src/main/scala/inox/ast/DSL.scala
index 08bdff350c56aba311e404175b16b6e643584f0e..52a867c9634d8b29625c27ddf217680b2619ae10 100644
--- a/src/main/scala/inox/ast/DSL.scala
+++ b/src/main/scala/inox/ast/DSL.scala
@@ -93,14 +93,11 @@ trait DSL {
   }
 
   // if-then-else
-  class DanglingElse private[DSL] (condThens: Seq[(Expr, Expr)]) {
-    def else_if (cond2: Expr)(thenn2: Expr) = new DanglingElse(condThens :+ (cond2 -> thenn2))
-    def else_ (theElse: Expr) = condThens.foldRight(theElse) {
-      case ((cond, thenn), elze) =>IfExpr(cond, thenn, elze)
-    }
+  class DanglingElse private[DSL] (theCond: Expr, theThen: Expr) {
+    def else_ (theElse: Expr) = IfExpr(theCond, theThen, theElse)
   }
 
-  def if_ (cond: Expr)(thenn: Expr) = new DanglingElse(Seq(cond -> thenn))
+  def if_ (cond: Expr)(thenn: Expr) = new DanglingElse(cond, thenn)
 
   def ite(cond: Expr, thenn: Expr, elze: Expr) = IfExpr(cond, thenn, elze)
 
diff --git a/src/main/scala/inox/ast/Extractors.scala b/src/main/scala/inox/ast/Extractors.scala
index 37152452c8616e2a47c36b0d49c12f14dddb0e5c..81c60e0dc56b32a15562ee4a3bd18db9c3717ecd 100644
--- a/src/main/scala/inox/ast/Extractors.scala
+++ b/src/main/scala/inox/ast/Extractors.scala
@@ -104,6 +104,8 @@ trait TreeDeconstructor {
       (Seq(t1, t2), Seq(), (es, tps) => t.MapApply(es(0), es(1)))
     case s.Let(binder, e, body) =>
       (Seq(e, body), Seq(binder.tpe), (es, tps) => t.Let(t.ValDef(binder.id, tps.head), es(0), es(1)))
+    case s.Assume(pred, body) =>
+      (Seq(pred, body), Seq(), (es, tps) => t.Assume(es(0), es(1)))
 
     /* Other operators */
     case s.FunctionInvocation(id, tps, args) =>
diff --git a/src/main/scala/inox/ast/SymbolOps.scala b/src/main/scala/inox/ast/SymbolOps.scala
index c45a91102740ba3cd59a0468e7309da5fb7bfef7..f26a9be3a25824e2e4f5d52aeb88173d35043381 100644
--- a/src/main/scala/inox/ast/SymbolOps.scala
+++ b/src/main/scala/inox/ast/SymbolOps.scala
@@ -189,23 +189,37 @@ trait SymbolOps { self: TypeOps =>
     * quantification instantiations.
     */
   def simplifyQuantifications(e: Expr): Expr = {
-    val fds = functionCallsOf(e).flatMap { fi =>
-      val fd = fi.tfd.fd
-      transitiveCallees(fd) + fd
+
+    def inlineFunctions(e: Expr): Expr = {
+      val fds = functionCallsOf(e).flatMap { fi =>
+        val fd = fi.tfd.fd
+        transitiveCallees(fd) + fd
+      }
+
+      val fdsToInline = fds
+        .filterNot(fd => transitivelyCalls(fd, fd))
+        .filter(fd => exists { case _: Forall => true case _ => false }(fd.fullBody))
+      
+      def inline(e: Expr): Expr = {
+        val subst = functionCallsOf(e)
+          .filter(fi => fdsToInline(fi.tfd.fd))
+          .map(fi => fi -> fi.inlined)
+        replace(subst.toMap, e)
+      }
+
+      fixpoint(inline)(e)
     }
 
-    val fdsToInline = fds
-      .filterNot(fd => transitivelyCalls(fd, fd))
-      .filter(fd => exists { case _: Forall => true case _ => false }(fd.fullBody))
-    
-    def inline(e: Expr): Expr = {
-      val subst = functionCallsOf(e)
-        .filter(fi => fdsToInline(fi.tfd.fd))
-        .map(fi => fi -> fi.inlined)
-      replace(subst.toMap, e)
+    /* Weaker variant of disjunctive normal form */
+    def normalizeClauses(e: Expr): Expr = e match {
+      case Not(Not(e)) => normalizeClauses(e)
+      case Not(Or(es)) => andJoin(es.map(e => normalizeClauses(Not(e))))
+      case Not(Implies(e1, e2)) => and(normalizeClauses(e1), normalizeClauses(Not(e2)))
+      case And(es) => andJoin(es map normalizeClauses)
+      case _ => e
     }
 
-    fixpoint(inline)(e)
+    normalizeClauses(inlineFunctions(e))
   }
 
   /** Fully expands all let expressions. */
diff --git a/src/main/scala/inox/solvers/unrolling/QuantificationTemplates.scala b/src/main/scala/inox/solvers/unrolling/QuantificationTemplates.scala
index 27f1edf537fd4e19cd7644db1f51e502096b3da9..b1333121596cc94a15ccee53a63f7849e2cae6c6 100644
--- a/src/main/scala/inox/solvers/unrolling/QuantificationTemplates.scala
+++ b/src/main/scala/inox/solvers/unrolling/QuantificationTemplates.scala
@@ -198,6 +198,7 @@ trait QuantificationTemplates { self: Templates =>
 
     val ignoredSubsts   = new IncrementalMap[Quantification, Set[(Int, Set[Encoded], Map[Encoded,Arg])]]
     val handledSubsts   = new IncrementalMap[Quantification, Set[(Set[Encoded], Map[Encoded,Arg])]]
+    val ignoredGrounds  = new IncrementalMap[Int, Set[Quantification]]
 
     val lambdaAxioms    = new IncrementalSet[(LambdaStructure, Seq[(Variable, Encoded)])]
     val templates       = new IncrementalMap[(Seq[ValDef], Expr, Seq[Encoded]), Map[Encoded, Encoded]]
@@ -217,7 +218,9 @@ trait QuantificationTemplates { self: Templates =>
     def refutationAssumptions = assumptions
 
     def unrollGeneration: Option[Int] = {
-      val gens: Seq[Int] = ignoredMatchers.toSeq.map(_._1) ++ ignoredSubsts.flatMap(p => p._2.map(_._1))
+      val gens: Seq[Int] = ignoredMatchers.toSeq.map(_._1) ++
+        ignoredSubsts.flatMap(p => p._2.map(_._1)) ++
+        ignoredGrounds.map(_._1)
       if (gens.isEmpty) None else Some(gens.min)
     }
 
@@ -227,15 +230,23 @@ trait QuantificationTemplates { self: Templates =>
     def unroll: Clauses = {
       val clauses = new scala.collection.mutable.ListBuffer[Encoded]
 
-      for (e @ (gen, bs, m) <- ignoredMatchers.toSeq if gen == currentGeneration) {
+      for (e @ (gen, bs, m) <- ignoredMatchers.toSeq if gen <= currentGeneration) {
         clauses ++= instantiateMatcher(bs, m)
         ignoredMatchers -= e
       }
 
-      for (q <- quantifications.toSeq) {
-        val (release, keep) = ignoredSubsts(q).partition(_._1 == currentGeneration)
-        for ((_, bs, subst) <- release) clauses ++= q.instantiateSubst(bs, subst)
+      for (q <- quantifications.toSeq if ignoredSubsts.isDefinedAt(q)) {
+        val (release, keep) = ignoredSubsts(q).partition(_._1 <= currentGeneration)
         ignoredSubsts += q -> keep
+
+        for ((_, bs, subst) <- release) {
+          clauses ++= q.instantiateSubst(bs, subst)
+        }
+      }
+
+      for ((gen, qs) <- ignoredGrounds.toSeq if gen <= currentGeneration; q <- qs) {
+        clauses ++= q.ensureGrounds
+        ignoredGrounds += gen -> (ignoredGrounds.getOrElse(gen, Set.empty) - q)
       }
 
       clauses.toSeq
@@ -250,7 +261,6 @@ trait QuantificationTemplates { self: Templates =>
     if (handledMatchers(blockers -> matcher)) {
       Seq.empty
     } else {
-      //println(blockers -> matcher)
       handledMatchers += blockers -> matcher
       quantifications.flatMap(_.instantiate(blockers, matcher))
     }
@@ -447,7 +457,8 @@ trait QuantificationTemplates { self: Templates =>
       val instantiation = new scala.collection.mutable.ListBuffer[Encoded]
       for (p @ (bs, subst) <- substs if !handledSubsts.get(this).exists(_ contains p)) {
         if (subst.values.exists(_.isRight)) {
-          ignoredSubsts += this -> (ignoredSubsts.getOrElse(this, Set.empty) + ((currentGeneration + 3, bs, subst)))
+          val gen = currentGeneration + 3 * subst.values.collect { case Right(m) => totalDepth(m) }.sum
+          ignoredSubsts += this -> (ignoredSubsts.getOrElse(this, Set.empty) + ((gen, bs, subst)))
         } else {
           instantiation ++= instantiateSubst(bs, subst)
         }
@@ -692,7 +703,8 @@ trait QuantificationTemplates { self: Templates =>
               clauses ++= axiom.instantiate(bs, m)
             }
 
-            clauses ++= axiom.ensureGrounds
+            val groundGen = currentGeneration + 3
+            ignoredGrounds += groundGen -> (ignoredGrounds.getOrElse(groundGen, Set.empty) + axiom)
             Map.empty
 
           case Negative(insts) =>
@@ -747,7 +759,7 @@ trait QuantificationTemplates { self: Templates =>
 
     val diff = (currentGeneration - optGen.get) max 0
     val currentMatchers = ignoredMatchers.toSeq
-    ignoredMatchers.clear
+    ignoredMatchers.clear()
     for ((gen, bs, m) <- currentMatchers) {
       ignoredMatchers += ((gen - diff, bs, m))
     }
diff --git a/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala b/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala
index dbe6ba29b30e75fa5a5b39e579b1299e73fd9311..4918b5c9ad3eb2997ac0cf89b570badb496e0984 100644
--- a/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala
+++ b/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala
@@ -215,41 +215,49 @@ trait AbstractUnrollingSolver
             }
           }.distinct
 
-          val default = if (allImages.isEmpty) {
+          def mkLambda(params: Seq[ValDef], body: Expr): Lambda = body.getType match {
+            case FunctionType(from, to) =>
+              val (rest, curr) = params.splitAt(params.size - from.size)
+              mkLambda(rest, Lambda(curr, body))
+            case _ => Lambda(params, body)
+          }
+
+          if (allImages.isEmpty) {
             def rec(e: Expr): Expr = e match {
               case Lambda(_, body) => rec(body)
               case IfExpr(_, _, elze) => rec(elze)
               case e => e
             }
 
-            rec(f)
+            mkLambda(params.map(_.toVal), rec(f))
           } else {
-            val optDefault = allImages.collectFirst {
-              case (firstArg +: otherArgs, result) if otherArgs.forall { o =>
-                evaluator.eval(Equals(firstArg, o)).result == Some(BooleanLiteral(true))
-              } => result
+            val projection: Expr = allImages.head._1.head
+
+            val allResults: Seq[(Seq[Expr], Expr)] =
+              (for (subset <- params.toSet.subsets; (args, _) <- allImages) yield {
+                val (concreteArgs, condOpts) = (params zip args).map { case (v, arg) =>
+                  if (!subset(v)) {
+                    (arg, Some(Equals(v, arg)))
+                  } else {
+                    (projection, None)
+                  }
+                }.unzip
+
+                val app = templates.mkApplication(f, concreteArgs)
+                val result = evaluator.eval(app).result.getOrElse {
+                  scala.sys.error("Unexpectedly failed to evaluate " + app.asString)
+                }
+
+                condOpts.flatten -> result
+              }).toSeq
+
+            val withConds :+ ((Seq(), default)) = allResults
+            val body = withConds.foldRight(default) { case ((conds, result), elze) =>
+              IfExpr(andJoin(conds), result, elze)
             }
 
-            optDefault.getOrElse {
-              val app = templates.mkApplication(f, Seq.fill(from.size)(allImages.head._1.head))
-              evaluator.eval(app).result.getOrElse {
-                scala.sys.error("Unexpectedly failed to evaluate " + app.asString)
-              }
-            }
+            mkLambda(params.map(_.toVal), body)
           }
-
-          val body = allImages.foldRight(default) { case ((args, result), elze) =>
-            IfExpr(andJoin((params zip args).map(p => Equals(p._1, p._2))), result, elze)
-          }
-
-          def mkLambda(params: Seq[ValDef], body: Expr): Lambda = body.getType match {
-            case FunctionType(from, to) =>
-              val (rest, curr) = params.splitAt(params.size - from.size)
-              mkLambda(rest, Lambda(curr, body))
-            case _ => Lambda(params, body)
-          }
-
-          mkLambda(params.map(_.toVal), body)
         }
       })
     }
@@ -305,7 +313,7 @@ trait AbstractUnrollingSolver
 
           val checkConfig = config
             .min(Configuration(model = !templates.requiresFiniteRangeCheck, unsatAssumptions = true))
-            .max(Configuration(model = false, unsatAssumptions = unrollAssumptions))
+            .max(Configuration(model = false, unsatAssumptions = unrollAssumptions && templates.canUnroll))
 
           val timer = ctx.timers.solvers.check.start()
           val res: SolverResponse[underlying.Model, Set[underlying.Trees]] =
diff --git a/src/main/scala/inox/utils/IncrementalSeq.scala b/src/main/scala/inox/utils/IncrementalSeq.scala
index 737cd224af7c67749326288b77fe14828a6fea49..2d8bee0d4cbe68a20d874758c16f4f7e7dc86a8f 100644
--- a/src/main/scala/inox/utils/IncrementalSeq.scala
+++ b/src/main/scala/inox/utils/IncrementalSeq.scala
@@ -17,11 +17,11 @@ class IncrementalSeq[A] extends IncrementalState
 
   def clear() : Unit = {
     stack.clear()
+    stack.push(new ArrayBuffer())
   }
 
   def reset(): Unit = {
     clear()
-    stack.push(new ArrayBuffer())
   }
 
   def push(): Unit = {