diff --git a/mytest/Epsilon1.scala b/mytest/Epsilon1.scala
new file mode 100644
index 0000000000000000000000000000000000000000..827c1e6e5a1de4363b7fc61bf7ceeba07c85ac2e
--- /dev/null
+++ b/mytest/Epsilon1.scala
@@ -0,0 +1,13 @@
+import leon.Utils._
+
+object Epsilon1 {
+
+  def greater(x: Int): Int = {
+    epsilon((y: Int) => y > x)
+  } ensuring(_ >= x)
+
+  def greaterWrong(x: Int): Int = {
+    epsilon((y: Int) => y >= x)
+  } ensuring(_ > x)
+
+}
diff --git a/mytest/Epsilon2.scala b/mytest/Epsilon2.scala
new file mode 100644
index 0000000000000000000000000000000000000000..1bf56bdd7b517c1c895ffe478046f4443856ea1e
--- /dev/null
+++ b/mytest/Epsilon2.scala
@@ -0,0 +1,23 @@
+import leon.Utils._
+
+object Epsilon1 {
+
+  def rand(): Int = epsilon((x: Int) => true)
+  def rand2(x: Int): Int = epsilon((y: Int) => true)
+  def rand3(x: Int): Int = epsilon((y: Int) => x == x)
+
+  //this should hold, that is the expected semantic of our epsilon
+  def property1(): Boolean = {
+    rand() == rand() 
+  } holds
+
+  //this should hold, that is the expected semantic of our epsilon
+  def property2(x: Int): Boolean = {
+    rand2(x) == rand2(x+1) 
+  } holds
+
+  //this should NOT hold
+  def property3(x: Int): Boolean = {
+    rand3(x) == rand3(x+1)
+  } holds
+}
diff --git a/mytest/Sets2.scala b/mytest/Sets2.scala
new file mode 100644
index 0000000000000000000000000000000000000000..14e636924d9c44a660a6d168b0a7a6badc5c8307
--- /dev/null
+++ b/mytest/Sets2.scala
@@ -0,0 +1,29 @@
+import leon.Annotations._
+import leon.Utils._
+
+object Sets2 {
+  sealed abstract class MyList
+  case class MyCons(head: Int, tail: MyList) extends MyList
+  case class MyNil() extends MyList
+
+  def size(lst: MyList): Int = (lst match {
+    case MyNil() => 0
+    case MyCons(_, xs) => 1 + size(xs)
+  })
+
+  def toSet(lst: MyList): Set[Int] = lst match {
+    case MyCons(x, xs) => toSet(xs) ++ Set(x)
+    case MyNil() => Set[Int]()
+  }
+
+  def toList(set: Set[Int]): MyList = if(set == Set.empty[Int]) MyNil() else {
+    val elem = epsilon((x : Int) => set contains x)
+    MyCons(elem, toList(set -- Set[Int](elem)))
+  }
+
+  @induct
+  def property(lst: MyList): Boolean = (size(toList(toSet(lst))) <= size(lst)) holds
+
+  def wrongProperty0(lst: MyList): Boolean = (size(toList(toSet(lst))) == size(lst)) holds
+  def wrongProperty1(lst: MyList): Boolean = (toList(toSet(lst)) == lst) holds
+}
diff --git a/src/main/scala/leon/EpsilonElimination.scala b/src/main/scala/leon/EpsilonElimination.scala
new file mode 100644
index 0000000000000000000000000000000000000000..585888f4c771ea6354df64f8792d0becd90dea52
--- /dev/null
+++ b/src/main/scala/leon/EpsilonElimination.scala
@@ -0,0 +1,33 @@
+package leon
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Trees._
+import purescala.TypeTrees._
+
+object EpsilonElimination extends Pass {
+
+  val description = "Remove all epsilons from the program"
+
+  def apply(pgm: Program): Program = {
+
+    val allFuns = pgm.definedFunctions
+    allFuns.foreach(fd => fd.body.map(body => {
+      val newBody = searchAndReplaceDFS{
+        case eps@Epsilon(pred) => {
+          val freshName = FreshIdentifier("epsilon")
+          val newFunDef = new FunDef(freshName, eps.getType, Seq())
+          val epsilonVar = EpsilonVariable(eps.posIntInfo)
+          val resultVar = ResultVariable().setType(eps.getType)
+          val postcondition = replace(Map(epsilonVar -> resultVar), pred)
+          newFunDef.postcondition = Some(postcondition)
+          Some(LetDef(newFunDef, FunctionInvocation(newFunDef, Seq())))
+        }
+        case _ => None
+      }(body)
+      fd.body = Some(newBody)
+    }))
+    pgm
+  }
+
+}
diff --git a/src/main/scala/leon/Evaluator.scala b/src/main/scala/leon/Evaluator.scala
index 72c62ef152b58b54a563ceb9e238c129af5a565c..6bb9ef1b3f4bc7fcfbcb9e719c36325a7759bd85 100644
--- a/src/main/scala/leon/Evaluator.scala
+++ b/src/main/scala/leon/Evaluator.scala
@@ -24,11 +24,16 @@ object Evaluator {
   case class InfiniteComputation() extends EvaluationResult {
     val finalResult = None
   }
+  case class PostconditionViolationFunctionFromModel() extends EvaluationResult {
+    val finalResult = None
+  }
+  
 
   def eval(context: EvaluationContext, expression: Expr, evaluator: Option[(EvaluationContext)=>Boolean], maxSteps: Int=500000) : EvaluationResult = {
     case class RuntimeErrorEx(msg: String) extends Exception
     case class InfiniteComputationEx() extends Exception
     case class TypeErrorEx(typeError: TypeError) extends Exception
+    case class PostconditionViolationFunctionFromModelEx() extends Exception
 
     var left: Int = maxSteps
 
@@ -85,16 +90,18 @@ object Evaluator {
             }
           }
 
-          if(!fd.hasBody) {
+          if(!fd.hasBody && !context.isDefinedAt(fd.id)) {
             throw RuntimeErrorEx("Evaluation of function with unknown implementation.")
           }
-          val callResult = rec(frame, matchToIfThenElse(fd.body.get))
+          val body = fd.body.getOrElse(context(fd.id))
+          val callResult = rec(frame, matchToIfThenElse(body))
 
           if(fd.hasPostcondition) {
             val freshResID = FreshIdentifier("result").setType(fd.returnType)
             val postBody = replace(Map(ResultVariable() -> Variable(freshResID)), matchToIfThenElse(fd.postcondition.get))
             rec(frame + ((freshResID -> callResult)), postBody) match {
               case BooleanLiteral(true) => ;
+              case BooleanLiteral(false) if !fd.hasImplementation => throw PostconditionViolationFunctionFromModelEx()
               case BooleanLiteral(false) => throw RuntimeErrorEx("Postcondition violation for " + fd.id.name + " reached in evaluation.")
               case other => throw TypeErrorEx(TypeError(other, BooleanType))
             }
@@ -306,6 +313,7 @@ object Evaluator {
           case RuntimeErrorEx(msg) => RuntimeError(msg)
           case InfiniteComputationEx() => InfiniteComputation()
           case TypeErrorEx(te) => te
+          case PostconditionViolationFunctionFromModelEx() => PostconditionViolationFunctionFromModel()
         }
     }
   }
diff --git a/src/main/scala/leon/FairZ3Solver.scala b/src/main/scala/leon/FairZ3Solver.scala
index d70d665fdb4e1281e490ab7640794c9b36360373..ebca10ab29caa0c40c4742dc0a37c3c1bcc655d3 100644
--- a/src/main/scala/leon/FairZ3Solver.scala
+++ b/src/main/scala/leon/FairZ3Solver.scala
@@ -581,9 +581,11 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S
           }
         }
         case (Some(true), m) => { // SAT
-          //println("MODEL IS: " + m)
           validatingStopwatch.start
-          val (trueModel, model) = validateAndDeleteModel(m, toCheckAgainstModels, varsInVC, evaluator)
+          val (trueModel, model) = if(Settings.verifyModel)
+              validateAndDeleteModel(m, toCheckAgainstModels, varsInVC, evaluator)
+            else 
+              (true, modelToMap(m, varsInVC))
           validatingStopwatch.stop
 
           if (trueModel) {
@@ -779,7 +781,33 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S
     import Evaluator._
 
     if(!forceStop) {
-      val asMap = modelToMap(model, variables)
+
+      val functionsModel: Map[Z3FuncDecl, (Seq[(Seq[Z3AST], Z3AST)], Z3AST)] = model.getModelFuncInterpretations.map(i => (i._1, (i._2, i._3))).toMap
+      val functionsAsMap: Map[Identifier, Expr] = functionsModel.flatMap(p => {
+        if(isKnownDecl(p._1)) {
+          val fd = functionDeclToDef(p._1)
+          if(!fd.hasImplementation) {
+            val (cses, default) = p._2 
+            val ite = cses.foldLeft(fromZ3Formula(model, default, Some(fd.returnType)))((expr, q) => IfExpr(
+                            And(
+                              q._1.zip(fd.args).map(a12 => Equals(fromZ3Formula(model, a12._1, Some(a12._2.tpe)), Variable(a12._2.id)))
+                            ),
+                            fromZ3Formula(model, q._2, Some(fd.returnType)),
+                            expr))
+            Seq((fd.id, ite))
+          } else Seq()
+        } else Seq()
+      }).toMap
+      val constantFunctionsAsMap: Map[Identifier, Expr] = model.getModelConstantInterpretations.flatMap(p => {
+        if(isKnownDecl(p._1)) {
+          val fd = functionDeclToDef(p._1)
+          if(!fd.hasImplementation) {
+            Seq((fd.id, fromZ3Formula(model, p._2, Some(fd.returnType))))
+          } else Seq()
+        } else Seq()
+      }).toMap
+
+      val asMap = modelToMap(model, variables) ++ functionsAsMap ++ constantFunctionsAsMap
       model.delete
       lazy val modelAsString = asMap.toList.map(p => p._1 + " -> " + p._2).mkString("\n")
       val evalResult = eval(asMap, formula, evaluator)
@@ -799,6 +827,10 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S
           reporter.info("- Invalid model.")
           (false, asMap)
         }
+        case PostconditionViolationFunctionFromModel() => {
+          reporter.info("- Invalid Model: postcondition violation of a function that whose implementation was specified by the model")
+          (false, asMap)
+        }
         case other => {
           reporter.error("Something went wrong. While evaluating the model, we got this: " + other)
           (false, asMap)
diff --git a/src/main/scala/leon/FunctionClosure.scala b/src/main/scala/leon/FunctionClosure.scala
index 0bcfa566e996e4f8d9ebe572bce0979ab37c565c..172281235e2c40aef6583c64156f991d90a6c6d3 100644
--- a/src/main/scala/leon/FunctionClosure.scala
+++ b/src/main/scala/leon/FunctionClosure.scala
@@ -13,7 +13,6 @@ object FunctionClosure extends Pass {
 
   private var pathConstraints: List[Expr] = Nil
   private var newFunDefs: Map[FunDef, FunDef] = Map()
-  //private var 
 
   def apply(program: Program): Program = {
     newFunDefs = Map()
@@ -21,7 +20,8 @@ object FunctionClosure extends Pass {
     funDefs.foreach(fd => {
       enclosingPreconditions = fd.precondition.toList
       pathConstraints = fd.precondition.toList
-      fd.body = Some(functionClosure(fd.getBody, fd.args.map(_.id).toSet))
+      fd.body = fd.body.map(b => functionClosure(b, fd.args.map(_.id).toSet))
+      fd.postcondition = fd.postcondition.map(b => functionClosure(b, fd.args.map(_.id).toSet))
     })
     program
   }
@@ -32,11 +32,13 @@ object FunctionClosure extends Pass {
       val id = fd.id
       val rt = fd.returnType
       val varDecl = fd.args
-      val funBody = fd.getBody
       val precondition = fd.precondition
       val postcondition = fd.postcondition
 
-      val bodyVars: Set[Identifier] = variablesOf(funBody) ++ variablesOf(precondition.getOrElse(BooleanLiteral(true)))
+      val bodyVars: Set[Identifier] = variablesOf(fd.body.getOrElse(BooleanLiteral(true))) ++ 
+                                      variablesOf(precondition.getOrElse(BooleanLiteral(true))) ++ 
+                                      variablesOf(postcondition.getOrElse(BooleanLiteral(true)))
+
       val capturedVars = bodyVars.intersect(bindedVars)// this should be the variable used that are in the scope
       val (constraints, allCapturedVars) = filterConstraints(capturedVars) //all relevant path constraints
       val capturedVarsWithConstraints = allCapturedVars.toSeq
@@ -52,32 +54,38 @@ object FunctionClosure extends Pass {
       newFunDef.parent = fd.parent
 
       val freshPrecondition = precondition.map(expr => replace(freshVarsExpr, expr))
+      val freshPostcondition = postcondition.map(expr => replace(freshVarsExpr, expr))
+      val freshBody = fd.body.map(b => replace(freshVarsExpr, b))
       val freshConstraints = constraints.map(expr => replace(freshVarsExpr, expr))
-      newFunDef.precondition = freshConstraints match {
-        case List() => freshPrecondition
-        case precs => Some(And(freshPrecondition.getOrElse(BooleanLiteral(true)) +: precs))
-      }
-      newFunDef.postcondition = postcondition.map(expr => replace(freshVarsExpr, expr))
 
       def substFunInvocInDef(expr: Expr): Option[Expr] = expr match {
         case fi@FunctionInvocation(fd, args) if fd.id == id => Some(FunctionInvocation(newFunDef, args ++ extraVarDecls.map(_.id.toVariable)).setPosInfo(fi))
         case _ => None
       }
-      val freshBody = replace(freshVarsExpr, funBody)
       val oldPathConstraints = pathConstraints
       pathConstraints = (precondition.getOrElse(BooleanLiteral(true)) :: pathConstraints).map(e => replace(freshVarsExpr, e))
-      val recBody = functionClosure(freshBody, bindedVars ++ newVarDecls.map(_.id))
+      val recPrecondition = freshConstraints match { //Actually, we do not allow nested fundef in precondition
+        case List() => freshPrecondition
+        case precs => Some(And(freshPrecondition.getOrElse(BooleanLiteral(true)) +: precs))
+      }
+      val recBody = freshBody.map(b =>
+                      functionClosure(b, bindedVars ++ newVarDecls.map(_.id))
+                    ).map(b => searchAndReplaceDFS(substFunInvocInDef)(b))
+      val recPostcondition = freshPostcondition.map(expr =>
+                               functionClosure(expr, bindedVars ++ newVarDecls.map(_.id))
+                             ).map(expr => searchAndReplaceDFS(substFunInvocInDef)(expr))
       pathConstraints = oldPathConstraints
-      val recBody2 = searchAndReplaceDFS(substFunInvocInDef)(recBody)
-      newFunDef.body = Some(recBody2)
+
+      newFunDef.precondition = recPrecondition
+      newFunDef.body = recBody
+      newFunDef.postcondition = recPostcondition
 
       def substFunInvocInRest(expr: Expr): Option[Expr] = expr match {
         case fi@FunctionInvocation(fd, args) if fd.id == id => Some(FunctionInvocation(newFunDef, args ++ capturedVarsWithConstraints.map(_.toVariable)).setPosInfo(fi))
         case _ => None
       }
-      val recRest = functionClosure(rest, bindedVars)
-      val recRest2 = searchAndReplaceDFS(substFunInvocInRest)(recRest)
-      LetDef(newFunDef, recRest2).setType(l.getType)
+      val recRest = searchAndReplaceDFS(substFunInvocInRest)(functionClosure(rest, bindedVars))
+      LetDef(newFunDef, recRest).setType(l.getType)
     }
     case l @ Let(i,e,b) => {
       val re = functionClosure(e, bindedVars)
diff --git a/src/main/scala/leon/FunctionHoisting.scala b/src/main/scala/leon/FunctionHoisting.scala
index c8ad9268dc3b571be1a812d35317f7bc4562b6a7..37bc69c41fa12e41c94b3c8d876631f8e3f47220 100644
--- a/src/main/scala/leon/FunctionHoisting.scala
+++ b/src/main/scala/leon/FunctionHoisting.scala
@@ -13,9 +13,23 @@ object FunctionHoisting extends Pass {
     val funDefs = program.definedFunctions
     var topLevelFuns: Set[FunDef] = Set()
     funDefs.foreach(fd => {
-      val (newBody, additionalTopLevelFun) = hoist(fd.getBody)
-      fd.body = Some(newBody)
-      topLevelFuns ++= additionalTopLevelFun
+      val s2 = fd.body match {
+        case Some(body) => {
+          val (e2, s2) = hoist(body)
+          fd.body = Some(e2)
+          s2
+        }
+        case None => Set()
+      }
+      val s4 = fd.postcondition match {
+        case Some(expr) => {
+          val (e4, s4) = hoist(expr)
+          fd.postcondition = Some(e4)
+          s4
+        }
+        case None => Set()
+      }
+      topLevelFuns ++= (s2 ++ s4)
     })
     val Program(id, ObjectDef(objId, defs, invariants)) = program
     Program(id, ObjectDef(objId, defs ++ topLevelFuns, invariants))
@@ -24,10 +38,23 @@ object FunctionHoisting extends Pass {
   private def hoist(expr: Expr): (Expr, Set[FunDef]) = expr match {
     case l @ LetDef(fd, rest) => {
       val (e, s) = hoist(rest)
-      val (e2, s2) = hoist(fd.getBody)
-      fd.body = Some(e2)
-
-      (e, (s ++ s2) + fd)
+      val s2 = fd.body match {
+        case Some(body) => {
+          val (e2, s2) = hoist(body)
+          fd.body = Some(e2)
+          s2
+        }
+        case None => Set()
+      }
+      val s4 = fd.postcondition match {
+        case Some(expr) => {
+          val (e4, s4) = hoist(expr)
+          fd.postcondition = Some(e4)
+          s4
+        }
+        case None => Set()
+      }
+      (e, (s ++ s2 ++ s4) + fd)
     }
     case l @ Let(i,e,b) => {
       val (re, s1) = hoist(e)
diff --git a/src/main/scala/leon/FunctionTemplate.scala b/src/main/scala/leon/FunctionTemplate.scala
index 6a4395f188bf19d7b636c3cb3ec646d921ed38b1..be4189b4283b2d79eefd63c94726ea7f6d683000 100644
--- a/src/main/scala/leon/FunctionTemplate.scala
+++ b/src/main/scala/leon/FunctionTemplate.scala
@@ -90,9 +90,11 @@ object FunctionTemplate {
     cache(funDef)
   } else {
     val result = {
+      /*
       if(!funDef.hasImplementation) {
         sys.error("Cannot create a FunctionTemplate out of a function with no body.")
       }
+      */
   
       val condVars : MutableSet[Identifier] = MutableSet.empty
       val exprVars : MutableSet[Identifier] = MutableSet.empty
@@ -165,14 +167,22 @@ object FunctionTemplate {
       }
   
       // Treating the body first.
+      /*
       val body : Expr = if(KEEPLETS) {
         matchToIfThenElse(funDef.getImplementation) 
       } else {
         matchToIfThenElse(expandLets(funDef.getImplementation))
       }
+      */
+      val body : Option[Expr] = if(KEEPLETS) {
+        funDef.body.map(b => matchToIfThenElse(b))
+      } else {
+        funDef.body.map(b => matchToIfThenElse(expandLets(b)))
+      }
 
       val invocation : Expr = FunctionInvocation(funDef, funDef.args.map(_.toVariable))
   
+      /*
       val invocationEqualsBody : Expr = {
         val b : Expr = Equals(invocation, body)
         if(PREPENDPRECONDS && funDef.hasPrecondition) {
@@ -181,11 +191,22 @@ object FunctionTemplate {
           b
         }
       }
+      */
+      val invocationEqualsBody : Option[Expr] = body.map(body => {
+        val b : Expr = Equals(invocation, body)
+        if(PREPENDPRECONDS && funDef.hasPrecondition) {
+          Implies(prec.get, b)
+        } else {
+          b
+        }
+      })
   
       val activatingBool : Identifier = FreshIdentifier("a", true).setType(BooleanType)
   
-      val finalPred : Expr = rec(activatingBool, true, invocationEqualsBody)
-      storeGuarded(activatingBool, true, finalPred)
+      //val finalPred : Expr = rec(activatingBool, true, invocationEqualsBody)
+      val finalPred : Option[Expr] = invocationEqualsBody.map(expr => rec(activatingBool, true, expr))
+      //storeGuarded(activatingBool, true, finalPred)
+      finalPred.foreach(p => storeGuarded(activatingBool, true, p))
   
       // Now the postcondition.
       if(funDef.hasPostcondition) {
diff --git a/src/main/scala/leon/ImperativeCodeElimination.scala b/src/main/scala/leon/ImperativeCodeElimination.scala
index b006520ebd0eee5b1d49861534d5dc686f8dea57..662ed9cc9e8ce207b004ecba81f83af41ea1446c 100644
--- a/src/main/scala/leon/ImperativeCodeElimination.scala
+++ b/src/main/scala/leon/ImperativeCodeElimination.scala
@@ -14,11 +14,11 @@ object ImperativeCodeElimination extends Pass {
 
   def apply(pgm: Program): Program = {
     val allFuns = pgm.definedFunctions
-    allFuns.foreach(fd => {
+    allFuns.foreach(fd => fd.body.map(body => {
       parent = fd
-      val (res, scope, _) = toFunction(fd.getBody)
+      val (res, scope, _) = toFunction(body)
       fd.body = Some(scope(res))
-    })
+    }))
     pgm
   }
 
diff --git a/src/main/scala/leon/Main.scala b/src/main/scala/leon/Main.scala
index 72623c96a2c732b4dac1995392545474c7f3f9c7..3d93d5972f95729d872c022ef418e760f6a61e1f 100644
--- a/src/main/scala/leon/Main.scala
+++ b/src/main/scala/leon/Main.scala
@@ -31,7 +31,7 @@ object Main {
   }
 
   private def defaultAction(program: Program, reporter: Reporter) : Unit = {
-    val passManager = new PassManager(Seq(ImperativeCodeElimination, UnitElimination, FunctionClosure, FunctionHoisting, Simplificator))
+    val passManager = new PassManager(Seq(EpsilonElimination, ImperativeCodeElimination, UnitElimination, FunctionClosure, FunctionHoisting, Simplificator))
     val program2 = passManager.run(program)
     val analysis = new Analysis(program2, reporter)
     analysis.analyse
diff --git a/src/main/scala/leon/PassManager.scala b/src/main/scala/leon/PassManager.scala
index f2830df79bfa129ce93d58157110a2107453595a..5381b7bee6a389ac120477c8316fcf1e97ccdc62 100644
--- a/src/main/scala/leon/PassManager.scala
+++ b/src/main/scala/leon/PassManager.scala
@@ -6,9 +6,9 @@ class PassManager(passes: Seq[Pass]) {
 
   def run(program: Program): Program = {
     passes.foldLeft(program)((pgm, pass) => {
-      //println("Running Pass: " + pass.description)
+      println("Running Pass: " + pass.description)
       val newPgm = pass(pgm)
-      //println("Resulting program: " + newPgm)
+      println("Resulting program: " + newPgm)
       newPgm
     })
   }
diff --git a/src/main/scala/leon/Settings.scala b/src/main/scala/leon/Settings.scala
index 797a209e57d08d863f24dcd5f97008d4fc875bf7..9e7055638b46d401a55d9a49866ad8bc0e7751e3 100644
--- a/src/main/scala/leon/Settings.scala
+++ b/src/main/scala/leon/Settings.scala
@@ -19,6 +19,7 @@ object Settings {
   var pruneBranches : Boolean = false
   var solverTimeout : Option[Int] = None
   var luckyTest : Boolean = true
+  var verifyModel : Boolean = true
   var useQuickCheck : Boolean = false
   var useParallel : Boolean = false
   // When this is None, use real integers
diff --git a/src/main/scala/leon/Simplificator.scala b/src/main/scala/leon/Simplificator.scala
index e8a7e2e005b68ce54a6482cb4a06f942d54ba58f..5562c75db5965e7d5f5916aa8923da065b1e3bb6 100644
--- a/src/main/scala/leon/Simplificator.scala
+++ b/src/main/scala/leon/Simplificator.scala
@@ -12,11 +12,10 @@ object Simplificator extends Pass {
   def apply(pgm: Program): Program = {
 
     val allFuns = pgm.definedFunctions
-    allFuns.foreach(fd => {
-      fd.body = Some(simplifyLets(fd.getBody))
-    })
+    allFuns.foreach(fd => fd.body.map(body => {
+      fd.body = Some(simplifyLets(body))
+    }))
     pgm
   }
 
 }
-
diff --git a/src/main/scala/leon/UnitElimination.scala b/src/main/scala/leon/UnitElimination.scala
index 7fe181fba57f7c80d0aa878896641b8195742485..2f5f1bc53fc000242758f19aee766cf175dadf84 100644
--- a/src/main/scala/leon/UnitElimination.scala
+++ b/src/main/scala/leon/UnitElimination.scala
@@ -32,9 +32,9 @@ object UnitElimination extends Pass {
 
     //then apply recursively to the bodies
     val newFuns = allFuns.flatMap(fd => if(fd.returnType == UnitType) Seq() else {
-      val body = fd.getBody
+      val newBody = fd.body.map(body => removeUnit(body))
       val newFd = fun2FreshFun(fd)
-      newFd.body = Some(removeUnit(body))
+      newFd.body = newBody
       Seq(newFd)
     })
 
@@ -100,13 +100,13 @@ object UnitElimination extends Pass {
             freshFunDef.precondition = fd.precondition //TODO: maybe removing unit from the conditions as well..
             freshFunDef.postcondition = fd.postcondition//TODO: maybe removing unit from the conditions as well..
             fun2FreshFun += (fd -> freshFunDef)
-            freshFunDef.body = Some(removeUnit(fd.getBody))
+            freshFunDef.body = fd.body.map(b => removeUnit(b))
             val restRec = removeUnit(b)
             fun2FreshFun -= fd
             (freshFunDef, restRec)
           } else {
             fun2FreshFun += (fd -> fd)
-            fd.body = Some(removeUnit(fd.getBody))
+            fd.body = fd.body.map(b => removeUnit(b))
             val restRec = removeUnit(b)
             fun2FreshFun -= fd
             (fd, restRec)
diff --git a/src/main/scala/leon/Utils.scala b/src/main/scala/leon/Utils.scala
index 9ed8ef400ea0f143af078149c0d3b3034394c3a4..ae60002b693a0b74657fa8640a7eef56a641703f 100644
--- a/src/main/scala/leon/Utils.scala
+++ b/src/main/scala/leon/Utils.scala
@@ -10,6 +10,7 @@ object Utils {
 
   implicit def any2IsValid(x: Boolean) : IsValid = new IsValid(x)
 
+  def epsilon[A](pred: (A) => Boolean): A = throw new RuntimeException("Implementation not supported")
 
   object InvariantFunction {
     def invariant(x: Boolean): Unit = ()
diff --git a/src/main/scala/leon/plugin/CodeExtraction.scala b/src/main/scala/leon/plugin/CodeExtraction.scala
index c418cdf4e4bb1f7fce36a2c8cce7ea1984855201..a0c7579410e87dfea059495303eadc5c555920ae 100644
--- a/src/main/scala/leon/plugin/CodeExtraction.scala
+++ b/src/main/scala/leon/plugin/CodeExtraction.scala
@@ -285,6 +285,11 @@ trait CodeExtraction extends Extractors {
         case e: ImpureCodeEncounteredException => None
       }
 
+      reqCont.map(e => 
+        if(containsLetDef(e)) {
+          unit.error(realBody.pos, "Function precondtion should not contain nested function definition")
+          throw ImpureCodeEncounteredException(realBody)
+        })
       funDef.body = bodyAttempt
       funDef.precondition = reqCont
       funDef.postcondition = ensCont
@@ -430,6 +435,11 @@ trait CodeExtraction extends Extractors {
         case e: ImpureCodeEncounteredException => None
       }
 
+      reqCont.map(e => 
+        if(containsLetDef(e)) {
+          unit.error(realBody.pos, "Function precondtion should not contain nested function definition")
+          throw ImpureCodeEncounteredException(realBody)
+        })
       funDef.body = bodyAttempt
       funDef.precondition = reqCont
       funDef.postcondition = ensCont
@@ -551,6 +561,17 @@ trait CodeExtraction extends Extractors {
             }
           }
         }
+        case epsi@ExEpsilonExpression(tpe, varSym, predBody) => {
+          val pstpe = scalaType2PureScala(unit, silent)(tpe)
+          val previousVarSubst: Option[Function0[Expr]] = varSubsts.get(varSym) //save the previous in case of nested epsilon
+          varSubsts(varSym) = (() => EpsilonVariable((epsi.pos.line, epsi.pos.column)).setType(pstpe))
+          val c1 = rec(predBody)
+          previousVarSubst match {
+            case Some(f) => varSubsts(varSym) = f
+            case None => varSubsts.remove(varSym)
+          }
+          Epsilon(c1).setType(pstpe).setPosInfo(epsi.pos.line, epsi.pos.column)
+        }
         case ExSomeConstruction(tpe, arg) => {
           // println("Got Some !" + tpe + ":" + arg)
           val underlying = scalaType2PureScala(unit, silent)(tpe)
diff --git a/src/main/scala/leon/plugin/Extractors.scala b/src/main/scala/leon/plugin/Extractors.scala
index 4bd9f9bf3bb34940a0bf0ea552a89df60b177ec3..78e66bf6c9ef5a2a8a1e0f23a2a3c4e30a85d19c 100644
--- a/src/main/scala/leon/plugin/Extractors.scala
+++ b/src/main/scala/leon/plugin/Extractors.scala
@@ -160,6 +160,22 @@ trait Extractors {
     //  }
     //}
 
+
+    object ExEpsilonExpression {
+      def unapply(tree: Apply) : Option[(Type, Symbol, Tree)] = tree match {
+        case Apply(
+              TypeApply(Select(Select(funcheckIdent, utilsName), epsilonName), typeTree :: Nil),
+              Function((vd @ ValDef(_, _, _, EmptyTree)) :: Nil, predicateBody) :: Nil) => {
+          if (utilsName.toString == "Utils" && epsilonName.toString == "epsilon")
+            Some((typeTree.tpe, vd.symbol, predicateBody))
+          else 
+            None
+        }
+        case _ => None
+      }
+    }
+
+
     object ExValDef {
       /** Extracts val's in the head of blocks. */
       def unapply(tree: ValDef): Option[(Symbol,Tree,Tree)] = tree match {
diff --git a/src/main/scala/leon/plugin/LeonPlugin.scala b/src/main/scala/leon/plugin/LeonPlugin.scala
index 5de24fa44bbf489350371d2bce9775231ebf3e1d..3654de04ad807d2fd55a7470ce5c3fd97a131327 100644
--- a/src/main/scala/leon/plugin/LeonPlugin.scala
+++ b/src/main/scala/leon/plugin/LeonPlugin.scala
@@ -40,6 +40,7 @@ class LeonPlugin(val global: Global, val actionAfterExtraction : Option[Program=
     "  --quickcheck         Use QuickCheck-like random search" + "\n" +
     "  --parallel           Run all solvers in parallel" + "\n" +
     "  --noLuckyTests       Do not perform additional tests to potentially find models early" + "\n" +
+    "  --noverifymodel      Do not verify the correctness of models returned by Z3" + "\n" +
     "  --verbose            Print debugging informations"
   )
 
@@ -63,6 +64,7 @@ class LeonPlugin(val global: Global, val actionAfterExtraction : Option[Program=
         case "quickcheck" =>                     leon.Settings.useQuickCheck = true
         case "parallel"   =>                     leon.Settings.useParallel = true
         case "noLuckyTests" =>                   leon.Settings.luckyTest = false
+        case "noverifymodel" =>                  leon.Settings.verifyModel = false
         case "verbose"    =>                     leon.Settings.verbose = true
         case s if s.startsWith("unrolling=") =>  leon.Settings.unrollingLevel = try { s.substring("unrolling=".length, s.length).toInt } catch { case _ => 0 }
         case s if s.startsWith("functions=") =>  leon.Settings.functionsToAnalyse = Set(splitList(s.substring("functions=".length, s.length)): _*)
diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index 6f2038edeab63f6a2dcc0809d4b912429f55b5eb..d1a39f7172fafb612c2201b2c4322615a0aabdef 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -145,6 +145,15 @@ object PrettyPrinter {
       sb.append("._" + i)
       sb
     }
+
+    case e@Epsilon(pred) => {
+      var nsb = sb
+      nsb.append("epsilon(x" + e.posIntInfo._1 + "_" + e.posIntInfo._2 + ". ")
+      nsb = pp(pred, nsb, lvl)
+      nsb.append(")")
+      nsb
+    }
+
     case OptionSome(a) => {
       var nsb = sb
       nsb.append("Some(")
@@ -333,6 +342,7 @@ object PrettyPrinter {
     }
 
     case ResultVariable() => sb.append("#res")
+    case EpsilonVariable((row, col)) => sb.append("x" + row + "_" + col)
     case Not(expr) => ppUnary(sb, expr, "\u00AC(", ")", lvl)               // \neg
 
     case e @ Error(desc) => {
diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala
index ff0eeea21289861dffc5bcd4f24efefad73d0eb1..f9d0498f0fd46c867817778fb6ba9a845498755f 100644
--- a/src/main/scala/leon/purescala/Trees.scala
+++ b/src/main/scala/leon/purescala/Trees.scala
@@ -40,6 +40,8 @@ object Trees {
    * the expected type. */
   case class Error(description: String) extends Expr with Terminal with ScalacPositional
 
+  case class Epsilon(pred: Expr) extends Expr with ScalacPositional
+
   /* Like vals */
   case class Let(binder: Identifier, value: Expr, body: Expr) extends Expr {
     binder.markAsLetBinder
@@ -266,6 +268,8 @@ object Trees {
   // represents the result in post-conditions
   case class ResultVariable() extends Expr with Terminal
 
+  case class EpsilonVariable(pos: (Int, Int)) extends Expr with Terminal
+
   /* Literals */
   sealed abstract class Literal[T] extends Expr with Terminal {
     val value: T
@@ -407,6 +411,7 @@ object Trees {
       case CaseClassInstanceOf(cd, e) => Some((e, CaseClassInstanceOf(cd, _)))
       case Assignment(id, e) => Some((e, Assignment(id, _)))
       case TupleSelect(t, i) => Some((t, TupleSelect(_, i)))
+      case e@Epsilon(t) => Some((t, (expr: Expr) => Epsilon(expr).setType(e.getType).setPosInfo(e)))
       case _ => None
     }
   }
@@ -751,7 +756,10 @@ object Trees {
     def rec(expr: Expr) : A = expr match {
       case l @ Let(_, e, b) => compute(l, combine(rec(e), rec(b)))
       case l @ LetVar(_, e, b) => compute(l, combine(rec(e), rec(b)))
-      case l @ LetDef(fd, b) => compute(l, combine(rec(fd.getBody), rec(b))) //TODO, still not sure about the semantic
+      case l @ LetDef(fd, b) => {//TODO, still not sure about the semantic
+        val exprs: Seq[Expr] = fd.precondition.toSeq ++ fd.body.toSeq ++ fd.postcondition.toSeq ++ Seq(b)
+        compute(l, exprs.map(rec(_)).reduceLeft(combine))
+      }
       case n @ NAryOperator(args, _) => {
         if(args.size == 0)
           compute(n, convert(n))
@@ -810,6 +818,19 @@ object Trees {
     treeCatamorphism(convert, combine, compute, expr)
   }
 
+  def containsLetDef(expr: Expr): Boolean = {
+    def convert(t : Expr) : Boolean = t match {
+      case (l : LetDef) => true
+      case _ => false
+    }
+    def combine(c1 : Boolean, c2 : Boolean) : Boolean = c1 || c2
+    def compute(t : Expr, c : Boolean) = t match {
+      case (l : LetDef) => true
+      case _ => c
+    }
+    treeCatamorphism(convert, combine, compute, expr)
+  }
+
   def variablesOf(expr: Expr) : Set[Identifier] = {
     def convert(t: Expr) : Set[Identifier] = t match {
       case Variable(i) => Set(i)