diff --git a/mytest/Abs.scala b/mytest/Abs.scala
index 5be0d8cf5fb77aba749440ca3901a4b989f8a2fd..bcec4f3737c912707121f071a4d581207a12854b 100644
--- a/mytest/Abs.scala
+++ b/mytest/Abs.scala
@@ -3,9 +3,8 @@ import leon.Utils._
 object Abs {
 
 
-  def abs(tab: Map[Int, Int], size: Int, j: Int): Map[Int, Int] = ({
-    require(size <= 5 && /*)
-    require(*/isArray(tab, size) && j >= 0 && j < size)
+  def abs(tab: Map[Int, Int], size: Int): Map[Int, Int] = ({
+    require(size <= 5 && isArray(tab, size))
     var k = 0
     var tabres = Map.empty[Int, Int]
     (while(k < size) {
@@ -14,9 +13,17 @@ object Abs {
       else
         tabres = tabres.updated(k, tab(k))
       k = k + 1
-    }) invariant(k >= 0 && k <= size && (if(j < k) tabres(j) >= 0 else true))
+    }) invariant(isArray(tabres, k) && k >= 0 && k <= size && isPositive(tabres, k))
     tabres
-  }) ensuring(res => res(j) >= 0)
+  }) ensuring(res => isArray(res, size) && isPositive(res, size))
+
+  def isPositive(a: Map[Int, Int], size: Int): Boolean = {
+    require(isArray(a, size))
+    def rec(i: Int): Boolean = if(i >= size) true else {
+      if(a(i) < 0) false else rec(i+1)
+    }
+    rec(0)
+  }
 
   def isArray(a: Map[Int, Int], size: Int): Boolean = {
     if(size < 0)
diff --git a/mytest/Bubble.scala b/mytest/Bubble.scala
index c69f74fa2765c7042985b4f8325a5a70335f85c5..340022195b26fa364d55ac123d0e2c37869ec96b 100644
--- a/mytest/Bubble.scala
+++ b/mytest/Bubble.scala
@@ -2,8 +2,8 @@ import leon.Utils._
 
 object Bubble {
 
-  def sort(a: Map[Int, Int], size: Int, k: Int, l1: Int, l2: Int): Map[Int, Int] = ({
-    require(size <= 5 && size > 0 && k < size - 1 && k >= 0 && l1 < size && l1 >= 0 && l2 < size && l2 >= 0 && isArray(a, size))
+  def sort(a: Map[Int, Int], size: Int): Map[Int, Int] = ({
+    require(size <= 5 && isArray(a, size))
     var i = size - 1
     var j = 0
     var sortedArray = a
@@ -17,35 +17,49 @@ object Bubble {
         }
         j = j + 1
       }) invariant(
-            isArray(sortedArray, size) && 
-            j >= 0 && 
             j <= i &&
-            (if(k >= i) sortedArray(k) <= sortedArray(k+1) else true) && 
-            (if(l1 <= i && l2 > i) sortedArray(l1) <= sortedArray(l2) else true)
+            isArray(sortedArray, size) && 
+            partitioned(sortedArray, size, 0, i, i+1, size-1) &&
+            partitioned(sortedArray, size, 0, j-1, j, j) &&
+            sorted(sortedArray, size, i, size-1)
           )
       i = i - 1
     }) invariant(
+          i >= 0 &&
           isArray(sortedArray, size) && 
-          i >= 0 && 
-          i < size && 
-          (if(k >= i) sortedArray(k) <= sortedArray(k+1) else true) && 
-          (if(l1 <= i && l2 > i) sortedArray(l1) <= sortedArray(l2) else true)
+          partitioned(sortedArray, size, 0, i, i+1, size-1) &&
+          sorted(sortedArray, size, i, size-1)
        )
     sortedArray
-  }) ensuring(res => res(k) <= res(k+1))
-  //ensuring(res => sorted(res, 0, size-1))
+  }) ensuring(res => sorted(res, size, 0, size-1))
 
-  //def sorted(a: Map[Int, Int], l: Int, u: Int): Boolean = {
-  //  require(isArray(a, u+1))
-  //  var k = l
-  //  var isSorted = true
-  //  while(k < u) {
-  //    if(a(k) > a(k+1))
-  //      isSorted = false
-  //    k = k + 1
-  //  }
-  //  isSorted
-  //}
+  def sorted(a: Map[Int, Int], size: Int, l: Int, u: Int): Boolean = {
+    require(isArray(a, size) && l >= 0 && u < size && l <= u)
+    var k = l
+    var isSorted = true
+    while(k <= u) {
+      if(a(k) > a(k+1))
+        isSorted = false
+      k = k + 1
+    }
+    isSorted
+  }
+  
+  def partitioned(a: Map[Int, Int], size: Int, l1: Int, u1: Int, l2: Int, u2: Int): Boolean = {
+    require(l1 >= 0 && l1 <= u1 && u1 < l2 && l2 <= u2 && u2 < size && isArray(a, size))
+    var i = l1
+    var j = l2
+    var isPartitionned = true
+    while(i <= u1) {
+      while(j <= u2) {
+        if(a(i) > a(j))
+          isPartitionned = false
+        j = j+1
+      }
+      i = i + 1
+    }
+    isPartitionned
+  }
 
 
   def isArray(a: Map[Int, Int], size: Int): Boolean = {
diff --git a/src/main/scala/leon/FunctionClosure.scala b/src/main/scala/leon/FunctionClosure.scala
index a7438c9e31637e431b1ab14f9dc3db953c8defb9..ac635c2f41ca3f2e688b915557ac3829add21125 100644
--- a/src/main/scala/leon/FunctionClosure.scala
+++ b/src/main/scala/leon/FunctionClosure.scala
@@ -11,10 +11,16 @@ object FunctionClosure extends Pass {
 
   private var enclosingPreconditions: List[Expr] = Nil
 
+  private var pathConstraints: List[Expr] = Nil
+  private var newFunDefs: Map[FunDef, FunDef] = Map()
+  //private var 
+
   def apply(program: Program): Program = {
+    newFunDefs = Map()
     val funDefs = program.definedFunctions
     funDefs.foreach(fd => {
       enclosingPreconditions = fd.precondition.toList
+      pathConstraints = fd.precondition.toList
       fd.body = Some(functionClosure(fd.getBody, fd.args.map(_.id).toSet))
     })
     program
@@ -22,52 +28,64 @@ object FunctionClosure extends Pass {
 
   private def functionClosure(expr: Expr, bindedVars: Set[Identifier]): Expr = expr match {
     case l @ LetDef(fd, rest) => {
+
       val id = fd.id
       val rt = fd.returnType
       val varDecl = fd.args
       val funBody = fd.getBody
-      val previousEnclosingPreconditions = enclosingPreconditions
-      enclosingPreconditions = fd.precondition match {
-        case Some(pre) => pre :: enclosingPreconditions
-        case None => enclosingPreconditions
-      }
-      val bodyVars: Set[Identifier] = variablesOf(funBody) 
-      val preconditionVars: Set[Identifier] = enclosingPreconditions.foldLeft(Set[Identifier]())((s, pre) => s ++ variablesOf(pre))
-      val vars = bodyVars ++ preconditionVars
-      val capturedVars = vars.intersect(bindedVars).toSeq // this should be the variable used that are in the scope
-      val freshVars: Map[Identifier, Identifier] = capturedVars.map(v => (v, FreshIdentifier(v.name).setType(v.getType))).toMap
+      val precondition = fd.precondition
+      val postcondition = fd.postcondition
+
+      val bodyVars: Set[Identifier] = variablesOf(funBody) ++ variablesOf(precondition.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
+
+      val freshVars: Map[Identifier, Identifier] = capturedVarsWithConstraints.map(v => (v, FreshIdentifier(v.name).setType(v.getType))).toMap
       val freshVarsExpr: Map[Expr, Expr] = freshVars.map(p => (p._1.toVariable, p._2.toVariable))
-      val freshBody = replace(freshVarsExpr, funBody)
+
       val extraVarDecls = freshVars.map{ case (_, v2) => VarDecl(v2, v2.getType) }
       val newVarDecls = varDecl ++ extraVarDecls
       val newFunId = FreshIdentifier(id.name)
       val newFunDef = new FunDef(newFunId, rt, newVarDecls)
-      enclosingPreconditions = enclosingPreconditions.map(pre => replace(freshVarsExpr, pre)) //introduce the new variables name for the list of preconditions
-      newFunDef.precondition = enclosingPreconditions match {
-        case List() => None
-        case precs => Some(And(precs))
+
+      val freshPrecondition = precondition.map(expr => replace(freshVarsExpr, expr))
+      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 = fd.postcondition.map(expr => replace(freshVarsExpr, expr))
+      newFunDef.postcondition = postcondition.map(expr => replace(freshVarsExpr, expr))
+
       def substFunInvocInDef(expr: Expr): Option[Expr] = expr match {
         case FunctionInvocation(fd, args) if fd.id == id => Some(FunctionInvocation(newFunDef, args ++ extraVarDecls.map(_.id.toVariable)))
         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))
+      pathConstraints = oldPathConstraints
       val recBody2 = searchAndReplaceDFS(substFunInvocInDef)(recBody)
       newFunDef.body = Some(recBody2)
+
       def substFunInvocInRest(expr: Expr): Option[Expr] = expr match {
-        case FunctionInvocation(fd, args) if fd.id == id => Some(FunctionInvocation(newFunDef, args ++ capturedVars.map(_.toVariable)))
+        case FunctionInvocation(fd, args) if fd.id == id => Some(FunctionInvocation(newFunDef, args ++ capturedVarsWithConstraints.map(_.toVariable)))
         case _ => None
       }
-      //need to remove the enclosing precondition before considering the rest
-      enclosingPreconditions = previousEnclosingPreconditions
       val recRest = functionClosure(rest, bindedVars)
       val recRest2 = searchAndReplaceDFS(substFunInvocInRest)(recRest)
       LetDef(newFunDef, recRest2).setType(l.getType)
     }
+
+    //case fi @ FunctionInvocation(fd, args) => {
+
+    //}
     case l @ Let(i,e,b) => {
       val re = functionClosure(e, bindedVars)
+      pathConstraints ::= Equals(Variable(i), re)
       val rb = functionClosure(b, bindedVars + i)
+      pathConstraints = pathConstraints.tail
       Let(i, re, rb).setType(l.getType)
     }
     case n @ NAryOperator(args, recons) => {
@@ -84,44 +102,40 @@ object FunctionClosure extends Pass {
       val r = functionClosure(t, bindedVars)
       recons(r).setType(u.getType)
     }
-    case i @ IfExpr(t1,t2,t3) => {
-      val r1 = functionClosure(t1, bindedVars)
-      val r2 = functionClosure(t2, bindedVars)
-      val r3 = functionClosure(t3, bindedVars)
-      IfExpr(r1, r2, r3).setType(i.getType)
+    case i @ IfExpr(cond,then,elze) => {
+      val rCond = functionClosure(cond, bindedVars)
+      pathConstraints ::= rCond
+      val rThen = functionClosure(then, bindedVars)
+      pathConstraints = pathConstraints.tail
+      pathConstraints ::= Not(rCond)
+      val rElze = functionClosure(elze, bindedVars)
+      pathConstraints = pathConstraints.tail
+      IfExpr(rCond, rThen, rElze).setType(i.getType)
     }
     case m @ MatchExpr(scrut,cses) => sys.error("Will see")//MatchExpr(rec(scrut), cses.map(inCase(_))).setType(m.getType).setPosInfo(m)
     case t if t.isInstanceOf[Terminal] => t
     case unhandled => scala.sys.error("Non-terminal case should be handled in searchAndReplace: " + unhandled)
   }
 
-  //def collectWithPathCondition(matcher: Expr=>Boolean, expression: Expr) : Set[(Seq[Expr],Expr)] = {
-  //  var collected : Set[(Seq[Expr],Expr)] = Set.empty
-
-  //  def rec(expr: Expr, path: List[Expr]) : Unit = {
-  //    if(matcher(expr)) {
-  //      collected = collected + ((path.reverse, expr))
-  //    }
-
-  //    expr match {
-  //      case Let(i,e,b) => {
-  //        rec(e, path)
-  //        rec(b, Equals(Variable(i), e) :: path)
-  //      }
-  //      case IfExpr(cond, then, elze) => {
-  //        rec(cond, path)
-  //        rec(then, cond :: path)
-  //        rec(elze, Not(cond) :: path)
-  //      }
-  //      case NAryOperator(args, _) => args.foreach(rec(_, path))
-  //      case BinaryOperator(t1, t2, _) => rec(t1, path); rec(t2, path)
-  //      case UnaryOperator(t, _) => rec(t, path)
-  //      case t : Terminal => ;
-  //      case _ => scala.sys.error("Unhandled tree in collectWithPathCondition : " + expr)
-  //    }
-  //  }
-
-  //  rec(expression, Nil)
-  //  collected
-  //}
+  //filter the list of constraints, only keeping those relevant to the set of variables
+  def filterConstraints(vars: Set[Identifier]): (List[Expr], Set[Identifier]) = {
+    var allVars = vars
+    var newVars: Set[Identifier] = Set()
+    var constraints = pathConstraints
+    var filteredConstraints: List[Expr] = Nil
+    do {
+      allVars ++= newVars
+      newVars = Set()
+      constraints = pathConstraints.filterNot(filteredConstraints.contains(_))
+      constraints.foreach(expr => {
+        val vs = variablesOf(expr)
+        if(!vs.intersect(allVars).isEmpty) {
+          filteredConstraints ::= expr
+          newVars ++= vs.diff(allVars)
+        }
+      })
+    } while(newVars != Set())
+    (filteredConstraints, allVars)
+  }
+
 }