diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala
index 56249605f64c06323bd402917978b61226aae52f..46c7bab49c6e38c25281406eee5f25dc2291f292 100644
--- a/src/main/scala/leon/purescala/TreeOps.scala
+++ b/src/main/scala/leon/purescala/TreeOps.scala
@@ -2083,16 +2083,6 @@ object TreeOps {
       None
   }
 
-  // Remove terminating/guiding witnesses that bother solvers
-  def removeWitnesses(prog: Program)(e: Expr): Expr = {
-    val witnesses = Set() ++ prog.library.guide ++ prog.library.terminating
-
-    postMap {
-      case FunctionInvocation(TypedFunDef(fd, _), _) if witnesses contains fd => Some(BooleanLiteral(true))  
-      case _ => None
-    }(e)
-  }
-
   /**
    * Deprecated API
    * ========
diff --git a/src/main/scala/leon/refactor/Repairman.scala b/src/main/scala/leon/refactor/Repairman.scala
index 37bf364613d2c08d9bcb267d1b6da367fb196aa4..de119dbc2edc11b9ae17ee2b6ff3a752a405c25f 100644
--- a/src/main/scala/leon/refactor/Repairman.scala
+++ b/src/main/scala/leon/refactor/Repairman.scala
@@ -73,14 +73,13 @@ class Repairman(ctx: LeonContext, program: Program, fd: FunDef) {
       passes
     )
 
-    val pc = and(
-      pre,
+    val ws = and(
       guide,
       terminating
     )
 
     // Synthesis from the ground up
-    val p = Problem(fd.params.map(_.id).toList, pc, spec, List(out))
+    val p = Problem(fd.params.map(_.id).toList, ws, pre, spec, List(out))
     val ch = Choose(List(out), spec)
     // do we really want to do that?
     fd.body = Some(ch)
@@ -96,7 +95,7 @@ class Repairman(ctx: LeonContext, program: Program, fd: FunDef) {
       )) diff Seq(ADTInduction)
     );
 
-    ChooseInfo(ctx, program, fd, pc, gexpr, ch, soptions)
+    ChooseInfo(ctx, program, fd, pre, gexpr, ch, soptions)
   }
 
   def repair(): Unit = {
diff --git a/src/main/scala/leon/synthesis/Problem.scala b/src/main/scala/leon/synthesis/Problem.scala
index 36e1e3ff2f2f1c1ba5fab5b968976ffddf96dde1..b3959f35c6c7034124a5db1a3f6b8d3b5505a3ce 100644
--- a/src/main/scala/leon/synthesis/Problem.scala
+++ b/src/main/scala/leon/synthesis/Problem.scala
@@ -10,10 +10,9 @@ import leon.purescala.Common._
 import leon.purescala.Constructors._
 
 // Defines a synthesis triple of the form:
-// ⟦ as ⟨ C | phi ⟩ xs ⟧
-case class Problem(as: List[Identifier], pc: Expr, phi: Expr, xs: List[Identifier]) {
-  override def toString = 
-    "⟦ "+as.mkString(";")+", " + (if (pc != BooleanLiteral(true)) pc+" ≺ " else "") + " ⟨ "+phi+" ⟩ " + xs.mkString(";") + " ⟧ "
+// ⟦ as ⟨ ws && pc | phi ⟩ xs ⟧
+case class Problem(as: List[Identifier], ws: Expr, pc: Expr, phi: Expr, xs: List[Identifier]) {
+  override def toString = "⟦ "+as.mkString(";")+", "+(if (ws != BooleanLiteral(true)) ws+" - " else "")+(if (pc != BooleanLiteral(true)) pc+" ≺ " else "")+" ⟨ "+phi+" ⟩ "+xs.mkString(";")+" ⟧ "
 
   def getTests(sctx: SynthesisContext): Seq[Example] = {
     import purescala.Extractors._
@@ -23,14 +22,12 @@ case class Problem(as: List[Identifier], pc: Expr, phi: Expr, xs: List[Identifie
 
     val ev = new DefaultEvaluator(sctx.context, sctx.program)
 
-    val safePc = removeWitnesses(sctx.program)(pc)
-
     def isValidExample(ex: Example): Boolean = {
       val (mapping, cond) = ex match {
         case io: InOutExample =>
-          (Map((as zip io.ins) ++ (xs zip io.outs): _*), And(safePc, phi))
+          (Map((as zip io.ins) ++ (xs zip io.outs): _*), And(pc, phi))
         case i =>
-          ((as zip i.ins).toMap, safePc)
+          ((as zip i.ins).toMap, pc)
       }
 
       ev.eval(cond, mapping) match {
@@ -212,6 +209,6 @@ object Problem {
     val phi = simplifyLets(ch.pred)
     val as = (variablesOf(And(pc, phi))--xs).toList
 
-    Problem(as, pc, phi, xs)
+    Problem(as, BooleanLiteral(true), pc, phi, xs)
   }
 }
diff --git a/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala b/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala
index be9d37584100c5bd9ac2dca599d25e4c652a3494..c55673a64766e17c347e862f80b84fc3c34f3031 100644
--- a/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala
+++ b/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala
@@ -43,6 +43,7 @@ case object ADTInduction extends Rule("ADT Induction") with Heuristic {
 
         val innerPhi = substAll(substMap, p.phi)
         val innerPC  = substAll(substMap, p.pc)
+        val innerWS  = substAll(substMap, p.ws)
 
         val subProblemsInfo = for (cct <- ct.knownCCDescendents) yield {
           var recCalls = Map[List[Identifier], List[Expr]]()
@@ -66,10 +67,11 @@ case object ADTInduction extends Rule("ADT Induction") with Heuristic {
 
           val subPhi = substAll(Map(inductOn -> CaseClass(cct, newIds.map(Variable(_)))), innerPhi)
           val subPC  = substAll(Map(inductOn -> CaseClass(cct, newIds.map(Variable(_)))), innerPC)
+          val subWS  = substAll(Map(inductOn -> CaseClass(cct, newIds.map(Variable(_)))), innerWS)
 
           val subPre = CaseClassInstanceOf(cct, Variable(origId))
 
-          val subProblem = Problem(inputs ::: residualArgs, andJoin(subPC :: postFs), subPhi, p.xs)
+          val subProblem = Problem(inputs ::: residualArgs, subWS, andJoin(subPC :: postFs), subPhi, p.xs)
 
           (subProblem, subPre, cct, newIds, recCalls)
         }
diff --git a/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala b/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala
index 033dfd592e398380dafa3e6a2bf8aace2acdefe1..1455331223860b0f0c6204be91d10358ce6d4cd7 100644
--- a/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala
+++ b/src/main/scala/leon/synthesis/heuristics/ADTLongInduction.scala
@@ -95,6 +95,7 @@ case object ADTLongInduction extends Rule("ADT Long Induction") with Heuristic {
 
         val innerPhi = substAll(substMap, p.phi)
         val innerPC  = substAll(substMap, p.pc)
+        val innerWS  = substAll(substMap, p.ws)
 
         val subProblemsInfo = for (c <- cases) yield {
           val InductCase(ids, calls, pat, pc, trMap) = c
@@ -104,6 +105,7 @@ case object ADTLongInduction extends Rule("ADT Long Induction") with Heuristic {
           var recCalls = Map[List[Identifier], List[Expr]]()
 
           val subPC = substAll(trMap, innerPC)
+          val subWS = substAll(trMap, innerWS)
           val subPhi = substAll(trMap, innerPhi)
 
           var postXss = List[Identifier]()
@@ -118,7 +120,7 @@ case object ADTLongInduction extends Rule("ADT Long Induction") with Heuristic {
             recCalls += postXs -> (Variable(cid) +: residualArgs.map(id => Variable(id)))
           }
 
-          val subProblem = Problem(c.ids ::: postXss, andJoin(subPC :: postFs), subPhi, p.xs)
+          val subProblem = Problem(c.ids ::: postXss, subWS, andJoin(subPC :: postFs), subPhi, p.xs)
           //println(subProblem)
           //println(recCalls)
           (subProblem, pat, recCalls, pc)
diff --git a/src/main/scala/leon/synthesis/heuristics/IntInduction.scala b/src/main/scala/leon/synthesis/heuristics/IntInduction.scala
index 71a2f3e9526641c4d9e909d5eb15e710f95b6bcf..a6f0d31794046b4d775c7841380035145ac5abd3 100644
--- a/src/main/scala/leon/synthesis/heuristics/IntInduction.scala
+++ b/src/main/scala/leon/synthesis/heuristics/IntInduction.scala
@@ -26,12 +26,13 @@ case object IntInduction extends Rule("Int Induction") with Heuristic {
 
         val newPhi     = subst(origId -> Variable(inductOn), p.phi)
         val newPc      = subst(origId -> Variable(inductOn), p.pc)
+        val newWs      = subst(origId -> Variable(inductOn), p.ws)
         val postCondGT = substAll(postXsMap + (origId -> Minus(Variable(inductOn), IntLiteral(1))), p.phi)
         val postCondLT = substAll(postXsMap + (origId -> Plus(Variable(inductOn), IntLiteral(1))), p.phi)
 
-        val subBase = Problem(List(), subst(origId -> IntLiteral(0), p.pc), subst(origId -> IntLiteral(0), p.phi), p.xs)
-        val subGT   = Problem(inductOn :: postXs, and(GreaterThan(Variable(inductOn), IntLiteral(0)), postCondGT, newPc), newPhi, p.xs)
-        val subLT   = Problem(inductOn :: postXs, and(LessThan(Variable(inductOn), IntLiteral(0)), postCondLT, newPc), newPhi, p.xs)
+        val subBase = Problem(List(), subst(origId -> IntLiteral(0), p.ws), subst(origId -> IntLiteral(0), p.pc), subst(origId -> IntLiteral(0), p.phi), p.xs)
+        val subGT   = Problem(inductOn :: postXs, newWs, and(GreaterThan(Variable(inductOn), IntLiteral(0)), postCondGT, newPc), newPhi, p.xs)
+        val subLT   = Problem(inductOn :: postXs, newWs, and(LessThan(Variable(inductOn), IntLiteral(0)), postCondLT, newPc), newPhi, p.xs)
 
         val onSuccess: List[Solution] => Option[Solution] = {
           case List(base, gt, lt) =>
diff --git a/src/main/scala/leon/synthesis/rules/ADTSplit.scala b/src/main/scala/leon/synthesis/rules/ADTSplit.scala
index 16ca8f15f325de5a0caab01e2cce5539ddf4fb6f..4453212ffbfcc4c2bea70c6630b975cc38f577d5 100644
--- a/src/main/scala/leon/synthesis/rules/ADTSplit.scala
+++ b/src/main/scala/leon/synthesis/rules/ADTSplit.scala
@@ -23,7 +23,7 @@ case object ADTSplit extends Rule("ADT Split.") {
         val optCases = for (dcd <- cd.knownDescendents.sortBy(_.id.name)) yield dcd match {
           case ccd : CaseClassDef =>
             val cct = CaseClassType(ccd, tpes)
-            val toSat = and(removeWitnesses(sctx.program)(p.pc), CaseClassInstanceOf(cct, Variable(id)))
+            val toSat = and(p.pc, CaseClassInstanceOf(cct, Variable(id)))
 
             val isImplied = solver.solveSAT(toSat) match {
               case (Some(false), _) => true
@@ -59,7 +59,8 @@ case object ADTSplit extends Rule("ADT Split.") {
 
            val subPhi = subst(id -> CaseClass(cct, args.map(Variable(_))), p.phi)
            val subPC  = subst(id -> CaseClass(cct, args.map(Variable(_))), p.pc)
-           val subProblem = Problem(args ::: oas, subPC, subPhi, p.xs)
+           val subWS  = subst(id -> CaseClass(cct, args.map(Variable(_))), p.ws)
+           val subProblem = Problem(args ::: oas, subWS, subPC, subPhi, p.xs)
            val subPattern = CaseClassPattern(None, cct, args.map(id => WildcardPattern(Some(id))))
 
            (cct, subProblem, subPattern)
diff --git a/src/main/scala/leon/synthesis/rules/CaseSplit.scala b/src/main/scala/leon/synthesis/rules/CaseSplit.scala
index 5ec5e3b0f75262f933ceaa518c4443552626ccef..5967bc4e6c859d0fb259fa59770428c73d085104 100644
--- a/src/main/scala/leon/synthesis/rules/CaseSplit.scala
+++ b/src/main/scala/leon/synthesis/rules/CaseSplit.scala
@@ -20,7 +20,7 @@ case object CaseSplit extends Rule("Case-Split") {
   }
 
   def split(alts: Seq[Expr], p: Problem, description: String): RuleInstantiation = {
-    val subs = alts.map(a => Problem(p.as, p.pc, a, p.xs)).toList
+    val subs = alts.map(a => Problem(p.as, p.ws, p.pc, a, p.xs)).toList
 
     val onSuccess: List[Solution] => Option[Solution] = {
       case sols if sols.size == subs.size =>
diff --git a/src/main/scala/leon/synthesis/rules/CegisLike.scala b/src/main/scala/leon/synthesis/rules/CegisLike.scala
index 5470b1769f0557f935098e9763eaa011e7289f85..a458f51f1c7b7fd2ebdf6706b4aba6617e1c65f1 100644
--- a/src/main/scala/leon/synthesis/rules/CegisLike.scala
+++ b/src/main/scala/leon/synthesis/rules/CegisLike.scala
@@ -182,7 +182,7 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
         // Map each x generated by the program to fresh xs passed as argument
         val newXs = p.xs.map(x => x -> FreshIdentifier(x.name, true).setType(x.getType))
 
-        val baseExpr = removeWitnesses(sctx.program)(p.phi)
+        val baseExpr = p.phi
 
         bssOrdered = bss.toSeq.sortBy(_.id)
 
@@ -429,14 +429,14 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
 
         baseExampleInputs ++= p.getTests(sctx).map(_.ins).toSet
 
-        val safePc = removeWitnesses(sctx.program)(p.pc)
+        val pc = p.pc
 
-        if (safePc == BooleanLiteral(true)) {
+        if (pc == BooleanLiteral(true)) {
           baseExampleInputs += p.as.map(a => simplestValue(a.getType))
         } else {
           val solver = sctx.newSolver.setTimeout(exSolverTo)
 
-          solver.assertCnstr(safePc)
+          solver.assertCnstr(pc)
 
           try {
             solver.check match {
@@ -467,9 +467,9 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
          * We generate tests for discarding potential programs
          */
         val inputIterator: Iterator[Seq[Expr]] = if (useVanuatoo) {
-          new VanuatooDataGen(sctx.context, sctx.program).generateFor(p.as, safePc, 20, 3000)
+          new VanuatooDataGen(sctx.context, sctx.program).generateFor(p.as, pc, 20, 3000)
         } else {
-          new NaiveDataGen(sctx.context, sctx.program, evaluator).generateFor(p.as, safePc, 20, 1000)
+          new NaiveDataGen(sctx.context, sctx.program, evaluator).generateFor(p.as, pc, 20, 1000)
         }
 
         val cachedInputIterator = new Iterator[Seq[Expr]] {
@@ -501,7 +501,7 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
             val res = Equals(Tuple(p.xs.map(Variable(_))), expr)
 
             val solver3 = sctx.newSolver.setTimeout(cexSolverTo)
-            solver3.assertCnstr(and(safePc, res, not(p.phi)))
+            solver3.assertCnstr(and(pc, res, not(p.phi)))
 
             try {
               solver3.check match {
@@ -523,8 +523,8 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) {
         // Keep track of collected cores to filter programs to test
         var collectedCores = Set[Set[Identifier]]()
 
-        val initExClause  = and(safePc, p.phi,      Variable(initGuard))
-        val initCExClause = and(safePc, not(p.phi), Variable(initGuard))
+        val initExClause  = and(pc, p.phi,      Variable(initGuard))
+        val initCExClause = and(pc, not(p.phi), Variable(initGuard))
 
         // solver1 is used for the initial SAT queries
         var solver1 = sctx.newSolver.setTimeout(exSolverTo)
diff --git a/src/main/scala/leon/synthesis/rules/DetupleInput.scala b/src/main/scala/leon/synthesis/rules/DetupleInput.scala
index ecf0774d66313d5592a8c3300eaa50c587f56fd0..e2345ab76b0fa1a348af7a9aad784f6e1ab9be8f 100644
--- a/src/main/scala/leon/synthesis/rules/DetupleInput.scala
+++ b/src/main/scala/leon/synthesis/rules/DetupleInput.scala
@@ -41,6 +41,7 @@ case object DetupleInput extends NormalizingRule("Detuple In") {
     if (p.as.exists(isDecomposable)) {
       var subProblem = p.phi
       var subPc      = p.pc
+      var subWs      = p.ws
 
       var reverseMap = Map[Identifier, Expr]()
 
@@ -50,6 +51,7 @@ case object DetupleInput extends NormalizingRule("Detuple In") {
 
           subProblem = subst(a -> expr, subProblem)
           subPc      = subst(a -> expr, subPc)
+          subWs      = subst(a -> expr, subWs)
 
           reverseMap ++= map
 
@@ -62,7 +64,7 @@ case object DetupleInput extends NormalizingRule("Detuple In") {
       val newAs = subAs.flatten
       //sctx.reporter.warning("newOuts: " + newOuts.toString)
 
-      val sub = Problem(newAs, subPc, subProblem, p.xs)
+      val sub = Problem(newAs, subWs, subPc, subProblem, p.xs)
 
       val onSuccess: List[Solution] => Option[Solution] = {
         case List(sol) =>
diff --git a/src/main/scala/leon/synthesis/rules/DetupleOutput.scala b/src/main/scala/leon/synthesis/rules/DetupleOutput.scala
index f64f3f31bc12861696911a3cb4787f55868fec66..592853c846f26342f12169634f08e576a8229d79 100644
--- a/src/main/scala/leon/synthesis/rules/DetupleOutput.scala
+++ b/src/main/scala/leon/synthesis/rules/DetupleOutput.scala
@@ -41,7 +41,7 @@ case object DetupleOutput extends Rule("Detuple Out") {
 
       val newOuts = subOuts.flatten
 
-      val sub = Problem(p.as, p.pc, subProblem, newOuts)
+      val sub = Problem(p.as, p.ws, p.pc, subProblem, newOuts)
 
       val onSuccess: List[Solution] => Option[Solution] = {
         case List(sol) =>
diff --git a/src/main/scala/leon/synthesis/rules/GuidedCloser.scala b/src/main/scala/leon/synthesis/rules/GuidedCloser.scala
index 45599ec7c29e2286191b1232171e881cb51c0520..0cc03942c364ec52da59e20cc0d1a9342bf59491 100644
--- a/src/main/scala/leon/synthesis/rules/GuidedCloser.scala
+++ b/src/main/scala/leon/synthesis/rules/GuidedCloser.scala
@@ -17,7 +17,7 @@ import solvers._
 
 case object GuidedCloser extends NormalizingRule("Guided Closer") {
   def instantiateOn(sctx: SynthesisContext, p: Problem): Traversable[RuleInstantiation] = {
-    val TopLevelAnds(clauses) = p.pc
+    val TopLevelAnds(clauses) = p.ws
 
     val guide = sctx.program.library.guide.get
 
diff --git a/src/main/scala/leon/synthesis/rules/GuidedDecomp.scala b/src/main/scala/leon/synthesis/rules/GuidedDecomp.scala
index af2ad3b6d5e5d84ad4eaf037c300a77bd01c6a98..a5a7418c218a87fa9e08acccedee547ebf5f4d9a 100644
--- a/src/main/scala/leon/synthesis/rules/GuidedDecomp.scala
+++ b/src/main/scala/leon/synthesis/rules/GuidedDecomp.scala
@@ -18,7 +18,7 @@ import solvers._
 
 case object GuidedDecomp extends Rule("Guided Decomp") {
   def instantiateOn(sctx: SynthesisContext, p: Problem): Traversable[RuleInstantiation] = {
-    val TopLevelAnds(clauses) = p.pc
+    val TopLevelAnds(clauses) = p.ws
 
     val guide = sctx.program.library.guide.get
 
@@ -26,9 +26,7 @@ case object GuidedDecomp extends Rule("Guided Decomp") {
       case FunctionInvocation(TypedFunDef(`guide`, _), Seq(expr)) => expr
     }
 
-    def simplify(e: Expr): Expr = {
-      Simplifiers.forPathConditions(sctx.context, sctx.program)(e)
-    }
+    val simplify = Simplifiers.bestEffort(sctx.context, sctx.program)_
 
     def doSubstitute(substs: Seq[(Expr, Expr)], e: Expr): Expr = {
       var res = e
@@ -40,8 +38,8 @@ case object GuidedDecomp extends Rule("Guided Decomp") {
 
     val alts = guides.collect {
       case g @ IfExpr(c, thn, els) =>
-        val sub1 = p.copy(pc = and(c, replace(Map(g -> thn), p.pc)))
-        val sub2 = p.copy(pc = and(Not(c), replace(Map(g -> els), p.pc)))
+        val sub1 = p.copy(ws = replace(Map(g -> thn), p.ws), pc = and(c, replace(Map(g -> thn), p.pc)))
+        val sub2 = p.copy(ws = replace(Map(g -> els), p.ws), pc = and(Not(c), replace(Map(g -> els), p.pc)))
 
         val onSuccess: List[Solution] => Option[Solution] = { 
           case List(s1, s2) =>
@@ -53,7 +51,7 @@ case object GuidedDecomp extends Rule("Guided Decomp") {
         Some(RuleInstantiation.immediateDecomp(p, this, List(sub1, sub2), onSuccess, "Guided If-Split on '"+c+"'"))
 
       case m @ MatchExpr(scrut0, cs) =>
-        
+
         val scrut = scrut0 match {
           case v : Variable => v
           case _ => Variable(FreshIdentifier("scrut", true).setType(scrut0.getType))
@@ -68,14 +66,15 @@ case object GuidedDecomp extends Rule("Guided Decomp") {
           
           val pc  = simplify(and(
             scrutCond,
-            replace(Map(scrut0 -> scrut),doSubstitute(substs,scrutConstraint)),
+            replace(Map(scrut0 -> scrut), doSubstitute(substs,scrutConstraint)),
             replace(Map(scrut0 -> scrut), replace(Map(m -> c.rhs), andJoin(cond)))
           ))
-          val phi = doSubstitute(substs, p.phi) 
+          val ws = replace(Map(m -> c.rhs), p.ws)
+          val phi = doSubstitute(substs, p.phi)
           val free = variablesOf(and(pc, phi)) -- p.xs
           val asPrefix = p.as.filter(free)
 
-          Problem(asPrefix ++ (free -- asPrefix), pc, phi, p.xs)
+          Problem(asPrefix ++ (free -- asPrefix), ws, pc, phi, p.xs)
         }
 
         val onSuccess: List[Solution] => Option[Solution] = { subs =>
diff --git a/src/main/scala/leon/synthesis/rules/IfSplit.scala b/src/main/scala/leon/synthesis/rules/IfSplit.scala
index 600e7f1c2ecfacbfa301c2d706096788db30321b..c870f5fe8f3c05ad19f93d252ac55396a45ef3ad 100644
--- a/src/main/scala/leon/synthesis/rules/IfSplit.scala
+++ b/src/main/scala/leon/synthesis/rules/IfSplit.scala
@@ -30,8 +30,8 @@ case object IfSplit extends Rule("If-Split") {
 
   def split(i: IfExpr, p: Problem, description: String): RuleInstantiation = {
     val subs = List(
-      Problem(p.as, and(p.pc, i.cond), replace(Map(i -> i.thenn), p.phi), p.xs),
-      Problem(p.as, and(p.pc, not(i.cond)), replace(Map(i -> i.elze), p.phi), p.xs)
+      Problem(p.as, p.ws, and(p.pc, i.cond), replace(Map(i -> i.thenn), p.phi), p.xs),
+      Problem(p.as, p.ws, and(p.pc, not(i.cond)), replace(Map(i -> i.elze), p.phi), p.xs)
     )
 
     val onSuccess: List[Solution] => Option[Solution] = {
diff --git a/src/main/scala/leon/synthesis/rules/IntegerEquation.scala b/src/main/scala/leon/synthesis/rules/IntegerEquation.scala
index ec7e2ae55ee6140f3559d4cdaf3ccc1099e1dd66..cc9ca0e95891371c8d6db3b7f7d28e035dc6b04e 100644
--- a/src/main/scala/leon/synthesis/rules/IntegerEquation.scala
+++ b/src/main/scala/leon/synthesis/rules/IntegerEquation.scala
@@ -57,7 +57,7 @@ case object IntegerEquation extends Rule("Integer Equation") {
 
         if(normalizedEq.size == 1) {
           val eqPre = Equals(normalizedEq.head, IntLiteral(0))
-          val newProblem = Problem(problem.as, and(eqPre, problem.pc), andJoin(allOthers), problem.xs)
+          val newProblem = Problem(problem.as, problem.ws, and(eqPre, problem.pc), andJoin(allOthers), problem.xs)
 
           val onSuccess: List[Solution] => Option[Solution] = { 
             case List(Solution(pre, defs, term)) =>
@@ -94,7 +94,7 @@ case object IntegerEquation extends Rule("Integer Equation") {
           val ys: List[Identifier] = problem.xs.filterNot(neqxs.contains(_))
           val subproblemxs: List[Identifier] = freshxs ++ ys
 
-          val newProblem = Problem(problem.as ++ freshInputVariables, and(eqPre, problem.pc), freshFormula, subproblemxs)
+          val newProblem = Problem(problem.as ++ freshInputVariables, problem.ws, and(eqPre, problem.pc), freshFormula, subproblemxs)
 
           val onSuccess: List[Solution] => Option[Solution] = { 
             case List(Solution(pre, defs, term)) => {
diff --git a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala b/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala
index 0b69b8fd22135be7ebe8c5321f1ebe5efd242735..6101bac28d303ad0af3857724f89f587abbef609 100644
--- a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala
+++ b/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala
@@ -174,7 +174,7 @@ case object IntegerInequalities extends Rule("Integer Inequalities") {
                                 newLowerBounds.map(lbound => LessEquals(Variable(k), Minus(b, lbound)))
           } ++ exprNotUsed))
         val subProblemxs: List[Identifier] = quotientIds ++ otherVars
-        val subProblem = Problem(problem.as ++ remainderIds, problem.pc, subProblemFormula, subProblemxs)
+        val subProblem = Problem(problem.as ++ remainderIds, problem.ws, problem.pc, subProblemFormula, subProblemxs)
 
 
         def onSuccess(sols: List[Solution]): Option[Solution] = sols match {
diff --git a/src/main/scala/leon/synthesis/rules/OnePoint.scala b/src/main/scala/leon/synthesis/rules/OnePoint.scala
index 5628e3404a1c7c545cde14224863252c27d7eff2..6c0e81a3c3dfc0d2951903f11f53d2b038af1023 100644
--- a/src/main/scala/leon/synthesis/rules/OnePoint.scala
+++ b/src/main/scala/leon/synthesis/rules/OnePoint.scala
@@ -31,7 +31,7 @@ case object OnePoint extends NormalizingRule("One-point") {
       val others = exprs.filter(_ != eq)
       val oxs    = p.xs.filter(_ != x)
 
-      val newProblem = Problem(p.as, p.pc, subst(x -> e, andJoin(others)), oxs)
+      val newProblem = Problem(p.as, p.ws, p.pc, subst(x -> e, andJoin(others)), oxs)
 
       val onSuccess: List[Solution] => Option[Solution] = {
         case List(Solution(pre, defs, term)) =>
diff --git a/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala b/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala
index e9953f65a17af5b4f1e2eefa3a296c52aa41d376..58eb0f5827450cde0038f9567cc02e3b9cf27fad 100644
--- a/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala
+++ b/src/main/scala/leon/synthesis/utils/ExpressionGrammar.scala
@@ -333,9 +333,9 @@ object ExpressionGrammars {
    }
   }
 
-  case class SafeRecCalls(prog: Program, pc: Expr) extends ExpressionGrammar[TypeTree] {
+  case class SafeRecCalls(prog: Program, ws: Expr, pc: Expr) extends ExpressionGrammar[TypeTree] {
     def computeProductions(t: TypeTree): Seq[Gen] = {
-      val calls = terminatingCalls(prog, t, pc)
+      val calls = terminatingCalls(prog, t, ws, pc)
 
       calls.map {
         case (e, free) =>
@@ -347,14 +347,14 @@ object ExpressionGrammars {
     }
   }
 
-  def default(prog: Program, inputs: Seq[Expr], currentFunction: FunDef, pc: Expr): ExpressionGrammar[TypeTree] = {
+  def default(prog: Program, inputs: Seq[Expr], currentFunction: FunDef, ws: Expr, pc: Expr): ExpressionGrammar[TypeTree] = {
     BaseGrammar ||
     OneOf(inputs) ||
     FunctionCalls(prog, currentFunction, inputs.map(_.getType)) ||
-    SafeRecCalls(prog, pc)
+    SafeRecCalls(prog, ws, pc)
   }
 
   def default(sctx: SynthesisContext, p: Problem): ExpressionGrammar[TypeTree] = {
-    default(sctx.program, p.as.map(_.toVariable), sctx.functionContext, p.pc)
+    default(sctx.program, p.as.map(_.toVariable), sctx.functionContext, p.ws, p.pc)
   }
 }
diff --git a/src/main/scala/leon/synthesis/utils/Helpers.scala b/src/main/scala/leon/synthesis/utils/Helpers.scala
index 98d946485dadb5356f6c5d78367065161896859a..5567c9d7a757d67b2253b80911bf1b89a716eb0b 100644
--- a/src/main/scala/leon/synthesis/utils/Helpers.scala
+++ b/src/main/scala/leon/synthesis/utils/Helpers.scala
@@ -34,10 +34,11 @@ object Helpers {
     }
   }
 
-  def terminatingCalls(prog: Program, tpe: TypeTree, e: Expr): List[(Expr, Set[Identifier])] = {
+  def terminatingCalls(prog: Program, tpe: TypeTree, ws: Expr, pc: Expr): List[(Expr, Set[Identifier])] = {
+    // TODO: Also allow calls to f(y) when: terminating(f(x)) && y == x.f 
     val terminating = prog.library.terminating.get
 
-    val TopLevelAnds(clauses) = e
+    val TopLevelAnds(clauses) = ws
 
     val gs: List[FunctionInvocation] = clauses.toList.collect {
       case FunctionInvocation(TypedFunDef(`terminating`, _), Seq(fi: FunctionInvocation)) => fi
diff --git a/src/main/scala/leon/utils/Simplifiers.scala b/src/main/scala/leon/utils/Simplifiers.scala
index cb57f3fd18f7d70e2b72fb41995509552f22d235..c0ccde86d850bae5cfb7a6e748b9da54c49ced67 100644
--- a/src/main/scala/leon/utils/Simplifiers.scala
+++ b/src/main/scala/leon/utils/Simplifiers.scala
@@ -14,7 +14,6 @@ object Simplifiers {
     val uninterpretedZ3 = SolverFactory(() => new UninterpretedZ3Solver(ctx, p))
 
     val simplifiers = List[Expr => Expr](
-      removeWitnesses(p) _,
       simplifyTautologies(uninterpretedZ3)(_),
       simplifyLets _,
       simplifyPaths(uninterpretedZ3)(_),
@@ -36,27 +35,6 @@ object Simplifiers {
     (new ScopeSimplifier).transform(s)
   }
 
-  // Besteffort, but keep witnesses
-  def forPathConditions(ctx: LeonContext, p: Program)(e: Expr): Expr = {
-    val uninterpretedZ3 = SolverFactory(() => new UninterpretedZ3Solver(ctx, p))
-
-    val simplifiers = List[Expr => Expr](
-      simplifyTautologies(uninterpretedZ3)(_),
-      simplifyLets _,
-      simplifyPaths(uninterpretedZ3)(_),
-      rewriteTuples _//,
-      //normalizeExpression _
-    )
-
-    val simple = { expr: Expr =>
-      simplifiers.foldLeft(expr){ case (x, sim) => 
-        sim(x)
-      }
-    }
-
-    fixpoint(simple, 5)(e)
-  }
-
   def namePreservingBestEffort(ctx: LeonContext, p: Program)(e: Expr): Expr = {
     val uninterpretedZ3 = SolverFactory(() => new UninterpretedZ3Solver(ctx, p))