diff --git a/src/main/scala/leon/repair/rules/Focus.scala b/src/main/scala/leon/repair/rules/Focus.scala
index 943a5a67f094aea19f1c3903da6b0a32b19e10ec..7ce3fd261cbd4b9f28fae11517bb7640895f5517 100644
--- a/src/main/scala/leon/repair/rules/Focus.scala
+++ b/src/main/scala/leon/repair/rules/Focus.scala
@@ -164,7 +164,7 @@ case object Focus extends PreprocessingRule("Focus") {
             val eb3 = if (vars.nonEmpty) {
               eb2.mapIns(ebF)
             } else {
-              eb2
+              eb2.eb
             }
 
             val newPc = andJoin(cond +: vars.map { id => equality(id.toVariable, map(id)) })
diff --git a/src/main/scala/leon/synthesis/ExamplesBank.scala b/src/main/scala/leon/synthesis/ExamplesBank.scala
index 1da37b3509f4abdd0a8b3ecbdd329b55ab16f45f..35a6986864dde1a97fdca214536dac6a21b52c57 100644
--- a/src/main/scala/leon/synthesis/ExamplesBank.scala
+++ b/src/main/scala/leon/synthesis/ExamplesBank.scala
@@ -160,38 +160,44 @@ case class ExamplesBank(valids: Seq[Example], invalids: Seq[Example]) {
 
 object ExamplesBank {
   def empty = ExamplesBank(Nil, Nil)
+
 }
 
 /** Same as an ExamplesBank, but with identifiers corresponding to values. This
   * allows us to evaluate expressions. */
 case class QualifiedExamplesBank(as: List[Identifier], xs: List[Identifier], eb: ExamplesBank)(implicit hctx: SearchContext) {
 
-  def removeOuts(toRemove: Set[Identifier]) = {
+  def removeOuts(toRemove: Set[Identifier]): QualifiedExamplesBank = {
+    val nxs    = xs.filterNot(toRemove)
     val toKeep = xs.zipWithIndex.filterNot(x => toRemove(x._1)).map(_._2)
 
-    eb mapOuts { out => List(toKeep.map(out)) }
+    QualifiedExamplesBank(as, nxs, eb mapOuts { out => List(toKeep.map(out)) })
   }
 
   def removeIns(toRemove: Set[Identifier]) = {
+    val nas = as.filterNot(toRemove)
     val toKeep: List[Int] = as.zipWithIndex.filterNot(a => toRemove(a._1)).map(_._2)
-    eb mapIns { (in: Seq[Expr]) => List(toKeep.map(in)) }
+
+    QualifiedExamplesBank(nas, xs, eb mapIns { (in: Seq[Expr]) => List(toKeep.map(in)) })
   }
 
   /** Filter inputs throught expr which is an expression evaluating to a boolean */
-  def filterIns(expr: Expr): ExamplesBank = {
+  def filterIns(expr: Expr): QualifiedExamplesBank = {
     filterIns(m => hctx.defaultEvaluator.eval(expr, m).result == Some(BooleanLiteral(true)))
   }
 
   /** Filters inputs through the predicate pred, with an assignment of input variables to expressions. */
-  def filterIns(pred: Map[Identifier, Expr] => Boolean): ExamplesBank = {
-    eb mapIns { in =>
-      val m = (as zip in).toMap
-      if(pred(m)) {
-        List(in)
-      } else {
-        Nil
+  def filterIns(pred: Map[Identifier, Expr] => Boolean): QualifiedExamplesBank = {
+    QualifiedExamplesBank(as, xs,
+      eb mapIns { in =>
+        val m = (as zip in).toMap
+        if(pred(m)) {
+          List(in)
+        } else {
+          Nil
+        }
       }
-    }
+    )
   }
 
   /** Maps inputs through the function f
@@ -206,3 +212,9 @@ case class QualifiedExamplesBank(as: List[Identifier], xs: List[Identifier], eb:
     }
   }
 }
+
+import scala.language.implicitConversions
+
+object QualifiedExamplesBank {
+  implicit def qebToEb(qeb: QualifiedExamplesBank): ExamplesBank = qeb.eb
+}
diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala
index f55c670f4515070a1d0ccb5bd02b33b24bf9c22f..ff92b251e76cce8508629fe3cafeb9e40f37cb74 100644
--- a/src/main/scala/leon/synthesis/Rules.scala
+++ b/src/main/scala/leon/synthesis/Rules.scala
@@ -51,26 +51,15 @@ object Rules {
     UnusedInput,
     EquivalentInputs,
     UnconstrainedOutput,
+    if(naiveGrammar) NaiveCEGIS else CEGIS,
     OptimisticGround,
-    EqualitySplit,
+    GenericTypeEqualitySplit,
     InequalitySplit,
     IntroduceRecCalls,
-    if(naiveGrammar) NaiveCEGIS else CEGIS,
-    //TEGIS,
-    //BottomUpTEGIS,
     rules.Assert,
-    //DetupleOutput, // Subsumed by IndependentSplit
     DetupleInput,
     ADTSplit,
-    //IntegerEquation,
-    //IntegerInequalities,
-    IntInduction,
     InnerCaseSplit
-    //new OptimisticInjection(_),
-    //new SelectiveInlining(_),
-    //ADTLongInduction,
-    //ADTInduction
-    //AngelicHoles // @EK: Disabled now as it is explicit with withOracle { .. }
   )
 
 }
@@ -212,20 +201,4 @@ trait RuleDSL {
     case _ => None
 
   }
-
-  /** Straightforward combination of solutions, where expression is reconstructed according to a combiner.
-    * If combiner fails, no solution will be returned.
-    *
-    * @param combiner The combiner of synthesized subterms which reconstructs the term of the solution from the subterms.
-    */
-  def simpleCombine(combiner: PartialFunction[List[Expr], Expr]): List[Solution] => Option[Solution] = { ls =>
-    combiner.lift(ls map (_.term)).map{ combined =>
-      Solution(
-        orJoin(ls map (_.pre)),
-        ls.flatMap (_.defs).toSet,
-        combined,
-        ls.forall(_.isTrusted)
-      )
-    }
-  }
 }
diff --git a/src/main/scala/leon/synthesis/rules/EqualitySplit.scala b/src/main/scala/leon/synthesis/rules/EqualitySplit.scala
deleted file mode 100644
index 6f6eea54f5a5647aed883a2e8de68508e1fdd950..0000000000000000000000000000000000000000
--- a/src/main/scala/leon/synthesis/rules/EqualitySplit.scala
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright 2009-2016 EPFL, Lausanne */
-
-package leon
-package synthesis
-package rules
-
-import purescala.Common.Identifier
-import purescala.Expressions._
-import purescala.Extractors._
-import purescala.Constructors._
-
-/** For every pair of input variables of the same type,
-  * checks equality and output an If-Then-Else statement with the two new branches. */
-case object EqualitySplit extends Rule("Eq. Split") {
-  def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
-    // We approximate knowledge of equality based on facts found at the top-level
-    // we don't care if the variables are known to be equal or not, we just
-    // don't want to split on two variables for which only one split
-    // alternative is viable. This should be much less expensive than making
-    //  calls to a solver for each pair.
-    var facts = Set[Set[Identifier]]()
-
-    def addFacts(e: Expr): Unit = e match {
-      case Not(e) => addFacts(e)
-      case LessThan(Variable(a), Variable(b))      => facts += Set(a,b)
-      case LessEquals(Variable(a), Variable(b))    => facts += Set(a,b)
-      case GreaterThan(Variable(a), Variable(b))   => facts += Set(a,b)
-      case GreaterEquals(Variable(a), Variable(b)) => facts += Set(a,b)
-      case Equals(Variable(a), Variable(b))        => facts += Set(a,b)
-      case _ =>
-    }
-
-    val TopLevelAnds(as) = and(p.pc, p.phi)
-    for (e <- as) {
-      addFacts(e)
-    }
-
-    val candidates = p.as.groupBy(_.getType).mapValues{ as =>
-      as.combinations(2).filterNot(facts contains _.toSet)
-    }.values.flatten
-
-    candidates.flatMap {
-      case List(a1, a2) =>
-
-        val sub1 = p.copy(
-          pc = and(Equals(Variable(a1), Variable(a2)), p.pc),
-          eb = p.qeb.filterIns( (m: Map[Identifier, Expr]) => m(a1) == m(a2))
-        )
-        val sub2 = p.copy(
-          pc = and(not(Equals(Variable(a1), Variable(a2))), p.pc),
-          eb = p.qeb.filterIns( (m: Map[Identifier, Expr]) => m(a1) != m(a2))
-        )
-
-        val onSuccess = simpleCombine { case List(s1, s2) => IfExpr(Equals(Variable(a1), Variable(a2)), s1, s2) }
-
-        Some(decomp(List(sub1, sub2), onSuccess, s"Eq. Split on '$a1' and '$a2'"))
-      case _ =>
-        None
-    }
-  }
-}
diff --git a/src/main/scala/leon/synthesis/rules/GenericTypeEqualitySplit.scala b/src/main/scala/leon/synthesis/rules/GenericTypeEqualitySplit.scala
new file mode 100644
index 0000000000000000000000000000000000000000..8dce44d6878ad24ed96dd5c33b9461100cd9f417
--- /dev/null
+++ b/src/main/scala/leon/synthesis/rules/GenericTypeEqualitySplit.scala
@@ -0,0 +1,72 @@
+/* Copyright 2009-2016 EPFL, Lausanne */
+
+package leon
+package synthesis
+package rules
+
+import leon.purescala.Common.Identifier
+import purescala.Constructors._
+import purescala.Expressions._
+import leon.purescala.Extractors.{IsTyped, TopLevelAnds}
+import purescala.Types._
+
+/** For every pair of input variables of the same generic type,
+  * checks equality and output an If-Then-Else statement with the two new branches.
+  */
+case object GenericTypeEqualitySplit extends Rule("Eq. Split") {
+  def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
+    // We approximate knowledge of equality based on facts found at the top-level
+    // we don't care if the variables are known to be equal or not, we just
+    // don't want to split on two variables for which only one split
+    // alternative is viable. This should be much less expensive than making
+    // calls to a solver for each pair.
+    def getFacts(e: Expr): Set[Set[Identifier]] = e match {
+      case Not(e)       => getFacts(e)
+      case Equals(Variable(a), Variable(b)) => Set(Set(a,b))
+      case _ => Set()
+    }
+
+    val TopLevelAnds(as) = and(p.pc, p.phi)
+
+    val facts = as.flatMap(getFacts).toSet
+
+    val candidates = p.as.combinations(2).collect {
+      case List(IsTyped(a1, TypeParameter(t1)), IsTyped(a2, TypeParameter(t2)))
+        if t1 == t2 && !facts(Set(a1, a2)) =>
+        (a1, a2)
+    }.toList
+
+    candidates.flatMap {
+      case (a1, a2) =>
+        val v1 = Variable(a1)
+        val v2 = Variable(a2)
+        val subProblems = List(
+          p.copy(as  = p.as.diff(Seq(a1)),
+                 pc  = subst(a1 -> v2, p.pc),
+                 ws  = subst(a1 -> v2, p.ws),
+                 phi = subst(a1 -> v2, p.phi),
+                 eb  = p.qeb.filterIns(Equals(v1, v2)).removeIns(Set(a1))),
+
+          p.copy(pc = and(p.pc, not(Equals(v1, v2))),
+                 eb = p.qeb.filterIns(not(Equals(v1, v2))))
+        )
+
+        val onSuccess: List[Solution] => Option[Solution] = {
+          case sols @ List(sEQ, sNE) =>
+            val pre = or(
+              and(Equals(v1, v2),      sEQ.pre),
+              and(not(Equals(v1, v2)), sNE.pre)
+            )
+
+            val term = IfExpr(Equals(v1, v2), sEQ.term, sNE.term)
+
+            Some(Solution(pre, sols.flatMap(_.defs).toSet, term, sols.forall(_.isTrusted)))
+        }
+
+        Some(decomp(subProblems, onSuccess, s"Eq. Split on '$v1' and '$v2'"))
+
+      case _ =>
+        None
+    }
+  }
+}
diff --git a/src/main/scala/leon/synthesis/rules/InequalitySplit.scala b/src/main/scala/leon/synthesis/rules/InequalitySplit.scala
index db41c6c3b45694c27af6c78b6fa420dcd3ca6324..54445a5d48dc199440366aa8ac302d1c075bd4c2 100644
--- a/src/main/scala/leon/synthesis/rules/InequalitySplit.scala
+++ b/src/main/scala/leon/synthesis/rules/InequalitySplit.scala
@@ -8,65 +8,99 @@ import purescala.Expressions._
 import purescala.Types._
 import purescala.Constructors._
 import purescala.Extractors._
-import purescala.Common._
 
+/** For every pair of variables of an integer type plus 0 of that type,
+  * splits for inequality between these variables
+  * and reconstructs the subproblems with a (nested) if-then-else.
+  *
+  * Takes into account knowledge about equality/inequality in the path condition.
+  *
+  */
 case object InequalitySplit extends Rule("Ineq. Split.") {
+
+  // Represents NEGATIVE knowledge
+  private abstract class Fact {
+    val l: Expr
+    val r: Expr
+  }
+  private case class LT(l: Expr, r: Expr) extends Fact
+  private case class EQ(l: Expr, r: Expr) extends Fact
+
   def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
-    // We approximate knowledge of equality based on facts found at the top-level
-    // we don't care if the variables are known to be equal or not, we just
-    // don't want to split on two variables for which only one split
-    // alternative is viable. This should be much less expensive than making
-    //  calls to a solver for each pair.
 
     val TopLevelAnds(as) = and(p.pc, p.phi)
-    def addFacts(e: Expr): Set[Identifier] = e match {
-      case Not(e) => addFacts(e)
-      case LessThan(Variable(a), Variable(b))      => Set(a,b)
-      case LessEquals(Variable(a), Variable(b))    => Set(a,b)
-      case GreaterThan(Variable(a), Variable(b))   => Set(a,b)
-      case GreaterEquals(Variable(a), Variable(b)) => Set(a,b)
-      case Equals(Variable(a), Variable(b))        => Set(a,b)
+
+    def getFacts(e: Expr): Set[Fact] = e match {
+      case LessThan(a, b)           => Set(LT(b,a), EQ(a,b))
+      case LessEquals(a, b)         => Set(LT(b,a))
+      case GreaterThan(a, b)        => Set(LT(a,b), EQ(a,b))
+      case GreaterEquals(a, b)      => Set(LT(a,b))
+      case Equals(a, b)             => Set(LT(a,b), LT(b,a))
+      case Not(LessThan(a, b))      => Set(LT(a,b))
+      case Not(LessEquals(a, b))    => Set(LT(a,b), EQ(a,b))
+      case Not(GreaterThan(a, b))   => Set(LT(b,a))
+      case Not(GreaterEquals(a, b)) => Set(LT(b,a), EQ(a,b))
+      case Not(Equals(a, b))        => Set(EQ(a,b))
       case _ => Set()
     }
-    val facts = as map addFacts
-
-    val argsPairs = p.as.filter(_.getType == IntegerType).combinations(2) ++
-                    p.as.filter(_.getType == Int32Type).combinations(2)
-
-    val candidates = argsPairs.toList.filter { case List(a1, a2) => !(facts contains Set(a1, a2)) }
-
-    candidates.collect {
-      case List(a1, a2) =>
-        val onSuccess = simpleCombine {
-          case sols@List(sLT, sEQ, sGT) =>
-            IfExpr(
-              LessThan(Variable(a1), Variable(a2)),
-              sLT,
-              IfExpr(
-                Equals(Variable(a1), Variable(a2)),
-                sEQ,
-                sGT
-              )
-            )
-        }
 
-        val subTypes = List(p.outType, p.outType, p.outType)
+    val facts = as flatMap getFacts
+
+    val candidates =
+      (p.as.map(_.toVariable).filter(_.getType == Int32Type) :+ IntLiteral(0)).combinations(2).toList ++
+      (p.as.map(_.toVariable).filter(_.getType == IntegerType) :+ InfiniteIntegerLiteral(0)).combinations(2).toList
 
-        new RuleInstantiation(s"Ineq. Split on '$a1' and '$a2'",
-                              SolutionBuilderDecomp(subTypes, onSuccess)) {
+    candidates.flatMap {
+      case List(v1, v2) =>
 
-          def apply(hctx: SearchContext) = {
-            implicit val _ = hctx
+        val lt = if (!facts.contains(LT(v1, v2))) {
+          val pc = LessThan(v1, v2)
+          Some(pc, p.copy(pc = and(p.pc, pc), eb = p.qeb.filterIns(pc)))
+        } else None
 
-            val subLT = p.copy(pc = and(LessThan(Variable(a1), Variable(a2)), p.pc),
-                               eb = p.qeb.filterIns(LessThan(Variable(a1), Variable(a2))))
-            val subEQ = p.copy(pc = and(Equals(Variable(a1), Variable(a2)), p.pc),
-                               eb = p.qeb.filterIns(Equals(Variable(a1), Variable(a2))))
-            val subGT = p.copy(pc = and(GreaterThan(Variable(a1), Variable(a2)), p.pc),
-                               eb = p.qeb.filterIns(GreaterThan(Variable(a1), Variable(a2))))
+        val gt = if (!facts.contains(LT(v2, v1))) {
+          val pc = GreaterThan(v1, v2)
+          Some(pc, p.copy(pc = and(p.pc, pc), eb = p.qeb.filterIns(pc)))
+        } else None
 
-            RuleExpanded(List(subLT, subEQ, subGT))
+        val eq = if (!facts.contains(EQ(v1, v2)) && !facts.contains(EQ(v2,v1))) {
+          val pc = Equals(v1, v2)
+          // One of v1, v2 will be an input variable
+          val a1 = (v1, v2) match {
+            case (Variable(a), _) => a
+            case (_, Variable(a)) => a
           }
+          val newP = p.copy(
+            as = p.as.diff(Seq(a1)),
+            pc = subst(a1 -> v2, p.pc),
+            ws = subst(a1 -> v2, p.ws),
+            phi = subst(a1 -> v2, p.phi),
+            eb = p.qeb.filterIns(Equals(v1, v2)).removeIns(Set(a1))
+          )
+          Some(pc, newP)
+        } else None
+
+        val (pcs, subProblems) = List(eq, lt, gt).flatten.unzip
+
+        if (pcs.size < 2) None
+        else {
+
+          val onSuccess: List[Solution] => Option[Solution] = { sols =>
+            val pre = orJoin(pcs.zip(sols).map { case (pc, sol) =>
+              and(pc, sol.pre)
+            })
+
+            val term = pcs.zip(sols) match {
+              case Seq((pc1, s1), (_, s2)) =>
+                IfExpr(pc1, s1.term, s2.term)
+              case Seq((pc1, s1), (pc2, s2), (_, s3)) =>
+                IfExpr(pc1, s1.term, IfExpr(pc2, s2.term, s3.term))
+            }
+
+            Some(Solution(pre, sols.flatMap(_.defs).toSet, term, sols.forall(_.isTrusted)))
+          }
+
+          Some(decomp(subProblems, onSuccess, s"Ineq. Split on '$v1' and '$v2'"))
         }
     }
   }
diff --git a/src/main/scala/leon/synthesis/rules/ADTInduction.scala b/src/main/scala/leon/synthesis/rules/unused/ADTInduction.scala
similarity index 99%
rename from src/main/scala/leon/synthesis/rules/ADTInduction.scala
rename to src/main/scala/leon/synthesis/rules/unused/ADTInduction.scala
index 90738c698c1947b197406e61390c0ba0ca628b7a..ab2720fb00f620c0800d6936c9e97b3be3deedac 100644
--- a/src/main/scala/leon/synthesis/rules/ADTInduction.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/ADTInduction.scala
@@ -2,7 +2,7 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Common._
 import purescala.Expressions._
diff --git a/src/main/scala/leon/synthesis/rules/ADTLongInduction.scala b/src/main/scala/leon/synthesis/rules/unused/ADTLongInduction.scala
similarity index 99%
rename from src/main/scala/leon/synthesis/rules/ADTLongInduction.scala
rename to src/main/scala/leon/synthesis/rules/unused/ADTLongInduction.scala
index d14c2b0f8538a61dd0ce8c3ae507f05bcc79c2f7..4ffd1a8c258a48007959f87cfb861812959517a8 100644
--- a/src/main/scala/leon/synthesis/rules/ADTLongInduction.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/ADTLongInduction.scala
@@ -2,7 +2,7 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Common._
 import purescala.Expressions._
diff --git a/src/main/scala/leon/synthesis/rules/AsChoose.scala b/src/main/scala/leon/synthesis/rules/unused/AsChoose.scala
similarity index 79%
rename from src/main/scala/leon/synthesis/rules/AsChoose.scala
rename to src/main/scala/leon/synthesis/rules/unused/AsChoose.scala
index 7f231b85df8c57f3a87e60f88030679024bf30d6..06270b939929a96985719b78a3f58ee58d9ce931 100644
--- a/src/main/scala/leon/synthesis/rules/AsChoose.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/AsChoose.scala
@@ -1,8 +1,8 @@
 /* Copyright 2009-2016 EPFL, Lausanne */
 
-package leon
-package synthesis
-package rules
+package leon.synthesis.rules.unused
+
+import leon.synthesis._
 
 case object AsChoose extends Rule("As Choose") {
   def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
diff --git a/src/main/scala/leon/synthesis/rules/BottomUpTegis.scala b/src/main/scala/leon/synthesis/rules/unused/BottomUpTegis.scala
similarity index 99%
rename from src/main/scala/leon/synthesis/rules/BottomUpTegis.scala
rename to src/main/scala/leon/synthesis/rules/unused/BottomUpTegis.scala
index 5dbcbb3a131deab0cf091778771a328ae9a47379..8f82395a55c522a8a84a9aa463e0e704cd89beed 100644
--- a/src/main/scala/leon/synthesis/rules/BottomUpTegis.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/BottomUpTegis.scala
@@ -2,7 +2,7 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Expressions._
 import purescala.Common._
diff --git a/src/main/scala/leon/synthesis/rules/DetupleOutput.scala b/src/main/scala/leon/synthesis/rules/unused/DetupleOutput.scala
similarity index 98%
rename from src/main/scala/leon/synthesis/rules/DetupleOutput.scala
rename to src/main/scala/leon/synthesis/rules/unused/DetupleOutput.scala
index a1d2193409788cd54d25639d6900dc5b9301ec33..18067e9529596329d44cacf9672931c6e0178414 100644
--- a/src/main/scala/leon/synthesis/rules/DetupleOutput.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/DetupleOutput.scala
@@ -2,7 +2,7 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Expressions._
 import purescala.Common._
diff --git a/src/main/scala/leon/synthesis/rules/IntInduction.scala b/src/main/scala/leon/synthesis/rules/unused/IntInduction.scala
similarity index 95%
rename from src/main/scala/leon/synthesis/rules/IntInduction.scala
rename to src/main/scala/leon/synthesis/rules/unused/IntInduction.scala
index bfebd3929b8155b154590c798272df4c2aeba1a1..6ef209fcb386a98046a0bd107dd94d4aa3c31403 100644
--- a/src/main/scala/leon/synthesis/rules/IntInduction.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/IntInduction.scala
@@ -2,14 +2,14 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
-import purescala.Common._
-import purescala.Expressions._
-import purescala.Extractors._
+import purescala.Common.FreshIdentifier
 import purescala.Constructors._
-import purescala.Types._
-import purescala.Definitions._
+import purescala.Definitions.{FunDef, ValDef}
+import purescala.Expressions._
+import purescala.Extractors.IsTyped
+import purescala.Types.IntegerType
 
 case object IntInduction extends Rule("Int Induction") {
   def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
diff --git a/src/main/scala/leon/synthesis/rules/IntegerEquation.scala b/src/main/scala/leon/synthesis/rules/unused/IntegerEquation.scala
similarity index 99%
rename from src/main/scala/leon/synthesis/rules/IntegerEquation.scala
rename to src/main/scala/leon/synthesis/rules/unused/IntegerEquation.scala
index f51d9007564414836852324b46ba84b473f0714c..fdb59b00d7afabcb089b100a85381e646c89f5c7 100644
--- a/src/main/scala/leon/synthesis/rules/IntegerEquation.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/IntegerEquation.scala
@@ -2,7 +2,7 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Common._
 import purescala.Expressions._
diff --git a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala b/src/main/scala/leon/synthesis/rules/unused/IntegerInequalities.scala
similarity index 99%
rename from src/main/scala/leon/synthesis/rules/IntegerInequalities.scala
rename to src/main/scala/leon/synthesis/rules/unused/IntegerInequalities.scala
index dfb1fa8d6db8b49ae80a5e2062db9fd2b0b2b6be..602a7e61ba1e94c174f44cc71c04790feeb636f6 100644
--- a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/IntegerInequalities.scala
@@ -2,7 +2,7 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Common._
 import purescala.Expressions._
diff --git a/src/main/scala/leon/synthesis/rules/OptimisticInjection.scala b/src/main/scala/leon/synthesis/rules/unused/OptimisticInjection.scala
similarity index 98%
rename from src/main/scala/leon/synthesis/rules/OptimisticInjection.scala
rename to src/main/scala/leon/synthesis/rules/unused/OptimisticInjection.scala
index 599fbd5df54d4750b5021916eecc5103e126b57a..b3d35f8a090d8f1b85532040b558cb8abf5a0c8f 100644
--- a/src/main/scala/leon/synthesis/rules/OptimisticInjection.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/OptimisticInjection.scala
@@ -2,7 +2,7 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Expressions._
 import purescala.Extractors._
diff --git a/src/main/scala/leon/synthesis/rules/SelectiveInlining.scala b/src/main/scala/leon/synthesis/rules/unused/SelectiveInlining.scala
similarity index 90%
rename from src/main/scala/leon/synthesis/rules/SelectiveInlining.scala
rename to src/main/scala/leon/synthesis/rules/unused/SelectiveInlining.scala
index 4469382133c2ee4eb09424b07266382aafa1a0c6..9dd4e68e01ede5e953c3b0f06a573be505056dc3 100644
--- a/src/main/scala/leon/synthesis/rules/SelectiveInlining.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/SelectiveInlining.scala
@@ -2,11 +2,11 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
-import purescala.Expressions._
-import purescala.Extractors._
 import purescala.Constructors._
+import purescala.Expressions.{Equals, Expr, FunctionInvocation}
+import purescala.Extractors.TopLevelAnds
 
 case object SelectiveInlining extends Rule("Sel. Inlining") {
   def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
diff --git a/src/main/scala/leon/synthesis/rules/SygusCVC4.scala b/src/main/scala/leon/synthesis/rules/unused/SygusCVC4.scala
similarity index 90%
rename from src/main/scala/leon/synthesis/rules/SygusCVC4.scala
rename to src/main/scala/leon/synthesis/rules/unused/SygusCVC4.scala
index d458de88caf44c03acd12dab1d0b1ce42c59767f..800d1e5f84c3067fe94fb368a82f1302a8981c43 100644
--- a/src/main/scala/leon/synthesis/rules/SygusCVC4.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/SygusCVC4.scala
@@ -2,9 +2,9 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
-import solvers.sygus._
+import leon.solvers.sygus.CVC4SygusSolver
 
 case object SygusCVC4 extends Rule("SygusCVC4") {
   def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
diff --git a/src/main/scala/leon/synthesis/rules/TEGIS.scala b/src/main/scala/leon/synthesis/rules/unused/TEGIS.scala
similarity index 94%
rename from src/main/scala/leon/synthesis/rules/TEGIS.scala
rename to src/main/scala/leon/synthesis/rules/unused/TEGIS.scala
index 242502a169ff1107ad9ace70e5cef240c269b7f6..7b08304dcf7735649f3e7ec760a9cba73fe6caaa 100644
--- a/src/main/scala/leon/synthesis/rules/TEGIS.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/TEGIS.scala
@@ -2,7 +2,7 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Types._
 import grammars._
diff --git a/src/main/scala/leon/synthesis/rules/TEGISLike.scala b/src/main/scala/leon/synthesis/rules/unused/TEGISLike.scala
similarity index 99%
rename from src/main/scala/leon/synthesis/rules/TEGISLike.scala
rename to src/main/scala/leon/synthesis/rules/unused/TEGISLike.scala
index a085ad4366ea1f852b0ad714c713a5943fb269fd..cd6382864163d11c770386f09804d0504d2702fa 100644
--- a/src/main/scala/leon/synthesis/rules/TEGISLike.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/TEGISLike.scala
@@ -2,7 +2,7 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Expressions._
 import purescala.Types._
diff --git a/src/main/scala/leon/synthesis/rules/TEGLESS.scala b/src/main/scala/leon/synthesis/rules/unused/TEGLESS.scala
similarity index 96%
rename from src/main/scala/leon/synthesis/rules/TEGLESS.scala
rename to src/main/scala/leon/synthesis/rules/unused/TEGLESS.scala
index f87968ea3ae2da64110f77ff4fc9d7b627c2b487..a58a0b138d14f9aefc2fba71f16130a682f22968 100644
--- a/src/main/scala/leon/synthesis/rules/TEGLESS.scala
+++ b/src/main/scala/leon/synthesis/rules/unused/TEGLESS.scala
@@ -2,11 +2,10 @@
 
 package leon
 package synthesis
-package rules
+package rules.unused
 
 import purescala.Types._
 import purescala.Extractors._
-import utils._
 import Witnesses._
 import grammars._
 
diff --git a/src/main/scala/leon/synthesis/utils/Helpers.scala b/src/main/scala/leon/synthesis/utils/Helpers.scala
index 87d9c587c6c0b9ce24bd09df5753f0a5bb02667d..a0b940958ffecee169005512693d00539ffef196 100644
--- a/src/main/scala/leon/synthesis/utils/Helpers.scala
+++ b/src/main/scala/leon/synthesis/utils/Helpers.scala
@@ -61,9 +61,19 @@ object Helpers {
       case _ => None
     }
     
+    val z   = InfiniteIntegerLiteral(0)
+    val one = InfiniteIntegerLiteral(1)
     val knownSmallers = clauses.collect {
       case Equals(v: Variable, s@CaseClassSelector(cct, r, _)) => subExprsOf(s, v)
       case Equals(s@CaseClassSelector(cct, r, _), v: Variable) => subExprsOf(s, v)
+      case GreaterThan(v: Variable, `z`) =>
+        Some(v -> Minus(v, one))
+      case LessThan(`z`, v: Variable) =>
+        Some(v -> Minus(v, one))
+      case LessThan(v: Variable, `z`) =>
+        Some(v -> Plus(v, one))
+      case GreaterThan(`z`, v: Variable) =>
+        Some(v -> Plus(v, one))
     }.flatten.groupBy(_._1).mapValues(v => v.map(_._2))
 
     def argsSmaller(e: Expr, tpe: TypeTree): Seq[Expr] = e match {
@@ -74,7 +84,6 @@ object Helpers {
         }.flatten
       case v: Variable =>
         knownSmallers.getOrElse(v, Seq())
-
       case _ => Nil
     }
 
diff --git a/src/test/scala/leon/regression/synthesis/StablePrintingSuite.scala b/src/test/scala/leon/regression/synthesis/StablePrintingSuite.scala
index da7f51f4fff9905542af4bfa471792da5ae86a20..6ab235dd5dda3f1c9e087ca0c93b374f07dec5df 100644
--- a/src/test/scala/leon/regression/synthesis/StablePrintingSuite.scala
+++ b/src/test/scala/leon/regression/synthesis/StablePrintingSuite.scala
@@ -42,10 +42,8 @@ class StablePrintingSuite extends LeonRegressionSuite {
       OptimisticGround,
       InequalitySplit,
       rules.Assert,
-      DetupleOutput,
       DetupleInput,
       ADTSplit,
-      IntInduction,
       InnerCaseSplit
     )
 
diff --git a/synthesis-collective.txt b/synthesis-collective.txt
index 5085e1dcc7f19028cf0399be1894bc03c4b8ba4f..f2cbedc5d302beb3622dd326c0d702fdf4eef190 100644
--- a/synthesis-collective.txt
+++ b/synthesis-collective.txt
@@ -6,7 +6,7 @@ F = Timeout/failed to synth.
 
 
 ============================================================================
-Name                        | FDefs| Size |  O-O-5   |  O-O-7   |<current> |
+Name                        | FDefs| Size |  O-O-5   |  O-O-7   | 0515ff9  |
 ============================================================================
 List.insert                 |   59 |    3 | ✓ | 0.8  | ✓ | 1.0  | ✓ | 0.7  |
 List.delete                 |   61 |    0 | ✓ | 4.5  | F | 30.1 | ✓ | 3.2  |
diff --git a/testcases/synthesis/current/RunLength/RunLength.scala b/testcases/synthesis/current/RunLength/RunLength.scala
index fd886180e7b2a21f1ba65f2698e86eee2cdd2001..8813b97f71fe090ec6e73b75b396f0eb25f984a8 100644
--- a/testcases/synthesis/current/RunLength/RunLength.scala
+++ b/testcases/synthesis/current/RunLength/RunLength.scala
@@ -5,7 +5,6 @@ import leon.collection._
 
 object RunLength {
 
-
   def decode[A](l: List[(BigInt, A)]): List[A] = {
     def fill[A](i: BigInt, a: A): List[A] = {
       if (i > 0) a :: fill(i - 1, a)
@@ -18,7 +17,6 @@ object RunLength {
     }
   }
 
-
   def legal[A](l: List[(BigInt, A)]): Boolean = l match {
     case Cons((i, x), tl) =>
       i > 0 && (tl match {
@@ -28,12 +26,6 @@ object RunLength {
     case _ => true
   }
 
-  /*def unique[A](l1: List[A], l2: List[A]) => {
-    require(encode(l1) == encode(l2))
-    l1 == l2
-  }.holds*/
-
-  // Solvable with --manual=2,0,0,1,0,0,3,0,1,1,0,0,1,0,0,0,1,1,1
   def encode[A](l: List[A]): List[(BigInt, A)] = {
     // Solution
     /*l match {