From 9d37d6ad3910089e03ea0995cf55f6cbbf23d914 Mon Sep 17 00:00:00 2001
From: Ravi Madhavan <ravi.kandhadai@epfl.ch>
Date: Tue, 12 May 2015 15:30:20 +0200
Subject: [PATCH] (a) Adding support for inferring invariants in Leon. (b)
 Adding support for inferring time, depth, stack and rec bounds (c) Adding
 support for compositional reasoning in inferrence of time bounds (d) Adding
 support for estimating stack usage at runtime (e) Adding support for
 fractional literals

---
 build.sbt                                     |   2 +-
 leon-change-notes                             | 155 ++++
 library/annotation/package.scala              |   7 +-
 library/instrumentation/package.scala         |  24 +
 library/invariant/package.scala               |  26 +
 library/lang/synthesis/package.scala          |   2 +-
 library/par/package.scala                     |   5 +-
 .../java/leon/codegen/runtime/Rational.java   | 127 ++++
 src/main/scala/leon/Main.scala                |  23 +-
 .../scala/leon/codegen/CodeGeneration.scala   | 200 ++---
 .../scala/leon/codegen/CompilationUnit.scala  |  38 +-
 .../leon/codegen/CompiledExpression.scala     |   2 +-
 .../leon/evaluators/CodeGenEvaluator.scala    |   6 +-
 .../leon/evaluators/RecursiveEvaluator.scala  |  72 +-
 .../frontends/scalac/CodeExtraction.scala     |  32 +-
 .../engine/CompositionalTemplateSolver.scala  | 235 ++++++
 .../invariant/engine/ConstraintTracker.scala  |  45 ++
 .../engine/InferInvariantsPhase.scala         | 165 ++++
 .../invariant/engine/InferenceContext.scala   |  31 +
 .../invariant/engine/InferenceEngine.scala    | 179 +++++
 .../invariant/engine/InferenceReport.scala    |  84 ++
 .../invariant/engine/RefinementEngine.scala   | 200 +++++
 .../invariant/engine/SpecInstatiator.scala    | 270 +++++++
 .../invariant/engine/TemplateEnumerator.scala | 195 +++++
 .../engine/UnfoldingTemplateSolver.scala      | 259 +++++++
 .../invariant/factories/AxiomFactory.scala    | 100 +++
 .../invariant/factories/TemplateFactory.scala | 154 ++++
 .../factories/TemplateInstantiator.scala      | 134 ++++
 .../factories/TemplateSolverFactory.scala     |  44 ++
 .../leon/invariant/structure/Constraint.scala | 272 +++++++
 .../leon/invariant/structure/Formula.scala    | 281 +++++++
 .../invariant/structure/FunctionUtils.scala   | 158 ++++
 .../structure/LinearConstraintUtil.scala      | 489 ++++++++++++
 .../templateSolvers/CegisSolver.scala         | 408 ++++++++++
 .../templateSolvers/ExtendedUFSolver.scala    |  79 ++
 .../templateSolvers/FarkasLemmaSolver.scala   | 332 ++++++++
 .../templateSolvers/NLTemplateSolver.scala    | 717 ++++++++++++++++++
 .../NLTemplateSolverWithMult.scala            |  98 +++
 .../templateSolvers/TemplateSolver.scala      | 117 +++
 .../templateSolvers/UFADTEliminator.scala     | 288 +++++++
 .../scala/leon/invariant/util/CallGraph.scala | 139 ++++
 .../util/ExpressionTransformer.scala          | 660 ++++++++++++++++
 .../scala/leon/invariant/util/Graph.scala     | 170 +++++
 .../util/LetTupleSimplifications.scala        | 465 ++++++++++++
 .../scala/leon/invariant/util/Minimizer.scala | 200 +++++
 .../invariant/util/RealExprEvaluator.scala    | 100 +++
 .../scala/leon/invariant/util/Stats.scala     | 130 ++++
 src/main/scala/leon/invariant/util/Util.scala | 717 ++++++++++++++++++
 .../scala/leon/purescala/Constructors.scala   |  35 +-
 src/main/scala/leon/purescala/ExprOps.scala   | 176 +++--
 .../scala/leon/purescala/Expressions.scala    |  81 +-
 .../scala/leon/purescala/PrettyPrinter.scala  |   8 +-
 .../leon/solvers/smtlib/SMTLIBSolver.scala    |  10 +-
 .../leon/solvers/z3/AbstractZ3Solver.scala    |  13 +-
 .../leon/transformations/DepthInstPhase.scala | 104 +++
 .../transformations/InstProgSimplifier.scala  |  87 +++
 .../transformations/InstrumentationUtil.scala | 110 +++
 .../transformations/IntToRealProgram.scala    | 234 ++++++
 .../NonRecursiveTimePhase.scala               | 120 +++
 .../NonlinearityEliminationPhase.scala        | 188 +++++
 .../transformations/RecursionCountPhase.scala |  71 ++
 .../SerialInstrumentationPhase.scala          | 489 ++++++++++++
 .../transformations/StackSpacePhase.scala     | 336 ++++++++
 .../leon/transformations/TimeStepsPhase.scala |  94 +++
 .../leon/verification/InjectAsserts.scala     |   6 +-
 .../orb/combined/InsertionSort.scala          |  26 +
 .../regression/orb/depth/BinaryTrie.scala     | 121 +++
 .../regression/orb/depth/Folds.scala          |  82 ++
 .../regression/orb/depth/ListOperations.scala |  44 ++
 .../regression/orb/depth/PropLogicDepth.scala | 112 +++
 .../orb/numerical/ConcatVariationsAbs.scala   |  43 ++
 .../regression/orb/numerical/QueueAbs.scala   |  70 ++
 .../regression/orb/numerical/SimpleLoop.scala |   9 +
 .../regression/orb/numerical/see-saw.scala    |  15 +
 .../regression/orb/stack/BinaryTrie.scala     | 120 +++
 .../regression/orb/stack/ListOperations.scala |  35 +
 .../orb/stack/SpeedBenchmarks.scala           |  75 ++
 .../regression/orb/timing/BinaryTrie.scala    | 119 +++
 .../regression/orb/timing/BinomialHeap.scala  | 181 +++++
 .../orb/timing/ConcatVariations.scala         |  42 +
 .../orb/timing/ListOperations.scala           |  40 +
 .../orb/timing/PropositionalLogic.scala       | 115 +++
 .../regression/orb/timing/SimpleMap.scala     |  25 +
 .../orb/OrbInstrumentationTestSuite.scala     |  48 ++
 .../regression/orb/OrbRegressionSuite.scala   |  63 ++
 .../leon/test/helpers/ExpressionsDSL.scala    |   2 +-
 .../leon/unit/evaluators/EvaluatorSuite.scala |  41 +-
 .../orb-testcases/amortized/BigNums.scala     |  50 ++
 .../automatic/AmortizedQueue.scala            |  74 ++
 .../orb-testcases/automatic/BinaryTrie.scala  |  63 ++
 .../automatic/BinomialHeap.scala              | 325 ++++++++
 .../orb-testcases/automatic/HeapSort.scala    | 109 +++
 .../automatic/InsertionSort.scala             |  25 +
 .../orb-testcases/automatic/LeftistHeap.scala |  61 ++
 .../automatic/ListOperations.scala            |  57 ++
 .../automatic/TreeOperations.scala            |  91 +++
 .../orb-testcases/composition/AVLSort.scala   | 189 +++++
 .../composition/ConstantPropagation.scala     | 291 +++++++
 .../orb-testcases/composition/HeapSort.scala  | 147 ++++
 .../orb-testcases/composition/HeapSort2.scala | 132 ++++
 .../composition/InsertionSort.scala           |  30 +
 .../composition/LeftistHeap.scala             | 113 +++
 .../orb-testcases/composition/MergeSort.scala | 150 ++++
 .../orb-testcases/composition/QuickSort.scala |  44 ++
 .../composition/Z3-exception-output.txt       |  68 ++
 testcases/orb-testcases/depth/AVLTree.scala   | 193 +++++
 .../orb-testcases/depth/AmortizedQueue.scala  |  86 +++
 .../orb-testcases/depth/BinaryTrie.scala      | 121 +++
 .../orb-testcases/depth/BinomialHeap.scala    | 199 +++++
 .../depth/ConcatVariations.scala              |  42 +
 testcases/orb-testcases/depth/Folds.scala     |  82 ++
 .../orb-testcases/depth/ForElimParallel.scala | 119 +++
 .../orb-testcases/depth/ForElimination.scala  | 103 +++
 .../orb-testcases/depth/InsertionSort.scala   |  28 +
 .../orb-testcases/depth/LeftistHeap.scala     |  66 ++
 .../orb-testcases/depth/ListOperations.scala  |  61 ++
 testcases/orb-testcases/depth/MergeSort.scala |  56 ++
 .../orb-testcases/depth/PrimesParallel.scala  |  78 ++
 .../orb-testcases/depth/PropLogicDepth.scala  | 112 +++
 .../orb-testcases/depth/QSortDepth.scala      |  41 +
 .../orb-testcases/depth/RedBlackTree.scala    | 113 +++
 .../orb-testcases/depth/SpeedBenchmarks.scala | 109 +++
 .../orb-testcases/depth/TreeOperations.scala  |  93 +++
 .../numerical/ConcatVariationsAbs.scala       |  43 ++
 .../numerical/ListAppendAbs.scala             |  20 +
 .../numerical/LogarithmTest.scala             |  30 +
 .../orb-testcases/numerical/QueueAbs.scala    |  70 ++
 .../numerical/SimpleInterProc.scala           |  16 +
 .../orb-testcases/numerical/SimpleLoop.scala  |   9 +
 .../orb-testcases/numerical/see-saw.scala     |  15 +
 .../orb-testcases/stack/BinaryTrie.scala      | 120 +++
 .../orb-testcases/stack/BinomialHeap.scala    | 207 +++++
 .../orb-testcases/stack/ListOperations.scala  |  35 +
 testcases/orb-testcases/stack/MergeSort.scala |  63 ++
 testcases/orb-testcases/stack/QuickSort.scala |  41 +
 .../orb-testcases/stack/RedBlackTree.scala    | 110 +++
 .../orb-testcases/stack/SpeedBenchmarks.scala |  75 ++
 .../orb-testcases/stack/TreeOperations.scala  |  93 +++
 testcases/orb-testcases/timing/AVLTree.scala  | 195 +++++
 .../orb-testcases/timing/AmortizedQueue.scala |  88 +++
 .../orb-testcases/timing/BinaryTrie.scala     | 119 +++
 .../orb-testcases/timing/BinomialHeap.scala   | 181 +++++
 .../orb-testcases/timing/ConcTrees.scala      | 536 +++++++++++++
 .../timing/ConcatVariations.scala             |  42 +
 .../timing/ConstantPropagation.scala          | 290 +++++++
 testcases/orb-testcases/timing/Folds.scala    |  77 ++
 .../orb-testcases/timing/ForElimination.scala | 102 +++
 .../orb-testcases/timing/InsertionSort.scala  |  26 +
 .../orb-testcases/timing/LeftistHeap.scala    |  82 ++
 .../orb-testcases/timing/ListOperations.scala |  61 ++
 .../orb-testcases/timing/MergeSort.scala      |  76 ++
 .../timing/PropositionalLogic.scala           | 115 +++
 .../orb-testcases/timing/QuickSort.scala      |  43 ++
 .../orb-testcases/timing/RedBlackTree.scala   | 112 +++
 .../timing/SortingCombined.scala              | 116 +++
 .../timing/SpeedBenchmarks.scala              | 109 +++
 .../orb-testcases/timing/TreeOperations.scala |  93 +++
 157 files changed, 19009 insertions(+), 348 deletions(-)
 create mode 100644 leon-change-notes
 create mode 100644 library/instrumentation/package.scala
 create mode 100644 library/invariant/package.scala
 create mode 100644 src/main/java/leon/codegen/runtime/Rational.java
 create mode 100644 src/main/scala/leon/invariant/engine/CompositionalTemplateSolver.scala
 create mode 100644 src/main/scala/leon/invariant/engine/ConstraintTracker.scala
 create mode 100644 src/main/scala/leon/invariant/engine/InferInvariantsPhase.scala
 create mode 100644 src/main/scala/leon/invariant/engine/InferenceContext.scala
 create mode 100644 src/main/scala/leon/invariant/engine/InferenceEngine.scala
 create mode 100644 src/main/scala/leon/invariant/engine/InferenceReport.scala
 create mode 100644 src/main/scala/leon/invariant/engine/RefinementEngine.scala
 create mode 100644 src/main/scala/leon/invariant/engine/SpecInstatiator.scala
 create mode 100644 src/main/scala/leon/invariant/engine/TemplateEnumerator.scala
 create mode 100644 src/main/scala/leon/invariant/engine/UnfoldingTemplateSolver.scala
 create mode 100644 src/main/scala/leon/invariant/factories/AxiomFactory.scala
 create mode 100644 src/main/scala/leon/invariant/factories/TemplateFactory.scala
 create mode 100644 src/main/scala/leon/invariant/factories/TemplateInstantiator.scala
 create mode 100644 src/main/scala/leon/invariant/factories/TemplateSolverFactory.scala
 create mode 100644 src/main/scala/leon/invariant/structure/Constraint.scala
 create mode 100644 src/main/scala/leon/invariant/structure/Formula.scala
 create mode 100644 src/main/scala/leon/invariant/structure/FunctionUtils.scala
 create mode 100644 src/main/scala/leon/invariant/structure/LinearConstraintUtil.scala
 create mode 100644 src/main/scala/leon/invariant/templateSolvers/CegisSolver.scala
 create mode 100644 src/main/scala/leon/invariant/templateSolvers/ExtendedUFSolver.scala
 create mode 100644 src/main/scala/leon/invariant/templateSolvers/FarkasLemmaSolver.scala
 create mode 100644 src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala
 create mode 100644 src/main/scala/leon/invariant/templateSolvers/NLTemplateSolverWithMult.scala
 create mode 100644 src/main/scala/leon/invariant/templateSolvers/TemplateSolver.scala
 create mode 100644 src/main/scala/leon/invariant/templateSolvers/UFADTEliminator.scala
 create mode 100644 src/main/scala/leon/invariant/util/CallGraph.scala
 create mode 100644 src/main/scala/leon/invariant/util/ExpressionTransformer.scala
 create mode 100644 src/main/scala/leon/invariant/util/Graph.scala
 create mode 100644 src/main/scala/leon/invariant/util/LetTupleSimplifications.scala
 create mode 100644 src/main/scala/leon/invariant/util/Minimizer.scala
 create mode 100644 src/main/scala/leon/invariant/util/RealExprEvaluator.scala
 create mode 100644 src/main/scala/leon/invariant/util/Stats.scala
 create mode 100644 src/main/scala/leon/invariant/util/Util.scala
 create mode 100644 src/main/scala/leon/transformations/DepthInstPhase.scala
 create mode 100644 src/main/scala/leon/transformations/InstProgSimplifier.scala
 create mode 100644 src/main/scala/leon/transformations/InstrumentationUtil.scala
 create mode 100644 src/main/scala/leon/transformations/IntToRealProgram.scala
 create mode 100644 src/main/scala/leon/transformations/NonRecursiveTimePhase.scala
 create mode 100644 src/main/scala/leon/transformations/NonlinearityEliminationPhase.scala
 create mode 100644 src/main/scala/leon/transformations/RecursionCountPhase.scala
 create mode 100644 src/main/scala/leon/transformations/SerialInstrumentationPhase.scala
 create mode 100644 src/main/scala/leon/transformations/StackSpacePhase.scala
 create mode 100644 src/main/scala/leon/transformations/TimeStepsPhase.scala
 create mode 100644 src/test/resources/regression/orb/combined/InsertionSort.scala
 create mode 100755 src/test/resources/regression/orb/depth/BinaryTrie.scala
 create mode 100755 src/test/resources/regression/orb/depth/Folds.scala
 create mode 100644 src/test/resources/regression/orb/depth/ListOperations.scala
 create mode 100644 src/test/resources/regression/orb/depth/PropLogicDepth.scala
 create mode 100644 src/test/resources/regression/orb/numerical/ConcatVariationsAbs.scala
 create mode 100644 src/test/resources/regression/orb/numerical/QueueAbs.scala
 create mode 100755 src/test/resources/regression/orb/numerical/SimpleLoop.scala
 create mode 100644 src/test/resources/regression/orb/numerical/see-saw.scala
 create mode 100644 src/test/resources/regression/orb/stack/BinaryTrie.scala
 create mode 100644 src/test/resources/regression/orb/stack/ListOperations.scala
 create mode 100644 src/test/resources/regression/orb/stack/SpeedBenchmarks.scala
 create mode 100644 src/test/resources/regression/orb/timing/BinaryTrie.scala
 create mode 100644 src/test/resources/regression/orb/timing/BinomialHeap.scala
 create mode 100644 src/test/resources/regression/orb/timing/ConcatVariations.scala
 create mode 100644 src/test/resources/regression/orb/timing/ListOperations.scala
 create mode 100644 src/test/resources/regression/orb/timing/PropositionalLogic.scala
 create mode 100644 src/test/resources/regression/orb/timing/SimpleMap.scala
 create mode 100644 src/test/scala/leon/regression/orb/OrbInstrumentationTestSuite.scala
 create mode 100644 src/test/scala/leon/regression/orb/OrbRegressionSuite.scala
 create mode 100644 testcases/orb-testcases/amortized/BigNums.scala
 create mode 100644 testcases/orb-testcases/automatic/AmortizedQueue.scala
 create mode 100755 testcases/orb-testcases/automatic/BinaryTrie.scala
 create mode 100644 testcases/orb-testcases/automatic/BinomialHeap.scala
 create mode 100644 testcases/orb-testcases/automatic/HeapSort.scala
 create mode 100644 testcases/orb-testcases/automatic/InsertionSort.scala
 create mode 100644 testcases/orb-testcases/automatic/LeftistHeap.scala
 create mode 100644 testcases/orb-testcases/automatic/ListOperations.scala
 create mode 100755 testcases/orb-testcases/automatic/TreeOperations.scala
 create mode 100644 testcases/orb-testcases/composition/AVLSort.scala
 create mode 100644 testcases/orb-testcases/composition/ConstantPropagation.scala
 create mode 100644 testcases/orb-testcases/composition/HeapSort.scala
 create mode 100644 testcases/orb-testcases/composition/HeapSort2.scala
 create mode 100644 testcases/orb-testcases/composition/InsertionSort.scala
 create mode 100644 testcases/orb-testcases/composition/LeftistHeap.scala
 create mode 100644 testcases/orb-testcases/composition/MergeSort.scala
 create mode 100644 testcases/orb-testcases/composition/QuickSort.scala
 create mode 100644 testcases/orb-testcases/composition/Z3-exception-output.txt
 create mode 100644 testcases/orb-testcases/depth/AVLTree.scala
 create mode 100644 testcases/orb-testcases/depth/AmortizedQueue.scala
 create mode 100755 testcases/orb-testcases/depth/BinaryTrie.scala
 create mode 100644 testcases/orb-testcases/depth/BinomialHeap.scala
 create mode 100644 testcases/orb-testcases/depth/ConcatVariations.scala
 create mode 100755 testcases/orb-testcases/depth/Folds.scala
 create mode 100644 testcases/orb-testcases/depth/ForElimParallel.scala
 create mode 100644 testcases/orb-testcases/depth/ForElimination.scala
 create mode 100644 testcases/orb-testcases/depth/InsertionSort.scala
 create mode 100644 testcases/orb-testcases/depth/LeftistHeap.scala
 create mode 100644 testcases/orb-testcases/depth/ListOperations.scala
 create mode 100644 testcases/orb-testcases/depth/MergeSort.scala
 create mode 100644 testcases/orb-testcases/depth/PrimesParallel.scala
 create mode 100644 testcases/orb-testcases/depth/PropLogicDepth.scala
 create mode 100644 testcases/orb-testcases/depth/QSortDepth.scala
 create mode 100755 testcases/orb-testcases/depth/RedBlackTree.scala
 create mode 100644 testcases/orb-testcases/depth/SpeedBenchmarks.scala
 create mode 100755 testcases/orb-testcases/depth/TreeOperations.scala
 create mode 100644 testcases/orb-testcases/numerical/ConcatVariationsAbs.scala
 create mode 100755 testcases/orb-testcases/numerical/ListAppendAbs.scala
 create mode 100755 testcases/orb-testcases/numerical/LogarithmTest.scala
 create mode 100644 testcases/orb-testcases/numerical/QueueAbs.scala
 create mode 100755 testcases/orb-testcases/numerical/SimpleInterProc.scala
 create mode 100755 testcases/orb-testcases/numerical/SimpleLoop.scala
 create mode 100644 testcases/orb-testcases/numerical/see-saw.scala
 create mode 100644 testcases/orb-testcases/stack/BinaryTrie.scala
 create mode 100644 testcases/orb-testcases/stack/BinomialHeap.scala
 create mode 100644 testcases/orb-testcases/stack/ListOperations.scala
 create mode 100644 testcases/orb-testcases/stack/MergeSort.scala
 create mode 100644 testcases/orb-testcases/stack/QuickSort.scala
 create mode 100644 testcases/orb-testcases/stack/RedBlackTree.scala
 create mode 100644 testcases/orb-testcases/stack/SpeedBenchmarks.scala
 create mode 100644 testcases/orb-testcases/stack/TreeOperations.scala
 create mode 100644 testcases/orb-testcases/timing/AVLTree.scala
 create mode 100644 testcases/orb-testcases/timing/AmortizedQueue.scala
 create mode 100644 testcases/orb-testcases/timing/BinaryTrie.scala
 create mode 100644 testcases/orb-testcases/timing/BinomialHeap.scala
 create mode 100644 testcases/orb-testcases/timing/ConcTrees.scala
 create mode 100644 testcases/orb-testcases/timing/ConcatVariations.scala
 create mode 100644 testcases/orb-testcases/timing/ConstantPropagation.scala
 create mode 100644 testcases/orb-testcases/timing/Folds.scala
 create mode 100644 testcases/orb-testcases/timing/ForElimination.scala
 create mode 100644 testcases/orb-testcases/timing/InsertionSort.scala
 create mode 100644 testcases/orb-testcases/timing/LeftistHeap.scala
 create mode 100644 testcases/orb-testcases/timing/ListOperations.scala
 create mode 100644 testcases/orb-testcases/timing/MergeSort.scala
 create mode 100644 testcases/orb-testcases/timing/PropositionalLogic.scala
 create mode 100644 testcases/orb-testcases/timing/QuickSort.scala
 create mode 100644 testcases/orb-testcases/timing/RedBlackTree.scala
 create mode 100644 testcases/orb-testcases/timing/SortingCombined.scala
 create mode 100644 testcases/orb-testcases/timing/SpeedBenchmarks.scala
 create mode 100644 testcases/orb-testcases/timing/TreeOperations.scala

diff --git a/build.sbt b/build.sbt
index c6449492b..49df8715f 100644
--- a/build.sbt
+++ b/build.sbt
@@ -1,4 +1,4 @@
-name := "Leon"
+name := "Orb2015"
 
 version := "3.0"
 
diff --git a/leon-change-notes b/leon-change-notes
new file mode 100644
index 000000000..4e0a3d4d7
--- /dev/null
+++ b/leon-change-notes
@@ -0,0 +1,155 @@
+In file ExprOps.scala, in function simplestValue:
+
+SimplestValue(tpe: TypeTree) : Expr = tpe match {
+    case Int32Type                  => IntLiteral(0)
+    case IntegerType                => InfiniteIntegerLiteral(0)
+    case CharType                   => CharLiteral('a')
+    case BooleanType                => BooleanLiteral(false)
+    case UnitType                   => UnitLiteral()
+    case SetType(baseType)          => EmptySet(tpe)
+    case MapType(fromType, toType)  => EmptyMap(fromType, toType)
+    case TupleType(tpes)            => Tuple(tpes.map(simplestValue))
+    case ArrayType(tpe)             => EmptyArray(tpe)   
+    case RationalType               => RationalLiteral(0, 1)
+
+In file Expressions.scala after UntilLiteral definition
+
+ case class RationalLiteral(numerator: BigInt, denominator: BigInt) extends Literal[(BigInt,BigInt)] {
+    val value = (numerator,denominator)
+    val getType = RationalType
+    
+    override def toString =  {
+      if(denominator == 1) numerator.toString
+      else numerator + "/" + denominator
+    }
+  }
+In file Expressions.scala, first five arithmetic types
+
+/* Arithmetic */
+  case class Plus(lhs: Expr, rhs: Expr) extends Expr {
+    val getType = superNumericType(lhs.getType, rhs.getType)
+  }
+  
+  case class Minus(lhs: Expr, rhs: Expr) extends Expr {
+    val getType = superNumericType(lhs.getType, rhs.getType)
+  }
+  
+  case class UMinus(expr: Expr) extends Expr {
+    require(isNumericType(expr.getType))
+    val getType = expr.getType
+  }
+  
+  case class Times(lhs: Expr, rhs: Expr) extends Expr {
+    val getType = superNumericType(lhs.getType, rhs.getType)
+  }
+  
+  case class Division(lhs: Expr, rhs: Expr) extends Expr {    
+    val getType = superNumericType(lhs.getType, rhs.getType)
+  }  
+
+
+In file PrettyPrinter.scala, in function pp
+
+case Let(b,d,e) =>
+        optB { d match {
+          case _:LetDef | _ : Let | LetPattern(_,_,_) =>
+            p"""|val $b = {
+                |  $d
+                |}
+                |$e"""
+          case _ =>
+            p"""|val $b = $d;
+                |$e"""
+        }}
+
+'b' is replaced by 'd'
+
+In file PrettyPrinter.scala,  In function requireBraces (before the case that returns true)
+
+    case (_, Some(_: IfExpr)) => false
+
+In file Types.scala, 
+
+import PrinterHelpers._
+
+After the definition of "IntegerType"
+
+  case object RationalType extends TypeTree with PrettyPrintable {
+    def printWith(implicit pctx: PrinterContext) {
+      p"Real"
+    }
+  }
+
+  def isNumericType(t: TypeTree) = t match {
+    case IntegerType | RationalType => true
+    case _ => false
+  }
+
+  def superNumericType(t1: TypeTree, t2: TypeTree) = {
+    require(isNumericType(t1) && isNumericType(t2))
+    if (t1 == RationalType || t2 == RationalType) RationalType
+    else IntegerType
+  }
+
+In AbstractZ3Solver, in function preparesorts 
+
+Add the following after sorts += IntegerType -> ...
+sorts += RationalType -> z3.mkRealSort
+
+In function typeToSort 
+add the first "case Int32Type | BooleanType | UnitType | IntegerType | CharType | RationalType"
+
+In function "toZ3Formula"
+
+After infiniteIntegerLiteral add 
+      case RationalLiteral(num, denom) => z3.mkNumeral(s"${num.toString} / ${denom.toString}", typeToSort(RationalType))
+In Lessthan, lessequals ...
+case LessThan(l, r) => l.getType match {
+        case RationalType => z3.mkLT(rec(l), rec(r))
+        case IntegerType => z3.mkLT(rec(l), rec(r))
+        case Int32Type => z3.mkBVSlt(rec(l), rec(r))
+      }
+      case LessEquals(l, r) => l.getType match {
+        case RationalType => z3.mkLE(rec(l), rec(r))
+        case IntegerType => z3.mkLE(rec(l), rec(r))
+        case Int32Type => z3.mkBVSle(rec(l), rec(r))
+      }
+      case GreaterThan(l, r) => l.getType match {
+        case RationalType => z3.mkGT(rec(l), rec(r))
+        case IntegerType => z3.mkGT(rec(l), rec(r))
+        case Int32Type => z3.mkBVSgt(rec(l), rec(r))
+      }
+      case GreaterEquals(l, r) => l.getType match {
+        case RationalType => z3.mkGE(rec(l), rec(r))
+        case IntegerType => z3.mkGE(rec(l), rec(r))
+        case Int32Type => z3.mkBVSge(rec(l), rec(r))
+      }
+
+In function "fromZ3Formula"
+in kind match , add after Z3NumeralIntAST
+
+case Z3NumeralRealAST(num: BigInt, dem: BigInt) => {
+          val rl = RationalLiteral(num, dem)
+          rl
+        }
+
+In file Main.scala, add in list 'allPhases'
+transformations.InstrumentationDriver,
+      invariant.engine.InferInvariantsPhase)
+ad the end
+
+add after optEval
+val optInstrument = LeonFlagOptionDef("instrument", "Instrument the code for inferring time/depth/stack bounds", false)
+    val optInferInv = LeonFlagOptionDef("inferInv", "Infer invariants from (instrumented) the code", false)
+
+after import MainComponent._
+import invariant.engine.InferInvariantsPhase
+    import transformations.InstrumentationDriver
+
+Add  after evalF
+val inferInvF = ctx.findOptionOrDefault(optInferInv)
+    val instrumentF = ctx.findOptionOrDefault(optInstrument)
+
+In pipe process add after else if(evalF) ...
+        else if (inferInvF) InstrumentationDriver andThen InferInvariantsPhase
+        else if (instrumentF) InstrumentationDriver
diff --git a/library/annotation/package.scala b/library/annotation/package.scala
index 63bf384f2..00ae0743c 100644
--- a/library/annotation/package.scala
+++ b/library/annotation/package.scala
@@ -15,5 +15,8 @@ package object annotation {
   class extern     extends StaticAnnotation
   @ignore
   class inline     extends StaticAnnotation
-}
-
+  @ignore
+  class monotonic  extends StaticAnnotation
+  @ignore
+  class compose    extends StaticAnnotation
+}
\ No newline at end of file
diff --git a/library/instrumentation/package.scala b/library/instrumentation/package.scala
new file mode 100644
index 000000000..a724eadd7
--- /dev/null
+++ b/library/instrumentation/package.scala
@@ -0,0 +1,24 @@
+/* Copyright 2009-2013 EPFL, Lausanne */
+
+package leon
+
+import leon.annotation._
+import leon.lang._
+import scala.language.implicitConversions
+
+package object instrumentation {
+  @library
+  def time: BigInt = 0
+
+  @library
+  def stack: BigInt = 0
+
+  @library
+  def rec: BigInt = 0
+
+  @library
+  def depth: BigInt = 0
+
+  @library
+  def tpr: BigInt = 0
+}
diff --git a/library/invariant/package.scala b/library/invariant/package.scala
new file mode 100644
index 000000000..4382462bd
--- /dev/null
+++ b/library/invariant/package.scala
@@ -0,0 +1,26 @@
+/* Copyright 2009-2013 EPFL, Lausanne */
+
+package leon
+
+import leon.annotation._
+import leon.lang._
+import scala.language.implicitConversions
+
+package object invariant {
+  @library
+  def tmpl(templateFunc: BigInt => Boolean): Boolean = true
+  @library
+  def tmpl(templateFunc: (BigInt, BigInt) => Boolean): Boolean = true
+  @library
+  def tmpl(templateFunc: (BigInt, BigInt, BigInt) => Boolean): Boolean = true
+  @library
+  def tmpl(templateFunc: (BigInt, BigInt, BigInt, BigInt) => Boolean): Boolean = true
+  @library
+  def tmpl(templateFunc: (BigInt, BigInt, BigInt, BigInt, BigInt) => Boolean): Boolean = true
+
+  @library
+  def ? : BigInt = 0
+
+  @library
+  def ?(id: BigInt) = id
+}
diff --git a/library/lang/synthesis/package.scala b/library/lang/synthesis/package.scala
index 7084d9c14..cb5699279 100644
--- a/library/lang/synthesis/package.scala
+++ b/library/lang/synthesis/package.scala
@@ -20,7 +20,7 @@ package object synthesis {
   @ignore
   def choose[A, B, C, D](predicate: (A, B, C, D) => Boolean): (A, B, C, D) = noImpl
   @ignore
-  def choose[A, B, C, D, E](predicate: (A, B, C, D, E) => Boolean): (A, B, C, D, E) = noImpl
+  def choose[A, B, C, D, E](predicate: (A, B, C, D, E) => Boolean): (A, B, C, D, E) = noImpl      
 
   @ignore
   def ???[T]: T = noImpl
diff --git a/library/par/package.scala b/library/par/package.scala
index 6e8d1d571..5842210fc 100644
--- a/library/par/package.scala
+++ b/library/par/package.scala
@@ -8,16 +8,17 @@ import leon.lang.synthesis.choose
 
 package object par {
 
-  // @library
+  @library
   @inline
   def parallel[A,B](x: => A, y: => B) : (A,B) = {
     (x,y)
   }
 
+  @library
   case class Task[A](c: A) {
     def join: A = c
   }
 
-  // @library
+  @library
   def task[A](c: A) = Task(c)
 }
diff --git a/src/main/java/leon/codegen/runtime/Rational.java b/src/main/java/leon/codegen/runtime/Rational.java
new file mode 100644
index 000000000..fc409434b
--- /dev/null
+++ b/src/main/java/leon/codegen/runtime/Rational.java
@@ -0,0 +1,127 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.codegen.runtime;
+
+import java.math.BigInteger;
+
+public final class Rational {
+
+	private final BigInteger _num;
+	private final BigInteger _denom;
+
+	/**
+	 * class invariant: the fractions are always normalized
+	 *
+	 * @param num
+	 *            numerator
+	 * @param denom
+	 *            denominator
+	 */
+	public Rational(BigInteger num, BigInteger denom) {
+		BigInteger modNum = num.abs();
+		BigInteger modDenom = denom.abs();
+		BigInteger divisor = modNum.gcd(modDenom);
+		BigInteger simpNum = num.divide(divisor);
+		BigInteger simpDenom = denom.divide(divisor);
+		if (isLTZ(simpDenom)) {
+			_num = simpNum.negate();
+			_denom = simpDenom.negate();
+		} else {
+			_num = simpNum;
+			_denom = simpDenom;
+		}
+	}
+
+	public Rational(String num, String denom) {
+		this(new BigInteger(num), new BigInteger(denom));
+	}
+
+	public BigInteger numerator() {
+		return _num;
+	}
+
+	public BigInteger denominator() {
+		return _denom;
+	}
+
+	public boolean isZero(BigInteger bi) {
+		return bi.signum() == 0;
+	}
+
+	public boolean isLEZ(BigInteger bi) {
+		return bi.signum() != 1;
+	}
+
+	public boolean isLTZ(BigInteger bi) {
+		return (bi.signum() == -1);
+	}
+
+	public boolean isGEZ(BigInteger bi) {
+		return (bi.signum() != -1);
+	}
+
+	public boolean isGTZ(BigInteger bi) {
+		return (bi.signum() == 1);
+	}
+
+	public Rational add(Rational that) {
+		return new Rational(_num.multiply(that._denom).add(
+				that._num.multiply(_denom)), _denom.multiply(that._denom));
+	}
+
+	public Rational sub(Rational that) {
+		return new Rational(_num.multiply(that._denom).subtract(
+				that._num.multiply(_denom)), _denom.multiply(that._denom));
+	}
+
+	public Rational mult(Rational that) {
+		return new Rational(_num.multiply(that._num),
+				_denom.multiply(that._denom));
+	}
+
+	public Rational div(Rational that) {
+		return new Rational(_num.multiply(that._denom),
+				_denom.multiply(that._num));
+	}
+
+	public Rational neg() {
+		return new Rational(_num.negate(), _denom);
+	}
+
+	public boolean lessThan(Rational that) {
+		return isLTZ(this.sub(that)._num);
+	}
+
+	public boolean lessEquals(Rational that) {
+		return isLEZ(this.sub(that)._num);
+	}
+
+	public boolean greaterThan(Rational that) {
+		return isGTZ(this.sub(that)._num);
+	}
+
+	public boolean greaterEquals(Rational that) {
+		return isGEZ(this.sub(that)._num);
+	}
+
+	@Override
+	public boolean equals(Object that) {
+		if (that == this)
+			return true;
+		if (!(that instanceof Rational))
+			return false;
+
+		Rational other = (Rational) that;
+		return isZero(this.sub(other)._num);
+	}
+
+	@Override
+	public String toString() {
+		return _num.toString() + "/" + _denom.toString();
+	}
+
+	@Override
+	public int hashCode() {
+		return _num.hashCode() ^ _denom.hashCode();
+	}
+}
diff --git a/src/main/scala/leon/Main.scala b/src/main/scala/leon/Main.scala
index 6e2af3812..34fc1c98c 100644
--- a/src/main/scala/leon/Main.scala
+++ b/src/main/scala/leon/Main.scala
@@ -24,8 +24,9 @@ object Main {
       repair.RepairPhase,
       evaluators.EvaluationPhase,
       solvers.isabelle.AdaptationPhase,
-      solvers.isabelle.IsabellePhase
-    )
+      solvers.isabelle.IsabellePhase,
+      transformations.InstrumentationPhase,
+      invariant.engine.InferInvariantsPhase)
   }
 
   // Add whatever you need here.
@@ -49,10 +50,11 @@ object Main {
     val optNoop        = LeonFlagOptionDef("noop",        "No operation performed, just output program",           false)
     val optVerify      = LeonFlagOptionDef("verify",      "Verify function contracts",                             false)
     val optHelp        = LeonFlagOptionDef("help",        "Show help message",                                     false)
+    val optInstrument = LeonFlagOptionDef("instrument", "Instrument the code for inferring time/depth/stack bounds", false)
+    val optInferInv = LeonFlagOptionDef("inferInv", "Infer invariants from (instrumented) the code", false)
 
     override val definedOptions: Set[LeonOptionDef[Any]] =
-      Set(optTermination, optRepair, optSynthesis, optIsabelle, optNoop, optHelp, optEval, optVerify)
-
+      Set(optTermination, optRepair, optSynthesis, optIsabelle, optNoop, optHelp, optEval, optVerify, optInstrument, optInferInv)
   }
 
   lazy val allOptions: Set[LeonOptionDef[Any]] = allComponents.flatMap(_.definedOptions)
@@ -70,8 +72,8 @@ object Main {
       reporter.info(opt.helpString)
     }
     reporter.info("")
-      
-    reporter.title("Additional options, by component:")
+
+    reporter.info("Additional options, by component:")
 
     for (c <- (allComponents - MainComponent - SharedOptions).toSeq.sortBy(_.name) if c.definedOptions.nonEmpty) {
       reporter.info("")
@@ -149,6 +151,8 @@ object Main {
     import evaluators.EvaluationPhase
     import solvers.isabelle.IsabellePhase
     import MainComponent._
+    import invariant.engine.InferInvariantsPhase
+    import transformations.InstrumentationPhase
 
     val helpF        = ctx.findOptionOrDefault(optHelp)
     val noopF        = ctx.findOptionOrDefault(optNoop)
@@ -159,6 +163,8 @@ object Main {
     val terminationF = ctx.findOptionOrDefault(optTermination)
     val verifyF      = ctx.findOptionOrDefault(optVerify)
     val evalF        = ctx.findOption(optEval).isDefined
+    val inferInvF = ctx.findOptionOrDefault(optInferInv)
+    val instrumentF = ctx.findOptionOrDefault(optInstrument)
     val analysisF    = verifyF && terminationF
 
     if (helpF) {
@@ -179,7 +185,10 @@ object Main {
         else if (terminationF) TerminationPhase
         else if (isabelleF) IsabellePhase
         else if (evalF) EvaluationPhase
+        else if (inferInvF) InstrumentationPhase andThen InferInvariantsPhase
+        else if (instrumentF) InstrumentationPhase andThen FileOutputPhase
         else analysis
+
       }
 
       pipeBegin andThen
@@ -242,7 +251,7 @@ object Main {
         case (vReport: verification.VerificationReport, tReport: termination.TerminationReport) =>
           ctx.reporter.info(vReport.summaryString)
           ctx.reporter.info(tReport.summaryString)
-        
+
         case report: verification.VerificationReport =>
           ctx.reporter.info(report.summaryString)
 
diff --git a/src/main/scala/leon/codegen/CodeGeneration.scala b/src/main/scala/leon/codegen/CodeGeneration.scala
index cd2881c82..3ea170a05 100644
--- a/src/main/scala/leon/codegen/CodeGeneration.scala
+++ b/src/main/scala/leon/codegen/CodeGeneration.scala
@@ -24,7 +24,7 @@ trait CodeGeneration {
 
   /** A class providing information about the status of parameters in the function that is being currently compiled.
    *  vars is a mapping from local variables/ parameters to the offset of the respective JVM local register
-   *  isStatic signifies if the current method is static (a function, in Leon terms) 
+   *  isStatic signifies if the current method is static (a function, in Leon terms)
    */
   class Locals private[codegen] (
     vars   : Map[Identifier, Int],
@@ -67,6 +67,7 @@ trait CodeGeneration {
   private[codegen] val MapClass                  = "leon/codegen/runtime/Map"
   private[codegen] val BigIntClass               = "leon/codegen/runtime/BigInt"
   private[codegen] val RealClass                 = "leon/codegen/runtime/Real"
+  private[codegen] val RationalClass             = "leon/codegen/runtime/Rational"
   private[codegen] val CaseClassClass            = "leon/codegen/runtime/CaseClass"
   private[codegen] val LambdaClass               = "leon/codegen/runtime/Lambda"
   private[codegen] val ErrorClass                = "leon/codegen/runtime/LeonCodeGenRuntimeException"
@@ -120,7 +121,7 @@ trait CodeGeneration {
       "L" + BigIntClass + ";"
 
     case RealType =>
-      "L" + RealClass + ";"
+      "L" + RationalClass + ";"
 
     case _ : FunctionType =>
       "L" + LambdaClass + ";"
@@ -141,12 +142,12 @@ trait CodeGeneration {
     case CharType               => s"L$BoxedCharClass;"
     case other                  => typeToJVM(other)
   }
-  
+
   /**
    * Compiles a function/method definition.
    * @param funDef The function definition to be compiled
    * @param owner The module/class that contains `funDef`
-   */  
+   */
   def compileFunDef(funDef: FunDef, owner: Definition) {
     val isStatic = owner.isInstanceOf[ModuleDef]
 
@@ -194,7 +195,7 @@ trait CodeGeneration {
     }
 
     val bodyWithPost = funDef.postcondition match {
-      case Some(post) if params.checkContracts => 
+      case Some(post) if params.checkContracts =>
         Ensuring(bodyWithPre, post).toAssert
       case _ => bodyWithPre
     }
@@ -569,10 +570,11 @@ trait CodeGeneration {
         ch << Ldc(v.toString)
         ch << InvokeSpecial(BigIntClass, constructorName, "(Ljava/lang/String;)V")
 
-      case RealLiteral(v) =>
-        ch << New(RealClass) << DUP
-        ch << Ldc(v.toString)
-        ch << InvokeSpecial(RealClass, constructorName, "(Ljava/lang/String;)V")
+      case FractionalLiteral(n, d) =>
+        ch << New(RationalClass) << DUP
+        ch << Ldc(n.toString)
+        ch << Ldc(d.toString)
+        ch << InvokeSpecial(RationalClass, constructorName, "(Ljava/lang/String;Ljava/lang/String;)V")
 
       // Case classes
       case CaseClass(cct, as) =>
@@ -718,7 +720,7 @@ trait CodeGeneration {
         val (className, fieldName, _) = leonFunDefToJVMInfo(tfd.fd).getOrElse {
           throw CompilationException("Unknown method : " + tfd.id)
         }
-        
+
         if (requireMonitor) {
           load(monitorID, ch)
           ch << InvokeVirtual(MonitorClass, "onInvoke", "()V")
@@ -748,7 +750,7 @@ trait CodeGeneration {
         //  ch << ALoad(locals.monitorIndex)
         //}
 
-        // No dynamic dispatching/overriding in Leon, 
+        // No dynamic dispatching/overriding in Leon,
         // so no need to take care of own vs. "super" methods
         ch << InvokeVirtual(SetClass, "getElements", s"()L$JavaIteratorClass;")
 
@@ -818,17 +820,17 @@ trait CodeGeneration {
         val (className, fieldName, _) = leonFunDefToJVMInfo(tfd.fd).getOrElse {
           throw CompilationException("Unknown method : " + tfd.id)
         }
-        
+
         if (requireMonitor) {
           load(monitorID, ch)
           ch << InvokeVirtual(MonitorClass, "onInvoke", "()V")
         }
-        // Load receiver 
-        mkExpr(rec,ch) 
-        
+        // Load receiver
+        mkExpr(rec,ch)
+
         // Get field
         ch << GetField(className, fieldName, typeToJVM(tfd.fd.returnType))
-        
+
         // unbox field
         (tfd.fd.returnType, tfd.returnType) match {
           case (TypeParameter(_), tpe)  =>
@@ -843,13 +845,13 @@ trait CodeGeneration {
           throw CompilationException("Unknown method : " + tfd.id)
         }
 
-        // Receiver of the method call 
+        // Receiver of the method call
         mkExpr(rec,ch)
 
         if (requireMonitor) {
           load(monitorID, ch)
         }
-  
+
         for((a, vd) <- as zip tfd.fd.params) {
           vd.getType match {
             case TypeParameter(_) =>
@@ -860,7 +862,7 @@ trait CodeGeneration {
         }
 
         // No interfaces in Leon, so no need to use InvokeInterface
-        ch << InvokeVirtual(className, methodName, sig) 
+        ch << InvokeVirtual(className, methodName, sig)
 
         (tfd.fd.returnType, tfd.returnType) match {
           case (TypeParameter(_), tpe)  =>
@@ -924,26 +926,26 @@ trait CodeGeneration {
       case RealPlus(l, r) =>
         mkExpr(l, ch)
         mkExpr(r, ch)
-        ch << InvokeVirtual(RealClass, "add", s"(L$RealClass;)L$RealClass;")
+        ch << InvokeVirtual(RationalClass, "add", s"(L$RationalClass;)L$RationalClass;")
 
       case RealMinus(l, r) =>
         mkExpr(l, ch)
         mkExpr(r, ch)
-        ch << InvokeVirtual(RealClass, "sub", s"(L$RealClass;)L$RealClass;")
+        ch << InvokeVirtual(RationalClass, "sub", s"(L$RationalClass;)L$RationalClass;")
 
       case RealTimes(l, r) =>
         mkExpr(l, ch)
         mkExpr(r, ch)
-        ch << InvokeVirtual(RealClass, "mult", s"(L$RealClass;)L$RealClass;")
+        ch << InvokeVirtual(RationalClass, "mult", s"(L$RationalClass;)L$RationalClass;")
 
       case RealDivision(l, r) =>
         mkExpr(l, ch)
         mkExpr(r, ch)
-        ch << InvokeVirtual(RealClass, "div", s"(L$RealClass;)L$RealClass;")
+        ch << InvokeVirtual(RationalClass, "div", s"(L$RationalClass;)L$RationalClass;")
 
       case RealUMinus(e) =>
         mkExpr(e, ch)
-        ch << InvokeVirtual(RealClass, "neg", s"()L$RealClass;")
+        ch << InvokeVirtual(RationalClass, "neg", s"()L$RationalClass;")
 
 
       //BV arithmetic
@@ -1036,7 +1038,7 @@ trait CodeGeneration {
           case ArrayType(BooleanType) => ch << NewArray.primitive("T_BOOLEAN"); BASTORE
           case ArrayType(other) => ch << NewArray(typeToJVM(other)); AASTORE
           case other => throw CompilationException(s"Cannot compile finite array expression whose type is $other.")
-        } 
+        }
         //srcArrary and targetArray is on the stack
         ch << DUP_X1 //insert targetArray under srcArray
         ch << Ldc(0) << SWAP //srcArray, 0, targetArray
@@ -1065,10 +1067,10 @@ trait CodeGeneration {
         for (i <- 0 until l) {
           val v = elems.get(i).orElse(default).getOrElse {
             throw CompilationException(s"No valuation for key '$i' in array")
-          } 
+          }
 
           ch << DUP << Ldc(i)
-          mkExpr(v, ch) 
+          mkExpr(v, ch)
           ch << storeInstr
         }
 
@@ -1104,22 +1106,22 @@ trait CodeGeneration {
         val id = runtime.GenericValues.register(gv)
         ch << Ldc(id)
         ch << InvokeStatic(GenericValuesClass, "get", s"(I)L$ObjectClass;")
-      
+
       case nt @ NoTree( tp@ValueType() ) =>
         mkExpr(simplestValue(tp), ch)
-        
+
       case NoTree(_) =>
         ch << ACONST_NULL
-      
+
       case This(ct) =>
         ch << ALoad(0)
-        
-      case p : Passes => 
+
+      case p : Passes =>
         mkExpr(matchToIfThenElse(p.asConstraint), ch)
 
-      case m : MatchExpr => 
+      case m : MatchExpr =>
         mkExpr(matchToIfThenElse(m), ch)
-      
+
       case b if b.getType == BooleanType && canDelegateToMkBranch =>
         val fl = ch.getFreshLabel("boolfalse")
         val al = ch.getFreshLabel("boolafter")
@@ -1127,7 +1129,7 @@ trait CodeGeneration {
         mkBranch(b, al, fl, ch, canDelegateToMkExpr = false)
         ch << Label(fl) << POP << Ldc(0) << Label(al)
 
-      case _ => throw CompilationException("Unsupported expr " + e + " : " + e.getClass) 
+      case _ => throw CompilationException("Unsupported expr " + e + " : " + e.getClass)
     }
   }
 
@@ -1200,7 +1202,7 @@ trait CodeGeneration {
         ch << CheckCast(BigIntClass)
 
       case RealType =>
-        ch << CheckCast(RealClass)
+        ch << CheckCast(RationalClass)
 
       case tt : TupleType =>
         ch << CheckCast(TupleClass)
@@ -1214,7 +1216,7 @@ trait CodeGeneration {
       case ft : FunctionType =>
         ch << CheckCast(LambdaClass)
 
-      case tp : TypeParameter => 
+      case tp : TypeParameter =>
 
       case tp : ArrayType =>
         ch << CheckCast(BoxedArrayClass) << InvokeVirtual(BoxedArrayClass, "arrayValue", s"()${typeToJVM(tp)}")
@@ -1243,7 +1245,7 @@ trait CodeGeneration {
         val fl = ch.getFreshLabel("ornext")
         mkBranch(es.head, thenn, fl, ch)
         ch << Label(fl)
-        mkBranch(orJoin(es.tail), thenn, elze, ch) 
+        mkBranch(orJoin(es.tail), thenn, elze, ch)
 
       case Implies(l, r) =>
         mkBranch(or(not(l), r), thenn, elze, ch)
@@ -1272,12 +1274,12 @@ trait CodeGeneration {
         mkExpr(r, ch)
         l.getType match {
           case Int32Type | CharType =>
-            ch << If_ICmpLt(thenn) << Goto(elze) 
+            ch << If_ICmpLt(thenn) << Goto(elze)
           case IntegerType =>
             ch << InvokeVirtual(BigIntClass, "lessThan", s"(L$BigIntClass;)Z")
             ch << IfEq(elze) << Goto(thenn)
           case RealType =>
-            ch << InvokeVirtual(RealClass, "lessThan", s"(L$RealClass;)Z")
+            ch << InvokeVirtual(RationalClass, "lessThan", s"(L$RationalClass;)Z")
             ch << IfEq(elze) << Goto(thenn)
         }
 
@@ -1286,12 +1288,12 @@ trait CodeGeneration {
         mkExpr(r, ch)
         l.getType match {
           case Int32Type | CharType =>
-            ch << If_ICmpGt(thenn) << Goto(elze) 
+            ch << If_ICmpGt(thenn) << Goto(elze)
           case IntegerType =>
             ch << InvokeVirtual(BigIntClass, "greaterThan", s"(L$BigIntClass;)Z")
             ch << IfEq(elze) << Goto(thenn)
           case RealType =>
-            ch << InvokeVirtual(RealClass, "greaterThan", s"(L$RealClass;)Z")
+            ch << InvokeVirtual(RationalClass, "greaterThan", s"(L$RationalClass;)Z")
             ch << IfEq(elze) << Goto(thenn)
         }
 
@@ -1300,12 +1302,12 @@ trait CodeGeneration {
         mkExpr(r, ch)
         l.getType match {
           case Int32Type | CharType =>
-            ch << If_ICmpLe(thenn) << Goto(elze) 
+            ch << If_ICmpLe(thenn) << Goto(elze)
           case IntegerType =>
             ch << InvokeVirtual(BigIntClass, "lessEquals", s"(L$BigIntClass;)Z")
             ch << IfEq(elze) << Goto(thenn)
           case RealType =>
-            ch << InvokeVirtual(RealClass, "lessEquals", s"(L$RealClass;)Z")
+            ch << InvokeVirtual(RationalClass, "lessEquals", s"(L$RationalClass;)Z")
             ch << IfEq(elze) << Goto(thenn)
         }
 
@@ -1314,16 +1316,16 @@ trait CodeGeneration {
         mkExpr(r, ch)
         l.getType match {
           case Int32Type | CharType =>
-            ch << If_ICmpGe(thenn) << Goto(elze) 
+            ch << If_ICmpGe(thenn) << Goto(elze)
           case IntegerType =>
             ch << InvokeVirtual(BigIntClass, "greaterEquals", s"(L$BigIntClass;)Z")
             ch << IfEq(elze) << Goto(thenn)
           case RealType =>
-            ch << InvokeVirtual(RealClass, "greaterEquals", s"(L$RealClass;)Z")
+            ch << InvokeVirtual(RationalClass, "greaterEquals", s"(L$RationalClass;)Z")
             ch << IfEq(elze) << Goto(thenn)
         }
-  
-      case IfExpr(c, t, e) => 
+
+      case IfExpr(c, t, e) =>
         val innerThen = ch.getFreshLabel("then")
         val innerElse = ch.getFreshLabel("else")
         mkBranch(c, innerThen, innerElse, ch)
@@ -1340,7 +1342,7 @@ trait CodeGeneration {
         mkExpr(other, ch, canDelegateToMkBranch = false)
         ch << IfEq(elze) << Goto(thenn)
 
-      case other => throw CompilationException("Unsupported branching expr. : " + other) 
+      case other => throw CompilationException("Unsupported branching expr. : " + other)
     }
   }
 
@@ -1366,38 +1368,38 @@ trait CodeGeneration {
   }
 
   /** Compiles a lazy field.
-    * 
+    *
     * To define a lazy field, we have to add an accessor method and an underlying field.
     * The accessor method has the name of the original (Scala) lazy field and can be public.
-    * The underlying field has a different name, is private, and is of a boxed type 
-    * to support null value (to signify uninitialized). 
-    * 
+    * The underlying field has a different name, is private, and is of a boxed type
+    * to support null value (to signify uninitialized).
+    *
     * @param lzy The lazy field to be compiled
     * @param owner The module/class containing `lzy`
     */
-  def compileLazyField(lzy: FunDef, owner: Definition) { 
+  def compileLazyField(lzy: FunDef, owner: Definition) {
     ctx.reporter.internalAssertion(lzy.canBeLazyField, s"Trying to compile non-lazy ${lzy.id.name} as a lazy field")
-        
+
     val (_, accessorName, _ ) = leonFunDefToJVMInfo(lzy).get
     val cf = classes(owner)
     val cName = defToJVMName(owner)
-    
+
     val isStatic = owner.isInstanceOf[ModuleDef]
-    
+
     // Name of the underlying field
     val underlyingName = underlyingField(accessorName)
     // Underlying field is of boxed type
     val underlyingType = typeToJVMBoxed(lzy.returnType)
-    
+
     // Underlying field. It is of a boxed type
     val fh = cf.addField(underlyingType,underlyingName)
     fh.setFlags( if (isStatic) {(
-      FIELD_ACC_STATIC | 
+      FIELD_ACC_STATIC |
       FIELD_ACC_PRIVATE
     ).asInstanceOf[U2] } else {
       FIELD_ACC_PRIVATE
     }) // FIXME private etc?
-      
+
     // accessor method
     locally {
       val parameters = if (requireMonitor) {
@@ -1413,11 +1415,11 @@ trait CodeGeneration {
         METHOD_ACC_PUBLIC
       ).asInstanceOf[U2] } else {
         METHOD_ACC_PUBLIC
-      }) 
+      })
       val ch = accM.codeHandler
       val body = lzy.body.getOrElse(throw CompilationException("Lazy field without body?"))
       val initLabel = ch.getFreshLabel("isInitialized")
-      
+
       if (requireMonitor) {
         load(monitorID, ch)(newLocs)
         ch << InvokeVirtual(MonitorClass, "onInvoke", "()V")
@@ -1429,13 +1431,13 @@ trait CodeGeneration {
         ch << ALoad(0) << GetField(cName, underlyingName, underlyingType) // if (lzy == null)
       }
       // oldValue
-      ch << DUP << IfNonNull(initLabel) 
+      ch << DUP << IfNonNull(initLabel)
       // null
       ch << POP
-      // 
-      mkBoxedExpr(body,ch)(newLocs) // lzy = <expr> 
+      //
+      mkBoxedExpr(body,ch)(newLocs) // lzy = <expr>
       ch << DUP
-      // newValue, newValue 
+      // newValue, newValue
       if (isStatic) {
         ch << PutStatic(cName, underlyingName, underlyingType)
         //newValue
@@ -1446,7 +1448,7 @@ trait CodeGeneration {
         ch << PutField (cName, underlyingName, underlyingType)
         //newValue
       }
-      ch << Label(initLabel)  // return lzy 
+      ch << Label(initLabel)  // return lzy
       //newValue
       lzy.returnType match {
         case ValueType() =>
@@ -1456,14 +1458,14 @@ trait CodeGeneration {
         case _ =>
           ch << ARETURN
       }
-      ch.freeze 
+      ch.freeze
     }
   }
-    
+
   /** Compile the (strict) field `field` which is owned by class `owner` */
   def compileStrictField(field : FunDef, owner : Definition) = {
 
-    ctx.reporter.internalAssertion(field.canBeStrictField, 
+    ctx.reporter.internalAssertion(field.canBeStrictField,
       s"Trying to compile ${field.id.name} as a strict field")
     val (_, fieldName, _) = leonFunDefToJVMInfo(field).get
 
@@ -1471,7 +1473,7 @@ trait CodeGeneration {
     val fh = cf.addField(typeToJVM(field.returnType),fieldName)
     fh.setFlags( owner match {
       case _ : ModuleDef => (
-        FIELD_ACC_STATIC | 
+        FIELD_ACC_STATIC |
         FIELD_ACC_PUBLIC | // FIXME
         FIELD_ACC_FINAL
       ).asInstanceOf[U2]
@@ -1481,16 +1483,16 @@ trait CodeGeneration {
       ).asInstanceOf[U2]
     })
   }
-  
+
   /** Initializes a lazy field to null
    *  @param ch the codehandler to add the initializing code to
-   *  @param className the name of the class in which the field is initialized 
+   *  @param className the name of the class in which the field is initialized
    *  @param lzy the lazy field to be initialized
    *  @param isStatic true if this is a static field
    */
   def initLazyField(ch: CodeHandler, className: String,  lzy: FunDef, isStatic: Boolean)(implicit locals: Locals) = {
     val (_, name, _) = leonFunDefToJVMInfo(lzy).get
-    val underlyingName = underlyingField(name) 
+    val underlyingName = underlyingField(name)
     val jvmType = typeToJVMBoxed(lzy.returnType)
     if (isStatic){
       ch << ACONST_NULL << PutStatic(className, underlyingName, jvmType)
@@ -1498,10 +1500,10 @@ trait CodeGeneration {
       ch << ALoad(0) << ACONST_NULL << PutField(className, underlyingName, jvmType)
     }
   }
-  
+
   /** Initializes a (strict) field
    *  @param ch the codehandler to add the initializing code to
-   *  @param className the name of the class in which the field is initialized 
+   *  @param className the name of the class in which the field is initialized
    *  @param field the field to be initialized
    *  @param isStatic true if this is a static field
    */
@@ -1519,8 +1521,8 @@ trait CodeGeneration {
     }
   }
 
-  def compileAbstractClassDef(acd : AbstractClassDef) {    
-    
+  def compileAbstractClassDef(acd : AbstractClassDef) {
+
     val cName = defToJVMName(acd)
 
     val cf  = classes(acd)
@@ -1533,30 +1535,30 @@ trait CodeGeneration {
 
     cf.addInterface(CaseClassClass)
 
-    // add special monitor for method invocations 
+    // add special monitor for method invocations
     if (params.doInstrument) {
       val fh = cf.addField("I", instrumentedField)
       fh.setFlags(FIELD_ACC_PUBLIC)
     }
-    
+
     val (fields, methods) = acd.methods partition { _.canBeField }
     val (strictFields, lazyFields) = fields partition { _.canBeStrictField }
-    
+
     // Compile methods
     for (method <- methods) {
       compileFunDef(method,acd)
     }
-    
+
     // Compile lazy fields
     for (lzy <- lazyFields) {
       compileLazyField(lzy, acd)
     }
-    
+
     // Compile strict fields
     for (field <- strictFields) {
       compileStrictField(field, acd)
     }
-    
+
     // definition of the constructor
     locally {
       val constrParams = if (requireMonitor) {
@@ -1586,7 +1588,7 @@ trait CodeGeneration {
           // Call constructor of java.lang.Object
           cch << InvokeSpecial(ObjectClass, constructorName, "()V")
       }
-      
+
       // Initialize special monitor field
       if (params.doInstrument) {
         cch << ALoad(0)
@@ -1637,9 +1639,9 @@ trait CodeGeneration {
 
     val cName = defToJVMName(ccd)
     val pName = ccd.parent.map(parent => defToJVMName(parent.classDef))
-    // An instantiation of ccd with its own type parameters 
+    // An instantiation of ccd with its own type parameters
     val cct = CaseClassType(ccd, ccd.tparams.map(_.tp))
-    
+
     val cf = classes(ccd)
 
     cf.setFlags((
@@ -1662,25 +1664,25 @@ trait CodeGeneration {
       case (id, jvmt) => (id, (cName, id.name, jvmt))
     }.toMap)
 
-    locally { 
+    locally {
       val (fields, methods) = ccd.methods partition { _.canBeField }
       val (strictFields, lazyFields) = fields partition { _.canBeStrictField }
-      
+
       // Compile methods
       for (method <- methods) {
         compileFunDef(method,ccd)
       }
-      
+
       // Compile lazy fields
       for (lzy <- lazyFields) {
-        compileLazyField(lzy, ccd) 
+        compileLazyField(lzy, ccd)
       }
-      
+
       // Compile strict fields
       for (field <- strictFields) {
-        compileStrictField(field, ccd) 
+        compileStrictField(field, ccd)
       }
-  
+
       // definition of the constructor
       if(!params.doInstrument && !requireMonitor && ccd.fields.isEmpty && !ccd.methods.exists(_.canBeField)) {
         cf.addDefaultConstructor
@@ -1692,14 +1694,14 @@ trait CodeGeneration {
             FIELD_ACC_FINAL
           ).asInstanceOf[U2])
         }
-  
+
         if (params.doInstrument) {
           val fh = cf.addField("I", instrumentedField)
           fh.setFlags(FIELD_ACC_PUBLIC)
         }
-  
+
         val cch = cf.addConstructor(constructorArgs.map(_._2) : _*).codeHandler
-  
+
         if (params.doInstrument) {
           cch << ALoad(0)
           cch << Ldc(0)
@@ -1831,7 +1833,7 @@ trait CodeGeneration {
               ech << InvokeVirtual(ObjectClass, "equals", s"(L$ObjectClass;)Z") << IfEq(notEq)
           }
         }
-      } 
+      }
 
       ech << Ldc(1) << IRETURN << Label(notEq) << Ldc(0) << IRETURN
       ech.freeze
@@ -1859,7 +1861,7 @@ trait CodeGeneration {
       hch << ALoad(0) << InvokeVirtual(cName, "productName", "()Ljava/lang/String;")
       hch << InvokeVirtual("java/lang/String", "hashCode", "()I")
       hch << InvokeStatic(HashingClass, "seqHash", s"([L$ObjectClass;I)I") << DUP
-      hch << ALoad(0) << SWAP << PutField(cName, hashFieldName, "I") 
+      hch << ALoad(0) << SWAP << PutField(cName, hashFieldName, "I")
       hch << IRETURN
 
       hch.freeze
diff --git a/src/main/scala/leon/codegen/CompilationUnit.scala b/src/main/scala/leon/codegen/CompilationUnit.scala
index c4551d5a4..a8c513a0c 100644
--- a/src/main/scala/leon/codegen/CompilationUnit.scala
+++ b/src/main/scala/leon/codegen/CompilationUnit.scala
@@ -75,9 +75,9 @@ class CompilationUnit(val ctx: LeonContext,
   // Returns className, methodName, methodSignature
   private[this] var funDefInfo = Map[FunDef, (String, String, String)]()
 
-  
+
   /**
-   * Returns (cn, mn, sig) where 
+   * Returns (cn, mn, sig) where
    *  cn is the module name
    *  mn is the safe method name
    *  sig is the method signature
@@ -164,8 +164,8 @@ class CompilationUnit(val ctx: LeonContext,
     case InfiniteIntegerLiteral(v) =>
       new runtime.BigInt(v.toString)
 
-    case RealLiteral(v) =>
-      new runtime.Real(v.toString)
+    case FractionalLiteral(n, d) =>
+      new runtime.Rational(n.toString, d.toString)
 
     case GenericValue(tp, id) =>
       e
@@ -218,7 +218,7 @@ class CompilationUnit(val ctx: LeonContext,
     //case _ =>
     //  compileExpression(e, Seq()).evalToJVM(Seq(),monitor)
   }
-  
+
   /** Translates JVM objects back to Leon values of the appropriate type */
   def jvmToValue(e: AnyRef, tpe: TypeTree): Expr = (e, tpe) match {
     case (i: Integer, Int32Type) =>
@@ -227,8 +227,10 @@ class CompilationUnit(val ctx: LeonContext,
     case (c: runtime.BigInt, IntegerType) =>
       InfiniteIntegerLiteral(BigInt(c.underlying))
 
-    case (c: runtime.Real, RealType) =>
-      RealLiteral(BigDecimal(c.underlying))
+    case (c: runtime.Rational, RealType) =>
+      val num = BigInt(c.numerator())
+      val denom = BigInt(c.denominator())
+      FractionalLiteral(num, denom)
 
     case (b: java.lang.Boolean, BooleanType) =>
       BooleanLiteral(b.booleanValue)
@@ -257,7 +259,7 @@ class CompilationUnit(val ctx: LeonContext,
 
     case (tpl: runtime.Tuple, tpe) =>
       val stpe = unwrapTupleType(tpe, tpl.getArity)
-      val elems = stpe.zipWithIndex.map { case (tpe, i) => 
+      val elems = stpe.zipWithIndex.map { case (tpe, i) =>
         jvmToValue(tpl.get(i), tpe)
       }
       tupleWrap(elems)
@@ -379,7 +381,7 @@ class CompilationUnit(val ctx: LeonContext,
 
     val (fields, functions) = module.definedFunctions partition { _.canBeField }
     val (strictFields, lazyFields) = fields partition { _.canBeStrictField }
-    
+
     // Compile methods
     for (function <- functions) {
       compileFunDef(function,module)
@@ -394,17 +396,17 @@ class CompilationUnit(val ctx: LeonContext,
     for (field <- strictFields) {
       compileStrictField(field, module)
     }
- 
+
     // Constructor
     cf.addDefaultConstructor
 
     val cName = defToJVMName(module)
 
     // Add class initializer method
-    locally{ 
+    locally{
       val mh = cf.addMethod("V", "<clinit>")
       mh.setFlags((
-        METHOD_ACC_STATIC | 
+        METHOD_ACC_STATIC |
         METHOD_ACC_PUBLIC
       ).asInstanceOf[U2])
 
@@ -412,9 +414,9 @@ class CompilationUnit(val ctx: LeonContext,
       /*
        * FIXME :
        * Dirty hack to make this compatible with monitoring of method invocations.
-       * Because we don't have access to the monitor object here, we initialize a new one 
-       * that will get lost when this method returns, so we can't hope to count 
-       * method invocations here :( 
+       * Because we don't have access to the monitor object here, we initialize a new one
+       * that will get lost when this method returns, so we can't hope to count
+       * method invocations here :(
        */
       val locals = NoLocals.withVar(monitorID -> ch.getFreshVar)
       ch << New(MonitorClass) << DUP
@@ -443,7 +445,7 @@ class CompilationUnit(val ctx: LeonContext,
           defToModuleOrClass += meth -> cls
         }
       }
-     
+
       for (m <- u.modules) {
         defineClass(m)
         for(funDef <- m.definedFunctions) {
@@ -453,14 +455,14 @@ class CompilationUnit(val ctx: LeonContext,
     }
   }
 
-  /** Compiles the program. 
+  /** Compiles the program.
     *
     * Uses information provided by [[init]].
     */
   def compile() {
     // Compile everything
     for (u <- program.units) {
-      
+
       for {
         ch <- u.classHierarchies
         c  <- ch
diff --git a/src/main/scala/leon/codegen/CompiledExpression.scala b/src/main/scala/leon/codegen/CompiledExpression.scala
index ad012bb74..a9d1eda0c 100644
--- a/src/main/scala/leon/codegen/CompiledExpression.scala
+++ b/src/main/scala/leon/codegen/CompiledExpression.scala
@@ -59,4 +59,4 @@ class CompiledExpression(unit: CompilationUnit, cf: ClassFile, expression: Expr,
       case ite : InvocationTargetException => throw ite.getCause
     }
   }
-} 
+}
diff --git a/src/main/scala/leon/evaluators/CodeGenEvaluator.scala b/src/main/scala/leon/evaluators/CodeGenEvaluator.scala
index 4cc67c3fa..36cd9da0c 100644
--- a/src/main/scala/leon/evaluators/CodeGenEvaluator.scala
+++ b/src/main/scala/leon/evaluators/CodeGenEvaluator.scala
@@ -22,7 +22,7 @@ class CodeGenEvaluator(ctx: LeonContext, val unit : CompilationUnit) extends Eva
 
   def eval(expression: Expr, model: solvers.Model) : EvaluationResult = {
     val toPairs = model.toSeq
-    compile(expression, toPairs.map(_._1)).map { e => 
+    compile(expression, toPairs.map(_._1)).map { e =>
       ctx.timers.evaluators.codegen.runtime.start()
       val res = e(model)
       ctx.timers.evaluators.codegen.runtime.stop()
@@ -57,8 +57,8 @@ class CodeGenEvaluator(ctx: LeonContext, val unit : CompilationUnit) extends Eva
             EvaluationResults.EvaluatorError(e.getMessage)
 
           case e : java.lang.ExceptionInInitializerError =>
-            EvaluationResults.RuntimeError(e.getException.getMessage) 
-          
+            EvaluationResults.RuntimeError(e.getException.getMessage)
+
           case so : java.lang.StackOverflowError =>
             EvaluationResults.RuntimeError("Stack overflow")
 
diff --git a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
index 2091b0e6e..bd2a594ec 100644
--- a/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
+++ b/src/main/scala/leon/evaluators/RecursiveEvaluator.scala
@@ -12,10 +12,10 @@ import purescala.TypeOps.isSubtypeOf
 import purescala.Constructors._
 import purescala.Extractors._
 import purescala.Quantification._
-
 import solvers.{Model, HenkinModel}
 import solvers.SolverFactory
 import synthesis.ConvertHoles.convertHoles
+import leon.purescala.ExprOps
 
 abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int) extends Evaluator(ctx, prog) {
   val name = "evaluator"
@@ -122,11 +122,11 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       if ( exists{
         case Hole(_,_) => true
         case _ => false
-      }(en)) 
+      }(en))
         e(convertHoles(en, ctx))
       else
         e(en.toAssert)
-    
+
     case Error(tpe, desc) =>
       throw RuntimeError("Error reached in evaluation: " + desc)
 
@@ -147,7 +147,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       val nil = CaseClass(CaseClassType(program.library.Nil.get, Seq(tp)), Seq())
       def mkCons(h: Expr, t: Expr) = CaseClass(CaseClassType(cons, Seq(tp)), Seq(h,t))
       els.foldRight(nil)(mkCons)
-      
+
     case FunctionInvocation(tfd, args) =>
       if (gctx.stepsLeft < 0) {
         throw RuntimeError("Exceeded number of allocated methods calls ("+gctx.maxSteps+")")
@@ -177,7 +177,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       val callResult = e(body)(frame, gctx)
 
       tfd.postcondition match  {
-        case Some(post) => 
+        case Some(post) =>
           e(application(post, Seq(callResult)))(frame, gctx) match {
             case BooleanLiteral(true) =>
             case BooleanLiteral(false) => throw RuntimeError("Postcondition violation for " + tfd.id.asString + " reached in evaluation.")
@@ -237,7 +237,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       if (isSubtypeOf(le.getType, ct)) {
         le
       } else {
-        throw RuntimeError("Cast error: cannot cast "+le.asString+" to "+ct.asString) 
+        throw RuntimeError("Cast error: cannot cast "+le.asString+" to "+ct.asString)
       }
 
     case IsInstanceOf(expr, ct) =>
@@ -263,17 +263,15 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType))
       }
 
-    case RealPlus(l,r) =>
+    case RealPlus(l, r) =>
       (e(l), e(r)) match {
-        case (RealLiteral(i1), RealLiteral(i2)) => RealLiteral(i1 + i2)
-        case (le,re) => throw EvalError(typeErrorMsg(le, RealType))
+        case (FractionalLiteral(ln, ld), FractionalLiteral(rn, rd)) =>
+          normalizeFraction(FractionalLiteral((ln * rd + rn * ld), (ld * rd)))
+        case (le, re) => throw EvalError(typeErrorMsg(le, RealType))
       }
 
     case RealMinus(l,r) =>
-      (e(l), e(r)) match {
-        case (RealLiteral(i1), RealLiteral(i2)) => RealLiteral(i1 - i2)
-        case (le,re) => throw EvalError(typeErrorMsg(le, RealType))
-      }
+      e(RealPlus(l, RealUMinus(r)))
 
     case BVPlus(l,r) =>
       (e(l), e(r)) match {
@@ -301,7 +299,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
 
     case RealUMinus(ex) =>
       e(ex) match {
-        case RealLiteral(i) => RealLiteral(-i)
+        case FractionalLiteral(n, d) => FractionalLiteral(-n, d)
         case re => throw EvalError(typeErrorMsg(re, RealType))
       }
 
@@ -333,12 +331,12 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       }
     case Modulo(l,r) =>
       (e(l), e(r)) match {
-        case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => 
+        case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) =>
           if(i2 < 0)
             InfiniteIntegerLiteral(i1 mod (-i2))
-          else if(i2 != BigInt(0)) 
-            InfiniteIntegerLiteral(i1 mod i2) 
-          else 
+          else if(i2 != BigInt(0))
+            InfiniteIntegerLiteral(i1 mod i2)
+          else
             throw RuntimeError("Modulo of division by 0.")
         case (le,re) => throw EvalError(typeErrorMsg(le, IntegerType))
       }
@@ -358,21 +356,24 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
 
     case BVRemainder(l,r) =>
       (e(l), e(r)) match {
-        case (IntLiteral(i1), IntLiteral(i2)) => 
+        case (IntLiteral(i1), IntLiteral(i2)) =>
           if(i2 != 0) IntLiteral(i1 % i2) else throw RuntimeError("Remainder of division by 0.")
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
 
     case RealTimes(l,r) =>
       (e(l), e(r)) match {
-        case (RealLiteral(i1), RealLiteral(i2)) => RealLiteral(i1 * i2)
+        case (FractionalLiteral(ln, ld), FractionalLiteral(rn, rd)) =>
+          normalizeFraction(FractionalLiteral((ln * rn), (ld * rd)))
         case (le,re) => throw EvalError(typeErrorMsg(le, RealType))
       }
 
     case RealDivision(l,r) =>
       (e(l), e(r)) match {
-        case (RealLiteral(i1), RealLiteral(i2)) =>
-          if (i2 != 0) RealLiteral(i1 / i2) else throw RuntimeError("Division by 0.")
+        case (FractionalLiteral(ln, ld), FractionalLiteral(rn, rd)) =>
+          if (rn != 0)
+            normalizeFraction(FractionalLiteral((ln * rd), (ld * rn)))
+          else throw RuntimeError("Division by 0.")
         case (le,re) => throw EvalError(typeErrorMsg(le, RealType))
       }
 
@@ -417,7 +418,9 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       (e(l), e(r)) match {
         case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 < i2)
         case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 < i2)
-        case (RealLiteral(r1), RealLiteral(r2)) => BooleanLiteral(r1 < r2)
+        case (a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) =>
+           val FractionalLiteral(n, _) = e(RealMinus(a, b))
+           BooleanLiteral(n < 0)
         case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 < c2)
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
@@ -426,7 +429,9 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       (e(l), e(r)) match {
         case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 > i2)
         case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 > i2)
-        case (RealLiteral(r1), RealLiteral(r2)) => BooleanLiteral(r1 > r2)
+        case (a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) =>
+           val FractionalLiteral(n, _) = e(RealMinus(a, b))
+           BooleanLiteral(n > 0)
         case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 > c2)
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
@@ -435,7 +440,9 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       (e(l), e(r)) match {
         case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 <= i2)
         case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 <= i2)
-        case (RealLiteral(r1), RealLiteral(r2)) => BooleanLiteral(r1 <= r2)
+        case (a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) =>
+           val FractionalLiteral(n, _) = e(RealMinus(a, b))
+           BooleanLiteral(n <= 0)
         case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 <= c2)
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
@@ -444,14 +451,16 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
       (e(l), e(r)) match {
         case (IntLiteral(i1), IntLiteral(i2)) => BooleanLiteral(i1 >= i2)
         case (InfiniteIntegerLiteral(i1), InfiniteIntegerLiteral(i2)) => BooleanLiteral(i1 >= i2)
-        case (RealLiteral(r1), RealLiteral(r2)) => BooleanLiteral(r1 >= r2)
+        case (a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) =>
+           val FractionalLiteral(n, _) = e(RealMinus(a, b))
+           BooleanLiteral(n >= 0)
         case (CharLiteral(c1), CharLiteral(c2)) => BooleanLiteral(c1 >= c2)
         case (le,re) => throw EvalError(typeErrorMsg(le, Int32Type))
       }
 
     case SetUnion(s1,s2) =>
       (e(s1), e(s2)) match {
-        case (f@FiniteSet(els1, _),FiniteSet(els2, _)) => 
+        case (f@FiniteSet(els1, _),FiniteSet(els2, _)) =>
           val SetType(tpe) = f.getType
           FiniteSet(els1 ++ els2, tpe)
         case (le,re) => throw EvalError(typeErrorMsg(le, s1.getType))
@@ -492,7 +501,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
         case _ => throw EvalError(typeErrorMsg(sr, SetType(Untyped)))
       }
 
-    case f @ FiniteSet(els, base) => 
+    case f @ FiniteSet(els, base) =>
       FiniteSet(els.map(e), base)
 
     case l @ Lambda(_, _) =>
@@ -588,12 +597,12 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
     case f @ FiniteArray(elems, default, length) =>
       val ArrayType(tp) = f.getType
       finiteArray(
-        elems.map(el => (el._1, e(el._2))), 
+        elems.map(el => (el._1, e(el._2))),
         default.map{ d => (e(d), e(length)) },
         tp
       )
 
-    case f @ FiniteMap(ss, kT, vT) => 
+    case f @ FiniteMap(ss, kT, vT) =>
       FiniteMap(ss.map{ case (k, v) => (e(k), e(v)) }.distinct, kT, vT)
 
     case g @ MapApply(m,k) => (e(m), e(k)) match {
@@ -620,7 +629,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
     case gv: GenericValue =>
       gv
 
-    case p : Passes => 
+    case p : Passes =>
       e(p.asConstraint)
 
     case choose: Choose =>
@@ -684,6 +693,7 @@ abstract class RecursiveEvaluator(ctx: LeonContext, prog: Program, maxSteps: Int
           throw RuntimeError("MatchError: "+rscrut.asString+" did not match any of the cases")
       }
 
+    case fl : FractionalLiteral => normalizeFraction(fl)
     case l : Literal[_] => l
 
     case other =>
diff --git a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
index 025aa4b98..fbbfd6e3d 100644
--- a/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
+++ b/src/main/scala/leon/frontends/scalac/CodeExtraction.scala
@@ -139,7 +139,7 @@ trait CodeExtraction extends ASTExtractors {
 
     //This is a bit misleading, if an expr is not mapped then it has no owner, if it is mapped to None it means
     //that it can have any owner
-    private var owners: Map[Identifier, Option[FunDef]] = Map() 
+    private var owners: Map[Identifier, Option[FunDef]] = Map()
 
     // This one never fails, on error, it returns Untyped
     def leonType(tpt: Type)(implicit dctx: DefContext, pos: Position): LeonType = {
@@ -379,7 +379,7 @@ trait CodeExtraction extends ASTExtractors {
       val allSels = sels map { prefix :+ _.name.toString }
 
       // Make a different import for each selector at the end of the chain
-      allSels flatMap { selectors => 
+      allSels flatMap { selectors =>
         assert(selectors.nonEmpty)
         val (thePath, isWild) = selectors.last match {
           case "_" => (selectors.dropRight(1), true)
@@ -448,8 +448,8 @@ trait CodeExtraction extends ASTExtractors {
     private var methodToClass = Map[FunDef, LeonClassDef]()
 
     /**
-     * For the function in $defs with name $owner, find its parameter with index $index, 
-     * and registers $fd as the default value function for this parameter.  
+     * For the function in $defs with name $owner, find its parameter with index $index,
+     * and registers $fd as the default value function for this parameter.
      */
     private def registerDefaultMethod(
       defs : List[Tree],
@@ -548,7 +548,7 @@ trait CodeExtraction extends ASTExtractors {
 
       //println(s"Body of $sym")
 
-      // We collect the methods and fields 
+      // We collect the methods and fields
       for (d <- tmpl.body) d match {
         case EmptyTree =>
           // ignore
@@ -575,7 +575,7 @@ trait CodeExtraction extends ASTExtractors {
 
           cd.registerMethod(fd)
           val matcher: PartialFunction[Tree, Symbol] = {
-            case ExFunctionDef(ownerSym, _ ,_ ,_, _) if ownerSym.name.toString == owner => ownerSym 
+            case ExFunctionDef(ownerSym, _ ,_ ,_, _) if ownerSym.name.toString == owner => ownerSym
           }
           registerDefaultMethod(tmpl.body, matcher, index, fd )
 
@@ -765,7 +765,7 @@ trait CodeExtraction extends ASTExtractors {
 
       // Find defining function for params with default value
       for ((s,vd) <- params zip funDef.params) {
-        vd.defaultValue = paramsToDefaultValues.get(s.symbol) 
+        vd.defaultValue = paramsToDefaultValues.get(s.symbol)
       }
 
       val newVars = for ((s, vd) <- params zip funDef.params) yield {
@@ -775,7 +775,7 @@ trait CodeExtraction extends ASTExtractors {
       val fctx = dctx.withNewVars(newVars).copy(isExtern = funDef.annotations("extern"))
 
       // If this is a lazy field definition, drop the assignment/ accessing
-      val body = 
+      val body =
         if (funDef.flags.contains(IsField(true))) { body0 match {
           case Block(List(Assign(_, realBody)),_ ) => realBody
           case _ => outOfSubsetError(body0, "Wrong form of lazy accessor")
@@ -938,7 +938,7 @@ trait CodeExtraction extends ASTExtractors {
         val recGuard = extractTree(cd.guard)(ndctx)
 
         if(isXLang(recGuard)) {
-          outOfSubsetError(cd.guard.pos, "Guard expression must be pure") 
+          outOfSubsetError(cd.guard.pos, "Guard expression must be pure")
         }
 
         GuardedCase(recPattern, recGuard, recBody).setPos(cd.pos)
@@ -1110,7 +1110,7 @@ trait CodeExtraction extends ASTExtractors {
           LetDef(funDefWithBody, restTree)
 
         // FIXME case ExDefaultValueFunction
-        
+
         /**
          * XLang Extractors
          */
@@ -1218,7 +1218,7 @@ trait CodeExtraction extends ASTExtractors {
           rec match {
             case IntLiteral(n) =>
               InfiniteIntegerLiteral(BigInt(n))
-            case _ => 
+            case _ =>
               outOfSubsetError(tr, "Conversion from Int to BigInt")
           }
 
@@ -1227,7 +1227,7 @@ trait CodeExtraction extends ASTExtractors {
           val rd = extractTree(d)
           (rn, rd) match {
             case (InfiniteIntegerLiteral(n), InfiniteIntegerLiteral(d)) =>
-              RealLiteral(BigDecimal(n) / BigDecimal(d))
+              FractionalLiteral(n, d)
             case _ =>
               outOfSubsetError(tr, "Real not build from literals")
           }
@@ -1235,7 +1235,7 @@ trait CodeExtraction extends ASTExtractors {
           val rn = extractTree(n)
           rn match {
             case InfiniteIntegerLiteral(n) =>
-              RealLiteral(BigDecimal(n))
+              FractionalLiteral(n, 1)
             case _ =>
               outOfSubsetError(tr, "Real not build from literals")
           }
@@ -1482,7 +1482,7 @@ trait CodeExtraction extends ASTExtractors {
 
         case str @ ExStringLiteral(s) =>
           val chars = s.toList.map(CharLiteral)
-          
+
           val consChar = CaseClassType(libraryCaseClass(str.pos, "leon.collection.Cons"), Seq(CharType))
           val nilChar  = CaseClassType(libraryCaseClass(str.pos, "leon.collection.Nil"),  Seq(CharType))
 
@@ -1810,11 +1810,11 @@ trait CodeExtraction extends ASTExtractors {
 
       case RefinedType(parents, defs) if defs.isEmpty =>
         /**
-         * For cases like if(a) e1 else e2 where 
+         * For cases like if(a) e1 else e2 where
          *   e1 <: C1,
          *   e2 <: C2,
          *   with C1,C2 <: C
-         * 
+         *
          * Scala might infer a type for C such as: Product with Serializable with C
          * we generalize to the first known type, e.g. C.
          */
diff --git a/src/main/scala/leon/invariant/engine/CompositionalTemplateSolver.scala b/src/main/scala/leon/invariant/engine/CompositionalTemplateSolver.scala
new file mode 100644
index 000000000..4c443b3f6
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/CompositionalTemplateSolver.scala
@@ -0,0 +1,235 @@
+package leon
+package invariant.engine
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import invariant.templateSolvers._
+import invariant.util.Util._
+import transformations._
+import invariant.structure.FunctionUtils._
+import transformations.InstUtil._
+import leon.invariant.structure.Formula
+import leon.invariant.structure.Call
+import leon.invariant.util.RealToInt
+import leon.invariant.util.OrderedMultiMap
+import leon.invariant.util.ExpressionTransformer
+import leon.invariant.factories.TemplateSolverFactory
+import leon.invariant.util.Minimizer
+import leon.solvers.Model
+
+class CompositionalTimeBoundSolver(ctx: InferenceContext, rootFd: FunDef)
+  extends FunctionTemplateSolver {
+
+  val printIntermediatePrograms = false
+  val debugDecreaseConstraints = false
+  val debugComposition = false
+  val reporter = ctx.reporter
+
+  def inferTemplate(instProg: Program) = {
+    (new UnfoldingTemplateSolver(ctx.copy(program = instProg), findRoot(instProg)))()
+  }
+
+  def findRoot(prog: Program) = {
+    functionByName(rootFd.id.name, prog).get
+  }
+
+  def apply() = {
+    // Check if all the three templates have different template variable sets
+    val (Some(tprTmpl), Some(recTmpl), Some(timeTmpl), othersTmpls) = extractSeparateTemplates(rootFd)
+    val tmplIds = (Seq(tprTmpl, recTmpl, timeTmpl) ++ othersTmpls) flatMap getTemplateIds
+    if (tmplIds.toSet.size < tmplIds.size)
+      throw new IllegalStateException("Templates for tpr, rec, time as well as all other templates " +
+        " taken together should not have the any common template variables for compositional analysis")
+
+    val origProg = ctx.program
+    // add only rec templates for all functions
+    val funToRecTmpl = origProg.definedFunctions.collect {
+      case fd if fd.hasTemplate && fd == rootFd =>
+        fd -> recTmpl
+      case fd if fd.hasTemplate =>
+        fd -> fd.getTemplate
+    }.toMap
+    val recProg = assignTemplateAndCojoinPost(funToRecTmpl, origProg)
+
+    // add only tpr template for all functions
+    val funToNonRecTmpl = origProg.definedFunctions.collect {
+      case fd if fd.hasTemplate && fd == rootFd =>
+        fd -> tprTmpl
+      case fd if fd.hasTemplate =>
+        fd -> fd.getTemplate
+    }.toMap
+    val tprProg = assignTemplateAndCojoinPost(funToNonRecTmpl, origProg)
+
+    if (printIntermediatePrograms) {
+      reporter.info("RecProg:\n" + recProg)
+      reporter.info("TRPProg: \n" + tprProg)
+    }
+    val recInfRes = inferTemplate(recProg)
+    val tprInfRes = inferTPRTemplate(tprProg)
+
+    (recInfRes, tprInfRes) match {
+      case (Some(InferResult(true, Some(recModel), _)),
+        Some(InferResult(true, Some(tprModel), _))) =>
+        // create a new program by omitting the templates of the root function
+        val funToTmpl = origProg.definedFunctions.collect {
+          case fd if fd.hasTemplate && fd != rootFd =>
+            (fd -> fd.getTemplate)
+        }.toMap
+        val compProg = assignTemplateAndCojoinPost(funToTmpl, origProg)
+        val compFunDef = findRoot(compProg)
+        val nctx = ctx.copy(program = compProg)
+
+        // construct the instantiated tpr bound and check if it monotonically decreases
+        val Operator(Seq(_, tprFun), _) = tprTmpl
+        val tprFunInst = (new RealToInt()).mapRealToInt(
+          replace(tprModel.map { case (k, v) => (k.toVariable -> v) }.toMap, tprFun))
+        // TODO: this would fail on non-integers, handle these by approximating to the next bigger integer
+
+        // Upper bound on time time <= recFun * tprFun + tprFun
+        val (_, multFun) = MultFuncs.getMultFuncs(if (ctx.usereals) RealType else IntegerType)
+        val Operator(Seq(_, recFun), _) = recTmpl
+        val recFunInst = (new RealToInt()).mapRealToInt(
+          replace(recModel.map { case (k, v) => (k.toVariable -> v) }.toMap, recFun))
+
+        val timeUpperBound = ExpressionTransformer.normalizeMultiplication(
+          Plus(FunctionInvocation(TypedFunDef(multFun, Seq()),
+            Seq(recFunInst, tprFunInst)), tprFunInst), ctx.multOp)
+        // res = body
+        val plainBody = Equals(getResId(rootFd).get.toVariable, matchToIfThenElse(rootFd.body.get))
+        val bodyExpr = if (rootFd.hasPrecondition) {
+          And(matchToIfThenElse(rootFd.precondition.get), plainBody)
+        } else plainBody
+
+        val Operator(Seq(timeInstExpr, _), _) = timeTmpl
+        val compositionAnt = And(Seq(LessEquals(timeInstExpr, timeUpperBound), bodyExpr))
+        val prototypeVC = And(compositionAnt, Not(timeTmpl))
+
+        // map the old functions in the vc using the new functions
+        val substMap = origProg.definedFunctions.collect {
+          case fd =>
+            (fd -> functionByName(fd.id.name, compProg).get)
+        }.toMap
+        val vcExpr = mapFunctionsInExpr(substMap)(prototypeVC)
+
+        if (printIntermediatePrograms) reporter.info("Comp prog: " + compProg)
+        if (debugComposition) reporter.info("Compositional VC: " + vcExpr)
+
+        val recTempSolver = new UnfoldingTemplateSolver(nctx, compFunDef) {
+          val minFunc = {
+            val mizer = new Minimizer(ctx)
+            Some(mizer.minimizeBounds(mizer.computeCompositionLevel(timeTmpl)) _)
+          }
+          override lazy val templateSolver =
+            TemplateSolverFactory.createTemplateSolver(ctx, constTracker, rootFd, minFunc)
+          override def instantiateModel(model: Model, funcs: Seq[FunDef]) = {
+            funcs.collect {
+              case `compFunDef` =>
+                compFunDef -> timeTmpl
+              case fd if fd.hasTemplate =>
+                fd -> fd.getTemplate
+            }.toMap
+          }
+        }
+        recTempSolver.solveParametricVC(vcExpr) match {
+          case Some(InferResult(true, Some(timeModel),timeInferredFuncs)) =>
+            val inferredFuns = (recInfRes.get.inferredFuncs ++ tprInfRes.get.inferredFuncs ++ timeInferredFuncs).distinct
+            Some(InferResult(true, Some(recModel ++ tprModel.toMap ++ timeModel.toMap),
+              inferredFuns.map(ifd => functionByName(ifd.id.name, origProg).get).distinct))
+          case res @ _ =>
+            res
+        }
+      case _ =>
+        reporter.info("Could not infer bounds on rec and(or) tpr. Cannot precced with composition.")
+        None
+    }
+  }
+
+  def combineMapsUsingConjunction(maps: List[Map[FunDef, Expr]]) = {
+    val combMap = new OrderedMultiMap[FunDef, Expr]
+    maps.foreach {
+      _.foreach {
+        case (k, v) =>
+          val origFun = functionByName(k.id.name, ctx.program).get
+          combMap.addBinding(origFun, v)
+      }
+    }
+    combMap.foldLeft(Map[FunDef, Expr]()) {
+      case (acc, (k, vs)) if vs.size == 1 => acc + (k -> vs(0))
+      case (acc, (k, vs)) => acc + (k -> And(vs.toSeq))
+    }
+  }
+
+  def extractSeparateTemplates(funDef: FunDef): (Option[Expr], Option[Expr], Option[Expr], Seq[Expr]) = {
+    if (!funDef.hasTemplate) (None, None, None, Seq[Expr]())
+    else {
+      val template = ExpressionTransformer.pullAndOrs(And(funDef.getTemplate,
+          funDef.getPostWoTemplate)) // note that some bounds can occur in post and not in tmpl
+      def extractTmplConjuncts(tmpl: Expr): Seq[Expr] = {
+        tmpl match {
+          case And(seqExprs) =>
+            seqExprs
+          case _ =>
+            throw new IllegalStateException("Compositional reasoning requires templates to be conjunctions!" + tmpl)
+        }
+      }
+      val tmplConjuncts = extractTmplConjuncts(template)
+      val tupleSelectToInst = InstUtil.getInstMap(funDef)
+      var tprTmpl: Option[Expr] = None
+      var timeTmpl: Option[Expr] = None
+      var recTmpl: Option[Expr] = None
+      var othersTmpls: Seq[Expr] = Seq[Expr]()
+      tmplConjuncts.foreach(conj => {
+        conj match {
+          case Operator(Seq(lhs, _), _) if (tupleSelectToInst.contains(lhs)) =>
+            tupleSelectToInst(lhs) match {
+              case n if n == TPR.name =>
+                tprTmpl = Some(conj)
+              case n if n == Time.name =>
+                timeTmpl = Some(conj)
+              case n if n == Rec.name =>
+                recTmpl = Some(conj)
+              case _ =>
+                othersTmpls = othersTmpls :+ conj
+            }
+          case _ =>
+            othersTmpls = othersTmpls :+ conj
+        }
+      })
+      (tprTmpl, recTmpl, timeTmpl, othersTmpls)
+    }
+  }
+
+  def inferTPRTemplate(tprProg: Program) = {
+    val tempSolver = new UnfoldingTemplateSolver(ctx.copy(program = tprProg), findRoot(tprProg)) {
+      override def constructVC(rootFd: FunDef): (Expr, Expr) = {
+        val body = Equals(getResId(rootFd).get.toVariable, matchToIfThenElse(rootFd.body.get))
+        val preExpr =
+          if (rootFd.hasPrecondition)
+            matchToIfThenElse(rootFd.precondition.get)
+          else tru
+        val tprTmpl = rootFd.getTemplate
+        val postWithTemplate = matchToIfThenElse(And(rootFd.getPostWoTemplate, tprTmpl))
+        // generate constraints characterizing decrease of the tpr function with recursive calls
+        val Operator(Seq(_, tprFun), op) = tprTmpl
+        val bodyFormula = new Formula(rootFd, ExpressionTransformer.normalizeExpr(body, ctx.multOp), ctx)
+        val constraints = bodyFormula.disjunctsInFormula.flatMap {
+          case (guard, ctrs) =>
+            ctrs.collect {
+              case call @ Call(_, FunctionInvocation(TypedFunDef(`rootFd`, _), _)) => //direct recursive call ?
+                Implies(guard, LessEquals(replace(formalToActual(call), tprFun), tprFun))
+            }
+        }
+        if (debugDecreaseConstraints)
+          reporter.info("Decrease constraints: " + createAnd(constraints.toSeq))
+
+        val fullPost = createAnd(postWithTemplate +: constraints.toSeq)
+        (And(preExpr, bodyFormula.toExpr), fullPost)
+      }
+    }
+    tempSolver()
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/engine/ConstraintTracker.scala b/src/main/scala/leon/invariant/engine/ConstraintTracker.scala
new file mode 100644
index 000000000..e50b50bb8
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/ConstraintTracker.scala
@@ -0,0 +1,45 @@
+package leon
+package invariant.engine
+
+import z3.scala._
+import purescala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import evaluators._
+import java.io._
+
+import invariant.factories._
+import invariant.util._
+import invariant.structure._
+
+class ConstraintTracker(ctx : InferenceContext, rootFun : FunDef/*, temFactory: TemplateFactory*/) {
+
+  //a mapping from functions to its VCs represented as a CNF formula
+  protected var funcVCs = Map[FunDef,Formula]()
+
+  val vcRefiner = new RefinementEngine(ctx, this/*, temFactory*/)
+  val specInstantiator = new SpecInstantiator(ctx, this/*, temFactory*/)
+
+  def getFuncs : Seq[FunDef] = funcVCs.keys.toSeq
+  def hasVC(fdef: FunDef) = funcVCs.contains(fdef)
+  def getVC(fd: FunDef) : Formula = funcVCs(fd)
+
+  def addVC(fd: FunDef, vc: Expr) = {
+    funcVCs += (fd -> new Formula(fd, vc, ctx))
+  }
+
+  def initialize = {
+    //assume specifications
+    specInstantiator.instantiate
+  }
+
+  def refineVCs(toUnrollCalls: Option[Set[Call]]) : Set[Call]  = {
+    val unrolledCalls = vcRefiner.refineAbstraction(toUnrollCalls)
+    specInstantiator.instantiate
+    unrolledCalls
+  }
+}
diff --git a/src/main/scala/leon/invariant/engine/InferInvariantsPhase.scala b/src/main/scala/leon/invariant/engine/InferInvariantsPhase.scala
new file mode 100644
index 000000000..30ca3fcde
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/InferInvariantsPhase.scala
@@ -0,0 +1,165 @@
+package leon
+package invariant.engine
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.ExprOps._
+import purescala.Expressions._
+import purescala.Extractors._
+import purescala.Types._
+import verification.VerificationReport
+import invariant.templateSolvers._
+import invariant.factories._
+import invariant.util._
+import invariant.structure.FunctionUtils._
+import invariant.structure._
+import transformations._
+import verification._
+import verification.VCKinds
+import leon.purescala.ScalaPrinter
+
+/**
+ * @author ravi
+ * This phase performs automatic invariant inference.
+ * TODO: should time be implicitly made positive
+ */
+object InferInvariantsPhase extends LeonPhase[Program, InferenceReport] {
+  val name = "InferInv"
+  val description = "Invariant Inference"
+
+  val optWholeProgram = LeonFlagOptionDef("wholeprogram", "Perform an non-modular whole program analysis", false)
+  val optFunctionUnroll = LeonFlagOptionDef("fullunroll", "Unroll all calls in every unroll step", false)
+  val optWithMult = LeonFlagOptionDef("withmult", "Multiplication is not converted to a recursive function in VCs", false)
+  val optUseReals = LeonFlagOptionDef("usereals", "Interpret the input program as a real program", false)
+  val optMinBounds = LeonFlagOptionDef("minbounds", "tighten time bounds", false)
+  val optInferTemp = LeonFlagOptionDef("inferTemp", "Infer templates by enumeration", false)
+  val optCegis = LeonFlagOptionDef("cegis", "use cegis instead of farkas", false)
+  val optStatsSuffix = LeonStringOptionDef("stats-suffix", "the suffix of the statistics file", "", "s")
+  val optTimeout = LeonLongOptionDef("timeout", "Timeout after T seconds when trying to prove a verification condition.", 20, "s")
+  val optDisableInfer = LeonFlagOptionDef("disableInfer", "Disable automatic inference of auxiliary invariants", false)
+
+  override val definedOptions: Set[LeonOptionDef[Any]] =
+    Set(optWholeProgram, optFunctionUnroll, optWithMult, optUseReals,
+        optMinBounds, optInferTemp, optCegis, optStatsSuffix, optTimeout,
+        optDisableInfer)
+
+  //TODO provide options for analyzing only selected functions
+  def run(ctx: LeonContext)(prog: Program): InferenceReport = {
+
+    //control printing of statistics
+    val dumpStats = true
+    var timeout: Int = 15
+
+    //defualt true flags
+    var modularlyAnalyze = true
+    var targettedUnroll = true
+
+    //default false flags
+    var tightBounds = false
+    var withmult = false
+    var inferTemp = false
+    var enumerationRelation: (Expr, Expr) => Expr = LessEquals
+    var useCegis = false
+    //var maxCegisBound = 200 //maximum bound for the constants in cegis
+    var maxCegisBound = 1000000000
+    var statsSuff = "-stats" + FileCountGUID.getID
+    var usereals = false
+    var autoInference = true
+
+    for (opt <- ctx.options) (opt.optionDef.name, opt.value) match {
+      case ("wholeprogram", true) => {
+        //do not do a modular analysis
+        modularlyAnalyze = false
+      }
+
+      case ("fullunroll", true) => {
+        //do not do a modular analysis
+        targettedUnroll = false
+      }
+
+      case ("minbounds", true) => {
+        tightBounds = true
+      }
+
+      case ("withmult", true) => {
+        withmult = true
+      }
+
+      case ("usereals", true) => {
+        usereals = true
+      }
+
+      case ("disableInfer", true) =>
+        autoInference = false
+
+      case ("inferTemp", true) => {
+        inferTemp = true
+        var foundStrongest = false
+        //go over all post-conditions and pick the strongest relation
+        prog.definedFunctions.foreach((fd) => {
+          if (!foundStrongest && fd.hasPostcondition) {
+            val cond = fd.postcondition.get
+            simplePostTransform((e) => e match {
+              case Equals(_, _) => {
+                enumerationRelation = Equals.apply _
+                foundStrongest = true
+                e
+              }
+              case _ => e
+            })(cond)
+          }
+        })
+      }
+
+      case ("cegis", true) => {
+        useCegis = true
+      }
+
+      case ("timeout", timeOut: Int) =>
+        timeout = timeOut
+
+      case ("stats-suffix", suffix: String) => {
+        statsSuff = suffix
+      }
+
+      case _ =>
+    }
+
+    val funToTmpl = prog.definedFunctions.collect {
+      case fd if fd.hasTemplate =>
+        fd -> fd.getTemplate
+    }.toMap
+    val qMarksRemovedProg = Util.assignTemplateAndCojoinPost(funToTmpl, prog, Map())
+
+    val newprog = if (usereals) {
+      (new IntToRealProgram())(qMarksRemovedProg)
+    } else qMarksRemovedProg
+    val nlelim = new NonlinearityEliminator(withmult, if (usereals) RealType else IntegerType)
+    val finalprog = nlelim(newprog)
+
+    val toVerifyPost = validateAndCollectNotValidated(qMarksRemovedProg, ctx, timeout)
+    //populate the inference context and invoke inferenceEngine
+    val inferctx = new InferenceContext(finalprog, toVerifyPost, ctx,
+      //multiplication operation
+      (e1, e2) => FunctionInvocation(TypedFunDef(nlelim.multFun, nlelim.multFun.tparams.map(_.tp)), Seq(e1, e2)),
+      enumerationRelation = LessEquals, modularlyAnalyze, targettedUnroll, autoInference,
+      dumpStats, tightBounds, withmult, usereals, inferTemp, useCegis, timeout, maxCegisBound, statsSuff)
+    (new InferenceEngine(inferctx)).run()
+  }
+
+  def createLeonContext(ctx: LeonContext, opts: String*): LeonContext = {
+    Main.processOptions(opts.toList).copy(reporter = ctx.reporter,
+      interruptManager = ctx.interruptManager, files = ctx.files, timers = ctx.timers)
+  }
+
+  def validateAndCollectNotValidated(prog: Program, ctx: LeonContext, timeout: Int): Set[String] = {
+    val verifyPipe = AnalysisPhase
+    val ctxWithTO = createLeonContext(ctx, "--timeout=" + timeout)
+    (verifyPipe.run(ctxWithTO)(prog)).results.collect{
+      case (VC(_, fd, VCKinds.Postcondition), Some(vcRes)) if vcRes.isInconclusive =>
+        fd.id.name
+      case (VC(_, fd, vcKind), Some(vcRes)) if vcRes.isInvalid =>
+        throw new IllegalStateException("Invalid" + vcKind + " for function " + fd.id.name)
+    }.toSet
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/engine/InferenceContext.scala b/src/main/scala/leon/invariant/engine/InferenceContext.scala
new file mode 100644
index 000000000..243cd5480
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/InferenceContext.scala
@@ -0,0 +1,31 @@
+package leon
+package invariant.engine
+
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala._
+
+/**
+ * @author ravi
+ */
+case class InferenceContext(
+  val program : Program,
+  val toVerifyPostFor: Set[String],
+  val leonContext : LeonContext,
+  val multOp: (Expr,Expr) => Expr,
+  val enumerationRelation : (Expr,Expr) => Expr,
+  val modularlyAnalyze : Boolean,
+  val targettedUnroll : Boolean,
+  val autoInference : Boolean,
+  val dumpStats : Boolean ,
+  val tightBounds : Boolean,
+  val withmult : Boolean,
+  val usereals : Boolean,
+  val inferTemp : Boolean,
+  val useCegis : Boolean,
+  val timeout: Int, //in secs
+  val maxCegisBound : Int,
+  val statsSuffix : String)  {
+
+  val reporter = leonContext.reporter
+}
diff --git a/src/main/scala/leon/invariant/engine/InferenceEngine.scala b/src/main/scala/leon/invariant/engine/InferenceEngine.scala
new file mode 100644
index 000000000..067eac087
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/InferenceEngine.scala
@@ -0,0 +1,179 @@
+package leon
+package invariant.engine
+
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import solvers._
+import java.io._
+import verification.VerificationReport
+import verification.VC
+import scala.util.control.Breaks._
+import invariant.templateSolvers._
+import invariant.factories._
+import invariant.util._
+import invariant.util.Util._
+import invariant.structure._
+import invariant.structure.FunctionUtils._
+import leon.invariant.factories.TemplateFactory
+
+/**
+ * @author ravi
+ * This phase performs automatic invariant inference.
+ * TODO: should time be implicitly made positive
+ */
+class InferenceEngine(ctx: InferenceContext) {
+
+  def run(): InferenceReport = {
+    val reporter = ctx.reporter
+    val program = ctx.program
+    reporter.info("Running Inference Engine...")
+
+    //register a shutdownhook
+    if (ctx.dumpStats) {
+      sys.ShutdownHookThread({ dumpStats(ctx.statsSuffix) })
+    }
+    val t1 = System.currentTimeMillis()
+    //compute functions to analyze by sorting based on topological order (this is an ascending topological order)
+    val callgraph = CallGraphUtil.constructCallGraph(program, withTemplates = true)
+    val functionsToAnalyze = if (ctx.modularlyAnalyze) {
+      callgraph.topologicalOrder
+    } else {
+      callgraph.topologicalOrder.reverse
+    }
+    //reporter.info("Analysis Order: " + functionsToAnalyze.map(_.id))
+    var results: Map[FunDef, InferenceCondition] = null
+    if (!ctx.useCegis) {
+      results = analyseProgram(functionsToAnalyze)
+      //println("Inferrence did not succeeded for functions: "+functionsToAnalyze.filterNot(succeededFuncs.contains _).map(_.id))
+    } else {
+      var remFuncs = functionsToAnalyze
+      var b = 200
+      var maxCegisBound = 200
+      breakable {
+        while (b <= maxCegisBound) {
+          Stats.updateCumStats(1, "CegisBoundsTried")
+          val succeededFuncs = analyseProgram(remFuncs)
+          remFuncs = remFuncs.filterNot(succeededFuncs.contains _)
+          if (remFuncs.isEmpty) break;
+          b += 5 //increase bounds in steps of 5
+        }
+        //println("Inferrence did not succeeded for functions: " + remFuncs.map(_.id))
+      }
+    }
+    val t2 = System.currentTimeMillis()
+    Stats.updateCumTime(t2 - t1, "TotalTime")
+    //dump stats
+    if (ctx.dumpStats) {
+      reporter.info("- Dumping statistics")
+      dumpStats(ctx.statsSuffix)
+    }
+    new InferenceReport(program, results.map(pair => {
+      val (fd, ic) = pair
+      (fd -> List[VC](ic))
+    }))(ctx)
+  }
+
+  def dumpStats(statsSuffix: String) = {
+    //pick the module id.
+    val modid = ctx.program.modules.last.id
+    val pw = new PrintWriter(modid + statsSuffix + ".txt")
+    Stats.dumpStats(pw)
+    SpecificStats.dumpOutputs(pw)
+    if (ctx.tightBounds) {
+      SpecificStats.dumpMinimizationStats(pw)
+    }
+  }
+
+  /**
+   * Returns map from analyzed functions to their inference conditions.
+   * TODO: use function names in inference conditions, so that
+   * we an get rid of dependence on origFd in many places.
+   */
+  def analyseProgram(functionsToAnalyze: Seq[FunDef]): Map[FunDef, InferenceCondition] = {
+    val reporter = ctx.reporter
+    val funToTmpl =
+      if (ctx.autoInference) {
+        //A template generator that generates templates for the functions (here we are generating templates by enumeration)
+        val tempFactory = new TemplateFactory(Some(new TemplateEnumerator(ctx)), ctx.program, ctx.reporter)
+        ctx.program.definedFunctions.map(fd => fd -> getOrCreateTemplateForFun(fd)).toMap
+      } else
+        ctx.program.definedFunctions.collect { case fd if fd.hasTemplate => fd -> fd.getTemplate }.toMap
+    val progWithTemplates = assignTemplateAndCojoinPost(funToTmpl, ctx.program)
+    var analyzedSet = Map[FunDef, InferenceCondition]()
+    functionsToAnalyze.filterNot((fd) => {
+      (fd.annotations contains "verified") ||
+        (fd.annotations contains "library") ||
+        (fd.annotations contains "theoryop")
+    }).foldLeft(progWithTemplates) { (prog, origFun) =>
+
+      val funDef = functionByName(origFun.id.name, prog).get
+      reporter.info("- considering function " + funDef.id.name + "...")
+
+      //skip the function if it has been analyzed
+      if (!analyzedSet.contains(origFun)) {
+        if (funDef.hasBody && funDef.hasPostcondition) {
+          val currCtx = ctx.copy(program = prog)
+          // for stats
+          Stats.updateCounter(1, "procs")
+          val solver =
+            if (funDef.annotations.contains("compose")) //compositional inference ?
+              new CompositionalTimeBoundSolver(currCtx, funDef)
+            else
+              new UnfoldingTemplateSolver(currCtx, funDef)
+          val t1 = System.currentTimeMillis()
+          val infRes = solver()
+          val funcTime = (System.currentTimeMillis() - t1) / 1000.0
+          infRes match {
+            case Some(InferResult(true, model, inferredFuns)) =>
+              val funsWithTemplates = inferredFuns.filter { fd =>
+                val origFd = Util.functionByName(fd.id.name, ctx.program).get
+                !analyzedSet.contains(origFd) && origFd.hasTemplate
+              }
+              // create a inference condition for reporting
+              var first = true
+              funsWithTemplates.foreach { fd =>
+                val origFd = Util.functionByName(fd.id.name, ctx.program).get
+                val inv = TemplateInstantiator.getAllInvariants(model.get,
+                  Map(origFd -> origFd.getTemplate))
+                // record the inferred invariants
+                val ic = new InferenceCondition(Some(inv(origFd)), fd)
+                ic.time = if (first) Some(funcTime) else Some(0.0)
+                // update analyzed set
+                analyzedSet += (origFd -> ic)
+                first = false
+              }
+              val invs = TemplateInstantiator.getAllInvariants(model.get,
+                funsWithTemplates.collect {
+                  case fd if fd.hasTemplate => fd -> fd.getTemplate
+                }.toMap)
+              if (ctx.modularlyAnalyze) {
+                // create a new program that has the inferred templates
+                val funToTmpl = prog.definedFunctions.collect {
+                  case fd if !invs.contains(fd) && fd.hasTemplate =>
+                    fd -> fd.getTemplate
+                }.toMap
+                assignTemplateAndCojoinPost(funToTmpl, prog, invs)
+              } else
+                prog
+            case _ =>
+              reporter.info("- Exhausted all templates, cannot infer invariants")
+              val ic = new InferenceCondition(None, origFun)
+              ic.time = Some(funcTime)
+              analyzedSet += (origFun -> ic)
+              prog
+          }
+        } else {
+          //nothing needs to be done here
+          reporter.info("Function does not have a body or postcondition")
+          prog
+        }
+      } else prog
+    }
+    analyzedSet
+  }
+}
diff --git a/src/main/scala/leon/invariant/engine/InferenceReport.scala b/src/main/scala/leon/invariant/engine/InferenceReport.scala
new file mode 100644
index 000000000..21756faac
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/InferenceReport.scala
@@ -0,0 +1,84 @@
+/* Copyright 2009-2013 EPFL, Lausanne */
+
+package leon
+package invariant.engine
+
+import purescala.Definitions.FunDef
+import verification._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Definitions._
+import purescala.Common._
+import invariant.templateSolvers._
+import invariant.factories._
+import invariant.util._
+import invariant.structure._
+import leon.transformations.InstUtil
+import leon.purescala.PrettyPrinter
+
+
+class InferenceCondition(val invariant: Option[Expr], funDef: FunDef)
+  extends VC(BooleanLiteral(true), funDef, null) {
+
+  var time : Option[Double] = None
+
+  def status: String = invariant match {
+    case None => "unknown"
+    case Some(inv) => {
+      val prettyInv = simplifyArithmetic(InstUtil.replaceInstruVars(Util.multToTimes(inv),fd))
+      PrettyPrinter(prettyInv)
+    }
+  }
+}
+
+class InferenceReport(p: Program, fvcs: Map[FunDef, List[VC]])(implicit ctx: InferenceContext)
+  extends VerificationReport(p : Program, Map()) {
+
+  import scala.math.Ordering.Implicits._
+  val conditions : Seq[InferenceCondition] =
+    fvcs.flatMap(_._2.map(_.asInstanceOf[InferenceCondition])).toSeq.sortBy(vc => vc.fd.id.name)
+
+  private def infoSep(size: Int)    : String = "╟" + ("┄" * size) + "╢\n"
+  private def infoFooter(size: Int) : String = "╚" + ("═" * size) + "╝"
+  private def infoHeader(size: Int) : String = ". ┌─────────┐\n" +
+                                          "╔═╡ Summary ╞" + ("═" * (size - 12)) + "╗\n" +
+                                          "║ └─────────┘" + (" " * (size - 12)) + "║"
+
+  private def infoLine(str: String, size: Int) : String = {
+    "║ "+ str + (" " * (size - str.size - 2)) + " ║"
+  }
+
+  private def fit(str : String, maxLength : Int) : String = {
+    if(str.length <= maxLength) {
+      str
+    } else {
+      str.substring(0, maxLength - 1) + "…"
+    }
+  }
+
+  private def funName(fd: FunDef)  = InstUtil.userFunctionName(fd)
+
+  override def summaryString : String = if(conditions.size > 0) {
+    val maxTempSize = (conditions.map(_.status.size).max + 3)
+    val outputStrs = conditions.map(vc => {
+      val timeStr = vc.time.map(t => "%-3.3f".format(t)).getOrElse("")
+      "%-15s %s %-4s".format(fit(funName(vc.fd), 15), vc.status + (" "*(maxTempSize-vc.status.size)), timeStr)
+    })
+    val summaryStr = {
+      val totalTime = conditions.foldLeft(0.0)((a, ic) => a + ic.time.getOrElse(0.0))
+      val inferredConds = conditions.count((ic) => ic.invariant.isDefined)
+      "total: %-4d  inferred: %-4d  unknown: %-4d  time: %-3.3f".format(
+        conditions.size, inferredConds, conditions.size - inferredConds, totalTime)
+    }
+    val entrySize = (outputStrs :+ summaryStr).map(_.size).max + 2
+
+    infoHeader(entrySize) +
+    outputStrs.map(str => infoLine(str, entrySize)).mkString("\n", "\n", "\n") +
+    infoSep(entrySize) +
+    infoLine(summaryStr, entrySize) + "\n" +
+    infoFooter(entrySize)
+
+  } else {
+    "No user provided templates were solved."
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/engine/RefinementEngine.scala b/src/main/scala/leon/invariant/engine/RefinementEngine.scala
new file mode 100644
index 000000000..cce8a3cb4
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/RefinementEngine.scala
@@ -0,0 +1,200 @@
+package leon
+package invariant.engine
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+
+import invariant.templateSolvers._
+import invariant.factories._
+import invariant.util._
+import invariant.util.Util._
+import invariant.structure._
+import FunctionUtils._
+
+//TODO: the parts of the code that collect the new head functions is ugly and has many side-effects. Fix this.
+//TODO: there is a better way to compute heads, which is to consider all guards not previous seen
+class RefinementEngine(ctx: InferenceContext, ctrTracker: ConstraintTracker) {
+
+  val tru = BooleanLiteral(true)
+  val reporter = ctx.reporter
+  val prog = ctx.program
+  val cg = CallGraphUtil.constructCallGraph(prog)
+
+  //this count indicates the number of times we unroll a recursive call
+  private val MAX_UNROLLS = 2
+
+  //debugging flags
+  private val dumpInlinedSummary = false
+
+  //print flags
+  val verbose = false
+
+  //the guards of disjuncts that were already processed
+  private var exploredGuards = Set[Variable]()
+
+  //a set of calls that have not been unrolled (these are potential unroll candidates)
+  //However, these calls except those given by the unspecdCalls have been assumed specifications
+  private var headCalls = Map[FunDef, Set[Call]]()
+  def getHeads(fd: FunDef) = if (headCalls.contains(fd)) headCalls(fd) else Set()
+  def resetHeads(fd: FunDef, heads: Set[Call]) = {
+    if (headCalls.contains(fd)) {
+      headCalls -= fd
+      headCalls += (fd -> heads)
+    } else {
+      headCalls += (fd -> heads)
+    }
+  }
+
+  /**
+   * This procedure refines the existing abstraction.
+   * Currently, the refinement happens by unrolling the head functions.
+   */
+  def refineAbstraction(toRefineCalls: Option[Set[Call]]): Set[Call] = {
+
+    ctrTracker.getFuncs.flatMap((fd) => {
+      val formula = ctrTracker.getVC(fd)
+      val disjuncts = formula.disjunctsInFormula
+      val newguards = formula.disjunctsInFormula.keySet.diff(exploredGuards)
+      exploredGuards ++= newguards
+
+      val newheads = newguards.flatMap(g => disjuncts(g).collect { case c: Call => c })
+      val allheads = getHeads(fd) ++ newheads
+
+      //unroll each call in the head pointers and in toRefineCalls
+      val callsToProcess = if (toRefineCalls.isDefined) {
+
+        //pick only those calls that have been least unrolled
+        val relevCalls = allheads.intersect(toRefineCalls.get)
+        var minCalls = Set[Call]()
+        var minUnrollings = MAX_UNROLLS
+        relevCalls.foreach((call) => {
+          val calldata = formula.callData(call)
+          val recInvokes = calldata.parents.count(_ == call.fi.tfd.fd)
+          if (recInvokes < minUnrollings) {
+            minUnrollings = recInvokes
+            minCalls = Set(call)
+          } else if (recInvokes == minUnrollings) {
+            minCalls += call
+          }
+        })
+        minCalls
+
+      } else allheads
+
+      if (verbose)
+        reporter.info("Unrolling: " + callsToProcess.size + "/" + allheads.size)
+
+      val unrolls = callsToProcess.foldLeft(Set[Call]())((acc, call) => {
+
+        val calldata = formula.callData(call)
+        val recInvokes = calldata.parents.count(_ == call.fi.tfd.fd)
+        //if the call is not a recursive call, unroll it unconditionally
+        if (recInvokes == 0) {
+          unrollCall(call, formula)
+          acc + call
+        } else {
+          //if the call is recursive, unroll iff the number of times the recursive function occurs in the context is < MAX-UNROLL
+          if (recInvokes < MAX_UNROLLS) {
+            unrollCall(call, formula)
+            acc + call
+          } else {
+            //otherwise, do not unroll the call
+            acc
+          }
+        }
+        //TODO: are there better ways of unrolling ??
+      })
+
+      //update the head functions
+      resetHeads(fd, allheads.diff(callsToProcess))
+      unrolls
+    }).toSet
+  }
+
+  def shouldCreateVC(recFun: FunDef): Boolean = {
+    if (ctrTracker.hasVC(recFun)) false
+    else {
+      //need not create vcs for theory operations
+      !recFun.isTheoryOperation && recFun.hasTemplate &&
+      	!recFun.annotations.contains("library")
+    }
+  }
+
+  /**
+   * Returns a set of unrolled calls and a set of new head functions
+   * here we unroll the methods in the current abstraction by one step.
+   * This procedure has side-effects on 'headCalls' and 'callDataMap'
+   */
+  def unrollCall(call: Call, formula: Formula) = {
+    val fi = call.fi
+    if (fi.tfd.fd.hasBody) {
+
+      //freshen the body and the post
+      val isRecursive = cg.isRecursive(fi.tfd.fd)
+      if (isRecursive) {
+        val recFun = fi.tfd.fd
+        val recFunTyped = fi.tfd
+
+        //check if we need to create a constraint tree for the call's target
+        if (shouldCreateVC(recFun)) {
+
+          //create a new verification condition for this recursive function
+          reporter.info("Creating VC for " + recFun.id)
+          val freshBody = freshenLocals(matchToIfThenElse(recFun.body.get))
+          val resvar = if (recFun.hasPostcondition) {
+            //create a new result variable here for the same reason as freshening the locals,
+            //which is to avoid variable capturing during unrolling
+            val origRes = getResId(recFun).get
+            Variable(FreshIdentifier(origRes.name, origRes.getType, true))
+          } else {
+            //create a new resvar
+            Variable(FreshIdentifier("res", recFun.returnType, true))
+          }
+          val plainBody = Equals(resvar, freshBody)
+          val bodyExpr = if (recFun.hasPrecondition) {
+            And(matchToIfThenElse(recFun.precondition.get), plainBody)
+          } else plainBody
+
+          //note: here we are only adding the template as the postcondition
+          val idmap = Util.formalToActual(Call(resvar, FunctionInvocation(recFunTyped, recFun.params.map(_.toVariable))))
+          val postTemp = replace(idmap, recFun.getTemplate)
+          val vcExpr = ExpressionTransformer.normalizeExpr(And(bodyExpr, Not(postTemp)), ctx.multOp)
+          ctrTracker.addVC(recFun, vcExpr)
+        }
+
+        //Here, unroll the call into the caller tree
+        if (verbose) reporter.info("Unrolling " + Equals(call.retexpr, call.fi))
+        inilineCall(call, formula)
+      } else {
+        //here we are unrolling a function without template
+        if (verbose) reporter.info("Unfolding " + Equals(call.retexpr, call.fi))
+        inilineCall(call, formula)
+      }
+    } else Set()
+  }
+
+  def inilineCall(call: Call, formula: Formula) = {
+    //here inline the body and conjoin it with the guard
+    val callee = call.fi.tfd.fd
+
+    //Important: make sure we use a fresh body expression here
+    val freshBody = freshenLocals(matchToIfThenElse(callee.body.get))
+    val calleeSummary =
+      Equals(Util.getFunctionReturnVariable(callee), freshBody)
+    val argmap1 = Util.formalToActual(call)
+    val inlinedSummary = ExpressionTransformer.normalizeExpr(replace(argmap1, calleeSummary), ctx.multOp)
+
+    if (this.dumpInlinedSummary)
+      println("Inlined Summary: " + inlinedSummary)
+
+    //conjoin the summary with the disjunct corresponding to the 'guard'
+    //note: the parents of the summary are the parents of the call plus the callee function
+    val calldata = formula.callData(call)
+    formula.conjoinWithDisjunct(calldata.guard, inlinedSummary, (callee +: calldata.parents))
+  }
+}
diff --git a/src/main/scala/leon/invariant/engine/SpecInstatiator.scala b/src/main/scala/leon/invariant/engine/SpecInstatiator.scala
new file mode 100644
index 000000000..9961df293
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/SpecInstatiator.scala
@@ -0,0 +1,270 @@
+package leon
+package invariant.engine
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import leon.invariant.templateSolvers.ExtendedUFSolver
+import invariant._
+import scala.util.control.Breaks._
+import solvers._
+import scala.concurrent._
+import scala.concurrent.duration._
+
+import invariant.templateSolvers._
+import invariant.factories._
+import invariant.util._
+import invariant.util.Util._
+import invariant.structure._
+import FunctionUtils._
+
+class SpecInstantiator(ctx: InferenceContext, ctrTracker: ConstraintTracker) {
+
+  val verbose = false
+
+  protected val disableAxioms = false
+  protected val debugAxiomInstantiation = false
+
+  val tru = BooleanLiteral(true)
+  val axiomFactory = new AxiomFactory(ctx) //handles instantiation of axiomatic specification
+  val program = ctx.program
+
+  //the guards of the set of calls that were already processed
+  protected var exploredGuards = Set[Variable]()
+
+  def instantiate() = {
+    val funcs = ctrTracker.getFuncs
+
+    funcs.foreach((fd) => {
+      val formula = ctrTracker.getVC(fd)
+      val disjuncts = formula.disjunctsInFormula
+      val newguards = disjuncts.keySet.diff(exploredGuards)
+      exploredGuards ++= newguards
+
+      val newcalls = newguards.flatMap(g => disjuncts(g).collect { case c: Call => c })
+      instantiateSpecs(formula, newcalls, funcs.toSet)
+
+      if (!disableAxioms) {
+        //remove all multiplication if "withmult" is specified
+        val relavantCalls = if (ctx.withmult) {
+          newcalls.filter(call => !Util.isMultFunctions(call.fi.tfd.fd))
+        } else newcalls
+        instantiateAxioms(formula, relavantCalls)
+      }
+    })
+  }
+
+  /**
+   * This function refines the formula by assuming the specifications/templates for calls in the formula
+   * Here, we assume (pre => post ^ template) for each call (templates only for calls with VC)
+   * Important: adding templates for 'newcalls' of the previous iterations is empirically more effective
+   */
+  //a set of calls for which templates or specifications have not been assumed
+  private var untemplatedCalls = Map[FunDef, Set[Call]]()
+  def getUntempCalls(fd: FunDef) = if (untemplatedCalls.contains(fd)) untemplatedCalls(fd) else Set()
+  def resetUntempCalls(fd: FunDef, calls: Set[Call]) = {
+    if (untemplatedCalls.contains(fd)) {
+      untemplatedCalls -= fd
+      untemplatedCalls += (fd -> calls)
+    } else {
+      untemplatedCalls += (fd -> calls)
+    }
+  }
+
+  def instantiateSpecs(formula: Formula, calls: Set[Call], funcsWithVC: Set[FunDef]) = {
+
+    //assume specifications
+    calls.foreach((call) => {
+      //first get the spec for the call if it exists
+      val spec = specForCall(call)
+      if (spec.isDefined && spec.get != tru) {
+        val cdata = formula.callData(call)
+        formula.conjoinWithDisjunct(cdata.guard, spec.get, cdata.parents)
+      }
+    })
+
+    //try to assume templates for all the current un-templated calls
+    var newUntemplatedCalls = Set[Call]()
+    getUntempCalls(formula.fd).foreach((call) => {
+      //first get the template for the call if one needs to be added
+      if (funcsWithVC.contains(call.fi.tfd.fd)) {
+        templateForCall(call) match {
+          case Some(temp) =>
+            val cdata = formula.callData(call)
+            formula.conjoinWithDisjunct(cdata.guard, temp, cdata.parents)
+          case _ =>
+            ; // here there is no template for the call
+        }
+      } else {
+        newUntemplatedCalls += call
+      }
+    })
+    resetUntempCalls(formula.fd, newUntemplatedCalls ++ calls)
+  }
+
+  def specForCall(call: Call): Option[Expr] = {
+    val argmap = Util.formalToActual(call)
+    val callee = call.fi.tfd.fd
+    if (callee.hasPostcondition) {
+      //get the postcondition without templates
+      val post = callee.getPostWoTemplate
+      val freshPost = freshenLocals(matchToIfThenElse(post))
+
+      val spec = if (callee.hasPrecondition) {
+        val freshPre = freshenLocals(matchToIfThenElse(callee.precondition.get))
+        Implies(freshPre, freshPost)
+      } else {
+        freshPost
+      }
+      val inlinedSpec = ExpressionTransformer.normalizeExpr(replace(argmap, spec), ctx.multOp)
+      Some(inlinedSpec)
+    } else {
+      None
+    }
+  }
+
+  def templateForCall(call: Call): Option[Expr] = {
+    val callee = call.fi.tfd.fd
+    if (callee.hasTemplate) {
+      val argmap = Util.formalToActual(call)
+      val tempExpr = replace(argmap, callee.getTemplate)
+      val template = if (callee.hasPrecondition) {
+        val freshPre = replace(argmap, freshenLocals(matchToIfThenElse(callee.precondition.get)))
+        Implies(freshPre, tempExpr)
+      } else {
+        tempExpr
+      }
+      //flatten functions
+      //TODO: should we freshen locals here ??
+      Some(ExpressionTransformer.normalizeExpr(template, ctx.multOp))
+    } else None
+  }
+
+  //axiomatic specification
+  protected var axiomRoots = Map[Seq[Call], Variable]() //a mapping from axioms keys (a sequence of calls) to the guards
+  def instantiateAxioms(formula: Formula, calls: Set[Call]) = {
+
+    val debugSolver = if (this.debugAxiomInstantiation) {
+      val sol = new ExtendedUFSolver(ctx.leonContext, program)
+      sol.assertCnstr(formula.toExpr)
+      Some(sol)
+    } else None
+
+    val inst1 = instantiateUnaryAxioms(formula, calls)
+    val inst2 = instantiateBinaryAxioms(formula, calls)
+    val axiomInsts = inst1 ++ inst2
+
+    Stats.updateCounterStats(Util.atomNum(Util.createAnd(axiomInsts)), "AxiomBlowup", "VC-refinement")
+    if(verbose) ctx.reporter.info("Number of axiom instances: " + axiomInsts.size)
+
+    if (this.debugAxiomInstantiation) {
+      println("Instantianting axioms over: " + calls)
+      println("Instantiated Axioms: ")
+      axiomInsts.foreach((ainst) => {
+        println(ainst)
+        debugSolver.get.assertCnstr(ainst)
+        val res = debugSolver.get.check
+        res match {
+          case Some(false) =>
+            println("adding axiom made formula unsat!!")
+          case _ => ;
+        }
+      })
+      debugSolver.get.free
+    }
+  }
+
+  //this code is similar to assuming specifications
+  def instantiateUnaryAxioms(formula: Formula, calls: Set[Call]) = {
+    val axioms = calls.collect {
+      case call @ _ if axiomFactory.hasUnaryAxiom(call) => {
+        val (ant, conseq) = axiomFactory.unaryAxiom(call)
+        val axiomInst = Implies(ant, conseq)
+        val nnfAxiom = ExpressionTransformer.normalizeExpr(axiomInst, ctx.multOp)
+        val cdata = formula.callData(call)
+        formula.conjoinWithDisjunct(cdata.guard, nnfAxiom, cdata.parents)
+        axiomInst
+      }
+    }
+    axioms.toSeq
+  }
+
+  /**
+   * Here, we assume that axioms do not introduce calls.
+   * If this does not hold, 'guards' have to be used while instantiating axioms so as
+   * to compute correct verification conditions.
+   * TODO: Use least common ancestor etc. to avoid axiomatizing calls along different disjuncts
+   * TODO: can we avoid axioms like (a <= b ^ x<=y => p <= q), (x <= y ^ a<=b => p <= q), ...
+   * TODO: can we have axiomatic specifications relating two different functions ?
+   */
+  protected var binaryAxiomCalls = Map[FunDef, Set[Call]]() //calls with axioms so far seen
+  def getBinaxCalls(fd: FunDef) = if (binaryAxiomCalls.contains(fd)) binaryAxiomCalls(fd) else Set[Call]()
+  def appendBinaxCalls(fd: FunDef, calls: Set[Call]) = {
+    if (binaryAxiomCalls.contains(fd)) {
+      val oldcalls = binaryAxiomCalls(fd)
+      binaryAxiomCalls -= fd
+      binaryAxiomCalls += (fd -> (oldcalls ++ calls))
+    } else {
+      binaryAxiomCalls += (fd -> calls)
+    }
+  }
+
+  def instantiateBinaryAxioms(formula: Formula, calls: Set[Call]) = {
+
+    val newCallsWithAxioms = calls.filter(axiomFactory.hasBinaryAxiom _)
+
+    def isInstantiable(call1: Call, call2: Call): Boolean = {
+      //important: check if the two calls refer to the same function
+      (call1.fi.tfd.id == call2.fi.tfd.id) && (call1 != call2)
+    }
+
+    val product = Util.cross[Call, Call](newCallsWithAxioms, getBinaxCalls(formula.fd), Some(isInstantiable)).flatMap(
+      p => Seq((p._1, p._2), (p._2, p._1))) ++
+      Util.cross[Call, Call](newCallsWithAxioms, newCallsWithAxioms, Some(isInstantiable)).map(p => (p._1, p._2))
+
+    //ctx.reporter.info("# of pairs with axioms: "+product.size)
+    //Stats.updateCumStats(product.size, "Call-pairs-with-axioms")
+
+    val addedAxioms = product.flatMap(pair => {
+      //union the parents of the two calls
+      val cdata1 = formula.callData(pair._1)
+      val cdata2 = formula.callData(pair._2)
+      val parents = cdata1.parents ++ cdata2.parents
+      val axiomInsts = axiomFactory.binaryAxiom(pair._1, pair._2)
+
+      axiomInsts.foldLeft(Seq[Expr]())((acc, inst) => {
+        val (ant, conseq) = inst
+        val axiom = Implies(ant, conseq)
+        val nnfAxiom = ExpressionTransformer.normalizeExpr(axiom, ctx.multOp)
+        val (axroot, _) = formula.conjoinWithRoot(nnfAxiom, parents)
+        //important: here we need to update the axiom roots
+        axiomRoots += (Seq(pair._1, pair._2) -> axroot)
+        acc :+ axiom
+      })
+    })
+    appendBinaxCalls(formula.fd, newCallsWithAxioms)
+    addedAxioms
+  }
+
+  /**
+   * Note: taking a formula as input may not be necessary. We can store it as a part of the state
+   * TODO: can we use transitivity here to optimize ?
+   */
+  def axiomsForCalls(formula: Formula, calls: Set[Call], model: Model): Seq[Constraint] = {
+    //note: unary axioms need not be instantiated
+    //consider only binary axioms
+    (for (x <- calls; y <- calls) yield (x, y)).foldLeft(Seq[Constraint]())((acc, pair) => {
+      val (c1, c2) = pair
+      if (c1 != c2) {
+        val axRoot = axiomRoots.get(Seq(c1, c2))
+        if (axRoot.isDefined)
+          acc ++ formula.pickSatDisjunct(axRoot.get, model)
+        else acc
+      } else acc
+    })
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/engine/TemplateEnumerator.scala b/src/main/scala/leon/invariant/engine/TemplateEnumerator.scala
new file mode 100644
index 000000000..17bfdee4b
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/TemplateEnumerator.scala
@@ -0,0 +1,195 @@
+package leon
+package invariant.engine
+
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import scala.collection.mutable.{ Set => MutableSet }
+import java.io._
+import scala.collection.mutable.{ Set => MutableSet }
+import scala.collection.mutable.{Set => MutableSet}
+
+import invariant.templateSolvers._
+import invariant.factories._
+import invariant.util._
+import invariant.structure._
+
+/**
+   * An enumeration based template generator.
+   * Enumerates all numerical terms in some order (this enumeration is incomplete for termination).
+   * TODO: Feature:
+   * (a) allow template functions and functions with template variables ?
+   * (b) should we unroll algebraic data types ?
+   *
+   * The following function may potentially have complexity O(n^i) where 'n' is the number of functions
+   * and 'i' is the increment step
+   * TODO: optimize the running and also reduce the size of the input templates
+   *
+   * For now this is incomplete
+   */
+class TemplateEnumerator(ctx: InferenceContext) extends TemplateGenerator {
+  val prog = ctx.program
+  val reporter = ctx.reporter
+
+    //create a call graph for the program
+    //Caution: this call-graph could be modified later while call the 'getNextTemplate' method
+    private val callGraph = {
+      val cg = CallGraphUtil.constructCallGraph(prog)
+      cg
+    }
+
+	private var tempEnumMap = Map[FunDef, FunctionTemplateEnumerator]()
+
+	def getNextTemplate(fd : FunDef) : Expr = {
+	  if(tempEnumMap.contains(fd)) tempEnumMap(fd).getNextTemplate()
+	  else {
+	    val enumerator = new FunctionTemplateEnumerator(fd, prog, ctx.enumerationRelation,  callGraph, reporter)
+	    tempEnumMap += (fd -> enumerator)
+	    enumerator.getNextTemplate()
+	  }
+	}
+}
+
+/**
+ * This class manages  templates for the given function
+ * 'op' is a side-effects parameter
+ * Caution: The methods of this class has side-effects on the 'callGraph' parameter
+ */
+class FunctionTemplateEnumerator(rootFun: FunDef, prog: Program, op: (Expr,Expr) => Expr,
+    callGraph : CallGraph,  reporter: Reporter) {
+  private val MAX_INCREMENTS = 2
+  private val zero = InfiniteIntegerLiteral(0)
+  //using default op as <= or == (manually adjusted)
+  //private val op = LessEquals
+    //LessThan
+    //LessEquals
+    //Equals.apply _
+  private var currTemp: Expr = null
+  private var incrStep: Int = 0
+  private var typeTermMap = Map[TypeTree, MutableSet[Expr]]()
+  private var ttCurrent = Map[TypeTree, MutableSet[Expr]]()
+
+  //get all functions that are not the current function.
+  //the value of the current function is given by res and its body
+  //itself characterizes how it is defined recursively w.r.t itself.
+  //Need to also avoid mutual recursion as it may lead to proving of invalid facts
+  private val fds = prog.definedFunctions.filter(_ != rootFun)
+
+  def getNextTemplate(): Expr = {
+    //println("Getting next template for function: "+fd.id)
+
+    if (incrStep == MAX_INCREMENTS){
+      //exhausted the templates, so return
+      op(currTemp, zero)
+    }
+    else {
+
+      incrStep += 1
+
+      var newTerms = Map[TypeTree, MutableSet[Expr]]()
+      if (currTemp == null) {
+        //initialize
+        //add all the arguments and results of fd to 'typeTermMap'
+        rootFun.params.foreach((vardecl) => {
+          val tpe = vardecl.getType
+          val v = vardecl.id.toVariable
+          if (newTerms.contains(tpe)) {
+            newTerms(tpe).add(v)
+          } else {
+            newTerms += (tpe -> MutableSet(v))
+          }
+        })
+
+        val resVar = Util.getFunctionReturnVariable(rootFun)
+        if (newTerms.contains(rootFun.returnType)) {
+          newTerms(rootFun.returnType).add(resVar)
+        } else {
+          newTerms += (rootFun.returnType -> MutableSet(resVar))
+        }
+
+        //also 'assignCurrTemp' to a template variable
+        currTemp = TemplateIdFactory.freshTemplateVar()
+      } else {
+
+        //apply the user-defined functions to the compatible terms in typeTermMap
+        //Important: Make sure that the recursive calls are not introduced in the templates
+        //TODO: this is a hack to prevent infinite recursion in specification. However, it is not clear if this will prevent inferrence of
+        //any legitimate specifications (however this can be modified).
+        fds.foreach((fun) => {
+          //Check if adding a call from 'rootFun' to 'fun' creates a mutual recursion by checking if
+          //'fun' transitively calls 'rootFun'
+          if (fun != rootFun && !callGraph.transitivelyCalls(fun, rootFun)) {
+
+            //check if every argument has at least one satisfying assignment?
+            if (fun.params.filter((vardecl) => !ttCurrent.contains(vardecl.getType)).isEmpty) {
+
+              //here compute all the combinations
+              val newcalls = generateFunctionCalls(fun)
+              if (newTerms.contains(fun.returnType)) {
+                newTerms(fun.returnType) ++= newcalls
+              } else {
+                var muset = MutableSet[Expr]()
+                muset ++= newcalls
+                newTerms += (fun.returnType -> muset)
+              }
+            }
+          }
+
+        })
+
+      }
+      //add all the newly generated expression to the typeTermMap
+      ttCurrent = newTerms
+      typeTermMap ++= newTerms
+
+      //statistics
+      reporter.info("- Number of new terms enumerated: " + newTerms.size)
+
+      //return all the integer valued terms of newTerms
+      //++ newTerms.getOrElse(Int32Type, Seq[Expr]()) (for now not handling int 32 terms)
+      val numericTerms = (newTerms.getOrElse(RealType, Seq[Expr]()) ++ newTerms.getOrElse(IntegerType, Seq[Expr]())).toSeq
+      if(!numericTerms.isEmpty) {
+        //create a linear combination of intTerms
+        val newTemp = numericTerms.foldLeft(null: Expr)((acc, t: Expr) => {
+          val summand = Times(t, TemplateIdFactory.freshTemplateVar() : Expr)
+          if (acc == null) summand
+          else
+            Plus(summand, acc)
+        })
+        //add newTemp to currTemp
+        currTemp = Plus(newTemp, currTemp)
+
+        //get all the calls in the 'newTemp' and add edges from 'rootFun' to the callees to the call-graph
+        val callees = CallGraphUtil.getCallees(newTemp)
+        callees.foreach(callGraph.addEdgeIfNotPresent(rootFun, _))
+      }
+      op(currTemp, zero)
+    }
+  }
+
+  /**
+   * Generate a set of function calls of fun using the terms in ttCurrent
+   */
+  def generateFunctionCalls(fun: FunDef): Set[Expr] = {
+    /**
+     * To be called with argIndex of zero and an empty argList
+     */
+    def genFunctionCallsRecur(argIndex: Int, argList: Seq[Expr]): Set[Expr] = {
+      if (argIndex == fun.params.size) {
+        //create a call using argList
+        //TODO: how should we handle generics
+        Set(FunctionInvocation(TypedFunDef(fun, fun.tparams.map(_.tp)), argList))
+      } else {
+        val arg = fun.params(argIndex)
+        val tpe = arg.getType
+        ttCurrent(tpe).foldLeft(Set[Expr]())((acc, term) => acc ++ genFunctionCallsRecur(argIndex + 1, argList :+ term))
+      }
+    }
+
+    genFunctionCallsRecur(0, Seq())
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/engine/UnfoldingTemplateSolver.scala b/src/main/scala/leon/invariant/engine/UnfoldingTemplateSolver.scala
new file mode 100644
index 000000000..a933be56a
--- /dev/null
+++ b/src/main/scala/leon/invariant/engine/UnfoldingTemplateSolver.scala
@@ -0,0 +1,259 @@
+package leon
+package invariant.engine
+
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import solvers._
+import solvers.z3.FairZ3Solver
+import java.io._
+import purescala.ScalaPrinter
+import verification._
+import scala.reflect.runtime.universe
+import invariant.templateSolvers._
+import invariant.factories._
+import invariant.util._
+import invariant.util.Util._
+import invariant.structure._
+import transformations._
+import FunctionUtils._
+import leon.invariant.templateSolvers.ExtendedUFSolver
+
+/**
+ * @author ravi
+ * This phase performs automatic invariant inference.
+ * TODO: Do we need to also assert that time is >= 0
+ */
+case class InferResult(res: Boolean, model: Option[Model], inferredFuncs: List[FunDef]) {
+}
+
+trait FunctionTemplateSolver {
+  def apply() : Option[InferResult]
+}
+
+class UnfoldingTemplateSolver(ctx: InferenceContext, rootFd: FunDef) extends FunctionTemplateSolver {
+
+  val reporter = ctx.reporter
+  val program = ctx.program
+  val debugVCs = false
+
+  lazy val constTracker = new ConstraintTracker(ctx, rootFd)
+  lazy val templateSolver = TemplateSolverFactory.createTemplateSolver(ctx, constTracker, rootFd)
+
+  def constructVC(funDef: FunDef): (Expr, Expr) = {
+    val body = funDef.body.get
+    val Lambda(Seq(ValDef(resid, _)), _) = funDef.postcondition.get
+    val resvar = resid.toVariable
+
+    val simpBody = matchToIfThenElse(body)
+    val plainBody = Equals(resvar, simpBody)
+    val bodyExpr = if (funDef.hasPrecondition) {
+      And(matchToIfThenElse(funDef.precondition.get), plainBody)
+    } else plainBody
+
+    val fullPost = matchToIfThenElse(if (funDef.hasTemplate)
+      if (ctx.toVerifyPostFor.contains(funDef.id.name))
+        And(funDef.getPostWoTemplate, funDef.getTemplate)
+      else
+        funDef.getTemplate
+    else
+      if (ctx.toVerifyPostFor.contains(funDef.id.name))
+        funDef.getPostWoTemplate
+      else
+        BooleanLiteral(true))
+
+    (bodyExpr, fullPost)
+  }
+
+  def solveParametricVC(vc: Expr) = {
+    val vcExpr = ExpressionTransformer.normalizeExpr(vc, ctx.multOp)
+    //for debugging
+    if (debugVCs) reporter.info("flattened VC: " + ScalaPrinter(vcExpr))
+
+    // initialize the constraint tracker
+    constTracker.addVC(rootFd, vcExpr)
+
+    var refinementStep: Int = 0
+    var toRefineCalls: Option[Set[Call]] = None
+    var infRes: Option[InferResult] = None
+    do {
+      Stats.updateCounter(1, "VC-refinement")
+      /* uncomment if we want to bound refinements
+       * if (refinementStep >= 5)
+          throw new IllegalStateException("Done 4 refinements")*/
+      val refined =
+        if (refinementStep >= 1) {
+          reporter.info("- More unrollings for invariant inference")
+
+          val toUnrollCalls = if (ctx.targettedUnroll) toRefineCalls else None
+          val unrolledCalls = constTracker.refineVCs(toUnrollCalls)
+          if (unrolledCalls.isEmpty) {
+            reporter.info("- Cannot do more unrollings, reached unroll bound")
+            false
+          } else true
+        } else {
+          constTracker.initialize
+          true
+        }
+      refinementStep += 1
+      infRes =
+        if (!refined)
+          Some(InferResult(false, None, List()))
+        else {
+          //solve for the templates in this unroll step
+          templateSolver.solveTemplates() match {
+            case (Some(model), callsInPath) =>
+              toRefineCalls = callsInPath
+              //Validate the model here
+              instantiateAndValidateModel(model, constTracker.getFuncs.toSeq)
+              Some(InferResult(true, Some(model),
+                constTracker.getFuncs.toList))
+            case (None, callsInPath) =>
+              toRefineCalls = callsInPath
+              //here, we do not know if the template is solvable or not, we need to do more unrollings.
+              None
+          }
+        }
+    } while (!infRes.isDefined)
+    infRes
+  }
+
+  def apply() = {
+    //create a body and post of the function
+    val (bodyExpr, fullPost) = constructVC(rootFd)
+    if (fullPost == tru)
+      Some(InferResult(true, Some(Model.empty), List()))
+    else
+      solveParametricVC(And(bodyExpr, Not(fullPost)))
+  }
+
+  def instantiateModel(model: Model, funcs: Seq[FunDef]) = {
+    funcs.collect {
+      case fd if fd.hasTemplate =>
+        fd -> fd.getTemplate
+    }.toMap
+  }
+
+  def instantiateAndValidateModel(model: Model, funcs: Seq[FunDef]) = {
+    val templates = instantiateModel(model, funcs)
+    val sols = TemplateInstantiator.getAllInvariants(model, templates)
+
+    var output = "Invariants for Function: " + rootFd.id + "\n"
+    sols foreach {
+      case (fd, inv) =>
+        val simpInv = simplifyArithmetic(InstUtil.replaceInstruVars(multToTimes(inv), fd))
+        reporter.info("- Found inductive invariant: " + fd.id + " --> " + ScalaPrinter(simpInv))
+        output += fd.id + " --> " + simpInv + "\n"
+    }
+    SpecificStats.addOutput(output)
+
+    reporter.info("- Verifying Invariants... ")
+    val verifierRes = verifyInvariant(sols)
+    val finalRes = verifierRes._1 match {
+      case Some(false) =>
+        reporter.info("- Invariant verified")
+        sols
+      case Some(true) =>
+        reporter.error("- Invalid invariant, model: " + verifierRes._2)
+        throw new IllegalStateException("")
+      case _ =>
+        //the solver timed out here
+        reporter.error("- Unable to prove or disprove invariant, the invariant is probably true")
+        sols
+    }
+    finalRes
+  }
+
+  /**
+   * This function creates a new program with each function postcondition strengthened by
+   * the inferred postcondition
+   */
+  def verifyInvariant(newposts: Map[FunDef, Expr]): (Option[Boolean], Model) = {
+    //create a fundef for each function in the program
+    //note: mult functions are also copied
+    val newFundefs = program.definedFunctions.collect {
+      case fd @ _ => { //if !Util.isMultFunctions(fd)
+        val newfd = new FunDef(FreshIdentifier(fd.id.name, Untyped, false),
+            fd.tparams, fd.returnType, fd.params)
+        (fd, newfd)
+      }
+    }.toMap
+    //note:  we are not replacing "mult" function by "Times"
+    val replaceFun = (e: Expr) => e match {
+      case fi @ FunctionInvocation(tfd1, args) if newFundefs.contains(tfd1.fd) =>
+        FunctionInvocation(TypedFunDef(newFundefs(tfd1.fd), tfd1.tps), args)
+      case _ => e
+    }
+    //create a body, pre, post for each newfundef
+    newFundefs.foreach((entry) => {
+      val (fd, newfd) = entry
+      //add a new precondition
+      newfd.precondition =
+        if (fd.precondition.isDefined)
+          Some(simplePostTransform(replaceFun)(fd.precondition.get))
+        else None
+
+      //add a new body
+      newfd.body = if (fd.hasBody)
+        Some(simplePostTransform(replaceFun)(fd.body.get))
+      else None
+
+      //add a new postcondition
+      val newpost = if (newposts.contains(fd)) {
+        val inv = newposts(fd)
+        if (fd.postcondition.isDefined) {
+          val Lambda(resultBinder, _) = fd.postcondition.get
+          Some(Lambda(resultBinder, And(fd.getPostWoTemplate, inv)))
+        } else {
+          //replace #res in the invariant by a new result variable
+          val resvar = FreshIdentifier("res", fd.returnType, true)
+          // FIXME: Is this correct (ResultVariable(fd.returnType) -> resvar.toVariable))
+          val ninv = replace(Map(ResultVariable(fd.returnType) -> resvar.toVariable), inv)
+          Some(Lambda(Seq(ValDef(resvar, Some(fd.returnType))), ninv))
+        }
+      } else if(fd.postcondition.isDefined) {
+        val Lambda(resultBinder, _) = fd.postcondition.get
+        Some(Lambda(resultBinder, fd.getPostWoTemplate))
+      } else None
+
+      newfd.postcondition = if (newpost.isDefined) {
+        val Lambda(resultBinder, pexpr) = newpost.get
+        // Some((resvar, simplePostTransform(replaceFun)(pexpr)))
+        Some(Lambda(resultBinder, simplePostTransform(replaceFun)(pexpr)))
+      } else None
+      newfd.addFlags(fd.flags)
+    })
+
+    val augmentedProg = Util.copyProgram(program, (defs: Seq[Definition]) => defs.collect {
+      case fd: FunDef if (newFundefs.contains(fd)) => newFundefs(fd)
+      case d if (!d.isInstanceOf[FunDef]) => d
+    })
+    //convert the program back to an integer program if necessary
+    val (newprog, newroot) = if (ctx.usereals) {
+      val realToIntconverter = new RealToIntProgram()
+      val intProg = realToIntconverter(augmentedProg)
+      (intProg, realToIntconverter.mappedFun(newFundefs(rootFd)))
+    } else {
+      (augmentedProg, newFundefs(rootFd))
+    }
+    //println("New Root: "+newroot)
+    import leon.solvers.z3._
+    val dummySolFactory = new leon.solvers.SolverFactory[ExtendedUFSolver] {
+      def getNewSolver() = new ExtendedUFSolver(ctx.leonContext, program)
+    }
+    val vericontext = VerificationContext(ctx.leonContext, newprog, dummySolFactory, reporter)
+    val defaultTactic = new DefaultTactic(vericontext)
+    val vc = defaultTactic.generatePostconditions(newroot)(0)
+
+    val verifyTimeout = 5
+    val fairZ3 = new SimpleSolverAPI(
+      new TimeoutSolverFactory(SolverFactory(() => new FairZ3Solver(ctx.leonContext, newprog) with TimeoutSolver),
+        verifyTimeout * 1000))
+    val sat = fairZ3.solveSAT(Not(vc.condition))
+    sat
+  }
+}
diff --git a/src/main/scala/leon/invariant/factories/AxiomFactory.scala b/src/main/scala/leon/invariant/factories/AxiomFactory.scala
new file mode 100644
index 000000000..27c7e44c7
--- /dev/null
+++ b/src/main/scala/leon/invariant/factories/AxiomFactory.scala
@@ -0,0 +1,100 @@
+package leon
+package invariant.factories
+
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import leon.invariant._
+import scala.util.control.Breaks._
+import scala.concurrent._
+import scala.concurrent.duration._
+
+import invariant.engine._
+import invariant.util._
+import invariant.structure._
+import FunctionUtils._
+
+class AxiomFactory(ctx : InferenceContext) {
+
+  val tru = BooleanLiteral(true)
+
+  //Add more axioms here, if necessary
+  def hasUnaryAxiom(call: Call) : Boolean = {
+    //important: here we need to avoid applying commutativity on the calls produced by axioms instantiation
+    call.fi.tfd.fd.isCommutative
+  }
+
+  def hasBinaryAxiom(call: Call) : Boolean = {
+    val callee = call.fi.tfd.fd
+    (callee.isMonotonic || callee.isDistributive)
+  }
+
+  def unaryAxiom(call: Call) : (Expr,Expr) = {
+    val callee = call.fi.tfd.fd
+    val tfd = call.fi.tfd
+
+    if(callee.isCommutative) {
+      //note: commutativity is defined only for binary operations
+      val Seq(a1, a2) = call.fi.args
+      val newret = TVarFactory.createTemp("cm").toVariable
+      val newfi = FunctionInvocation(tfd,Seq(a2,a1))
+      val newcall = Call(newret,newfi)
+      (tru, And(newcall.toExpr, Equals(newret, call.retexpr)))
+    } else
+      throw new IllegalStateException("Call does not have unary axiom: "+call)
+  }
+
+  def binaryAxiom(call1: Call, call2: Call): Seq[(Expr,Expr)] = {
+
+    if (call1.fi.tfd.id != call2.fi.tfd.id)
+      throw new IllegalStateException("Instantiating binary axiom on calls to different functions: " + call1 + "," + call2)
+
+    if (!hasBinaryAxiom(call1))
+      throw new IllegalStateException("Call does not have binary axiom: " + call1)
+
+    val callee = call1.fi.tfd.fd
+    //monotonicity
+    var axioms = if (callee.isMonotonic) {
+      Seq(monotonizeCalls(call1, call2))
+    } else Seq()
+
+    //distributivity
+    axioms ++= (if (callee.isDistributive) {
+      //println("Applying distributivity on: "+(call1,call2))
+      Seq(undistributeCalls(call1, call2))
+    } else Seq())
+
+    axioms
+  }
+
+  def monotonizeCalls(call1: Call, call2: Call): (Expr,Expr) = {
+    val ants = (call1.fi.args zip call2.fi.args).foldLeft(Seq[Expr]())((acc, pair) => {
+      val lesse = LessEquals(pair._1, pair._2)
+      lesse +: acc
+    })
+    val conseq = LessEquals(call1.retexpr, call2.retexpr)
+    (Util.createAnd(ants), conseq)
+  }
+
+  //this is applicable only to binary operations
+  def undistributeCalls(call1: Call, call2: Call): (Expr,Expr) = {
+    val fd = call1.fi.tfd.fd
+    val tfd = call1.fi.tfd
+
+    val Seq(a1,b1) = call1.fi.args
+    val Seq(a2,b2) = call2.fi.args
+    val r1 = call1.retexpr
+    val r2 = call2.retexpr
+
+    val dret1 = TVarFactory.createTemp("dt", IntegerType).toVariable
+    val dret2 = TVarFactory.createTemp("dt", IntegerType).toVariable
+    val dcall1 = Call(dret1, FunctionInvocation(tfd,Seq(a2,Plus(b1,b2))))
+    val dcall2 = Call(dret2, FunctionInvocation(tfd,Seq(Plus(a1,a2),b2)))
+    (LessEquals(b1,b2), And(LessEquals(Plus(r1,r2),dret2), dcall2.toExpr))
+  }
+}
diff --git a/src/main/scala/leon/invariant/factories/TemplateFactory.scala b/src/main/scala/leon/invariant/factories/TemplateFactory.scala
new file mode 100644
index 000000000..68080a79e
--- /dev/null
+++ b/src/main/scala/leon/invariant/factories/TemplateFactory.scala
@@ -0,0 +1,154 @@
+package leon
+package invariant.factories
+
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import scala.collection.mutable.{ Map => MutableMap }
+import invariant._
+import scala.collection.mutable.{Map => MutableMap}
+
+import invariant.engine._
+import invariant.util._
+import invariant.structure._
+import FunctionUtils._
+
+object TemplateIdFactory {
+  //a set of template ids
+  private var ids = Set[Identifier]()
+
+  def getTemplateIds : Set[Identifier] = ids
+
+  def freshIdentifier(name : String = "", idType: TypeTree = RealType) : Identifier = {
+    val idname = if(name.isEmpty()) "a?"
+    			 else name + "?"
+    val freshid = FreshIdentifier(idname, idType, true)
+    ids += freshid
+    freshid
+  }
+
+  def copyIdentifier(id: Identifier) : Identifier = {
+    val freshid = FreshIdentifier(id.name, RealType, false)
+    ids += freshid
+    freshid
+  }
+
+   /**
+   * Template variables have real type
+   */
+  def IsTemplateIdentifier(id : Identifier) : Boolean = {
+    ids.contains(id)
+  }
+
+  def IsTemplateVar(v : Variable) : Boolean = {
+    IsTemplateIdentifier(v.id)
+  }
+
+  def freshTemplateVar(name : String= "") : Variable = {
+    Variable(freshIdentifier(name))
+  }
+}
+
+trait TemplateGenerator {
+  def getNextTemplate(fd : FunDef): Expr
+}
+
+/**
+ * Templates are expressions with template variables.
+ * The program variables that can be free in the templates are only the arguments and
+ * the result variable.
+ * Note: the program logic depends on the mutability here.
+ */
+class TemplateFactory(tempGen : Option[TemplateGenerator], prog: Program, reporter : Reporter) {
+
+  //a mapping from function definition to the template
+  private var templateMap = {
+    //initialize the template map with predefined user maps
+    var muMap = MutableMap[FunDef, Expr]()
+    Util.functionsWOFields(prog.definedFunctions).foreach { fd =>
+      val tmpl = fd.template
+      if (tmpl.isDefined) {
+        muMap.update(fd, tmpl.get)
+      }
+    }
+    muMap
+  }
+
+  def setTemplate(fd:FunDef, tempExpr :Expr) = {
+    templateMap += (fd -> tempExpr)
+  }
+
+  /**
+   * This is the default template generator.
+   *
+   */
+  def getDefaultTemplate(fd : FunDef): Expr = {
+
+    //just consider all the arguments, return values that are integers
+    val baseTerms = fd.params.filter((vardecl) => Util.isNumericType(vardecl.getType)).map(_.toVariable) ++
+    					(if(Util.isNumericType(fd.returnType)) Seq(Util.getFunctionReturnVariable(fd))
+    					 else Seq())
+
+    val lhs = baseTerms.foldLeft(TemplateIdFactory.freshTemplateVar() : Expr)((acc, t)=> {
+       Plus(Times(TemplateIdFactory.freshTemplateVar(),t),acc)
+    })
+    val tempExpr = LessEquals(lhs,InfiniteIntegerLiteral(0))
+    tempExpr
+  }
+
+
+  /**
+   * Constructs a template using a mapping from the formals to actuals.
+   * Uses default template if a template does not exist for the function and no template generator is provided.
+   * Otherwise, use the provided template generator
+   */
+  var refinementSet = Set[FunDef]()
+  def constructTemplate(argmap: Map[Expr,Expr], fd: FunDef): Expr = {
+
+    //initialize the template for the function
+    if (!templateMap.contains(fd)) {
+      if(!tempGen.isDefined) templateMap += (fd -> getDefaultTemplate(fd))
+      else {
+    	templateMap += (fd -> tempGen.get.getNextTemplate(fd))
+    	refinementSet += fd
+    	//for information
+      	reporter.info("- Template generated for function "+fd.id+" : "+templateMap(fd))
+      }
+    }
+    replace(argmap,templateMap(fd))
+  }
+
+
+  /**
+   * Refines the templates of the functions that were assigned templates using the template generator.
+   */
+  def refineTemplates(): Boolean = {
+
+    if(tempGen.isDefined) {
+      var modifiedTemplate = false
+      refinementSet.foreach((fd) => {
+        val oldTemp = templateMap(fd)
+        val newTemp = tempGen.get.getNextTemplate(fd)
+
+        if (oldTemp != newTemp) {
+          modifiedTemplate = true
+          templateMap.update(fd, newTemp)
+          reporter.info("- New template for function " + fd.id + " : " + newTemp)
+        }
+      })
+      modifiedTemplate
+    } else false
+  }
+
+  def getTemplate(fd : FunDef) : Option[Expr] = {
+    templateMap.get(fd)
+  }
+
+  def getFunctionsWithTemplate : Seq[FunDef] = templateMap.keys.toSeq
+
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/factories/TemplateInstantiator.scala b/src/main/scala/leon/invariant/factories/TemplateInstantiator.scala
new file mode 100644
index 000000000..5944f68bd
--- /dev/null
+++ b/src/main/scala/leon/invariant/factories/TemplateInstantiator.scala
@@ -0,0 +1,134 @@
+package leon
+package invariant.factories
+
+import z3.scala._
+import purescala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import invariant.engine._
+import invariant.util._
+import invariant.structure._
+import leon.solvers.Model
+import leon.invariant.util.RealValuedExprEvaluator
+
+object TemplateInstantiator {
+    /**
+   * Computes the invariant for all the procedures given a mapping for the
+   * template variables.
+   * (Undone) If the mapping does not have a value for an id, then the id is bound to the simplest value
+   */
+  def getAllInvariants(model: Model, templates :Map[FunDef, Expr]): Map[FunDef, Expr] = {
+    val invs = templates.map((pair) => {
+      val (fd, t) = pair
+      //flatten the template
+      val freevars = variablesOf(t)
+      val template = ExpressionTransformer.FlattenFunction(t)
+
+      val tempvars = Util.getTemplateVars(template)
+      val tempVarMap: Map[Expr, Expr] = tempvars.map((v) => {
+        (v, model(v.id))
+      }).toMap
+
+      val instTemplate = instantiate(template, tempVarMap)
+      //now unflatten it
+      val comprTemp = ExpressionTransformer.unFlatten(instTemplate, freevars)
+      (fd, comprTemp)
+    })
+    invs
+  }
+
+  /**
+   * Instantiates templated subexpressions of the given expression (expr) using the given mapping for the template variables.
+   * The instantiation also takes care of converting the rational coefficients to integer coefficients.
+   */
+  def instantiate(expr: Expr, tempVarMap: Map[Expr, Expr]): Expr = {
+    //do a simple post transform and replace the template vars by their values
+    val inv = simplePostTransform((tempExpr: Expr) => tempExpr match {
+      case e @ Operator(Seq(lhs, rhs), op) if ((e.isInstanceOf[Equals] || e.isInstanceOf[LessThan]
+        || e.isInstanceOf[LessEquals] || e.isInstanceOf[GreaterThan]
+        || e.isInstanceOf[GreaterEquals])
+        &&
+        !Util.getTemplateVars(tempExpr).isEmpty) => {
+
+        //println("Template Expression: "+tempExpr)
+        val linearTemp = LinearConstraintUtil.exprToTemplate(tempExpr)
+        // println("MODEL\n" + tempVarMap)
+        instantiateTemplate(linearTemp, tempVarMap)
+      }
+      case _ => tempExpr
+    })(expr)
+    inv
+  }
+
+
+  def validateLiteral(e : Expr) = e match {
+    case FractionalLiteral(num, denom) => {
+      if (denom == 0)
+        throw new IllegalStateException("Denominator is zero !! " +e)
+      if (denom < 0)
+        throw new IllegalStateException("Denominator is negative: " + denom)
+      true
+    }
+    case IntLiteral(_) => true
+    case InfiniteIntegerLiteral(_) => true
+    case _ => throw new IllegalStateException("Not a real literal: " + e)
+  }
+
+  def instantiateTemplate(linearTemp: LinearTemplate, tempVarMap: Map[Expr, Expr]): Expr = {
+    val bigone = BigInt(1)
+    val coeffMap = linearTemp.coeffTemplate.map((entry) => {
+      val (term, coeffTemp) = entry
+      val coeffE = replace(tempVarMap, coeffTemp)
+      val coeff = RealValuedExprEvaluator.evaluate(coeffE)
+
+      validateLiteral(coeff)
+
+      (term -> coeff)
+    })
+    val const = if (linearTemp.constTemplate.isDefined){
+      val constE = replace(tempVarMap, linearTemp.constTemplate.get)
+      val constV = RealValuedExprEvaluator.evaluate(constE)
+
+      validateLiteral(constV)
+      Some(constV)
+    }
+    else None
+
+    val realValues: Seq[Expr] = coeffMap.values.toSeq ++ { if (const.isDefined) Seq(const.get) else Seq() }
+    //the coefficients could be fractions ,so collect all the denominators
+    val getDenom = (t: Expr) => t match {
+      case FractionalLiteral(num, denum) => denum
+      case _ => bigone
+    }
+
+    val denoms = realValues.foldLeft(Set[BigInt]())((acc, entry) => { acc + getDenom(entry) })
+
+    //compute the LCM of the denominators
+    val gcd = denoms.foldLeft(bigone)((acc, d) => acc.gcd(d))
+    val lcm = denoms.foldLeft(BigInt(1))((acc, d) => {
+      val product = (acc * d)
+      if(product % gcd == 0)
+        product/ gcd
+      else product
+    })
+
+    //scale the numerator by lcm
+    val scaleNum = (t: Expr) => t match {
+      case FractionalLiteral(num, denum) =>
+        InfiniteIntegerLiteral(num * (lcm / denum))
+      case InfiniteIntegerLiteral(n) =>
+        InfiniteIntegerLiteral(n * lcm)
+      case _ => throw new IllegalStateException("Coefficient not assigned to any value")
+    }
+    val intCoeffMap = coeffMap.map((entry) => (entry._1, scaleNum(entry._2)))
+    val intConst = if (const.isDefined) Some(scaleNum(const.get)) else None
+
+    val linearCtr = new LinearConstraint(linearTemp.op, intCoeffMap, intConst)
+    linearCtr.toExpr
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/factories/TemplateSolverFactory.scala b/src/main/scala/leon/invariant/factories/TemplateSolverFactory.scala
new file mode 100644
index 000000000..25abefa22
--- /dev/null
+++ b/src/main/scala/leon/invariant/factories/TemplateSolverFactory.scala
@@ -0,0 +1,44 @@
+package leon
+package invariant.factories
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import invariant._
+import invariant.engine._
+import invariant.util._
+import invariant.structure._
+import FunctionUtils._
+import templateSolvers._
+import leon.solvers.Model
+
+object TemplateSolverFactory {
+
+  def createTemplateSolver(ctx: InferenceContext, ctrack: ConstraintTracker, rootFun: FunDef,
+    // options to solvers
+    minopt: Option[(Expr, Model) => Model] = None,
+    bound: Option[Int] = None): TemplateSolver = {
+    if (ctx.useCegis) {
+      // TODO: find a better way to specify CEGIS total time bound
+      new CegisSolver(ctx, rootFun, ctrack, 10000, bound)
+    } else {
+      val minimizer = if (ctx.tightBounds && rootFun.hasTemplate) {
+        if (minopt.isDefined)
+          minopt
+        else {
+          //TODO: need to assert that the templates are resource templates
+          Some((new Minimizer(ctx)).tightenTimeBounds(rootFun.getTemplate) _)
+        }
+      } else
+        None
+      if (ctx.withmult) {
+        new NLTemplateSolverWithMult(ctx, rootFun, ctrack, minimizer)
+      } else {
+        new NLTemplateSolver(ctx, rootFun, ctrack, minimizer)
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/structure/Constraint.scala b/src/main/scala/leon/invariant/structure/Constraint.scala
new file mode 100644
index 000000000..2a6e32ce4
--- /dev/null
+++ b/src/main/scala/leon/invariant/structure/Constraint.scala
@@ -0,0 +1,272 @@
+package leon
+package invariant.structure
+
+import z3.scala._
+import purescala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import solvers.{ Solver, TimeoutSolver }
+import solvers.z3.FairZ3Solver
+import scala.collection.mutable.{ Set => MutableSet }
+import scala.collection.mutable.{ Map => MutableMap }
+import evaluators._
+import java.io._
+import solvers.z3.UninterpretedZ3Solver
+import invariant.util._
+
+trait Constraint {
+  def toExpr: Expr
+}
+/**
+ * Class representing linear templates which is a constraint of the form
+ * a1*v1 + a2*v2 + .. + an*vn + a0 <= 0 or = 0 or < 0 where ai's are unknown coefficients
+ * which could be any arbitrary expression with template variables as free variables
+ * and vi's are variables.
+ * Note: we need atleast one coefficient or one constant to be defined.
+ * Otherwise a NPE will be thrown (in the computation of 'template')
+ */
+class LinearTemplate(oper: Seq[Expr] => Expr,
+  coeffTemp: Map[Expr, Expr],
+  constTemp: Option[Expr]) extends Constraint {
+
+  val zero = InfiniteIntegerLiteral(0)
+
+  val op = {
+    oper
+  }
+  val coeffTemplate = {
+    //assert if the coefficients are templated expressions
+    assert(coeffTemp.values.foldLeft(true)((acc, e) => {
+      acc && Util.isTemplateExpr(e)
+    }))
+
+    //print the template mapping
+    /*println("Coeff Mapping: "+coeffTemp)
+    println("Constant: "+constTemplate)*/
+    coeffTemp
+  }
+
+  val constTemplate = {
+    assert(constTemp match {
+      case None => true
+      case Some(e) => Util.isTemplateExpr(e)
+    })
+    constTemp
+  }
+
+  val template = {
+    //construct the expression corresponding to the template here
+    var lhs = coeffTemp.foldLeft(null: Expr)((acc, entry) => {
+      val (term, coeff) = entry
+      val minterm = Times(coeff, term)
+      if (acc == null) minterm else Plus(acc, minterm)
+    })
+    lhs = if (constTemp.isDefined) {
+      if (lhs == null) constTemp.get
+      else Plus(lhs, constTemp.get)
+    } else lhs
+    val expr = oper(Seq(lhs, zero))
+    //assert(expr.isInstanceOf[Equals] || expr.isInstanceOf[LessThan] || expr.isInstanceOf[GreaterThan]
+    //  || expr.isInstanceOf[LessEquals] || expr.isInstanceOf[GreaterEquals])
+    expr
+  }
+
+  def templateVars: Set[Variable] = {
+    Util.getTemplateVars(template)
+  }
+
+  def coeffEntryToString(coeffEntry: (Expr, Expr)): String = {
+    val (e, i) = coeffEntry
+    i match {
+      case InfiniteIntegerLiteral(x) if (x == 1) => e.toString
+      case InfiniteIntegerLiteral(x) if (x == -1) => "-" + e.toString
+      case InfiniteIntegerLiteral(v) => v + e.toString
+      case IntLiteral(1) => e.toString
+      case IntLiteral(-1) => "-" + e.toString
+      case IntLiteral(v) => v + e.toString
+      case _ => i + " * " + e.toString
+    }
+  }
+
+  override def toExpr: Expr = template
+
+  override def toString(): String = {
+
+    val coeffStr = if (coeffTemplate.isEmpty) ""
+    else {
+      val (head :: tail) = coeffTemplate.toList
+      tail.foldLeft(coeffEntryToString(head))((str, pair) => {
+
+        val termStr = coeffEntryToString(pair)
+        (str + " + " + termStr)
+      })
+    }
+    val constStr = if (constTemplate.isDefined) constTemplate.get.toString else ""
+    val str = if (!coeffStr.isEmpty() && !constStr.isEmpty()) coeffStr + " + " + constStr
+    else coeffStr + constStr
+    str + (template match {
+      case t: Equals => " = "
+      case t: LessThan => " < "
+      case t: GreaterThan => " > "
+      case t: LessEquals => " <= "
+      case t: GreaterEquals => " >= "
+    }) + "0"
+  }
+
+  override def hashCode(): Int = {
+    template.hashCode()
+  }
+
+  override def equals(obj: Any): Boolean = obj match {
+    case lit: LinearTemplate => {
+      if (!lit.template.equals(this.template)) {
+        //println(lit.template + " and " + this.template+ " are not equal ")
+        false
+      } else true
+    }
+    case _ => false
+  }
+}
+
+/**
+ * class representing a linear constraint. This is a linear template wherein the coefficients are constants
+ */
+class LinearConstraint(opr: Seq[Expr] => Expr, cMap: Map[Expr, Expr], constant: Option[Expr])
+  extends LinearTemplate(opr, cMap, constant) {
+
+  val coeffMap = {
+    //assert if the coefficients are only constant expressions
+    assert(cMap.values.foldLeft(true)((acc, e) => {
+      acc && variablesOf(e).isEmpty
+    }))
+
+    //TODO: here we should try to simplify the constant expressions
+    cMap
+  }
+
+  val const = constant.map((c) => {
+    //check if constant does not have any variables
+    assert(variablesOf(c).isEmpty)
+    c
+  })
+}
+
+case class BoolConstraint(e: Expr) extends Constraint {
+  val expr = {
+    assert(e match {
+      case Variable(_) => true
+      case Not(Variable(_)) => true
+      case t: BooleanLiteral => true
+      case Not(t: BooleanLiteral) => true
+      case _ => false
+    })
+    e
+  }
+
+  override def toString(): String = {
+    expr.toString
+  }
+
+  def toExpr: Expr = expr
+}
+
+object ADTConstraint {
+
+  def apply(e: Expr): ADTConstraint = e match {
+
+    //is this a tuple or case class select ?
+    // case Equals(Variable(_), CaseClassSelector(_, _, _)) | Iff(Variable(_), CaseClassSelector(_, _, _)) => {
+    case Equals(Variable(_), CaseClassSelector(_, _, _)) => {
+      val ccExpr = ExpressionTransformer.classSelToCons(e)
+      new ADTConstraint(ccExpr, Some(ccExpr))
+    }
+    // case Equals(Variable(_),TupleSelect(_,_)) | Iff(Variable(_),TupleSelect(_,_)) => {
+    case Equals(Variable(_), TupleSelect(_, _)) => {
+      val tpExpr = ExpressionTransformer.tupleSelToCons(e)
+      new ADTConstraint(tpExpr, Some(tpExpr))
+    }
+    //is this a tuple or case class def ?
+    case Equals(Variable(_), CaseClass(_, _)) | Equals(Variable(_), Tuple(_)) => {
+      new ADTConstraint(e, Some(e))
+    }
+    //is this an instanceOf ?
+    case Equals(v @ Variable(_), ci @ IsInstanceOf(_, _)) => {
+      new ADTConstraint(e, None, Some(e))
+    }
+    // considering asInstanceOf as equalities
+    case Equals(lhs @ Variable(_), ci @ AsInstanceOf(rhs @ Variable(_), _)) => {
+      val eq = Equals(lhs, rhs)
+      new ADTConstraint(eq, None, None, Some(eq))
+    }
+    //equals and disequalities betweeen variables
+    case Equals(lhs @ Variable(_), rhs @ Variable(_)) if (lhs.getType != Int32Type && lhs.getType != RealType && lhs.getType != IntegerType) => {
+      new ADTConstraint(e, None, None, Some(e))
+    }
+    case Not(Equals(lhs @ Variable(_), rhs @ Variable(_))) if (lhs.getType != Int32Type && lhs.getType != RealType && lhs.getType != IntegerType) => {
+      new ADTConstraint(e, None, None, Some(e))
+    }
+    case _ => {
+      throw new IllegalStateException("Expression not an ADT constraint: " + e)
+    }
+  }
+}
+
+class ADTConstraint(val expr: Expr,
+  val cons: Option[Expr] = None,
+  val inst: Option[Expr] = None,
+  val comp: Option[Expr] = None) extends Constraint {
+
+  override def toString(): String = {
+    expr.toString
+  }
+
+  override def toExpr = expr
+}
+
+case class Call(retexpr: Expr, fi: FunctionInvocation) extends Constraint {
+  val expr = Equals(retexpr, fi)
+
+  override def toExpr = expr
+}
+
+object ConstraintUtil {
+
+  def createConstriant(ie: Expr): Constraint = {
+    ie match {
+      case Variable(_) | Not(Variable(_)) | BooleanLiteral(_) | Not(BooleanLiteral(_)) => BoolConstraint(ie)
+      case Equals(v @ Variable(_), fi @ FunctionInvocation(_, _)) => Call(v, fi)
+      case Equals(Variable(_), CaseClassSelector(_, _, _))
+        | Equals(Variable(_), CaseClass(_, _))
+        | Equals(Variable(_), TupleSelect(_, _))
+        | Equals(Variable(_), Tuple(_))
+        | Equals(Variable(_), IsInstanceOf(_, _)) => {
+
+        ADTConstraint(ie)
+      }
+      case Equals(lhs, rhs) if (lhs.getType != Int32Type && lhs.getType != RealType && lhs.getType != IntegerType) => {
+        //println("ADT constraint: "+ie)
+        ADTConstraint(ie)
+      }
+      case Not(Equals(lhs, rhs)) if (lhs.getType != Int32Type && lhs.getType != RealType && lhs.getType != IntegerType) => {
+        ADTConstraint(ie)
+      }
+      case _ => {
+        val simpe = simplifyArithmetic(ie)
+        simpe match {
+          case b: BooleanLiteral => BoolConstraint(b)
+          case _ => {
+            val template = LinearConstraintUtil.exprToTemplate(ie)
+            LinearConstraintUtil.evaluate(template) match {
+              case Some(v) => BoolConstraint(BooleanLiteral(v))
+              case _ => template
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/main/scala/leon/invariant/structure/Formula.scala b/src/main/scala/leon/invariant/structure/Formula.scala
new file mode 100644
index 000000000..0fedbc705
--- /dev/null
+++ b/src/main/scala/leon/invariant/structure/Formula.scala
@@ -0,0 +1,281 @@
+package leon
+package invariant.structure
+
+import z3.scala._
+import purescala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import solvers.{ Solver, TimeoutSolver }
+import solvers.z3.FairZ3Solver
+import java.io._
+import solvers.z3._
+import invariant.engine._
+import invariant.util._
+import leon.solvers.Model
+
+/**
+ * Data associated with a call
+ */
+class CallData(val guard : Variable, val parents: List[FunDef]) {
+}
+
+/**
+ * Representation of an expression as a set of implications.
+ * 'initexpr' is required to be in negation normal form and And/Ors have been pulled up
+ * TODO: optimize the representation so that we use fewer guards.
+ */
+class Formula(val fd: FunDef, initexpr: Expr, ctx: InferenceContext) {
+
+  val fls = BooleanLiteral(false)
+  val tru = BooleanLiteral(true)
+  val useImplies = false
+
+  val combiningOp = if(useImplies) Implies.apply _ else Equals.apply _
+  protected var disjuncts = Map[Variable, Seq[Constraint]]() //a mapping from guards to conjunction of atoms
+  protected var conjuncts = Map[Variable, Expr]() //a mapping from guards to disjunction of atoms
+  private var callDataMap = Map[Call, CallData]() //a mapping from a 'call' to the 'guard' guarding the call plus the list of transitive callers of 'call'
+
+  val firstRoot : Variable = addConstraints(initexpr, List(fd))._1
+  protected var roots : Seq[Variable] = Seq(firstRoot) //a list of roots, the formula is a conjunction of formula of each root
+
+  def disjunctsInFormula = disjuncts
+
+  def callData(call: Call) : CallData = callDataMap(call)
+
+  //return the root variable and the sequence of disjunct guards added
+  //(which includes the root variable incase it respresents a disjunct)
+  def addConstraints(ine: Expr, callParents : List[FunDef]) : (Variable, Seq[Variable]) = {
+
+    var newDisjGuards = Seq[Variable]()
+
+    def getCtrsFromExprs(guard: Variable, exprs: Seq[Expr]) : Seq[Constraint] = {
+      var break = false
+      exprs.foldLeft(Seq[Constraint]())((acc, e) => {
+        if (break) acc
+        else {
+          val ctr = ConstraintUtil.createConstriant(e)
+          ctr match {
+            case BoolConstraint(BooleanLiteral(true)) => acc
+            case BoolConstraint(BooleanLiteral(false)) => {
+              break = true
+              Seq(ctr)
+            }
+            case call@Call(_,_) => {
+
+              if(callParents.isEmpty)
+                throw new IllegalArgumentException("Parent not specified for call: "+ctr)
+              else {
+                callDataMap += (call -> new CallData(guard, callParents))
+              }
+              acc :+ call
+            }
+            case _ => acc :+ ctr
+          }
+        }
+      })
+    }
+
+    val f1 = simplePostTransform((e: Expr) => e match {
+      case Or(args) => {
+        val newargs = args.map(arg => arg match {
+          case v: Variable if (disjuncts.contains(v)) => arg
+          case v: Variable if (conjuncts.contains(v)) => throw new IllegalStateException("or gaurd inside conjunct: "+e+" or-guard: "+v)
+          case _ => {
+            val atoms = arg  match {
+              case And(atms) => atms
+              case _ => Seq(arg)
+            }
+            val g = TVarFactory.createTemp("b", BooleanType).toVariable
+            newDisjGuards :+= g
+            //println("atoms: "+atoms)
+            val ctrs = getCtrsFromExprs(g, atoms)
+            disjuncts += (g -> ctrs)
+            g
+          }
+        })
+        //create a temporary for Or
+        val gor = TVarFactory.createTemp("b", BooleanType).toVariable
+        val newor = Util.createOr(newargs)
+        conjuncts += (gor -> newor)
+        gor
+      }
+      case And(args) => {
+        val newargs = args.map(arg => if (Util.getTemplateVars(e).isEmpty) {
+          arg
+        } else {
+          //if the expression has template variables then we separate it using guards
+          val g = TVarFactory.createTemp("b", BooleanType).toVariable
+          newDisjGuards :+= g
+          val ctrs = getCtrsFromExprs(g, Seq(arg))
+          disjuncts += (g -> ctrs)
+          g
+        })
+        Util.createAnd(newargs)
+      }
+      case _ => e
+    })(ExpressionTransformer.simplify(simplifyArithmetic(
+        //TODO: this is a hack as of now. Fix this.
+        //Note: it is necessary to convert real literals to integers since the linear constraint cannot handle real literals
+        if(ctx.usereals) ExpressionTransformer.FractionalLiteralToInt(ine)
+        else ine
+        )))
+
+    val rootvar = f1 match {
+      case v: Variable if(conjuncts.contains(v)) => v
+      case v: Variable if(disjuncts.contains(v)) => throw new IllegalStateException("f1 is a disjunct guard: "+v)
+      case _ => {
+        val atoms = f1 match {
+          case And(atms) => atms
+          case _ => Seq(f1)
+        }
+        val g = TVarFactory.createTemp("b", BooleanType).toVariable
+        val ctrs = getCtrsFromExprs(g, atoms)
+        newDisjGuards :+= g
+        disjuncts += (g -> ctrs)
+        g
+      }
+    }
+    (rootvar, newDisjGuards)
+  }
+
+  //'satGuard' is required to a guard variable
+  def pickSatDisjunct(startGaurd : Variable, model: Model): Seq[Constraint] = {
+
+    def traverseOrs(gd: Variable, model: Model): Seq[Variable] = {
+      val e @ Or(guards) = conjuncts(gd)
+      //pick one guard that is true
+      val guard = guards.collectFirst { case g @ Variable(id) if (model(id) == tru) => g }
+      if (!guard.isDefined)
+        throw new IllegalStateException("No satisfiable guard found: " + e)
+      guard.get +: traverseAnds(guard.get, model)
+    }
+
+    def traverseAnds(gd: Variable, model: Model): Seq[Variable] = {
+      val ctrs = disjuncts(gd)
+      val guards = ctrs.collect {
+        case BoolConstraint(v @ Variable(_)) if (conjuncts.contains(v) || disjuncts.contains(v)) => v
+      }
+      if (guards.isEmpty) Seq()
+      else {
+        guards.foldLeft(Seq[Variable]())((acc, g) => {
+          if (model(g.id) != tru)
+            throw new IllegalStateException("Not a satisfiable guard: " + g)
+
+          if (conjuncts.contains(g))
+            acc ++ traverseOrs(g, model)
+          else {
+            acc ++ (g +: traverseAnds(g, model))
+          }
+        })
+      }
+    }
+    //if startGuard is unsat return empty
+    if (model(startGaurd.id) == fls) Seq()
+    else {
+      val satGuards = if (conjuncts.contains(startGaurd)) traverseOrs(startGaurd, model)
+      else (startGaurd +: traverseAnds(startGaurd, model))
+      satGuards.flatMap(g => disjuncts(g))
+    }
+  }
+
+  /**
+   * 'neweexpr' is required to be in negation normal form and And/Ors have been pulled up
+   */
+  def conjoinWithDisjunct(guard: Variable, newexpr: Expr, callParents: List[FunDef]) : (Variable, Seq[Variable]) = {
+     val (exprRoot, newGaurds) = addConstraints(newexpr, callParents)
+     //add 'newguard' in conjunction with 'disjuncts(guard)'
+     val ctrs = disjuncts(guard)
+     disjuncts -= guard
+     disjuncts += (guard -> (BoolConstraint(exprRoot) +: ctrs))
+     (exprRoot, newGaurds)
+  }
+
+  def conjoinWithRoot(newexpr: Expr, callParents: List[FunDef]): (Variable, Seq[Variable]) = {
+    val (exprRoot, newGaurds) = addConstraints(newexpr, callParents)
+    roots :+= exprRoot
+    (exprRoot, newGaurds)
+  }
+
+  /**
+   * The first return value is param part and the second one is the
+   * non-parametric part
+   */
+  def splitParamPart : (Expr, Expr) = {
+    var paramPart = Seq[Expr]()
+    var rest = Seq[Expr]()
+    disjuncts.foreach(entry => {
+      val (g,ctrs) = entry
+      val ctrExpr = combiningOp(g,Util.createAnd(ctrs.map(_.toExpr)))
+      if(Util.getTemplateVars(ctrExpr).isEmpty)
+        rest :+= ctrExpr
+      else
+        paramPart :+= ctrExpr
+
+    })
+    val conjs = conjuncts.map((entry) => combiningOp(entry._1, entry._2)).toSeq ++ roots
+    (Util.createAnd(paramPart), Util.createAnd(rest ++ conjs ++ roots))
+  }
+
+  def toExpr : Expr={
+    val disjs = disjuncts.map((entry) => {
+      val (g,ctrs) = entry
+      combiningOp(g, Util.createAnd(ctrs.map(_.toExpr)))
+    }).toSeq
+    val conjs = conjuncts.map((entry) => combiningOp(entry._1, entry._2)).toSeq
+    Util.createAnd(disjs ++ conjs ++ roots)
+  }
+
+  //unpack the disjunct and conjuncts by removing all guards
+  def unpackedExpr : Expr = {
+    //replace all conjunct guards in disjuncts by their mapping
+    val disjs : Map[Expr,Expr] = disjuncts.map((entry) => {
+      val (g,ctrs) = entry
+      val newctrs = ctrs.map(_ match {
+        case BoolConstraint(g@Variable(_)) if conjuncts.contains(g) => conjuncts(g)
+        case ctr@_ => ctr.toExpr
+      })
+      (g, Util.createAnd(newctrs))
+    })
+    val rootexprs = roots.map(_ match {
+        case g@Variable(_) if conjuncts.contains(g) => conjuncts(g)
+        case e@_ => e
+      })
+    //replace every guard in the 'disjs' by its disjunct. DO this as long as every guard is replaced in every disjunct
+    var unpackedDisjs = disjs
+    var replacedGuard = true
+    //var removeGuards = Seq[Variable]()
+    while(replacedGuard) {
+      replacedGuard = false
+
+      val newDisjs = unpackedDisjs.map(entry => {
+        val (g,d) = entry
+        val guards = variablesOf(d).collect{ case id@_ if disjuncts.contains(id.toVariable) => id.toVariable }
+        if (guards.isEmpty) entry
+        else {
+          /*println("Disunct: "+d)
+          println("guard replaced: "+guards)*/
+          replacedGuard = true
+          //removeGuards ++= guards
+          (g, replace(unpackedDisjs, d))
+        }
+      })
+      unpackedDisjs = newDisjs
+    }
+    //replace all the 'guards' in root using 'unpackedDisjs'
+    replace(unpackedDisjs, Util.createAnd(rootexprs))
+  }
+
+  override def toString : String = {
+    val disjStrs = disjuncts.map((entry) => {
+      val (g,ctrs) = entry
+      simplifyArithmetic(combiningOp(g, Util.createAnd(ctrs.map(_.toExpr)))).toString
+    }).toSeq
+    val conjStrs = conjuncts.map((entry) => combiningOp(entry._1, entry._2).toString).toSeq
+    val rootStrs = roots.map(_.toString)
+    (disjStrs ++ conjStrs ++ rootStrs).foldLeft("")((acc,str) => acc + "\n" + str)
+  }
+}
diff --git a/src/main/scala/leon/invariant/structure/FunctionUtils.scala b/src/main/scala/leon/invariant/structure/FunctionUtils.scala
new file mode 100644
index 000000000..9bdc6692c
--- /dev/null
+++ b/src/main/scala/leon/invariant/structure/FunctionUtils.scala
@@ -0,0 +1,158 @@
+package leon
+package invariant.structure
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import invariant.factories._
+import invariant.util._
+import Util._
+import scala.language.implicitConversions
+
+/**
+ * Some utiliy methods for functions.
+ * This also does caching to improve performance.
+ */
+object FunctionUtils {
+
+  class FunctionInfo(fd: FunDef) {
+    //flags
+    lazy val isTheoryOperation = fd.annotations.contains("theoryop")
+    lazy val isMonotonic = fd.annotations.contains("monotonic")
+    lazy val isCommutative = fd.annotations.contains("commutative")
+    lazy val isDistributive = fd.annotations.contains("distributive")
+    lazy val compose = fd.annotations.contains("compose")
+
+    //the template function
+    lazy val tmplFunctionName = "tmpl"
+    /**
+     * checks if the function name is 'tmpl' and there is only one argument
+     * if not, type checker would anyway throw an error if leon.invariant._ is included
+     */
+    def isTemplateInvocation(finv: Expr) = {
+      finv match {
+        case FunctionInvocation(funInv, args) =>
+          (funInv.id.name == "tmpl" && funInv.returnType == BooleanType &&
+            args.size == 1 && args(0).isInstanceOf[Lambda])
+        case _ =>
+          false
+      }
+    }
+
+    def isQMark(e: Expr) = e match {
+      case FunctionInvocation(TypedFunDef(fd, Seq()), args) =>
+        (fd.id.name == "?" && fd.returnType == IntegerType &&
+          args.size <= 1)
+      case _ => false
+    }
+
+    def extractTemplateFromLambda(tempLambda: Lambda): Expr = {
+      val Lambda(vdefs, body) = tempLambda
+      val vars = vdefs.map(_.id.toVariable)
+      val tempVars = vars.map { // reuse template variables if possible
+        case v if TemplateIdFactory.IsTemplateIdentifier(v.id) => v
+        case v =>
+          TemplateIdFactory.freshIdentifier(v.id.name).toVariable
+      }
+      val repmap = (vars zip tempVars).toMap[Expr, Expr]
+      replace(repmap, body)
+    }
+
+    def tmplFunction(paramTypes: Seq[TypeTree]) = {
+      val lambdaType = FunctionType(paramTypes, BooleanType)
+      val paramid = FreshIdentifier("lamb", lambdaType)
+      new FunDef(FreshIdentifier("tmpl", BooleanType), Seq(), BooleanType, Seq(ValDef(paramid)))
+    }
+
+    /**
+     * Repackages '?' mark expression into tmpl functions
+     */
+    def qmarksToTmplFunction(ine: Expr) = {
+      var tempIds = Seq[Identifier]()
+      var indexToId = Map[BigInt, Identifier]()
+      val lambBody = simplePostTransform {
+        case q @ FunctionInvocation(_, Seq()) if isQMark(q) => // question mark with zero args
+          val freshid = TemplateIdFactory.freshIdentifier("q")
+          tempIds :+= freshid
+          freshid.toVariable
+
+        case q @ FunctionInvocation(_, Seq(InfiniteIntegerLiteral(index))) if isQMark(q) => //question mark with one arg
+          indexToId.getOrElse(index, {
+            val freshid = TemplateIdFactory.freshIdentifier("q" + index)
+            tempIds :+= freshid
+            indexToId += (index -> freshid)
+            freshid
+          }).toVariable
+
+        case other => other
+      }(ine)
+      FunctionInvocation(TypedFunDef(tmplFunction(tempIds.map(_.getType)), Seq()),
+        Seq(Lambda(tempIds.map(id => ValDef(id)), lambBody)))
+    }
+
+    /**
+     * Does not support mixing of tmpl exprs and '?'.
+     * Need to check that tmpl functions are not nested.
+     */
+    lazy val (postWoTemplate, templateExpr) = {
+      if (fd.postcondition.isDefined) {
+        val Lambda(_, postBody) = fd.postcondition.get
+        // collect all terms with question marks and convert them to a template
+        val postWoQmarks = postBody match {
+          case And(args) if args.exists(exists(isQMark) _) =>
+            val (tempExprs, otherPreds) = args.partition {
+              case a if exists(isQMark)(a) => true
+              case _ => false
+            }
+            //println(s"Otherpreds: $otherPreds ${qmarksToTmplFunction(Util.createAnd(tempExprs))}")
+            Util.createAnd(otherPreds :+ qmarksToTmplFunction(Util.createAnd(tempExprs)))
+          case pb if exists(isQMark)(pb) =>
+            qmarksToTmplFunction(pb)
+          case other => other
+        }
+        //the 'body' could be a template or 'And(pred, template)'
+        postWoQmarks match {
+          case finv @ FunctionInvocation(_, args) if isTemplateInvocation(finv) =>
+            (None, Some(finv))
+          case And(args) if args.exists(isTemplateInvocation) =>
+            val (tempFuns, otherPreds) = args.partition {
+              case a if isTemplateInvocation(a) => true
+              case _ => false
+            }
+            if (tempFuns.size > 1) {
+              throw new IllegalStateException("Multiple template functions used in the postcondition: " + postBody)
+            } else {
+              val rest = if (otherPreds.size <= 1) otherPreds(0) else And(otherPreds)
+              (Some(rest), Some(tempFuns(0).asInstanceOf[FunctionInvocation]))
+            }
+          case pb =>
+            (Some(pb), None)
+        }
+      } else {
+        (None, None)
+      }
+    }
+
+    lazy val template = templateExpr map (finv => extractTemplateFromLambda(finv.args(0).asInstanceOf[Lambda]))
+
+    def hasTemplate: Boolean = templateExpr.isDefined
+    def getPostWoTemplate = postWoTemplate match {
+      case None => tru
+      case Some(expr) => expr
+    }
+    def getTemplate = template.get
+  }
+
+  // a cache for function infos
+  private var functionInfos = Map[FunDef, FunctionInfo]()
+  implicit def funDefToFunctionInfo(fd: FunDef): FunctionInfo = {
+    functionInfos.getOrElse(fd, {
+      val info = new FunctionInfo(fd)
+      functionInfos += (fd -> info)
+      info
+    })
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/structure/LinearConstraintUtil.scala b/src/main/scala/leon/invariant/structure/LinearConstraintUtil.scala
new file mode 100644
index 000000000..102c2a088
--- /dev/null
+++ b/src/main/scala/leon/invariant/structure/LinearConstraintUtil.scala
@@ -0,0 +1,489 @@
+package leon
+package invariant.structure
+
+import purescala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import scala.collection.mutable.{ Set => MutableSet }
+import scala.collection.mutable.{ Map => MutableMap }
+import java.io._
+import invariant.util._
+import BigInt._
+import Constructors._
+
+class NotImplementedException(message: String) extends RuntimeException(message) {
+
+}
+
+//a collections of utility methods that manipulate the templates
+object LinearConstraintUtil {
+  val zero = InfiniteIntegerLiteral(0)
+  val one = InfiniteIntegerLiteral(1)
+  val mone = InfiniteIntegerLiteral(-1)
+  val tru = BooleanLiteral(true)
+  val fls = BooleanLiteral(false)
+
+  //some utility methods
+  def getFIs(ctr: LinearConstraint): Set[FunctionInvocation] = {
+    val fis = ctr.coeffMap.keys.collect((e) => e match {
+      case fi: FunctionInvocation => fi
+    })
+    fis.toSet
+  }
+
+  def evaluate(lt: LinearTemplate): Option[Boolean] = lt match {
+    case lc: LinearConstraint if (lc.coeffMap.size == 0) =>
+      ExpressionTransformer.simplify(lt.toExpr) match {
+        case BooleanLiteral(v) => Some(v)
+        case _ => None
+      }
+    case _ => None
+  }
+
+   /**
+   * the expression 'Expr' is required to be a linear atomic predicate (or a template),
+   * if not, an exception would be thrown.
+   * For now some of the constructs are not handled.
+   * The function returns a linear template or a linear constraint depending
+   * on whether the expression has template variables or not
+   */
+  def exprToTemplate(expr: Expr): LinearTemplate = {
+
+    //println("Expr: "+expr)
+    //these are the result values
+    var coeffMap = MutableMap[Expr, Expr]()
+    var constant: Option[Expr] = None
+    var isTemplate : Boolean = false
+
+    def addCoefficient(term: Expr, coeff: Expr) = {
+      if (coeffMap.contains(term)) {
+        val value = coeffMap(term)
+        val newcoeff = simplifyArithmetic(Plus(value, coeff))
+
+        //if newcoeff becomes zero remove it from the coeffMap
+        if(newcoeff == zero) {
+          coeffMap.remove(term)
+        } else{
+          coeffMap.update(term, newcoeff)
+        }
+      } else coeffMap += (term -> simplifyArithmetic(coeff))
+
+      if (!variablesOf(coeff).isEmpty) {
+        isTemplate = true
+      }
+    }
+
+    def addConstant(coeff: Expr) ={
+      if (constant.isDefined) {
+        val value = constant.get
+        constant = Some(simplifyArithmetic(Plus(value, coeff)))
+      } else
+        constant = Some(simplifyArithmetic(coeff))
+
+      if (!variablesOf(coeff).isEmpty) {
+        isTemplate = true
+      }
+    }
+
+    //recurse into plus and get all minterms
+    def getMinTerms(lexpr: Expr): Seq[Expr] = lexpr match {
+      case Plus(e1, e2) => getMinTerms(e1) ++ getMinTerms(e2)
+      case _ => Seq(lexpr)
+    }
+
+    val linearExpr = MakeLinear(expr)
+    //the top most operator should be a relation
+    val Operator(Seq(lhs, InfiniteIntegerLiteral(x)), op) = linearExpr
+    /*if (lhs.isInstanceOf[InfiniteIntegerLiteral])
+      throw new IllegalStateException("relation on two integers, not in canonical form: " + linearExpr)*/
+
+    val minterms =  getMinTerms(lhs)
+
+    //handle each minterm
+    minterms.foreach((minterm: Expr) => minterm match {
+      case _ if (Util.isTemplateExpr(minterm)) => {
+        addConstant(minterm)
+      }
+      case Times(e1, e2) => {
+        e2 match {
+          case Variable(_) => ;
+          case ResultVariable(_) => ;
+          case FunctionInvocation(_, _) => ;
+          case _ => throw new IllegalStateException("Multiplicand not a constraint variable: " + e2)
+        }
+        e1 match {
+          //case c @ InfiniteIntegerLiteral(_) => addCoefficient(e2, c)
+          case _ if (Util.isTemplateExpr(e1)) => {
+            addCoefficient(e2, e1)
+          }
+          case _ => throw new IllegalStateException("Coefficient not a constant or template expression: " + e1)
+        }
+      }
+      case Variable(_) => {
+        //here the coefficient is 1
+        addCoefficient(minterm, one)
+      }
+      case ResultVariable(_) => {
+        addCoefficient(minterm, one)
+      }
+      case _ => throw new IllegalStateException("Unhandled min term: " + minterm)
+    })
+
+    if(coeffMap.isEmpty && constant.isEmpty) {
+      //here the generated template the constant term is zero.
+      new LinearConstraint(op, Map.empty, Some(zero))
+    } else if(isTemplate) {
+      new LinearTemplate(op, coeffMap.toMap, constant)
+    } else{
+      new LinearConstraint(op, coeffMap.toMap,constant)
+    }
+  }
+
+  /**
+   * This method may have to do all sorts of transformation to make the expressions linear constraints.
+   * This assumes that the input expression is an atomic predicate (i.e, without and, or and nots)
+   * This is subjected to constant modification.
+   */
+  def MakeLinear(atom: Expr): Expr = {
+
+    //pushes the minus inside the arithmetic terms
+    //we assume that inExpr is in linear form
+    def PushMinus(inExpr: Expr): Expr = {
+      inExpr match {
+        case IntLiteral(v) => IntLiteral(-v)
+        case InfiniteIntegerLiteral(v) => InfiniteIntegerLiteral(-v)
+        case t: Terminal => Times(mone, t)
+        case fi @ FunctionInvocation(fdef, args) => Times(mone, fi)
+        case UMinus(e1) => e1
+        case RealUMinus(e1) => e1
+        case Minus(e1, e2) => Plus(PushMinus(e1), e2)
+        case RealMinus(e1, e2) => Plus(PushMinus(e1), e2)
+        case Plus(e1, e2) => Plus(PushMinus(e1), PushMinus(e2))
+        case RealPlus(e1, e2) => Plus(PushMinus(e1), PushMinus(e2))
+        case Times(e1, e2) => {
+          //here push the minus in to the coefficient which is the first argument
+          Times(PushMinus(e1), e2)
+        }
+        case RealTimes(e1, e2) => Times(PushMinus(e1), e2)
+        case _ => throw new NotImplementedException("PushMinus -- Operators not yet handled: " + inExpr)
+      }
+    }
+
+    //we assume that ine is in linear form
+    def PushTimes(mul: Expr, ine: Expr): Expr = {
+      ine match {
+        case t: Terminal => Times(mul, t)
+        case fi @ FunctionInvocation(fdef, args) => Times(mul, fi)
+        case Plus(e1, e2) => Plus(PushTimes(mul, e1), PushTimes(mul, e2))
+        case RealPlus(e1, e2) => Plus(PushTimes(mul, e1), PushTimes(mul, e2))
+        case Times(e1, e2) => {
+          //here push the times into the coefficient which should be the first expression
+          Times(PushTimes(mul, e1), e2)
+        }
+        case RealTimes(e1, e2) => Times(PushTimes(mul, e1), e2)
+        case _ => throw new NotImplementedException("PushTimes -- Operators not yet handled: " + ine)
+      }
+    }
+
+    //collect all the constants in addition and simplify them
+    //we assume that ine is in linear form and also that all constants are integers
+    def simplifyConsts(ine: Expr): (Option[Expr], BigInt) = {
+      ine match {
+        case IntLiteral(v) => (None, v)
+        case InfiniteIntegerLiteral(v) => (None, v)
+        case Plus(e1, e2) => {
+          val (r1, c1) = simplifyConsts(e1)
+          val (r2, c2) = simplifyConsts(e2)
+
+          val newe = (r1, r2) match {
+            case (None, None) => None
+            case (Some(t), None) => Some(t)
+            case (None, Some(t)) => Some(t)
+            case (Some(t1), Some(t2)) => Some(Plus(t1, t2))
+          }
+          (newe, c1 + c2)
+        }
+        case _ => (Some(ine), 0)
+      }
+    }
+
+    def mkLinearRecur(inExpr: Expr): Expr = {
+      inExpr match {
+        case e @ Operator(Seq(e1, e2), op)
+        if ((e.isInstanceOf[Equals] || e.isInstanceOf[LessThan]
+            || e.isInstanceOf[LessEquals] || e.isInstanceOf[GreaterThan]
+            || e.isInstanceOf[GreaterEquals])) => {
+
+          //check if the expression has real valued sub-expressions
+          val isReal = Util.hasReals(e1) || Util.hasReals(e2)
+          //doing something else ... ?
+    		  // println("[DEBUG] Expr 1 " + e1 + " of type " + e1.getType + " and Expr 2 " + e2 + " of type" + e2.getType)
+          val (newe, newop) = e match {
+            case t: Equals => (Minus(e1, e2), Equals)
+            case t: LessEquals => (Minus(e1, e2), LessEquals)
+            case t: GreaterEquals => (Minus(e2, e1), LessEquals)
+            case t: LessThan => {
+              if (isReal)
+                (Minus(e1, e2), LessThan)
+              else
+                (Plus(Minus(e1, e2), one), LessEquals)
+            }
+            case t: GreaterThan => {
+              if(isReal)
+                 (Minus(e2,e1),LessThan)
+              else
+            	 (Plus(Minus(e2, e1), one), LessEquals)
+            }
+          }
+          val r = mkLinearRecur(newe)
+          //simplify the resulting constants
+          val (r2, const) = simplifyConsts(r)
+          val finale = if (r2.isDefined) {
+            if (const != 0) Plus(r2.get, InfiniteIntegerLiteral(const))
+            else r2.get
+          } else InfiniteIntegerLiteral(const)
+          //println(r + " simplifies to "+finale)
+          newop(finale, zero)
+        }
+        case Minus(e1, e2) => Plus(mkLinearRecur(e1), PushMinus(mkLinearRecur(e2)))
+        case RealMinus(e1, e2) => RealPlus(mkLinearRecur(e1), PushMinus(mkLinearRecur(e2)))
+        case UMinus(e1) => PushMinus(mkLinearRecur(e1))
+        case RealUMinus(e1) => PushMinus(mkLinearRecur(e1))
+        case Times(_, _) | RealTimes(_, _) => {
+          val Operator(Seq(e1, e2), op) = inExpr
+          val (r1, r2) = (mkLinearRecur(e1), mkLinearRecur(e2))
+          if(Util.isTemplateExpr(r1)) {
+            PushTimes(r1, r2)
+          } else if(Util.isTemplateExpr(r2)){
+            PushTimes(r2, r1)
+          } else
+            throw new IllegalStateException("Expression not linear: " + Times(r1, r2))
+        }
+        case Plus(e1, e2) => Plus(mkLinearRecur(e1), mkLinearRecur(e2))
+        case RealPlus(e1, e2) => RealPlus(mkLinearRecur(e1), mkLinearRecur(e2))
+        case t: Terminal => t
+        case fi: FunctionInvocation => fi
+        case _ => throw new IllegalStateException("Expression not linear: " + inExpr)
+      }
+    }
+    val rese = mkLinearRecur(atom)
+    rese
+  }
+
+  /**
+   * Replaces an expression by another expression in the terms of the given linear constraint.
+   */
+  def replaceInCtr(replaceMap: Map[Expr, Expr], lc: LinearConstraint): Option[LinearConstraint] = {
+
+    //println("Replacing in "+lc+" repMap: "+replaceMap)
+    val newexpr = ExpressionTransformer.simplify(simplifyArithmetic(replace(replaceMap, lc.toExpr)))
+    //println("new expression: "+newexpr)
+    if (newexpr == tru) None
+    else if(newexpr == fls) throw new IllegalStateException("!!Constraint reduced to false during elimination: " + lc)
+    else {
+      val res = exprToTemplate(newexpr)
+      //check if res is true or false
+      evaluate(res) match {
+        case Some(false) => throw new IllegalStateException("!!Constraint reduced to false during elimination: " + lc)
+        case Some(true) => None //constraint reduced to true
+        case _ =>
+          val resctr = res.asInstanceOf[LinearConstraint]
+          Some(resctr)
+      }
+    }
+  }
+
+    /**
+   * Eliminates the specified variables from a conjunction of linear constraints (a disjunct) (that is satisfiable)
+   * We assume that the disjunct is in nnf form
+   *
+   * debugger is a function used for debugging
+   */
+  val debugElimination = false
+  def apply1PRuleOnDisjunct(linearCtrs: Seq[LinearConstraint], elimVars: Set[Identifier],
+      debugger: Option[(Seq[LinearConstraint] => Unit)]): Seq[LinearConstraint] = {
+    //eliminate one variable at a time
+    //each iteration produces a new set of linear constraints
+    elimVars.foldLeft(linearCtrs)((acc, elimVar) => {
+      val newdisj = apply1PRuleOnDisjunct(acc, elimVar)
+
+      if(debugElimination) {
+        if(debugger.isDefined) {
+          debugger.get(newdisj)
+        }
+      }
+
+      newdisj
+    })
+  }
+
+  def apply1PRuleOnDisjunct(linearCtrs: Seq[LinearConstraint], elimVar: Identifier): Seq[LinearConstraint] = {
+
+    if(debugElimination)
+      println("Trying to eliminate: "+elimVar)
+
+    //collect all relevant constraints
+    val emptySeq = Seq[LinearConstraint]()
+    val (relCtrs, rest) = linearCtrs.foldLeft((emptySeq,emptySeq))((acc,lc) => {
+      if(variablesOf(lc.toExpr).contains(elimVar)) {
+        (lc +: acc._1,acc._2)
+      } else {
+        (acc._1,lc +: acc._2)
+      }
+    })
+
+    //now consider each constraint look for (a) equality involving the elimVar or (b) check if all bounds are lower
+    //or (c) if all bounds are upper.
+    var elimExpr : Option[Expr] = None
+    var bestExpr = false
+    var elimCtr : Option[LinearConstraint] = None
+    var allUpperBounds : Boolean = true
+    var allLowerBounds : Boolean = true
+    var foundEquality : Boolean = false
+    var skippingEquality : Boolean = false
+
+    relCtrs.foreach((lc) => {
+      //check for an equality
+      if (lc.toExpr.isInstanceOf[Equals] && lc.coeffMap.contains(elimVar.toVariable)) {
+        foundEquality = true
+
+        //here, sometimes we replace an existing expression with a better one if available
+        if (!elimExpr.isDefined || shouldReplace(elimExpr.get, lc, elimVar)) {
+          //if the coeffcient of elimVar is +ve the the sign of the coeff of every other term should be changed
+          val InfiniteIntegerLiteral(elimCoeff) = lc.coeffMap(elimVar.toVariable)
+          //make sure the value of the coefficient is 1 or  -1
+          //TODO: handle cases wherein the coefficient is not 1 or -1
+          if (elimCoeff == 1 || elimCoeff == -1) {
+            val changeSign = if (elimCoeff > 0) true else false
+
+            val startval = if (lc.const.isDefined) {
+              val InfiniteIntegerLiteral(cval) = lc.const.get
+              val newconst = if (changeSign) -cval else cval
+              InfiniteIntegerLiteral(newconst)
+
+            } else zero
+
+            val substExpr = lc.coeffMap.foldLeft(startval: Expr)((acc, summand) => {
+              val (term, InfiniteIntegerLiteral(coeff)) = summand
+              if (term != elimVar.toVariable) {
+
+                val newcoeff = if (changeSign) -coeff else coeff
+                val newsummand = if (newcoeff == 1) term else Times(term, InfiniteIntegerLiteral(newcoeff))
+                if (acc == zero) newsummand
+                else Plus(acc, newsummand)
+
+              } else acc
+            })
+
+            elimExpr = Some(simplifyArithmetic(substExpr))
+            elimCtr = Some(lc)
+
+            if (debugElimination) {
+              println("Using ctr: " + lc + " found mapping: " + elimVar + " --> " + substExpr)
+            }
+          } else {
+            skippingEquality = true
+          }
+        }
+      } else if ((lc.toExpr.isInstanceOf[LessEquals] || lc.toExpr.isInstanceOf[LessThan])
+        && lc.coeffMap.contains(elimVar.toVariable)) {
+
+        val InfiniteIntegerLiteral(elimCoeff) = lc.coeffMap(elimVar.toVariable)
+        if (elimCoeff > 0) {
+          //here, we have found an upper bound
+          allLowerBounds = false
+        } else {
+          //here, we have found a lower bound
+          allUpperBounds = false
+        }
+      } else {
+        //here, we assume that the operators are normalized to Equals, LessThan and LessEquals
+        throw new IllegalStateException("LinearConstraint not in expeceted form : " + lc.toExpr)
+      }
+    })
+
+    val newctrs = if (elimExpr.isDefined) {
+
+      val elimMap = Map[Expr, Expr](elimVar.toVariable -> elimExpr.get)
+      var repCtrs = Seq[LinearConstraint]()
+      relCtrs.foreach((ctr) => {
+        if (ctr != elimCtr.get) {
+          //replace 'elimVar' by 'elimExpr' in ctr
+          val repCtr = this.replaceInCtr(elimMap, ctr)
+          if (repCtr.isDefined)
+            repCtrs +:= repCtr.get
+        }
+      })
+      repCtrs
+
+    } else if (!foundEquality && (allLowerBounds || allUpperBounds)) {
+      //here, drop all relCtrs. None of them are important
+      Seq()
+    } else {
+      //for stats
+      if(skippingEquality) {
+        Stats.updateCumStats(1,"SkippedVar")
+      }
+      //cannot eliminate the variable
+      relCtrs
+    }
+    val resctrs = (newctrs ++ rest)
+    //println("After eliminating: "+elimVar+" : "+resctrs)
+    resctrs
+  }
+
+  def sizeExpr(ine: Expr): Int = {
+    val simpe = simplifyArithmetic(ine)
+    var size = 0
+    simplePostTransform((e: Expr) => {
+      size += 1
+      e
+    })(simpe)
+    size
+  }
+
+  def sizeCtr(ctr : LinearConstraint) : Int = {
+    val coeffSize = ctr.coeffMap.foldLeft(0)((acc, pair) => {
+      val (term, coeff) = pair
+      if(coeff == one) acc + 1
+      else acc + sizeExpr(coeff) + 2
+    })
+    if(ctr.const.isDefined) coeffSize + 1
+    else coeffSize
+  }
+
+  def shouldReplace(currExpr : Expr, candidateCtr : LinearConstraint, elimVar: Identifier) : Boolean = {
+    if(!currExpr.isInstanceOf[InfiniteIntegerLiteral]) {
+      //is the candidate a constant
+      if(candidateCtr.coeffMap.size == 1) true
+      else{
+        //computing the size of currExpr
+        if(sizeExpr(currExpr) > (sizeCtr(candidateCtr) - 1)) true
+        else false
+      }
+    } else false
+  }
+
+  //remove transitive axioms
+
+  /**
+   * Checks if the expression is linear i.e,
+   * is only conjuntion and disjunction of linear atomic predicates
+   */
+  def isLinear(e: Expr) : Boolean = {
+     e match {
+       case And(args) => args forall isLinear
+       case Or(args) => args forall isLinear
+       case Not(arg) => isLinear(arg)
+       case Implies(e1, e2) => isLinear(e1) && isLinear(e2)
+       case t : Terminal => true
+       case atom =>
+         exprToTemplate(atom).isInstanceOf[LinearConstraint]
+     }
+  }
+}
+
diff --git a/src/main/scala/leon/invariant/templateSolvers/CegisSolver.scala b/src/main/scala/leon/invariant/templateSolvers/CegisSolver.scala
new file mode 100644
index 000000000..305bd98e3
--- /dev/null
+++ b/src/main/scala/leon/invariant/templateSolvers/CegisSolver.scala
@@ -0,0 +1,408 @@
+package leon
+package invariant.templateSolvers
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import scala.util.control.Breaks._
+import solvers._
+import solvers.z3._
+import invariant.engine._
+import invariant.factories._
+import invariant.util._
+import invariant.structure._
+import invariant.structure.FunctionUtils._
+import leon.invariant.util.RealValuedExprEvaluator._
+
+class CegisSolver(ctx: InferenceContext,
+  rootFun: FunDef,
+  ctrTracker: ConstraintTracker,
+  timeout: Int,
+  bound: Option[Int] = None) extends TemplateSolver(ctx, rootFun, ctrTracker) {
+
+  override def solve(tempIds: Set[Identifier], funcVCs: Map[FunDef, Expr]): (Option[Model], Option[Set[Call]]) = {
+
+    val initCtr = if (bound.isDefined) {
+      //use a predefined bound on the template variables
+      Util.createAnd(tempIds.map((id) => {
+        val idvar = id.toVariable
+        And(Implies(LessThan(idvar, realzero), GreaterEquals(idvar, InfiniteIntegerLiteral(-bound.get))),
+          Implies(GreaterEquals(idvar, realzero), LessEquals(idvar, InfiniteIntegerLiteral(bound.get))))
+      }).toSeq)
+
+    } else tru
+
+    val funcs = funcVCs.keys
+    val formula = Util.createOr(funcs.map(funcVCs.apply _).toSeq)
+
+    //using reals with bounds does not converge and also results in overflow
+    val (res, _, model) = (new CegisCore(ctx, timeout, this)).solve(tempIds, formula, initCtr, solveAsInt = true)
+    res match {
+      case Some(true) => (Some(model), None)
+      case Some(false) => (None, None) //no solution exists
+      case _ => //timed out
+        throw new IllegalStateException("Timeout!!")
+    }
+  }
+}
+
+class CegisCore(ctx: InferenceContext,
+  timeout: Int,
+  cegisSolver: TemplateSolver) {
+
+  val fls = BooleanLiteral(false)
+  val tru = BooleanLiteral(true)
+  val zero = InfiniteIntegerLiteral(0)
+  val timeoutMillis = timeout.toLong * 1000
+  val dumpCandidateInvs = true
+  val minimizeSum = false
+  val program = ctx.program
+  val context = ctx.leonContext
+  val reporter = context.reporter
+
+  /**
+   * Finds a model for the template variables in the 'formula' so that 'formula' is falsified
+   * subject to the constraints on the template variables given by the 'envCtrs'
+   *
+   * The parameter solveAsInt when set to true will convert the template constraints
+   * to integer constraints and solve. This should be enabled when bounds are used to constrain the variables
+   */
+  def solve(tempIds: Set[Identifier], formula: Expr, initCtr: Expr, solveAsInt: Boolean,
+    initModel: Option[Model] = None): (Option[Boolean], Expr, Model) = {
+
+    //start a timer
+    val startTime = System.currentTimeMillis()
+
+    //for some sanity checks
+    var oldModels = Set[Expr]()
+    def addModel(m: Model) = {
+      val mexpr = Util.modelToExpr(m)
+      if (oldModels.contains(mexpr))
+        throw new IllegalStateException("repeating model !!:" + m)
+      else oldModels += mexpr
+    }
+
+    //add the initial model
+    val simplestModel = if (initModel.isDefined) initModel.get else {
+      new Model(tempIds.map((id) => (id -> simplestValue(id.getType))).toMap)
+    }
+    addModel(simplestModel)
+
+    val tempVarSum = if (minimizeSum) {
+      //compute the sum of the tempIds
+      val rootTempIds = Util.getTemplateVars(cegisSolver.rootFun.getTemplate)
+      if (rootTempIds.size >= 1) {
+        rootTempIds.tail.foldLeft(rootTempIds.head.asInstanceOf[Expr])((acc, tvar) => Plus(acc, tvar))
+      } else zero
+    } else zero
+
+    //convert initCtr to a real-constraint
+    val initRealCtr = ExpressionTransformer.IntLiteralToReal(initCtr)
+    if (Util.hasInts(initRealCtr))
+      throw new IllegalStateException("Initial constraints have integer terms: " + initRealCtr)
+
+    def cegisRec(model: Model, prevctr: Expr): (Option[Boolean], Expr, Model) = {
+
+      val elapsedTime = (System.currentTimeMillis() - startTime)
+      if (elapsedTime >= timeoutMillis - 100) {
+        //if we have timed out return the present set of constrains and the current model we have
+        (None, prevctr, model)
+      } else {
+
+        //println("elapsedTime: "+elapsedTime / 1000+" timeout: "+timeout)
+        Stats.updateCounter(1, "CegisIters")
+
+        if (dumpCandidateInvs) {
+          reporter.info("Candidate invariants")
+          val candInvs = cegisSolver.getAllInvariants(model)
+          candInvs.foreach((entry) => println(entry._1.id + "-->" + entry._2))
+        }
+        val tempVarMap: Map[Expr, Expr] = model.map((elem) => (elem._1.toVariable, elem._2)).toMap
+        val instFormula = simplifyArithmetic(TemplateInstantiator.instantiate(formula, tempVarMap))
+
+        //sanity checks
+        val spuriousTempIds = variablesOf(instFormula).intersect(TemplateIdFactory.getTemplateIds)
+        if (!spuriousTempIds.isEmpty)
+          throw new IllegalStateException("Found a template variable in instFormula: " + spuriousTempIds)
+        if (Util.hasReals(instFormula))
+          throw new IllegalStateException("Reals in instFormula: " + instFormula)
+
+        //println("solving instantiated vcs...")
+        val t1 = System.currentTimeMillis()
+        val solver1 = new ExtendedUFSolver(context, program)
+        solver1.assertCnstr(instFormula)
+        val res = solver1.check
+        val t2 = System.currentTimeMillis()
+        println("1: " + (if (res.isDefined) "solved" else "timedout") + "... in " + (t2 - t1) / 1000.0 + "s")
+
+        res match {
+          case Some(true) => {
+            //simplify the tempctrs, evaluate every atom that does not involve a template variable
+            //this should get rid of all functions
+            val satctrs =
+              simplePreTransform((e) => e match {
+                //is 'e' free of template variables ?
+                case _ if (variablesOf(e).filter(TemplateIdFactory.IsTemplateIdentifier _).isEmpty) => {
+                  //evaluate the term
+                  val value = solver1.evalExpr(e)
+                  if (value.isDefined) value.get
+                  else throw new IllegalStateException("Cannot evaluate expression: " + e)
+                }
+                case _ => e
+              })(Not(formula))
+            solver1.free()
+
+            //sanity checks
+            val spuriousProgIds = variablesOf(satctrs).filterNot(TemplateIdFactory.IsTemplateIdentifier _)
+            if (!spuriousProgIds.isEmpty)
+              throw new IllegalStateException("Found a progam variable in tempctrs: " + spuriousProgIds)
+
+            val tempctrs = if (!solveAsInt) ExpressionTransformer.IntLiteralToReal(satctrs) else satctrs
+            val newctr = And(tempctrs, prevctr)
+            //println("Newctr: " +newctr)
+
+            if (ctx.dumpStats) {
+              Stats.updateCounterStats(Util.atomNum(newctr), "CegisTemplateCtrs", "CegisIters")
+            }
+
+            //println("solving template constraints...")
+            val t3 = System.currentTimeMillis()
+            val elapsedTime = (t3 - startTime)
+            val solver2 = SimpleSolverAPI(new TimeoutSolverFactory(SolverFactory(() => new ExtendedUFSolver(context, program) with TimeoutSolver),
+              timeoutMillis - elapsedTime))
+
+            val (res1, newModel) = if (solveAsInt) {
+              //convert templates to integers and solve. Finally, re-convert integer models for templates to real models
+              val rti = new RealToInt()
+              val intctr = rti.mapRealToInt(And(newctr, initRealCtr))
+              val intObjective = rti.mapRealToInt(tempVarSum)
+              val (res1, intModel) = if (minimizeSum) {
+                minimizeIntegers(intctr, intObjective)
+              } else {
+                solver2.solveSAT(intctr)
+              }
+              (res1, rti.unmapModel(intModel))
+            } else {
+
+              /*if(InvariantUtil.hasInts(tempctrs))
+            	throw new IllegalStateException("Template constraints have integer terms: " + tempctrs)*/
+              if (minimizeSum) {
+                minimizeReals(And(newctr, initRealCtr), tempVarSum)
+              } else {
+                solver2.solveSAT(And(newctr, initRealCtr))
+              }
+            }
+
+            val t4 = System.currentTimeMillis()
+            println("2: " + (if (res1.isDefined) "solved" else "timed out") + "... in " + (t4 - t3) / 1000.0 + "s")
+
+            if (res1.isDefined) {
+              if (res1.get == false) {
+                //there exists no solution for templates
+                (Some(false), newctr, Model.empty)
+
+              } else {
+                //this is for sanity check
+                addModel(newModel)
+                //generate more constraints
+                cegisRec(newModel, newctr)
+              }
+            } else {
+              //we have timed out
+              (None, prevctr, model)
+            }
+          }
+          case Some(false) => {
+            solver1.free()
+            //found a model for disabling the formula
+            (Some(true), prevctr, model)
+          } case _ => {
+            solver1.free()
+            throw new IllegalStateException("Cannot solve instFormula: " + instFormula)
+          }
+        }
+      }
+    }
+    //note: initRealCtr is used inside 'cegisRec'
+    cegisRec(simplestModel, tru)
+  }
+
+  /**
+   * Performs minimization
+   */
+  val MaxIter = 16 //note we may not be able to represent anything beyond 2^16
+  val MaxInt = Int.MaxValue
+  val sqrtMaxInt = 45000
+  val half = FractionalLiteral(1, 2)
+  val two = FractionalLiteral(2, 1)
+  val rzero = FractionalLiteral(0, 1)
+  val mone = FractionalLiteral(-1, 1)
+  val debugMinimization = false
+
+  def minimizeReals(inputCtr: Expr, objective: Expr): (Option[Boolean], Model) = {
+    //val t1 = System.currentTimeMillis()
+    val sol = SimpleSolverAPI(new TimeoutSolverFactory(SolverFactory(() => new ExtendedUFSolver(context, program) with TimeoutSolver), timeoutMillis))
+    val (res, model1) = sol.solveSAT(inputCtr)
+    res match {
+      case Some(true) => {
+        //do a binary search on sequentially on each of these tempvars
+        println("minimizing " + objective + " ...")
+        val idMap: Map[Expr, Expr] = variablesOf(objective).map(id => (id.toVariable -> model1(id))).toMap
+        var upperBound: FractionalLiteral = evaluate(replace(idMap, objective))
+        var lowerBound: Option[FractionalLiteral] = None
+        var currentModel = model1
+        var continue = true
+        var iter = 0
+        do {
+          iter += 1
+          //here we perform some sanity checks to prevent overflow
+          if (!boundSanityChecks(upperBound, lowerBound)) {
+            continue = false
+          } else {
+            if (lowerBound.isDefined && evaluateRealPredicate(GreaterEquals(lowerBound.get, upperBound))) {
+              continue = false
+            } else {
+
+              val currval = if (lowerBound.isDefined) {
+                val midval = evaluate(Times(half, Plus(upperBound, lowerBound.get)))
+                floor(midval)
+
+              } else {
+                val rlit @ FractionalLiteral(n, d) = upperBound
+                if (isGEZ(rlit)) {
+                  if (n == 0) {
+                    //make the upper bound negative
+                    mone
+                  } else {
+                    floor(evaluate(Times(half, upperBound)))
+                  }
+                } else floor(evaluate(Times(two, upperBound)))
+
+              }
+              val boundCtr = LessEquals(objective, currval)
+              //val t1 = System.currentTimeMillis()
+              val solver2 = SimpleSolverAPI(new TimeoutSolverFactory(SolverFactory(() => new ExtendedUFSolver(context, program) with TimeoutSolver), timeoutMillis))
+              val (res, newModel) = sol.solveSAT(And(inputCtr, boundCtr))
+              //val t2 = System.currentTimeMillis()
+              //println((if (res.isDefined) "solved" else "timed out") + "... in " + (t2 - t1) / 1000.0 + "s")
+              res match {
+                case Some(true) => {
+                  //here we have a new upper bound
+                  currentModel = newModel
+                  val idMap: Map[Expr, Expr] = variablesOf(objective).map(id => (id.toVariable -> newModel(id))).toMap
+                  val value = evaluate(replace(idMap, objective))
+                  upperBound = value
+                  if (this.debugMinimization)
+                    reporter.info("Found new upper bound: " + upperBound)
+                }
+                case _ => {
+                  //here we have a new lower bound : currval
+                  lowerBound = Some(currval)
+                  if (this.debugMinimization)
+                    reporter.info("Found new lower bound: " + currval)
+                }
+              }
+            }
+          }
+        } while (continue && iter < MaxIter)
+        //here, we found a best-effort minimum
+        reporter.info("Minimization complete...")
+        (Some(true), currentModel)
+      }
+      case _ => (res, model1)
+    }
+  }
+
+  def boundSanityChecks(ub: FractionalLiteral, lb: Option[FractionalLiteral]): Boolean = {
+    val FractionalLiteral(n, d) = ub
+    if (n <= (MaxInt / 2)) {
+      if (lb.isDefined) {
+        val FractionalLiteral(n2, _) = lb.get
+        (n2 <= sqrtMaxInt && d <= sqrtMaxInt)
+      } else {
+        (d <= (MaxInt / 2))
+      }
+    } else false
+  }
+
+  def minimizeIntegers(inputCtr: Expr, objective: Expr): (Option[Boolean], Model) = {
+    //val t1 = System.currentTimeMillis()
+    val sol = SimpleSolverAPI(new TimeoutSolverFactory(SolverFactory(() => new ExtendedUFSolver(context, program) with TimeoutSolver), timeoutMillis))
+    val (res, model1) = sol.solveSAT(inputCtr)
+    res match {
+      case Some(true) => {
+        //do a binary search on sequentially on each of these tempvars
+        reporter.info("minimizing " + objective + " ...")
+        val idMap: Map[Expr, Expr] = variablesOf(objective).map(id => (id.toVariable -> model1(id))).toMap
+        var upperBound = simplifyArithmetic(replace(idMap, objective)).asInstanceOf[InfiniteIntegerLiteral].value
+        var lowerBound: Option[BigInt] = None
+        var currentModel = model1
+        var continue = true
+        var iter = 0
+        do {
+          iter += 1
+          if (lowerBound.isDefined && lowerBound.get >= upperBound - 1) {
+            continue = false
+          } else {
+
+            val currval = if (lowerBound.isDefined) {
+              val sum = (upperBound + lowerBound.get)
+              floorDiv(sum, 2)
+            } else {
+              if (upperBound >= 0) {
+                if (upperBound == 0) {
+                  //make the upper bound negative
+                  BigInt(-1)
+                } else {
+                  floorDiv(upperBound, 2)
+                }
+              } else 2 * upperBound
+            }
+            val boundCtr = LessEquals(objective, InfiniteIntegerLiteral(currval))
+            //val t1 = System.currentTimeMillis()
+            val solver2 = SimpleSolverAPI(new TimeoutSolverFactory(SolverFactory(() => new ExtendedUFSolver(context, program) with TimeoutSolver), timeoutMillis))
+            val (res, newModel) = sol.solveSAT(And(inputCtr, boundCtr))
+            //val t2 = System.currentTimeMillis()
+            //println((if (res.isDefined) "solved" else "timed out") + "... in " + (t2 - t1) / 1000.0 + "s")
+            res match {
+              case Some(true) => {
+                //here we have a new upper bound
+                currentModel = newModel
+                val idMap: Map[Expr, Expr] = variablesOf(objective).map(id => (id.toVariable -> newModel(id))).toMap
+                val value = simplifyArithmetic(replace(idMap, objective)).asInstanceOf[InfiniteIntegerLiteral].value
+                upperBound = value
+                if (this.debugMinimization)
+                  reporter.info("Found new upper bound: " + upperBound)
+              }
+              case _ => {
+                //here we have a new lower bound : currval
+                lowerBound = Some(currval)
+                if (this.debugMinimization)
+                  reporter.info("Found new lower bound: " + currval)
+              }
+            }
+          }
+        } while (continue && iter < MaxIter)
+        //here, we found a best-effort minimum
+        reporter.info("Minimization complete...")
+        (Some(true), currentModel)
+      }
+      case _ => (res, model1)
+    }
+  }
+
+  def floorDiv(did: BigInt, div: BigInt): BigInt = {
+    if (div <= 0) throw new IllegalStateException("Invalid divisor")
+    if (did < 0) {
+      if (did % div != 0) did / div - 1
+      else did / div
+    } else {
+      did / div
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/templateSolvers/ExtendedUFSolver.scala b/src/main/scala/leon/invariant/templateSolvers/ExtendedUFSolver.scala
new file mode 100644
index 000000000..8bc93564c
--- /dev/null
+++ b/src/main/scala/leon/invariant/templateSolvers/ExtendedUFSolver.scala
@@ -0,0 +1,79 @@
+/* Copyright 2009-2013 EPFL, Lausanne */
+
+package leon
+package invariant.templateSolvers
+
+import z3.scala._
+import leon.solvers._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.Extractors._
+import purescala.ExprOps._
+import purescala.Types._
+import leon.LeonContext
+import leon.solvers.z3.UninterpretedZ3Solver
+
+/**
+ *  A uninterpreted solver extended with additional functionalities.
+ *  TODO: need to handle bit vectors
+ */
+class ExtendedUFSolver(context : LeonContext, program: Program)
+  extends UninterpretedZ3Solver(context, program) {
+
+  override val name = "Z3-eu"
+  override val description = "Extended UF-ADT Z3 Solver"
+
+  /**
+   * This uses z3 methods to evaluate the model
+   */
+  def evalExpr(expr: Expr): Option[Expr] = {
+    val ast = toZ3Formula(expr)
+    val model = solver.getModel
+    val res = model.eval(ast, true)
+    if (res.isDefined)
+      Some(fromZ3Formula(model, res.get, null))
+    else None
+  }
+
+  def getAssertions : Expr = {
+    val assers = solver.getAssertions.map((ast) => fromZ3Formula(null, ast, null))
+    And(assers)
+  }
+
+  /**
+   * Uses z3 to convert a formula to SMTLIB.
+   */
+  def ctrsToString(logic: String, unsatcore: Boolean = false): String = {
+    z3.setAstPrintMode(Z3Context.AstPrintMode.Z3_PRINT_SMTLIB2_COMPLIANT)
+    var seenHeaders = Set[String]()
+    var headers = Seq[String]()
+    var asserts = Seq[String]()
+    solver.getAssertions().toSeq.foreach((asser) => {
+      val str = z3.benchmarkToSMTLIBString("benchmark", logic, "unknown", "", Seq(), asser)
+      //remove from the string the headers and also redeclaration of template variables
+      //split based on newline to get a list of strings
+      val strs = str.split("\n")
+      val newstrs = strs.filter((line) => !seenHeaders.contains(line))
+      var newHeaders = Seq[String]()
+      newstrs.foreach((line) => {
+        if (line == "; benchmark") newHeaders :+= line
+        else if (line.startsWith("(set")) newHeaders :+= line
+        else if (line.startsWith("(declare")) newHeaders :+= line
+        else if(line.startsWith("(check-sat)")) {} //do nothing
+        else asserts :+= line
+      })
+      headers ++= newHeaders
+      seenHeaders ++= newHeaders
+    })
+    val initstr = if (unsatcore) {
+      "(set-option :produce-unsat-cores true)"
+    } else ""
+    val smtstr = headers.foldLeft(initstr)((acc, hdr) => acc + "\n" + hdr) + "\n" +
+      asserts.foldLeft("")((acc, asrt) => acc + "\n" + asrt) + "\n" +
+      "(check-sat)" + "\n" +
+      (if (!unsatcore) "(get-model)"
+      else "(get-unsat-core)")
+    smtstr
+  }
+}
diff --git a/src/main/scala/leon/invariant/templateSolvers/FarkasLemmaSolver.scala b/src/main/scala/leon/invariant/templateSolvers/FarkasLemmaSolver.scala
new file mode 100644
index 000000000..13e8727a4
--- /dev/null
+++ b/src/main/scala/leon/invariant/templateSolvers/FarkasLemmaSolver.scala
@@ -0,0 +1,332 @@
+package leon
+package invariant.templateSolvers
+
+import z3.scala._
+import purescala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import solvers.SimpleSolverAPI
+import scala.collection.mutable.{ Map => MutableMap }
+import invariant.engine._
+import invariant.factories._
+import invariant.util.Util._
+import invariant.util._
+import invariant.structure._
+import leon.solvers.TimeoutSolver
+import leon.solvers.SolverFactory
+import leon.solvers.TimeoutSolverFactory
+import leon.solvers.Model
+import leon.invariant.util.RealValuedExprEvaluator._
+
+class FarkasLemmaSolver(ctx: InferenceContext) {
+
+  //debug flags
+  val verbose = true
+  val verifyModel = false
+  val dumpNLCtrsAsSMTLIB = false
+  val dumpNLCtrs = false
+  val debugNLCtrs = false
+
+  // functionality flags
+  val solveAsBitvectors = false
+  val bvsize = 5
+  val useIncrementalSolvingForNLctrs = false //note: NLsat doesn't support incremental solving. It starts from sratch even in incremental solving.
+
+  val leonctx = ctx.leonContext
+  val program = ctx.program
+  val reporter = ctx.reporter
+  val timeout = ctx.timeout
+  /**
+   * This procedure produces a set of constraints that need to be satisfiable for the
+   * conjunction ants and conseqs to be false
+   * antsSimple - antecedents without template variables
+   * antsTemp - antecedents with template variables
+   * Similarly for conseqsSimple and conseqsTemp
+   *
+   * Let A,A' and C,C' denote the simple and templated portions of the antecedent and the consequent respectively.
+   * We need to check \exists a, \forall x, A[x] ^ A'[x,a] ^ C[x] ^ C'[x,a] = false
+   *
+   */
+  def constraintsForUnsat(linearCtrs: Seq[LinearConstraint], temps: Seq[LinearTemplate]): Expr = {
+
+    //for debugging
+    /*println("#" * 20)
+    println(allAnts + " ^ " + allConseqs)
+    println("#" * 20)*/
+    this.applyFarkasLemma(linearCtrs ++ temps, Seq(), true)
+  }
+
+  /**
+   * This procedure produces a set of constraints that need to be satisfiable for the implication to hold
+   * antsSimple - antecedents without template variables
+   * antsTemp - antecedents with template variables
+   * Similarly for conseqsSimple and conseqsTemp
+   *
+   * Let A,A' and C,C' denote the simple and templated portions of the antecedent and the consequent respectively.
+   * We need to check \exists a, \forall x, A[x] ^ A'[x,a] => C[x] ^ C'[x,a]
+   *
+   */
+  def constraintsForImplication(antsSimple: Seq[LinearConstraint], antsTemp: Seq[LinearTemplate],
+    conseqsSimple: Seq[LinearConstraint], conseqsTemp: Seq[LinearTemplate],
+    uisolver: SimpleSolverAPI): Expr = {
+
+    val allAnts = antsSimple ++ antsTemp
+    val allConseqs = conseqsSimple ++ conseqsTemp
+    //for debugging
+    println("#" * 20)
+    println(allAnts + " => " + allConseqs)
+    println("#" * 20)
+
+    //Optimization 1: Check if ants are unsat (already handled)
+    val pathVC = createAnd(antsSimple.map(_.toExpr).toSeq ++ conseqsSimple.map(_.toExpr).toSeq)
+    val notPathVC = And(createAnd(antsSimple.map(_.toExpr).toSeq), Not(createAnd(conseqsSimple.map(_.toExpr).toSeq)))
+    val (satVC, _) = uisolver.solveSAT(pathVC)
+    val (satNVC, _) = uisolver.solveSAT(notPathVC)
+
+    //Optimization 2: use the unsatisfiability of VC and not VC to simplify the constraint generation
+    //(a) if A => C is false and A' is true then the entire formula is unsat
+    //(b) if A => C is false and A' is not true then we need to ensure A^A' is unsat (i.e, disable Ant)
+    //(c) if A => C is true (i.e, valid) then it suffices to ensure A^A' => C' is valid
+    //(d) if A => C is neither true nor false then we cannot do any simplification
+    //TODO: Food for thought:
+    //(a) can we do any simplification for case (d) with the model
+    //(b) could the linearity in the disabled case be exploited
+    val (ants, conseqs, disableFlag) = (satVC, satNVC) match {
+      case (Some(false), _) if (antsTemp.isEmpty) => (Seq(), Seq(), false)
+      case (Some(false), _) => (allAnts, Seq(), true) //here only disable the antecedents
+      case (_, Some(false)) => (allAnts, conseqsTemp, false) //here we need to only check the inductiveness of the templates
+      case _ => (allAnts, allConseqs, false)
+    }
+    if (ants.isEmpty) {
+      BooleanLiteral(false)
+    } else {
+      this.applyFarkasLemma(ants, conseqs, disableFlag)
+    }
+  }
+
+  /**
+   * This procedure uses Farka's lemma to generate a set of non-linear constraints for the input implication.
+   * Note that these non-linear constraints are in real arithmetic.
+   * TODO: Correctness issue: need to handle strict inequalities in consequent
+   * Do we really need the consequent ??
+   */
+  def applyFarkasLemma(ants: Seq[LinearTemplate], conseqs: Seq[LinearTemplate], disableAnts: Boolean): Expr = {
+
+    //compute the set of all constraint variables in ants
+    val antCVars = ants.foldLeft(Set[Expr]())((acc, ant) => acc ++ ant.coeffTemplate.keySet)
+
+    //the creates constraints for a single consequent
+    def createCtrs(conseq: Option[LinearTemplate]): Expr = {
+      //create a set of identifiers one for each ants
+      val lambdas = ants.map((ant) => (ant -> Variable(FreshIdentifier("l", RealType, true)))).toMap
+      val lambda0 = Variable(FreshIdentifier("l", RealType, true))
+
+      //add a bunch of constraints on lambdas
+      var strictCtrLambdas = Seq[Variable]()
+      val lambdaCtrs = (ants.collect((ant) => ant.template match {
+        case t: LessEquals => GreaterEquals(lambdas(ant), zero)
+        case t: LessThan => {
+          val l = lambdas(ant)
+          strictCtrLambdas :+= l
+          GreaterEquals(l, zero)
+        }
+      }).toSeq :+ GreaterEquals(lambda0, zero))
+
+      //add the constraints on constant terms
+      val sumConst = ants.foldLeft(UMinus(lambda0): Expr)((acc, ant) => ant.constTemplate match {
+        case Some(d) => Plus(acc, Times(lambdas(ant), d))
+        case None => acc
+      })
+
+      val cvars = antCVars ++ (if (conseq.isDefined) conseq.get.coeffTemplate.keys else Seq())
+      //initialize enabled and disabled parts
+      var enabledPart: Expr = if (conseq.isDefined) {
+        conseq.get.constTemplate match {
+          case Some(d) => Equals(d, sumConst)
+          case None => Equals(zero, sumConst)
+        }
+      } else null
+      //the disabled part handles strict inequalities as well using Motzkin's transposition
+      var disabledPart: Expr =
+        if (strictCtrLambdas.isEmpty) Equals(one, sumConst)
+        else Or(Equals(one, sumConst),
+          And(Equals(zero, sumConst), createOr(strictCtrLambdas.map(GreaterThan(_, zero)))))
+
+      for (cvar <- cvars) {
+        //compute the linear combination of all the coeffs of antCVars
+        //println("Processing cvar: "+cvar)
+        var sumCoeff: Expr = zero
+        for (ant <- ants) {
+          //handle coefficients here
+          if (ant.coeffTemplate.contains(cvar)) {
+            val addend = Times(lambdas(ant), ant.coeffTemplate.get(cvar).get)
+            if (sumCoeff == zero)
+              sumCoeff = addend
+            else
+              sumCoeff = Plus(sumCoeff, addend)
+          }
+        }
+        //println("sum coeff: "+sumCoeff)
+        //make the sum equal to the coeff. of cvar in conseq
+        if (conseq.isDefined) {
+          enabledPart = And(enabledPart,
+            (if (conseq.get.coeffTemplate.contains(cvar))
+              Equals(conseq.get.coeffTemplate.get(cvar).get, sumCoeff)
+            else Equals(zero, sumCoeff)))
+        }
+
+        disabledPart = And(disabledPart, Equals(zero, sumCoeff))
+      } //end of cvars loop
+
+      //the final constraint is a conjunction of lambda constraints and disjunction of enabled and disabled parts
+      if (disableAnts) And(createAnd(lambdaCtrs), disabledPart)
+      else {
+        //And(And(lambdaCtrs), enabledPart)
+        And(createAnd(lambdaCtrs), Or(enabledPart, disabledPart))
+      }
+    }
+
+    val ctrs = if (disableAnts) {
+      //here conseqs are empty
+      createCtrs(None)
+    } else {
+      val Seq(head, tail @ _*) = conseqs
+      val nonLinearCtrs = tail.foldLeft(createCtrs(Some(head)))((acc, conseq) => And(acc, createCtrs(Some(conseq))))
+      nonLinearCtrs
+    }
+    ExpressionTransformer.IntLiteralToReal(ctrs)
+  }
+
+  def solveFarkasConstraints(nlctrs: Expr): (Option[Boolean], Model) = {
+
+    // factor out common nonlinear terms and create an equiv-satisfiable constraint
+    def reduceCommonNLTerms(ctrs: Expr) = {
+      var nlUsage = new CounterMap[Expr]()
+      postTraversal{
+        case t: Times => nlUsage.inc(t)
+        case e => ;
+      }(ctrs)
+      val repMap = nlUsage.collect{
+        case (k, v) if v > 1 =>
+          (k -> FreshIdentifier("t", RealType, true).toVariable)
+      }.toMap
+      createAnd(replace(repMap, ctrs) +: repMap.map {
+        case (k, v) => Equals(v, k)
+      }.toSeq)
+    }
+
+    // try eliminate nonlinearity to whatever extent possible
+    var elimMap = Map[Identifier, (Identifier, Identifier)]() // maps the fresh identifiers to the product of the identifiers they represent.
+    def reduceNonlinearity(farkasctrs: Expr): Expr = {
+      var varCounts = new CounterMap[Identifier]()
+      // collect # of uses of each variable
+      postTraversal {
+        case Variable(id) => varCounts.inc(id)
+        case _ => ;
+      }(farkasctrs)
+      var adnlCtrs = Seq[Expr]()
+      val simpCtrs = simplePostTransform {
+        case Times(vlb @ Variable(lb), va @ Variable(a)) if (varCounts(lb) == 1 || varCounts(a) == 1) => // is lb or a used only once ?
+          // stats
+          Stats.updateCumStats(1, "NonlinearMultEliminated")
+          val freshid = FreshIdentifier(lb.name + a.name, RealType, true)
+          val freshvar = freshid.toVariable
+          elimMap += (freshid -> (lb, a))
+          if (varCounts(lb) == 1)
+            // va = 0 ==> freshvar = 0
+            adnlCtrs :+= Implies(Equals(va, realzero), Equals(freshvar, realzero))
+          else // here varCounts(a) == 1
+            adnlCtrs :+= Implies(Equals(vlb, realzero), Equals(freshvar, realzero))
+          freshvar
+        case e =>
+          e
+      }(farkasctrs)
+      createAnd(simpCtrs +: adnlCtrs)
+    }
+    val simpctrs = (reduceCommonNLTerms _ andThen
+    					reduceNonlinearity)(nlctrs)
+
+    //for debugging nonlinear constraints
+    if (this.debugNLCtrs && Util.hasInts(simpctrs)) {
+      throw new IllegalStateException("Nonlinear constraints have integers: " + simpctrs)
+    }
+    if (verbose && LinearConstraintUtil.isLinear(simpctrs)) {
+      reporter.info("Constraints reduced to linear !")
+    }
+    if (this.dumpNLCtrs) {
+      reporter.info("InputCtrs: " + nlctrs)
+      reporter.info("SimpCtrs: " + simpctrs)
+      if (this.dumpNLCtrsAsSMTLIB) {
+        val filename = ctx.program.modules.last.id + "-nlctr" + FileCountGUID.getID + ".smt2"
+        if (Util.atomNum(simpctrs) >= 5) {
+          if (solveAsBitvectors)
+            Util.toZ3SMTLIB(simpctrs, filename, "QF_BV", leonctx, program, useBitvectors = true, bitvecSize = bvsize)
+          else
+            Util.toZ3SMTLIB(simpctrs, filename, "QF_NRA", leonctx, program)
+          reporter.info("NLctrs dumped to: " + filename)
+        }
+      }
+    }
+
+    // solve the resulting constraints using solver
+    val innerSolver = if (solveAsBitvectors) {
+      throw new IllegalStateException("Not supported now. Will be in the future!")
+      //new ExtendedUFSolver(leonctx, program, useBitvectors = true, bitvecSize = bvsize) with TimeoutSolver
+    } else {
+      new ExtendedUFSolver(leonctx, program) with TimeoutSolver
+    }
+    val solver = SimpleSolverAPI(new TimeoutSolverFactory(SolverFactory(() => innerSolver), timeout * 1000))
+    if (verbose) reporter.info("solving...")
+    val t1 = System.currentTimeMillis()
+    val (res, model) = solver.solveSAT(simpctrs)
+    val t2 = System.currentTimeMillis()
+    if (verbose) reporter.info((if (res.isDefined) "solved" else "timed out") + "... in " + (t2 - t1) / 1000.0 + "s")
+    Stats.updateCounterTime((t2 - t1), "NL-solving-time", "disjuncts")
+
+    res match {
+      case Some(true) =>
+        // construct assignments for the variables that were removed during nonlinearity reduction
+        def divide(dividend: Expr, divisor: Expr) = {
+          divisor match {
+            case `realzero` =>
+              assert(dividend == realzero)
+              // here result can be anything. So make it zero
+              realzero
+            case _ =>
+              val res = evaluate(Division(dividend, divisor))
+              res
+          }
+        }
+        val newassignments = elimMap.flatMap {
+          case (k, (v1, v2)) =>
+            val kval = evaluate(model(k))
+            if (model.isDefinedAt(v1) && model.isDefinedAt(v2))
+              throw new IllegalStateException(
+                s"Variables $v1 and $v2 in an eliminated nonlinearity have models")
+            else if (model.isDefinedAt(v1)) {
+              val v2val = divide(kval, evaluate(model(v1)))
+              Seq((v2 -> v2val))
+            } else if (model.isDefinedAt(v2))
+              Seq((v1 -> divide(kval, evaluate(model(v2)))))
+            else
+              // here v1 * v2 = k. Therefore make v1 = k and v2 = 1
+              Seq((v1 -> kval), (v2 -> FractionalLiteral(1, 1)))
+        }
+        val fullmodel = model ++ newassignments
+        if (this.verifyModel) {
+          //println("Fullmodel: "+fullmodel)
+          assert(evaluateRealFormula(replace(
+              fullmodel.map { case (k, v) => (k.toVariable, v) }.toMap,
+              nlctrs)))
+        }
+        (res, fullmodel)
+      case _ =>
+        (res, model)
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala
new file mode 100644
index 000000000..2e01e4682
--- /dev/null
+++ b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala
@@ -0,0 +1,717 @@
+package leon
+package invariant.templateSolvers
+
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import evaluators._
+import scala.collection.mutable.{ Map => MutableMap }
+import java.io._
+import solvers._
+import solvers.z3._
+import scala.util.control.Breaks._
+import purescala.ScalaPrinter
+import scala.collection.mutable.{ Map => MutableMap }
+import scala.reflect.runtime.universe
+import invariant.engine._
+import invariant.factories._
+import invariant.util._
+import invariant.util.ExpressionTransformer._
+import invariant.structure._
+import invariant.structure.FunctionUtils._
+import leon.invariant.util.RealValuedExprEvaluator._
+
+class NLTemplateSolver(ctx: InferenceContext, rootFun: FunDef, ctrTracker: ConstraintTracker,
+  minimizer: Option[(Expr, Model) => Model])
+  extends TemplateSolver(ctx, rootFun, ctrTracker) {
+
+  //flags controlling debugging
+  val debugIncrementalVC = false
+  val debugElimination = false
+  val debugChooseDisjunct = false
+  val debugTheoryReduction = false
+  val debugAxioms = false
+  val verifyInvariant = false
+  val debugReducedFormula = false
+  val trackUnpackedVCCTime = false
+
+  //print flags
+  val verbose = false
+  val printCounterExample = false
+  val printPathToConsole = false
+  val dumpPathAsSMTLIB = false
+  val printCallConstriants = false
+  val dumpInstantiatedVC = false
+
+  private val program = ctx.program
+  private val timeout = ctx.timeout
+  private val leonctx = ctx.leonContext
+
+  //flag controlling behavior
+  private val farkasSolver = new FarkasLemmaSolver(ctx)
+  private val startFromEarlierModel = true
+  private val disableCegis = true
+  private val useIncrementalSolvingForVCs = true
+
+  //this is private mutable state used by initialized during every call to 'solve' and used by 'solveUNSAT'
+  protected var funcVCs = Map[FunDef, Expr]()
+  //TODO: can incremental solving be trusted ? There were problems earlier.
+  protected var vcSolvers = Map[FunDef, ExtendedUFSolver]()
+  protected var paramParts = Map[FunDef, Expr]()
+  private var lastFoundModel: Option[Model] = None
+
+  //for miscellaneous things
+  val trackNumericalDisjuncts = false
+  var numericalDisjuncts = List[Expr]()
+
+  protected def splitVC(fd: FunDef): (Expr, Expr) = {
+    ctrTracker.getVC(fd).splitParamPart
+  }
+
+  def initVCSolvers {
+    funcVCs.keys.foreach(fd => {
+      val (paramPart, rest) = if (ctx.usereals) {
+        val (pp, r) = splitVC(fd)
+        (IntLiteralToReal(pp), IntLiteralToReal(r))
+      } else
+        splitVC(fd)
+
+      if (Util.hasReals(rest) && Util.hasInts(rest))
+        throw new IllegalStateException("Non-param Part has both integers and reals: " + rest)
+
+      val vcSolver = new ExtendedUFSolver(leonctx, program)
+      vcSolver.assertCnstr(rest)
+
+      if (debugIncrementalVC) {
+        assert(Util.getTemplateVars(rest).isEmpty)
+        println("For function: " + fd.id)
+        println("Param part: " + paramPart)
+        /*vcSolver.check match {
+        case Some(false) => throw new IllegalStateException("Non param-part is unsat "+rest)
+        case _ => ;
+      	}*/
+      }
+      vcSolvers += (fd -> vcSolver)
+      paramParts += (fd -> paramPart)
+    })
+  }
+
+  def freeVCSolvers {
+    vcSolvers.foreach(entry => entry._2.free)
+  }
+
+  /**
+   * This function computes invariants belonging to the given templates incrementally.
+   * The result is a mapping from function definitions to the corresponding invariants.
+   */
+  override def solve(tempIds: Set[Identifier], funcVCs: Map[FunDef, Expr]): (Option[Model], Option[Set[Call]]) = {
+    //initialize vcs of functions
+    this.funcVCs = funcVCs
+    if (useIncrementalSolvingForVCs) {
+      initVCSolvers
+    }
+    val initModel = if (this.startFromEarlierModel && lastFoundModel.isDefined) {
+      val candModel = lastFoundModel.get
+      new Model(tempIds.map(id =>
+        (id -> candModel.getOrElse(id, simplestValue(id.getType)))).toMap)
+    } else {
+      new Model(tempIds.map((id) =>
+        (id -> simplestValue(id.getType))).toMap)
+    }
+    val sol = solveUNSAT(initModel, tru, Seq(), Set())
+
+    if (useIncrementalSolvingForVCs) {
+      freeVCSolvers
+    }
+    //set lowerbound map
+    //TODO: find a way to record lower bound stats
+    /*if (ctx.tightBounds)
+      SpecificStats.addLowerBoundStats(rootFun, minimizer.lowerBoundMap, "")*/
+    //miscellaneous stuff
+    if (trackNumericalDisjuncts) {
+      this.numericalDisjuncts = List[Expr]()
+    }
+    sol
+  }
+
+  //state for minimization
+  var minStarted = false
+  var minStartTime: Long = 0
+  var minimized = false
+
+  def minimizationInProgress {
+    if (!minStarted) {
+      minStarted = true
+      minStartTime = System.currentTimeMillis()
+    }
+  }
+
+  def minimizationCompleted {
+    minStarted = false
+    val mintime = (System.currentTimeMillis() - minStartTime)
+    /*Stats.updateCounterTime(mintime, "minimization-time", "procs")
+    Stats.updateCumTime(mintime, "Total-Min-Time")*/
+  }
+
+  def solveUNSAT(model: Model, inputCtr: Expr, solvedDisjs: Seq[Expr], seenCalls: Set[Call]): (Option[Model], Option[Set[Call]]) = {
+
+    if (verbose) {
+      reporter.info("Candidate invariants")
+      val candInvs = getAllInvariants(model)
+      candInvs.foreach((entry) => reporter.info(entry._1.id + "-->" + entry._2))
+    }
+
+    if (this.startFromEarlierModel) this.lastFoundModel = Some(model)
+
+    val (res, newCtr, newModel, newdisjs, newcalls) = invalidateSATDisjunct(inputCtr, model)
+    res match {
+      case None => {
+        //here, we cannot proceed and have to return unknown
+        //However, we can return the calls that need to be unrolled
+        (None, Some(seenCalls ++ newcalls))
+      }
+      case Some(false) => {
+        //here, the vcs are unsatisfiable when instantiated with the invariant
+        if (minimizer.isDefined) {
+          //for stats
+          minimizationInProgress
+          if (minimized) {
+            minimizationCompleted
+            (Some(model), None)
+          } else {
+            val minModel = minimizer.get(inputCtr, model)
+            minimized = true
+            if (minModel == model) {
+              minimizationCompleted
+              (Some(model), None)
+            } else {
+              solveUNSAT(minModel, inputCtr, solvedDisjs, seenCalls)
+            }
+          }
+        } else {
+          (Some(model), None)
+        }
+      }
+      case Some(true) => {
+        //here, we have found a new candidate invariant. Hence, the above process needs to be repeated
+        minimized = false
+        solveUNSAT(newModel, newCtr, solvedDisjs ++ newdisjs, seenCalls ++ newcalls)
+      }
+    }
+  }
+
+  //TODO: this code does too much imperative update.
+  //TODO: use guards to block a path and not use the path itself
+  def invalidateSATDisjunct(inputCtr: Expr, model: Model): (Option[Boolean], Expr, Model, Seq[Expr], Set[Call]) = {
+
+    val tempIds = model.map(_._1)
+    val tempVarMap: Map[Expr, Expr] = model.map((elem) => (elem._1.toVariable, elem._2)).toMap
+    val inputSize = Util.atomNum(inputCtr)
+
+    var disjsSolvedInIter = Seq[Expr]()
+    var callsInPaths = Set[Call]()
+    var conflictingFuns = funcVCs.keySet
+    //mapping from the functions to the counter-example paths that were seen
+    var seenPaths = MutableMap[FunDef, Seq[Expr]]()
+    def updateSeenPaths(fd: FunDef, cePath: Expr): Unit = {
+      if (seenPaths.contains(fd)) {
+        seenPaths.update(fd, cePath +: seenPaths(fd))
+      } else {
+        seenPaths += (fd -> Seq(cePath))
+      }
+    }
+
+    def invalidateDisjRecr(prevCtr: Expr): (Option[Boolean], Expr, Model) = {
+
+      Stats.updateCounter(1, "disjuncts")
+
+      var blockedCEs = false
+      var confFunctions = Set[FunDef]()
+      var confDisjuncts = Seq[Expr]()
+
+      val newctrs = conflictingFuns.foldLeft(Seq[Expr]())((acc, fd) => {
+
+        val disableCounterExs = if (seenPaths.contains(fd)) {
+          blockedCEs = true
+          Not(Util.createOr(seenPaths(fd)))
+        } else tru
+        val (data, ctrsForFun) = getUNSATConstraints(fd, model, disableCounterExs)
+        val (disjunct, callsInPath) = data
+        if (ctrsForFun == tru) acc
+        else {
+          confFunctions += fd
+          confDisjuncts :+= disjunct
+          callsInPaths ++= callsInPath
+          //instantiate the disjunct
+          val cePath = simplifyArithmetic(TemplateInstantiator.instantiate(disjunct, tempVarMap))
+
+          //some sanity checks
+          if (variablesOf(cePath).exists(TemplateIdFactory.IsTemplateIdentifier _))
+            throw new IllegalStateException("Found template identifier in counter-example disjunct: " + cePath)
+
+          updateSeenPaths(fd, cePath)
+          acc :+ ctrsForFun
+        }
+      })
+      //update conflicting functions
+      conflictingFuns = confFunctions
+      if (newctrs.isEmpty) {
+
+        if (!blockedCEs) {
+          //yes, hurray,found an inductive invariant
+          (Some(false), prevCtr, model)
+        } else {
+          //give up, only hard paths remaining
+          reporter.info("- Exhausted all easy paths !!")
+          reporter.info("- Number of remaining hard paths: " + seenPaths.values.foldLeft(0)((acc, elem) => acc + elem.size))
+          //TODO: what to unroll here ?
+          (None, tru, Model.empty)
+        }
+      } else {
+
+        //check that the new constraints does not have any reals
+        val newPart = Util.createAnd(newctrs)
+        val newSize = Util.atomNum(newPart)
+        Stats.updateCounterStats((newSize + inputSize), "NLsize", "disjuncts")
+        if (verbose)
+          reporter.info("# of atomic predicates: " + newSize + " + " + inputSize)
+
+        /*if (this.debugIncremental)
+          solverWithCtr.assertCnstr(newPart)*/
+
+        //here we need to solve for the newctrs + inputCtrs
+        val combCtr = And(prevCtr, newPart)
+        val (res, newModel) = farkasSolver.solveFarkasConstraints(combCtr)
+
+        res match {
+          case None => {
+            //here we have timed out while solving the non-linear constraints
+            if (verbose)
+              if (!this.disableCegis)
+                reporter.info("NLsolver timed-out on the disjunct... starting cegis phase...")
+              else
+                reporter.info("NLsolver timed-out on the disjunct... blocking this disjunct...")
+
+            if (!this.disableCegis) {
+              val (cres, cctr, cmodel) = solveWithCegis(tempIds.toSet, Util.createOr(confDisjuncts), inputCtr, Some(model))
+              cres match {
+                case Some(true) => {
+                  disjsSolvedInIter ++= confDisjuncts
+                  (Some(true), And(inputCtr, cctr), cmodel)
+                }
+                case Some(false) => {
+                  disjsSolvedInIter ++= confDisjuncts
+                  //here also return the calls that needs to be unrolled
+                  (None, fls, Model.empty)
+                }
+                case _ => {
+                  if (verbose) reporter.info("retrying...")
+                  Stats.updateCumStats(1, "retries")
+                  //disable this disjunct and retry but, use the inputCtrs + the constraints generated by cegis from the next iteration
+                  invalidateDisjRecr(And(inputCtr, cctr))
+                }
+              }
+            } else {
+              if (verbose) reporter.info("retrying...")
+              Stats.updateCumStats(1, "retries")
+              invalidateDisjRecr(inputCtr)
+            }
+          }
+          case Some(false) => {
+            //reporter.info("- Number of explored paths (of the DAG) in this unroll step: " + exploredPaths)
+            disjsSolvedInIter ++= confDisjuncts
+            (None, fls, Model.empty)
+          }
+          case Some(true) => {
+            disjsSolvedInIter ++= confDisjuncts
+            //new model may not have mappings for all the template variables, hence, use the mappings from earlier models
+            val compModel = new Model(tempIds.map((id) => {
+              if (newModel.isDefinedAt(id))
+                (id -> newModel(id))
+              else
+                (id -> model(id))
+            }).toMap)
+            (Some(true), combCtr, compModel)
+          }
+        }
+      }
+    }
+    val (res, newctr, newmodel) = invalidateDisjRecr(inputCtr)
+    (res, newctr, newmodel, disjsSolvedInIter, callsInPaths)
+  }
+
+  def solveWithCegis(tempIds: Set[Identifier], expr: Expr, precond: Expr, initModel: Option[Model]): (Option[Boolean], Expr, Model) = {
+
+    val cegisSolver = new CegisCore(ctx, timeout, this)
+    val (res, ctr, model) = cegisSolver.solve(tempIds, expr, precond, solveAsInt = false, initModel)
+    if (!res.isDefined)
+      reporter.info("cegis timed-out on the disjunct...")
+    (res, ctr, model)
+  }
+
+  protected def instantiateTemplate(e: Expr, tempVarMap: Map[Expr, Expr]): Expr = {
+    if (ctx.usereals) replace(tempVarMap, e)
+    else
+      simplifyArithmetic(TemplateInstantiator.instantiate(e, tempVarMap))
+  }
+
+  /**
+   * Constructs a quantifier-free non-linear constraint for unsatisfiability
+   */
+  def getUNSATConstraints(fd: FunDef, inModel: Model, disableCounterExs: Expr): ((Expr, Set[Call]), Expr) = {
+
+    val tempVarMap: Map[Expr, Expr] = inModel.map((elem) => (elem._1.toVariable, elem._2)).toMap
+    val innerSolver = if (this.useIncrementalSolvingForVCs) vcSolvers(fd)
+    else new ExtendedUFSolver(leonctx, program)
+    val instExpr = if (this.useIncrementalSolvingForVCs) {
+      val instParamPart = instantiateTemplate(this.paramParts(fd), tempVarMap)
+      And(instParamPart, disableCounterExs)
+    } else {
+      val instVC = instantiateTemplate(funcVCs(fd), tempVarMap)
+      And(instVC, disableCounterExs)
+    }
+    //For debugging
+    if (this.dumpInstantiatedVC) {
+      // println("Plain vc: "+funcVCs(fd))
+      val wr = new PrintWriter(new File("formula-dump.txt"))
+      val fullExpr = if (this.useIncrementalSolvingForVCs) {
+        And(innerSolver.getAssertions, instExpr)
+      } else
+        instExpr
+      // println("Instantiated VC of " + fd.id + " is: " + fullExpr)
+      wr.println("Function name: " + fd.id)
+      wr.println("Formula expr: ")
+      ExpressionTransformer.PrintWithIndentation(wr, fullExpr)
+      wr.flush()
+      wr.close()
+    }
+    //throw an exception if the candidate expression has reals
+    if (Util.hasMixedIntReals(instExpr)) {
+      //variablesOf(instExpr).foreach(id => println("Id: "+id+" type: "+id.getType))
+      throw new IllegalStateException("Instantiated VC of " + fd.id + " contains mixed integer/reals: " + instExpr)
+    }
+
+    //reporter.info("checking VC inst ...")
+    var t1 = System.currentTimeMillis()
+    val (res, model) = if (this.useIncrementalSolvingForVCs) {
+      innerSolver.push
+      innerSolver.assertCnstr(instExpr)
+      //dump the inst VC as SMTLIB
+      /*val filename = "vc" + FileCountGUID.getID + ".smt2"
+      Util.toZ3SMTLIB(innerSolver.getAssertions, filename, "", leonctx, program)
+      val writer = new PrintWriter(filename)
+      writer.println(innerSolver.ctrsToString(""))
+      writer.close()
+      println("vc dumped to: " + filename)*/
+
+      val solRes = innerSolver.check
+      innerSolver.pop()
+      solRes match {
+        case Some(true) => (solRes, innerSolver.getModel)
+        case _ => (solRes, Model.empty)
+      }
+    } else {
+      val solver = SimpleSolverAPI(SolverFactory(() => innerSolver))
+      solver.solveSAT(instExpr)
+    }
+    val vccTime = (System.currentTimeMillis() - t1)
+
+    if (verbose) reporter.info("checked VC inst... in " + vccTime / 1000.0 + "s")
+    Stats.updateCounterTime(vccTime, "VC-check-time", "disjuncts")
+    Stats.updateCumTime(vccTime, "TotalVCCTime")
+
+    //for debugging
+    if (this.trackUnpackedVCCTime) {
+      val upVCinst = simplifyArithmetic(TemplateInstantiator.instantiate(ctrTracker.getVC(fd).unpackedExpr, tempVarMap))
+      Stats.updateCounterStats(Util.atomNum(upVCinst), "UP-VC-size", "disjuncts")
+
+      t1 = System.currentTimeMillis()
+      val (res2, _) = SimpleSolverAPI(SolverFactory(() => new ExtendedUFSolver(leonctx, program))).solveSAT(upVCinst)
+      val unpackedTime = System.currentTimeMillis() - t1
+      if (res != res2) {
+        throw new IllegalStateException("Unpacked VC produces different result: " + upVCinst)
+      }
+      Stats.updateCumTime(unpackedTime, "TotalUPVCCTime")
+      reporter.info("checked UP-VC inst... in " + unpackedTime / 1000.0 + "s")
+    }
+
+    t1 = System.currentTimeMillis()
+    res match {
+      case None => {
+        throw new IllegalStateException("cannot check the satisfiability of " + funcVCs(fd))
+      }
+      case Some(false) => {
+        //do not generate any constraints
+        ((fls, Set()), tru)
+      }
+      case Some(true) => {
+        //For debugging purposes.
+        if (verbose) reporter.info("Function: " + fd.id + "--Found candidate invariant is not a real invariant! ")
+        if (this.printCounterExample) {
+          reporter.info("Model: " + model)
+        }
+
+        //get the disjuncts that are satisfied
+        val (data, newctr) = generateCtrsFromDisjunct(fd, model)
+        if (newctr == tru)
+          throw new IllegalStateException("Cannot find a counter-example path!!")
+
+        val t2 = System.currentTimeMillis()
+        Stats.updateCounterTime((t2 - t1), "Disj-choosing-time", "disjuncts")
+        Stats.updateCumTime((t2 - t1), "Total-Choose-Time")
+
+        (data, newctr)
+      }
+    }
+  }
+
+  val evaluator = new DefaultEvaluator(leonctx, program) //as of now used only for debugging
+  //a helper method
+  //TODO: this should also handle reals
+  protected def doesSatisfyModel(expr: Expr, model: Model): Boolean = {
+    evaluator.eval(expr, model).result match {
+      case Some(BooleanLiteral(true)) => true
+      case _ => false
+    }
+  }
+
+  /**
+   * Evaluator for a predicate that is a simple equality/inequality between two variables
+   */
+  protected def predEval(model: Model): (Expr => Boolean) = {
+    if (ctx.usereals) realEval(model)
+    else intEval(model)
+  }
+
+  protected def intEval(model: Model): (Expr => Boolean) = {
+    def modelVal(id: Identifier): BigInt = {
+      val InfiniteIntegerLiteral(v) = model(id)
+      v
+    }
+    def eval: (Expr => Boolean) = e => e match {
+      case And(args) => args.forall(eval)
+      // case Iff(Variable(id1), Variable(id2)) => model(id1) == model(id2)
+      case Equals(Variable(id1), Variable(id2)) => model(id1) == model(id2) //note: ADTs can also be compared for equality
+      case LessEquals(Variable(id1), Variable(id2)) => modelVal(id1) <= modelVal(id2)
+      case GreaterEquals(Variable(id1), Variable(id2)) => modelVal(id1) >= modelVal(id2)
+      case GreaterThan(Variable(id1), Variable(id2)) => modelVal(id1) > modelVal(id2)
+      case LessThan(Variable(id1), Variable(id2)) => modelVal(id1) < modelVal(id2)
+      case _ => throw new IllegalStateException("Predicate not handled: " + e)
+    }
+    eval
+  }
+
+  protected def realEval(model: Model): (Expr => Boolean) = {
+    def modelVal(id: Identifier): FractionalLiteral = {
+      //println("Identifier: "+id)
+      model(id).asInstanceOf[FractionalLiteral]
+    }
+    (e: Expr) => e match {
+      case Equals(Variable(id1), Variable(id2)) => model(id1) == model(id2) //note: ADTs can also be compared for equality
+      case Operator(Seq(Variable(id1), Variable(id2)), op) if (e.isInstanceOf[LessThan]
+        || e.isInstanceOf[LessEquals] || e.isInstanceOf[GreaterThan]
+        || e.isInstanceOf[GreaterEquals]) => {
+        evaluateRealPredicate(op(Seq(modelVal(id1), modelVal(id2))))
+      }
+      case _ => throw new IllegalStateException("Predicate not handled: " + e)
+    }
+  }
+
+  /**
+   * This solver does not use any theories other than UF/ADT. It assumes that other theories are axiomatized in the VC.
+   * This method can overloaded by the subclasses.
+   */
+  protected def axiomsForTheory(formula: Formula, calls: Set[Call], model: Model): Seq[Constraint] = Seq()
+
+  protected def generateCtrsFromDisjunct(fd: FunDef, model: Model): ((Expr, Set[Call]), Expr) = {
+
+    val formula = ctrTracker.getVC(fd)
+    //this picks the satisfiable disjunct of the VC modulo axioms
+    val satCtrs = formula.pickSatDisjunct(formula.firstRoot, model)
+    //for debugging
+    if (this.debugChooseDisjunct || this.printPathToConsole || this.dumpPathAsSMTLIB || this.verifyInvariant) {
+      val pathctrs = satCtrs.map(_.toExpr)
+      val plainFormula = Util.createAnd(pathctrs)
+      val pathcond = simplifyArithmetic(plainFormula)
+
+      if (this.debugChooseDisjunct) {
+        satCtrs.filter(_.isInstanceOf[LinearConstraint]).map(_.toExpr).foreach((ctr) => {
+          if (!doesSatisfyModel(ctr, model))
+            throw new IllegalStateException("Path ctr not satisfied by model: " + ctr)
+        })
+      }
+
+      if (this.verifyInvariant) {
+        println("checking invariant for path...")
+        val sat = Util.checkInvariant(pathcond, leonctx, program)
+      }
+
+      if (this.printPathToConsole) {
+        //val simpcond = ExpressionTransformer.unFlatten(pathcond, variablesOf(pathcond).filterNot(TVarFactory.isTemporary _))
+        val simpcond = pathcond
+        println("Full-path: " + ScalaPrinter(simpcond))
+        val filename = "full-path-" + FileCountGUID.getID + ".txt"
+        val wr = new PrintWriter(new File(filename))
+        ExpressionTransformer.PrintWithIndentation(wr, simpcond)
+        println("Printed to file: " + filename)
+        wr.flush()
+        wr.close()
+      }
+
+      if (this.dumpPathAsSMTLIB) {
+        val filename = "pathcond" + FileCountGUID.getID + ".smt2"
+        Util.toZ3SMTLIB(pathcond, filename, "QF_NIA", leonctx, program)
+        println("Path dumped to: " + filename)
+      }
+    }
+
+    var calls = Set[Call]()
+    var cons = Set[Expr]()
+    satCtrs.foreach(ctr => ctr match {
+      case t: Call => calls += t
+      case t: ADTConstraint if (t.cons.isDefined) => cons += t.cons.get
+      case _ => ;
+    })
+    val callExprs = calls.map(_.toExpr)
+
+    var t1 = System.currentTimeMillis()
+    val axiomCtrs = ctrTracker.specInstantiator.axiomsForCalls(formula, calls, model)
+    var t2 = System.currentTimeMillis()
+    Stats.updateCumTime((t2 - t1), "Total-AxiomChoose-Time")
+
+    //here, handle theory operations by reducing them to axioms.
+    //Note: uninterpreted calls/ADTs are handled below as they are more general. Here, we handle
+    //other theory axioms like: multiplication, sets, arrays, maps etc.
+    t1 = System.currentTimeMillis()
+    val theoryCtrs = axiomsForTheory(formula, calls, model)
+    t2 = System.currentTimeMillis()
+    Stats.updateCumTime((t2 - t1), "Total-TheoryAxiomatization-Time")
+
+    //Finally, eliminate UF/ADT
+    t1 = System.currentTimeMillis()
+    val callCtrs = (new UFADTEliminator(leonctx, program)).constraintsForCalls((callExprs ++ cons),
+      predEval(model)).map(ConstraintUtil.createConstriant _)
+    t2 = System.currentTimeMillis()
+    Stats.updateCumTime((t2 - t1), "Total-ElimUF-Time")
+
+    //exclude guards, separate calls and cons from the rest
+    var lnctrs = Set[LinearConstraint]()
+    var temps = Set[LinearTemplate]()
+    (satCtrs ++ callCtrs ++ axiomCtrs ++ theoryCtrs).foreach(ctr => ctr match {
+      case t: LinearConstraint => lnctrs += t
+      case t: LinearTemplate => temps += t
+      case _ => ;
+    })
+
+    if (this.debugChooseDisjunct) {
+      lnctrs.map(_.toExpr).foreach((ctr) => {
+        if (!doesSatisfyModel(ctr, model))
+          throw new IllegalStateException("Ctr not satisfied by model: " + ctr)
+      })
+    }
+
+    if (this.debugTheoryReduction) {
+      val simpPathCond = Util.createAnd((lnctrs ++ temps).map(_.template).toSeq)
+      if (this.verifyInvariant) {
+        println("checking invariant for simp-path...")
+        Util.checkInvariant(simpPathCond, leonctx, program)
+      }
+    }
+
+    if (this.trackNumericalDisjuncts) {
+      numericalDisjuncts :+= Util.createAnd((lnctrs ++ temps).map(_.template).toSeq)
+    }
+
+    val (data, nlctr) = processNumCtrs(lnctrs.toSeq, temps.toSeq)
+    ((data, calls), nlctr)
+  }
+
+  /**
+   * Endpoint of the pipeline. Invokes the Farkas Lemma constraint generation.
+   */
+  def processNumCtrs(lnctrs: Seq[LinearConstraint], temps: Seq[LinearTemplate]): (Expr, Expr) = {
+    //here we are invalidating A^~(B)
+    if (temps.isEmpty) {
+      //here ants ^ conseq is sat (otherwise we wouldn't reach here) and there is no way to falsify this path
+      (Util.createAnd(lnctrs.map(_.toExpr)), fls)
+    } else {
+
+      if (this.debugElimination) {
+        //println("Path Constraints (before elim): "+(lnctrs ++ temps))
+        if (this.verifyInvariant) {
+          println("checking invariant for disjunct before elimination...")
+          Util.checkInvariant(Util.createAnd((lnctrs ++ temps).map(_.template)), leonctx, program)
+        }
+      }
+      //compute variables to be eliminated
+      val t1 = System.currentTimeMillis()
+      val ctrVars = lnctrs.foldLeft(Set[Identifier]())((acc, lc) => acc ++ variablesOf(lc.toExpr))
+      val tempVars = temps.foldLeft(Set[Identifier]())((acc, lt) => acc ++ variablesOf(lt.template))
+      val elimVars = ctrVars.diff(tempVars)
+
+      val debugger = if (debugElimination && verifyInvariant) {
+        Some((ctrs: Seq[LinearConstraint]) => {
+          //println("checking disjunct before elimination...")
+          //println("ctrs: "+ctrs)
+          val debugRes = Util.checkInvariant(Util.createAnd((ctrs ++ temps).map(_.template)), leonctx, program)
+        })
+      } else None
+      val elimLnctrs = LinearConstraintUtil.apply1PRuleOnDisjunct(lnctrs, elimVars, debugger)
+      val t2 = System.currentTimeMillis()
+
+      if (this.debugElimination) {
+        println("Path constriants (after elimination): " + elimLnctrs)
+        if (this.verifyInvariant) {
+          println("checking invariant for disjunct after elimination...")
+          Util.checkInvariant(Util.createAnd((elimLnctrs ++ temps).map(_.template)), leonctx, program)
+        }
+      }
+      //for stats
+      if (ctx.dumpStats) {
+        var elimCtrCount = 0
+        var elimCtrs = Seq[LinearConstraint]()
+        var elimRems = Set[Identifier]()
+        elimLnctrs.foreach((lc) => {
+          val evars = variablesOf(lc.toExpr).intersect(elimVars)
+          if (!evars.isEmpty) {
+            elimCtrs :+= lc
+            elimCtrCount += 1
+            elimRems ++= evars
+          }
+        })
+        Stats.updateCounterStats((elimVars.size - elimRems.size), "Eliminated-Vars", "disjuncts")
+        Stats.updateCounterStats((lnctrs.size - elimLnctrs.size), "Eliminated-Atoms", "disjuncts")
+        Stats.updateCounterStats(temps.size, "Param-Atoms", "disjuncts")
+        Stats.updateCounterStats(lnctrs.size, "NonParam-Atoms", "disjuncts")
+        Stats.updateCumTime((t2 - t1), "ElimTime")
+      }
+      val newLnctrs = elimLnctrs.toSet.toSeq
+
+      //TODO:Remove transitive facts. E.g. a <= b, b <= c, a <=c can be simplified by dropping a <= c
+      //TODO: simplify the formulas and remove implied conjuncts if possible (note the formula is satisfiable, so there can be no inconsistencies)
+      //e.g, remove: a <= b if we have a = b or if a < b
+      //Also, enrich the rules for quantifier elimination: try z3 quantifier elimination on variables that have an equality.
+
+      //TODO: Use the dependence chains in the formulas to identify what to assertionize
+      // and what can never be implied by solving for the templates
+
+      val disjunct = Util.createAnd((newLnctrs ++ temps).map(_.template))
+      val implCtrs = farkasSolver.constraintsForUnsat(newLnctrs, temps)
+
+      //for debugging
+      if (this.debugReducedFormula) {
+        println("Final Path Constraints: " + disjunct)
+        if (this.verifyInvariant) {
+          println("checking invariant for final disjunct... ")
+          Util.checkInvariant(disjunct, leonctx, program)
+        }
+      }
+
+      (disjunct, implCtrs)
+    }
+  }
+}
diff --git a/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolverWithMult.scala b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolverWithMult.scala
new file mode 100644
index 000000000..10a232e3f
--- /dev/null
+++ b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolverWithMult.scala
@@ -0,0 +1,98 @@
+package leon
+package invariant.templateSolvers
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import leon.invariant._
+import scala.util.control.Breaks._
+import solvers._
+
+import invariant.engine._
+import invariant.factories._
+import invariant.util._
+import invariant.structure._
+
+class NLTemplateSolverWithMult(ctx : InferenceContext, rootFun: FunDef,
+  ctrTracker: ConstraintTracker, minimizer: Option[(Expr, Model) => Model])
+  extends NLTemplateSolver(ctx, rootFun, ctrTracker, minimizer) {
+
+  val axiomFactory = new AxiomFactory(ctx)
+
+  override def getVCForFun(fd: FunDef): Expr = {
+    val plainvc = ctrTracker.getVC(fd).toExpr
+    val nlvc = Util.multToTimes(plainvc)
+    nlvc
+  }
+
+  override def splitVC(fd: FunDef) : (Expr,Expr) = {
+    val (paramPart, rest) = ctrTracker.getVC(fd).splitParamPart
+    (Util.multToTimes(paramPart),Util.multToTimes(rest))
+  }
+
+  override def axiomsForTheory(formula : Formula, calls: Set[Call], model: Model) : Seq[Constraint] = {
+
+    //in the sequel we instantiate axioms for multiplication
+    val inst1 = unaryMultAxioms(formula, calls, predEval(model))
+    val inst2 = binaryMultAxioms(formula,calls, predEval(model))
+    val multCtrs = (inst1 ++ inst2).flatMap(_ match {
+      case And(args) => args.map(ConstraintUtil.createConstriant _)
+      case e => Seq(ConstraintUtil.createConstriant(e))
+    })
+
+    Stats.updateCounterStats(multCtrs.size, "MultAxiomBlowup", "disjuncts")
+    ctx.reporter.info("Number of multiplication induced predicates: "+multCtrs.size)
+    multCtrs
+  }
+
+  def chooseSATPredicate(expr: Expr, predEval: (Expr => Boolean)): Expr = {
+    val norme = ExpressionTransformer.normalizeExpr(expr,ctx.multOp)
+    val preds = norme match {
+      case Or(args) => args
+      case Operator(_, _) => Seq(norme)
+      case _ => throw new IllegalStateException("Not(ant) is not in expected format: " + norme)
+    }
+    //pick the first predicate that holds true
+    preds.collectFirst { case pred @ _ if predEval(pred) => pred }.get
+  }
+
+  def isMultOp(call : Call) : Boolean = {
+    Util.isMultFunctions(call.fi.tfd.fd)
+  }
+
+  def unaryMultAxioms(formula: Formula, calls: Set[Call], predEval: (Expr => Boolean)) : Seq[Expr] = {
+    val axioms = calls.flatMap {
+      case call@_ if (isMultOp(call) && axiomFactory.hasUnaryAxiom(call)) => {
+        val (ant,conseq) = axiomFactory.unaryAxiom(call)
+        if(predEval(ant))
+          Seq(ant,conseq)
+        else
+          Seq(chooseSATPredicate(Not(ant), predEval))
+      }
+      case _ => Seq()
+    }
+    axioms.toSeq
+  }
+
+  def binaryMultAxioms(formula: Formula, calls: Set[Call], predEval: (Expr => Boolean)) : Seq[Expr] = {
+
+    val mults = calls.filter(call => isMultOp(call) && axiomFactory.hasBinaryAxiom(call))
+    val product = Util.cross(mults,mults).collect{ case (c1,c2) if c1 != c2 => (c1,c2) }
+
+    ctx.reporter.info("Theory axioms: "+product.size)
+    Stats.updateCumStats(product.size, "-Total-theory-axioms")
+
+    val newpreds = product.flatMap(pair => {
+      val axiomInsts = axiomFactory.binaryAxiom(pair._1, pair._2)
+      axiomInsts.flatMap {
+        case (ant,conseq) if predEval(ant) => Seq(ant,conseq) 			//if axiom-pre holds.
+        case (ant,_) => Seq(chooseSATPredicate(Not(ant), predEval))		//if axiom-pre does not hold.
+      }
+    })
+    newpreds.toSeq
+  }
+}
diff --git a/src/main/scala/leon/invariant/templateSolvers/TemplateSolver.scala b/src/main/scala/leon/invariant/templateSolvers/TemplateSolver.scala
new file mode 100644
index 000000000..9b360c2db
--- /dev/null
+++ b/src/main/scala/leon/invariant/templateSolvers/TemplateSolver.scala
@@ -0,0 +1,117 @@
+package leon
+package invariant.templateSolvers
+
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import leon.invariant._
+import scala.util.control.Breaks._
+import scala.concurrent._
+import scala.concurrent.duration._
+import invariant.engine._
+import invariant.factories._
+import invariant.util._
+import invariant.structure._
+import invariant.structure.FunctionUtils._
+import leon.solvers.Model
+
+abstract class TemplateSolver(ctx: InferenceContext, val rootFun: FunDef,
+  ctrTracker: ConstraintTracker) {
+
+  protected val reporter = ctx.reporter
+  //protected val cg = CallGraphUtil.constructCallGraph(program)
+
+  //some constants
+  protected val fls = BooleanLiteral(false)
+  protected val tru = BooleanLiteral(true)
+  //protected val zero = IntLiteral(0)
+
+  private val dumpVCtoConsole = false
+  private val dumpVCasText = false
+  private val dumpVCasSMTLIB = false
+
+  /**
+   * Completes a model by adding mapping to new template variables
+   */
+  def completeModel(model: Map[Identifier, Expr], tempIds: Set[Identifier]): Map[Identifier, Expr] = {
+    tempIds.map((id) => {
+      if (!model.contains(id)) {
+        (id, simplestValue(id.getType))
+      } else (id, model(id))
+    }).toMap
+  }
+
+  /**
+   * Computes the invariant for all the procedures given a mapping for the
+   * template variables.
+   */
+  def getAllInvariants(model: Model): Map[FunDef, Expr] = {
+    val templates = ctrTracker.getFuncs.collect {
+      case fd if fd.hasTemplate =>
+        fd -> fd.getTemplate
+    }
+    TemplateInstantiator.getAllInvariants(model, templates.toMap)
+  }
+
+  protected def getVCForFun(fd: FunDef): Expr = {
+    ctrTracker.getVC(fd).toExpr
+  }
+
+  /**
+   * This function computes invariants belonging to the given templates incrementally.
+   * The result is a mapping from function definitions to the corresponding invariants.
+   */
+  def solveTemplates(): (Option[Model], Option[Set[Call]]) = {
+    //traverse each of the functions and collect the VCs
+    val funcs = ctrTracker.getFuncs
+    val funcExprs = funcs.map((fd) => {
+      val vc = if (ctx.usereals)
+        ExpressionTransformer.IntLiteralToReal(getVCForFun(fd))
+      else getVCForFun(fd)
+      if (dumpVCtoConsole || dumpVCasText || dumpVCasSMTLIB) {
+        //val simpForm = simplifyArithmetic(vc)
+        val filename = "vc-" + FileCountGUID.getID
+        if (dumpVCtoConsole) {
+          println("Func: " + fd.id + " VC: " + vc)
+        }
+        if (dumpVCasText) {
+          val wr = new PrintWriter(new File(filename + ".txt"))
+          //ExpressionTransformer.PrintWithIndentation(wr, vcstr)
+          println("Printed VC of " + fd.id + " to file: " + filename)
+          wr.println(vc.toString)
+          wr.flush()
+          wr.close()
+        }
+        if (dumpVCasSMTLIB) {
+          Util.toZ3SMTLIB(vc, filename + ".smt2", "QF_LIA", ctx.leonContext, ctx.program)
+          println("Printed VC of " + fd.id + " to file: " + filename)
+        }
+      }
+
+      if (ctx.dumpStats) {
+        Stats.updateCounterStats(Util.atomNum(vc), "VC-size", "VC-refinement")
+        Stats.updateCounterStats(Util.numUIFADT(vc), "UIF+ADT", "VC-refinement")
+      }
+      (fd -> vc)
+    }).toMap
+    //Assign some values for the template variables at random (actually use the simplest value for the type)
+    val tempIds = funcExprs.foldLeft(Set[Identifier]()) {
+      case (acc, (_, vc)) =>
+        //val tempOption = if (fd.hasTemplate) Some(fd.getTemplate) else None
+        //if (!tempOption.isDefined) acc
+        //else
+        acc ++ Util.getTemplateIds(vc)
+    }
+
+    Stats.updateCounterStats(tempIds.size, "TemplateIds", "VC-refinement")
+    val solution = solve(tempIds, funcExprs)
+    solution
+  }
+
+  def solve(tempIds: Set[Identifier], funcVCs: Map[FunDef, Expr]): (Option[Model], Option[Set[Call]])
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/templateSolvers/UFADTEliminator.scala b/src/main/scala/leon/invariant/templateSolvers/UFADTEliminator.scala
new file mode 100644
index 000000000..fb7519850
--- /dev/null
+++ b/src/main/scala/leon/invariant/templateSolvers/UFADTEliminator.scala
@@ -0,0 +1,288 @@
+package leon
+package invariant.templateSolvers
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import leon.invariant.util.UndirectedGraph
+import scala.util.control.Breaks._
+import invariant.util._
+import leon.purescala.TypeOps
+
+class UFADTEliminator(ctx: LeonContext, program: Program) {
+
+  val debugAliases = false
+  val makeEfficient = true //this will happen at the expense of completeness
+  val reporter = ctx.reporter
+  val verbose = false
+
+  def collectCompatibleCalls(calls: Set[Expr]) = {
+    //compute the cartesian product of the calls and select the pairs having the same function symbol and also implied by the precond
+    val vec = calls.toArray
+    val size = calls.size
+    var j = 0
+    //for stats
+    var tuples = 0
+    var functions = 0
+    var adts = 0
+    val product = vec.foldLeft(Set[(Expr, Expr)]())((acc, call) => {
+
+      //an optimization: here we can exclude calls to maxFun from axiomatization, they will be inlined anyway
+      /*val shouldConsider = if(InvariantUtil.isCallExpr(call)) {
+        val BinaryOperator(_,FunctionInvocation(calledFun,_), _) = call
+        if(calledFun == DepthInstPhase.maxFun) false
+        else true
+      } else true*/
+      var pairs = Set[(Expr, Expr)]()
+      for (i <- j + 1 until size) {
+        val call2 = vec(i)
+        if (mayAlias(call, call2)) {
+
+          call match {
+            case Equals(_, fin : FunctionInvocation) => functions += 1
+            case Equals(_, tup : Tuple) => tuples += 1
+            case _ => adts += 1
+          }
+          if (debugAliases)
+            println("Aliases: " + call + "," + call2)
+
+          pairs ++= Set((call, call2))
+
+        } else {
+          if (debugAliases) {
+            (call, call2) match {
+              case (Equals(_, t1 @ Tuple(_)), Equals(_, t2 @ Tuple(_))) =>
+                println("No Aliases: " + t1.getType + "," + t2.getType)
+              case _ => println("No Aliases: " + call + "," + call2)
+            }
+          }
+        }
+      }
+      j += 1
+      acc ++ pairs
+    })
+    if(verbose) reporter.info("Number of compatible calls: " + product.size)
+    /*reporter.info("Compatible Tuples: "+tuples)
+    reporter.info("Compatible Functions+ADTs: "+(functions+adts))*/
+    Stats.updateCounterStats(product.size, "Compatible-Calls", "disjuncts")
+    Stats.updateCumStats(functions, "Compatible-functioncalls")
+    Stats.updateCumStats(adts, "Compatible-adtcalls")
+    Stats.updateCumStats(tuples, "Compatible-tuples")
+    product
+  }
+
+  /**
+   * Convert the theory formula into linear arithmetic formula.
+   * The calls could be functions calls or ADT constructor calls.
+   * 'predEval' is an evaluator that evaluates a predicate to a boolean value
+   */
+  def constraintsForCalls(calls: Set[Expr], predEval: (Expr => Boolean)): Seq[Expr] = {
+
+    //check if two calls (to functions or ADT cons) have the same value in the model
+    def doesAlias(call1: Expr, call2: Expr): Boolean = {
+      val Operator(Seq(r1 @ Variable(_), _), _) = call1
+      val Operator(Seq(r2 @ Variable(_), _), _) = call2
+      val resEquals = predEval(Equals(r1, r2))
+      if (resEquals) {
+        if (Util.isCallExpr(call1)) {
+          val (ants, _) = axiomatizeCalls(call1, call2)
+          val antsHold = ants.forall(ant => {
+            val Operator(Seq(lvar @ Variable(_), rvar @ Variable(_)), _) = ant
+            //(model(lid) == model(rid))
+            predEval(Equals(lvar, rvar))
+          })
+          antsHold
+        } else true
+      } else false
+    }
+
+    def predForEquality(call1: Expr, call2: Expr): Seq[Expr] = {
+
+      val eqs = if (Util.isCallExpr(call1)) {
+        val (_, rhs) = axiomatizeCalls(call1, call2)
+        Seq(rhs)
+      } else {
+        val (lhs, rhs) = axiomatizeADTCons(call1, call2)
+        lhs :+ rhs
+      }
+      //remove self equalities.
+      val preds = eqs.filter(_ match {
+        case Operator(Seq(Variable(lid), Variable(rid)), _) => {
+          if (lid == rid) false
+          else {
+            if (lid.getType == Int32Type || lid.getType == RealType || lid.getType == IntegerType) true
+            else false
+          }
+        }
+        case e @ _ => throw new IllegalStateException("Not an equality or Iff: " + e)
+      })
+      preds
+    }
+
+    def predForDisequality(call1: Expr, call2: Expr): Seq[Expr] = {
+
+      val (ants, _) = if (Util.isCallExpr(call1)) {
+        axiomatizeCalls(call1, call2)
+      } else {
+        axiomatizeADTCons(call1, call2)
+      }
+
+      if (makeEfficient && ants.exists(_ match {
+        case Equals(l, r) if (l.getType != RealType && l.getType != BooleanType && l.getType != IntegerType) => true
+        case _ => false
+      })) {
+        Seq()
+      } else {
+        var unsatIntEq: Option[Expr] = None
+        var unsatOtherEq: Option[Expr] = None
+        ants.foreach(eq =>
+          if (!unsatOtherEq.isDefined) {
+            eq match {
+              case Equals(lhs @ Variable(_), rhs @ Variable(_)) if !predEval(Equals(lhs, rhs)) => {
+                if (lhs.getType != Int32Type && lhs.getType != RealType && lhs.getType != IntegerType)
+                  unsatOtherEq = Some(eq)
+                else if (!unsatIntEq.isDefined)
+                  unsatIntEq = Some(eq)
+              }
+              case _ => ;
+            }
+          })
+        if (unsatOtherEq.isDefined) Seq() //need not add any constraint
+        else if (unsatIntEq.isDefined) {
+          //pick the constraint a < b or a > b that is satisfied
+          val Equals(lhs @ Variable(_), rhs @ Variable(_)) = unsatIntEq.get
+          val lLTr = LessThan(lhs, rhs)
+          val atom = if (predEval(lLTr)) lLTr
+          else GreaterThan(lhs, rhs)
+          /*val InfiniteIntegerLiteral(lval) = model(lid)
+          val InfiniteIntegerLiteral(rval) = model(rid)
+          val atom = if (lval < rval) LessThan(lhs, rhs)
+          else if (lval > rval) GreaterThan(lhs, rhs)
+          else throw new IllegalStateException("Models are equal!!")*/
+
+          /*if (ants.exists(_ match {
+              case Equals(l, r) if (l.getType != Int32Type && l.getType != RealType && l.getType != BooleanType && l.getType != IntegerType) => true
+              case _ => false
+            })) {
+              Stats.updateCumStats(1, "Diseq-blowup")
+            }*/
+          Seq(atom)
+        } else throw new IllegalStateException("All arguments are equal: " + (call1, call2))
+      }
+    }
+
+    var eqGraph = new UndirectedGraph[Expr]() //an equality graph
+    var neqSet = Set[(Expr, Expr)]()
+    val product = collectCompatibleCalls(calls)
+    val newctrs = product.foldLeft(Seq[Expr]())((acc, pair) => {
+      val (call1, call2) = (pair._1, pair._2)
+      //println("Assertionizing "+call1+" , call2: "+call2)
+      if (!eqGraph.BFSReach(call1, call2) && !neqSet.contains((call1, call2)) && !neqSet.contains((call2, call1))) {
+        if (doesAlias(call1, call2)) {
+          eqGraph.addEdge(call1, call2)
+          //note: here it suffices to check for adjacency and not reachability of calls (i.e, exprs).
+          //This is because the transitive equalities (corresponding to rechability) are encoded by the generated equalities.
+          acc ++ predForEquality(call1, call2)
+
+        } else {
+          neqSet ++= Set((call1, call2))
+          acc ++ predForDisequality(call1, call2)
+        }
+      } else acc
+    })
+
+    //reporter.info("Number of equal calls: " + eqGraph.getEdgeCount)
+    newctrs
+  }
+
+  /**
+   * This function actually checks if two non-primitive expressions could have the same value
+   * (when some constraints on their arguments hold).
+   * Remark: notice  that when the expressions have ADT types, then this is basically a form of may-alias check.
+   * TODO: handling generic can become very trickier here.
+   */
+  def mayAlias(e1: Expr, e2: Expr): Boolean = {
+    //check if call and call2 are compatible
+    /*(e1, e2) match {
+      case (Equals(_, FunctionInvocation(fd1, _)), Equals(_, FunctionInvocation(fd2, _))) if (fd1.id == fd2.id) => true
+      case (Equals(_, CaseClass(cd1, _)), Equals(_, CaseClass(cd2, _))) if (cd1.id == cd2.id) => true
+      case (Equals(_, tp1 @ Tuple(e1)), Equals(_, tp2 @ Tuple(e2))) => {
+        //get the types and check if the types are compatible
+        val TupleType(tps1) = tp1.getType
+        val TupleType(tps2) = tp2.getType
+        (tps1 zip tps2).forall(pair => {
+          val (t1, t2) = pair
+          val lub = TypeOps.leastUpperBound(t1, t2)
+          (lub == Some(t1) || lub == Some(t2))
+        })
+      }
+      case _ => false
+    }*/
+    (e1, e2) match {
+      case (Equals(_, FunctionInvocation(fd1, _)), Equals(_, FunctionInvocation(fd2, _))) => {
+        (fd1.id == fd2.id && fd1.fd.tparams == fd2.fd.tparams)
+      }
+      case (Equals(_, CaseClass(cd1, _)), Equals(_, CaseClass(cd2, _))) => {
+        // if (cd1.id == cd2.id && cd1.tps != cd2.tps) println("Invalidated the classes " + e1 + " " + e2)
+        (cd1.id == cd2.id && cd1.tps == cd2.tps)
+      }
+      case (Equals(_, tp1 @ Tuple(e1)), Equals(_, tp2 @ Tuple(e2))) => {
+        //get the types and check if the types are compatible
+        val TupleType(tps1) = tp1.getType
+        val TupleType(tps2) = tp2.getType
+        (tps1 zip tps2).forall(pair => {
+          val (t1, t2) = pair
+          val lub = TypeOps.leastUpperBound(t1, t2)
+          (lub == Some(t1) || lub == Some(t2))
+        })
+      }
+      case _ => false
+    }
+  }
+
+  /**
+   * This procedure generates constraints for the calls to be equal
+   */
+  def axiomatizeCalls(call1: Expr, call2: Expr): (Seq[Expr], Expr) = {
+    val (v1, fi1, v2, fi2) = {
+      val Equals(r1, f1 @ FunctionInvocation(_, _)) = call1
+      val Equals(r2, f2 @ FunctionInvocation(_, _)) = call2
+      (r1, f1, r2, f2)
+    }
+
+    val ants = (fi1.args.zip(fi2.args)).foldLeft(Seq[Expr]())((acc, pair) => {
+      val (arg1, arg2) = pair
+      acc :+ Equals(arg1, arg2)
+    })
+    val conseq = Equals(v1, v2)
+    (ants, conseq)
+  }
+
+  /**
+   * The returned pairs should be interpreted as a bidirectional implication
+   */
+  def axiomatizeADTCons(sel1: Expr, sel2: Expr): (Seq[Expr], Expr) = {
+
+    val (v1, args1, v2, args2) = sel1 match {
+      case Equals(r1 @ Variable(_), CaseClass(_, a1)) => {
+        val Equals(r2 @ Variable(_), CaseClass(_, a2)) = sel2
+        (r1, a1, r2, a2)
+      }
+      case Equals(r1 @ Variable(_), Tuple(a1)) => {
+        val Equals(r2 @ Variable(_), Tuple(a2)) = sel2
+        (r1, a1, r2, a2)
+      }
+    }
+
+    val ants = (args1.zip(args2)).foldLeft(Seq[Expr]())((acc, pair) => {
+      val (arg1, arg2) = pair
+      acc :+ Equals(arg1, arg2)
+    })
+    val conseq = Equals(v1, v2)
+    (ants, conseq)
+  }
+}
diff --git a/src/main/scala/leon/invariant/util/CallGraph.scala b/src/main/scala/leon/invariant/util/CallGraph.scala
new file mode 100644
index 000000000..73ac3b099
--- /dev/null
+++ b/src/main/scala/leon/invariant/util/CallGraph.scala
@@ -0,0 +1,139 @@
+package leon
+package invariant.util
+
+import purescala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import Util._
+import invariant.structure.FunctionUtils._
+
+/**
+ * This represents a call graph of the functions in the program
+ */
+class CallGraph {
+  val graph = new DirectedGraph[FunDef]()
+
+  def addFunction(fd: FunDef) = graph.addNode(fd)
+
+  def addEdgeIfNotPresent(src: FunDef, callee: FunDef): Unit = {
+    if (!graph.containsEdge(src, callee))
+      graph.addEdge(src, callee)
+  }
+
+  def callees(src: FunDef): Set[FunDef] = {
+    graph.getSuccessors(src)
+  }
+
+  def transitiveCallees(src: FunDef): Set[FunDef] = {
+    graph.BFSReachables(src)
+  }
+
+  def isRecursive(fd: FunDef): Boolean = {
+    transitivelyCalls(fd, fd)
+  }
+
+  /**
+   * Checks if the src transitively calls the procedure proc
+   */
+  def transitivelyCalls(src: FunDef, proc: FunDef): Boolean = {
+    //important: We cannot say that src calls it self even though source is reachable from itself in the callgraph
+    graph.BFSReach(src, proc, excludeSrc = true)
+  }
+
+  def calls(src: FunDef, proc: FunDef): Boolean = {
+    graph.containsEdge(src, proc)
+  }
+
+  /**
+   * sorting functions in ascending topological order
+   */
+  def topologicalOrder: Seq[FunDef] = {
+
+    def insert(index: Int, l: Seq[FunDef], fd: FunDef): Seq[FunDef] = {
+      var i = 0
+      var head = Seq[FunDef]()
+      l.foreach((elem) => {
+        if (i == index)
+          head :+= fd
+        head :+= elem
+        i += 1
+      })
+      head
+    }
+
+    var funcList = Seq[FunDef]()
+    graph.getNodes.toList.foreach((f) => {
+      var inserted = false
+      var index = 0
+      for (i <- 0 to funcList.length - 1) {
+        if (!inserted && this.transitivelyCalls(funcList(i), f)) {
+          index = i
+          inserted = true
+        }
+      }
+      if (!inserted)
+        funcList :+= f
+      else funcList = insert(index, funcList, f)
+    })
+
+    funcList
+  }
+
+  override def toString: String = {
+    val procs = graph.getNodes
+    procs.foldLeft("")((acc, proc) => {
+      acc + proc.id + " --calls--> " +
+        graph.getSuccessors(proc).foldLeft("")((acc, succ) => acc + "," + succ.id) + "\n"
+    })
+  }
+}
+
+object CallGraphUtil {
+
+  def constructCallGraph(prog: Program, onlyBody: Boolean = false, withTemplates: Boolean = false): CallGraph = {
+//
+    // println("Constructing call graph")
+    val cg = new CallGraph()
+    functionsWOFields(prog.definedFunctions).foreach((fd) => {
+      if (fd.hasBody) {
+        // println("Adding func " + fd.id.uniqueName)
+        var funExpr = fd.body.get
+        if (!onlyBody) {
+          if (fd.hasPrecondition)
+            funExpr = Tuple(Seq(funExpr, fd.precondition.get))
+          if (fd.hasPostcondition)
+            funExpr = Tuple(Seq(funExpr, fd.postcondition.get))
+        }
+        if (withTemplates && fd.hasTemplate) {
+          funExpr = Tuple(Seq(funExpr, fd.getTemplate))
+        }
+
+        //introduce a new edge for every callee
+        val callees = getCallees(funExpr)
+        if (callees.isEmpty)
+          cg.addFunction(fd)
+        else
+          callees.foreach(cg.addEdgeIfNotPresent(fd, _))
+      }
+    })
+    cg
+  }
+
+  def getCallees(expr: Expr): Set[FunDef] = {
+    var callees = Set[FunDef]()
+    simplePostTransform((expr) => expr match {
+      //note: do not consider field invocations
+      case FunctionInvocation(TypedFunDef(callee, _), args)
+      	if callee.isRealFunction => {
+        callees += callee
+        expr
+      }
+      case _ => expr
+    })(expr)
+    callees
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/util/ExpressionTransformer.scala b/src/main/scala/leon/invariant/util/ExpressionTransformer.scala
new file mode 100644
index 000000000..e38bdf3aa
--- /dev/null
+++ b/src/main/scala/leon/invariant/util/ExpressionTransformer.scala
@@ -0,0 +1,660 @@
+package leon
+package invariant.util
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import java.io._
+import purescala.ScalaPrinter
+import invariant.structure.Call
+import invariant.structure.FunctionUtils._
+import leon.invariant.factories.TemplateIdFactory
+
+/**
+ * A collection of transformation on expressions and some utility methods.
+ * These operations are mostly semantic preserving (specific assumptions/requirements are specified on the operations)
+ */
+object ExpressionTransformer {
+
+  val zero = InfiniteIntegerLiteral(0)
+  val one = InfiniteIntegerLiteral(1)
+  val mone = InfiniteIntegerLiteral(-1)
+  val tru = BooleanLiteral(true)
+  val fls = BooleanLiteral(false)
+  val bone = BigInt(1)
+
+  /**
+   * This function conjoins the conjuncts created by 'transfomer' within the clauses containing Expr.
+   * This is meant to be used by operations that may flatten subexpression using existential quantifiers.
+   * @param insideFunction when set to true indicates that the newConjuncts (second argument)
+   * should not conjoined to the And(..) / Or(..) expressions found because they
+   * may be called inside a function.
+   */
+  def conjoinWithinClause(e: Expr, transformer: (Expr, Boolean) => (Expr, Set[Expr]),
+    insideFunction: Boolean): (Expr, Set[Expr]) = {
+      e match {
+        case And(args) if !insideFunction => {
+          val newargs = args.map((arg) => {
+            val (nexp, ncjs) = transformer(arg, false)
+            Util.createAnd(nexp +: ncjs.toSeq)
+          })
+          (Util.createAnd(newargs), Set())
+        }
+
+        case Or(args) if !insideFunction => {
+          val newargs = args.map((arg) => {
+            val (nexp, ncjs) = transformer(arg, false)
+            Util.createAnd(nexp +: ncjs.toSeq)
+          })
+          (Util.createOr(newargs), Set())
+        }
+
+        case t: Terminal => (t, Set())
+
+        /*case BinaryOperator(e1, e2, op) => {
+          val (nexp1, ncjs1) = transformer(e1, true)
+          val (nexp2, ncjs2) = transformer(e2, true)
+          (op(nexp1, nexp2), ncjs1 ++ ncjs2)
+        }
+
+        case u @ UnaryOperator(e1, op) => {
+          val (nexp, ncjs) = transformer(e1, true)
+          (op(nexp), ncjs)
+        }*/
+
+        case n @ Operator(args, op) => {
+          var ncjs = Set[Expr]()
+          val newargs = args.map((arg) => {
+            val (nexp, js) = transformer(arg, true)
+            ncjs ++= js
+            nexp
+          })
+          (op(newargs), ncjs)
+        }
+        case _ => throw new IllegalStateException("Impossible event: expr did not match any case: " + e)
+      }
+    }
+
+  /**
+   * Assumed that that given expression has boolean type
+   * converting if-then-else and let into a logical formula
+   */
+  def reduceLangBlocks(inexpr: Expr, multop: (Expr, Expr) => Expr) = {
+
+    def transform(e: Expr, insideFunction: Boolean): (Expr, Set[Expr]) = {
+      e match {
+        // Handle asserts here. Return flattened body as the result
+        case as @ Assert(pred, _, body) => {
+          val freshvar = TVarFactory.createTemp("asrtres", e.getType).toVariable
+          val newexpr = Equals(freshvar, body)
+          val resset = transform(newexpr, insideFunction)
+          (freshvar, resset._2 + resset._1)
+        }
+        //handles division by constant
+        case Division(lhs, rhs @ InfiniteIntegerLiteral(v)) => {
+          //this models floor and not integer division
+          val quo = TVarFactory.createTemp("q", IntegerType).toVariable
+          var possibs = Seq[Expr]()
+          for (i <- v - 1 to 0 by -1) {
+            if (i == 0) possibs :+= Equals(lhs, Times(rhs, quo))
+            else possibs :+= Equals(lhs, Plus(Times(rhs, quo), InfiniteIntegerLiteral(i)))
+          }
+          //compute the disjunction of all possibs
+          val newexpr = Or(possibs)
+          //println("newexpr: "+newexpr)
+          val resset = transform(newexpr, true)
+          (quo, resset._2 + resset._1)
+        }
+        //handles division by variables
+        case Division(lhs, rhs) => {
+          //this models floor and not integer division
+          val quo = TVarFactory.createTemp("q", IntegerType).toVariable
+          val rem = TVarFactory.createTemp("r", IntegerType).toVariable
+          val mult = multop(quo, rhs)
+          val divsem = Equals(lhs, Plus(mult, rem))
+          //TODO: here, we have to use |rhs|
+          val newexpr = Util.createAnd(Seq(divsem, LessEquals(zero, rem), LessEquals(rem, Minus(rhs, one))))
+          val resset = transform(newexpr, true)
+          (quo, resset._2 + resset._1)
+        }
+        case err @ Error(_, msg) => {
+          //replace this by a fresh variable of the error type
+          (TVarFactory.createTemp("err", err.getType).toVariable, Set[Expr]())
+        }
+        case Equals(lhs, rhs) => {
+          val (nexp1, ncjs1) = transform(lhs, true)
+          val (nexp2, ncjs2) = transform(rhs, true)
+          (Equals(nexp1, nexp2), ncjs1 ++ ncjs2)
+        }
+        case IfExpr(cond, thn, elze) => {
+          val freshvar = TVarFactory.createTemp("ifres", e.getType).toVariable
+          val newexpr = Or(And(cond, Equals(freshvar, thn)), And(Not(cond), Equals(freshvar, elze)))
+          val resset = transform(newexpr, insideFunction)
+          (freshvar, resset._2 + resset._1)
+        }
+        case Let(binder, value, body) => {
+          //TODO: do we have to consider reuse of let variables ?
+          val (resbody, bodycjs) = transform(body, true)
+          val (resvalue, valuecjs) = transform(value, true)
+
+          (resbody, (valuecjs + Equals(binder.toVariable, resvalue)) ++ bodycjs)
+        }
+        //the value is a tuple in the following case
+        case LetTuple(binders, value, body) => {
+          //TODO: do we have to consider reuse of let variables ?
+          val (resbody, bodycjs) = transform(body, true)
+          val (resvalue, valuecjs) = transform(value, true)
+
+          //here we optimize the case where resvalue itself has tuples
+          val newConjuncts = resvalue match {
+            case Tuple(args) => {
+              binders.zip(args).map((elem) => {
+                val (bind, arg) = elem
+                Equals(bind.toVariable, arg)
+              })
+            }
+            case _ => {
+              //may it is better to assign resvalue to a temporary variable (if it is not already a variable)
+              val (resvalue2, cjs) = resvalue match {
+                case t: Terminal => (t, Seq())
+                case _ => {
+                  val freshres = TVarFactory.createTemp("tres", resvalue.getType).toVariable
+                  (freshres, Seq(Equals(freshres, resvalue)))
+                }
+              }
+              var i = 0
+              val cjs2 = binders.map((bind) => {
+                i += 1
+                Equals(bind.toVariable, TupleSelect(resvalue2, i))
+              })
+              (cjs ++ cjs2)
+            }
+          }
+
+          (resbody, (valuecjs ++ newConjuncts) ++ bodycjs)
+        }
+        case _ => {
+          conjoinWithinClause(e, transform, false)
+        }
+      }
+    }
+    val (nexp, ncjs) = transform(inexpr, false)
+    val res = if (!ncjs.isEmpty) {
+      Util.createAnd(nexp +: ncjs.toSeq)
+    } else nexp
+    res
+  }
+
+  /**
+   * Requires: The expression has to be in NNF form and without if-then-else and let constructs
+   * Assumed that that given expression has boolean type
+   * (a) the function replaces every function call by a variable and creates a new equality
+   * (b) it also replaces arguments that are not variables by fresh variables and creates
+   * a new equality mapping the fresh variable to the argument expression
+   */
+  def FlattenFunction(inExpr: Expr): Expr = {
+
+    /**
+     * First return value is the new expression. The second return value is the
+     * set of new conjuncts
+     * @param insideFunction when set to true indicates that the newConjuncts (second argument)
+     * should not conjoined to the And(..) / Or(..) expressions found because they
+     * may be called inside a function.
+     */
+    def flattenFunc(e: Expr, insideFunction: Boolean): (Expr, Set[Expr]) = {
+      e match {
+        case fi @ FunctionInvocation(fd, args) => {
+          //now also flatten the args. The following is slightly tricky
+          val (newargs, newConjuncts) = flattenArgs(args, true)
+          //create a new equality in UIFs
+          val newfi = FunctionInvocation(fd, newargs)
+          //create a new variable to represent the function
+          val freshResVar = Variable(TVarFactory.createTemp("r", fi.getType))
+          val res = (freshResVar, newConjuncts + Equals(freshResVar, newfi))
+          res
+        }
+        case inst @ IsInstanceOf(e1, cd) => {
+          //replace e by a variable
+          val (newargs, newcjs) = flattenArgs(Seq(e1), true)
+          var newConjuncts = newcjs
+
+          val freshArg = newargs(0)
+          val newInst = IsInstanceOf(freshArg, cd)
+          val freshResVar = Variable(TVarFactory.createTemp("ci", inst.getType))
+          newConjuncts += Equals(freshResVar, newInst)
+          (freshResVar, newConjuncts)
+        }
+        case cs @ CaseClassSelector(cd, e1, sel) => {
+          val (newargs, newcjs) = flattenArgs(Seq(e1), true)
+          var newConjuncts = newcjs
+
+          val freshArg = newargs(0)
+          val newCS = CaseClassSelector(cd, freshArg, sel)
+          val freshResVar = Variable(TVarFactory.createTemp("cs", cs.getType))
+          newConjuncts += Equals(freshResVar, newCS)
+
+          (freshResVar, newConjuncts)
+        }
+        case ts @ TupleSelect(e1, index) => {
+          val (newargs, newcjs) = flattenArgs(Seq(e1), true)
+          var newConjuncts = newcjs
+
+          val freshArg = newargs(0)
+          val newTS = TupleSelect(freshArg, index)
+          val freshResVar = Variable(TVarFactory.createTemp("ts", ts.getType))
+          newConjuncts += Equals(freshResVar, newTS)
+
+          (freshResVar, newConjuncts)
+        }
+        case cc @ CaseClass(cd, args) => {
+
+          val (newargs, newcjs) = flattenArgs(args, true)
+          var newConjuncts = newcjs
+
+          val newCC = CaseClass(cd, newargs)
+          val freshResVar = Variable(TVarFactory.createTemp("cc", cc.getType))
+          newConjuncts += Equals(freshResVar, newCC)
+
+          (freshResVar, newConjuncts)
+        }
+        case tp @ Tuple(args) => {
+          val (newargs, newcjs) = flattenArgs(args, true)
+          var newConjuncts = newcjs
+
+          val newTP = Tuple(newargs)
+          val freshResVar = Variable(TVarFactory.createTemp("tp", tp.getType))
+          // if(freshResVar.id.toString == "tp6"){
+          //   println("Creating temporary tp6 type: "+tp.getType+" expr: "+tp)
+          //   throw new IllegalStateException("")
+          // }
+          newConjuncts += Equals(freshResVar, newTP)
+
+          (freshResVar, newConjuncts)
+        }
+        case _ => conjoinWithinClause(e, flattenFunc, insideFunction)
+      }
+    }
+
+    def flattenArgs(args: Seq[Expr], insideFunction: Boolean): (Seq[Expr], Set[Expr]) = {
+      var newConjuncts = Set[Expr]()
+      val newargs = args.map((arg) =>
+        arg match {
+          case v: Variable => v
+          case r: ResultVariable => r
+          case _ => {
+            val (nexpr, ncjs) = flattenFunc(arg, insideFunction)
+
+            newConjuncts ++= ncjs
+
+            nexpr match {
+              case v: Variable => v
+              case r: ResultVariable => r
+              case _ => {
+                val freshArgVar = Variable(TVarFactory.createTemp("arg", arg.getType))
+                newConjuncts += Equals(freshArgVar, nexpr)
+                freshArgVar
+              }
+            }
+          }
+        })
+      (newargs, newConjuncts)
+    }
+
+    val (nexp, ncjs) = flattenFunc(inExpr, false)
+    if (!ncjs.isEmpty) {
+      Util.createAnd(nexp +: ncjs.toSeq)
+    } else nexp
+  }
+
+  /**
+   * The following procedure converts the formula into negated normal form by pushing all not's inside.
+   * It also handles disequality constraints.
+   * Assumption:
+   *  (a) the formula does not have match constructs
+   * Some important features.
+   * (a) For a strict inequality with real variables/constants, the following produces a strict inequality
+   * (b) Strict inequalities with only integer variables/constants are reduced to non-strict inequalities
+   */
+  def TransformNot(expr: Expr, retainNEQ: Boolean = false): Expr = { // retainIff : Boolean = false
+    def nnf(inExpr: Expr): Expr = {
+
+      if (inExpr.getType != BooleanType) inExpr
+      else inExpr match {
+        case Not(Not(e1)) => nnf(e1)
+        case e @ Not(t: Terminal) => e
+        case e @ Not(FunctionInvocation(_, _)) => e
+        case Not(And(args)) => Util.createOr(args.map(arg => nnf(Not(arg))))
+        case Not(Or(args)) => Util.createAnd(args.map(arg => nnf(Not(arg))))
+        case Not(e @ Operator(Seq(e1, e2), op)) => {
+        	//matches integer binary relation or a boolean equality
+          if (e1.getType == BooleanType || e1.getType == Int32Type || e1.getType == RealType || e1.getType == IntegerType) {
+            e match {
+              case e: Equals => {
+                if (e1.getType == BooleanType && e2.getType == BooleanType) {
+                  Or(And(nnf(e1), nnf(Not(e2))), And(nnf(e2), nnf(Not(e1))))
+                } else {
+                  if (retainNEQ) Not(Equals(e1, e2))
+                  else Or(nnf(LessThan(e1, e2)), nnf(GreaterThan(e1, e2)))
+                }
+              }
+              case e: LessThan => GreaterEquals(nnf(e1), nnf(e2))
+              case e: LessEquals => GreaterThan(nnf(e1), nnf(e2))
+              case e: GreaterThan => LessEquals(nnf(e1), nnf(e2))
+              case e: GreaterEquals => LessThan(nnf(e1), nnf(e2))
+              case e: Implies => And(nnf(e1), nnf(Not(e2)))
+              case _ => throw new IllegalStateException("Unknown binary operation: " + e)
+            }
+          } else {
+            //in this case e is a binary operation over ADTs
+            e match {
+              case ninst @ Not(IsInstanceOf(e1, cd)) => Not(IsInstanceOf(nnf(e1), cd))
+              case e: Equals => Not(Equals(nnf(e1), nnf(e2)))
+              case _ => throw new IllegalStateException("Unknown operation on algebraic data types: " + e)
+            }
+          }
+        }
+        case Implies(lhs, rhs) => nnf(Or(Not(lhs), rhs))
+        case e @ Equals(lhs, IsInstanceOf(_, _) | CaseClassSelector(_, _, _) | TupleSelect(_, _) | FunctionInvocation(_, _)) =>
+          //all case where rhs could use an ADT tree e.g. instanceOF, tupleSelect, fieldSelect, function invocation
+          e
+        case Equals(lhs, rhs) if (lhs.getType == BooleanType && rhs.getType == BooleanType) => {
+          nnf(And(Implies(lhs, rhs), Implies(rhs, lhs)))
+        }
+        case Not(IfExpr(cond, thn, elze)) => IfExpr(nnf(cond), nnf(Not(thn)), nnf(Not(elze)))
+        case Not(Let(i, v, e)) => Let(i, nnf(v), nnf(Not(e)))
+        //note that Not(LetTuple) is not possible
+        case t: Terminal => t
+        /*case u @ UnaryOperator(e1, op) => op(nnf(e1))
+        case b @ BinaryOperator(e1, e2, op) => op(nnf(e1), nnf(e2))*/
+        case n @ Operator(args, op) => op(args.map(nnf(_)))
+
+        case _ => throw new IllegalStateException("Impossible event: expr did not match any case: " + inExpr)
+      }
+    }
+    val nnfvc = nnf(expr)
+    nnfvc
+  }
+
+  /**
+   * Eliminates redundant nesting of ORs and ANDs.
+   * This is supposed to be a semantic preserving transformation
+   */
+  def pullAndOrs(expr: Expr): Expr = {
+
+    simplePostTransform((e: Expr) => e match {
+      case Or(args) => {
+        val newArgs = args.foldLeft(Seq[Expr]())((acc, arg) => arg match {
+          case Or(inArgs) => acc ++ inArgs
+          case _ => acc :+ arg
+        })
+        Util.createOr(newArgs)
+      }
+      case And(args) => {
+        val newArgs = args.foldLeft(Seq[Expr]())((acc, arg) => arg match {
+          case And(inArgs) => acc ++ inArgs
+          case _ => acc :+ arg
+        })
+        Util.createAnd(newArgs)
+      }
+      case _ => e
+    })(expr)
+  }
+
+  def classSelToCons(e: Expr): Expr = {
+    val (r, cd, ccvar, ccfld) = e match {
+      case Equals(r0 @ Variable(_), CaseClassSelector(cd0, ccvar0, ccfld0)) => (r0, cd0, ccvar0, ccfld0)
+      case _ => throw new IllegalStateException("Not a case-class-selector call")
+    }
+    //convert this to a cons by creating dummy variables
+    val args = cd.fields.map((fld) => {
+      if (fld.id == ccfld) r
+      else {
+        //create a dummy identifier there
+        TVarFactory.createDummy(fld.getType).toVariable
+      }
+    })
+    Equals(ccvar, CaseClass(cd, args))
+  }
+
+  def tupleSelToCons(e: Expr): Expr = {
+    val (r, tpvar, index) = e match {
+      case Equals(r0 @ Variable(_), TupleSelect(tpvar0, index0)) => (r0, tpvar0, index0)
+      // case Iff(r0 @ Variable(_), TupleSelect(tpvar0, index0)) => (r0, tpvar0, index0)
+      case _ => throw new IllegalStateException("Not a tuple-selector call")
+    }
+    //convert this to a Tuple by creating dummy variables
+    val tupleType = tpvar.getType.asInstanceOf[TupleType]
+    val args = (1 until tupleType.dimension + 1).map((i) => {
+      if (i == index) r
+      else {
+        //create a dummy identifier there (note that here we have to use i-1)
+        TVarFactory.createDummy(tupleType.bases(i - 1)).toVariable
+      }
+    })
+    Equals(tpvar, Tuple(args))
+  }
+
+  /**
+   * Normalizes the expressions
+   */
+  def normalizeExpr(expr: Expr, multOp: (Expr, Expr) => Expr): Expr = {
+    //reduce the language before applying flatten function
+    // println("Normalizing " + ScalaPrinter(expr) + "\n")
+    val redex = reduceLangBlocks(expr, multOp)
+    // println("Redex: "+ScalaPrinter(redex) + "\n")
+    val nnfExpr = TransformNot(redex)
+    // println("NNFexpr: "+ScalaPrinter(nnfExpr) + "\n")
+    //flatten all function calls
+    val flatExpr = FlattenFunction(nnfExpr)
+    // println("Flatexpr: "+ScalaPrinter(flatExpr) + "\n")
+    //perform additional simplification
+    val simpExpr = pullAndOrs(TransformNot(flatExpr))
+    simpExpr
+  }
+
+  /**
+   * This is the inverse operation of flattening, this is mostly
+   * used to produce a readable formula.
+   * Freevars is a set of identifiers that are program variables
+   * This assumes that temporary identifiers (which are not freevars) are not reused across clauses.
+   */
+  def unFlatten(ine: Expr, freevars: Set[Identifier]): Expr = {
+    var tempMap = Map[Expr, Expr]()
+    val newinst = simplePostTransform((e: Expr) => e match {
+      case Equals(v @ Variable(id), rhs @ _) if !freevars.contains(id) =>
+        if (tempMap.contains(v)) e
+        else {
+          tempMap += (v -> rhs)
+          tru
+        }
+      case _ => e
+    })(ine)
+    val closure = (e: Expr) => replace(tempMap, e)
+    Util.fix(closure)(newinst)
+  }
+
+  /**
+   * convert all integer constants to real constants
+   */
+  def IntLiteralToReal(inexpr: Expr): Expr = {
+    val transformer = (e: Expr) => e match {
+      case InfiniteIntegerLiteral(v) => FractionalLiteral(v, 1)
+      case IntLiteral(v) => FractionalLiteral(v, 1)
+      case _ => e
+    }
+    simplePostTransform(transformer)(inexpr)
+  }
+
+  /**
+   * convert all real constants to integers
+   */
+  def FractionalLiteralToInt(inexpr: Expr): Expr = {
+    val transformer = (e: Expr) => e match {
+      case FractionalLiteral(v, `bone`) => InfiniteIntegerLiteral(v)
+      case FractionalLiteral(_, _) => throw new IllegalStateException("cannot convert real literal to integer: " + e)
+      case _ => e
+    }
+    simplePostTransform(transformer)(inexpr)
+  }
+
+  /**
+   * A hacky way to implement subexpression check.
+   * TODO: fix this
+   */
+  def isSubExpr(key: Expr, expr: Expr): Boolean = {
+
+    var found = false
+    simplePostTransform((e: Expr) => e match {
+      case _ if (e == key) =>
+        found = true; e
+      case _ => e
+    })(expr)
+    found
+  }
+
+  /**
+   * Some simplification rules (keep adding more and more rules)
+   */
+  def simplify(expr: Expr): Expr = {
+
+    //Note: some simplification are already performed by the class constructors (see Tree.scala)
+    simplePostTransform((e: Expr) => e match {
+      case Equals(lhs, rhs) if (lhs == rhs) => tru
+      case LessEquals(lhs, rhs) if (lhs == rhs) => tru
+      case GreaterEquals(lhs, rhs) if (lhs == rhs) => tru
+      case LessThan(lhs, rhs) if (lhs == rhs) => fls
+      case GreaterThan(lhs, rhs) if (lhs == rhs) => fls
+      case UMinus(InfiniteIntegerLiteral(v)) => InfiniteIntegerLiteral(-v)
+      case Equals(InfiniteIntegerLiteral(v1), InfiniteIntegerLiteral(v2)) => BooleanLiteral(v1 == v2)
+      case LessEquals(InfiniteIntegerLiteral(v1), InfiniteIntegerLiteral(v2)) => BooleanLiteral(v1 <= v2)
+      case LessThan(InfiniteIntegerLiteral(v1), InfiniteIntegerLiteral(v2)) => BooleanLiteral(v1 < v2)
+      case GreaterEquals(InfiniteIntegerLiteral(v1), InfiniteIntegerLiteral(v2)) => BooleanLiteral(v1 >= v2)
+      case GreaterThan(InfiniteIntegerLiteral(v1), InfiniteIntegerLiteral(v2)) => BooleanLiteral(v1 > v2)
+      case _ => e
+    })(expr)
+  }
+
+  /**
+   * Input expression is assumed to be in nnf form
+   * Note: (a) Not(Equals()) and Not(Variable) is allowed
+   */
+  def isDisjunct(e: Expr): Boolean = e match {
+    case And(args) => args.foldLeft(true)((acc, arg) => acc && isDisjunct(arg))
+    case Not(Equals(_, _)) | Not(Variable(_)) => true
+    case Or(_) | Implies(_, _) | Not(_) | Equals(_, _) => false
+    case _ => true
+  }
+
+  /**
+   * assuming that the expression is in nnf form
+   * Note: (a) Not(Equals()) and Not(Variable) is allowed
+   */
+  def isConjunct(e: Expr): Boolean = e match {
+    case Or(args) => args.foldLeft(true)((acc, arg) => acc && isConjunct(arg))
+    case Not(Equals(_, _)) | Not(Variable(_)) => true
+    case And(_) | Implies(_, _) | Not(_) | Equals(_, _) => false
+    case _ => true
+  }
+
+  def PrintWithIndentation(wr: PrintWriter, expr: Expr): Unit = {
+
+    def uniOP(e: Expr, seen: Int): Boolean = e match {
+      case And(args) => {
+        //have we seen an or ?
+        if (seen == 2) false
+        else args.foldLeft(true)((acc, arg) => acc && uniOP(arg, 1))
+      }
+      case Or(args) => {
+        //have we seen an And ?
+        if (seen == 1) false
+        else args.foldLeft(true)((acc, arg) => acc && uniOP(arg, 2))
+      }
+      case t: Terminal => true
+      /*case u @ UnaryOperator(e1, op) => uniOP(e1, seen)
+      case b @ BinaryOperator(e1, e2, op) => uniOP(e1, seen) && uniOP(e2, seen)*/
+      case n @ Operator(args, op) => args.foldLeft(true)((acc, arg) => acc && uniOP(arg, seen))
+    }
+
+    def printRec(e: Expr, indent: Int): Unit = {
+      if (uniOP(e, 0)) wr.println(ScalaPrinter(e))
+      else {
+        wr.write("\n" + " " * indent + "(\n")
+        e match {
+          case And(args) => {
+            var start = true
+            args.map((arg) => {
+              wr.print(" " * (indent + 1))
+              if (!start) wr.print("^")
+              printRec(arg, indent + 1)
+              start = false
+            })
+          }
+          case Or(args) => {
+            var start = true
+            args.map((arg) => {
+              wr.print(" " * (indent + 1))
+              if (!start) wr.print("v")
+              printRec(arg, indent + 1)
+              start = false
+            })
+          }
+          case _ => throw new IllegalStateException("how can this happen ? " + e)
+        }
+        wr.write(" " * indent + ")\n")
+      }
+    }
+    printRec(expr, 0)
+  }
+
+  /**
+   * Converts to sum of products form by distributing
+   * multiplication over addition
+   */
+  def normalizeMultiplication(e: Expr, multop: (Expr, Expr) => Expr): Expr = {
+
+    def isConstantOrTemplateVar(e: Expr) = {
+      e match {
+        case l: Literal[_] => true
+        case Variable(id) if TemplateIdFactory.IsTemplateIdentifier(id) => true
+        case _ => false
+      }
+    }
+
+    def distribute(e: Expr): Expr = {
+      simplePreTransform(_ match {
+        case e @ FunctionInvocation(TypedFunDef(fd, _), Seq(e1, e2)) if Util.isMultFunctions(fd) =>
+          val newe = (e1, e2) match {
+            case (Plus(sum1, sum2), _) =>
+              // distribute e2 over e1
+              Plus(multop(sum1, e2), multop(sum2, e2))
+            case (_, Plus(sum1, sum2)) =>
+              // distribute e1 over e2
+              Plus(multop(e1, sum1), multop(e1, sum2))
+            case (Times(arg1, arg2), _) =>
+              // pull the constants out of multiplication (note: times is used when one of the arguments is a literal or template id
+              if (isConstantOrTemplateVar(arg1)) {
+                Times(arg1, multop(arg2, e2))
+              } else
+                Times(arg2, multop(arg1, e2)) // here using commutativity axiom
+            case (_, Times(arg1, arg2)) =>
+              if (isConstantOrTemplateVar(arg1))
+                Times(arg1, multop(e1, arg2))
+              else
+                Times(arg2, multop(e1, arg1))
+            case _ if isConstantOrTemplateVar(e1) || isConstantOrTemplateVar(e2) =>
+              // here one of the operands is a literal or template var, so convert mult to times and continue
+              Times(e1, e2)
+            case _ =>
+              e
+          }
+          newe
+        case other => other
+      })(e)
+    }
+    distribute(e)
+  }
+}
diff --git a/src/main/scala/leon/invariant/util/Graph.scala b/src/main/scala/leon/invariant/util/Graph.scala
new file mode 100644
index 000000000..22f4e83d1
--- /dev/null
+++ b/src/main/scala/leon/invariant/util/Graph.scala
@@ -0,0 +1,170 @@
+package leon
+package invariant.util
+
+class DirectedGraph[T] {
+
+  var adjlist = scala.collection.mutable.Map[T, Set[T]]()
+  var edgeCount: Int = 0
+
+  def addNode(n: T) {
+    if (!adjlist.contains(n)) {
+      adjlist.update(n, Set())
+    }
+  }
+
+  def addEdge(src: T, dest: T): Unit = {
+    val newset = if (adjlist.contains(src)) adjlist(src) + dest
+    else Set(dest)
+
+    //this has some side-effects
+    adjlist.update(src, newset)
+
+    edgeCount += 1
+  }
+
+  def BFSReach(src: T, dest: T, excludeSrc: Boolean = false): Boolean = {
+    var queue = List[T]()
+    var visited = Set[T]()
+    visited += src
+
+    //TODO: is there a better (and efficient) way to implement BFS without using side-effects
+    def BFSReachRecur(cur: T): Boolean = {
+      var found: Boolean = false
+      if (adjlist.contains(cur)) {
+        adjlist(cur).foreach((fi) => {
+          if (fi == dest) found = true
+          else if (!visited.contains(fi)) {
+            visited += fi
+            queue ::= fi
+          }
+        })
+      }
+      if (found) true
+      else if (queue.isEmpty) false
+      else {
+        val (head :: tail) = queue
+        queue = tail
+        BFSReachRecur(head)
+      }
+    }
+
+    if (!excludeSrc && src == dest) true
+    else BFSReachRecur(src)
+  }
+
+  def BFSReachables(src: T): Set[T] = {
+    var queue = List[T]()
+    var visited = Set[T]()
+    visited += src
+
+    def BFSReachRecur(cur: T): Unit = {
+      if (adjlist.contains(cur)) {
+        adjlist(cur).foreach((neigh) => {
+          if (!visited.contains(neigh)) {
+            visited += neigh
+            queue ::= neigh
+          }
+        })
+      }
+      if (!queue.isEmpty) {
+        val (head :: tail) = queue
+        queue = tail
+        BFSReachRecur(head)
+      }
+    }
+
+    BFSReachRecur(src)
+    visited
+  }
+
+  def containsEdge(src: T, dest: T): Boolean = {
+    if (adjlist.contains(src)) {
+      adjlist(src).contains(dest)
+    } else false
+  }
+
+  def getEdgeCount: Int = edgeCount
+  def getNodes: Set[T] = adjlist.keySet.toSet
+  def getSuccessors(src: T): Set[T] = adjlist(src)
+
+  /**
+   * Change this to the verified component
+   */
+  def sccs: List[List[T]] = {
+
+    type Component = List[T]
+
+    case class State(count: Int,
+      visited: Map[T, Boolean],
+      dfNumber: Map[T, Int],
+      lowlinks: Map[T, Int],
+      stack: List[T],
+      components: List[Component])
+
+    def search(vertex: T, state: State): State = {
+      val newState = state.copy(visited = state.visited.updated(vertex, true),
+        dfNumber = state.dfNumber.updated(vertex, state.count),
+        count = state.count + 1,
+        lowlinks = state.lowlinks.updated(vertex, state.count),
+        stack = vertex :: state.stack)
+
+      def processVertex(st: State, w: T): State = {
+        if (!st.visited(w)) {
+          val st1 = search(w, st)
+          val min = Math.min(st1.lowlinks(w), st1.lowlinks(vertex))
+          st1.copy(lowlinks = st1.lowlinks.updated(vertex, min))
+        } else {
+          if ((st.dfNumber(w) < st.dfNumber(vertex)) && st.stack.contains(w)) {
+            val min = Math.min(st.dfNumber(w), st.lowlinks(vertex))
+            st.copy(lowlinks = st.lowlinks.updated(vertex, min))
+          } else st
+        }
+      }
+
+      val strslt = getSuccessors(vertex).foldLeft(newState)(processVertex)
+
+      if (strslt.lowlinks(vertex) == strslt.dfNumber(vertex)) {
+
+        val index = strslt.stack.indexOf(vertex)
+        val (comp, rest) = strslt.stack.splitAt(index + 1)
+        strslt.copy(stack = rest,
+          components = strslt.components :+ comp)
+      } else strslt
+    }
+
+    val initial = State(
+      count = 1,
+      visited = getNodes.map { (_, false) }.toMap,
+      dfNumber = Map(),
+      lowlinks = Map(),
+      stack = Nil,
+      components = Nil)
+
+    var state = initial
+    while (state.visited.exists(_._2 == false)) {
+      state.visited.find(_._2 == false).foreach { tuple =>
+        val (vertex, _) = tuple
+        state = search(vertex, state)
+      }
+    }
+    state.components
+  }
+
+}
+
+class UndirectedGraph[T] extends DirectedGraph[T] {
+
+  override def addEdge(src: T, dest: T): Unit = {
+    val newset1 = if (adjlist.contains(src)) adjlist(src) + dest
+    else Set(dest)
+
+    val newset2 = if (adjlist.contains(dest)) adjlist(dest) + src
+    else Set(src)
+
+    //this has some side-effects
+    adjlist.update(src, newset1)
+    adjlist.update(dest, newset2)
+
+    edgeCount += 1
+  }
+}
diff --git a/src/main/scala/leon/invariant/util/LetTupleSimplifications.scala b/src/main/scala/leon/invariant/util/LetTupleSimplifications.scala
new file mode 100644
index 000000000..966121756
--- /dev/null
+++ b/src/main/scala/leon/invariant/util/LetTupleSimplifications.scala
@@ -0,0 +1,465 @@
+package leon
+package invariant.util
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import java.io._
+import java.io._
+import purescala.ScalaPrinter
+import leon.utils._
+
+import invariant.structure.Call
+import invariant.structure.FunctionUtils._
+import leon.transformations.InstUtil._
+
+/**
+ * A collection of transformation on expressions and some utility methods.
+ * These operations are mostly semantic preserving (specific assumptions/requirements are specified on the operations)
+ */
+object LetTupleSimplification {
+
+  val zero = InfiniteIntegerLiteral(0)
+  val one = InfiniteIntegerLiteral(1)
+  val mone = InfiniteIntegerLiteral(-1)
+  val tru = BooleanLiteral(true)
+  val fls = BooleanLiteral(false)
+  val bone = BigInt(1)
+
+  def letSanityChecks(ine: Expr) = {
+    simplePostTransform(_ match {
+      case letExpr @ Let(binderId, letValue, body)
+      	if (binderId.getType != letValue.getType) =>
+          throw new IllegalStateException("Binder and value type mismatch: "+
+              s"(${binderId.getType},${letValue.getType})")
+      case e => e
+    })(ine)
+  }
+
+  /**
+   * This function simplifies lets of the form <Var> = <TupleType Expr> by replacing
+   * uses of the <Var>._i by the approppriate expression in the let body or by
+   * introducing a new let <Var'> = <Var>._i and using <Var'> in place of <Var>._i
+   * in the original let body.
+   * Caution: this function may not be idempotent.
+   */
+  def simplifyTuples(ine: Expr): Expr = {
+
+    var processedLetBinders = Set[Identifier]()
+    def recSimplify(e: Expr, replaceMap: Map[Expr, Expr]): Expr = {
+
+      //println("Before: "+e)
+      val transe = e match {
+        case letExpr @ Let(binderId, letValue, body) if !processedLetBinders(binderId) =>
+          processedLetBinders += binderId
+          // transform the 'letValue' with the current map
+          val nvalue = recSimplify(letValue, replaceMap)
+          // enrich the map if letValue is of tuple type
+          nvalue.getType match {
+            case TupleType(argTypes) =>
+              var freshBinders = Set[Identifier]()
+              def freshBinder(typ: TypeTree) = {
+                val freshid = TVarFactory.createTemp(binderId.name, typ)
+                freshBinders += freshid
+                freshid.toVariable
+              }
+              val newmap: Map[Expr, Expr] = nvalue match {
+                case Tuple(args) => // this is an optimization for the case where nvalue is a tuple
+                  args.zipWithIndex.map {
+                    case (t: Terminal, index) =>
+                      (TupleSelect(binderId.toVariable, index + 1) -> t)
+                    case (_, index) =>
+                      (TupleSelect(binderId.toVariable, index + 1) -> freshBinder(argTypes(index)))
+                  }.toMap
+                case _ =>
+                  argTypes.zipWithIndex.map {
+                    case (argtype, index) =>
+                      (TupleSelect(binderId.toVariable, index + 1) -> freshBinder(argtype))
+                  }.toMap
+              }
+              // transform the body using the new map + old map
+              val nbody = recSimplify(body, replaceMap ++ newmap)
+              val bodyFreevars = variablesOf(nbody)
+              // create a sequence of lets for the freshBinders
+              val nletBody = newmap.foldLeft(nbody) {
+                case (acc, (k, Variable(id))) if freshBinders(id) && bodyFreevars(id) =>
+                  // here, the 'id' is a newly created binder and is also used in the transformed body
+                  Let(id, k, acc)
+                case (acc, _) =>
+                  acc
+              }
+              Let(binderId, nvalue, nletBody)
+            case _ =>
+              // no simplification can be done in this step
+              Let(binderId, nvalue, recSimplify(body, replaceMap))
+          }
+        case ts @ TupleSelect(_, _) if replaceMap.contains(ts) =>
+          postMap(replaceMap.lift, true)(e) //perform recursive replacements to handle nested tuple selects
+        //replaceMap(ts) //replace tuple-selects in the map with the new identifier
+
+        case t: Terminal => t
+
+        /*case UnaryOperator(sube, op) =>
+          op(recSimplify(sube, replaceMap))
+
+        case BinaryOperator(e1, e2, op) =>
+          op(recSimplify(e1, replaceMap), recSimplify(e2, replaceMap))*/
+
+        case Operator(subes, op) =>
+          op(subes.map(recSimplify(_, replaceMap)))
+      }
+      //println("After: "+e)
+      transe
+    }
+    fixpoint((e: Expr) => simplifyArithmetic(recSimplify(e, Map())))(ine)
+  }
+
+  // sanity checks
+  def checkTupleSelectInsideMax(e: Expr): Boolean = {
+    //exists( predicate: Expr => Expr) (e)
+    var error = false
+    def helper(e: Expr): Unit = {
+      e match {
+        case FunctionInvocation(tfd, args) if (tfd.fd == maxFun) => {
+
+          val Seq(arg1: Expr, arg2: Expr) = args
+          (arg1, arg2) match {
+            case (_: TupleSelect, _) => error = true
+            case (_, _: TupleSelect) => error = true
+            case _ => { ; }
+          }
+        }
+
+        case _ => { ; }
+      }
+    }
+
+    postTraversal(helper)(e)
+    error
+  }
+
+  def simplifyMax(ine: Expr): Expr = {
+    val debugMaxSimplify = false
+    //computes a lower bound value, assuming that every sub-term used in the term is positive
+    //Note: this is applicable only to expressions involving depth
+    def positiveTermLowerBound(e: Expr): Int = e match {
+      case IntLiteral(v) => v
+      case Plus(l, r) => positiveTermLowerBound(l) + positiveTermLowerBound(r)
+      case FunctionInvocation(tfd, args) if (tfd.fd == maxFun) => {
+        val Seq(arg1, arg2) = args
+        val lb1 = positiveTermLowerBound(arg1)
+        val lb2 = positiveTermLowerBound(arg2)
+        if (lb1 >= lb2) lb1 else lb2
+      }
+      case _ => 0 //other case are not handled as they do not appear
+    }
+
+    //checks if 'sub' is subsumed by 'e' i.e, 'e' will always take a value
+    // greater than or equal to 'sub'.
+    //Assuming that every sub-term used in the term is positive
+    def subsumedBy(sub: Expr, e: Expr): Boolean = e match {
+      case _ if (sub == e) => true
+      case Plus(l, r) => subsumedBy(sub, l) || subsumedBy(sub, r)
+      case FunctionInvocation(tfd, args) if (tfd.fd == maxFun) =>
+        val Seq(l, r) = args
+        subsumedBy(sub, l) || subsumedBy(sub, r)
+      case _ => false
+    }
+
+    // in the sequel, we are using the fact that 'depth' is positive and
+    // 'ine' contains only 'depth' variables
+    val simpe = simplePostTransform((e: Expr) => e match {
+      case FunctionInvocation(tfd, args) if (tfd.fd == maxFun) => {
+        if (debugMaxSimplify) {
+          println("Simplifying: " + e)
+        }
+        val newargs: Seq[Expr] = args.map(simplifyArithmetic)
+        val Seq(arg1: Expr, arg2: Expr) = newargs
+        val simpval = if (!Util.hasCalls(arg1) && !Util.hasCalls(arg2)) {
+          import invariant.structure.LinearConstraintUtil._
+          val lt = exprToTemplate(LessEquals(Minus(arg1, arg2), InfiniteIntegerLiteral(0)))
+          //now, check if all the variables in 'lt' have only positive coefficients
+          val allPositive = lt.coeffTemplate.forall(entry => entry match {
+            case (k, IntLiteral(v)) if (v >= 0) => true
+            case _ => false
+          }) && (lt.constTemplate match {
+            case None => true
+            case Some(IntLiteral(v)) if (v >= 0) => true
+            case _ => false
+          })
+          if (allPositive) arg1
+          else {
+            val allNegative = lt.coeffTemplate.forall(entry => entry match {
+              case (k, IntLiteral(v)) if (v <= 0) => true
+              case _ => false
+            }) && (lt.constTemplate match {
+              case None => true
+              case Some(IntLiteral(v)) if (v <= 0) => true
+              case _ => false
+            })
+            if (allNegative) arg2
+            else FunctionInvocation(tfd, newargs) //here we cannot do any simplification.
+          }
+
+        } else {
+          (arg1, arg2) match {
+            case (IntLiteral(v), r) if (v <= positiveTermLowerBound(r)) => r
+            case (l, IntLiteral(v)) if (v <= positiveTermLowerBound(l)) => l
+            case (l, r) if subsumedBy(l, r) => r
+            case (l, r) if subsumedBy(r, l) => l
+            case _ => FunctionInvocation(tfd, newargs)
+          }
+        }
+        if (debugMaxSimplify) {
+          println("Simplified value: " + simpval)
+        }
+        simpval
+      }
+      // case FunctionInvocation(tfd, args) if(tfd.fd.id.name == "max") => {
+      // throw new IllegalStateException("Found just max in expression " + e + "\n")
+      // }
+      case _ => e
+    })(ine)
+    simpe
+  }
+
+  def inlineMax(ine: Expr): Expr = {
+    //inline 'max' operations here
+    simplePostTransform((e: Expr) => e match {
+      case FunctionInvocation(tfd, args) if (tfd.fd == maxFun) =>
+        val Seq(arg1, arg2) = args
+        val bindWithLet = (value: Expr, body: (Expr with Terminal) => Expr) => {
+          value match {
+            case t: Terminal => body(t)
+            case Let(id, v, b: Terminal) =>
+              //here we can use 'b' in 'body'
+              Let(id, v, body(b))
+            case _ =>
+              val mt = TVarFactory.createTemp("mt", value.getType)
+              Let(mt, value, body(mt.toVariable))
+          }
+        }
+        bindWithLet(arg1, a1 => bindWithLet(arg2, a2 =>
+          IfExpr(GreaterEquals(a1, a2), a1, a2)))
+      case _ => e
+    })(ine)
+  }
+
+  def removeLetsFromLetValues(ine: Expr): Expr = {
+
+    /**
+     * Navigates through the sequence of lets in 'e'
+     * and replaces its 'let' free part by subst.
+     * Assuming that 'e' has only lets at the top and no nested lets in the value
+     */
+    def replaceLetBody(e: Expr, subst: Expr => Expr): Expr = e match {
+      case Let(binder, letv, letb) =>
+        Let(binder, letv, replaceLetBody(letb, subst))
+      case _ =>
+        subst(e)
+    }
+
+    // the function removes the lets from the let values
+    // by pulling them out
+    def pullLetToTop(e: Expr): Expr = {
+      val transe = e match {
+        //note: do not pull let's out of ensuring or requires
+        case Ensuring(body, pred) =>
+          Ensuring(pullLetToTop(body), pred)
+        case Require(pre, body) =>
+          Require(pre, pullLetToTop(body))
+
+        case letExpr @ Let(binder, letValue, body) =>
+          // transform the 'letValue' with the current map
+          pullLetToTop(letValue) match {
+            case sublet @ Let(binder2, subvalue, subbody) =>
+              // transforming "let v = (let v1 = e1 in e2) in e3"
+              // to "let v1 = e1 in (let v = e2 in e3)"
+              // here, subvalue is free of lets, but subbody may again be a let
+              val newbody = replaceLetBody(subbody, Let(binder, _, pullLetToTop(body)))
+              Let(binder2, subvalue, newbody)
+            case nval =>
+              // here, there is no let in the value
+              Let(binder, nval, pullLetToTop(body))
+          }
+        case t: Terminal => t
+        case Operator(Seq(sube), op) =>
+          replaceLetBody(pullLetToTop(sube), e => op(Seq(e)))
+
+        case Operator(Seq(e1, e2), op) =>
+          replaceLetBody(pullLetToTop(e1), te1 =>
+            replaceLetBody(pullLetToTop(e2), te2 => op(Seq(te1, te2))))
+
+        //don't pull things out of if-then-else and match (don't know why this is a problem)
+        case IfExpr(c, th, elze) =>
+          IfExpr(pullLetToTop(c), pullLetToTop(th), pullLetToTop(elze))
+
+        case Operator(Seq(), op) =>
+          op(Seq())
+
+        case Operator(subes, op) =>
+          // transform all the sub-expressions
+          val nsubes = subes map pullLetToTop
+          //collects all the lets and makes the bodies a tuple
+          var i = -1
+          val transLet = nsubes.tail.foldLeft(nsubes.head) {
+            case (acc, nsube) =>
+              i += 1
+              replaceLetBody(acc, e1 =>
+                replaceLetBody(nsube, e2 => e1 match {
+                  case _ if i == 0 =>
+                    Tuple(Seq(e1, e2))
+                  case Tuple(args) =>
+                    Tuple(args :+ e2)
+                }))
+          }
+          replaceLetBody(transLet, (e: Expr) => e match {
+            case Tuple(args) =>
+              op(args)
+            case _ => op(Seq(e)) //here, there was only one argument
+          })
+      }
+      transe
+    }
+    val res = pullLetToTop(matchToIfThenElse(ine))
+    // println("After Pulling lets to top : \n" + ScalaPrinter.apply(res))
+    res
+  }
+
+  def simplifyLetsAndLetsWithTuples(ine: Expr) = {
+
+    def simplerLet(t: Expr): Option[Expr] = {
+      val res = t match {
+        case letExpr @ Let(i, t: Terminal, b) =>
+          Some(replace(Map(Variable(i) -> t), b))
+
+        // check if the let can be completely removed
+        case letExpr @ Let(i, e, b) => {
+          val occurrences = count {
+            case Variable(x) if x == i => 1
+            case _ => 0
+          }(b)
+
+          if (occurrences == 0) {
+            Some(b)
+          } else if (occurrences == 1) {
+            Some(replace(Map(Variable(i) -> e), b))
+          } else {
+        	 //TODO: we can also remove zero occurrences and compress the tuples
+            // this may be necessary when instrumentations are combined.
+            letExpr match {
+              case letExpr @ Let(binder, lval @ Tuple(subes), b) =>
+                def occurrences(index: Int) = {
+                  val res = count {
+                    case TupleSelect(sel, i) if sel == binder.toVariable && i == index => 1
+                    case _ => 0
+                  }(b)
+                  res
+                }
+                val repmap: Map[Expr, Expr] = subes.zipWithIndex.collect {
+                  case (sube, i) if occurrences(i + 1) == 1 =>
+                    (TupleSelect(binder.toVariable, i + 1) -> sube)
+                }.toMap
+                Some(Let(binder, lval, replace(repmap, b)))
+              //note: here, we cannot remove the let,
+              //if it is not used it will be removed in the next iteration
+
+              case _ => None
+            }
+          }
+        }
+
+        case _ => None
+      }
+      res
+    }
+
+    val transforms = removeLetsFromLetValues _ andThen fixpoint(postMap(simplerLet)) _ andThen simplifyArithmetic
+    transforms(ine)
+  }
+
+  /*
+    This function tries to simplify a part of the expression tree consisting of the same operation.
+    The operatoin needs to be associative and commutative for this simplification to work .
+    Arguments:
+      op: An implementation of the opertaion to be simplified
+      getLeaves: Gets all the operands from the AST (if the argument is not of
+                  the form currently being simplified, this is required to return an empty set)
+      identity: The identity element for the operation
+      makeTree: Makes an AST from the operands
+  */
+  def simplifyConstantsGeneral(e: Expr, op: (BigInt, BigInt) => BigInt,
+    getLeaves: (Expr, Boolean) => Seq[Expr], identity: BigInt,
+    makeTree: (Expr, Expr) => Expr): Expr = {
+
+    val allLeaves = getLeaves(e, true)
+    // Here the expression is not of the form we are currently simplifying
+    if (allLeaves.size == 0) e
+    else {
+      // fold constants here
+      val allConstantsOpped = allLeaves.foldLeft(identity)((acc, e) => e match {
+        case InfiniteIntegerLiteral(x) => op(acc, x)
+        case _ => acc
+      })
+
+      val allNonConstants = allLeaves.filter((e) => e match {
+        case _: InfiniteIntegerLiteral => false
+        case _ => true
+      })
+
+      // Reconstruct the expressin tree with the non-constants and the result of constant evaluation above
+      if (allConstantsOpped != identity) {
+        allNonConstants.foldLeft(InfiniteIntegerLiteral(allConstantsOpped): Expr)((acc: Expr, currExpr) => makeTree(acc, currExpr))
+      }
+      else {
+        if (allNonConstants.size == 0) InfiniteIntegerLiteral(identity)
+        else {
+          allNonConstants.tail.foldLeft(allNonConstants.head)((acc: Expr, currExpr) => makeTree(acc, currExpr))
+        }
+      }
+    }
+  }
+
+  //Use the above function to simplify additions and maximums interleaved
+  def simplifyAdditionsAndMax(e: Expr): Expr = {
+    def getAllSummands(e: Expr, isTopLevel: Boolean): Seq[Expr] = {
+      e match {
+        case Plus(e1, e2) => {
+          getAllSummands(e1, false) ++ getAllSummands(e2, false)
+        }
+        case _ => if (isTopLevel) Seq[Expr]()  else Seq[Expr](e)
+      }
+    }
+
+    def getAllMaximands(e: Expr, isTopLevel: Boolean): Seq[Expr] = {
+      e match {
+        case FunctionInvocation(tfd, args) if (tfd.fd == maxFun) => {
+          args.foldLeft(Seq[Expr]())((accSet, e) => accSet ++ getAllMaximands(e, false))
+        }
+        case _ => if (isTopLevel) Seq[Expr]() else Seq[Expr](e)
+      }
+    }
+
+    simplePostTransform(e => {
+      val plusSimplifiedExpr =
+        simplifyConstantsGeneral(e, _ + _, getAllSummands, 0, ((e1, e2) => Plus(e1, e2)))
+
+      // Maximum simplification assumes all arguments to max
+      // are non-negative (and hence 0 is the identity)
+      val maxSimplifiedExpr =
+        simplifyConstantsGeneral(plusSimplifiedExpr,
+          ((a: BigInt, b: BigInt) => if (a > b) a else b),
+          getAllMaximands,
+          0,
+          ((e1, e2) => {
+            val typedMaxFun = TypedFunDef(maxFun, Seq())
+            FunctionInvocation(typedMaxFun, Seq(e1, e2))
+          }))
+
+      maxSimplifiedExpr
+    })(e)
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/util/Minimizer.scala b/src/main/scala/leon/invariant/util/Minimizer.scala
new file mode 100644
index 000000000..7e44eaaa7
--- /dev/null
+++ b/src/main/scala/leon/invariant/util/Minimizer.scala
@@ -0,0 +1,200 @@
+package leon
+package invariant.util
+import z3.scala._
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import solvers._
+import solvers.z3._
+import leon.invariant._
+import scala.util.control.Breaks._
+import invariant.engine.InferenceContext
+import invariant.factories._
+import leon.invariant.templateSolvers.ExtendedUFSolver
+import leon.invariant.util.RealValuedExprEvaluator._
+
+class Minimizer(ctx: InferenceContext) {
+
+  val verbose = false
+  val debugMinimization = false
+  /**
+   * Here we are assuming that that initModel is a model for ctrs
+   * TODO: make sure that the template for rootFun is the time template
+   */
+  val MaxIter = 16 //note we may not be able to represent anything beyond 2^16
+  /*val MaxInt = Int.MaxValue
+  val sqrtMaxInt = 45000 //this is a number that is close a sqrt of 2^31
+*/ val half = FractionalLiteral(1, 2)
+  val two = FractionalLiteral(2, 1)
+  val rzero = FractionalLiteral(0, 1)
+  val mone = FractionalLiteral(-1, 1)
+
+  private val program = ctx.program
+  private val leonctx = ctx.leonContext
+  val reporter = leonctx.reporter
+
+  //for statistics and output
+  //store the lowerbounds for each template variables in the template of the rootFun provided it is a time template
+  var lowerBoundMap = Map[Variable, FractionalLiteral]()
+  def updateLowerBound(tvar: Variable, rval: FractionalLiteral) = {
+    //record the lower bound if it exist
+    if (lowerBoundMap.contains(tvar)) {
+      lowerBoundMap -= tvar
+    }
+    lowerBoundMap += (tvar -> rval)
+  }
+
+  def tightenTimeBounds(timeTemplate: Expr)(inputCtr: Expr, initModel: Model) = {
+    //the order in which the template variables are minimized is based on the level of nesting of the  terms
+    minimizeBounds(computeCompositionLevel(timeTemplate))(inputCtr, initModel)
+  }
+
+  def minimizeBounds(nestMap: Map[Variable, Int])(inputCtr: Expr, initModel: Model): Model = {
+    val orderedTempVars = nestMap.toSeq.sortWith((a, b) => a._2 >= b._2).map(_._1)
+    //do a binary search sequentially on each of these tempvars
+    val solver = SimpleSolverAPI(
+      new TimeoutSolverFactory(SolverFactory(() =>
+        new ExtendedUFSolver(leonctx, program) with TimeoutSolver), ctx.timeout * 1000))
+
+    reporter.info("minimizing...")
+    var currentModel = initModel
+    orderedTempVars.foldLeft(inputCtr: Expr)((acc, tvar) => {
+      var upperBound = if (currentModel.isDefinedAt(tvar.id)) {
+        currentModel(tvar.id).asInstanceOf[FractionalLiteral]
+      } else {
+        initModel(tvar.id).asInstanceOf[FractionalLiteral]
+      }
+      //note: the lower bound is an integer by construction (and is by default zero)
+      var lowerBound: FractionalLiteral =
+        if (tvar == orderedTempVars(0) && lowerBoundMap.contains(tvar))
+          lowerBoundMap(tvar)
+        else realzero
+      //a helper method
+      def updateState(nmodel: Model) = {
+        upperBound = nmodel(tvar.id).asInstanceOf[FractionalLiteral]
+        currentModel = nmodel
+        if (this.debugMinimization) {
+          reporter.info("Found new upper bound: " + upperBound)
+          //reporter.info("Model: "+currentModel)
+        }
+      }
+
+      if (this.debugMinimization)
+        reporter.info(s"Minimizing variable: $tvar Initial Bounds: [$upperBound,$lowerBound]")
+      //TODO: use incremental solving of z3 when it is  supported in nlsat
+      var continue = true
+      var iter = 0
+      do {
+        iter += 1
+        if (continue) {
+          //we make sure that curr val is an integer
+          val currval = floor(evaluate(Times(half, Plus(upperBound, lowerBound))))
+          //check if the lowerbound, if it exists, is < currval
+          if (evaluateRealPredicate(GreaterEquals(lowerBound, currval)))
+            continue = false
+          else {
+            val boundCtr = And(LessEquals(tvar, currval), GreaterEquals(tvar, lowerBound))
+            //val t1 = System.currentTimeMillis()
+            val (res, newModel) = solver.solveSAT(And(acc, boundCtr))
+            //val t2 = System.currentTimeMillis()
+            //println((if (res.isDefined) "solved" else "timed out") + "... in " + (t2 - t1) / 1000.0 + "s")
+            res match {
+              case Some(true) =>
+                updateState(newModel)
+              case _ =>
+                //here we have a new lower bound: currval
+                lowerBound = currval
+                if (this.debugMinimization)
+                  reporter.info("Found new lower bound: " + currval)
+            }
+          }
+        }
+      } while (continue && iter < MaxIter)
+      //this is the last ditch effort to make the upper bound constant smaller.
+      //check if the floor of the upper-bound is a solution
+      val currval @ FractionalLiteral(n, d) =
+        if (currentModel.isDefinedAt(tvar.id)) {
+          currentModel(tvar.id).asInstanceOf[FractionalLiteral]
+        } else {
+          initModel(tvar.id).asInstanceOf[FractionalLiteral]
+        }
+      if (d != 1) {
+        val (res, newModel) = solver.solveSAT(And(acc, Equals(tvar, floor(currval))))
+        if (res == Some(true))
+          updateState(newModel)
+      }
+      //here, we found a best-effort minimum
+      if (lowerBound != realzero) {
+        updateLowerBound(tvar, lowerBound)
+      }
+      And(acc, Equals(tvar, currval))
+    })
+    new Model(initModel.map {
+      case (id, e) =>
+        if (currentModel.isDefinedAt(id))
+          (id -> currentModel(id))
+        else
+          (id -> initModel(id))
+    }.toMap)
+  }
+
+  def checkBoundingInteger(tvar: Variable, rl: FractionalLiteral, nlctr: Expr, solver: SimpleSolverAPI): Option[Model] = {
+    val nl @ FractionalLiteral(n, d) = normalizeFraction(rl)
+    if (d != 1) {
+      val flval = floor(nl)
+      val (res, newModel) = solver.solveSAT(And(nlctr, Equals(tvar, flval)))
+      res match {
+        case Some(true) => Some(newModel)
+        case _ => None
+      }
+    } else None
+  }
+
+  /**
+   * The following code is little tricky
+   */
+  def computeCompositionLevel(template: Expr): Map[Variable, Int] = {
+    var nestMap = Map[Variable, Int]()
+
+    def updateMax(v: Variable, level: Int) = {
+      if (verbose) reporter.info("Nesting level: " + v + "-->" + level)
+      if (nestMap.contains(v)) {
+        if (nestMap(v) < level) {
+          nestMap -= v
+          nestMap += (v -> level)
+        }
+      } else
+        nestMap += (v -> level)
+    }
+
+    def functionNesting(e: Expr): Int = {
+      e match {
+
+        case Times(e1, v @ Variable(id)) if (TemplateIdFactory.IsTemplateIdentifier(id)) => {
+          val nestLevel = functionNesting(e1)
+          updateMax(v, nestLevel)
+          nestLevel
+        }
+        case Times(v @ Variable(id), e2) if (TemplateIdFactory.IsTemplateIdentifier(id)) => {
+          val nestLevel = functionNesting(e2)
+          updateMax(v, nestLevel)
+          nestLevel
+        }
+        case v @ Variable(id) if (TemplateIdFactory.IsTemplateIdentifier(id)) => {
+          updateMax(v, 0)
+          0
+        }
+        case FunctionInvocation(_, args) => 1 + args.foldLeft(0)((acc, arg) => acc + functionNesting(arg))
+        case t: Terminal => 0
+        /*case UnaryOperator(arg, _) => functionNesting(arg)
+        case BinaryOperator(a1, a2, _) => functionNesting(a1) + functionNesting(a2)*/
+        case Operator(args, _) => args.foldLeft(0)((acc, arg) => acc + functionNesting(arg))
+      }
+    }
+    functionNesting(template)
+    nestMap
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/util/RealExprEvaluator.scala b/src/main/scala/leon/invariant/util/RealExprEvaluator.scala
new file mode 100644
index 000000000..d591de245
--- /dev/null
+++ b/src/main/scala/leon/invariant/util/RealExprEvaluator.scala
@@ -0,0 +1,100 @@
+package leon
+package invariant.util
+
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import scala.math.BigInt.int2bigInt
+
+object RealValuedExprEvaluator {
+
+  /**
+   * Requires that the input expression is ground
+   */
+  def evaluate(expr: Expr): FractionalLiteral = {
+    plainEvaluate(expr)
+  }
+
+  def plainEvaluate(expr: Expr): FractionalLiteral = expr match {
+
+    case UMinus(e) => {
+      val FractionalLiteral(num, denom) = plainEvaluate(e)
+      FractionalLiteral(-num, denom)
+    }
+    case Minus(lhs, rhs) => {
+      plainEvaluate(Plus(lhs, UMinus(rhs)))
+    }
+    case Plus(_, _) | RealPlus(_, _) => {
+      val Operator(Seq(lhs, rhs), op) = expr
+      val FractionalLiteral(lnum, ldenom) = plainEvaluate(lhs)
+      val FractionalLiteral(rnum, rdenom) = plainEvaluate(rhs)
+      normalizeFraction(FractionalLiteral((lnum * rdenom + rnum * ldenom), (ldenom * rdenom)))
+    }
+    case Times(_, _) | RealTimes(_, _) => {
+      val Operator(Seq(lhs, rhs), op) = expr
+      val FractionalLiteral(lnum, ldenom) = plainEvaluate(lhs)
+      val FractionalLiteral(rnum, rdenom) = plainEvaluate(rhs)
+      normalizeFraction(FractionalLiteral((lnum * rnum), (ldenom * rdenom)))
+    }
+    case Division(_, _) | RealDivision(_, _) => {
+      val Operator(Seq(lhs, rhs), op) = expr
+      val FractionalLiteral(lnum, ldenom) = plainEvaluate(lhs)
+      val FractionalLiteral(rnum, rdenom) = plainEvaluate(rhs)
+      plainEvaluate(Times(FractionalLiteral(lnum, ldenom), FractionalLiteral(rdenom, rnum)))
+    }
+    case il @ InfiniteIntegerLiteral(v) => FractionalLiteral(v, 1)
+    case rl @ FractionalLiteral(_, _) => normalizeFraction(rl)
+    case _ => throw new IllegalStateException("Not an evaluatable expression: " + expr)
+  }
+
+  def evaluateRealPredicate(expr: Expr): Boolean = expr match {
+    case Equals(a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) => isEQZ(evaluate(Minus(a, b)))
+    case LessEquals(a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) => isLEZ(evaluate(Minus(a, b)))
+    case LessThan(a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) => isLTZ(evaluate(Minus(a, b)))
+    case GreaterEquals(a @ FractionalLiteral(_, _), b @ FractionalLiteral(_, _)) => isGEZ(evaluate(Minus(a, b)))
+    case GreaterThan(a @ FractionalLiteral(n1, d1), b @ FractionalLiteral(n2, d2)) => isGTZ(evaluate(Minus(a, b)))
+  }
+
+  def isEQZ(rlit: FractionalLiteral): Boolean = {
+    val FractionalLiteral(n, d) = rlit
+    if (d == 0) throw new IllegalStateException("denominator zero")
+    (n == 0)
+  }
+
+  def isLEZ(rlit: FractionalLiteral): Boolean = {
+    val FractionalLiteral(n, d) = rlit
+    if (d == 0) throw new IllegalStateException("denominator zero")
+    if (d < 0) throw new IllegalStateException("denominator negative: " + d)
+    (n <= 0)
+  }
+
+  def isLTZ(rlit: FractionalLiteral): Boolean = {
+    val FractionalLiteral(n, d) = rlit
+    if (d == 0) throw new IllegalStateException("denominator zero")
+    if (d < 0) throw new IllegalStateException("denominator negative: " + d)
+    (n < 0)
+  }
+
+  def isGEZ(rlit: FractionalLiteral): Boolean = {
+    val FractionalLiteral(n, d) = rlit
+    if (d == 0) throw new IllegalStateException("denominator zero")
+    if (d < 0) throw new IllegalStateException("denominator negative: " + d)
+    (n >= 0)
+  }
+
+  def isGTZ(rlit: FractionalLiteral): Boolean = {
+    val FractionalLiteral(n, d) = rlit
+    if (d == 0) throw new IllegalStateException("denominator zero")
+    if (d < 0) throw new IllegalStateException("denominator negative: " + d)
+    (n > 0)
+  }
+
+  def evaluateRealFormula(expr: Expr): Boolean = expr match {
+    case And(args) => args forall evaluateRealFormula
+    case Or(args) => args exists evaluateRealFormula
+    case Not(arg) => !evaluateRealFormula(arg)
+    case BooleanLiteral(b) => b
+    case Operator(args, op) =>
+      evaluateRealPredicate(op(args map evaluate))
+  }
+}
diff --git a/src/main/scala/leon/invariant/util/Stats.scala b/src/main/scala/leon/invariant/util/Stats.scala
new file mode 100644
index 000000000..76a1f12ee
--- /dev/null
+++ b/src/main/scala/leon/invariant/util/Stats.scala
@@ -0,0 +1,130 @@
+package leon
+package invariant.util
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import scala.collection.mutable.{ Map => MutableMap }
+import java.io._
+import leon.invariant._
+import java.io._
+import scala.collection.mutable.{Map => MutableMap}
+
+
+/**
+ * A generic statistics object that provides:
+ * (a) Temporal variables that change over time. We track the total sum and max of the values the variable takes over time
+ * (b) Counters that are incremented over time. Variables can be associated with counters.
+ *     We track the averages value of a variable over time w.r.t to the counters with which it is associated.
+ */
+object Stats {
+  val keystats = MutableMap[String, (Long, Long)]()
+  val counterMap = MutableMap[String, Seq[String]]()
+  var cumKeys = Seq[String]()
+  var timekeys = Set[String]() //this may be inner, outer or cumkey
+
+  private def updateStats(newval: Long, key: String, cname: Option[String]) = {
+    val (cum, max) = keystats.getOrElse(key, {
+      val init = (0: Long, 0: Long)
+      keystats += (key -> (0, 0))
+
+      if (cname.isDefined) {
+        val presentKeys = counterMap(cname.get)
+        counterMap.update(cname.get, presentKeys :+ key)
+      } else {
+        cumKeys :+= key
+      }
+      init
+    })
+    val newcum = cum + newval
+    val newmax = if (max < newval) newval else max
+    keystats.update(key, (newcum, newmax))
+  }
+  //a special method for adding times
+  private def updateTimeStats(newval: Long, key: String, cname: Option[String]) = {
+    if (!timekeys.contains(key))
+      timekeys += key
+    updateStats(newval, key, cname)
+  }
+
+  def updateCumStats(newval: Long, key: String) = updateStats(newval, key, None)
+  def updateCumTime(newval: Long, key: String) = updateTimeStats(newval, key, None)
+  def updateCounter(incr: Long, key: String) = {
+    if (!counterMap.contains(key)) {
+      counterMap.update(key, Seq())
+    }
+    //counters are considered as cumulative stats
+    updateStats(incr, key, None)
+  }
+  def updateCounterStats(newval: Long, key: String, cname: String) = updateStats(newval, key, Some(cname))
+  def updateCounterTime(newval: Long, key: String, cname: String) = updateTimeStats(newval, key, Some(cname))
+
+  private def getCum(key: String): Long = keystats(key)._1
+  private def getMax(key: String): Long = keystats(key)._2
+
+  def dumpStats(pr: PrintWriter) = {
+    //Print cumulative stats
+    cumKeys.foreach(key => {
+      if (timekeys.contains(key)) {
+        pr.println(key + ": " + (getCum(key).toDouble / 1000.0) + "s")
+      } else
+        pr.println(key + ": " + getCum(key))
+    })
+
+    //dump the averages and maximum of all stats associated with counters
+    counterMap.keys.foreach((ckey) => {
+      pr.println("### Statistics for counter: " + ckey + " ####")
+      val counterval = getCum(ckey)
+      val assocKeys = counterMap(ckey)
+      assocKeys.foreach((key) => {
+        if (timekeys.contains(key)) {
+          pr.println("Avg." + key + ": " + (getCum(key).toDouble / (counterval * 1000.0)) + "s")
+          pr.println("Max." + key + ": " + (getMax(key).toDouble / 1000.0) + "s")
+        } else {
+          pr.println("Avg." + key + ": " + (getCum(key).toDouble / counterval))
+          pr.println("Max." + key + ": " + getMax(key))
+        }
+      })
+    })
+  }
+}
+
+/**
+ * Statistics specific for this application
+ */
+object SpecificStats {
+
+  var output: String = ""
+  def addOutput(out: String) = {
+    output += out + "\n"
+  }
+  def dumpOutputs(pr: PrintWriter) {
+    pr.println("########## Outputs ############")
+    pr.println(output)
+    pr.flush()
+  }
+
+  //minimization stats
+  var lowerBounds = Map[FunDef, Map[Variable, FractionalLiteral]]()
+  var lowerBoundsOutput = Map[FunDef, String]()
+  def addLowerBoundStats(fd: FunDef, lbMap: Map[Variable, FractionalLiteral], out: String) = {
+    lowerBounds += (fd -> lbMap)
+    lowerBoundsOutput += (fd -> out)
+  }
+  def dumpMinimizationStats(pr: PrintWriter) {
+    pr.println("########## Lower Bounds ############")
+    lowerBounds.foreach((pair) => {
+      val (fd, lbMap) = pair
+      pr.print(fd.id + ": \t")
+      lbMap.foreach((entry) => {
+        pr.print("(" + entry._1 + "->" + entry._2 + "), ")
+      })
+      pr.print("\t Test results: " + lowerBoundsOutput(fd))
+      pr.println()
+    })
+    pr.flush()
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/invariant/util/Util.scala b/src/main/scala/leon/invariant/util/Util.scala
new file mode 100644
index 000000000..fdd70bf9a
--- /dev/null
+++ b/src/main/scala/leon/invariant/util/Util.scala
@@ -0,0 +1,717 @@
+package leon
+package invariant.util
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import scala.collection.mutable.{ Set => MutableSet, Map => MutableMap }
+import scala.collection.immutable.Stack
+import java.io._
+import leon.invariant._
+import java.io._
+import solvers.z3._
+import solvers._
+import invariant.engine._
+import invariant.factories._
+import invariant.structure._
+import leon.purescala.PrettyPrintable
+import leon.purescala.PrinterContext
+import purescala.PrinterHelpers._
+import FunctionUtils._
+import leon.invariant.templateSolvers.ExtendedUFSolver
+import scala.annotation.tailrec
+
+object FileCountGUID {
+  var fileCount = 0
+  def getID: Int = {
+    var oldcnt = fileCount
+    fileCount += 1
+    oldcnt
+  }
+}
+
+//three valued logic
+object TVL {
+  abstract class Value
+  object FALSE extends Value
+  object TRUE extends Value
+  object MAYBE extends Value
+}
+
+//this is used as a place holder for result
+case class ResultVariable(tpe: TypeTree) extends Expr with Terminal with PrettyPrintable {
+  val getType = tpe
+  override def toString: String = "#res"
+
+  def printWith(implicit pctx: PrinterContext) {
+    p"#res"
+  }
+}
+
+//this used to refer to the time steps of a procedure
+case class TimeVariable() extends Expr with Terminal with PrettyPrintable {
+  val getType = IntegerType
+  override def toString: String = "#time"
+  def printWith(implicit pctx: PrinterContext) {
+    p"#time"
+  }
+}
+
+//this used to refer to the depth of a procedure
+case class DepthVariable() extends Expr with Terminal with PrettyPrintable {
+  val getType = IntegerType
+  override def toString: String = "#depth"
+  def printWith(implicit pctx: PrinterContext) {
+    p"#time"
+  }
+}
+
+object TVarFactory {
+
+  val temporaries = MutableSet[Identifier]()
+  //these are dummy identifiers used in 'CaseClassSelector' conversion
+  val dummyIds = MutableSet[Identifier]()
+
+  def createTemp(name: String, tpe: TypeTree = Untyped): Identifier = {
+    val freshid = FreshIdentifier(name, tpe, true)
+    temporaries.add(freshid)
+    freshid
+  }
+
+  def createDummy(tpe: TypeTree): Identifier = {
+    val freshid = FreshIdentifier("dy", tpe, true)
+    dummyIds.add(freshid)
+    freshid
+  }
+
+  def isTemporary(id: Identifier): Boolean = temporaries.contains(id)
+  def isDummy(id: Identifier): Boolean = dummyIds.contains(id)
+}
+
+object Util {
+
+  val zero = InfiniteIntegerLiteral(0)
+  val one = InfiniteIntegerLiteral(1)
+  val tru = BooleanLiteral(true)
+  val fls = BooleanLiteral(false)
+
+  /**
+   * Here, we exclude empty units that do not have any modules and empty
+   * modules that do not have any definitions
+   */
+  def copyProgram(prog: Program, mapdefs: (Seq[Definition] => Seq[Definition])): Program = {
+    prog.copy(units = prog.units.collect {
+      case unit if (!unit.defs.isEmpty) => unit.copy(defs = unit.defs.collect {
+        case module : ModuleDef  if (!module.defs.isEmpty) =>
+          module.copy(defs = mapdefs(module.defs))
+        case other => other
+      })
+    })
+  }
+
+  def createTemplateFun(plainTemp: Expr): FunctionInvocation = {
+    val tmpl = Lambda(getTemplateIds(plainTemp).toSeq.map(id => ValDef(id)), plainTemp)
+    val tmplFd = new FunDef(FreshIdentifier("tmpl", FunctionType(Seq(tmpl.getType), BooleanType), false),
+      Seq(), BooleanType, Seq(ValDef(FreshIdentifier("arg", tmpl.getType),
+        Some(tmpl.getType))))
+    tmplFd.body = Some(BooleanLiteral(true))
+    FunctionInvocation(TypedFunDef(tmplFd, Seq()), Seq(tmpl))
+  }
+
+  /**
+   * This is the default template generator.
+   * Note: we are not creating template for libraries.
+   */
+  def getOrCreateTemplateForFun(fd: FunDef): Expr = {
+    val plainTemp = if (fd.hasTemplate) fd.getTemplate
+    else if (fd.annotations.contains("library")) BooleanLiteral(true)
+    else {
+      //just consider all the arguments, return values that are integers
+      val baseTerms = fd.params.filter((vardecl) => isNumericType(vardecl.getType)).map(_.toVariable) ++
+        (if (isNumericType(fd.returnType)) Seq(Util.getFunctionReturnVariable(fd))
+        else Seq())
+      val lhs = baseTerms.foldLeft(TemplateIdFactory.freshTemplateVar(): Expr)((acc, t) => {
+        Plus(Times(TemplateIdFactory.freshTemplateVar(), t), acc)
+      })
+      val tempExpr = LessEquals(lhs, InfiniteIntegerLiteral(0))
+      tempExpr
+    }
+    plainTemp
+  }
+
+  def mapFunctionsInExpr(funmap: Map[FunDef, FunDef])(ine: Expr): Expr = {
+    simplePostTransform((e: Expr) => e match {
+      case FunctionInvocation(tfd, args) if funmap.contains(tfd.fd) =>
+        FunctionInvocation(TypedFunDef(funmap(tfd.fd), tfd.tps), args)
+      case _ => e
+    })(ine)
+  }
+
+  def assignTemplateAndCojoinPost(funToTmpl: Map[FunDef, Expr], prog: Program, funToPost: Map[FunDef, Expr] = Map()): Program = {
+
+    val funMap = Util.functionsWOFields(prog.definedFunctions).foldLeft(Map[FunDef, FunDef]()) {
+      case (accMap, fd) if fd.isTheoryOperation =>
+        accMap + (fd -> fd)
+      case (accMap, fd) => {
+        val freshId = FreshIdentifier(fd.id.name, fd.returnType, true)
+        val newfd = new FunDef(freshId, fd.tparams, fd.returnType, fd.params)
+        accMap.updated(fd, newfd)
+      }
+    }
+
+    // FIXME: This with createAnd (which performs simplifications) gives an error during composition.
+    val mapExpr = mapFunctionsInExpr(funMap) _
+    for ((from, to) <- funMap) {
+      to.fullBody = if (!funToTmpl.contains(from)) {
+        mapExpr {
+          from.fullBody match {
+            case Ensuring(b, post) =>
+              Ensuring(b,
+                Lambda(Seq(ValDef(Util.getResId(from).get)),
+                  createAnd(Seq(from.getPostWoTemplate, funToPost.getOrElse(from, tru)))))
+            case fb =>
+              fb
+          }
+        }
+      } else {
+        val newTmpl = createTemplateFun(funToTmpl(from))
+        mapExpr {
+          from.fullBody match {
+            case Require(pre, body) =>
+              val toPost =
+                Lambda(Seq(ValDef(FreshIdentifier("res", from.returnType))),
+                  createAnd(Seq(newTmpl, funToPost.getOrElse(from, tru))))
+              Ensuring(Require(pre, body), toPost)
+
+            case Ensuring(Require(pre, body), post) =>
+              Ensuring(Require(pre, body),
+                Lambda(Seq(ValDef(Util.getResId(from).get)),
+                  createAnd(Seq(from.getPostWoTemplate, newTmpl, funToPost.getOrElse(from, tru)))))
+
+            case Ensuring(body, post) =>
+              Ensuring(body,
+                Lambda(Seq(ValDef(Util.getResId(from).get)),
+                  createAnd(Seq(from.getPostWoTemplate, newTmpl, funToPost.getOrElse(from, tru)))))
+
+            case body =>
+              val toPost =
+                Lambda(Seq(ValDef(FreshIdentifier("res", from.returnType))),
+                  createAnd(Seq(newTmpl, funToPost.getOrElse(from, tru))))
+              Ensuring(body, toPost)
+          }
+        }
+      }
+      //copy annotations
+      from.flags.foreach(to.addFlag(_))
+    }
+    val newprog = Util.copyProgram(prog, (defs: Seq[Definition]) => defs.map {
+      case fd: FunDef if funMap.contains(fd) =>
+        funMap(fd)
+      case d => d
+    })
+    newprog
+  }
+
+  def functionByName(nm: String, prog: Program) = {
+    prog.definedFunctions.find(fd => fd.id.name == nm)
+  }
+
+  def functionsWOFields(fds: Seq[FunDef]): Seq[FunDef] = {
+    fds.filter(_.isRealFunction)
+  }
+
+  def isNumericExpr(expr: Expr): Boolean = {
+    expr.getType == IntegerType ||
+      expr.getType == RealType
+  }
+
+  def getFunctionReturnVariable(fd: FunDef) = {
+    if (fd.hasPostcondition) getResId(fd).get.toVariable
+    else ResultVariable(fd.returnType) /*FreshIdentifier("res", fd.returnType).toVariable*/
+  }
+
+  //compute the formal to the actual argument mapping
+  def formalToActual(call: Call): Map[Expr, Expr] = {
+    val fd = call.fi.tfd.fd
+    val resvar = getFunctionReturnVariable(fd)
+    val argmap: Map[Expr, Expr] = Map(resvar -> call.retexpr) ++ fd.params.map(_.id.toVariable).zip(call.fi.args)
+    argmap
+  }
+
+  /**
+   * Checks if the input expression has only template variables as free variables
+   */
+  def isTemplateExpr(expr: Expr): Boolean = {
+    var foundVar = false
+    simplePostTransform((e: Expr) => e match {
+      case Variable(id) => {
+        if (!TemplateIdFactory.IsTemplateIdentifier(id))
+          foundVar = true
+        e
+      }
+      case ResultVariable(_) => {
+        foundVar = true
+        e
+      }
+      case _ => e
+    })(expr)
+
+    !foundVar
+  }
+
+  def getTemplateIds(expr: Expr) = {
+    variablesOf(expr).filter(TemplateIdFactory.IsTemplateIdentifier)
+  }
+
+  def getTemplateVars(expr: Expr): Set[Variable] = {
+    /*var tempVars = Set[Variable]()
+    postTraversal(e => e match {
+      case t @ Variable(id) =>
+        if (TemplateIdFactory.IsTemplateIdentifier(id))
+          tempVars += t
+      case _ =>
+    })(expr)
+    tempVars*/
+    getTemplateIds(expr).map(_.toVariable)
+  }
+
+  /**
+   * Checks if the expression has real valued sub-expressions.
+   */
+  def hasReals(expr: Expr): Boolean = {
+    var foundReal = false
+    simplePostTransform((e: Expr) => e match {
+      case _ => {
+        if (e.getType == RealType)
+          foundReal = true;
+        e
+      }
+    })(expr)
+    foundReal
+  }
+
+  /**
+   * Checks if the expression has real valued sub-expressions.
+   * Note: important, <, <=, > etc have default int type.
+   * However, they can also be applied over real arguments
+   * So check only if all terminals are real
+   */
+  def hasInts(expr: Expr): Boolean = {
+    var foundInt = false
+    simplePostTransform((e: Expr) => e match {
+      case e: Terminal if (e.getType == Int32Type || e.getType == IntegerType) => {
+        foundInt = true;
+        e
+      }
+      case _ => e
+    })(expr)
+    foundInt
+  }
+
+  def hasMixedIntReals(expr: Expr): Boolean = {
+    hasInts(expr) && hasReals(expr)
+  }
+
+  def fix[A](f: (A) => A)(a: A): A = {
+    val na = f(a)
+    if (a == na) a else fix(f)(na)
+  }
+
+  def atomNum(e: Expr): Int = {
+    var count: Int = 0
+    simplePostTransform((e: Expr) => e match {
+      case And(args) => {
+        count += args.size
+        e
+      }
+      case Or(args) => {
+        count += args.size
+        e
+      }
+      case _ => e
+    })(e)
+    count
+  }
+
+  def numUIFADT(e: Expr): Int = {
+    var count: Int = 0
+    simplePostTransform((e: Expr) => e match {
+      case FunctionInvocation(_, _) | CaseClass(_, _) | Tuple(_) => {
+        count += 1
+        e
+      }
+      case _ => e
+    })(e)
+    count
+  }
+
+  def hasCalls(e: Expr) = numUIFADT(e) >= 1
+
+  def getCallExprs(ine: Expr): Set[Expr] = {
+    var calls = Set[Expr]()
+    simplePostTransform((e: Expr) => e match {
+      case call @ _ if Util.isCallExpr(e) => {
+        calls += e
+        call
+      }
+      case _ => e
+    })(ine)
+    calls
+  }
+
+  def isCallExpr(e: Expr): Boolean = e match {
+    case Equals(Variable(_), FunctionInvocation(_, _)) => true
+    // case Iff(Variable(_),FunctionInvocation(_,_)) => true
+    case _ => false
+  }
+
+  def isADTConstructor(e: Expr): Boolean = e match {
+    case Equals(Variable(_), CaseClass(_, _)) => true
+    case Equals(Variable(_), Tuple(_)) => true
+    case _ => false
+  }
+
+  def modelToExpr(model: Model): Expr = {
+    model.foldLeft(tru: Expr)((acc, elem) => {
+      val (k, v) = elem
+      val eq = Equals(k.toVariable, v)
+      if (acc == tru) eq
+      else And(acc, eq)
+    })
+  }
+
+  def gcd(x: Int, y: Int): Int = {
+    if (x == 0) y
+    else gcd(y % x, x)
+  }
+
+  def toZ3SMTLIB(expr: Expr, filename: String,
+    theory: String, ctx: LeonContext, pgm: Program,
+    useBitvectors: Boolean = false,
+    bitvecSize: Int = 32) = {
+    //create new solver, assert constraints and print
+    val printSol = new ExtendedUFSolver(ctx, pgm)
+    printSol.assertCnstr(expr)
+    val writer = new PrintWriter(filename)
+    writer.println(printSol.ctrsToString(theory))
+    printSol.free()
+    writer.flush()
+    writer.close()
+  }
+
+  /**
+   * A helper function that can be used to hardcode an invariant and see if it unsatifies the paths
+   */
+  def checkInvariant(expr: Expr, ctx: LeonContext, prog: Program): Option[Boolean] = {
+    val idmap: Map[Expr, Expr] = variablesOf(expr).collect {
+      case id @ _ if (id.name.toString == "a?") => id.toVariable -> InfiniteIntegerLiteral(6)
+      case id @ _ if (id.name.toString == "c?") => id.toVariable -> InfiniteIntegerLiteral(2)
+    }.toMap
+    //println("found ids: " + idmap.keys)
+    if (!idmap.keys.isEmpty) {
+      val newpathcond = replace(idmap, expr)
+      //check if this is solvable
+      val solver = SimpleSolverAPI(SolverFactory(() => new ExtendedUFSolver(ctx, prog)))
+      solver.solveSAT(newpathcond)._1 match {
+        case Some(true) => {
+          println("Path satisfiable for a?,c? -->6,2 ")
+          Some(true)
+        }
+        case _ => {
+          println("Path unsat for a?,c? --> 6,2")
+          Some(false)
+        }
+      }
+    } else None
+  }
+
+  def collectUNSATCores(ine: Expr, ctx: LeonContext, prog: Program): Expr = {
+    var controlVars = Map[Variable, Expr]()
+    var newEqs = Map[Expr, Expr]()
+    val solver = new ExtendedUFSolver(ctx, prog)
+    val newe = simplePostTransform((e: Expr) => e match {
+      case And(_) | Or(_) => {
+        val v = TVarFactory.createTemp("a", BooleanType).toVariable
+        newEqs += (v -> e)
+        val newe = Equals(v, e)
+
+        //create new variable and add it in disjunction
+        val cvar = FreshIdentifier("ctrl", BooleanType, true).toVariable
+        controlVars += (cvar -> newe)
+        solver.assertCnstr(Or(newe, cvar))
+        v
+      }
+      case _ => e
+    })(ine)
+    //create new variable and add it in disjunction
+    val cvar = FreshIdentifier("ctrl", BooleanType, true).toVariable
+    controlVars += (cvar -> newe)
+    solver.assertCnstr(Or(newe, cvar))
+
+    val res = solver.checkAssumptions(controlVars.keySet.map(Not.apply _))
+    println("Result: " + res)
+    val coreExprs = solver.getUnsatCore
+    val simpcores = coreExprs.foldLeft(Seq[Expr]())((acc, coreExp) => {
+      val Not(cvar @ Variable(_)) = coreExp
+      val newexp = controlVars(cvar)
+      //println("newexp: "+newexp)
+      newexp match {
+        // case Iff(v@Variable(_),rhs) if(newEqs.contains(v)) => acc
+        case Equals(v @ Variable(_), rhs) if (v.getType == BooleanType && rhs.getType == BooleanType && newEqs.contains(v)) => acc
+        case _ => {
+          acc :+ newexp
+        }
+      }
+    })
+    val cores = Util.fix((e: Expr) => replace(newEqs, e))(Util.createAnd(simpcores.toSeq))
+
+    solver.free
+    //cores
+    ExpressionTransformer.unFlatten(cores,
+      variablesOf(ine).filterNot(TVarFactory.isTemporary _))
+  }
+
+  def isMultFunctions(fd: FunDef) = {
+    (fd.id.name == "mult" || fd.id.name == "pmult") &&
+      fd.isTheoryOperation
+  }
+  //replaces occurrences of mult by Times
+  def multToTimes(ine: Expr): Expr = {
+    simplePostTransform((e: Expr) => e match {
+      case FunctionInvocation(TypedFunDef(fd, _), args) if isMultFunctions(fd) => {
+        Times(args(0), args(1))
+      }
+      case _ => e
+    })(ine)
+  }
+
+  /**
+   * A cross product with an optional filter
+   */
+  def cross[U, V](a: Set[U], b: Set[V], selector: Option[(U, V) => Boolean] = None): Set[(U, V)] = {
+
+    val product = (for (x <- a; y <- b) yield (x, y))
+    if (selector.isDefined)
+      product.filter(pair => selector.get(pair._1, pair._2))
+    else
+      product
+  }
+
+  def getResId(funDef: FunDef): Option[Identifier] = {
+    funDef.fullBody match {
+      case Ensuring(_, post) => {
+        post match {
+          case Lambda(Seq(ValDef(fromRes, _)), _) => Some(fromRes)
+          case _ =>
+            throw new IllegalStateException("Postcondition with multiple return values!")
+        }
+      }
+      case _ => None
+    }
+  }
+
+  def createAnd(exprs: Seq[Expr]): Expr = {
+    val newExprs = exprs.filterNot(conj => conj == tru)
+    newExprs match {
+      case Seq() => tru
+      case Seq(e) => e
+      case _ => And(newExprs)
+    }
+  }
+
+  def createOr(exprs: Seq[Expr]): Expr = {
+    val newExprs = exprs.filterNot(disj => disj == fls)
+    newExprs match {
+      case Seq() => fls
+      case Seq(e) => e
+      case _ => Or(newExprs)
+    }
+  }
+
+  def isNumericType(t: TypeTree) = t match {
+    case IntegerType | RealType => true
+    case _ => false
+  }
+
+  //tests if the solver uses nlsat
+  def usesNLSat(solver: AbstractZ3Solver) = {
+    //check for nlsat
+    val x = FreshIdentifier("x", RealType).toVariable
+    val testExpr = Equals(Times(x, x), FractionalLiteral(2, 1))
+    solver.assertCnstr(testExpr)
+    solver.check match {
+      case Some(true) => true
+      case _ => false
+    }
+  }
+}
+
+/**
+ * maps all real valued variables and literals to new integer variables/literals and
+ * performs the reverse mapping
+ * Note: this should preserve the template identifier property
+ */
+class RealToInt {
+
+  val bone = BigInt(1)
+  var realToIntId = Map[Identifier, Identifier]()
+  var intToRealId = Map[Identifier, Identifier]()
+
+  def mapRealToInt(inexpr: Expr): Expr = {
+    val transformer = (e: Expr) => e match {
+      case FractionalLiteral(num, `bone`) => InfiniteIntegerLiteral(num)
+      case FractionalLiteral(_, _) => throw new IllegalStateException("Real literal with non-unit denominator")
+      case v @ Variable(realId) if (v.getType == RealType) => {
+        val newId = realToIntId.getOrElse(realId, {
+          //note: the fresh identifier has to be a template identifier if the original one is a template identifier
+          val freshId = if (TemplateIdFactory.IsTemplateIdentifier(realId))
+            TemplateIdFactory.freshIdentifier(realId.name, IntegerType)
+          else
+            FreshIdentifier(realId.name, IntegerType, true)
+
+          realToIntId += (realId -> freshId)
+          intToRealId += (freshId -> realId)
+          freshId
+        })
+        Variable(newId)
+      }
+      case _ => e
+    }
+    simplePostTransform(transformer)(inexpr)
+  }
+
+  def unmapModel(model: Model): Model = {
+    new Model(model.map(pair => {
+      val (key, value) = if (intToRealId.contains(pair._1)) {
+        (intToRealId(pair._1),
+          pair._2 match {
+            case InfiniteIntegerLiteral(v) => FractionalLiteral(v.toInt, 1)
+            case _ => pair._2
+          })
+      } else pair
+      (key -> value)
+    }).toMap)
+  }
+
+  def mapModel(model: Model): Model = {
+    new Model(model.collect {
+      case (k, FractionalLiteral(n, bone)) =>
+        (realToIntId(k), InfiniteIntegerLiteral(n))
+      case (k, v) =>
+        if (realToIntId.contains(k)) {
+          (realToIntId(k), v)
+        } else {
+          (k, v)
+        }
+    }.toMap)
+  }
+}
+
+class MultiMap[A, B] extends scala.collection.mutable.HashMap[A, scala.collection.mutable.Set[B]] with scala.collection.mutable.MultiMap[A, B] {
+  /**
+   * Creates a new map and does not change the existing map
+   */
+  def append(that: MultiMap[A, B]): MultiMap[A, B] = {
+    val newmap = new MultiMap[A, B]()
+    this.foreach { case (k, vset) => newmap += (k -> vset) }
+    that.foreach {
+      case (k, vset) => vset.foreach(v => newmap.addBinding(k, v))
+    }
+    newmap
+  }
+}
+
+/**
+ * A multimap that allows duplicate entries
+ */
+class OrderedMultiMap[A, B] extends scala.collection.mutable.HashMap[A, scala.collection.mutable.ListBuffer[B]] {
+
+  def addBinding(key: A, value: B): this.type = {
+    get(key) match {
+      case None =>
+        val list = new scala.collection.mutable.ListBuffer[B]()
+        list += value
+        this(key) = list
+      case Some(list) =>
+        list += value
+    }
+    this
+  }
+
+  /**
+   * Creates a new map and does not change the existing map
+   */
+  def append(that: OrderedMultiMap[A, B]): OrderedMultiMap[A, B] = {
+    val newmap = new OrderedMultiMap[A, B]()
+    this.foreach { case (k, vlist) => newmap += (k -> vlist) }
+    that.foreach {
+      case (k, vlist) => vlist.foreach(v => newmap.addBinding(k, v))
+    }
+    newmap
+  }
+
+  /**
+   * Make the value of every key distinct
+   */
+  def distinct: OrderedMultiMap[A, B] = {
+    val newmap = new OrderedMultiMap[A, B]()
+    this.foreach { case (k, vlist) => newmap += (k -> vlist.distinct) }
+    newmap
+  }
+}
+
+/**
+ * Implements a mapping from Seq[A] to B where Seq[A]
+ * is stored as a Trie
+ */
+final class TrieMap[A, B] {
+  var childrenMap = Map[A, TrieMap[A, B]]()
+  var dataMap = Map[A, B]()
+
+  @tailrec def addBinding(key: Seq[A], value: B) {
+    key match {
+      case Seq() =>
+        throw new IllegalStateException("Key is empty!!")
+      case Seq(x) =>
+        //add the value to the dataMap
+        if (dataMap.contains(x))
+          throw new IllegalStateException("A mapping for key already exists: " + x + " --> " + dataMap(x))
+        else
+          dataMap += (x -> value)
+      case head +: tail => //here, tail has at least one element
+        //check if we have an entry for seq(0) if yes go to the children, if not create one
+        val child = childrenMap.getOrElse(head, {
+          val ch = new TrieMap[A, B]()
+          childrenMap += (head -> ch)
+          ch
+        })
+        child.addBinding(tail, value)
+    }
+  }
+
+  @tailrec def lookup(key: Seq[A]): Option[B] = {
+    key match {
+      case Seq() =>
+        throw new IllegalStateException("Key is empty!!")
+      case Seq(x) =>
+        dataMap.get(x)
+      case head +: tail => //here, tail has at least one element
+        childrenMap.get(head) match {
+          case Some(child) =>
+            child.lookup(tail)
+          case _ => None
+        }
+    }
+  }
+}
+
+class CounterMap[T] extends scala.collection.mutable.HashMap[T, Int] {
+  def inc(v: T) = {
+    if (this.contains(v))
+      this(v) += 1
+    else this += (v -> 1)
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/purescala/Constructors.scala b/src/main/scala/leon/purescala/Constructors.scala
index 7747ec680..913e6efbd 100644
--- a/src/main/scala/leon/purescala/Constructors.scala
+++ b/src/main/scala/leon/purescala/Constructors.scala
@@ -19,7 +19,7 @@ import Types._
   *  */
 object Constructors {
 
-  /** If `isTuple`, the whole expression is returned. This is to avoid a situation like  
+  /** If `isTuple`, the whole expression is returned. This is to avoid a situation like
     * `tupleSelect(tupleWrap(Seq(Tuple(x,y))),1) -> x`, which is not expected.
     * Instead,
     * `tupleSelect(tupleWrap(Seq(Tuple(x,y))),1) -> Tuple(x,y)`.
@@ -71,10 +71,10 @@ object Constructors {
     */
   def tupleWrap(es: Seq[Expr]): Expr = es match {
     case Seq() => UnitLiteral()
-    case Seq(elem) => elem 
+    case Seq(elem) => elem
     case more => Tuple(more)
   }
-  
+
   /** Wraps the sequence of patterns as a tuple. If the sequence contains a single pattern, it is returned instead.
     * If the sequence is empty, [[purescala.Expressions.LiteralPattern `LiteralPattern`]]`(None, `[[purescala.Expressions.UnitLiteral `UnitLiteral`]]`())` is returned.
     * @see [[purescala.Expressions.TuplePattern]]
@@ -85,9 +85,9 @@ object Constructors {
     case Seq(elem) => elem
     case more => TuplePattern(None, more)
   }
-  
+
   /** Wraps the sequence of types as a tuple. If the sequence contains a single type, it is returned instead.
-    * If the sequence is empty, the [[purescala.Types.UnitType UnitType]] is returned. 
+    * If the sequence is empty, the [[purescala.Types.UnitType UnitType]] is returned.
     * @see [[purescala.Types.TupleType]]
     */
   def tupleTypeWrap(tps : Seq[TypeTree]) = tps match {
@@ -101,12 +101,12 @@ object Constructors {
     * @see [[purescala.Expressions.FunctionInvocation]]
     */
   def functionInvocation(fd : FunDef, args : Seq[Expr]) = {
-    
+
     require(fd.params.length == args.length, "Invoking function with incorrect number of arguments")
-    
+
     val formalType = tupleTypeWrap(fd.params map { _.getType })
     val actualType = tupleTypeWrap(args map { _.getType })
-    
+
     canBeSubtypeOf(actualType, typeParamsOf(formalType).toSeq, formalType) match {
       case Some(tmap) =>
         FunctionInvocation(fd.typed(fd.tparams map { tpd => tmap.getOrElse(tpd.tp, tpd.tp) }), args)
@@ -168,13 +168,13 @@ object Constructors {
     val filtered = filterCases(scrutinee.getType, None, cases)
     if (filtered.nonEmpty)
       MatchExpr(scrutinee, filtered)
-    else 
+    else
       Error(
         cases.headOption.map{ _.rhs.getType }.getOrElse(Untyped),
         "No case matches the scrutinee"
       )
-  } 
-  
+  }
+
   /** $encodingof `&&`-expressions with arbitrary number of operands, and simplified.
     * @see [[purescala.Expressions.And And]]
     */
@@ -251,7 +251,7 @@ object Constructors {
     */
   def finiteArray(els: Seq[Expr]): Expr = {
     require(els.nonEmpty)
-    finiteArray(els, None, Untyped) // Untyped is not correct, but will not be used anyway 
+    finiteArray(els, None, Untyped) // Untyped is not correct, but will not be used anyway
   }
   /** $encodingof Simplified `Array[...](...)` (array length and default element defined at run-time) with type information
     * @see [[purescala.Constructors#finiteArray(els:Map* finiteArray]]
@@ -320,11 +320,11 @@ object Constructors {
     case (_, InfiniteIntegerLiteral(bi)) if bi == 0 => lhs
     case (IntLiteral(0), _) => rhs
     case (_, IntLiteral(0)) => lhs
-    case (RealLiteral(d), _) if d == 0 => rhs
-    case (_, RealLiteral(d)) if d == 0 => lhs
-    case (IsTyped(_, IntegerType), IsTyped(_, IntegerType)) => Plus(lhs, rhs)
+    case (FractionalLiteral(n, d), _) if n == 0 => rhs
+    case (_, FractionalLiteral(n, d)) if n == 0 => lhs
     case (IsTyped(_, Int32Type), IsTyped(_, Int32Type)) => BVPlus(lhs, rhs)
     case (IsTyped(_, RealType), IsTyped(_, RealType)) => RealPlus(lhs, rhs)
+    case _ => Plus(lhs, rhs)
   }
 
   /** $encodingof simplified `... - ...` (minus).
@@ -337,9 +337,9 @@ object Constructors {
     case (_, IntLiteral(0)) => lhs
     case (InfiniteIntegerLiteral(bi), _) if bi == 0 => UMinus(rhs)
     case (IntLiteral(0), _) => BVUMinus(rhs)
-    case (IsTyped(_, IntegerType), IsTyped(_, IntegerType)) => Minus(lhs, rhs)
     case (IsTyped(_, Int32Type), IsTyped(_, Int32Type)) => BVMinus(lhs, rhs)
     case (IsTyped(_, RealType), IsTyped(_, RealType)) => RealMinus(lhs, rhs)
+    case _ => Minus(lhs, rhs)
   }
 
   /** $encodingof simplified `... * ...` (times).
@@ -356,9 +356,9 @@ object Constructors {
     case (_, IntLiteral(1)) => lhs
     case (IntLiteral(0), _) => IntLiteral(0)
     case (_, IntLiteral(0)) => IntLiteral(0)
-    case (IsTyped(_, IntegerType), IsTyped(_, IntegerType)) => Times(lhs, rhs)
     case (IsTyped(_, Int32Type), IsTyped(_, Int32Type)) => BVTimes(lhs, rhs)
     case (IsTyped(_, RealType), IsTyped(_, RealType)) => RealTimes(lhs, rhs)
+    case _ => Times(lhs, rhs)
   }
 
   /** $encodingof expr.asInstanceOf[tpe], returns `expr` it it already is of type `tpe`.  */
@@ -366,7 +366,6 @@ object Constructors {
     if (isSubtypeOf(expr.getType, tpe)) {
       expr
     } else {
-      //println(s"$expr:${expr.getType} is not a subtype of $tpe")
       AsInstanceOf(expr, tpe)
     }
   }
diff --git a/src/main/scala/leon/purescala/ExprOps.scala b/src/main/scala/leon/purescala/ExprOps.scala
index 1d98f57b8..d8aadc52a 100644
--- a/src/main/scala/leon/purescala/ExprOps.scala
+++ b/src/main/scala/leon/purescala/ExprOps.scala
@@ -14,7 +14,7 @@ import solvers._
 
 /** Provides functions to manipulate [[purescala.Expressions]].
   *
-  * This object provides a few generic operations on Leon expressions, 
+  * This object provides a few generic operations on Leon expressions,
   * as well as some common operations.
   *
   * The generic operations lets you apply operations on a whole tree
@@ -47,7 +47,7 @@ object ExprOps {
     * A right tree fold applies the input function to the subnodes first (from left
     * to right), and combine the results along with the current node value.
     *
-    * @param f a function that takes the current node and the seq 
+    * @param f a function that takes the current node and the seq
     *        of results form the subtrees.
     * @param e The Expr on which to apply the fold.
     * @return The expression after applying `f` on all subtrees.
@@ -115,10 +115,10 @@ object ExprOps {
     * Takes a partial function of replacements and substitute
     * '''before''' recursing down the trees.
     *
-    * Supports two modes : 
-    * 
+    * Supports two modes :
+    *
     *   - If applyRec is false (default), will only substitute once on each level.
-    * 
+    *
     *   e.g.
     *   {{{
     *     Add(a, Minus(b, c)) with replacements: Minus(b,c) -> d, b -> e, d -> f
@@ -127,18 +127,18 @@ object ExprOps {
     *   {{{
     *     Add(a, d)   // And not Add(a, f) because it only substitute once for each level.
     *   }}}
-    *     
+    *
     *   - If applyRec is true, it will substitute multiple times on each level:
-    * 
+    *
     *   e.g.
     *   {{{
     *   Add(a, Minus(b, c)) with replacements: Minus(b,c) -> d, b -> e, d -> f
     *   }}}
     *   will yield:
     *   {{{
-    *   Add(a, f)  
+    *   Add(a, f)
     *   }}}
-    *   
+    *
     * @note The mode with applyRec true can diverge if f is not well formed
     */
   def preMap(f: Expr => Option[Expr], applyRec : Boolean = false)(e: Expr): Expr = {
@@ -146,7 +146,7 @@ object ExprOps {
 
     val newV = if (applyRec) {
       // Apply f as long as it returns Some()
-      fixpoint { e : Expr => f(e) getOrElse e } (e) 
+      fixpoint { e : Expr => f(e) getOrElse e } (e)
     } else {
       f(e) getOrElse e
     }
@@ -166,7 +166,7 @@ object ExprOps {
     * Takes a partial function of replacements.
     * Substitutes '''after''' recursing down the trees.
     *
-    * Supports two modes : 
+    * Supports two modes :
     *
     *   - If applyRec is false (default), will only substitute once on each level.
     *   e.g.
@@ -177,7 +177,7 @@ object ExprOps {
     *   {{{
     *     Add(a, Minus(e, c))
     *   }}}
-    *   
+    *
     *   - If applyRec is true, it will substitute multiple times on each level:
     *   e.g.
     *   {{{
@@ -185,7 +185,7 @@ object ExprOps {
     *   }}}
     *   will yield:
     *   {{{
-    *     Add(a, f)  
+    *     Add(a, f)
     *   }}}
     *
     * @note The mode with applyRec true can diverge if f is not well formed (i.e. not convergent)
@@ -205,7 +205,7 @@ object ExprOps {
 
     if (applyRec) {
       // Apply f as long as it returns Some()
-      fixpoint { e : Expr => f(e) getOrElse e } (newV) 
+      fixpoint { e : Expr => f(e) getOrElse e } (newV)
     } else {
       f(newV) getOrElse newV
     }
@@ -222,7 +222,7 @@ object ExprOps {
     * @param pre a function applied on a node before doing a recursion in the children
     * @param post a function applied to the node built from the recursive application to
                   all children
-    * @param combiner a function to combine the resulting values from all children with 
+    * @param combiner a function to combine the resulting values from all children with
                       the current node
     * @param init the initial value
     * @param expr the expression on which to apply the transform
@@ -270,7 +270,7 @@ object ExprOps {
   def collect[T](matcher: Expr => Set[T])(e: Expr): Set[T] = {
     foldRight[Set[T]]({ (e, subs) => matcher(e) ++ subs.flatten } )(e)
   }
-  
+
   def collectPreorder[T](matcher: Expr => Seq[T])(e: Expr): Seq[T] = {
     foldRight[Seq[T]]({ (e, subs) => matcher(e) ++ subs.flatten } )(e)
   }
@@ -341,15 +341,15 @@ object ExprOps {
       case _ => Set()
     }(expr)
   }
-  
+
   /** Returns functions in directly nested LetDefs */
   def directlyNestedFunDefs(e: Expr): Set[FunDef] = {
-    foldRight[Set[FunDef]]{ 
+    foldRight[Set[FunDef]]{
       case (LetDef(fd,bd), _) => Set(fd)
       case (_, subs) => subs.flatten.toSet
     }(e)
   }
-  
+
   /** Computes the negation of a boolean formula, with some simplifications. */
   def negate(expr: Expr) : Expr = {
     //require(expr.getType == BooleanType)
@@ -388,13 +388,13 @@ object ExprOps {
   def freshenLocals(expr: Expr) : Expr = {
     def freshenCase(cse: MatchCase) : MatchCase = {
       val allBinders: Set[Identifier] = cse.pattern.binders
-      val subMap: Map[Identifier,Identifier] = 
+      val subMap: Map[Identifier,Identifier] =
         Map(allBinders.map(i => (i, FreshIdentifier(i.name, i.getType, true))).toSeq : _*)
       val subVarMap: Map[Expr,Expr] = subMap.map(kv => Variable(kv._1) -> Variable(kv._2))
-      
+
       MatchCase(
         replacePatternBinders(cse.pattern, subMap),
-        cse.optGuard map { replace(subVarMap, _)}, 
+        cse.optGuard map { replace(subVarMap, _)},
         replace(subVarMap,cse.rhs)
       )
     }
@@ -418,7 +418,7 @@ object ExprOps {
   def depth(e: Expr): Int = {
     foldRight[Int]{ (e, sub) => 1 + (0 +: sub).max }(e)
   }
-  
+
   /** Applies the function to the I/O constraint and simplifies the resulting constraint */
   def applyAsMatches(p : Passes, f : Expr => Expr) = {
     f(p.asConstraint) match {
@@ -494,7 +494,7 @@ object ExprOps {
     val grouped : Map[TypeTree, Seq[Identifier]] = allVars.groupBy(_.getType)
     val subst = grouped.foldLeft(Map.empty[Identifier, Identifier]) { case (subst, (tpe, ids)) =>
       val currentVars = typedIds(tpe)
-      
+
       val freshCount = ids.size - currentVars.size
       val typedVars = if (freshCount > 0) {
         val allIds = currentVars ++ List.range(0, freshCount).map(_ => FreshIdentifier("x", tpe, true))
@@ -538,7 +538,7 @@ object ExprOps {
     import evaluators._
 
     val eval = new DefaultEvaluator(ctx, program)
-    
+
     def rec(e: Expr): Option[Expr] = e match {
       case l: Terminal => None
       case e if isGround(e) => eval.eval(e) match {
@@ -583,7 +583,7 @@ object ExprOps {
       case letTuple @ LetTuple(ids, Tuple(exprs), body) if isDeterministic(body) =>
         var newBody = body
 
-        val (remIds, remExprs) = (ids zip exprs).filter { 
+        val (remIds, remExprs) = (ids zip exprs).filter {
           case (id, value: Terminal) =>
             newBody = replace(Map(Variable(id) -> value), newBody)
             //we replace, so we drop old
@@ -603,7 +603,7 @@ object ExprOps {
               true
             }
         }.unzip
-          
+
         Some(Constructors.letTuple(remIds, tupleWrap(remExprs), newBody))
 
       case l @ LetTuple(ids, tExpr: Terminal, body) if isDeterministic(body) =>
@@ -805,14 +805,14 @@ object ExprOps {
     * case m @ MyCaseClass(t: B, (_, 7)) =>
     * }}}
     * will yield the following condition before simplification (to give some flavour)
-    * 
+    *
     * {{{and(IsInstanceOf(MyCaseClass, i), and(Equals(m, i), InstanceOfClass(B, i.t), equals(i.k.arity, 2), equals(i.k._2, 7))) }}}
-    * 
+    *
     * Pretty-printed, this would be:
     * {{{
     * i.instanceOf[MyCaseClass] && m == i && i.t.instanceOf[B] && i.k.instanceOf[Tuple2] && i.k._2 == 7
     * }}}
-    * 
+    *
     * @see [[purescala.Expressions.Pattern]]
     */
   def conditionForPattern(in: Expr, pattern: Pattern, includeBinders: Boolean = false): Expr = {
@@ -937,9 +937,9 @@ object ExprOps {
   }
 
   /** For each case in the [[purescala.Expressions.MatchExpr MatchExpr]], concatenates the path condition with the newly induced conditions.
-   *  
+   *
    *  Each case holds the conditions on other previous cases as negative.
-   *  
+   *
     * @see [[purescala.ExprOps#conditionForPattern conditionForPattern]]
     * @see [[purescala.ExprOps#mapForPattern mapForPattern]]
     */
@@ -951,7 +951,7 @@ object ExprOps {
       val g = c.optGuard getOrElse BooleanLiteral(true)
       val cond = conditionForPattern(scrut, c.pattern, includeBinders = true)
       val localCond = pcSoFar :+ cond :+ g
-      
+
       // These contain no binders defined in this MatchCase
       val condSafe = conditionForPattern(scrut, c.pattern)
       val gSafe = replaceFromIDs(mapForPattern(scrut, c.pattern),g)
@@ -984,7 +984,7 @@ object ExprOps {
   def passesPathConditions(p : Passes, pathCond: List[Expr]) : Seq[List[Expr]] = {
     matchExprCaseConditions(MatchExpr(p.in, p.cases), pathCond)
   }
-  
+
   /**
    * Returns a pattern from an expression, and a guard if any.
    */
@@ -995,7 +995,7 @@ object ExprOps {
       case Tuple(subs) => TuplePattern(None, subs map rec)
       case l : Literal[_] => LiteralPattern(None, l)
       case Variable(i) => WildcardPattern(Some(i))
-      case other => 
+      case other =>
         val id = FreshIdentifier("other", other.getType, true)
         guard = and(guard, Equals(Variable(id), other))
         WildcardPattern(Some(id))
@@ -1003,9 +1003,9 @@ object ExprOps {
     (rec(e), guard)
   }
 
-  /** 
+  /**
     * Takes a pattern and returns an expression that corresponds to it.
-    * Also returns a sequence of `Identifier -> Expr` pairs which 
+    * Also returns a sequence of `Identifier -> Expr` pairs which
     * represent the bindings for intermediate binders (from outermost to innermost)
     */
   def patternToExpression(p: Pattern, expectedType: TypeTree): (Expr, Seq[(Identifier, Expr)]) = {
@@ -1036,12 +1036,12 @@ object ExprOps {
       }
       case TuplePattern(b, subs) =>
         val TupleType(subTypes) = expectedType
-        val e = Tuple(subs zip subTypes map { 
+        val e = Tuple(subs zip subTypes map {
           case (sub, subType) => rec(sub, subType)
         })
         addBinding(b, e)
         e
-      case CaseClassPattern(b, cct, subs) => 
+      case CaseClassPattern(b, cct, subs) =>
         val e = CaseClass(cct, subs zip cct.fieldsTypes map { case (sub,tp) => rec(sub,tp) })
         addBinding(b, e)
         e
@@ -1070,6 +1070,7 @@ object ExprOps {
   /** Returns simplest value of a given type */
   def simplestValue(tpe: TypeTree) : Expr = tpe match {
     case Int32Type                  => IntLiteral(0)
+    case RealType               	=> FractionalLiteral(0, 1)
     case IntegerType                => InfiniteIntegerLiteral(0)
     case CharType                   => CharLiteral('a')
     case BooleanType                => BooleanLiteral(false)
@@ -1172,7 +1173,7 @@ object ExprOps {
     def pre(e : Expr) = e match {
 
       case LetDef(fd, expr) if fd.hasPrecondition =>
-       val pre = fd.precondition.get 
+       val pre = fd.precondition.get
 
         solver.solveVALID(pre) match {
           case Some(true)  =>
@@ -1188,7 +1189,7 @@ object ExprOps {
 
         e
 
-      case IfExpr(cond, thenn, elze) => 
+      case IfExpr(cond, thenn, elze) =>
         try {
           solver.solveVALID(cond) match {
             case Some(true)  => thenn
@@ -1200,7 +1201,7 @@ object ExprOps {
           }
         } catch {
           // let's give up when the solver crashes
-          case _ : Exception => e 
+          case _ : Exception => e
         }
 
       case _ => e
@@ -1297,7 +1298,7 @@ object ExprOps {
     preTraversal{
       case Choose(_) => return false
       case Hole(_, _) => return false
-      //@EK FIXME: do we need it? 
+      //@EK FIXME: do we need it?
       //case Error(_, _) => return false
       case _ =>
     }(e)
@@ -1310,7 +1311,7 @@ object ExprOps {
   }
 
   /** Substitute (free) variables in an expression with values form a model.
-    * 
+    *
     * Complete with simplest values in case of incomplete model.
     */
   def valuateWithModelIn(expr: Expr, vars: Set[Identifier], model: Model): Expr = {
@@ -1364,7 +1365,7 @@ object ExprOps {
       //btw, I know those are not the most general rules, but they lead to good optimizations :)
       case Plus(UMinus(Plus(e1, e2)), e3) if e1 == e3 => UMinus(e2)
       case Plus(UMinus(Plus(e1, e2)), e3) if e2 == e3 => UMinus(e1)
-      case Minus(e1, e2) if e1 == e2 => InfiniteIntegerLiteral(0) 
+      case Minus(e1, e2) if e1 == e2 => InfiniteIntegerLiteral(0)
       case Minus(Plus(e1, e2), Plus(e3, e4)) if e1 == e4 && e2 == e3 => InfiniteIntegerLiteral(0)
       case Minus(Plus(e1, e2), Plus(Plus(e3, e4), e5)) if e1 == e4 && e2 == e3 => UMinus(e5)
 
@@ -1375,6 +1376,41 @@ object ExprOps {
     fixpoint(simplePostTransform(simplify0))(expr)
   }
 
+  /**
+   * Some helper methods for FractionalLiterals
+   */
+  def normalizeFraction(fl: FractionalLiteral) = {
+    val FractionalLiteral(num, denom) = fl
+    val modNum = if (num < 0) -num else num
+    val modDenom = if (denom < 0) -denom else denom
+    val divisor = modNum.gcd(modDenom)
+    val simpNum = num / divisor
+    val simpDenom = denom / divisor
+    if (simpDenom < 0)
+      FractionalLiteral(-simpNum, -simpDenom)
+    else
+      FractionalLiteral(simpNum, simpDenom)
+  }
+
+  val realzero = FractionalLiteral(0, 1)
+  def floor(fl: FractionalLiteral): FractionalLiteral = {
+    val FractionalLiteral(n, d) = normalizeFraction(fl)
+    if (d == 0) throw new IllegalStateException("denominator zero")
+    if (n == 0) realzero
+    else if (n > 0) {
+      //perform integer division
+      FractionalLiteral(n / d, 1)
+    } else {
+      //here the number is negative
+      if (n % d == 0)
+        FractionalLiteral(n / d, 1)
+      else {
+        //perform integer division and subtract 1
+        FractionalLiteral(n / d - 1, 1)
+      }
+    }
+  }
+
   /** Checks whether a predicate is inductive on a certain identfier.
     *
     * isInductive(foo(a, b), a) where a: List will check whether
@@ -1390,7 +1426,7 @@ object ExprOps {
 
           val isType = IsInstanceOf(Variable(on), cct)
 
-          val recSelectors = cct.fields.collect { 
+          val recSelectors = cct.fields.collect {
             case vd if vd.getType == on.getType => vd.id
           }
 
@@ -1512,11 +1548,11 @@ object ExprOps {
 
             g && e && h
         }
-        
+
       }
 
       import synthesis.Witnesses.Terminating
-      
+
       val res = (t1, t2) match {
         case (Variable(i1), Variable(i2)) =>
           idHomo(i1, i2)
@@ -1531,7 +1567,7 @@ object ExprOps {
 
         case (MatchExpr(s1, cs1), MatchExpr(s2, cs2)) =>
           cs1.size == cs2.size && isHomo(s1, s2) && casesMatch(cs1,cs2)
-          
+
         case (Passes(in1, out1, cs1), Passes(in2, out2, cs2)) =>
           cs1.size == cs2.size && isHomo(in1,in2) && isHomo(out1,out2) && casesMatch(cs1,cs2)
 
@@ -1539,7 +1575,7 @@ object ExprOps {
           // TODO: Check type params
           fdHomo(tfd1.fd, tfd2.fd) &&
           (args1 zip args2).forall{ case (a1, a2) => isHomo(a1, a2) }
-          
+
         case (Terminating(tfd1, args1), Terminating(tfd2, args2)) =>
           // TODO: Check type params
           fdHomo(tfd1.fd, tfd2.fd) &&
@@ -1596,7 +1632,7 @@ object ExprOps {
      *
      * TODO: We ignore type parameters here, we might want to make sure it's
      * valid. What's Leon's semantics w.r.t. erasure?
-     */ 
+     */
     def areExaustive(pss: Seq[(TypeTree, Seq[Pattern])]): Boolean = pss.forall { case (tpe, ps) =>
 
       tpe match {
@@ -1653,24 +1689,24 @@ object ExprOps {
             }
           }
 
-        case BooleanType => 
-          // make sure ps contains either 
+        case BooleanType =>
+          // make sure ps contains either
           // - Wildcard or
-          // - both true and false 
+          // - both true and false
           (ps exists { _.isInstanceOf[WildcardPattern] }) || {
             var found = Set[Boolean]()
-            ps foreach { 
+            ps foreach {
               case LiteralPattern(_, BooleanLiteral(b)) => found += b
               case _ => ()
             }
             (found contains true) && (found contains false)
           }
 
-        case UnitType => 
+        case UnitType =>
           // Anything matches ()
           ps.nonEmpty
 
-        case Int32Type => 
+        case Int32Type =>
           // Can't possibly pattern match against all Ints one by one
           ps exists (_.isInstanceOf[WildcardPattern])
 
@@ -1702,7 +1738,7 @@ object ExprOps {
     * }
     * }}}
     * becomes
-    * {{{ 
+    * {{{
     * def foo(a, b) {
     *   if (..) { foo(b, a) } else { .. }
     * }
@@ -1751,7 +1787,7 @@ object ExprOps {
             case (Some(oe), Some(ie)) =>
               val res = FreshIdentifier("res", fdOuter.returnType, true)
               Some(Lambda(Seq(ValDef(res)), and(
-                application(oe, Seq(Variable(res))), 
+                application(oe, Seq(Variable(res))),
                 application(simplePreTransform(pre)(ie), Seq(Variable(res)))
               )))
           }
@@ -1791,12 +1827,12 @@ object ExprOps {
    * Body manipulation
    * =================
    */
-  
+
   /** Replaces the precondition of an existing [[Expressions.Expr]] with a new one.
-    *  
+    *
     * If no precondition is provided, removes any existing precondition.
     * Else, wraps the expression with a [[Expressions.Require]] clause referring to the new precondition.
-    *  
+    *
     * @param expr The current expression
     * @param pred An optional precondition. Setting it to None removes any precondition.
     * @see [[Expressions.Ensuring]]
@@ -1813,10 +1849,10 @@ object ExprOps {
   }
 
   /** Replaces the postcondition of an existing [[Expressions.Expr]] with a new one.
-    *  
+    *
     * If no postcondition is provided, removes any existing postcondition.
     * Else, wraps the expression with a [[Expressions.Ensuring]] clause referring to the new postcondition.
-    *  
+    *
     * @param expr The current expression
     * @param oie An optional postcondition. Setting it to None removes any postcondition.
     * @see [[Expressions.Ensuring]]
@@ -1830,7 +1866,7 @@ object ExprOps {
   }
 
   /** Adds a body to a specification
-    *  
+    *
     * @param expr The specification expression [[Expressions.Ensuring]] or [[Expressions.Require]]. If none of these, the argument is discarded.
     * @param body An option of [[Expressions.Expr]] possibly containing an expression body.
     * @return The post/pre condition with the body. If no body is provided, returns [[Expressions.NoTree]]
@@ -1845,10 +1881,10 @@ object ExprOps {
   }
 
   /** Extracts the body without its specification
-    * 
+    *
     * [[Expressions.Expr]] trees contain its specifications as part of certain nodes.
     * This function helps extracting only the body part of an expression
-    * 
+    *
     * @return An option type with the resulting expression if not [[Expressions.NoTree]]
     * @see [[Expressions.Ensuring]]
     * @see [[Expressions.Require]]
@@ -1875,7 +1911,7 @@ object ExprOps {
 
   /** Returns a tuple of precondition, the raw body and the postcondition of an expression */
   def breakDownSpecs(e : Expr) = (preconditionOf(e), withoutSpec(e), postconditionOf(e))
-    
+
   def preTraversalWithParent(f: (Expr, Option[Tree]) => Unit, initParent: Option[Tree] = None)(e: Expr): Unit = {
     val rec = preTraversalWithParent(f, Some(e)) _
 
@@ -1952,7 +1988,7 @@ object ExprOps {
     */
   def liftClosures(e: Expr): (Set[FunDef], Expr) = {
     var fds: Map[FunDef, FunDef] = Map()
-    
+
     import synthesis.Witnesses.Terminating
     val res1 = preMap({
       case LetDef(fd, b) =>
@@ -1968,7 +2004,7 @@ object ExprOps {
         } else {
           None
         }
-        
+
       case Terminating(tfd, args) =>
         if (fds contains tfd.fd) {
           Some(Terminating(fds(tfd.fd).typed(tfd.tps), args))
diff --git a/src/main/scala/leon/purescala/Expressions.scala b/src/main/scala/leon/purescala/Expressions.scala
index c807ef816..bfe78acb3 100644
--- a/src/main/scala/leon/purescala/Expressions.scala
+++ b/src/main/scala/leon/purescala/Expressions.scala
@@ -10,7 +10,7 @@ import Extractors._
 import Constructors._
 import ExprOps.replaceFromIDs
 
-/** Expression definitions for Pure Scala. 
+/** Expression definitions for Pure Scala.
   *
   * If you are looking for things such as function or class definitions,
   * please have a look in [[purescala.Definitions]].
@@ -25,7 +25,7 @@ import ExprOps.replaceFromIDs
   * optimization opportunities. Unless you need exact control on the structure
   * of the trees, you should use constructors in [[purescala.Constructors]], that
   * simplify the trees they produce.
-  * 
+  *
   * @define encodingof Encoding of
   * @define noteBitvector (32-bit vector)
   * @define noteReal (Real)
@@ -77,7 +77,7 @@ object Expressions {
   }
 
   /** Precondition of an [[Expressions.Expr]]. Corresponds to the Leon keyword *require*
-    *  
+    *
     * @param pred The precondition formula inside ``require(...)``
     * @param body The body following the ``require(...)``
     */
@@ -90,7 +90,7 @@ object Expressions {
   }
 
   /** Postcondition of an [[Expressions.Expr]]. Corresponds to the Leon keyword *ensuring*
-    * 
+    *
     * @param body The body of the expression. It can contain at most one [[Expressions.Require]] sub-expression.
     * @param pred The predicate to satisfy. It should be a function whose argument's type can handle the type of the body
     */
@@ -114,7 +114,7 @@ object Expressions {
   }
 
   /** Local assertions with customizable error message
-    * 
+    *
     * @param pred The predicate, first argument of `assert(..., ...)`
     * @param error An optional error string to display if the assert fails. Second argument of `assert(..., ...)`
     * @param body The expression following `assert(..., ...)`
@@ -156,7 +156,7 @@ object Expressions {
   }
 
   /** $encodingof `def ... = ...; ...` (local function definition)
-    * 
+    *
     * @param fd The function definition.
     * @param body The body of the expression after the function
     */
@@ -172,7 +172,7 @@ object Expressions {
     * Both [[Expressions.MethodInvocation]] and [[Expressions.This]] get removed by phase [[MethodLifting]].
     * Methods become functions, [[Expressions.This]] becomes first argument,
     * and [[Expressions.MethodInvocation]] becomes [[Expressions.FunctionInvocation]].
-    * 
+    *
     * @param rec The expression evaluating to an object
     * @param cd The class definition typing `rec`
     * @param tfd The typed function definition of the method
@@ -203,7 +203,7 @@ object Expressions {
 
 
   /* Higher-order Functions */
-  
+
   /** $encodingof `callee(args...)`, where [[callee]] is an expression of a function type (not a method) */
   case class Application(callee: Expr, args: Seq[Expr]) extends Expr {
     val getType = callee.getType match {
@@ -251,12 +251,12 @@ object Expressions {
   }
 
   /** $encodingof `... match { ... }`
-    * 
+    *
     * '''cases''' should be nonempty. If you are not sure about this, you should use
     * [[purescala.Constructors#matchExpr purescala's constructor matchExpr]]
-    * 
+    *
     * @param scrutinee Expression to the left of the '''match''' keyword
-    * @param cases A sequence of cases to match `scrutinee` against 
+    * @param cases A sequence of cases to match `scrutinee` against
     */
   case class MatchExpr(scrutinee: Expr, cases: Seq[MatchCase]) extends Expr {
     require(cases.nonEmpty)
@@ -264,7 +264,7 @@ object Expressions {
   }
 
   /** $encodingof `case pattern [if optGuard] => rhs`
-    * 
+    *
     * @param pattern The pattern just to the right of the '''case''' keyword
     * @param optGuard An optional if-condition just to the left of the `=>`
     * @param rhs The expression to the right of `=>`
@@ -275,7 +275,7 @@ object Expressions {
   }
 
   /** $encodingof a pattern after a '''case''' keyword.
-    * 
+    *
     * @see [[Expressions.MatchCase]]
     */
   sealed abstract class Pattern extends Tree {
@@ -301,7 +301,7 @@ object Expressions {
   /** Pattern encoding `case _ => `, or `case binder => ` if identifier [[binder]] is present */
   case class WildcardPattern(binder: Option[Identifier]) extends Pattern { // c @ _
     val subPatterns = Seq()
-  } 
+  }
   /** Pattern encoding `case binder @ ct(subPatterns...) =>`
     *
     * If [[binder]] is empty, consider a wildcard `_` in its place.
@@ -319,7 +319,7 @@ object Expressions {
     * If [[binder]] is empty, consider a wildcard `_` in its place.
     */
   case class LiteralPattern[+T](binder: Option[Identifier], lit : Literal[T]) extends Pattern {
-    val subPatterns = Seq()    
+    val subPatterns = Seq()
   }
 
   /** A custom pattern defined through an object's `unapply` function */
@@ -362,11 +362,11 @@ object Expressions {
 
   /** Symbolic I/O examples as a match/case.
     * $encodingof `out == (in match { cases; case _ => out })`
-    *  
+    *
     * [[cases]] should be nonempty. If you are not sure about this, you should use
     * [[purescala.Constructors#passes purescala's constructor passes]]
-    * 
-    * @param in 
+    *
+    * @param in
     * @param out
     * @param cases
     */
@@ -402,8 +402,9 @@ object Expressions {
   case class InfiniteIntegerLiteral(value: BigInt) extends Literal[BigInt] {
     val getType = IntegerType
   }
-  /** $encodingof a real number literal */
-  case class RealLiteral(value: BigDecimal) extends Literal[BigDecimal] {
+  /** $encodingof a fraction literal */
+  case class FractionalLiteral(numerator: BigInt, denominator: BigInt) extends Literal[(BigInt, BigInt)] {
+    val value = (numerator, denominator)
     val getType = RealType
   }
   /** $encodingof a boolean literal '''true''' or '''false''' */
@@ -500,7 +501,7 @@ object Expressions {
   }
 
   /** $encodingof `... || ...`
-    *  
+    *
     * [[exprs]] must contain at least two elements; if you are not sure about this,
     * you should use [[purescala.Constructors#or purescala's constructor or]] or
     * [[purescala.Constructors#orJoin purescala's constructor orJoin]]
@@ -574,7 +575,7 @@ object Expressions {
     }
   }
   /** $encodingof `... /  ...`
-    * 
+    *
     * Division and Remainder follows Java/Scala semantics. Division corresponds
     * to / operator on BigInt and Remainder corresponds to %. Note that in
     * Java/Scala % is called remainder and the "mod" operator (Modulo in Leon) is also
@@ -591,7 +592,7 @@ object Expressions {
     }
   }
   /** $encodingof `... %  ...` (can return negative numbers)
-    *  
+    *
     * @see [[Expressions.Division]]
     */
   case class Remainder(lhs: Expr, rhs: Expr) extends Expr {
@@ -601,7 +602,7 @@ object Expressions {
     }
   }
   /** $encodingof `... mod  ...` (cannot return negative numbers)
-    *  
+    *
     * @see [[Expressions.Division]]
     */
   case class Modulo(lhs: Expr, rhs: Expr) extends Expr {
@@ -615,11 +616,11 @@ object Expressions {
     val getType = BooleanType
   }
   /** $encodingof `... > ...`*/
-  case class GreaterThan(lhs: Expr, rhs: Expr) extends Expr { 
+  case class GreaterThan(lhs: Expr, rhs: Expr) extends Expr {
     val getType = BooleanType
   }
   /** $encodingof `... <= ...`*/
-  case class LessEquals(lhs: Expr, rhs: Expr) extends Expr { 
+  case class LessEquals(lhs: Expr, rhs: Expr) extends Expr {
     val getType = BooleanType
   }
   /** $encodingof `... >= ...`*/
@@ -635,32 +636,32 @@ object Expressions {
     val getType = Int32Type
   }
   /** $encodingof `... - ...` $noteBitvector*/
-  case class BVMinus(lhs: Expr, rhs: Expr) extends Expr { 
+  case class BVMinus(lhs: Expr, rhs: Expr) extends Expr {
     require(lhs.getType == Int32Type && rhs.getType == Int32Type)
     val getType = Int32Type
   }
   /** $encodingof `- ...` $noteBitvector*/
-  case class BVUMinus(expr: Expr) extends Expr { 
+  case class BVUMinus(expr: Expr) extends Expr {
     require(expr.getType == Int32Type)
     val getType = Int32Type
   }
   /** $encodingof `... * ...` $noteBitvector*/
-  case class BVTimes(lhs: Expr, rhs: Expr) extends Expr { 
+  case class BVTimes(lhs: Expr, rhs: Expr) extends Expr {
     require(lhs.getType == Int32Type && rhs.getType == Int32Type)
     val getType = Int32Type
   }
   /** $encodingof `... / ...` $noteBitvector*/
-  case class BVDivision(lhs: Expr, rhs: Expr) extends Expr { 
+  case class BVDivision(lhs: Expr, rhs: Expr) extends Expr {
     require(lhs.getType == Int32Type && rhs.getType == Int32Type)
     val getType = Int32Type
   }
   /** $encodingof `... % ...` $noteBitvector*/
-  case class BVRemainder(lhs: Expr, rhs: Expr) extends Expr { 
+  case class BVRemainder(lhs: Expr, rhs: Expr) extends Expr {
     require(lhs.getType == Int32Type && rhs.getType == Int32Type)
     val getType = Int32Type
   }
   /** $encodingof `! ...` $noteBitvector */
-  case class BVNot(expr: Expr) extends Expr { 
+  case class BVNot(expr: Expr) extends Expr {
     val getType = Int32Type
   }
   /** $encodingof `... & ...` $noteBitvector */
@@ -696,22 +697,22 @@ object Expressions {
     val getType = RealType
   }
   /** $encodingof `... - ...` $noteReal */
-  case class RealMinus(lhs: Expr, rhs: Expr) extends Expr { 
+  case class RealMinus(lhs: Expr, rhs: Expr) extends Expr {
     require(lhs.getType == RealType && rhs.getType == RealType)
     val getType = RealType
   }
   /** $encodingof `- ...` $noteReal */
-  case class RealUMinus(expr: Expr) extends Expr { 
+  case class RealUMinus(expr: Expr) extends Expr {
     require(expr.getType == RealType)
     val getType = RealType
   }
   /** $encodingof `... * ...` $noteReal */
-  case class RealTimes(lhs: Expr, rhs: Expr) extends Expr { 
+  case class RealTimes(lhs: Expr, rhs: Expr) extends Expr {
     require(lhs.getType == RealType && rhs.getType == RealType)
     val getType = RealType
   }
   /** $encodingof `... / ...` $noteReal */
-  case class RealDivision(lhs: Expr, rhs: Expr) extends Expr { 
+  case class RealDivision(lhs: Expr, rhs: Expr) extends Expr {
     require(lhs.getType == RealType && rhs.getType == RealType)
     val getType = RealType
   }
@@ -720,11 +721,11 @@ object Expressions {
   /* Tuple operations */
 
   /** $encodingof `(..., ....)` (tuple)
-    * 
+    *
     * [[exprs]] should always contain at least 2 elements.
     * If you are not sure about this requirement, you should use
     * [[purescala.Constructors#tupleWrap purescala's constructor tupleWrap]]
-    * 
+    *
     * @param exprs The expressions in the tuple
     */
   case class Tuple (exprs: Seq[Expr]) extends Expr {
@@ -733,7 +734,7 @@ object Expressions {
   }
 
   /** $encodingof `(tuple)._i`
-    * 
+    *
     * Index is 1-based, first element of tuple is 1.
     * If you are not sure that [[tuple]] is indeed of a TupleType,
     * you should use [[purescala.Constructors$.tupleSelect(t:leon\.purescala\.Expressions\.Expr,index:Int,isTuple:Boolean):leon\.purescala\.Expressions\.Expr* purescala's constructor tupleSelect]]
@@ -839,7 +840,7 @@ object Expressions {
   }
 
   /** $encodingof Array(elems...) with predetermined elements
-    * @param elems The map from the position to the elements.  
+    * @param elems The map from the position to the elements.
     * @param defaultLength An optional pair where the first element is the default value
     *                      and the second is the size of the array. Set this for big arrays
     *                      with a default value (as genereted with `Array.fill` in Scala).
diff --git a/src/main/scala/leon/purescala/PrettyPrinter.scala b/src/main/scala/leon/purescala/PrettyPrinter.scala
index 57618655f..2fccfbdaf 100644
--- a/src/main/scala/leon/purescala/PrettyPrinter.scala
+++ b/src/main/scala/leon/purescala/PrettyPrinter.scala
@@ -160,7 +160,9 @@ class PrettyPrinter(opts: PrinterOptions,
       case Equals(l,r)          => optP { p"$l == $r" }
       case IntLiteral(v)        => p"$v"
       case InfiniteIntegerLiteral(v) => p"$v"
-      case RealLiteral(d)       => p"$d"
+      case FractionalLiteral(n, d) =>
+        if (d == 1) p"$n"
+        else p"$n/$d"
       case CharLiteral(v)       => p"$v"
       case BooleanLiteral(v)    => p"$v"
       case UnitLiteral()        => p"()"
@@ -286,7 +288,7 @@ class PrettyPrinter(opts: PrinterOptions,
               val orderedElements = es.toSeq.sortWith((e1, e2) => e1._1 < e2._1).map(el => el._2)
               p"Array($orderedElements)"
             } else if(length < 10) {
-              val elems = (0 until length).map(i => 
+              val elems = (0 until length).map(i =>
                 es.find(el => el._1 == i).map(el => el._2).getOrElse(d.get)
               )
               p"Array($elems)"
@@ -418,7 +420,7 @@ class PrettyPrinter(opts: PrinterOptions,
             |${nary(defs,"\n\n")}
             |"""
 
-      case Import(path, isWild) => 
+      case Import(path, isWild) =>
         if (isWild) {
           p"import ${nary(path,".")}._"
         } else {
diff --git a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
index 275013666..fd533d2af 100644
--- a/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
+++ b/src/main/scala/leon/solvers/smtlib/SMTLIBSolver.scala
@@ -317,7 +317,7 @@ abstract class SMTLIBSolver(val context: LeonContext, val program: Program)
 
       case InfiniteIntegerLiteral(i) => if (i >= 0) Ints.NumeralLit(i) else Ints.Neg(Ints.NumeralLit(-i))
       case IntLiteral(i) => FixedSizeBitVectors.BitVectorLit(Hexadecimal.fromInt(i))
-      case RealLiteral(d) => if (d >= 0) Reals.DecimalLit(d) else Reals.Neg(Reals.DecimalLit(-d))
+      case FractionalLiteral(n, d) => Reals.Div(Reals.NumeralLit(n), Reals.NumeralLit(d))
       case CharLiteral(c) => FixedSizeBitVectors.BitVectorLit(Hexadecimal.fromInt(c.toInt))
       case BooleanLiteral(v) => Core.BoolConst(v)
       case Let(b,d,e) =>
@@ -592,10 +592,14 @@ abstract class SMTLIBSolver(val context: LeonContext, val program: Program)
       InfiniteIntegerLiteral(n)
 
     case (SDecimal(d), RealType) =>
-      RealLiteral(d)
+      // converting bigdecimal to a fraction
+      val scale = d.scale
+      val num = BigInt(d.bigDecimal.scaleByPowerOfTen(scale).toBigInteger())
+      val denom = BigInt(new java.math.BigDecimal(1).scaleByPowerOfTen(-scale).toBigInteger())
+      FractionalLiteral(num, denom)
 
     case (SNumeral(n), RealType) =>
-      RealLiteral(BigDecimal(n))
+      FractionalLiteral(n, 1)
 
     case (Core.True(), BooleanType)  => BooleanLiteral(true)
     case (Core.False(), BooleanType)  => BooleanLiteral(false)
diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
index 44df7eb67..9c6979ca1 100644
--- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
+++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala
@@ -80,7 +80,7 @@ trait AbstractZ3Solver extends Solver {
       z3.mkFreshFuncDecl(gv.tp.id.uniqueName+"#"+gv.id+"!val", Seq(), typeToSort(gv.tp))
     }
   }
-  
+
   // ADT Manager
   protected val adtManager = new ADTManager(context)
 
@@ -272,7 +272,7 @@ trait AbstractZ3Solver extends Solver {
     }
 
     def rec(ex: Expr): Z3AST = ex match {
-      
+
       // TODO: Leave that as a specialization?
       case LetTuple(ids, e, b) => {
         z3Vars = z3Vars ++ ids.zipWithIndex.map { case (id, ix) =>
@@ -283,7 +283,7 @@ trait AbstractZ3Solver extends Solver {
         z3Vars = z3Vars -- ids
         rb
       }
-      
+
       case p @ Passes(_, _, _) =>
         rec(p.asConstraint)
 
@@ -326,7 +326,7 @@ trait AbstractZ3Solver extends Solver {
       case Not(e) => z3.mkNot(rec(e))
       case IntLiteral(v) => z3.mkInt(v, typeToSort(Int32Type))
       case InfiniteIntegerLiteral(v) => z3.mkNumeral(v.toString, typeToSort(IntegerType))
-      case RealLiteral(v) => z3.mkNumeral(v.toString, typeToSort(RealType))
+      case FractionalLiteral(n, d) => z3.mkNumeral(s"$n / $d", typeToSort(RealType))
       case CharLiteral(c) => z3.mkInt(c, typeToSort(CharType))
       case BooleanLiteral(v) => if (v) z3.mkTrue() else z3.mkFalse()
       case Equals(l, r) => z3.mkEq(rec( l ), rec( r ) )
@@ -381,6 +381,7 @@ trait AbstractZ3Solver extends Solver {
         case RealType => z3.mkLE(rec(l), rec(r))
         case Int32Type => z3.mkBVSle(rec(l), rec(r))
         case CharType => z3.mkBVSle(rec(l), rec(r))
+        //case _ => throw new IllegalStateException(s"l: $l, Left type: ${l.getType} Expr: $ex")
       }
       case GreaterThan(l, r) => l.getType match {
         case IntegerType => z3.mkGT(rec(l), rec(r))
@@ -583,9 +584,7 @@ trait AbstractZ3Solver extends Solver {
             }
           }
         }
-        case Z3NumeralRealAST(num: BigInt, den: BigInt) => {
-          RealLiteral(BigDecimal(num) / BigDecimal(den))
-        }
+        case Z3NumeralRealAST(n: BigInt, d: BigInt) => FractionalLiteral(n, d)
         case Z3AppAST(decl, args) =>
           val argsSize = args.size
           if(argsSize == 0 && (variables containsB t)) {
diff --git a/src/main/scala/leon/transformations/DepthInstPhase.scala b/src/main/scala/leon/transformations/DepthInstPhase.scala
new file mode 100644
index 000000000..a505929d0
--- /dev/null
+++ b/src/main/scala/leon/transformations/DepthInstPhase.scala
@@ -0,0 +1,104 @@
+package leon
+package transformations
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Extractors._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Types._
+import leon.utils._
+import invariant.util.Util._
+
+object DepthCostModel {
+  val typedMaxFun = TypedFunDef(InstUtil.maxFun, Seq())
+
+  def costOf(e: Expr): Int =
+    e match {
+      case FunctionInvocation(fd, args) => 1
+      case t: Terminal => 0
+      case _ => 1
+    }
+
+  def costOfExpr(e: Expr) = InfiniteIntegerLiteral(costOf(e))
+}
+
+class DepthInstrumenter(p: Program, si: SerialInstrumenter) extends Instrumenter(p, si) {
+  import DepthCostModel._
+
+  def inst = Depth
+
+  def functionsToInstrument(): Map[FunDef, List[Instrumentation]] = {
+    //find all functions transitively called from rootFuncs (here ignore functions called via pre/post conditions)
+    val instFunSet = getRootFuncs().foldLeft(Set[FunDef]())((acc, fd) => acc ++ cg.transitiveCallees(fd))
+    instFunSet.map(x => (x, List(Depth))).toMap
+  }
+
+  def additionalfunctionsToAdd(): Seq[FunDef] = Seq()// - max functions are inlined, so they need not be added
+
+  def instrumentMatchCase(me: MatchExpr, mc: MatchCase,
+    caseExprCost: Expr, scrutineeCost: Expr): Expr = {
+    val costMatch = costOfExpr(me)
+    def totalCostOfMatchPatterns(me: MatchExpr, mc: MatchCase): BigInt = 0
+    combineDepthIds(costMatch, List(caseExprCost, scrutineeCost))
+  }
+
+  def instrument(e: Expr, subInsts: Seq[Expr], funInvResVar: Option[Variable] = None)(implicit fd: FunDef, letIdMap: Map[Identifier, Identifier]): Expr = {
+    val costOfParent = costOfExpr(e)
+    e match {
+      case Variable(id) if letIdMap.contains(id) =>
+        // add the cost of instrumentation here
+        Plus(costOfParent, si.selectInst(fd)(letIdMap(id).toVariable, inst))
+
+      case t: Terminal => costOfParent
+      case FunctionInvocation(tfd, args) =>
+        val depthvar = subInsts.last
+        val remSubInsts = subInsts.slice(0, subInsts.length - 1)
+        val costofOp = {
+          costOfParent match {
+            case InfiniteIntegerLiteral(x) if (x == 0) => depthvar
+            case _ => Plus(costOfParent, depthvar)
+          }
+        }
+        combineDepthIds(costofOp, remSubInsts)
+      case e : Let =>
+        //in this case, ignore the depth of the value, it will included if the bounded variable is
+        // used in the body
+        combineDepthIds(costOfParent, subInsts.tail)
+      case _ =>
+        val costofOp = costOfParent
+        combineDepthIds(costofOp, subInsts)
+    }
+  }
+
+  def instrumentIfThenElseExpr(e: IfExpr, condInst: Option[Expr],
+    thenInst: Option[Expr], elzeInst: Option[Expr]): (Expr, Expr) = {
+
+    val cinst = condInst.toList
+    val tinst = thenInst.toList
+    val einst = elzeInst.toList
+
+    (combineDepthIds(zero, cinst ++ tinst), combineDepthIds(zero, cinst ++ einst))
+  }
+
+  def combineDepthIds(costofOp: Expr, subeInsts: Seq[Expr]): Expr = {
+    if (subeInsts.size == 0) costofOp
+    else if (subeInsts.size == 1) Plus(costofOp, subeInsts(0))
+    else {
+      //optimization: remove duplicates from 'subeInsts' as 'max' is an idempotent operation
+      val head +: tail = subeInsts.distinct
+      val summand = tail.foldLeft(head: Expr)((acc, id) => {
+        (acc, id) match {
+          case (InfiniteIntegerLiteral(x), _) if (x == 0) => id
+          case (_, InfiniteIntegerLiteral(x)) if (x == 0) => acc
+          case _ =>
+            FunctionInvocation(typedMaxFun, Seq(acc, id))
+        }
+      })
+      costofOp match {
+        case InfiniteIntegerLiteral(x) if (x == 0) => summand
+        case _ => Plus(costofOp, summand)
+      }
+    }
+  }
+}
diff --git a/src/main/scala/leon/transformations/InstProgSimplifier.scala b/src/main/scala/leon/transformations/InstProgSimplifier.scala
new file mode 100644
index 000000000..037a44435
--- /dev/null
+++ b/src/main/scala/leon/transformations/InstProgSimplifier.scala
@@ -0,0 +1,87 @@
+package leon
+package transformations
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Extractors._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Types._
+import leon.purescala.ScalaPrinter
+import leon.utils._
+import invariant.util.Util._
+import invariant.util.ExpressionTransformer._
+import invariant.structure.FunctionUtils._
+import invariant.util.LetTupleSimplification._
+
+/**
+ * A simplifier phase that eliminates tuples that are not needed
+ * from function bodies, and also performs other simplifications.
+ * Note: performing simplifications during instrumentation
+ * will affect the validity of the information stored in function info.
+ */
+object ProgramSimplifier {
+  val debugSimplify = false
+
+  def mapProgram(funMap: Map[FunDef, FunDef]): Map[FunDef, FunDef] = {
+
+    def mapExpr(ine: Expr): Expr = {
+      val replaced = simplePostTransform((e: Expr) => e match {
+        case FunctionInvocation(tfd, args) if funMap.contains(tfd.fd) =>
+          FunctionInvocation(TypedFunDef(funMap(tfd.fd), tfd.tps), args)
+        case _ => e
+      })(ine)
+
+      // One might want to add the maximum function to the program in the stack
+      // and depth instrumentation phases if inlineMax is removed from here
+      val allSimplifications =
+        simplifyTuples _ andThen
+          simplifyMax _ andThen
+          simplifyLetsAndLetsWithTuples _ andThen
+          simplifyAdditionsAndMax _ andThen
+          inlineMax _
+
+      allSimplifications(replaced)
+    }
+
+    for ((from, to) <- funMap) {
+      to.fullBody = mapExpr(from.fullBody)
+      //copy annotations
+      from.flags.foreach(to.addFlag(_))
+    }
+    funMap
+  }
+
+  def createNewFunDefs(program: Program): Map[FunDef, FunDef] = {
+    val allFuncs = functionsWOFields(program.definedFunctions)
+
+    allFuncs.foldLeft(Map[FunDef, FunDef]()) {
+      case (accMap, fd) if fd.isTheoryOperation =>
+        accMap + (fd -> fd)
+      case (accMap, fd) => {
+        //here we need not augment the return types
+        val freshId = FreshIdentifier(fd.id.name, fd.returnType)
+        val newfd = new FunDef(freshId, fd.tparams, fd.returnType, fd.params)
+        accMap.updated(fd, newfd)
+      }
+    }
+  }
+
+  def createNewProg(mappedFuncs: Map[FunDef, FunDef], prog: Program): Program = {
+    val newprog = copyProgram(prog, (defs: Seq[Definition]) => defs.map {
+      case fd: FunDef if mappedFuncs.contains(fd) =>
+        mappedFuncs(fd)
+      case d => d
+    })
+
+    if (debugSimplify)
+      println("After Simplifications: \n" + ScalaPrinter.apply(newprog))
+    newprog
+  }
+
+  def apply(program: Program): Program = {
+    val newFuncs = createNewFunDefs(program)
+    val mappedFuncs = mapProgram(newFuncs)
+    createNewProg(mappedFuncs, program)
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/transformations/InstrumentationUtil.scala b/src/main/scala/leon/transformations/InstrumentationUtil.scala
new file mode 100644
index 000000000..fa35cc3f5
--- /dev/null
+++ b/src/main/scala/leon/transformations/InstrumentationUtil.scala
@@ -0,0 +1,110 @@
+package leon
+package transformations
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import leon.utils.Library
+
+sealed abstract class Instrumentation {
+  val getType: TypeTree
+  val name: String
+  def isInstVariable(e: Expr): Boolean = {
+    e match {
+      case FunctionInvocation(TypedFunDef(fd, _), _) if (fd.id.name == name && fd.annotations("library")) =>
+        true
+      case _ => false
+    }
+  }
+  override def toString = name
+}
+
+object Time extends Instrumentation {
+  override val getType = IntegerType
+  override val name = "time"
+}
+object Depth extends Instrumentation {
+  override val getType = IntegerType
+  override val name = "depth"
+}
+object Rec extends Instrumentation {
+  override val getType = IntegerType
+  override val name = "rec"
+}
+
+/**
+ * time per recursive step.
+ */
+object TPR extends Instrumentation {
+  override val getType = IntegerType
+  override val name = "tpr"
+}
+
+object Stack extends Instrumentation {
+  override val getType = IntegerType
+  override val name = "stack"
+}
+//add more instrumentation variables
+
+object InstUtil {
+
+  val maxFun = {
+    val xid = FreshIdentifier("x", IntegerType)
+    val yid = FreshIdentifier("y", IntegerType)
+    val varx = xid.toVariable
+    val vary = yid.toVariable
+    val args = Seq(xid, yid)
+    val maxType = FunctionType(Seq(IntegerType, IntegerType), IntegerType)
+    val mfd = new FunDef(FreshIdentifier("max", maxType, false), Seq(), IntegerType,
+      args.map((arg) => ValDef(arg, Some(arg.getType))))
+
+    val cond = GreaterEquals(varx, vary)
+    mfd.body = Some(IfExpr(cond, varx, vary))
+    mfd.addFlag(Annotation("theoryop", Seq()))
+    mfd
+  }
+
+  def userFunctionName(fd: FunDef) = fd.id.name.split("-")(0)
+
+  def getInstMap(fd: FunDef) = {
+    val resvar = invariant.util.Util.getResId(fd).get.toVariable // note: every instrumented function has a postcondition
+    val insts = fd.id.name.split("-").tail // split the name of the function w.r.t '-'
+    (insts.zipWithIndex).foldLeft(Map[Expr, String]()) {
+      case (acc, (instName, i)) =>
+        acc + (TupleSelect(resvar, i + 2) -> instName)
+    }
+  }
+
+  def getInstExpr(fd: FunDef, inst: Instrumentation) = {
+    val resvar = invariant.util.Util.getResId(fd).get.toVariable // note: every instrumented function has a postcondition
+    val insts = fd.id.name.split("-").tail // split the name of the function w.r.t '-'
+    val index = insts.indexOf(inst.name)
+    if (index >= 0)
+      Some(TupleSelect(resvar, index + 2))
+    else None
+  }
+
+  def getInstVariableMap(fd: FunDef) = {
+    getInstMap(fd).map {
+      case (ts, instName) =>
+        (ts -> Variable(FreshIdentifier(instName, IntegerType)))
+    }
+  }
+
+  def isInstrumented(fd: FunDef, instType: Instrumentation) = {
+    fd.id.name.split("-").contains(instType.toString)
+  }
+
+  def resultExprForInstVariable(fd: FunDef, instType: Instrumentation) = {
+    getInstVariableMap(fd).collectFirst {
+      case (k, Variable(id)) if (id.name == instType.toString) => k
+    }
+  }
+
+  def replaceInstruVars(e: Expr, fd: FunDef): Expr = {
+    replace(getInstVariableMap(fd), e)
+  }
+}
diff --git a/src/main/scala/leon/transformations/IntToRealProgram.scala b/src/main/scala/leon/transformations/IntToRealProgram.scala
new file mode 100644
index 000000000..d24b4c87a
--- /dev/null
+++ b/src/main/scala/leon/transformations/IntToRealProgram.scala
@@ -0,0 +1,234 @@
+package leon
+package transformations
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+import leon.purescala.ScalaPrinter
+
+import invariant.factories._
+import invariant.util.Util._
+import invariant.structure._
+
+abstract class ProgramTypeTransformer {
+  protected var defmap = Map[ClassDef, ClassDef]()
+  protected var idmap = Map[Identifier, Identifier]()
+  protected var newFundefs = Map[FunDef, FunDef]()
+
+  def mapField(cdef: CaseClassDef, fieldId: Identifier): Identifier = {
+    (cdef.fieldsIds.collectFirst {
+      case fid @ _ if (fid.name == fieldId.name) => fid
+    }).get
+  }
+
+  def mapClass[T <: ClassDef](cdef: T): T = {
+    if (defmap.contains(cdef)) {
+      defmap(cdef).asInstanceOf[T]
+    } else {
+      cdef match {
+        case ccdef: CaseClassDef =>
+          val newparent = if (ccdef.hasParent) {
+            val absType = ccdef.parent.get
+            Some(AbstractClassType(mapClass(absType.classDef), absType.tps))
+          } else None
+          val newclassDef = ccdef.copy(id = FreshIdentifier(ccdef.id.name, ccdef.id.getType, true), parent = newparent)
+
+          //important: register a child if a parent was newly created.
+          if (newparent.isDefined)
+            newparent.get.classDef.registerChild(newclassDef)
+
+          defmap += (ccdef -> newclassDef)
+          newclassDef.setFields(ccdef.fields.map(mapDecl))
+          newclassDef.asInstanceOf[T]
+
+        case acdef: AbstractClassDef =>
+          val newparent = if (acdef.hasParent) {
+            val absType = acdef.parent.get
+            Some(AbstractClassType(mapClass(absType.classDef), absType.tps))
+          } else None
+          val newClassDef = acdef.copy(id = FreshIdentifier(acdef.id.name, acdef.id.getType, true), parent = newparent)
+          defmap += (acdef -> newClassDef)
+          newClassDef.asInstanceOf[T]
+      }
+    }
+  }
+
+  def mapId(id: Identifier): Identifier = {
+    val newtype = mapType(id.getType)
+    val newId = idmap.getOrElse(id, {
+      //important need to preserve distinction between template variables and ordinary variables
+      val freshId = if (TemplateIdFactory.IsTemplateIdentifier(id)) TemplateIdFactory.copyIdentifier(id)
+      else FreshIdentifier(id.name, newtype, true)
+      idmap += (id -> freshId)
+      freshId
+    })
+    newId
+  }
+
+  def mapDecl(decl: ValDef): ValDef = {
+    val newtpe = mapType(decl.getType)
+    new ValDef(mapId(decl.id), Some(newtpe))
+  }
+
+  def mapType(tpe: TypeTree): TypeTree = {
+    tpe match {
+      case t @ RealType => mapNumericType(t)
+      case t @ IntegerType => mapNumericType(t)
+      case AbstractClassType(adef, tps) => AbstractClassType(mapClass(adef), tps)
+      case CaseClassType(cdef, tps) => CaseClassType(mapClass(cdef), tps)
+      case TupleType(bases) => TupleType(bases.map(mapType))
+      case _ => tpe
+    }
+  }
+
+  def mapNumericType(tpe: TypeTree): TypeTree
+
+  def mapLiteral(lit: Literal[_]): Literal[_]
+
+  def transform(program: Program): Program = {
+    //create a new fundef for each function in the program
+    //Unlike functions, classes are created lazily as required.
+    newFundefs = program.definedFunctions.map((fd) => {
+      val newFunType = FunctionType(fd.tparams.map((currParam) => currParam.tp), fd.returnType)
+      val newfd = new FunDef(FreshIdentifier(fd.id.name, newFunType, true), fd.tparams,
+          mapType(fd.returnType), fd.params.map(mapDecl))
+      (fd, newfd)
+    }).toMap
+
+    /**
+     * Here, we assume that tuple-select and case-class-select have been reduced
+     */
+    def transformExpr(e: Expr): Expr = e match {
+      case l: Literal[_] => mapLiteral(l)
+      case v @ Variable(inId) => mapId(inId).toVariable
+      case FunctionInvocation(TypedFunDef(intfd, tps), args) => FunctionInvocation(TypedFunDef(newFundefs(intfd), tps), args.map(transformExpr))
+      case CaseClass(CaseClassType(classDef, tps), args) => CaseClass(CaseClassType(mapClass(classDef), tps), args.map(transformExpr))
+      case IsInstanceOf(expr, CaseClassType(classDef, tps)) => IsInstanceOf(transformExpr(expr), CaseClassType(mapClass(classDef), tps))
+      case CaseClassSelector(CaseClassType(classDef, tps), expr, fieldId) => {
+        val newtype = CaseClassType(mapClass(classDef), tps)
+        CaseClassSelector(newtype, transformExpr(expr), mapField(newtype.classDef, fieldId))
+      }
+      //need to handle 'let' and 'letTuple' specially
+      case Let(binder, value, body) => Let(mapId(binder), transformExpr(value), transformExpr(body))
+      case t: Terminal => t
+      /*case UnaryOperator(arg, op) => op(transformExpr(arg))
+      case BinaryOperator(arg1, arg2, op) => op(transformExpr(arg1), transformExpr(arg2))*/
+      case Operator(args, op) => op(args.map(transformExpr))
+    }
+
+    //create a body, pre, post for each newfundef
+    newFundefs.foreach((entry) => {
+      val (fd, newfd) = entry
+
+      //add a new precondition
+      newfd.precondition =
+        if (fd.precondition.isDefined)
+          Some(transformExpr(fd.precondition.get))
+        else None
+
+      //add a new body
+      newfd.body = if (fd.hasBody) {
+        //replace variables by constants if possible
+        val simpBody = matchToIfThenElse(fd.body.get)
+        Some(transformExpr(simpBody))
+      } else Some(NoTree(fd.returnType))
+
+      // FIXME
+      //add a new postcondition
+      newfd.fullBody = if (fd.postcondition.isDefined && newfd.body.isDefined) {
+        val Lambda(Seq(ValDef(resid, _)), pexpr) = fd.postcondition.get
+        val tempRes = mapId(resid).toVariable
+        Ensuring(newfd.body.get, Lambda(Seq(ValDef(tempRes.id, Some(tempRes.getType))), transformExpr(pexpr)))
+        // Some(mapId(resid), transformExpr(pexpr))
+      } else NoTree(fd.returnType)
+
+      fd.flags.foreach(newfd.addFlag(_))
+    })
+
+    val newprog = copyProgram(program, (defs: Seq[Definition]) => defs.map {
+      case fd: FunDef => newFundefs(fd)
+      case cd: ClassDef => mapClass(cd)
+      case d @ _ => throw new IllegalStateException("Unknown Definition: " + d)
+    })
+    newprog
+  }
+}
+
+class IntToRealProgram extends ProgramTypeTransformer {
+
+  private var realToIntId = Map[Identifier, Identifier]()
+
+  def mapNumericType(tpe: TypeTree) = {
+    require(isNumericType(tpe))
+    tpe match {
+      case IntegerType => RealType
+      case _ => tpe
+    }
+  }
+
+  def mapLiteral(lit: Literal[_]): Literal[_] = lit match {
+    case IntLiteral(v) => FractionalLiteral(v, 1)
+    case _ => lit
+  }
+
+  def apply(program: Program): Program = {
+
+    val newprog = transform(program)
+    //reverse the map
+    realToIntId = idmap.map(entry => (entry._2 -> entry._1))
+    //println("After Real Program Conversion: \n" + ScalaPrinter.apply(newprog))
+    //print all the templates
+    /*newprog.definedFunctions.foreach((fd) => {
+      val funinfo = FunctionInfoFactory.getFunctionInfo(fd)
+      if (funinfo.isDefined && funinfo.get.hasTemplate)
+        println("Function: " + fd.id + " template --> " + funinfo.get.getTemplate)
+    })*/
+    newprog
+  }
+
+  /**
+   * Assuming that the model maps only variables
+   */
+  def unmapModel(model: Map[Identifier, Expr]): Map[Identifier, Expr] = {
+    model.map((pair) => {
+      val (key, value) = if (realToIntId.contains(pair._1)) {
+        (realToIntId(pair._1), pair._2)
+      } else pair
+      (key -> value)
+    })
+  }
+}
+
+class RealToIntProgram extends ProgramTypeTransformer {
+  val debugIntToReal = false
+  val bone = BigInt(1)
+
+  def mapNumericType(tpe: TypeTree) = {
+    require(isNumericType(tpe))
+    tpe match {
+      case RealType => IntegerType
+      case _ => tpe
+    }
+  }
+
+  def mapLiteral(lit: Literal[_]): Literal[_] = lit match {
+    case FractionalLiteral(v, `bone`) => InfiniteIntegerLiteral(v)
+    case FractionalLiteral(_, _) => throw new IllegalStateException("Cannot convert real to integer: " + lit)
+    case _ => lit
+  }
+
+  def apply(program: Program): Program = {
+
+    val newprog = transform(program)
+
+    if (debugIntToReal)
+      println("Program to Verify: \n" + ScalaPrinter.apply(newprog))
+
+    newprog
+  }
+
+  def mappedFun(fd: FunDef): FunDef = newFundefs(fd)
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/transformations/NonRecursiveTimePhase.scala b/src/main/scala/leon/transformations/NonRecursiveTimePhase.scala
new file mode 100644
index 000000000..f234c8afe
--- /dev/null
+++ b/src/main/scala/leon/transformations/NonRecursiveTimePhase.scala
@@ -0,0 +1,120 @@
+package leon
+package transformations
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Extractors._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Types._
+import leon.utils._
+import leon.invariant.util.Util._
+
+import scala.collection.mutable.{Map => MutableMap}
+
+object tprCostModel {
+  def costOf(e: Expr): Int = e match {
+    case FunctionInvocation(fd, args) => 1
+    case t: Terminal => 0
+    case _ => 1
+  }
+  def costOfExpr(e: Expr) = InfiniteIntegerLiteral(costOf(e))
+}
+
+class TPRInstrumenter(p: Program, si: SerialInstrumenter) extends Instrumenter(p, si) {
+  import tprCostModel._
+
+  def inst = TPR
+
+  val sccs = cg.graph.sccs.flatMap { scc =>
+    scc.map(fd => (fd -> scc.toSet))
+  }.toMap
+
+  //find all functions transitively called from rootFuncs (here ignore functions called via pre/post conditions)
+  val tprFuncs = getRootFuncs()
+  val timeFuncs = tprFuncs.foldLeft(Set[FunDef]())((acc, fd) => acc ++ cg.transitiveCallees(fd))
+
+  def functionsToInstrument(): Map[FunDef, List[Instrumentation]] = {
+    var emap = MutableMap[FunDef,List[Instrumentation]]()
+    def update(fd: FunDef, inst: Instrumentation) {
+      if (emap.contains(fd))
+        emap(fd) :+= inst
+      else emap.update(fd, List(inst))
+    }
+    tprFuncs.map(fd => update(fd, TPR))
+    timeFuncs.map(fd => update(fd, Time))
+    emap.toMap
+  }
+
+  def additionalfunctionsToAdd() = Seq()
+
+  def instrumentMatchCase(
+    me: MatchExpr,
+    mc: MatchCase,
+    caseExprCost: Expr,
+    scrutineeCost: Expr): Expr = {
+    val costMatch = costOfExpr(me)
+
+    def totalCostOfMatchPatterns(me: MatchExpr, mc: MatchCase): BigInt = {
+      def patCostRecur(pattern: Pattern, innerPat: Boolean, countLeafs: Boolean): Int = {
+        pattern match {
+          case InstanceOfPattern(_, _) => {
+            if (innerPat) 2 else 1
+          }
+          case WildcardPattern(None) => 0
+          case WildcardPattern(Some(id)) => {
+            if (countLeafs && innerPat) 1
+            else 0
+          }
+          case CaseClassPattern(_, _, subPatterns) => {
+            (if (innerPat) 2 else 1) + subPatterns.foldLeft(0)((acc, subPat) =>
+              acc + patCostRecur(subPat, true, countLeafs))
+          }
+          case TuplePattern(_, subPatterns) => {
+            (if (innerPat) 2 else 1) + subPatterns.foldLeft(0)((acc, subPat) =>
+              acc + patCostRecur(subPat, true, countLeafs))
+          }
+          case LiteralPattern(_, _) => if (innerPat) 2 else 1
+          case _ =>
+            throw new NotImplementedError(s"Pattern $pattern not handled yet!")
+        }
+      }
+      me.cases.take(me.cases.indexOf(mc)).foldLeft(0)(
+        (acc, currCase) => acc + patCostRecur(currCase.pattern, false, false)) +
+        patCostRecur(mc.pattern, false, true)
+    }
+    Plus(costMatch, Plus(
+      Plus(InfiniteIntegerLiteral(totalCostOfMatchPatterns(me, mc)),
+        caseExprCost),
+      scrutineeCost))
+  }
+
+  def instrument(e: Expr, subInsts: Seq[Expr], funInvResVar: Option[Variable] = None)
+    (implicit fd: FunDef, letIdMap: Map[Identifier,Identifier]): Expr = e match {
+    case t: Terminal => costOfExpr(t)
+    case FunctionInvocation(tfd, args) => {
+      val remSubInsts = if (tprFuncs.contains(tfd.fd))
+        subInsts.slice(0, subInsts.length - 1)
+      else subInsts
+      if (sccs(fd)(tfd.fd)) {
+        remSubInsts.foldLeft(costOfExpr(e) : Expr)(
+          (acc: Expr, subeTime: Expr) => Plus(subeTime, acc))
+      }
+      else {
+        val allSubInsts = remSubInsts :+ si.selectInst(tfd.fd)(funInvResVar.get, Time)
+        allSubInsts.foldLeft(costOfExpr(e) : Expr)(
+          (acc: Expr, subeTime: Expr) => Plus(subeTime, acc))
+      }
+    }
+    case _ =>
+      subInsts.foldLeft(costOfExpr(e) : Expr)(
+        (acc: Expr, subeTime: Expr) => Plus(subeTime, acc))
+  }
+
+  def instrumentIfThenElseExpr(e: IfExpr, condInst: Option[Expr],
+      thenInst: Option[Expr], elzeInst: Option[Expr]): (Expr, Expr) = {
+    val costIf = costOfExpr(e)
+    (Plus(costIf, Plus(condInst.get, thenInst.get)),
+      Plus(costIf, Plus(condInst.get, elzeInst.get)))
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/transformations/NonlinearityEliminationPhase.scala b/src/main/scala/leon/transformations/NonlinearityEliminationPhase.scala
new file mode 100644
index 000000000..2f41a5ccb
--- /dev/null
+++ b/src/main/scala/leon/transformations/NonlinearityEliminationPhase.scala
@@ -0,0 +1,188 @@
+package leon
+package transformations
+
+import invariant.factories._
+import invariant.util.Util._
+import invariant.structure.FunctionUtils._
+
+import purescala.ScalaPrinter
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Extractors._
+import purescala.Types._
+
+object MultFuncs {
+  def getMultFuncs(domain: TypeTree): (FunDef, FunDef) = {
+    //a recursive function that represents multiplication of two positive arguments
+    val pivMultFun = {
+      val xid = FreshIdentifier("x", domain)
+      val yid = FreshIdentifier("y", domain)
+      val varx = xid.toVariable
+      val vary = yid.toVariable
+      val args = Seq(xid, yid)
+      val funcType = FunctionType(Seq(domain, domain), domain)
+      val mfd = new FunDef(FreshIdentifier("pmult", funcType, false), Seq(), domain,
+        args.map((arg) => ValDef(arg, Some(arg.getType))))
+      val tmfd = TypedFunDef(mfd, Seq())
+
+      //define a body (a) using mult(x,y) = if(x == 0 || y ==0) 0 else mult(x-1,y) + y
+      val cond = Or(Equals(varx, zero), Equals(vary, zero))
+      val xminus1 = Minus(varx, one)
+      val yminus1 = Minus(vary, one)
+      val elze = Plus(FunctionInvocation(tmfd, Seq(xminus1, vary)), vary)
+      mfd.body = Some(IfExpr(cond, zero, elze))
+
+      //add postcondition
+      val resvar = FreshIdentifier("res", domain).toVariable
+      val post0 = GreaterEquals(resvar, zero)
+
+      //define alternate definitions of multiplication as postconditions
+      //(a) res = !(x==0 || y==0) => mult(x,y-1) + x
+      val guard = Not(cond)
+      val defn2 = Equals(resvar, Plus(FunctionInvocation(tmfd, Seq(varx, yminus1)), varx))
+      val post1 = Implies(guard, defn2)
+
+      // mfd.postcondition = Some((resvar.id, And(Seq(post0, post1))))
+      mfd.fullBody = Ensuring(mfd.body.get, Lambda(Seq(ValDef(resvar.id, Some(resvar.getType))), And(Seq(post0, post1))))
+      //set function properties (for now, only monotonicity)
+      mfd.addFlags(Set(Annotation("theoryop", Seq()), Annotation("monotonic", Seq()))) //"distributive" ?
+      mfd
+    }
+
+    //a function that represents multiplication, this transitively calls pmult
+    val multFun = {
+      val xid = FreshIdentifier("x", domain)
+      val yid = FreshIdentifier("y", domain)
+      val args = Seq(xid, yid)
+      val funcType = FunctionType(Seq(domain, domain), domain)
+      val fd = new FunDef(FreshIdentifier("mult", funcType, false), Seq(), domain, args.map((arg) => ValDef(arg, Some(arg.getType))))
+      val tpivMultFun = TypedFunDef(pivMultFun, Seq())
+
+      //the body is defined as mult(x,y) = val px = if(x < 0) -x else x;
+      //val py = if(y<0) -y else y;  val r = pmult(px,py);
+      //if(x < 0 && y < 0 || x >= 0 && y >= 0) r else -r
+      val varx = xid.toVariable
+      val vary = yid.toVariable
+      val modx = IfExpr(LessThan(varx, zero), UMinus(varx), varx)
+      val mody = IfExpr(LessThan(vary, zero), UMinus(vary), vary)
+      val px = FreshIdentifier("px", domain, false)
+      val py = FreshIdentifier("py", domain, false)
+      val call = Let(px, modx, Let(py, mody, FunctionInvocation(tpivMultFun, Seq(px, py).map(_.toVariable))))
+      val bothPive = And(GreaterEquals(varx, zero), GreaterEquals(vary, zero))
+      val bothNive = And(LessThan(varx, zero), LessThan(vary, zero))
+      val res = FreshIdentifier("r", domain, false)
+      val body = Let(res, call, IfExpr(Or(bothPive, bothNive), res.toVariable, UMinus(res.toVariable)))
+      fd.body = Some(body)
+      //set function properties
+      fd.addFlags(Set(Annotation("theoryop", Seq()), Annotation("monotonic", Seq())))
+      fd
+    }
+
+    (pivMultFun, multFun)
+  }
+}
+
+class NonlinearityEliminator(skipAxioms: Boolean, domain: TypeTree) {
+  import MultFuncs._
+  require(isNumericType(domain))
+
+  val debugNLElim = false
+
+  val one = InfiniteIntegerLiteral(1)
+  val zero = InfiniteIntegerLiteral(0)
+
+  val (pivMultFun, multFun) = getMultFuncs(domain)
+
+  //TOOD: note associativity property of multiplication is not taken into account
+  def apply(program: Program): Program = {
+
+    //create a fundef for each function in the program
+    val newFundefs = program.definedFunctions.map((fd) => {
+      val newFunType = FunctionType(fd.tparams.map((currParam) => currParam.tp), fd.returnType)
+      val newfd = new FunDef(FreshIdentifier(fd.id.name, newFunType, false), fd.tparams, fd.returnType, fd.params)
+      (fd, newfd)
+    }).toMap
+
+    //note, handling templates variables is slightly tricky as we need to preserve a*x as it is
+    val tmult = TypedFunDef(multFun, Seq())
+    var addMult = false
+    def replaceFun(ine: Expr, allowedVars: Set[Identifier] = Set()): Expr = {
+      simplePostTransform(e => e match {
+        case fi @ FunctionInvocation(tfd1, args) if newFundefs.contains(tfd1.fd) =>
+          FunctionInvocation(TypedFunDef(newFundefs(tfd1.fd), tfd1.tps), args)
+
+        case Times(Variable(id), e2) if (allowedVars.contains(id)) => e
+        case Times(e1, Variable(id)) if (allowedVars.contains(id)) => e
+
+        case Times(e1, e2) if (!e1.isInstanceOf[Literal[_]] && !e2.isInstanceOf[Literal[_]]) => {
+          //replace times by a mult function
+          addMult = true
+          FunctionInvocation(tmult, Seq(e1, e2))
+        }
+        //note: include mult function if division operation is encountered
+        //division is handled during verification condition generation.
+        case Division(_, _) => {
+          addMult = true
+          e
+        }
+        case _ => e
+      })(ine)
+    }
+
+    //create a body, pre, post for each newfundef
+    newFundefs.foreach((entry) => {
+      val (fd, newfd) = entry
+
+      //add a new precondition
+      newfd.precondition =
+        if (fd.precondition.isDefined)
+          Some(replaceFun(fd.precondition.get))
+        else None
+
+      //add a new body
+      newfd.body = if (fd.hasBody) {
+        //replace variables by constants if possible
+        val simpBody = simplifyLets(fd.body.get)
+        Some(replaceFun(simpBody))
+      } else None
+
+
+      //add a new postcondition
+      newfd.postcondition = if (fd.postcondition.isDefined) {
+        //we need to handle template and postWoTemplate specially
+        val Lambda(resultBinders, _) = fd.postcondition.get
+        val tmplExpr = fd.templateExpr
+        val newpost = if (fd.hasTemplate) {
+          val FunctionInvocation(tmpfd, Seq(Lambda(tmpvars, tmpbody))) = tmplExpr.get
+          val newtmp = FunctionInvocation(tmpfd, Seq(Lambda(tmpvars,
+            replaceFun(tmpbody, tmpvars.map(_.id).toSet))))
+          fd.postWoTemplate match {
+            case None =>
+              newtmp
+            case Some(postExpr) =>
+              And(replaceFun(postExpr), newtmp)
+          }
+        } else
+          replaceFun(fd.getPostWoTemplate)
+
+        Some(Lambda(resultBinders, newpost))
+      } else None
+
+      fd.flags.foreach(newfd.addFlag(_))
+    })
+
+    val newprog = copyProgram(program, (defs: Seq[Definition]) => {
+      defs.map {
+        case fd: FunDef => newFundefs(fd)
+        case d => d
+      } ++ (if (addMult) Seq(multFun, pivMultFun) else Seq())
+    })
+
+    if (debugNLElim)
+      println("After Nonlinearity Elimination: \n" + ScalaPrinter.apply(newprog))
+
+    newprog
+  }
+}
diff --git a/src/main/scala/leon/transformations/RecursionCountPhase.scala b/src/main/scala/leon/transformations/RecursionCountPhase.scala
new file mode 100644
index 000000000..73472e272
--- /dev/null
+++ b/src/main/scala/leon/transformations/RecursionCountPhase.scala
@@ -0,0 +1,71 @@
+package leon
+package transformations
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Extractors._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Types._
+import leon.utils._
+import invariant.util.Util._
+
+class RecursionCountInstrumenter(p: Program, si: SerialInstrumenter) extends Instrumenter(p, si) {
+
+  def inst = Rec
+
+  val sccs = cg.graph.sccs.flatMap { scc =>
+    scc.map(fd => (fd -> scc.toSet))
+  }.toMap
+
+  /**
+   * Instrument only those functions that are in the same sccs of the root functions
+   */
+  def functionsToInstrument(): Map[FunDef, List[Instrumentation]] = {
+    val instFunSet = getRootFuncs().flatMap(sccs.apply _)
+    instFunSet.map(x => (x, List(Rec))).toMap
+  }
+
+  override def additionalfunctionsToAdd(): Seq[FunDef] = Seq.empty[FunDef]
+
+  def addSubInstsIfNonZero(subInsts: Seq[Expr], init: Expr): Expr = {
+    subInsts.foldLeft(init) {
+      case (acc, subinst) if subinst != zero =>
+        if (acc == zero) subinst
+        else Plus(acc, subinst)
+    }
+  }
+
+  def instrumentMatchCase(me: MatchExpr,
+    mc: MatchCase,
+    caseExprCost: Expr,
+    scrutineeCost: Expr): Expr = {
+    Plus(caseExprCost, scrutineeCost)
+  }
+
+  def instrument(e: Expr, subInsts: Seq[Expr], funInvResVar: Option[Variable] = None)
+    (implicit fd: FunDef, leIdtMap: Map[Identifier,Identifier]): Expr = e match {
+    case FunctionInvocation(TypedFunDef(callee, _), _) if sccs(fd)(callee) =>
+      //this is a recursive call
+      //Note that the last element of subInsts is the instExpr of the invoked function
+      addSubInstsIfNonZero(subInsts, one)
+    case FunctionInvocation(TypedFunDef(callee, _), _) if si.funcInsts.contains(callee) && si.funcInsts(callee).contains(this.inst) =>
+      //this is not a recursive call, so do not consider the cost of the callee
+      //Note that the last element of subInsts is the instExpr of the invoked function
+      addSubInstsIfNonZero(subInsts.take(subInsts.size - 1), zero)
+    case _ =>
+      //add the cost of every sub-expression
+      addSubInstsIfNonZero(subInsts, zero)
+  }
+
+  def instrumentIfThenElseExpr(e: IfExpr, condInst: Option[Expr], thenInst: Option[Expr],
+    elzeInst: Option[Expr]): (Expr, Expr) = {
+
+    val cinst = condInst.toList
+    val tinst = thenInst.toList
+    val einst = elzeInst.toList
+
+    (addSubInstsIfNonZero(cinst ++ tinst, zero),
+      addSubInstsIfNonZero(cinst ++ einst, zero))
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/transformations/SerialInstrumentationPhase.scala b/src/main/scala/leon/transformations/SerialInstrumentationPhase.scala
new file mode 100644
index 000000000..f6862377d
--- /dev/null
+++ b/src/main/scala/leon/transformations/SerialInstrumentationPhase.scala
@@ -0,0 +1,489 @@
+package leon
+package transformations
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Extractors._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Types._
+import leon.purescala.ScalaPrinter
+import leon.utils._
+import invariant.util._
+import invariant.util.CallGraphUtil
+import invariant.structure.FunctionUtils._
+import scala.collection.mutable.{Map => MutableMap}
+
+/**
+ * An instrumentation phase that performs a sequence of instrumentations
+ */
+
+object InstrumentationPhase extends TransformationPhase {
+  val name = "Instrumentation Phase"
+  val description = "Instruments the program for all counters needed"
+
+  def apply(ctx: LeonContext, program: Program): Program = {
+    val instprog = new SerialInstrumenter(ctx, program)
+    instprog.apply
+  }
+}
+
+class SerialInstrumenter(ctx: LeonContext, program: Program) {
+  val debugInstrumentation = false
+
+  val instToInstrumenter: Map[Instrumentation, Instrumenter] =
+    Map(Time -> new TimeInstrumenter(program, this),
+      Depth -> new DepthInstrumenter(program, this),
+      Rec -> new RecursionCountInstrumenter(program, this),
+      Stack -> new StackSpaceInstrumenter(program, this),
+      TPR -> new TPRInstrumenter(program, this))
+
+  // a map from functions to the list of instrumentations to be performed for the function
+  lazy val funcInsts = {
+    var emap = MutableMap[FunDef,List[Instrumentation]]()
+    def update(fd: FunDef, inst: Instrumentation) {
+      if (emap.contains(fd))
+        emap(fd) = (emap(fd) :+ inst).distinct
+      else emap.update(fd, List(inst))
+    }
+    instToInstrumenter.values.foreach{ m =>
+      m.functionsToInstrument.foreach({ case (fd, instsToPerform) =>
+        instsToPerform.foreach(instToPerform => update(fd, instToPerform)) })
+    }
+    emap.toMap
+  }
+  lazy val instFuncs = funcInsts.keySet //should we exclude theory operations ?
+
+  def instrumenters(fd: FunDef) = funcInsts(fd) map instToInstrumenter.apply _
+  def instTypes(fd: FunDef) = funcInsts(fd).map(_.getType)
+  /**
+   * Index of the instrumentation 'inst' in result tuple that would be created.
+   * The return value will be >= 2 as the actual result value would be at index 1
+   */
+  def instIndex(fd: FunDef)(ins: Instrumentation) = funcInsts(fd).indexOf(ins) + 2
+  def selectInst(fd: FunDef)(e: Expr, ins: Instrumentation) = TupleSelect(e, instIndex(fd)(ins))
+
+  def apply: Program = {
+
+    //create new functions. Augment the return type of a function iff the postcondition uses
+    //the instrumentation variable or if the function is transitively called from such a function
+    //note: need not instrument fields
+    val funMap = Util.functionsWOFields(program.definedFunctions).foldLeft(Map[FunDef, FunDef]()) {
+      case (accMap, fd: FunDef) if fd.isTheoryOperation =>
+        accMap + (fd -> fd)
+      case (accMap, fd) => {
+        if (instFuncs.contains(fd)) {
+          val newRetType = TupleType(fd.returnType +: instTypes(fd))
+          // let the names of the function encode the kind of instrumentations performed
+          val freshId = FreshIdentifier(fd.id.name + "-" + funcInsts(fd).map(_.name).mkString("-"), newRetType)
+          val newfd = new FunDef(freshId, fd.tparams, newRetType, fd.params)
+          accMap + (fd -> newfd)
+        } else {
+          //here we need not augment the return types but do need to create a new copy
+          val freshId = FreshIdentifier(fd.id.name, fd.returnType)
+          val newfd = new FunDef(freshId, fd.tparams, fd.returnType, fd.params)
+          accMap + (fd -> newfd)
+        }
+      }
+    }
+
+    def mapExpr(ine: Expr): Expr = {
+      simplePostTransform((e: Expr) => e match {
+        case FunctionInvocation(tfd, args) if funMap.contains(tfd.fd) =>
+          if (instFuncs.contains(tfd.fd))
+            TupleSelect(FunctionInvocation(TypedFunDef(funMap(tfd.fd), tfd.tps), args), 1)
+          else
+            FunctionInvocation(TypedFunDef(funMap(tfd.fd), tfd.tps), args)
+        case _ => e
+      })(ine)
+    }
+
+    def mapBody(body: Expr, from: FunDef, to: FunDef) = {
+      val res = if (instFuncs.contains(from)) {
+        (new ExprInstrumenter(funMap)(from)(body))
+      } else
+        mapExpr(body)
+      res
+    }
+
+    def mapPost(pred: Expr, from: FunDef, to: FunDef) = {
+      pred match {
+        case Lambda(Seq(ValDef(fromRes, _)), postCond) if (instFuncs.contains(from)) =>
+          val toResId = FreshIdentifier(fromRes.name, to.returnType, true)
+          val newpost = postMap((e: Expr) => e match {
+            case Variable(`fromRes`) =>
+              Some(TupleSelect(toResId.toVariable, 1))
+
+            case _ if funcInsts(from).exists(_.isInstVariable(e)) =>
+              val inst = funcInsts(from).find(_.isInstVariable(e)).get
+              Some(TupleSelect(toResId.toVariable, instIndex(from)(inst)))
+
+            case _ =>
+              None
+          })(postCond)
+          Lambda(Seq(ValDef(toResId)), mapExpr(newpost))
+        case _ =>
+          mapExpr(pred)
+      }
+    }
+
+    // Map the bodies and preconditions
+    for ((from, to) <- funMap) {
+      //copy annotations
+      from.flags.foreach(to.addFlag(_))
+      to.fullBody = from.fullBody match {
+        case Require(pre, body) =>
+          //here 'from' does not have a postcondition but 'to' will always have a postcondition
+          val toPost =
+            Lambda(Seq(ValDef(FreshIdentifier("res", to.returnType))), BooleanLiteral(true))
+          val bodyPre =
+            Require(mapExpr(pre), mapBody(body, from, to))
+          Ensuring(bodyPre, toPost)
+
+        case Ensuring(Require(pre, body), post) =>
+          Ensuring(Require(mapExpr(pre), mapBody(body, from, to)),
+            mapPost(post, from, to))
+
+        case Ensuring(body, post) =>
+          Ensuring(mapBody(body, from, to), mapPost(post, from, to))
+
+        case body =>
+          val toPost =
+            Lambda(Seq(ValDef(FreshIdentifier("res", to.returnType))), BooleanLiteral(true))
+          Ensuring(mapBody(body, from, to), toPost)
+      }
+    }
+
+    val additionalFuncs = funMap.flatMap{ case (k, _) =>
+       if (instFuncs(k))
+        instrumenters(k).flatMap(_.additionalfunctionsToAdd)
+      else List()
+    }.toList.distinct
+
+    val newprog = Util.copyProgram(program, (defs: Seq[Definition]) =>
+      defs.map {
+        case fd: FunDef if funMap.contains(fd) =>
+           funMap(fd)
+        case d => d
+      } ++ additionalFuncs)
+    if (debugInstrumentation)
+      println("After Instrumentation: \n" + ScalaPrinter.apply(newprog))
+
+    ProgramSimplifier(newprog)
+  }
+
+  class ExprInstrumenter(funMap: Map[FunDef, FunDef])(implicit currFun: FunDef) {
+    val retainMatches = true
+
+    val insts = funcInsts(currFun)
+    val instrumenters = SerialInstrumenter.this.instrumenters(currFun)
+    val instIndex = SerialInstrumenter.this.instIndex(currFun) _
+    val selectInst = SerialInstrumenter.this.selectInst(currFun) _
+    val instTypes = SerialInstrumenter.this.instTypes(currFun)
+
+    // Should be called only if 'expr' has to be instrumented
+    // Returned Expr is always an expr of type tuple (Expr, Int)
+    def tupleify(e: Expr, subs: Seq[Expr], recons: Seq[Expr] => Expr)(implicit letIdMap: Map[Identifier, Identifier]): Expr = {
+      // When called for:
+      // Op(n1,n2,n3)
+      // e      = Op(n1,n2,n3)
+      // subs   = Seq(n1,n2,n3)
+      // recons = { Seq(newn1,newn2,newn3) => Op(newn1, newn2, newn3) }
+      //
+      // This transformation should return, informally:
+      //
+      // LetTuple((e1,t1), transform(n1),
+      //   LetTuple((e2,t2), transform(n2),
+      //    ...
+      //      Tuple(recons(e1, e2, ...), t1 + t2 + ... costOfExpr(Op)
+      //    ...
+      //   )
+      // )
+      //
+      // You will have to handle FunctionInvocation specially here!
+      tupleifyRecur(e, subs, recons, List(), Map())
+    }
+
+    def tupleifyRecur(e: Expr, subs: Seq[Expr], recons: Seq[Expr] => Expr, subeVals: List[Expr],
+      subeInsts: Map[Instrumentation, List[Expr]])(implicit letIdMap: Map[Identifier, Identifier]): Expr = {
+      //note: subs.size should be zero if e is a terminal
+      if (subs.size == 0) {
+        e match {
+          case v @ Variable(id) =>
+            val valPart = if (letIdMap.contains(id)) {
+              TupleSelect(letIdMap(id).toVariable, 1) //this takes care of replacement
+            } else v
+            val instPart = instrumenters map (_.instrument(v, Seq()))
+            Tuple(valPart +: instPart)
+
+          case t: Terminal =>
+            val instPart = instrumenters map (_.instrument(t, Seq()))
+            val finalRes = Tuple(t +: instPart)
+            finalRes
+
+          case f @ FunctionInvocation(tfd, args) if tfd.fd.isRealFunction =>
+            val newfd = funMap(tfd.fd)
+            val newFunInv = FunctionInvocation(TypedFunDef(newfd, tfd.tps), subeVals)
+            //create a variables to store the result of function invocation
+            if (instFuncs(tfd.fd)) {
+              //this function is also instrumented
+              val resvar = Variable(FreshIdentifier("e", newfd.returnType, true))
+              val valexpr = TupleSelect(resvar, 1)
+              val instexprs = instrumenters.map { m =>
+                val calleeInst = if (funcInsts(tfd.fd).contains(m.inst)) {
+                  List(SerialInstrumenter.this.selectInst(tfd.fd)(resvar, m.inst))
+                } else List()
+                //Note we need to ensure that the last element of list is the instval of the finv
+                m.instrument(e, subeInsts.getOrElse(m.inst, List()) ++ calleeInst, Some(resvar))
+              }
+              Let(resvar.id, newFunInv, Tuple(valexpr +: instexprs))
+            } else {
+              val resvar = Variable(FreshIdentifier("e", tfd.fd.returnType, true))
+              val instexprs = instrumenters.map { m =>
+                m.instrument(e, subeInsts.getOrElse(m.inst, List()))
+              }
+              Let(resvar.id, newFunInv, Tuple(resvar +: instexprs))
+            }
+
+          // This case will be taken if the function invocation is actually a val (lazy or otherwise) in the class
+          case f @ FunctionInvocation(tfd, args) =>
+            val resvar = Variable(FreshIdentifier("e", tfd.fd.returnType, true))
+            val instPart = instrumenters map (_.instrument(f, Seq()))
+            val finalRes = Tuple(f +: instPart)
+            finalRes
+
+          case _ =>
+            val exprPart = recons(subeVals)
+            val instexprs = instrumenters.zipWithIndex.map {
+              case (menter, i) => menter.instrument(e, subeInsts.getOrElse(menter.inst, List()))
+            }
+            Tuple(exprPart +: instexprs)
+        }
+      } else {
+        val currExp = subs.head
+        val resvar = Variable(FreshIdentifier("e", TupleType(currExp.getType +: instTypes), true))
+        val eval = TupleSelect(resvar, 1)
+        val instMap = insts.map { inst =>
+          (inst -> (subeInsts.getOrElse(inst, List()) :+ selectInst(resvar, inst)))
+        }.toMap
+        //process the remaining arguments
+        val recRes = tupleifyRecur(e, subs.tail, recons, subeVals :+ eval, instMap)
+        //transform the current expression
+        val newCurrExpr = transform(currExp)
+        Let(resvar.id, newCurrExpr, recRes)
+      }
+    }
+
+    /**
+     * TODO: need to handle new expression trees
+     * Match statements without guards are now instrumented directly
+     */
+    def transform(e: Expr)(implicit letIdMap: Map[Identifier, Identifier]): Expr = e match {
+      // Assume that none of the matchcases has a guard. It has already been converted into an if then else
+      case me @ MatchExpr(scrutinee, matchCases) =>
+        val containsGuard = matchCases.exists(currCase => currCase.optGuard.isDefined)
+        if (containsGuard) {
+          def rewritePM(me: MatchExpr): Option[Expr] = {
+            val MatchExpr(scrut, cases) = me
+            val condsAndRhs = for (cse <- cases) yield {
+              val map = mapForPattern(scrut, cse.pattern)
+              val patCond = conditionForPattern(scrut, cse.pattern, includeBinders = false)
+              val realCond = cse.optGuard match {
+                case Some(g) => And(patCond, replaceFromIDs(map, g))
+                case None => patCond
+              }
+              val newRhs = replaceFromIDs(map, cse.rhs)
+              (realCond, newRhs)
+            }
+            val bigIte = condsAndRhs.foldRight[Expr](
+              Error(me.getType, "Match is non-exhaustive").copiedFrom(me))((p1, ex) => {
+                if (p1._1 == BooleanLiteral(true)) {
+                  p1._2
+                } else {
+                  IfExpr(p1._1, p1._2, ex)
+                }
+              })
+            Some(bigIte)
+          }
+          transform(rewritePM(me).get)
+        } else {
+          val instScrutinee =
+            Variable(FreshIdentifier("scr", TupleType(scrutinee.getType +: instTypes), true))
+
+          def transformMatchCaseList(mCases: Seq[MatchCase]): Seq[MatchCase] = {
+            def transformMatchCase(mCase: MatchCase) = {
+              val MatchCase(pattern, guard, expr) = mCase
+              val newExpr = {
+                val exprVal =
+                  Variable(FreshIdentifier("expr", TupleType(expr.getType +: instTypes), true))
+                val newExpr = transform(expr)
+                val instExprs = instrumenters map { m =>
+                  m.instrumentMatchCase(me, mCase, selectInst(exprVal, m.inst),
+                    selectInst(instScrutinee, m.inst))
+                }
+                val letBody = Tuple(TupleSelect(exprVal, 1) +: instExprs)
+                Let(exprVal.id, newExpr, letBody)
+              }
+              MatchCase(pattern, guard, newExpr)
+            }
+            if (mCases.length == 0) Seq[MatchCase]()
+            else {
+              transformMatchCase(mCases.head) +: transformMatchCaseList(mCases.tail)
+            }
+          }
+          val matchExpr = MatchExpr(TupleSelect(instScrutinee, 1),
+            transformMatchCaseList(matchCases))
+          Let(instScrutinee.id, transform(scrutinee), matchExpr)
+        }
+
+      case Let(i, v, b) => {
+        val (ni, nv) = {
+          val ir = Variable(FreshIdentifier("ir", TupleType(v.getType +: instTypes), true))
+          val transv = transform(v)
+          (ir, transv)
+        }
+        val r = Variable(FreshIdentifier("r", TupleType(b.getType +: instTypes), true))
+        val transformedBody = transform(b)(letIdMap + (i -> ni.id))
+        val instexprs = instrumenters map { m =>
+          m.instrument(e, List(selectInst(ni, m.inst), selectInst(r, m.inst)))
+        }
+        Let(ni.id, nv,
+          Let(r.id, transformedBody, Tuple(TupleSelect(r, 1) +: instexprs)))
+      }
+
+      case ife @ IfExpr(cond, th, elze) => {
+        val (nifCons, condInsts) = {
+          val rescond = Variable(FreshIdentifier("c", TupleType(cond.getType +: instTypes), true))
+          val condInstPart = insts.map { inst => (inst -> selectInst(rescond, inst)) }.toMap
+          val recons = (e1: Expr, e2: Expr) => {
+            Let(rescond.id, transform(cond), IfExpr(TupleSelect(rescond, 1), e1, e2))
+          }
+          (recons, condInstPart)
+        }
+        val (nthenCons, thenInsts) = {
+          val resthen = Variable(FreshIdentifier("th", TupleType(th.getType +: instTypes), true))
+          val thInstPart = insts.map { inst => (inst -> selectInst(resthen, inst)) }.toMap
+          val recons = (theninsts: List[Expr]) => {
+            Let(resthen.id, transform(th), Tuple(TupleSelect(resthen, 1) +: theninsts))
+          }
+          (recons, thInstPart)
+        }
+        val (nelseCons, elseInsts) = {
+          val reselse = Variable(FreshIdentifier("el", TupleType(elze.getType +: instTypes), true))
+          val elInstPart = insts.map { inst => (inst -> selectInst(reselse, inst)) }.toMap
+          val recons = (einsts: List[Expr]) => {
+            Let(reselse.id, transform(elze), Tuple(TupleSelect(reselse, 1) +: einsts))
+          }
+          (recons, elInstPart)
+        }
+        val (finalThInsts, finalElInsts) = instrumenters.foldLeft((List[Expr](), List[Expr]())) {
+          case ((thinsts, elinsts), menter) =>
+            val inst = menter.inst
+            val (thinst, elinst) = menter.instrumentIfThenElseExpr(ife,
+              Some(condInsts(inst)), Some(thenInsts(inst)), Some(elseInsts(inst)))
+            (thinsts :+ thinst, elinsts :+ elinst)
+        }
+        val nthen = nthenCons(finalThInsts)
+        val nelse = nelseCons(finalElInsts)
+        nifCons(nthen, nelse)
+      }
+
+      // For all other operations, we go through a common tupleifier.
+      case n @ Operator(ss, recons) =>
+        tupleify(e, ss, recons)
+
+/*      case b @ BinaryOperator(s1, s2, recons) =>
+        tupleify(e, Seq(s1, s2), { case Seq(s1, s2) => recons(s1, s2) })
+
+      case u @ UnaryOperator(s, recons) =>
+        tupleify(e, Seq(s), { case Seq(s) => recons(s) })
+*/
+      case t: Terminal =>
+        tupleify(e, Seq(), { case Seq() => t })
+    }
+
+    def apply(e: Expr): Expr = {
+      // Apply transformations
+      val newe =
+        if (retainMatches) e
+        else matchToIfThenElse(liftExprInMatch(e))
+      val transformed = transform(newe)(Map())
+      val bodyId = FreshIdentifier("bd", transformed.getType, true)
+      val instExprs = instrumenters map { m =>
+        m.instrumentBody(newe,
+          selectInst(bodyId.toVariable, m.inst))
+
+      }
+      Let(bodyId, transformed,
+        Tuple(TupleSelect(bodyId.toVariable, 1) +: instExprs))
+    }
+
+    def liftExprInMatch(ine: Expr): Expr = {
+      def helper(e: Expr): Expr = {
+        e match {
+          case MatchExpr(strut, cases) => strut match {
+            case t: Terminal => e
+            case _ => {
+              val freshid = FreshIdentifier("m", strut.getType, true)
+              Let(freshid, strut, MatchExpr(freshid.toVariable, cases))
+            }
+          }
+          case _ => e
+        }
+      }
+
+      if (retainMatches) helper(ine)
+      else simplePostTransform(helper)(ine)
+    }
+  }
+}
+
+/**
+ * Implements procedures for a specific instrumentation
+ */
+abstract class Instrumenter(program: Program, si: SerialInstrumenter) {
+
+  def inst: Instrumentation
+
+  protected val cg = CallGraphUtil.constructCallGraph(program, onlyBody = true)
+
+  def functionsToInstrument(): Map[FunDef, List[Instrumentation]]
+
+  def additionalfunctionsToAdd(): Seq[FunDef]
+
+  def instrumentBody(bodyExpr: Expr, instExpr: Expr)(implicit fd: FunDef): Expr = instExpr
+
+  def getRootFuncs(prog: Program = program): Set[FunDef] = {
+    prog.definedFunctions.filter { fd =>
+      (fd.hasPostcondition && exists(inst.isInstVariable)(fd.postcondition.get))
+    }.toSet
+  }
+
+  /**
+   * Given an expression to be instrumented
+   * and the instrumentation of each of its subexpressions,
+   * computes an instrumentation for the procedure.
+   * The sub-expressions correspond to expressions returned
+   * by Expression Extractors.
+   * fd is the function containing the expression `e`
+   */
+  def instrument(e: Expr, subInsts: Seq[Expr], funInvResVar: Option[Variable] = None)
+    (implicit fd: FunDef, letIdMap: Map[Identifier, Identifier]): Expr
+
+  /**
+   * Instrument procedure specialized for if-then-else
+   */
+  def instrumentIfThenElseExpr(e: IfExpr, condInst: Option[Expr],
+    thenInst: Option[Expr], elzeInst: Option[Expr]): (Expr, Expr)
+
+  /**
+   * This function is expected to combine the cost of the scrutinee,
+   * the pattern matching and the expression.
+   * The cost model for pattern matching is left to the user.
+   * As matches with guards are converted to ifThenElse statements,
+   * the user may want to make sure that the cost model for pattern
+   * matching across match statements and ifThenElse statements is consistent
+   */
+  def instrumentMatchCase(me: MatchExpr, mc: MatchCase,
+    caseExprCost: Expr, scrutineeCost: Expr): Expr
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/transformations/StackSpacePhase.scala b/src/main/scala/leon/transformations/StackSpacePhase.scala
new file mode 100644
index 000000000..f4edb7ee1
--- /dev/null
+++ b/src/main/scala/leon/transformations/StackSpacePhase.scala
@@ -0,0 +1,336 @@
+package leon
+package transformations
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Extractors._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Types._
+import leon.utils._
+
+class StackSpaceInstrumenter(p: Program, si: SerialInstrumenter) extends Instrumenter(p, si) {
+  val typedMaxFun = TypedFunDef(InstUtil.maxFun, Seq())
+  val optimiseTailCalls = true
+
+  def inst = Stack
+
+  def functionsToInstrument(): Map[FunDef, List[Instrumentation]] = {
+    // find all functions transitively called from rootFuncs (here ignore functions called via pre/post conditions)
+    val instFunSet = getRootFuncs().foldLeft(Set[FunDef]())((acc, fd) => acc ++ cg.transitiveCallees(fd))
+    instFunSet.map(x => (x, List(Stack))).toMap
+  }
+
+  def additionalfunctionsToAdd(): Seq[FunDef] = Seq() //Seq(InstUtil.maxFun) - max functions are inlined, so they need not be added
+
+  def addSubInstsIfNonZero(subInsts: Seq[Expr], init: Expr): Expr = {
+    subInsts.foldLeft(init)((acc: Expr, subeTime: Expr) => {
+      (subeTime, acc) match {
+        case (InfiniteIntegerLiteral(x), _) if (x == 0) => acc
+        case (_, InfiniteIntegerLiteral(x)) if (x == 0) => subeTime
+        case _ => FunctionInvocation(typedMaxFun, Seq(acc, subeTime))
+      }
+    })
+  }
+
+  // Check if a given function call is a tail recursive call
+  def isTailCall(call: FunctionInvocation, fd: FunDef): Boolean = {
+    if (fd.body.isDefined) {
+      def helper(e: Expr): Boolean = {
+        e match {
+          case FunctionInvocation(_,_) if (e == call) => true
+          case Let(binder, value, body) => helper(body)
+          case LetDef(_,body) => helper(body)
+          case IfExpr(_,thenExpr, elseExpr) => helper(thenExpr) || helper(elseExpr)
+          case MatchExpr(_, mCases) => {
+            mCases.exists(currCase => helper(currCase.rhs))
+          }
+          case _ => false
+        }
+      }
+      helper(fd.body.get)
+    }
+    else false
+  }
+
+  def instrumentMatchCase(me: MatchExpr, mc: MatchCase,
+    caseExprCost: Expr, scrutineeCost: Expr): Expr = {
+
+    def costOfMatchPattern(me: MatchExpr, mc: MatchCase): Expr = {
+      val costOfMatchPattern = 1
+      InfiniteIntegerLiteral(costOfMatchPattern)
+    }
+
+    addSubInstsIfNonZero(Seq(costOfMatchPattern(me, mc), caseExprCost, scrutineeCost), InfiniteIntegerLiteral(0))
+  }
+
+  def instrument(e: Expr, subInsts: Seq[Expr], funInvResVar: Option[Variable] = None)
+    (implicit fd: FunDef, letIdMap: Map[Identifier,Identifier]): Expr = {
+
+    e match {
+      case t: Terminal => InfiniteIntegerLiteral(0)
+      case FunctionInvocation(callFd, args) => {
+        // Need to extimate the size of the activation frame of this function.
+        //  #Args +
+        //  #LocalVals +
+        //  #Temporaries created (assume tree-like evaluation of expressions. This will the maximum
+        //                        number of temporaries allocated. Also because we assume all the
+        //                        temporaries are allocated on the stack and not used only from registers)
+
+        val numTemps =
+          if (callFd.body.isDefined) {
+            val (temp, stack) = estimateTemporaries(callFd.body.get)
+            temp + stack
+          } else 0
+        val retVar = subInsts.last
+        val remSubInsts = subInsts.slice(0, subInsts.length - 1)
+        val totalInvocationCost = {
+          // model scala's tail recursion optimization here
+          if ((isTailCall(FunctionInvocation(callFd, args), fd) && fd.id == callFd.id) && optimiseTailCalls)
+            InfiniteIntegerLiteral(0)
+          else
+            retVar
+        }
+        val subeTimesExpr = addSubInstsIfNonZero(remSubInsts, InfiniteIntegerLiteral(0))
+
+        subeTimesExpr match {
+          case InfiniteIntegerLiteral(x) if (x == 0) => totalInvocationCost
+          case _ =>
+            addSubInstsIfNonZero(remSubInsts :+ totalInvocationCost, InfiniteIntegerLiteral(0))
+        }
+      }
+      case _ => addSubInstsIfNonZero(subInsts, InfiniteIntegerLiteral(0))
+    }
+  }
+
+  override def instrumentBody(bodyExpr: Expr, instExpr: Expr)(implicit fd: FunDef): Expr = {
+    val minActivationRecSize = 2
+    val (temps, stack) = estimateTemporaries(bodyExpr)
+    //println(temps + " " + stack)
+    Plus(instExpr, InfiniteIntegerLiteral(temps + stack + fd.params.length +
+      1 /*object ref*/ +
+      1 /*return variable before jumping*/ +
+      minActivationRecSize /*Sometimes for some reason, there are holes in local vars*/))
+  }
+
+  def instrumentIfThenElseExpr(e: IfExpr, condInst: Option[Expr], thenInst: Option[Expr],
+    elzeInst: Option[Expr]): (Expr, Expr) = {
+    import invariant.util.Util._
+
+    val cinst = condInst.toList
+    val tinst = thenInst.toList
+    val einst = elzeInst.toList
+
+    (addSubInstsIfNonZero(cinst ++ tinst, zero),
+      addSubInstsIfNonZero(cinst ++ einst, zero))
+  }
+
+  /* Tries to estimate the depth of the operand stack and the temporaries
+    (excluding arguments) needed by the bytecode. As the JVM might perform
+    some optimizations when actually executing the bytecode, what we compute
+    here is an upper bound on the memory needed to evaluate the expression
+  */
+  // (temporaries, stackSize)
+  def estimateTemporaries(e: Expr): (Int, Int) = {
+    e match {
+      /* Like vals */
+      case Let(binder: Identifier, value: Expr, body: Expr) => {
+      // One for the val created + Temps in expr on RHS of initilisation + Rem. body
+        val (valTemp, valStack) = estimateTemporaries(value)
+        val (bodyTemp, bodyStack) = estimateTemporaries(body)
+        (1 + valTemp + bodyTemp, Math.max(valStack, bodyStack))
+      }
+
+      case LetDef(fd: FunDef, body: Expr) => {
+      // The function definition does not take up stack space. Goes into the constant pool
+        estimateTemporaries(body)
+      }
+
+      case FunctionInvocation(tfd: TypedFunDef, args: Seq[Expr]) => {
+      // One for the object reference. + stack for computing arguments and also the
+      // fact that the arguments go into the stack
+        val (temp, stack) =
+          args.foldLeft(((0, 0), 0))((t: ((Int, Int),Int), currExpr) => {
+            t match {
+              case (acc: (Int, Int), currExprNum: Int) =>
+                val (seTemp, seStack) = estimateTemporaries(currExpr)
+                ((acc._1 + seTemp, Math.max(acc._2, currExprNum + seStack)), 1 + currExprNum)
+            }
+          })._1
+
+        (temp + 1 /*possibly if the ret val needs to be stored for future use*/, stack + 1)
+      }
+
+      case MethodInvocation(rec: Expr, cd: ClassDef, tfd: TypedFunDef, args: Seq[Expr]) => {
+        val (recTemp, recStack) = estimateTemporaries(rec)
+        val (temp, stack) =
+          args.foldLeft(((recTemp, Math.max(args.length, recStack)), 0))((t: ((Int, Int),Int), currExpr) => {
+            t match {
+              case (acc: (Int, Int), currExprNum: Int) =>
+                val (seTemp, seStack) = estimateTemporaries(currExpr)
+                ((acc._1 + seTemp, Math.max(acc._2, currExprNum + seStack)), 1 + currExprNum)
+            }
+          })._1
+
+        (temp + 1 /*possibly if the ret val needs to be stored for future use*/, stack + 1)
+      }
+
+      case Application(caller: Expr, args: Seq[Expr]) => {
+        val (callerTemp, callerStack) = estimateTemporaries(caller)
+        args.foldLeft(((callerTemp, Math.max(args.length, callerStack)), 0))((t: ((Int, Int),Int), currExpr) => {
+          t match {
+            case (acc: (Int, Int), currExprNum: Int) =>
+              val (seTemp, seStack) = estimateTemporaries(currExpr)
+              ((acc._1 + seTemp, Math.max(acc._2, currExprNum + seStack)), 1 + currExprNum)
+          }
+        })._1
+      }
+
+      case IfExpr(cond: Expr, thenn: Expr, elze: Expr) => {
+        val (condTemp, condStack) = estimateTemporaries(cond)
+        val (thennTemp, thennStack) = estimateTemporaries(thenn)
+        val (elzeTemp, elzeStack) = estimateTemporaries(elze)
+
+        (condTemp + thennTemp + elzeTemp,
+          Math.max(condStack, Math.max(thennStack, elzeStack)))
+      }
+
+      case Tuple (exprs: Seq[Expr]) => {
+        val (temp, stack) =
+          exprs.foldLeft(((0, 0), 0))((t: ((Int, Int),Int), currExpr) => {
+            t match {
+              case (acc: (Int, Int), currExprNum: Int) =>
+                val (seTemp, seStack) = estimateTemporaries(currExpr)
+                ((acc._1 + seTemp, Math.max(acc._2, currExprNum + seStack)), 1 + currExprNum)
+            }
+          })._1
+
+        (temp, stack + 2)
+      }
+
+      case MatchExpr(scrutinee: Expr, cases: Seq[MatchCase]) => {
+
+        // FIXME
+        def estimateTemporariesMatchPattern(pattern: Pattern): (Int, Int) = {
+          pattern match {
+            case InstanceOfPattern(binder: Option[Identifier], ct: ClassType) => { // c: Class
+              (0,1)
+            }
+
+            case WildcardPattern(binder: Option[Identifier]) => { // c @ _
+              (if (binder.isDefined) 1 else 0, 0)
+            }
+
+            case CaseClassPattern(binder: Option[Identifier], ct: CaseClassType, subPatterns: Seq[Pattern]) => {
+              val (temp, stack) =
+                subPatterns.foldLeft((1 /* create a new var for matching */, 1))((t: (Int, Int), currPattern) => {
+                  t match {
+                    case acc: (Int, Int) => {
+                      val (patTemp, patStack) = estimateTemporariesMatchPattern(currPattern)
+                      (acc._1 + patTemp, Math.max(acc._2, patStack))
+                    }
+                  }
+                })
+
+              (temp, stack)
+            }
+
+            case TuplePattern(binder: Option[Identifier], subPatterns: Seq[Pattern]) => {
+              val (temp, stack) =
+                subPatterns.foldLeft((1 /* create a new var for matching */, 1))((t: (Int, Int), currPattern) => {
+                  t match {
+                    case acc: (Int, Int) => {
+                      val (patTemp, patStack) = estimateTemporariesMatchPattern(currPattern)
+                      (acc._1 + patTemp, Math.max(acc._2, patStack))
+                    }
+                  }
+                })
+
+              (temp, stack)
+            }
+
+            case LiteralPattern(binder, lit) => {
+              (0,2)
+            }
+            case _ =>
+            	throw new NotImplementedError(s"Pattern $pattern not handled yet!")
+          }
+        }
+
+        val (scrTemp, scrStack) = estimateTemporaries(scrutinee)
+
+        val res = cases.foldLeft(((scrTemp + 1 /* create a new var for matching */, Math.max(scrStack, 3 /*MatchError*/))))((t: (Int, Int), currCase: MatchCase) => {
+          t match {
+            case acc: (Int, Int) =>
+              val (patTemp, patStack) = estimateTemporariesMatchPattern(currCase.pattern)
+              val (rhsTemp, rhsStack) = estimateTemporaries(currCase.rhs)
+              val (guardTemp, guardStack) =
+                if (currCase.optGuard.isDefined) estimateTemporaries(currCase.optGuard.get) else (0,0)
+
+              (patTemp + rhsTemp + guardTemp + acc._1,
+                Math.max(acc._2, Math.max(patStack, Math.max(guardStack, rhsStack))))
+          }
+        })
+        res
+      }
+
+      /* Propositional logic */
+      case Implies(lhs: Expr, rhs: Expr) => {
+        val (lhsTemp, lhsStack)= estimateTemporaries(lhs)
+        val (rhsTemp, rhsStack)= estimateTemporaries(rhs)
+        (rhsTemp + lhsTemp, 1 + Math.max(lhsStack, rhsStack))
+      }
+
+      case Not(expr: Expr) => estimateTemporaries(expr)
+
+      case Equals(lhs: Expr, rhs: Expr) => {
+        val (lhsTemp, lhsStack)= estimateTemporaries(lhs)
+        val (rhsTemp, rhsStack)= estimateTemporaries(rhs)
+        (rhsTemp + lhsTemp +
+            // If object ref, check for non nullity
+            1,
+            //(if (!(lhs.getType == IntegerType && rhs.getType == IntegerType)) 1 else 0),
+          1 + Math.max(lhsStack, rhsStack))
+      }
+
+      case CaseClass(ct: CaseClassType, args: Seq[Expr]) => {
+        val (temp, stack) =
+          args.foldLeft(((0, 0), 0))((t: ((Int, Int),Int), currExpr) => {
+            t match {
+              case (acc: (Int, Int), currExprNum: Int) =>
+                val (seTemp, seStack) = estimateTemporaries(currExpr)
+                ((acc._1 + seTemp, Math.max(acc._2, currExprNum + seStack)), 1 + currExprNum)
+            }
+          })._1
+
+        (temp, stack + 2)
+      }
+
+      case _: Literal[_] => (0, 1)
+
+      case Variable(id: Identifier) => (0, 1)
+
+      case Lambda(args: Seq[ValDef], body: Expr) => (0, 0)
+
+      case TupleSelect(tuple: Expr, index: Int) => (0, 1)
+
+      /*case BinaryOperator(s1,s2,_) => {
+        val (s1Temp, s1Stack)= estimateTemporaries(s1)
+        val (s2Temp, s2Stack)= estimateTemporaries(s2)
+        (s1Temp + s2Temp, Math.max(s1Stack, 1 + s2Stack))
+      }*/
+
+      case Operator(exprs, _) => {
+        exprs.foldLeft(((0, 0), 0))((t: ((Int, Int),Int), currExpr) => {
+          t match {
+            case (acc: (Int, Int), currExprNum: Int) =>
+              val (seTemp, seStack) = estimateTemporaries(currExpr)
+              ((acc._1 + seTemp, Math.max(acc._2, currExprNum + seStack)), 1 + currExprNum)
+          }
+        })._1
+      }
+
+      case _ => (0, 0)
+    }
+  }
+}
diff --git a/src/main/scala/leon/transformations/TimeStepsPhase.scala b/src/main/scala/leon/transformations/TimeStepsPhase.scala
new file mode 100644
index 000000000..4d8613649
--- /dev/null
+++ b/src/main/scala/leon/transformations/TimeStepsPhase.scala
@@ -0,0 +1,94 @@
+package leon
+package transformations
+
+import purescala.Common._
+import purescala.Definitions._
+import purescala.Extractors._
+import purescala.Expressions._
+import purescala.ExprOps._
+import purescala.Types._
+import leon.utils._
+import leon.invariant.util.Util._
+
+object timeCostModel {
+  def costOf(e: Expr): Int = e match {
+    case FunctionInvocation(fd, args) => 1
+    case t: Terminal => 0
+    case _ => 1
+  }
+
+  def costOfExpr(e: Expr) = InfiniteIntegerLiteral(costOf(e))
+}
+
+class TimeInstrumenter(p: Program, si: SerialInstrumenter) extends Instrumenter(p, si) {
+  import timeCostModel._
+
+  def inst = Time
+
+  def functionsToInstrument(): Map[FunDef, List[Instrumentation]] = {
+    //find all functions transitively called from rootFuncs (here ignore functions called via pre/post conditions)
+    val instFunSet = getRootFuncs().foldLeft(Set[FunDef]())((acc, fd) => acc ++ cg.transitiveCallees(fd))
+    instFunSet.map(x => (x, List(Time))).toMap
+  }
+
+  def additionalfunctionsToAdd() = Seq()
+
+  def instrumentMatchCase(
+    me: MatchExpr,
+    mc: MatchCase,
+    caseExprCost: Expr,
+    scrutineeCost: Expr): Expr = {
+    val costMatch = costOfExpr(me)
+
+    def totalCostOfMatchPatterns(me: MatchExpr, mc: MatchCase): BigInt = {
+
+      def patCostRecur(pattern: Pattern, innerPat: Boolean, countLeafs: Boolean): Int = {
+        pattern match {
+          case InstanceOfPattern(_, _) => {
+            if (innerPat) 2 else 1
+          }
+          case WildcardPattern(None) => 0
+          case WildcardPattern(Some(id)) => {
+            if (countLeafs && innerPat) 1
+            else 0
+          }
+          case CaseClassPattern(_, _, subPatterns) => {
+            (if (innerPat) 2 else 1) + subPatterns.foldLeft(0)((acc, subPat) =>
+              acc + patCostRecur(subPat, true, countLeafs))
+          }
+          case TuplePattern(_, subPatterns) => {
+            (if (innerPat) 2 else 1) + subPatterns.foldLeft(0)((acc, subPat) =>
+              acc + patCostRecur(subPat, true, countLeafs))
+          }
+          case LiteralPattern(_, _) => if (innerPat) 2 else 1
+          case _ =>
+            throw new NotImplementedError(s"Pattern $pattern not handled yet!")
+        }
+      }
+
+      me.cases.take(me.cases.indexOf(mc)).foldLeft(0)(
+        (acc, currCase) => acc + patCostRecur(currCase.pattern, false, false)) +
+        patCostRecur(mc.pattern, false, true)
+    }
+
+    Plus(costMatch, Plus(
+      Plus(InfiniteIntegerLiteral(totalCostOfMatchPatterns(me, mc)),
+        caseExprCost),
+      scrutineeCost))
+  }
+
+  def instrument(e: Expr, subInsts: Seq[Expr], funInvResVar: Option[Variable] = None)
+  	(implicit fd: FunDef, letIdMap: Map[Identifier,Identifier]): Expr = e match {
+    case t: Terminal => costOfExpr(t)
+    case _ =>
+      subInsts.foldLeft(costOfExpr(e) : Expr)(
+        (acc: Expr, subeTime: Expr) => Plus(subeTime, acc))
+  }
+
+  def instrumentIfThenElseExpr(e: IfExpr, condInst: Option[Expr],
+      thenInst: Option[Expr], elzeInst: Option[Expr]): (Expr, Expr) = {
+    val costIf = costOfExpr(e)
+    (Plus(costIf, Plus(condInst.get, thenInst.get)),
+      Plus(costIf, Plus(condInst.get, elzeInst.get)))
+  }
+}
\ No newline at end of file
diff --git a/src/main/scala/leon/verification/InjectAsserts.scala b/src/main/scala/leon/verification/InjectAsserts.scala
index 8244da31a..ffa8d13a0 100644
--- a/src/main/scala/leon/verification/InjectAsserts.scala
+++ b/src/main/scala/leon/verification/InjectAsserts.scala
@@ -21,7 +21,7 @@ object InjectAsserts extends LeonPhase[Program, Program] {
     }
 
     pgm.definedFunctions.foreach(fd => {
-      fd.body = fd.body.map(postMap { 
+      fd.body = fd.body.map(postMap {
         case e @ ArraySelect(a, i)        =>
           Some(Assert(indexUpTo(i, ArrayLength(a)), Some("Array index out of range"), e).setPos(e))
         case e @ ArrayUpdated(a, i, v)    =>
@@ -69,14 +69,14 @@ object InjectAsserts extends LeonPhase[Program, Program] {
                      ).setPos(e))
 
         case e @ RealDivision(_, d)  =>
-          Some(Assert(Not(Equals(d, RealLiteral(0))),
+          Some(Assert(Not(Equals(d, FractionalLiteral(0, 1))),
                       Some("Division by zero"),
                       e
                      ).setPos(e))
 
         case _ =>
           None
-      }) 
+      })
     })
 
     pgm
diff --git a/src/test/resources/regression/orb/combined/InsertionSort.scala b/src/test/resources/regression/orb/combined/InsertionSort.scala
new file mode 100644
index 000000000..8fd79a2e8
--- /dev/null
+++ b/src/test/resources/regression/orb/combined/InsertionSort.scala
@@ -0,0 +1,26 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object InsertionSort {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail:List) extends List
+  case class Nil() extends List
+
+  def size(l : List) : BigInt = (l match {
+    case Cons(_, xs) => 1 + size(xs)
+    case _ => 0
+  })
+
+  def sortedIns(e: BigInt, l: List): List = {
+    l match {
+      case Cons(x,xs) => if (x <= e) Cons(x,sortedIns(e, xs)) else Cons(e, l)
+      case _ => Cons(e,Nil())
+    }
+  } ensuring(res => size(res) == size(l) + 1 && tmpl((a,b) => time <= a*size(l) +b && depth <=  a*size(l) +b))
+
+  def sort(l: List): List = (l match {
+    case Cons(x,xs) => sortedIns(x, sort(xs))
+    case _ => Nil()
+
+  }) ensuring(res => size(res) == size(l) && tmpl((a,b) => time <= a*(size(l)*size(l)) +b && rec <= a*size(l) + b))
+}
diff --git a/src/test/resources/regression/orb/depth/BinaryTrie.scala b/src/test/resources/regression/orb/depth/BinaryTrie.scala
new file mode 100755
index 000000000..562ab19ea
--- /dev/null
+++ b/src/test/resources/regression/orb/depth/BinaryTrie.scala
@@ -0,0 +1,121 @@
+import leon.instrumentation._
+import leon.invariant._
+
+import scala.collection.immutable.Set
+
+object ParallelBinaryTrie {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(nvalue: BigInt, left: Tree, right: Tree) extends Tree
+
+  sealed abstract class IList
+  case class Cons(head: BigInt, tail: IList) extends IList
+  case class Nil() extends IList
+
+  def listSize(l: IList): BigInt = (l match {
+    case Nil() => 0
+    case Cons(x, xs) => 1 + listSize(xs)
+  })
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(x, l, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def find(inp: IList, t: Tree): Tree = {
+    inp match {
+      case Nil() => t
+      case Cons(x, Nil()) => t
+      case Cons(x, xs @ Cons(y, _)) => {
+        t match {
+          case Leaf() => t
+          case Node(v, l, r) => {
+            if (y > 0) find(xs, l) else find(xs, r)
+          }
+        }
+      }
+      case _ => t
+    }
+  } ensuring (res => true && tmpl ((a, c) => depth <= a * listSize(inp) + c))
+
+  def insert(inp: IList, t: Tree): Tree = {
+    t match {
+      case Leaf() => {
+        inp match {
+          case Nil() => t
+          case Cons(x, xs) => {
+            val newch = insert(xs, Leaf())
+            newch match {
+              case Leaf() => Node(x, Leaf(), Leaf())
+              case Node(y, _, _) => if (y > 0) Node(x, newch, Leaf()) else Node(y, Leaf(), newch)
+            }
+          }
+        }
+
+      }
+      case Node(v, l, r) => {
+        inp match {
+          case Nil() => t
+          case Cons(x, Nil()) => t
+          case Cons(x, xs @ Cons(y, _)) => {
+            val ch = if (y > 0) l else r
+            if (y > 0)
+              Node(v, insert(xs, ch), r)
+            else
+              Node(v, l, insert(xs, ch))
+          }
+          case _ => t
+        }
+      }
+    }
+  } ensuring (res => true && tmpl ((a, c) => depth <= a * listSize(inp) + c))
+
+  def create(inp: IList): Tree = {
+    insert(inp, Leaf())
+  } ensuring (res => true && tmpl ((a, c) => depth <= a * listSize(inp) + c))
+
+  def delete(inp: IList, t: Tree): Tree = {
+    t match {
+        case Leaf() => {
+          inp match {
+            case Nil() => Leaf()
+            case Cons(x ,xs) => {
+              //the input is not in the tree, so do nothing
+              Leaf()
+            }
+          }
+        }
+        case Node(v, l, r) => {
+          inp match {
+            case Nil() => {
+              //the tree has extensions of the input list so do nothing
+              t
+            }
+            case Cons(x, Nil()) => {
+              //if "l" and "r" are nil, remove the node
+              if(l == Leaf() && r == Leaf()) Leaf()
+              else t
+            }
+            case Cons(x ,xs@Cons(y, _)) => {
+              val ch = if(y > 0) l else r
+              val newch = delete(xs, ch)
+              if(newch == Leaf() && ((y > 0 && r == Leaf()) || (y <= 0 && l == Leaf()))) Leaf()
+              else {
+                if(y > 0)
+        		  Node(v, newch, r)
+        	    else
+        	      Node(v, l, newch)
+              }
+            }
+            case _ => t
+        }
+      }
+    }
+  } ensuring (res => true && tmpl ((a, c) => depth <= a * listSize(inp) + c))
+}
diff --git a/src/test/resources/regression/orb/depth/Folds.scala b/src/test/resources/regression/orb/depth/Folds.scala
new file mode 100755
index 000000000..305446be5
--- /dev/null
+++ b/src/test/resources/regression/orb/depth/Folds.scala
@@ -0,0 +1,82 @@
+import leon.instrumentation._
+import leon.invariant._
+
+
+object TreeMaps {
+
+  sealed abstract class Tree
+  case class Node(left: Tree, value: BigInt, right: Tree) extends Tree
+  case class Leaf() extends Tree
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def parallelSearch(elem : BigInt, t : Tree) : Boolean = {
+    t match {
+      case Leaf() => false
+      case Node(l, x, r) =>
+        if(x == elem) true
+        else {
+          val r1 = parallelSearch(elem, r)
+          val r2 = parallelSearch(elem, l)
+          if(r1 || r2) true
+          else false
+        }
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*height(t) + b))
+
+
+  def squareMap(t : Tree) : Tree = {
+    t match {
+      case Leaf() => t
+      case Node(l, x, r) =>
+        val nl = squareMap(l)
+        val nr = squareMap(r)
+        Node(nl, x*x, nr)
+    }
+  } ensuring (res => true && tmpl((a,b) => depth <= a*height(t) + b))
+
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def fact(n : BigInt) : BigInt = {
+    require(n >= 0)
+
+    if(n == 1 || n == 0) BigInt(1)
+    else n * fact(n-1)
+
+  } ensuring(res => tmpl((a,b) => depth <= a*n + b))
+
+  def descending(l: List, k: BigInt) : Boolean = {
+    l match {
+      case Nil() => true
+      case Cons(x, t) => x > 0 && x <= k && descending(t, x-1)
+    }
+  }
+
+  def factMap(l: List, k: BigInt): List = {
+    require(descending(l, k) && k >= 0)
+
+   l match {
+    case Nil() => Nil()
+    case Cons(x, t) =>  {
+      val f = fact(x)
+      Cons(f, factMap(t, x-1))
+    }
+
+  }} ensuring(res => true && tmpl((a,b) => depth <= a*k + b))
+}
\ No newline at end of file
diff --git a/src/test/resources/regression/orb/depth/ListOperations.scala b/src/test/resources/regression/orb/depth/ListOperations.scala
new file mode 100644
index 000000000..7d77ba834
--- /dev/null
+++ b/src/test/resources/regression/orb/depth/ListOperations.scala
@@ -0,0 +1,44 @@
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object ListOperations {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def append(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => Cons(x, append(xs, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => depth <= a*size(l1) + b))
+
+  def reverseRec(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => reverseRec(xs, Cons(x, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => depth <= a*size(l1) + b))
+
+  def reverse(l: List): List = {
+    reverseRec(l, Nil())
+
+  } ensuring (res => size(l) == size(res) && tmpl((a,b) => depth <= a*size(l) + b))
+
+  def remove(elem: BigInt, l: List): List = {
+    l match {
+      case Nil() => Nil()
+      case Cons(hd, tl) => if (hd == elem) remove(elem, tl) else Cons(hd, remove(elem, tl))
+    }
+  } ensuring (res => size(l) >= size(res) && tmpl((a,b) => depth <= a*size(l) + b))
+
+  def contains(list: List, elem: BigInt): Boolean = (list match {
+    case Nil() => false
+    case Cons(x, xs) => x == elem || contains(xs, elem)
+
+  }) ensuring (res => true && tmpl((a,b) => depth <= a*size(list) + b))
+}
diff --git a/src/test/resources/regression/orb/depth/PropLogicDepth.scala b/src/test/resources/regression/orb/depth/PropLogicDepth.scala
new file mode 100644
index 000000000..881cd61a4
--- /dev/null
+++ b/src/test/resources/regression/orb/depth/PropLogicDepth.scala
@@ -0,0 +1,112 @@
+import scala.collection.immutable.Set
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object PropLogicDepth {
+
+  sealed abstract class Formula
+  case class And(lhs: Formula, rhs: Formula) extends Formula
+  case class Or(lhs: Formula, rhs: Formula) extends Formula
+  case class Implies(lhs: Formula, rhs: Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Literal(id: BigInt) extends Formula
+  case class True() extends Formula
+  case class False() extends Formula
+
+  def max(x: BigInt,y: BigInt) = if (x >= y) x else y
+
+  def nestingDepth(f: Formula) : BigInt = (f match {
+    case And(lhs, rhs) => max(nestingDepth(lhs),nestingDepth(rhs)) + 1
+    case Or(lhs, rhs) => max(nestingDepth(lhs),nestingDepth(rhs)) + 1
+    case Implies(lhs, rhs) => max(nestingDepth(lhs),nestingDepth(rhs)) + 1
+    case Not(f) => nestingDepth(f) + 1
+    case _ => 1
+  })
+
+  def removeImplies(f: Formula): Formula = (f match {
+    case And(lhs, rhs) => And(removeImplies(lhs), removeImplies(rhs))
+    case Or(lhs, rhs) => Or(removeImplies(lhs), removeImplies(rhs))
+    case Implies(lhs, rhs) => Or(Not(removeImplies(lhs)),removeImplies(rhs))
+    case Not(f) => Not(removeImplies(f))
+    case _ => f
+
+  }) ensuring((res) => true && tmpl((a,b) => depth <= a*nestingDepth(f) + b))
+
+  def nnf(formula: Formula): Formula = (formula match {
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs) => Or(nnf(lhs), nnf(rhs))
+    case Implies(lhs, rhs) => Implies(nnf(lhs), nnf(rhs))
+    case Not(And(lhs, rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs, rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Implies(lhs, rhs)) => And(nnf(lhs), nnf(Not(rhs)))
+    case Not(Not(f)) => nnf(f)
+    case Not(Literal(_)) => formula
+    case Literal(_) => formula
+    case Not(True()) => False()
+    case Not(False()) => True()
+    case _ => formula
+  }) ensuring((res) => true && tmpl((a,b) => depth <= a*nestingDepth(formula) + b))
+
+  def isNNF(f: Formula): Boolean = { f match {
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Implies(lhs, rhs) => false
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case _ => true
+  }}  ensuring((res) => true && tmpl((a,b) => depth <= a*nestingDepth(f) + b))
+
+  def simplify(f: Formula): Formula = (f match {
+    case And(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs or rhs is false, return false
+      //if lhs is true return rhs
+      //if rhs is true return lhs
+      (sl,sr) match {
+        case (False(), _) => False()
+        case (_, False()) => False()
+        case (True(), _) => sr
+        case (_, True()) => sl
+        case _ => And(sl, sr)
+      }
+    }
+    case Or(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs or rhs is true, return true
+      //if lhs is false return rhs
+      //if rhs is false return lhs
+      (sl,sr) match {
+        case (True(), _) => True()
+        case (_, True()) => True()
+        case (False(), _) => sr
+        case (_, False()) => sl
+        case _ => Or(sl, sr)
+      }
+    }
+    case Implies(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs is false return true
+      //if rhs is true return true
+      //if lhs is true return rhs
+      //if rhs is false return Not(rhs)
+      (sl,sr) match {
+        case (False(), _) => True()
+        case (_, True()) => True()
+        case (True(), _) => sr
+        case (_, False()) => Not(sl)
+        case _ => Implies(sl, sr)
+      }
+    }
+    case Not(True()) => False()
+    case Not(False()) => True()
+    case _ => f
+
+  }) ensuring((res) => true && tmpl((a,b) => depth <= a*nestingDepth(f) + b))
+}
\ No newline at end of file
diff --git a/src/test/resources/regression/orb/numerical/ConcatVariationsAbs.scala b/src/test/resources/regression/orb/numerical/ConcatVariationsAbs.scala
new file mode 100644
index 000000000..bff880ab3
--- /dev/null
+++ b/src/test/resources/regression/orb/numerical/ConcatVariationsAbs.scala
@@ -0,0 +1,43 @@
+import leon.invariant._
+
+object ConcatVariationsAbs {
+  def genL(n: BigInt): BigInt = {
+    require(n >= 0)
+    if (n == 0)
+      BigInt(2)
+    else
+      4 + genL(n - 1)
+  } ensuring (res => tmpl((a, b) => res <= a * n + b))
+
+  def append(l1: BigInt, l2: BigInt): BigInt = {
+    require(l1 >= 0 && l2 >= 0)
+    if (l1 == 0)
+      BigInt(3)
+    else
+      append(l1 - 1, l2 + 1) + 5
+  } ensuring (res => tmpl((a, b) => res <= a * l1 + b))
+
+  def f_good(m: BigInt, n: BigInt): BigInt = {
+    require(0 <= m && 0 <= n)
+    if (m == 0) BigInt(2)
+    else {
+      val t1 = genL(n)
+      val t2 = f_good(m - 1, n)
+      val t3 = append(n, n * (m - 1))
+      (t1 + t2 + t3 + 6)
+    }
+
+  } ensuring (res => tmpl((a, b, c, d) => res <= a * (n * m) + b * n + c * m + d))
+
+  def f_worst(m: BigInt, n: BigInt): BigInt = {
+    require(0 <= m && 0 <= n)
+    if (m == 0) BigInt(2)
+    else {
+      val t1 = genL(n)
+      val t2 = f_worst(m - 1, n)
+      val t3 = append(n * (m - 1), n)
+      (t1 + t2 + t3 + 6)
+    }
+
+  } ensuring (res => tmpl((a, c, d, e, f) => res <= a * ((n * m) * m) + c * (n * m) + d * n + e * m + f))
+}
diff --git a/src/test/resources/regression/orb/numerical/QueueAbs.scala b/src/test/resources/regression/orb/numerical/QueueAbs.scala
new file mode 100644
index 000000000..a7aee3a93
--- /dev/null
+++ b/src/test/resources/regression/orb/numerical/QueueAbs.scala
@@ -0,0 +1,70 @@
+import leon.invariant._
+
+object AmortizedQueue {
+  def concat(l1: BigInt, l2: BigInt): BigInt = {
+    require(l1 >= 0 && l2 >= 0)
+    if (l1 == 0)
+      BigInt(3)
+    else
+      concat(l1 - 1, l2 + 1) + 5
+  } ensuring (res => tmpl((a, b) => res <= a * l1 + b))
+
+  def reverseRec(l1: BigInt, l2: BigInt): BigInt = {
+    require(l1 >= 0 && l2 >= 0)
+    if (l1 == 0)
+      BigInt(3)
+    else {
+      reverseRec(l1 - 1, l2 + 1) + 6
+    }
+  } ensuring (res => tmpl((a, b) => res <= a * l1 + b))
+
+  def reverse(l: BigInt): BigInt = {
+    require(l >= 0)
+    reverseRec(l, 0) + 1
+  } ensuring (res => tmpl((a, b) => res <= a * l + b))
+
+  def create(front: BigInt, rear: BigInt): BigInt = {
+    require(front >= 0 && rear >= 0)
+    if (rear <= front)
+      BigInt(4)
+    else {
+      val t1 = reverse(rear)
+      val t2 = concat(front, rear)
+      t1 + t2 + 7
+    }
+  }
+
+  def enqueue(q: BigInt, front: BigInt, rear: BigInt): BigInt = {
+    require(q == front + rear && q >= 0 && front >= 0 && rear >= 0)
+    create(front, rear) + 5
+  } ensuring (res => tmpl((a, b) => res <= a * q + b))
+
+  def dequeue(q: BigInt, front: BigInt, rear: BigInt): BigInt = {
+    require(q == front + rear && q >= 1 && front >= rear && rear >= 0)
+    if (front >= 1) {
+      create(front - 1, rear) + 4
+    } else {
+      //since front should be greater than rear, here rear should be 0 as well
+      BigInt(5)
+    }
+  } ensuring (res => tmpl((a, b) => res <= a * q + b))
+
+  def removeLast(l: BigInt): BigInt = {
+    require(l >= 1)
+    if (l == 1) {
+      BigInt(4)
+    } else {
+      removeLast(l - 1) + 6
+    }
+  } ensuring (res => tmpl((a, b) => res <= a * l + b))
+
+  def pop(q: BigInt, front: BigInt, rear: BigInt): BigInt = {
+    require(q == front + rear && q >= 1 && front >= rear && rear >= 0)
+    if (rear >= 1) {
+      BigInt(3)
+    } else {
+      val t1 = removeLast(front)
+      t1 + 5
+    }
+  } ensuring (res => tmpl((a, b) => res <= a * q + b))
+}
diff --git a/src/test/resources/regression/orb/numerical/SimpleLoop.scala b/src/test/resources/regression/orb/numerical/SimpleLoop.scala
new file mode 100755
index 000000000..6a2cdb3d9
--- /dev/null
+++ b/src/test/resources/regression/orb/numerical/SimpleLoop.scala
@@ -0,0 +1,9 @@
+object SimpleLoop
+{
+	def s(x: BigInt) : BigInt = {
+	  if(x < 0)
+	    BigInt(0)
+	  else
+	    s(x-1) + 1
+	} ensuring(res => res != -1)
+}
\ No newline at end of file
diff --git a/src/test/resources/regression/orb/numerical/see-saw.scala b/src/test/resources/regression/orb/numerical/see-saw.scala
new file mode 100644
index 000000000..894a8caed
--- /dev/null
+++ b/src/test/resources/regression/orb/numerical/see-saw.scala
@@ -0,0 +1,15 @@
+object SeeSaw {
+  def s(x: BigInt, y: BigInt, z: BigInt): BigInt = {
+    require(y >= 0)
+
+    if (x >= 100) {
+      y
+    } else if (x <= z) { //some condition
+      s(x + 1, y + 2, z)
+    } else if (x <= z + 9) { //some condition
+      s(x + 1, y + 3, z)
+    } else {
+      s(x + 2, y + 1, z)
+    }
+  } ensuring (res => (100 - x <= 2 * res))
+}
\ No newline at end of file
diff --git a/src/test/resources/regression/orb/stack/BinaryTrie.scala b/src/test/resources/regression/orb/stack/BinaryTrie.scala
new file mode 100644
index 000000000..f2dfd876c
--- /dev/null
+++ b/src/test/resources/regression/orb/stack/BinaryTrie.scala
@@ -0,0 +1,120 @@
+import leon.invariant._
+import leon.instrumentation._
+//import scala.collection.immutable.Set
+
+object BinaryTrie {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(nvalue: BigInt, left: Tree, right: Tree) extends Tree
+
+  sealed abstract class IList
+  case class Cons(head: BigInt, tail: IList) extends IList
+  case class Nil() extends IList
+
+  def listSize(l: IList): BigInt = (l match {
+    case Nil() => 0
+    case Cons(x, xs) => 1 + listSize(xs)
+  })
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(x, l, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def find(inp: IList, t: Tree): Tree = {
+    inp match {
+      case Nil() => t
+      case Cons(x, Nil()) => t
+      case Cons(x, xs @ Cons(y, _)) => {
+        t match {
+          case Leaf() => t
+          case Node(v, l, r) => {
+            if (y > 0) find(xs, l) else find(xs, r)
+          }
+        }
+      }
+      case _ => t
+    }
+  } ensuring (_ => stack <= ? * listSize(inp) + ?)
+
+  def insert(inp: IList, t: Tree): Tree = {
+    t match {
+      case Leaf() => {
+        inp match {
+          case Nil() => t
+          case Cons(x, xs) => {
+            val newch = insert(xs, Leaf())
+            newch match {
+              case Leaf() => Node(x, Leaf(), Leaf())
+              case Node(y, _, _) => if (y > 0) Node(x, newch, Leaf()) else Node(y, Leaf(), newch)
+            }
+          }
+        }
+
+      }
+      case Node(v, l, r) => {
+        inp match {
+          case Nil() => t
+          case Cons(x, Nil()) => t
+          case Cons(x, xs @ Cons(y, _)) => {
+            val ch = if (y > 0) l else r
+            if (y > 0)
+              Node(v, insert(xs, ch), r)
+            else
+              Node(v, l, insert(xs, ch))
+          }
+          case _ => t
+        }
+      }
+    }
+  } ensuring (_ => stack <= ? * listSize(inp) + ?)
+
+  def create(inp: IList): Tree = {
+    insert(inp, Leaf())
+  } ensuring (_ => stack <= ? * listSize(inp) + ?)
+
+  def delete(inp: IList, t: Tree): Tree = {
+    t match {
+        case Leaf() => {
+          inp match {
+            case Nil() => Leaf()
+            case Cons(x ,xs) => {
+              //the input is not in the tree, so do nothing
+              Leaf()
+            }
+          }
+        }
+        case Node(v, l, r) => {
+          inp match {
+            case Nil() => {
+              //the tree has extensions of the input list so do nothing
+              t
+            }
+            case Cons(x, Nil()) => {
+              //if "l" and "r" are nil, remove the node
+              if(l == Leaf() && r == Leaf()) Leaf()
+              else t
+            }
+            case Cons(x ,xs@Cons(y, _)) => {
+              val ch = if(y > 0) l else r
+              val newch = delete(xs, ch)
+              if(newch == Leaf() && ((y > 0 && r == Leaf()) || (y <= 0 && l == Leaf()))) Leaf()
+              else {
+                if(y > 0)
+        		  Node(v, newch, r)
+        	    else
+        	      Node(v, l, newch)
+              }
+            }
+            case _ => t
+        }
+      }
+    }
+  } ensuring (_ => stack <= ? * listSize(inp) + ?)
+}
diff --git a/src/test/resources/regression/orb/stack/ListOperations.scala b/src/test/resources/regression/orb/stack/ListOperations.scala
new file mode 100644
index 000000000..3ae4a2d17
--- /dev/null
+++ b/src/test/resources/regression/orb/stack/ListOperations.scala
@@ -0,0 +1,35 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object ListOperations {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def reverseRec(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => reverseRec(xs, Cons(x, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => stack <= a*size(l1) + b))
+
+  def contains(list: List, elem: BigInt): Boolean = (list match {
+    case Nil() => false
+    case Cons(x, xs) => x == elem || contains(xs, elem)
+
+  }) ensuring (res => tmpl((a,b) => stack <= a*size(list) + b))
+
+  def distinct(l: List): List = (
+    l match {
+      case Nil() => Nil()
+      case Cons(x, xs) => {
+        val newl = distinct(xs)
+        if (contains(newl, x)) newl
+        else Cons(x, newl)
+      }
+   }) ensuring (res => size(l) >= size(res) && tmpl((a,b) => stack <= a*size(l) + b))
+}
diff --git a/src/test/resources/regression/orb/stack/SpeedBenchmarks.scala b/src/test/resources/regression/orb/stack/SpeedBenchmarks.scala
new file mode 100644
index 000000000..c1c59d592
--- /dev/null
+++ b/src/test/resources/regression/orb/stack/SpeedBenchmarks.scala
@@ -0,0 +1,75 @@
+import leon.invariant._
+import leon.instrumentation._
+import leon.math._
+
+object SpeedBenchmarks {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  sealed abstract class StringBuffer
+  case class Chunk(str: List, next: StringBuffer) extends StringBuffer
+  case class Empty() extends StringBuffer
+
+  def length(sb: StringBuffer) : BigInt = sb match {
+    case Chunk(_, next) => 1 + length(next)
+    case _ => 0
+  }
+
+  def sizeBound(sb: StringBuffer, k: BigInt) : Boolean ={
+    sb match {
+      case Chunk(str, next) => size(str) <= k && sizeBound(next, k)
+      case _ => 0 <= k
+    }
+  }
+
+  def sizeBuffer(sb: StringBuffer): BigInt = {
+    sb match {
+      case Chunk(str, next) => size(str) + sizeBuffer(sb)
+      case Empty() => 0
+    }
+  }
+
+  /**
+   * Fig. 1 of SPEED, POPL'09: The functional version of the implementation.
+   * Equality check of two string buffers
+   */
+  def Equals(str1: List, str2: List, s1: StringBuffer, s2: StringBuffer, k: BigInt) : Boolean = {
+    require(sizeBound(s1, k) && sizeBound(s2, k) && size(str1) <= k && size(str2) <= k && k >= 0)
+
+    (str1, str2) match {
+      case (Cons(h1,t1), Cons(h2,t2)) => {
+        if(h1 != h2) false
+        else Equals(t1,t2, s1,s2, k)
+      }
+      case (Cons(_,_), Nil()) => {
+        //load from s2
+        s2 match {
+          case Chunk(str, next) => Equals(str1, str, s1, next, k)
+          case Empty() => false
+        }
+      }
+      case (Nil(), Cons(_,_)) => {
+        //load from s1
+        s1 match {
+          case Chunk(str, next) => Equals(str, str2, next, s2, k)
+          case Empty() => false
+        }
+      }
+      case _ =>{
+        //load from both
+        (s1,s2) match {
+          case (Chunk(nstr1, next1),Chunk(nstr2, next2)) => Equals(nstr1, nstr2, next1, next2, k)
+          case (Empty(),Chunk(nstr2, next2)) => Equals(str1, nstr2, s1, next2, k)
+          case (Chunk(nstr1, next1), Empty()) => Equals(nstr1, str2, next1, s2, k)
+          case _ => true
+        }
+      }
+    }
+  } ensuring(res => tmpl((a,b,c,d,e) => stack <= a*max(sizeBuffer(s1), sizeBuffer(s2)) + c*(k+1) + e))
+}
diff --git a/src/test/resources/regression/orb/timing/BinaryTrie.scala b/src/test/resources/regression/orb/timing/BinaryTrie.scala
new file mode 100644
index 000000000..a1de6ee0e
--- /dev/null
+++ b/src/test/resources/regression/orb/timing/BinaryTrie.scala
@@ -0,0 +1,119 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object BinaryTrie {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(nvalue: BigInt, left: Tree, right: Tree) extends Tree
+
+  sealed abstract class IList
+  case class Cons(head: BigInt, tail: IList) extends IList
+  case class Nil() extends IList
+
+  def listSize(l: IList): BigInt = (l match {
+    case Nil() => 0
+    case Cons(x, xs) => 1 + listSize(xs)
+  })
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(x, l, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def find(inp: IList, t: Tree): Tree = {
+    inp match {
+      case Nil() => t
+      case Cons(x, Nil()) => t
+      case Cons(x, xs @ Cons(y, _)) => {
+        t match {
+          case Leaf() => t
+          case Node(v, l, r) => {
+            if (y > 0) find(xs, l) else find(xs, r)
+          }
+        }
+      }
+      case _ => t
+    }
+  } ensuring (_ => time <= ? * listSize(inp) + ?)
+
+  def insert(inp: IList, t: Tree): Tree = {
+    t match {
+      case Leaf() => {
+        inp match {
+          case Nil() => t
+          case Cons(x, xs) => {
+            val newch = insert(xs, Leaf())
+            newch match {
+              case Leaf() => Node(x, Leaf(), Leaf())
+              case Node(y, _, _) => if (y > 0) Node(x, newch, Leaf()) else Node(y, Leaf(), newch)
+            }
+          }
+        }
+
+      }
+      case Node(v, l, r) => {
+        inp match {
+          case Nil() => t
+          case Cons(x, Nil()) => t
+          case Cons(x, xs @ Cons(y, _)) => {
+            val ch = if (y > 0) l else r
+            if (y > 0)
+              Node(v, insert(xs, ch), r)
+            else
+              Node(v, l, insert(xs, ch))
+          }
+          case _ => t
+        }
+      }
+    }
+  } ensuring (_ => time <= ? * listSize(inp) + ?)
+
+  def create(inp: IList): Tree = {
+    insert(inp, Leaf())
+  } ensuring (res => true && tmpl((a, c) => time <= a * listSize(inp) + c))
+
+  def delete(inp: IList, t: Tree): Tree = {
+    t match {
+        case Leaf() => {
+          inp match {
+            case Nil() => Leaf()
+            case Cons(x ,xs) => {
+              //the input is not in the tree, so do nothing
+              Leaf()
+            }
+          }
+        }
+        case Node(v, l, r) => {
+          inp match {
+            case Nil() => {
+              //the tree has extensions of the input list so do nothing
+              t
+            }
+            case Cons(x, Nil()) => {
+              //if "l" and "r" are nil, remove the node
+              if(l == Leaf() && r == Leaf()) Leaf()
+              else t
+            }
+            case Cons(x ,xs@Cons(y, _)) => {
+              val ch = if(y > 0) l else r
+              val newch = delete(xs, ch)
+              if(newch == Leaf() && ((y > 0 && r == Leaf()) || (y <= 0 && l == Leaf()))) Leaf()
+              else {
+                if(y > 0)
+        		  Node(v, newch, r)
+        	    else
+        	      Node(v, l, newch)
+              }
+            }
+            case _ => t
+        }
+      }
+    }
+  } ensuring (_ => time <= ? * listSize(inp) + ?)
+}
diff --git a/src/test/resources/regression/orb/timing/BinomialHeap.scala b/src/test/resources/regression/orb/timing/BinomialHeap.scala
new file mode 100644
index 000000000..81b990d41
--- /dev/null
+++ b/src/test/resources/regression/orb/timing/BinomialHeap.scala
@@ -0,0 +1,181 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object BinomialHeap {
+  //sealed abstract class TreeNode
+  case class TreeNode(rank: BigInt, elem: Element, children: BinomialHeap)
+  case class Element(n: BigInt)
+
+  sealed abstract class BinomialHeap
+  case class ConsHeap(head: TreeNode, tail: BinomialHeap) extends BinomialHeap
+  case class NilHeap() extends BinomialHeap
+
+  sealed abstract class List
+  case class NodeL(head: BinomialHeap, tail: List) extends List
+  case class NilL() extends List
+
+  sealed abstract class OptionalTree
+  case class Some(t : TreeNode) extends OptionalTree
+  case class None() extends OptionalTree
+
+  /* Lower or Equal than for Element structure */
+  private def leq(a: Element, b: Element) : Boolean = {
+    a match {
+      case Element(a1) => {
+        b match {
+          case Element(a2) => {
+            if(a1 <= a2) true
+            else false
+          }
+        }
+      }
+    }
+  }
+
+  /* isEmpty function of the Binomial Heap */
+  def isEmpty(t: BinomialHeap) = t match {
+    case ConsHeap(_,_) => false
+    case _ => true
+  }
+
+  /* Helper function to determine rank of a TreeNode */
+  def rank(t: TreeNode) : BigInt = t.rank /*t match {
+    case TreeNode(r, _, _) => r
+  }*/
+
+  /* Helper function to get the root element of a TreeNode */
+  def root(t: TreeNode) : Element = t.elem /*t match {
+    case TreeNode(_, e, _) => e
+  }*/
+
+  /* Linking trees of equal ranks depending on the root element */
+  def link(t1: TreeNode, t2: TreeNode): TreeNode = {
+    if (leq(t1.elem, t2.elem)) {
+      TreeNode(t1.rank + 1, t1.elem, ConsHeap(t2, t1.children))
+    } else {
+      TreeNode(t1.rank + 1, t2.elem, ConsHeap(t1, t2.children))
+    }
+  }
+
+  def treeNum(h: BinomialHeap) : BigInt = {
+    h match {
+      case ConsHeap(head, tail) =>  1 + treeNum(tail)
+      case _ => 0
+    }
+  }
+
+  /* Insert a tree into a binomial heap. The tree should be correct in relation to the heap */
+  def insTree(t: TreeNode, h: BinomialHeap) : BinomialHeap = {
+    h match {
+      case ConsHeap(head, tail) =>  {
+        if (rank(t) < rank(head)) {
+          ConsHeap(t, h)
+        } else if (rank(t) > rank(head)) {
+          ConsHeap(head, insTree(t,tail))
+        } else {
+          insTree(link(t,head), tail)
+        }
+      }
+      case _ => ConsHeap(t, NilHeap())
+    }
+  } ensuring(_ => time <= ? * treeNum(h) + ?)
+
+  /* Merge two heaps together */
+  def merge(h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    h1 match {
+      case ConsHeap(head1, tail1) => {
+        h2 match {
+          case ConsHeap(head2, tail2) => {
+            if (rank(head1) < rank(head2)) {
+              ConsHeap(head1, merge(tail1, h2))
+            } else if (rank(head2) < rank(head1)) {
+              ConsHeap(head2, merge(h1, tail2))
+            } else {
+              mergeWithCarry(link(head1, head2), tail1, tail2)
+            }
+          }
+          case _ => h1
+        }
+      }
+      case _ => h2
+    }
+  } ensuring(_ => time <= ? * treeNum(h1) + ? * treeNum(h2) + ?)
+
+  def mergeWithCarry(t: TreeNode, h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    h1 match {
+      case ConsHeap(head1, tail1) => {
+        h2 match {
+          case ConsHeap(head2, tail2) => {
+            if (rank(head1) < rank(head2)) {
+
+              if (rank(t) < rank(head1))
+                ConsHeap(t, ConsHeap(head1, merge(tail1, h2)))
+              else
+                mergeWithCarry(link(t, head1), tail1, h2)
+
+            } else if (rank(head2) < rank(head1)) {
+
+              if (rank(t) < rank(head2))
+                ConsHeap(t, ConsHeap(head2, merge(h1, tail2)))
+              else
+                mergeWithCarry(link(t, head2), h1, tail2)
+
+            } else {
+              ConsHeap(t, mergeWithCarry(link(head1, head2), tail1, tail2))
+            }
+          }
+          case _ => {
+            insTree(t, h1)
+          }
+        }
+      }
+      case _ => insTree(t, h2)
+    }
+  } ensuring (_ => time <= ? * treeNum(h1) + ? * treeNum(h2) + ?)
+
+  //Auxiliary helper function to simplefy findMin and deleteMin
+  def removeMinTree(h: BinomialHeap): (OptionalTree, BinomialHeap) = {
+    h match {
+      case ConsHeap(head, NilHeap()) => (Some(head), NilHeap())
+      case ConsHeap(head1, tail1) => {
+        val (opthead2, tail2) = removeMinTree(tail1)
+        opthead2 match {
+          case Some(head2) =>
+            if (leq(root(head1), root(head2))) {
+              (Some(head1), tail1)
+            } else {
+              (Some(head2), ConsHeap(head1, tail2))
+            }
+          case _ => (Some(head1), tail1)
+        }
+      }
+      case _ => (None(), NilHeap())
+    }
+  } ensuring (res => treeNum(res._2) <= treeNum(h) && time <= ? * treeNum(h) + ?)
+
+  /*def findMin(h: BinomialHeap) : Element = {
+	  val (opt, _) = removeMinTree(h)
+	  opt match {
+	    case Some(TreeNode(_,e,ts1)) => e
+	    case _ => Element(-1)
+	  }
+  } ensuring(res => true && tmpl((a,b) => time <= a*treeNum(h) + b))*/
+
+  def minTreeChildren(h: BinomialHeap) : BigInt = {
+    val (min, _) = removeMinTree(h)
+    min match {
+      case Some(TreeNode(_,_,ch)) => treeNum(ch)
+      case _ => 0
+	  }
+  }
+
+  // Discard the minimum element of the extracted min tree and put its children back into the heap
+  def deleteMin(h: BinomialHeap) : BinomialHeap = {
+	  val (min, ts2) = removeMinTree(h)
+	  min match {
+		case Some(TreeNode(_,_,ts1)) => merge(ts1, ts2)
+		case _ => h
+	  }
+  } ensuring(_ => time <= ? * minTreeChildren(h) + ? * treeNum(h) + ?)
+
+}
diff --git a/src/test/resources/regression/orb/timing/ConcatVariations.scala b/src/test/resources/regression/orb/timing/ConcatVariations.scala
new file mode 100644
index 000000000..a94fb418a
--- /dev/null
+++ b/src/test/resources/regression/orb/timing/ConcatVariations.scala
@@ -0,0 +1,42 @@
+import leon.invariant._
+import leon.instrumentation._
+
+
+object ConcatVariations {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def genL(n: BigInt): List = {
+    require(n >= 0)
+    if (n == 0) Nil()
+    else
+      Cons(n, genL(n - 1))
+  } ensuring (res => size(res) == n && tmpl((a,b) => time <= a*n + b))
+
+  def append(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => Cons(x, append(xs, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => time <= a*size(l1) + b))
+
+  def f_good(m: BigInt, n: BigInt): List = {
+    require(0 <= m && 0 <= n)
+    if (m == 0) Nil()
+    else append(genL(n), f_good(m - 1, n))
+
+  } ensuring(res => size(res) == n*m && tmpl((a,b,c,d) => time <= a*(n*m) + b*n + c*m +d))
+
+  def f_worst(m: BigInt, n: BigInt): List = {
+    require(0 <= m && 0 <= n)
+
+    if (m == 0) Nil()
+    else append(f_worst(m - 1, n), genL(n))
+
+  } ensuring(res => size(res) == n*m && tmpl((a,c,d,e,f) => time <= a*((n*m)*m)+c*(n*m)+d*n+e*m+f))
+}
diff --git a/src/test/resources/regression/orb/timing/ListOperations.scala b/src/test/resources/regression/orb/timing/ListOperations.scala
new file mode 100644
index 000000000..13b031b4d
--- /dev/null
+++ b/src/test/resources/regression/orb/timing/ListOperations.scala
@@ -0,0 +1,40 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object ListOperations {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def append(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => Cons(x, append(xs, l2))
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => time <= a*size(l1) + b))
+
+  def remove(elem: BigInt, l: List): List = {
+    l match {
+      case Nil() => Nil()
+      case Cons(hd, tl) => if (hd == elem) remove(elem, tl) else Cons(hd, remove(elem, tl))
+    }
+  } ensuring (res => size(l) >= size(res) && tmpl((a,b) => time <= a*size(l) + b))
+
+  def contains(list: List, elem: BigInt): Boolean = (list match {
+    case Nil() => false
+    case Cons(x, xs) => x == elem || contains(xs, elem)
+  }) ensuring (res => true && tmpl((a,b) => time <= a*size(list) + b))
+
+  def distinct(l: List): List = (
+    l match {
+      case Nil() => Nil()
+      case Cons(x, xs) => {
+        val newl = distinct(xs)
+        if (contains(newl, x)) newl
+        else Cons(x, newl)
+      }
+   }) ensuring (res => size(l) >= size(res) && tmpl((a,b) => time <= a*(size(l)*size(l)) + b))
+}
diff --git a/src/test/resources/regression/orb/timing/PropositionalLogic.scala b/src/test/resources/regression/orb/timing/PropositionalLogic.scala
new file mode 100644
index 000000000..22dfdcdec
--- /dev/null
+++ b/src/test/resources/regression/orb/timing/PropositionalLogic.scala
@@ -0,0 +1,115 @@
+import scala.collection.immutable.Set
+import leon.invariant._
+import leon.instrumentation._
+
+object PropositionalLogic {
+
+  sealed abstract class Formula
+  case class And(lhs: Formula, rhs: Formula) extends Formula
+  case class Or(lhs: Formula, rhs: Formula) extends Formula
+  case class Implies(lhs: Formula, rhs: Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Literal(id: BigInt) extends Formula
+  case class True() extends Formula
+  case class False() extends Formula
+
+  case class Pair(f: Formula, b: Boolean)
+
+  sealed abstract class List
+  case class Cons(x: Pair, xs: List) extends List
+  case class Nil() extends List
+
+  def size(f : Formula) : BigInt = (f match {
+    case And(lhs, rhs) => size(lhs) + size(rhs) + 1
+    case Or(lhs, rhs) => size(lhs) + size(rhs) + 1
+    case Implies(lhs, rhs) => size(lhs) + size(rhs) + 1
+    case Not(f) => size(f) + 1
+    case _ => 1
+  })
+
+  def removeImplies(f: Formula): Formula = (f match {
+    case And(lhs, rhs) => And(removeImplies(lhs), removeImplies(rhs))
+    case Or(lhs, rhs) => Or(removeImplies(lhs), removeImplies(rhs))
+    case Implies(lhs, rhs) => Or(Not(removeImplies(lhs)),removeImplies(rhs))
+    case Not(f) => Not(removeImplies(f))
+    case _ => f
+
+  }) ensuring(_ => time <= ? * size(f) + ?)
+
+  def nnf(formula: Formula): Formula = (formula match {
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs) => Or(nnf(lhs), nnf(rhs))
+    case Implies(lhs, rhs) => Implies(nnf(lhs), nnf(rhs))
+    case Not(And(lhs, rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs, rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Implies(lhs, rhs)) => And(nnf(lhs), nnf(Not(rhs)))
+    case Not(Not(f)) => nnf(f)
+    case Not(Literal(_)) => formula
+    case Literal(_) => formula
+    case Not(True()) => False()
+    case Not(False()) => True()
+    case _ => formula
+  }) ensuring(_ => time <= ? * size(formula) + ?)
+
+  def isNNF(f: Formula): Boolean = { f match {
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Implies(lhs, rhs) => false
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case _ => true
+  }} ensuring(_ => time <= ? * size(f) + ?)
+
+  def simplify(f: Formula): Formula = (f match {
+    case And(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs or rhs is false, return false
+      //if lhs is true return rhs
+      //if rhs is true return lhs
+      (sl,sr) match {
+        case (False(), _) => False()
+        case (_, False()) => False()
+        case (True(), _) => sr
+        case (_, True()) => sl
+        case _ => And(sl, sr)
+      }
+    }
+    case Or(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs or rhs is true, return true
+      //if lhs is false return rhs
+      //if rhs is false return lhs
+      (sl,sr) match {
+        case (True(), _) => True()
+        case (_, True()) => True()
+        case (False(), _) => sr
+        case (_, False()) => sl
+        case _ => Or(sl, sr)
+      }
+    }
+    case Implies(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs is false return true
+      //if rhs is true return true
+      //if lhs is true return rhs
+      //if rhs is false return Not(rhs)
+      (sl,sr) match {
+        case (False(), _) => True()
+        case (_, True()) => True()
+        case (True(), _) => sr
+        case (_, False()) => Not(sl)
+        case _ => Implies(sl, sr)
+      }
+    }
+    case Not(True()) => False()
+    case Not(False()) => True()
+    case _ => f
+
+  }) ensuring(_ => time <= ? *size(f) + ?)
+}
diff --git a/src/test/resources/regression/orb/timing/SimpleMap.scala b/src/test/resources/regression/orb/timing/SimpleMap.scala
new file mode 100644
index 000000000..86e2c7b7b
--- /dev/null
+++ b/src/test/resources/regression/orb/timing/SimpleMap.scala
@@ -0,0 +1,25 @@
+import leon.instrumentation._
+import leon.invariant._
+
+object SimpleMap {
+  sealed abstract class List
+  case class Cons(head: (BigInt, BigInt), tail: List) extends List
+  case class Nil() extends List
+
+  def size(l : List) : BigInt = (l match {
+    case Cons(_, xs) => 1 + size(xs)
+    case _ => 0
+  })
+
+  def insert(l: List, key: BigInt, value: BigInt): List = {
+    Cons((key, value), l)
+  } ensuring(res => tmpl((a) => time <= a))
+
+  def getOrElse(l: List, key: BigInt, elseValue: BigInt): BigInt = {
+    l match {
+      case Nil() => elseValue
+      case Cons((currKey, currValue), _) if (currKey == key) => currValue
+      case Cons(_, tail) => getOrElse(tail, key, elseValue)
+    }
+  } ensuring(res => tmpl((a, b) => time <= a*size(l) + b))
+}
\ No newline at end of file
diff --git a/src/test/scala/leon/regression/orb/OrbInstrumentationTestSuite.scala b/src/test/scala/leon/regression/orb/OrbInstrumentationTestSuite.scala
new file mode 100644
index 000000000..b6a7d60f0
--- /dev/null
+++ b/src/test/scala/leon/regression/orb/OrbInstrumentationTestSuite.scala
@@ -0,0 +1,48 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.regression.orb
+import leon.test._
+import leon._
+import leon.purescala.Definitions._
+import leon.invariant.engine._
+import leon.transformations._
+import java.io.File
+import leon.purescala.Types.TupleType
+
+class OrbInstrumentationTestSuite extends LeonRegressionSuite {
+
+  test("TestInstrumentation") {
+    val ctx = createLeonContext("--inferInv", "--minbounds", "--timeout=" + 10)
+    val testFilename = toTempFile(
+      """
+	import leon.annotation._
+	import leon.invariant._
+	import leon.instrumentation._
+
+	object Test {
+	  sealed abstract class List
+	  case class Cons(tail: List) extends List
+	  case class Nil() extends List
+
+	  // proved with unrolling=0
+	  def size(l: List) : BigInt = (l match {
+	      case Nil() => BigInt(0)
+	      case Cons(t) => 1 + size(t)
+	  }) ensuring(res => tmpl(a => time <= a))
+	}""")
+    val beginPipe = leon.frontends.scalac.ExtractionPhase andThen
+      new leon.utils.PreprocessingPhase
+    val program = beginPipe.run(ctx)(testFilename)
+    val processPipe = InstrumentationPhase
+    // check properties.
+    val instProg = processPipe.run(ctx)(program)
+    val sizeFun = instProg.definedFunctions.find(_.id.name.startsWith("size"))
+    if(!sizeFun.isDefined || !sizeFun.get.returnType.isInstanceOf[TupleType])
+      fail("Error in instrumentation")
+  }
+
+  def toTempFile(content: String): List[String] = {
+    val pipeline = leon.utils.TemporaryInputPhase
+    pipeline.run(createLeonContext())((List(content), Nil))
+  }
+}
diff --git a/src/test/scala/leon/regression/orb/OrbRegressionSuite.scala b/src/test/scala/leon/regression/orb/OrbRegressionSuite.scala
new file mode 100644
index 000000000..5d6f7c0e7
--- /dev/null
+++ b/src/test/scala/leon/regression/orb/OrbRegressionSuite.scala
@@ -0,0 +1,63 @@
+/* Copyright 2009-2015 EPFL, Lausanne */
+
+package leon.regression.orb
+import leon.test._
+
+import leon._
+import leon.purescala.Definitions._
+import leon.invariant.engine._
+import leon.transformations._
+
+import java.io.File
+
+class OrbRegressionSuite extends LeonRegressionSuite {
+  private def forEachFileIn(path: String)(block: File => Unit) {
+    val fs = filesInResourceDir(path, _.endsWith(".scala"))
+    for (f <- fs) {
+      block(f)
+    }
+  }
+
+  private def testInference(f: File, bound: Int) {
+
+    val ctx = createLeonContext("--inferInv", "--minbounds", "--timeout="+bound)
+    val beginPipe = leon.frontends.scalac.ExtractionPhase andThen
+      new leon.utils.PreprocessingPhase
+    val program = beginPipe.run(ctx)(f.getAbsolutePath :: Nil)
+    val processPipe = InstrumentationPhase andThen InferInvariantsPhase
+    val report = processPipe.run(ctx)(program)
+    val fails = report.conditions.filterNot(_.invariant.isDefined)
+    if (!fails.isEmpty)
+      fail(s"Inference failed for functions ${fails.map(_.fd).mkString("\n")}")
+  }
+
+  forEachFileIn("regression/orb/timing") { f =>
+    test("Timing: " + f.getName) {
+      testInference(f, 50)
+    }
+  }
+
+  forEachFileIn("regression/orb/stack/") { f =>
+    test("Stack: " + f.getName) {
+      testInference(f, 50)
+    }
+  }
+
+  forEachFileIn("regression/orb//depth") { f =>
+    test("Depth: " + f.getName) {
+      testInference(f, 50)
+    }
+  }
+
+  forEachFileIn("regression/orb/numerical") { f =>
+    test("Numerical: " + f.getName) {
+      testInference(f, 50)
+    }
+  }
+
+  forEachFileIn("regression/orb/combined/") { f =>
+    test("Multiple Instrumentations: " + f.getName) {
+      testInference(f, 50)
+    }
+  }
+}
diff --git a/src/test/scala/leon/test/helpers/ExpressionsDSL.scala b/src/test/scala/leon/test/helpers/ExpressionsDSL.scala
index 08ab65881..74cd84c2c 100644
--- a/src/test/scala/leon/test/helpers/ExpressionsDSL.scala
+++ b/src/test/scala/leon/test/helpers/ExpressionsDSL.scala
@@ -16,7 +16,7 @@ trait ExpressionsDSL {
   def bi(x: Int)    = InfiniteIntegerLiteral(x)
   def b(x: Boolean) = BooleanLiteral(x)
   def i(x: Int)     = IntLiteral(x)
-  def r(x: Double)  = RealLiteral(BigDecimal(x))
+  def r(n: BigInt, d: BigInt)  = FractionalLiteral(n, d)
 
   val a = FreshIdentifier("a", Int32Type).toVariable
   val b = FreshIdentifier("b", Int32Type).toVariable
diff --git a/src/test/scala/leon/unit/evaluators/EvaluatorSuite.scala b/src/test/scala/leon/unit/evaluators/EvaluatorSuite.scala
index a18a0dca2..4d97487f6 100644
--- a/src/test/scala/leon/unit/evaluators/EvaluatorSuite.scala
+++ b/src/test/scala/leon/unit/evaluators/EvaluatorSuite.scala
@@ -48,9 +48,9 @@ class EvaluatorSuite extends LeonTestSuite with helpers.ExpressionsDSL {
       eval(e, UnitLiteral())                === UnitLiteral()
       eval(e, InfiniteIntegerLiteral(0))    === InfiniteIntegerLiteral(0)
       eval(e, InfiniteIntegerLiteral(42))   === InfiniteIntegerLiteral(42)
-      eval(e, RealLiteral(0))               === RealLiteral(0)
-      eval(e, RealLiteral(42))              === RealLiteral(42)
-      eval(e, RealLiteral(13.255))          === RealLiteral(13.255)
+      eval(e, FractionalLiteral(0 ,1))      === FractionalLiteral(0 ,1)
+      eval(e, FractionalLiteral(42 ,1))     === FractionalLiteral(42, 1)
+      eval(e, FractionalLiteral(26, 3))     === FractionalLiteral(26, 3)
     }
   }
 
@@ -172,32 +172,29 @@ class EvaluatorSuite extends LeonTestSuite with helpers.ExpressionsDSL {
   }
 
   test("Real Arightmetic") { implicit fix =>
-    for(e <- allEvaluators) {
-      eval(e, RealPlus(RealLiteral(3), RealLiteral(5)))     === RealLiteral(8)
-      eval(e, RealMinus(RealLiteral(7), RealLiteral(2)))    === RealLiteral(5)
-      eval(e, RealUMinus(RealLiteral(7)))                   === RealLiteral(-7)
-      eval(e, RealTimes(RealLiteral(2), RealLiteral(3)))    === RealLiteral(6)
-      eval(e, RealPlus(RealLiteral(2.5), RealLiteral(3.5))) === RealLiteral(6)
+    for (e <- allEvaluators) {
+      eval(e, RealPlus(FractionalLiteral(2, 3), FractionalLiteral(1, 3))) === FractionalLiteral(1, 1)
+      eval(e, RealMinus(FractionalLiteral(1, 1), FractionalLiteral(1, 4))) === FractionalLiteral(3, 4)
+      eval(e, RealUMinus(FractionalLiteral(7, 1))) === FractionalLiteral(-7, 1)
+      eval(e, RealTimes(FractionalLiteral(2, 3), FractionalLiteral(1, 3))) === FractionalLiteral(2, 9)
     }
   }
 
   test("Real Comparisons") { implicit fix =>
     for(e <- allEvaluators) {
-      eval(e, GreaterEquals(RealLiteral(7), RealLiteral(4))) === BooleanLiteral(true)
-      eval(e, GreaterEquals(RealLiteral(7), RealLiteral(7))) === BooleanLiteral(true)
-      eval(e, GreaterEquals(RealLiteral(4), RealLiteral(7))) === BooleanLiteral(false)
+      eval(e, GreaterEquals(FractionalLiteral(7, 1), FractionalLiteral(4, 2))) === BooleanLiteral(true)
+      eval(e, GreaterEquals(FractionalLiteral(7, 2), FractionalLiteral(49, 13))) === BooleanLiteral(false)
 
-      eval(e, GreaterThan(RealLiteral(7), RealLiteral(4)))  === BooleanLiteral(true)
-      eval(e, GreaterThan(RealLiteral(7), RealLiteral(7)))  === BooleanLiteral(false)
-      eval(e, GreaterThan(RealLiteral(4), RealLiteral(7)))  === BooleanLiteral(false)
+      eval(e, GreaterThan(FractionalLiteral(49, 13), FractionalLiteral(7, 2))) === BooleanLiteral(true)
+      eval(e, GreaterThan(FractionalLiteral(49, 14), FractionalLiteral(7, 2))) === BooleanLiteral(false)
+      eval(e, GreaterThan(FractionalLiteral(4, 2), FractionalLiteral(7, 1))) === BooleanLiteral(false)
 
-      eval(e, LessEquals(RealLiteral(7), RealLiteral(4)))   === BooleanLiteral(false)
-      eval(e, LessEquals(RealLiteral(7), RealLiteral(7)))   === BooleanLiteral(true)
-      eval(e, LessEquals(RealLiteral(4), RealLiteral(7)))   === BooleanLiteral(true)
+      eval(e, LessEquals(FractionalLiteral(7, 1), FractionalLiteral(4, 2))) === BooleanLiteral(false)
+      eval(e, LessEquals(FractionalLiteral(7, 2), FractionalLiteral(49, 13))) === BooleanLiteral(true)
 
-      eval(e, LessThan(RealLiteral(7), RealLiteral(4)))     === BooleanLiteral(false)
-      eval(e, LessThan(RealLiteral(7), RealLiteral(7)))     === BooleanLiteral(false)
-      eval(e, LessThan(RealLiteral(4), RealLiteral(7)))     === BooleanLiteral(true)
+      eval(e, LessThan(FractionalLiteral(49, 13), FractionalLiteral(7, 2))) === BooleanLiteral(false)
+      eval(e, LessThan(FractionalLiteral(49, 14), FractionalLiteral(7, 2))) === BooleanLiteral(false)
+      eval(e, LessThan(FractionalLiteral(4, 2), FractionalLiteral(7, 1))) === BooleanLiteral(true)
     }
   }
 
@@ -266,7 +263,7 @@ class EvaluatorSuite extends LeonTestSuite with helpers.ExpressionsDSL {
   test("Array Default Value") { implicit fix  =>
     for (e <- allEvaluators) {
       val id = FreshIdentifier("id", Int32Type)
-      eqArray(eval(e, finiteArray(Map[Int, Expr](), Some(Variable(id), IntLiteral(7)), Int32Type), Map(id -> IntLiteral(27))).res, 
+      eqArray(eval(e, finiteArray(Map[Int, Expr](), Some(Variable(id), IntLiteral(7)), Int32Type), Map(id -> IntLiteral(27))).res,
                       finiteArray(Map[Int, Expr](), Some(IntLiteral(27), IntLiteral(7)), Int32Type))
     }
   }
diff --git a/testcases/orb-testcases/amortized/BigNums.scala b/testcases/orb-testcases/amortized/BigNums.scala
new file mode 100644
index 000000000..883d1f45a
--- /dev/null
+++ b/testcases/orb-testcases/amortized/BigNums.scala
@@ -0,0 +1,50 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object BigNums {
+  sealed abstract class BigNum
+  case class Cons(head: BigInt, tail: BigNum) extends BigNum
+  case class Nil() extends BigNum
+
+  def incrTime(l: BigNum) : BigInt = {
+    l match {
+      case Nil() => 1
+      case Cons(x, tail) =>
+        if(x == 0) 1
+        else 1 + incrTime(tail)
+    }
+  }
+
+  def potentialIncr(l: BigNum) : BigInt = {
+    l match {
+      case Nil() => 0
+      case Cons(x, tail) =>
+        if(x == 0) potentialIncr(tail)
+        else 1 + potentialIncr(tail)
+    }
+  }
+
+  def increment(l: BigNum) : BigNum = {
+    l match {
+      case Nil() => Cons(1,l)
+      case Cons(x, tail) =>
+        if(x == 0) Cons(1, tail)
+        else Cons(0, increment(tail))
+    }
+  } ensuring (res => time <= ? * incrTime(l) + ? && incrTime(l) + potentialIncr(res) - potentialIncr(l) <= ?)
+
+  /**
+   * Nop is the number of operations
+   */
+  def incrUntil(nop: BigInt, l: BigNum) : BigNum = {
+    if(nop == 0)  l
+    else {
+      incrUntil(nop-1, increment(l))
+    }
+  } ensuring (res => time <= ? * nop + ? * potentialIncr(l) + ?)
+
+  def count(nop: BigInt) : BigNum = {
+    incrUntil(nop, Nil())
+  } ensuring (res => time <= ? * nop + ?)
+
+}
diff --git a/testcases/orb-testcases/automatic/AmortizedQueue.scala b/testcases/orb-testcases/automatic/AmortizedQueue.scala
new file mode 100644
index 000000000..4aa3e785e
--- /dev/null
+++ b/testcases/orb-testcases/automatic/AmortizedQueue.scala
@@ -0,0 +1,74 @@
+import leon.lang.invariantLang._
+
+object AmortizedQueue {
+  sealed abstract class List
+  case class Cons(head : Int, tail : List) extends List
+  case class Nil() extends List
+
+  case class Queue(front : List, rear : List)
+
+  def size(list : List) : Int = (list match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + size(xs)
+  })
+
+
+  def qsize(q : Queue) : Int = size(q.front) + size(q.rear)
+
+  def asList(q : Queue) : List = concat(q.front, reverse(q.rear))
+
+  def concat(l1 : List, l2 : List) : List = (l1 match {
+    case Nil() => l2
+    case Cons(x,xs) => Cons(x, concat(xs, l2))
+
+  }) //ensuring (res => size(res) == size(l1) + size(l2))
+
+  def isAmortized(q : Queue) : Boolean = size(q.front) >= size(q.rear)
+
+  def isEmpty(queue : Queue) : Boolean = queue match {
+    case Queue(Nil(), Nil()) => true
+    case _ => false
+  }
+
+  def reverseRec(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => reverseRec(xs, Cons(x, l2))
+
+  }) //ensuring (res =>  size(l1) + size(l2) == size(res))
+
+  def reverse(l: List): List = {
+    reverseRec(l, Nil())
+  } //ensuring (res => size(l) == size(res))
+
+  def amortizedQueue(front : List, rear : List) : Queue = {
+    if (size(rear) <= size(front))
+      Queue(front, rear)
+    else
+      Queue(concat(front, reverse(rear)), Nil())
+  }
+
+  def enqueue(q : Queue, elem : Int) : Queue = ({
+
+    amortizedQueue(q.front, Cons(elem, q.rear))
+
+  }) ensuring(res =>  qsize(res) == qsize(q) + 1)
+
+
+  def removeLast(l : List) : List = {
+    require(l != Nil())
+    l match {
+      case Cons(x,Nil()) => Nil()
+      case Cons(x,xs) => Cons(x, removeLast(xs))
+      case _ => Nil()
+    }
+  }
+
+  def pop(q : Queue) : Queue = {
+    require(isAmortized(q) && !isEmpty(q))
+    q match {
+     case Queue(front, Cons(r,rs)) => Queue(front, rs)
+     case Queue(front, rear) => Queue(removeLast(front), rear)
+     case _ => Queue(Nil(),Nil())
+    }
+  } ensuring(res =>  qsize(res) == qsize(q) - 1)
+}
diff --git a/testcases/orb-testcases/automatic/BinaryTrie.scala b/testcases/orb-testcases/automatic/BinaryTrie.scala
new file mode 100755
index 000000000..e4247d9f7
--- /dev/null
+++ b/testcases/orb-testcases/automatic/BinaryTrie.scala
@@ -0,0 +1,63 @@
+import leon.lang.invariantLang._
+
+
+object BinaryTrie {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(nvalue: Int, left : Tree, right: Tree) extends Tree
+
+  sealed abstract class IList
+  case class Cons(head: Int, tail: IList) extends IList
+  case class Nil() extends IList
+
+  def listSize(l: IList): Int = (l match {
+    case Nil() => 0
+    case Cons(x, xs) => 1 + listSize(xs)
+  })
+
+  def height(t: Tree): Int = {
+	  t match{
+	    case Leaf() => 0
+	    case Node(x,l,r) => {
+	      val hl = height(l)
+	      val hr = height(r)
+	      if(hl > hr) hl + 1 else hr + 1
+	    }
+	  }
+  }
+
+  def insert(inp: IList, t: Tree): Tree = {
+    t match {
+        case Leaf() => {
+          inp match {
+            case Nil() => t
+            case Cons(x ,xs) => {
+              val newch = insert(xs, Leaf())
+              newch match {
+                case Leaf() => Node(x, Leaf(), Leaf())
+                case Node(y, _, _) => if(y > 0) Node(x, newch, Leaf()) else Node(y, Leaf(), newch)
+              }
+            }
+          }
+        }
+        case Node(v, l, r) => {
+          inp match {
+            case Nil() => t
+            case Cons(x, Nil()) => t
+            case Cons(x ,xs@Cons(y, _)) => {
+              val ch = if(y > 0) l else r
+        	  if(y > 0)
+        		  Node(v, insert(xs, ch), r)
+        	  else
+        	    Node(v, l, insert(xs, ch))
+            }
+            case _ => t
+        }
+      }
+    }
+}
+
+  def create(inp: IList) : Tree = {
+    insert(inp, Leaf())
+  }ensuring(res => height(res) >= listSize(inp))
+}
diff --git a/testcases/orb-testcases/automatic/BinomialHeap.scala b/testcases/orb-testcases/automatic/BinomialHeap.scala
new file mode 100644
index 000000000..f9b44e066
--- /dev/null
+++ b/testcases/orb-testcases/automatic/BinomialHeap.scala
@@ -0,0 +1,325 @@
+/** 
+ * Okasaki3_2
+ * 
+ * Based on the chapter 3.2 of Okasaki's paper Purely Functional Data Structure
+ * Implements the "Binomial Heap" data structure described in the chapter.
+ * 
+ * @author Florian Briant
+ **/
+
+import leon.Utils._
+import leon.Annotations._
+
+object BinomialHeap {    
+  sealed abstract class BinomialTree
+  case class Node(rank: Int, elem: Element, children: BinomialHeap) extends BinomialTree   
+  
+  sealed abstract class ElementAbs
+  case class Element(n: Int) extends ElementAbs
+  
+  sealed abstract class BinomialHeap
+  case class ConsHeap(head: BinomialTree, tail: BinomialHeap) extends BinomialHeap
+  case class NilHeap extends BinomialHeap
+  
+  sealed abstract class List
+  case class NodeL(head: BinomialHeap, tail: List) extends List
+  case class NilL() extends List
+  
+  sealed abstract class OptionalTree
+  case class Some(t : BinomialTree) extends OptionalTree
+  case class None extends OptionalTree
+  
+  /* Lower or Equal than for Element structure */
+  private def leq(a: Element, b: Element) : Boolean = {
+    a match {
+      case Element(a1) => {
+        b match {
+          case Element(a2) => {
+            if(a1 <= a2) true 
+            else false
+          }
+        }
+      }
+    }
+  }
+  
+  /* isEmpty function of the Binomial Heap */
+  def isEmpty(t: BinomialHeap) = t match {
+    case ConsHeap(_,_) => false
+    case NilHeap() => true
+  }
+  
+  /* Helper function to determine rank of a BinomialTree */
+  def rank(t: BinomialTree) : Int =  t match {
+    case Node(r, _, _) => r
+  }
+  
+  /* Helper function to get the root element of a BinomialTree */
+  def root(t: BinomialTree) : Element = t match {
+    case Node(_, e, _) => e
+  }
+
+  /* Helper function which tell if a binomial tree is valid */
+  //  private def isBinomialChildrenValid(pare: Element, ch: BinomialHeap) : Boolean = ch match {
+  //    case ConsHeap(t1@Node(r, e, _), tail@ConsHeap(t2,_)) => rank(t2) == r - 1 && leq(pare,e) && isBinomialTreeValid(t1) && isBinomialChildrenValid(pare, tail)
+  //    case ConsHeap(t1@Node(r, e, _), NilHeap()) => leq(pare,e) && isBinomialTreeValid(t1)
+  //    case NilHeap() => true
+  //  }
+  //  private def isBinomialTreeValid(l: BinomialTree) : Boolean = l match {
+  //    case Node(r, e, ch@ConsHeap(t, _)) => rank(t) == r - 1 && isBinomialChildrenValid(e, ch)
+  //    case Node(_, _, NilHeap()) => true
+  //  }
+  //  
+  //  // Helper function which tell if a binomial heap is valid 
+  //  private def isBinomialHeapValid(h: BinomialHeap) : Boolean = h match {
+  //      case ConsHeap(e, tail@ConsHeap(e2, _)) => rank(e) < rank(e2) && isBinomialTreeValid(e) && isBinomialHeapValid(tail)
+  //      case ConsHeap(e, NilHeap()) => isBinomialTreeValid(e) 
+  //      case NilHeap() => true
+  //  }
+
+  def checkChildren(index: Int, origRank: Int, origElem: Element, children: BinomialHeap): Boolean = children match {
+    case ConsHeap(h, t) => h match {
+      case Node(r1, e1, _) => leq(origElem, e1) && r1 == origRank - index - 1 && isBinomialTreeValid(h) && checkChildren(index + 1, origRank, origElem, t)
+    }
+    case NilHeap() => index == origRank
+  }
+  private def isBinomialTreeValid(l: BinomialTree) : Boolean = l match {
+    case Node(r, e, c) => {      
+      checkChildren(0, r, e, c)
+    }
+  }  
+  def isBinomialHeapValidStep(h1: BinomialHeap, oldR: Int) : Boolean = h1 match {
+      case ConsHeap(e, tail) => oldR < rank(e) && isBinomialHeapValidStep(tail, rank(e)) && isBinomialTreeValid(e)
+      case NilHeap() => true
+  }
+  // Helper function which tell if a binomial heap is valid 
+  private def isBinomialHeapValid(h: BinomialHeap) : Boolean ={    
+    isBinomialHeapValidStep(h, -1)
+  }
+  
+  /*private def rankIncrease(h: BinomialHeap) : Boolean = {
+    h match {
+      case ConsHeap(tr, tail) => {        
+        tail match{ 
+          case ConsHeap(tr2, tail2) => tr < tr2 && rankIncrease(tail)
+          case NilHeap => true
+        }        
+        rank(tr) < heapRank(tail) && rankIncrease(tail)
+      } 
+      case NilHeap() => true
+    }
+  }*/
+  
+  /* Linking trees of equal ranks depending on the root element */ 
+  def link(t1: BinomialTree, t2: BinomialTree) : BinomialTree = {
+    require(isBinomialTreeValid(t1) && isBinomialTreeValid(t2) && rank(t1) == rank(t2))
+    t1 match {
+        case Node(r, x1, c1) => {
+          t2 match {
+            case Node(_, x2, c2) => {
+              if (leq(x1,x2)) {
+                  Node(r+1, x1, ConsHeap(t2, c1))  
+              } else {
+                  Node(r+1, x2, ConsHeap(t1, c2))
+              }
+            }
+          }
+        }
+    }
+  } ensuring(res => isBinomialTreeValid(res))
+
+  /* Insert a tree into a binomial heap. The tree should be correct in relation to the heap */
+  def insTree(t: BinomialTree, h: BinomialHeap) : BinomialHeap = {
+    require(isBinomialTreeValid(t) && isBinomialHeapValid(h))// && isTreeValidForInsert(t,h))    
+    h match {
+      case ConsHeap(head, tail) =>  {
+        if (rank(t) < rank(head)) {
+          ConsHeap(t, h)
+        }else if (rank(t) > rank(head)) {
+          ConsHeap(head, insTree(t,tail))
+        } else {
+          insTree(link(t,head), tail)
+        }
+      }
+      case NilHeap() => ConsHeap(t, NilHeap())
+    }
+  } ensuring(res => isBinomialHeapValid(res))
+
+  /*def mult(x : Int, y : Int) : Int = {
+      if(x == 0 || y == 0) 0
+      else
+    	  mult(x-1,y-1) + x + y -1
+  }*/
+
+  /* Merge two heaps together */
+  /*def merge(h1: BinomialHeap, h2: BinomialHeap) : BinomialHeap = {
+    //require(isBinomialHeapValid(h1) && isBinomialHeapValid(h2))
+    require(rankIncrease(h1) && rankIncrease(h2))
+    h1 match {
+      case ConsHeap(head1, tail1) => {
+        h2 match {
+          case ConsHeap(head2, tail2) => {
+            if (rank(head1) < rank(head2)) {
+              ConsHeap(head1, merge(tail1, h2))
+            } else if (rank(head2) < rank(head1)) {
+              ConsHeap(head2, merge(h1, tail2))
+            } else {
+              insTree(link(head1, head2), merge(tail1, tail2))
+            }
+          }
+          case NilHeap() => h1
+        }
+      }
+      case NilHeap() => h2
+    }
+  } ensuring(res => (treeNum(res)<=treeNum(h1)+treeNum(h2) && rankIncrease(res) && heapRank(res)>=min(heapRank(h1),heapRank(h2))) 
+      template((b,c,d) => time <= b*treeNum(h1) + c*treeNum(h2) + d))*/
+  //ensuring(res => treeNum(res)<=treeNum(h1)+treeNum(h2) template((a,b,c,d) => time <= a*mult(treeNum(h1),treeNum(h2)) + b*treeNum(h1) + c*treeNum(h2) + d))
+  //((((((2 * res4._2) + (-2 * treeNum2(h2))) + (-1 * treeNum2(h1))) + (-74 * mult2(treeNum2(h1), treeNum2(h2)))) + -6) <= 0)
+  //ensuring(res => isBinomialHeapValid(res))
+
+  /* Merge two heaps together */
+  def merge(h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    require(isBinomialHeapValid(h1) && isBinomialHeapValid(h2))    
+    h1 match {
+      case ConsHeap(head1, tail1) => {
+        h2 match {
+          case ConsHeap(head2, tail2) => {
+            if (rank(head1) < rank(head2)) {
+              ConsHeap(head1, merge(tail1, h2))
+            } else if (rank(head2) < rank(head1)) {
+              ConsHeap(head2, merge(h1, tail2))
+            } else {
+              mergeWithCarry(link(head1, head2), tail1, tail2)
+            }
+          }
+          case NilHeap() => h1
+        }
+      }
+      case NilHeap() => h2
+    }
+  }  ensuring(res => isBinomialHeapValid(res))
+
+  /* Helper function to validate the input tree of insTree */
+  private def isValidCarry(t: BinomialTree, h: BinomialHeap) = h match {
+    case ConsHeap(head, tail) => rank(t) <= rank(head) 
+    case NilHeap() => true
+  }
+  
+  def mergeWithCarry(t: BinomialTree, h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    require(isBinomialTreeValid(t) && isBinomialHeapValid(h1) && isBinomialHeapValid(h2) && isValidCarry(t,h1) && isValidCarry(t,h2))    
+    t match {
+      case Node(r, _, _) => {
+        h1 match {
+          case ConsHeap(head1, tail1) => {
+            h2 match {
+              case ConsHeap(head2, tail2) => {
+                if (rank(head1) < rank(head2)) {
+                  
+                  if (rank(t) < rank(head1))
+                    ConsHeap(t, ConsHeap(head1, merge(tail1, h2)))
+                  else 
+                    mergeWithCarry(link(t, head1), tail1, h2)                                     
+                } else if (rank(head2) < rank(head1)) {
+                  
+                  if (rank(t) < rank(head2))
+                    ConsHeap(t, ConsHeap(head2, merge(h1, tail2)))
+                  else
+                    mergeWithCarry(link(t, head2), h1, tail2)                   
+                  
+                } else {
+                  ConsHeap(t, mergeWithCarry(link(head1, head2), tail1, tail2))
+                }
+              }
+              case NilHeap() => {              
+                insTree(t, h1)
+              }
+            }
+          }
+          case NilHeap() => insTree(t, h2)
+        }
+      }
+    }
+  } ensuring (res => isBinomialHeapValid(res))
+
+  /* Helper function to define ensuring clause in removeMinTree */
+  private def isRemovedMinTreeValid(x : (OptionalTree, BinomialHeap)) : Boolean = {
+    val (opt,h) = x
+    opt match {	    
+		case Some(t) => isBinomialTreeValid(t) && isBinomialHeapValid(h)
+		case _ => isBinomialHeapValid(h)		  
+	  }
+  }
+
+  //Auxiliary helper function to simplefy findMin and deleteMin  
+  def removeMinTree(h: BinomialHeap): (OptionalTree, BinomialHeap) = {
+    require(!isEmpty(h) && isBinomialHeapValid(h)) 
+    h match {
+      case ConsHeap(head, NilHeap()) => (Some(head), NilHeap())
+      case ConsHeap(head1, tail1) => {
+        val (opthead2, tail2) = removeMinTree(tail1)
+        opthead2 match {
+          case None() => (Some(head1), tail1)
+          case Some(head2) =>
+            if (leq(root(head1), root(head2))) {
+              (Some(head1), tail1)
+            } else {
+              (Some(head2), ConsHeap(head1, tail2))
+            }
+        }
+      }
+      case _ => (None(), NilHeap())
+    }
+  } ensuring(res => isRemovedMinTreeValid(res))
+  
+//  def revRec(l1: BinomialHeap, l2: BinomialHeap): BinomialHeap = (l1 match {
+//    case NilHeap() => l2
+//    case ConsHeap(x, xs) => revRec(xs, ConsHeap(x, l2))
+//
+//  }) 
+//
+//  def rev(l: BinomialHeap): BinomialHeap = {
+//    revRec(l, NilHeap())    
+//  } 
+  
+  // Discard the minimum element of the extracted min tree and put its children back into the heap 
+  def deleteMin(h: BinomialHeap) : BinomialHeap = {
+	  require(!isEmpty(h) && isBinomialHeapValid(h)) 
+	  val (min, ts2) = removeMinTree(h)
+	  min match {	    
+		case Some(Node(_,_,ts1)) => merge(ts1, ts2)
+		case _ => h		  
+	  }
+  } ensuring(res => isBinomialHeapValid(h))
+
+  /* TEST AREA */
+  
+  /*def BTtest1() : Boolean = isBinomialTreeValid(Node(1, Element(2), ConsHeap(Node(0, Element(3), NilHeap()),NilHeap())))*/ 
+  /*def BTtest2() : Boolean = isBinomialTreeValid(Node(0, Element(3), NilHeap()))*/
+  /*def BTtest3() : Boolean = isBinomialTreeValid(Node(1, Element(975), ConsHeap(Node(0, Element(976), NilHeap()), NilHeap())))*/
+  /*def BHtest1() : Boolean = isBinomialHeapValid(ConsHeap(Node(0, Element(0), Nil()),ConsHeap(Node(1, Element(0), ConsHeap(Node(0, Element(1), NilHeap()),NilHeap())),NilHeap())))*/
+  /*def testInsTree1() : BinomialHeap = insTree(Node(0, Element(2), NilHeap()), ConsHeap(Node(1, Element(3), ConsHeap(Node(0, Element(4), NilHeap()),NilHeap())),NilHeap()))*/
+  /*def testInsTree2() : BinomialHeap = insTree(Node(0, Element(2), NilHeap()), ConsHeap(Node(0, Element(1), NilHeap()), NilHeap()))*/
+  
+  /*def testMerge1() : BinomialHeap = merge(ConsHeap(Node(0, Element(1), NilHeap()), NilHeap()), ConsHeap(Node(1, Element(3), ConsHeap(Node(0, Element(4), NilHeap()),NilHeap())),NilHeap()))*/
+  /*def testMerge2() : BinomialHeap = merge(ConsHeap(Node(1, Element(2), ConsHeap(Node(0, Element(4), NilHeap()),NilHeap())),NilHeap()), ConsHeap(Node(0, Element(3), NilHeap()), NilHeap()))*/
+  /*def testMerge3() : BinomialHeap = merge(ConsHeap(Node(0, Element(4), NilHeap()), NilHeap()), ConsHeap(Node(0, Element(1), NilHeap()), NilHeap()))*/
+  
+  /*def testRemoveMinTree1() : (BinomialTree, BinomialHeap) = removeMinTree(ConsHeap(Node(0, Element(1), NilHeap()), NilHeap()))
+  def testRemoveMinTree2() : (BinomialTree, BinomialHeap) = removeMinTree(testMerge1())
+  def testRemoveMinTree3() : (BinomialTree, BinomialHeap) = removeMinTree(testMerge2())*/
+  
+  /*def testFindMin1() : Element = findMin(testMerge1())
+  
+  def testConcat : List = concat(ConsHeap(Node(0, Element(0), NilHeap()), NilHeap()), ConsHeap(Node(0, Element(0), NilHeap()), ConsHeap(Node(0, Element(0), NilHeap()), NilHeap())))
+  
+  def testRev: List = rev(ConsHeap(Node(0, Element(0), NilHeap()), ConsHeap(Node(1, Element(1), NilHeap()),ConsHeap(Node(2, Element(2), NilHeap()),NilHeap()))))*/
+  
+  /*def testDeleteMin1() = deleteMin(testMerge1())*/
+  
+  /*def sortTest() = bubbleSort(NodeL(testMerge1(), NodeL(testMerge2(), NilL())), true)
+  def sortTest2() = bubbleSort(NodeL(testMerge1(), NodeL(testMerge2(), NilL())), false)*/
+ 
+  
+  
+}
diff --git a/testcases/orb-testcases/automatic/HeapSort.scala b/testcases/orb-testcases/automatic/HeapSort.scala
new file mode 100644
index 000000000..4354d8db5
--- /dev/null
+++ b/testcases/orb-testcases/automatic/HeapSort.scala
@@ -0,0 +1,109 @@
+import scala.collection.immutable.Set
+// import leon.Utils._
+
+object HeapSort {
+  sealed abstract class List
+  case class Cons(head:Int,tail:List) extends List
+  case class Nil() extends List
+
+  sealed abstract class Heap
+  case class Leaf() extends Heap
+  case class Node(rk : Int, value: Int, left: Heap, right: Heap) extends Heap
+
+  private def rightHeight(h: Heap) : Int = {h match {
+    case Leaf() => 0
+    case Node(_,_,_,r) => rightHeight(r) + 1
+  }} ensuring(_ >= 0)
+
+  private def rank(h: Heap) : Int = h match {
+    case Leaf() => 0
+    case Node(rk,_,_,_) => rk
+  }
+
+  private def hasLeftistProperty(h: Heap) : Boolean = (h match {
+    case Leaf() => true
+    case Node(_,_,l,r) => hasLeftistProperty(l) && hasLeftistProperty(r) && rightHeight(l) >= rightHeight(r) && (rank(h) == rightHeight(h))
+  })
+
+  def heapSize(t: Heap): Int = {
+    require(hasLeftistProperty(t))
+    (t match {
+      case Leaf() => 0
+      case Node(_,v, l, r) => heapSize(l) + 1 + heapSize(r)
+    })
+  } ensuring(_ >= 0)
+
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    h1 match {
+      case Leaf() => h2
+      case Node(_, v1, l1, r1) => h2 match {
+        case Leaf() => h1
+        case Node(_, v2, l2, r2) =>
+          if(v1 > v2)
+            makeT(v1, l1, merge(r1, h2))
+          else
+            makeT(v2, l2, merge(h1, r2))
+      }
+    }
+  } ensuring(res => hasLeftistProperty(res) && heapSize(h1) + heapSize(h2) == heapSize(res))
+
+
+  private def makeT(value: Int, left: Heap, right: Heap) : Heap = {
+    if(rank(left) >= rank(right))
+      Node(rank(right) + 1, value, left, right)
+    else
+      Node(rank(left) + 1, value, right, left)
+  }
+
+ def insert(element: Int, heap: Heap) : Heap = {
+   require(hasLeftistProperty(heap))
+
+    merge(Node(1, element, Leaf(), Leaf()), heap)
+
+  } ensuring(res => heapSize(res) == heapSize(heap) + 1)
+
+   def findMax(h: Heap) : Int = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,m,_,_) => m
+      case Leaf() => -1000
+    }
+  }
+
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,_,l,r) => merge(l, r)
+      case l @ Leaf() => l
+    }
+  }
+
+  def listSize(l : List) : Int = (l match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + listSize(xs)
+  }) ensuring(_ >= 0)
+
+  def removeElements(h : Heap, l : List) : List = {
+          require(hasLeftistProperty(h))
+   h match {
+    case Leaf() => l
+    case _ => removeElements(removeMax(h),Cons(findMax(h),l))
+
+  }} ensuring(res => heapSize(h) + listSize(l) == listSize(res))
+
+  def buildHeap(l : List, h: Heap) : Heap = {
+          require(hasLeftistProperty(h))
+   l match {
+    case Nil() => h
+    case Cons(x,xs) => buildHeap(xs, insert(x, h))
+
+  }} ensuring(res => hasLeftistProperty(res) && heapSize(h) + listSize(l) == heapSize(res))
+
+  def sort(l: List): List = ({
+
+    val heap = buildHeap(l,Leaf())
+    removeElements(heap, Nil())
+
+  }) ensuring(res => listSize(res) == listSize(l))
+}
diff --git a/testcases/orb-testcases/automatic/InsertionSort.scala b/testcases/orb-testcases/automatic/InsertionSort.scala
new file mode 100644
index 000000000..ea036f298
--- /dev/null
+++ b/testcases/orb-testcases/automatic/InsertionSort.scala
@@ -0,0 +1,25 @@
+import leon.lang.invariantLang._
+
+object InsertionSort {
+  sealed abstract class List
+  case class Cons(head:Int,tail:List) extends List
+  case class Nil() extends List
+
+  def size(l : List) : Int = (l match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + size(xs)
+  })
+
+  def sortedIns(e: Int, l: List): List = {
+    l match {
+      case Nil() => Cons(e,Nil())
+      case Cons(x,xs) => if (x <= e) Cons(x,sortedIns(e, xs)) else Cons(e, l)
+    }
+  } //ensuring(res => size(res) = size(l) + 1)
+
+  def sort(l: List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,xs) => sortedIns(x, sort(xs))
+
+  }) ensuring(res => size(res) == size(l))
+}
diff --git a/testcases/orb-testcases/automatic/LeftistHeap.scala b/testcases/orb-testcases/automatic/LeftistHeap.scala
new file mode 100644
index 000000000..6507f69ec
--- /dev/null
+++ b/testcases/orb-testcases/automatic/LeftistHeap.scala
@@ -0,0 +1,61 @@
+import leon.lang.invariantLang._
+
+object LeftistHeap {
+  sealed abstract class Heap
+  case class Leaf() extends Heap
+  case class Node(rk : Int, value: Int, left: Heap, right: Heap) extends Heap
+
+  private def rightHeight(h: Heap) : Int = h match {
+    case Leaf() => 0
+    case Node(_,_,_,r) => rightHeight(r) + 1
+  }
+
+  private def hasLeftistProperty(h: Heap) : Boolean = (h match {
+    case Leaf() => true
+    case Node(_,_,l,r) => hasLeftistProperty(l) && hasLeftistProperty(r) && rightHeight(l) >= rightHeight(r)
+  })
+
+  def size(t: Heap): Int = {
+    (t match {
+      case Leaf() => 0
+      case Node(_,v, l, r) => size(l) + 1 + size(r)
+    })
+  }
+
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,_,l,r) => merge(l, r)
+      case l @ Leaf() => l
+    }
+  } ensuring(res => size(res) >= size(h) - 1)
+
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    h1 match {
+      case Leaf() => h2
+      case Node(_, v1, l1, r1) => h2 match {
+        case Leaf() => h1
+        case Node(_, v2, l2, r2) =>
+          if(v1 > v2)
+            makeT(v1, l1, merge(r1, h2))
+          else
+            makeT(v2, l2, merge(h1, r2))
+      }
+    }
+  } //ensuring(res => size(res) == size(h1) + size(h2))
+
+  private def makeT(value: Int, left: Heap, right: Heap) : Heap = {
+    if(rightHeight(left) >= rightHeight(right))
+      Node(rightHeight(right) + 1, value, left, right)
+    else
+      Node(rightHeight(left) + 1, value, right, left)
+  }
+
+  def insert(element: Int, heap: Heap) : Heap = {
+   require(hasLeftistProperty(heap))
+
+    merge(Node(1, element, Leaf(), Leaf()), heap)
+
+  }ensuring(res => size(res) == size(heap) + 1)
+}
diff --git a/testcases/orb-testcases/automatic/ListOperations.scala b/testcases/orb-testcases/automatic/ListOperations.scala
new file mode 100644
index 000000000..a7483304d
--- /dev/null
+++ b/testcases/orb-testcases/automatic/ListOperations.scala
@@ -0,0 +1,57 @@
+import leon.lang.invariantLang._
+
+object ListOperations {
+  sealed abstract class List
+  case class Cons(head: Int, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): Int = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def append(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => Cons(x, append(xs, l2))
+
+  }) //ensuring (res => size(l1) + size(l2) == size(res))
+
+  def reverseRec(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => reverseRec(xs, Cons(x, l2))
+
+  }) //ensuring (res => size(l1) + size(l2) == size(res))
+
+  def reverse(l: List): List = {
+    reverseRec(l, Nil())
+  } ensuring (res => size(l) == size(res))
+
+  def reverse2(l: List): List = {
+    l match {
+      case Nil() => l
+      case Cons(hd, tl) => append(reverse2(tl), Cons(hd, Nil()))
+    }
+  } ensuring (res => size(res) == size(l))
+
+//  def remove(elem: Int, l: List): List = {
+//    l match {
+//      case Nil() => Nil()
+//      case Cons(hd, tl) => if (hd == elem) remove(elem, tl) else Cons(hd, remove(elem, tl))
+//    }
+//  }
+//
+//  def contains(list: List, elem: Int): Boolean = (list match {
+//    case Nil() => false
+//    case Cons(x, xs) => x == elem || contains(xs, elem)
+//  }) ensuring (res => true)
+//
+//  def distinct(l: List): List = (
+//    l match {
+//      case Nil() => Nil()
+//      case Cons(x, xs) => {
+//        val newl = distinct(l)
+//        if (contains(newl, x)) newl
+//        else Cons(x, newl)
+//      }
+//    })
+}
diff --git a/testcases/orb-testcases/automatic/TreeOperations.scala b/testcases/orb-testcases/automatic/TreeOperations.scala
new file mode 100755
index 000000000..74e84f0f4
--- /dev/null
+++ b/testcases/orb-testcases/automatic/TreeOperations.scala
@@ -0,0 +1,91 @@
+import leon.lang.invariantLang._
+
+object TreeOperations {
+
+  sealed abstract class List
+  case class Cons(head: Int, tail: List) extends List
+  case class Nil() extends List
+
+  sealed abstract class Tree
+  case class Node(left: Tree, value: Int, right: Tree) extends Tree
+  case class Leaf() extends Tree
+
+  def listSize(l: List): Int = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + listSize(t)
+  })
+
+  def size(t: Tree): Int = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        size(l) + size(r) + 1
+      }
+    }
+  }
+
+ /* def height(t: Tree): Int = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  } */
+  //ensuring(res => res != size(t) + 1 template((a,b,c)=> a*size(t) + b*res +c <= 0))
+
+  def insert(elem: Int, t: Tree): Tree = {
+    t match {
+      case Leaf() => Node(Leaf(), elem, Leaf())
+      case Node(l, x, r) => if (x <= elem) Node(l, x, insert(elem, r))
+      else Node(insert(elem, l), x, r)
+    }
+  }
+  //ensuring (res => true template ((a, b, c) => a * size(t) + b * size(res) + c == 0))
+
+  def addAll(l: List, t: Tree): Tree = {
+    l match {
+      case Nil() => t
+      case Cons(x, xs) => addAll(xs, insert(x, t))
+    }
+  } ensuring (res => size(res) >= size(t))
+
+  def remove(elem: Int, t: Tree): Tree = {
+    t match {
+      case Leaf() => Leaf()
+      case Node(l, x, r) => {
+
+        if (x < elem) Node(l, x, remove(elem, r))
+        else if (x > elem) Node(remove(elem, l), x, r)
+        else {
+          t match {
+            case Node(Leaf(), x, Leaf()) => Leaf()
+            case Node(Leaf(), x, Node(_, rx, _)) => Node(Leaf(), rx, remove(rx, r))
+            case Node(Node(_, lx, _), x, r) => Node(remove(lx, l), lx, r)
+            case _ => Leaf()
+          }
+        }
+      }
+    }
+  }
+  //ensuring (res => true template ((a, b, c) => a * size(res) + b * size(t) + c <= 0))
+
+  def removeAll(l: List, t: Tree): Tree = {
+    l match {
+      case Nil() => t
+      case Cons(x, xs) => removeAll(xs, remove(x, t))
+    }
+  } ensuring (res => size(res) <= size(t))
+
+/*  def contains(elem : Int, t : Tree) : Boolean = {
+    t match {
+      case Leaf() => false
+      case Node(l, x, r) =>
+        if(x == elem) true
+        else if (x < elem) contains(elem, r)
+        else contains(elem, l)
+    }
+  }*/
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/composition/AVLSort.scala b/testcases/orb-testcases/composition/AVLSort.scala
new file mode 100644
index 000000000..411e4719f
--- /dev/null
+++ b/testcases/orb-testcases/composition/AVLSort.scala
@@ -0,0 +1,189 @@
+import leon.invariant._
+import leon.instrumentation._
+import leon.math._
+
+/**
+ * created by manos and modified by ravi.
+ * BST property cannot be verified
+ */
+object AVLTree  {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(left : Tree, value : BigInt, right: Tree, rank : BigInt) extends Tree
+
+  sealed abstract class OptionInt
+  case class None() extends OptionInt
+  case class Some(i: BigInt) extends OptionInt
+
+  // def min(i1:BigInt, i2:BigInt) : BigInt = if (i1<=i2) i1 else i2
+  // def max(i1:BigInt, i2:BigInt) : BigInt = if (i1>=i2) i1 else i2
+
+  def rank(t: Tree) : BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(_,_,_,rk) => rk
+    }
+  }
+
+  def listSize(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + listSize(t)
+  })
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r, _) => {
+        val hl = height(l)
+        val hr = height(r)
+        max(hl,hr) + 1
+      }
+    }
+  }
+
+  def size(t: Tree): BigInt = {
+    (t match {
+      case Leaf() => 0
+      case Node(l, _, r,_) => size(l) + 1 + size(r)
+    })
+  }
+
+  def rankHeight(t: Tree) : Boolean = t match {
+    case Leaf() => true
+    case Node(l,_,r,rk) => rankHeight(l) && rankHeight(r) && rk == height(t)
+  }
+
+  def balanceFactor(t : Tree) : BigInt = {
+    t match{
+      case Leaf() => 0
+      case Node(l, _, r, _) => rank(l) - rank(r)
+    }
+  }
+
+  def unbalancedInsert(t: Tree, e : BigInt) : Tree = {
+    t match {
+      case Leaf() => Node(Leaf(), e, Leaf(), 1)
+      case Node(l,v,r,h) =>
+             if (e == v) t
+        else if (e <  v){
+          val newl = avlInsert(l,e)
+          Node(newl, v, r, max(rank(newl), rank(r)) + 1)
+        }
+        else {
+          val newr = avlInsert(r,e)
+          Node(l, v, newr, max(rank(l), rank(newr)) + 1)
+        }
+    }
+  }
+
+  def avlInsert(t: Tree, e : BigInt) : Tree = {
+    balance(unbalancedInsert(t,e))
+  } ensuring(res => tmpl((a,b) => time <= a*height(t) + b))
+
+  def deletemax(t: Tree): (Tree, OptionInt) = {
+    t match {
+      case Node(Leaf(), v, Leaf(), _) => (Leaf(), Some(v))
+      case Node(l, v, Leaf(), _) => {
+        val (newl, opt) =  deletemax(l)
+        opt match {
+          case None() => (t, None())
+          case Some(lmax) => {
+            val newt = balance(Node(newl, lmax, Leaf(), rank(newl) + 1))
+            (newt, Some(v))
+          }
+        }
+      }
+      case Node(_, _, r, _) => deletemax(r)
+      case _ => (t, None())
+    }
+  } ensuring(res => tmpl((a,b) => time <= a*height(t) + b))
+
+  def unbalancedDelete(t: Tree, e: BigInt): Tree = {
+    t match {
+      case Leaf() => Leaf() //not found case
+      case Node(l, v, r, h) =>
+        if (e == v) {
+          if (l == Leaf()) r
+          else if(r == Leaf()) l
+          else {
+            val (newl, opt) = deletemax(l)
+            opt match {
+              case None() => t
+              case Some(newe) => {
+                Node(newl, newe, r, max(rank(newl), rank(r)) + 1)
+              }
+            }
+          }
+        } else if (e < v) {
+          val newl = avlDelete(l, e)
+          Node(newl, v, r, max(rank(newl), rank(r)) + 1)
+        } else {
+          val newr = avlDelete(r, e)
+          Node(l, v, newr, max(rank(l), rank(newr)) + 1)
+        }
+    }
+  }
+
+  def avlDelete(t: Tree, e: BigInt): Tree = {
+    balance(unbalancedDelete(t, e))
+  } ensuring(res => tmpl((a,b) => time <= a*height(t) + b))
+
+  def balance(t:Tree) : Tree = {
+    t match {
+      case Leaf() => Leaf() // impossible...
+      case Node(l, v, r, h) =>
+        val bfactor = balanceFactor(t)
+        // at this point, the tree is unbalanced
+        if(bfactor > 1 ) { // left-heavy
+          val newL =
+            if (balanceFactor(l) < 0) { // l is right heavy
+              rotateLeft(l)
+            }
+            else l
+          rotateRight(Node(newL,v,r, max(rank(newL), rank(r)) + 1))
+        }
+        else if(bfactor < -1) {
+          val newR =
+            if (balanceFactor(r) > 0) { // r is left heavy
+              rotateRight(r)
+            }
+            else r
+          rotateLeft(Node(l,v,newR, max(rank(newR), rank(l)) + 1))
+        } else t
+      }
+  }
+
+  def rotateRight(t:Tree) = {
+    t match {
+      case Node(Node(ll, vl, rl, _),v,r, _) =>
+
+        val hr = max(rank(rl),rank(r)) + 1
+        Node(ll, vl, Node(rl,v,r,hr), max(rank(ll),hr) + 1)
+
+      case _ => t // this should not happen
+  } }
+
+  def rotateLeft(t:Tree) =  {
+    t match {
+      case Node(l, v, Node(lr,vr,rr,_), _) =>
+
+        val hl = max(rank(l),rank(lr)) + 1
+        Node(Node(l,v,lr,hl), vr, rr, max(hl, rank(rr)) + 1)
+      case _ => t // this should not happen
+  } }
+
+  def addAll(l: List, t: Tree): Tree = {
+    l match {
+      case Nil() => t
+      case Cons(x, xs) =>{
+        val newt = avlInsert(t, x)
+        addAll(xs, newt)
+      }
+    }
+  } ensuring(res => tmpl((a,b,c) => time <= a*(listSize(l) * (height(t) + listSize(l))) + b*listSize(l) + c))
+}
+
diff --git a/testcases/orb-testcases/composition/ConstantPropagation.scala b/testcases/orb-testcases/composition/ConstantPropagation.scala
new file mode 100644
index 000000000..24caa45dc
--- /dev/null
+++ b/testcases/orb-testcases/composition/ConstantPropagation.scala
@@ -0,0 +1,291 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+import leon._
+import leon.invariant._
+import leon.instrumentation._
+
+object IntLattice {
+  abstract class Element
+  case class Bot() extends Element
+  case class Top() extends Element
+  case class BigIntVal(x: BigInt) extends Element
+
+  def height: BigInt = {
+    /**
+     * A number that depends on the lattice definition.
+     * In simplest case it has height 3 (_|_ (bot) <= BigInts <= T (top))
+     */
+    3
+  } ensuring(res => time <= ?)
+
+  def join(oldVal: Element, newVal: Element) = (oldVal, newVal) match {
+    case (Bot(), any) => any // bot is the identity for join
+    case (any, Bot()) => any
+    case (Top(), _) => Top() // top joined with anything is top
+    case (_, Top()) => Top()
+    case (BigIntVal(x), BigIntVal(y)) if (x == y) => BigIntVal(y)
+    case _ =>
+      //here old and new vals are different BigIntegers
+      Top()
+  }
+}
+
+object LatticeOps {
+  import IntLattice._
+
+  def add(a: Element, b: Element): Element = {
+    (a, b) match {
+      case (Bot(), _) => Bot()
+      case (_, Bot()) => Bot()
+      case (Top(), _) => Top()
+      case (_, Top()) => Top()
+      case (BigIntVal(x), BigIntVal(y)) => BigIntVal(x + y)
+    }
+  }
+
+  def multiply(a: Element, b: Element): Element = {
+    (a, b) match {
+      case (_, BigIntVal(x)) if x == 0 => BigIntVal(0)
+      case (BigIntVal(x), _) if x == 0 => BigIntVal(0)
+      case (Bot(), _) => Bot()
+      case (_, Bot()) => Bot()
+      case (Top(), _) => Top()
+      case (_, Top()) => Top()
+      case (BigIntVal(x), BigIntVal(y)) => BigIntVal(x * y)
+    }
+  }
+}
+
+object ConstantPropagation {
+  import IntLattice._
+  import LatticeOps._
+
+  abstract class Expr
+  case class Times(lhs: Expr, rhs: Expr) extends Expr
+  case class Plus(lhs: Expr, rhs: Expr) extends Expr
+  case class BigIntLiteral(v: BigInt) extends Expr
+  case class FunctionCall(calleeName: Identifier, args: List[Expr]) extends Expr
+  case class IfThenElse(cond: Expr, thenExpr: Expr, elseExpr: Expr) extends Expr
+  case class Identifier(id: BigInt) extends Expr
+
+  /**
+   * Definition of a function AST
+   */
+  case class Function(name: Identifier, params: List[Expr], body: Expr)
+
+  /**
+   * Assuming that the functions are ordered from callee to
+   * caller and there is no mutual recursion
+   */
+  case class Program(funcs: List[Function])
+
+  def size(l: List[Function]): BigInt = {
+    l match {
+      case Cons(_, t) => 1 + size(t)
+      case Nil() => 0
+    }
+  } ensuring(_ >= 0)
+
+  def sizeExprList(exprs: List[Expr]): BigInt = {
+    exprs match {
+      case Nil() => 0
+      case Cons(currExpr, otherExprs) => sizeExpr(currExpr) + sizeExprList(otherExprs)
+    }
+  } ensuring(_ >= 0)
+
+  def sizeExpr(e: Expr): BigInt = {
+    e match {
+      case Plus(l, r) => 1 + sizeExpr(l) + sizeExpr(r)
+      case Times(l, r) => 1 + sizeExpr(l) + sizeExpr(r)
+      case FunctionCall(c, args) => {
+        1 + sizeExprList(args)
+      }
+      case IfThenElse(c, th, el) =>
+        1 + sizeExpr(c) + sizeExpr(th) + sizeExpr(el)
+      case _ => 1
+    }
+  } ensuring(_ >= 0)
+
+  def sizeFuncList(funcs: List[Function]): BigInt = {
+    funcs match {
+      case Nil() => 0
+      case Cons(currFunc, otherFuncs) =>
+        1 + sizeExpr(currFunc.body) + sizeFuncList(otherFuncs)
+    }
+  } ensuring(_ >= 0)
+
+  def initToBot(l: List[Function]): List[(BigInt /*function id*/ , Element)] = {
+    l match {
+      case Nil() => Nil[(BigInt /*function id*/ , Element)]()
+      case Cons(fun, tail) => Cons((fun.name.id, Bot()), initToBot(tail))
+    }
+  } ensuring (res => tmpl ((a, b) => time <= a * size(l) + b))
+
+  def foldConstants(p: Program): Program = {
+    val initVals = initToBot(p.funcs)
+    val fvals = computeSummaries(p, initVals, height)
+    val newfuns = transformFuns(p.funcs, fvals)
+    Program(newfuns)
+  } ensuring(res => tmpl((a, b, c, d, e) => time <= a*(height*sizeFuncList(p.funcs)) + b*height +  c*sizeFuncList(p.funcs) + d*size(p.funcs) + e))
+
+  /**
+   * The initVals is the initial values for the
+   * values of the functions
+   */
+  @compose
+  def computeSummaries(p: Program, initVals: List[(BigInt /*function id*/ , Element)], noIters: BigInt): List[(BigInt /*function id*/ , Element)] = {
+    require(noIters >= 0)
+    if (noIters <= 0) {
+      initVals
+    } else
+      computeSummaries(p, analyzeFuns(p.funcs, initVals, initVals), noIters - 1)
+  } ensuring(res =>
+      time <= ? * (noIters * sizeFuncList(p.funcs)) + ? * sizeFuncList(p.funcs) + ? * noIters + ? &&
+      rec <= noIters + ? &&
+      tpr <= ? * sizeFuncList(p.funcs) + ? &&
+      true)
+
+  /**
+   * Initial fvals and oldVals are the same
+   * but as the function progresses, fvals will only have the olds values
+   * of the functions that are yet to be processed, whereas oldVals will remain the same.
+   */
+  def analyzeFuns(funcs: List[Function], fvals: List[(BigInt, Element)], oldVals: List[(BigInt, Element)]): List[(BigInt, Element)] = {
+    (funcs, fvals) match {
+      case (Cons(f, otherFuns), Cons((fid, fval), otherVals)) =>
+        val newval = analyzeFunction(f, oldVals)
+        val approxVal = join(fval, newval) //creates an approximation of newVal to ensure convergence
+        Cons((fid, approxVal), analyzeFuns (otherFuns, otherVals, oldVals))
+      case _ =>
+        Nil[(BigInt, Element)]() //this also handles precondition violations e.g. lists aren't of same size etc.
+    }
+  } ensuring (res => tmpl ((a, b) => time <= a * sizeFuncList(funcs) + b))
+
+  @library
+  def getFunctionVal(funcId: BigInt, funcVals: List[(BigInt, Element)]): Element = {
+    funcVals match {
+      case Nil() => Bot()
+      case Cons((currFuncId, currFuncVal), otherFuncVals) if (currFuncId == funcId) => currFuncVal
+      case Cons(_, otherFuncVals) =>
+        getFunctionVal(funcId, otherFuncVals)
+    }
+  } ensuring (res => time <= 1)
+
+  def analyzeExprList(l: List[Expr], funcVals: List[(BigInt, Element)]): List[Element] = {
+    l match {
+      case Nil() => Nil[Element]()
+      case Cons(expr, otherExprs) => Cons(analyzeExpr(expr, funcVals), analyzeExprList(otherExprs, funcVals))
+    }
+  } ensuring (res => tmpl ((a, b) => time <= a * sizeExprList(l) + b))
+
+  /**
+   * Returns the value of the expression when "abstractly BigInterpreted"
+   * using the lattice.
+   */
+  def analyzeExpr(e: Expr, funcVals: List[(BigInt, Element)]): Element = {
+    e match {
+      case Times(lhs: Expr, rhs: Expr) => {
+        val lval = analyzeExpr(lhs, funcVals)
+        val rval = analyzeExpr(rhs, funcVals)
+        multiply(lval, rval)
+      }
+      case Plus(lhs: Expr, rhs: Expr) => {
+        val lval = analyzeExpr(lhs, funcVals)
+        val rval = analyzeExpr(rhs, funcVals)
+        add(lval, rval)
+      }
+      case FunctionCall(calleeName, args: List[Expr]) => {
+        getFunctionVal(calleeName.id, funcVals)
+      }
+      case IfThenElse(c, th, el) => {
+        //analyze then and else branches and join their values
+        //TODO: this can be made more precise e.g. if 'c' is
+        //a non-zero value it can only execute the then branch.
+        val v1 = analyzeExpr(th, funcVals)
+        val v2 = analyzeExpr(el, funcVals)
+        join(v1, v2)
+      }
+      case lit @ BigIntLiteral(v) =>
+        BigIntVal(v)
+
+      case Identifier(_) => Bot()
+    }
+  } ensuring (res => tmpl ((a, b) => time <= a * sizeExpr(e) + b))
+
+  def analyzeFunction(f: Function, oldVals: List[(BigInt, Element)]): Element = {
+    // traverse the body of the function and simplify constants
+    // for function calls assume the value given by oldVals
+    // also for if-then-else statments, take a join of the values along if and else branches
+    // assume that bot op any = bot and top op any = top (but this can be made more precise).
+    analyzeExpr(f.body, oldVals)
+  } ensuring (res => tmpl ((a, b) => time <= a * sizeExpr(f.body) + b))
+
+  def transformExprList(l: List[Expr], funcVals: List[(BigInt, Element)]): List[Expr] = {
+    l match {
+      case Nil() => Nil[Expr]()
+      case Cons(expr, otherExprs) => Cons(transformExpr(expr, funcVals),
+        transformExprList(otherExprs, funcVals))
+    }
+  } ensuring (res => tmpl ((a, b) => time <= a * sizeExprList(l) + b))
+
+  /**
+   * Returns the folded expression
+   */
+  def transformExpr(e: Expr, funcVals: List[(BigInt, Element)]): Expr = {
+    e match {
+      case Times(lhs: Expr, rhs: Expr) => {
+        val foldedLHS = transformExpr(lhs, funcVals)
+        val foldedRHS = transformExpr(rhs, funcVals)
+        (foldedLHS, foldedRHS) match {
+          case (BigIntLiteral(x), BigIntLiteral(y)) =>
+            BigIntLiteral(x * y)
+          case _ =>
+            Times(foldedLHS, foldedRHS)
+        }
+      }
+      case Plus(lhs: Expr, rhs: Expr) => {
+        val foldedLHS = transformExpr(lhs, funcVals)
+        val foldedRHS = transformExpr(rhs, funcVals)
+        (foldedLHS, foldedRHS) match {
+          case (BigIntLiteral(x), BigIntLiteral(y)) =>
+            BigIntLiteral(x + y)
+          case _ =>
+            Plus(foldedLHS, foldedRHS)
+        }
+      }
+      case FunctionCall(calleeName, args: List[Expr]) => {
+        getFunctionVal(calleeName.id, funcVals) match {
+          case BigIntVal(x) =>
+            BigIntLiteral(x)
+          case _ =>
+            val foldedArgs = transformExprList(args, funcVals)
+            FunctionCall(calleeName, foldedArgs)
+        }
+      }
+      case IfThenElse(c, th, el) => {
+        val foldedCond = transformExpr(c, funcVals)
+        val foldedTh = transformExpr(th, funcVals)
+        val foldedEl = transformExpr(el, funcVals)
+        foldedCond match {
+          case BigIntLiteral(x) => {
+            if (x != 0) foldedTh
+            else foldedEl
+          }
+          case _ => IfThenElse(foldedCond, foldedTh, foldedEl)
+        }
+      }
+      case _ => e
+    }
+  } ensuring (res => tmpl ((a, b) => time <= a * sizeExpr(e) + b))
+
+  def transformFuns(funcs: List[Function], fvals: List[(BigInt, Element)]): List[Function] = {
+    funcs match {
+      case Cons(f, otherFuns) =>
+        val newfun = Function(f.name, f.params, transformExpr(f.body, fvals))
+        Cons(newfun, transformFuns(otherFuns, fvals))
+      case _ =>
+        Nil[Function]()
+    }
+  } ensuring (res => tmpl ((a, b) => time <= a * sizeFuncList(funcs) + b))
+}
diff --git a/testcases/orb-testcases/composition/HeapSort.scala b/testcases/orb-testcases/composition/HeapSort.scala
new file mode 100644
index 000000000..a95e6e114
--- /dev/null
+++ b/testcases/orb-testcases/composition/HeapSort.scala
@@ -0,0 +1,147 @@
+import scala.collection.immutable.Set
+import leon.invariant._
+import leon.instrumentation._
+import leon.annotation._
+import leon.lang._
+
+object HeapSort {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  sealed abstract class Heap
+  case class Leaf() extends Heap
+  case class Node(rk: BigInt, value: BigInt, left: Heap, right: Heap) extends Heap
+
+  @monotonic
+  def log(x: BigInt): BigInt = {
+    require(x >= 0)
+    if (x <= 1) 0
+    else {
+      1 + log(x / 2)
+    }
+  } ensuring (_ >= 0)
+
+  // @library
+  // def logMonotone(x: BigInt, y: BigInt) = {
+  //   require(x >= 0 && y >=0 )
+  //   if(x <= y) log(x) <= log(y)
+  //   else log(x) >= log(y)
+  // } holds
+
+  @library
+  def heapSize(t: Heap): BigInt = {
+    require(hasLeftistProperty(t))
+    t match {
+      case Leaf() => 0
+      case Node(_, v, l, r) => heapSize(l) + 1 + heapSize(r)
+    }
+  } ensuring (res => res >= 0 && rightHeight(t) <= log(res) + 1)
+
+  private def rightHeight(h: Heap): BigInt = {
+    h match {
+      case Leaf() => 0
+      case Node(_, _, _, r) => rightHeight(r) + 1
+    }
+  } ensuring (res => res >= 0)
+
+  private def rank(h: Heap): BigInt = h match {
+    case Leaf() => 0
+    case Node(rk, _, _, _) => rk
+  }
+
+  private def hasLeftistProperty(h: Heap): Boolean = (h match {
+    case Leaf() => true
+    case Node(_, _, l, r) => hasLeftistProperty(l) && hasLeftistProperty(r) && rightHeight(l) >= rightHeight(r) && (rank(h) == rightHeight(h))
+  })
+
+  def leftRightHeight(h: Heap): BigInt = {
+    h match {
+      case Leaf() => 0
+      case Node(_, _, l, r) => rightHeight(l)
+    }
+  }
+
+  // @library
+  private def merge(h1: Heap, h2: Heap): Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    h1 match {
+      case Leaf() => h2
+      case Node(_, v1, l1, r1) => h2 match {
+        case Leaf() => h1
+        case Node(_, v2, l2, r2) =>
+          if (v1 > v2)
+            makeT(v1, l1, merge(r1, h2))
+          else
+            makeT(v2, l2, merge(h1, r2))
+      }
+    }
+  } ensuring (res => hasLeftistProperty(res) && heapSize(res) == heapSize(h1) + heapSize(h2) &&
+      //time <= ? * rightHeight(h1) + ? * rightHeight(h2) + ? )
+		  time <= 35*rightHeight(h1) + 35*rightHeight(h2) + 2)
+
+  private def makeT(value: BigInt, left: Heap, right: Heap): Heap = {
+    require(hasLeftistProperty(left) && hasLeftistProperty(right))
+    if (rank(left) >= rank(right))
+      Node(rank(right) + 1, value, left, right)
+    else
+      Node(rank(left) + 1, value, right, left)
+  }
+
+  // @library
+  def insert(element: BigInt, heap: Heap): Heap = {
+    require(hasLeftistProperty(heap))
+
+    merge(Node(1, element, Leaf(), Leaf()), heap)
+
+  } ensuring(res => heapSize(res) == heapSize(heap) + 1 &&
+      time <= 35*rightHeight(heap) + 41)
+
+  // def findMax(h: Heap) : BigInt = {
+  //   require(hasLeftistProperty(h))
+  //   h match {
+  //     case Node(_,m,_,_) => m
+  //     case Leaf() => -1000
+  //   }
+  // }
+
+  // def removeMax(h: Heap) : Heap = {
+  //   require(hasLeftistProperty(h))
+  //   h match {
+  //     case Node(_,_,l,r) => merge(l, r)
+  //     case l @ Leaf() => l
+  //   }
+  // } ensuring(res => true && tmpl((a,b) => time <= a*leftRightHeight(h) + b))
+
+  // def listSize(l: List): BigInt = (l match {
+  //   case Nil() => 0
+  //   case Cons(_, xs) => 1 + listSize(xs)
+  // }) ensuring (_ >= 0)
+
+  // def removeElements(h : Heap, l : List) : List = {
+  //   require(hasLeftistProperty(h))
+  //   h match {
+  //     case Leaf() => l
+  //     case _ => removeElements(removeMax(h),Cons(findMax(h),l))
+  //   }
+  // } ensuring(res => heapSize(h) + listSize(l) == listSize(res))
+
+  // @compose
+  // def buildHeap(l: List, h: Heap): Heap = {
+  //   require(hasLeftistProperty(h))
+  //   l match {
+  //     case Nil() => h
+  //     case Cons(x, xs) => buildHeap(xs, insert(x, h))
+  //   }
+  // } ensuring (res => hasLeftistProperty(res) &&
+  //     heapSize(res) >= heapSize(h) &&
+  //     logMonotone(heapSize(h), heapSize(res)) &&
+  //     tpr <= ? * log(heapSize(res)) + ? &&
+  //     rec <= ? * listSize(l) + ? &&
+  //     time <= ? *(listSize(l)*log(heapSize(res))) + ? *log(heapSize(res)) + ?)
+
+  // def sort(l: List): List = ({
+  //   val heap = buildHeap(l,Leaf())
+  //   removeElements(heap, Nil())
+  // }) ensuring(res => listSize(res) == listSize(l))
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/composition/HeapSort2.scala b/testcases/orb-testcases/composition/HeapSort2.scala
new file mode 100644
index 000000000..b6edc137b
--- /dev/null
+++ b/testcases/orb-testcases/composition/HeapSort2.scala
@@ -0,0 +1,132 @@
+import scala.collection.immutable.Set
+import leon.invariant._
+import leon.instrumentation._
+import leon.annotation._
+import leon.lang._
+
+object LeftistHeap {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  sealed abstract class Heap
+  case class Leaf() extends Heap
+  case class Node(rk : BigInt, value: BigInt, left: Heap, right: Heap) extends Heap
+
+  private def rightHeight(h: Heap) : BigInt = {
+    h match {
+      case Leaf() => 0
+      case Node(_,_,_,r) => rightHeight(r) + 1
+    }
+  } ensuring (res => res >= 0)
+
+  private def rank(h: Heap) : BigInt = h match {
+    case Leaf() => 0
+    case Node(rk,_,_,_) => rk
+  }
+
+  private def hasLeftistProperty(h: Heap) : Boolean = (h match {
+    case Leaf() => true
+    case Node(_,_,l,r) => hasLeftistProperty(l) && hasLeftistProperty(r) && rightHeight(l) >= rightHeight(r) && (rank(h) == rightHeight(h))
+  })
+
+  @monotonic
+  def log(x: BigInt): BigInt = {
+    require(x >= 0)
+    if (x <= 1) 0
+    else {
+      1 + log(x / 2)
+    }
+  } ensuring (_ >= 0)
+
+  def heapSize(t: Heap): BigInt = {
+    require(hasLeftistProperty(t))
+    (t match {
+      case Leaf() => 0
+      case Node(_,v, l, r) => heapSize(l) + 1 + heapSize(r)
+    })
+  } ensuring (res => res >= 0 && rightHeight(t) <= log(res) + 1)
+
+  def listSize(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + listSize(xs)
+  }) ensuring (_ >= 0)
+
+  def leftRightHeight(h: Heap) : BigInt = {h match {
+    case Leaf() => 0
+    case Node(_,_,l,r) => rightHeight(l)
+  }}
+
+  @library
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    h1 match {
+      case Leaf() => h2
+      case Node(_, v1, l1, r1) => h2 match {
+        case Leaf() => h1
+        case Node(_, v2, l2, r2) =>
+          if(v1 > v2)
+            makeT(v1, l1, merge(r1, h2))
+          else
+            makeT(v2, l2, merge(h1, r2))
+      }
+    }
+  } ensuring(res => hasLeftistProperty(res) && heapSize(res) == heapSize(h1) + heapSize(h2) && time <= 35 * rightHeight(h1) + 35 * rightHeight(h2) + 2)
+
+  private def makeT(value: BigInt, left: Heap, right: Heap) : Heap = {
+    if(rank(left) >= rank(right))
+      Node(rank(right) + 1, value, left, right)
+    else
+      Node(rank(left) + 1, value, right, left)
+  }
+
+  @library
+  def insert(element: BigInt, heap: Heap) : Heap = {
+    require(hasLeftistProperty(heap))
+
+    merge(Node(1, element, Leaf(), Leaf()), heap)
+  } ensuring(res => hasLeftistProperty(res) && heapSize(res) == heapSize(heap) + 1 && time <= 35 * rightHeight(heap) + 41)
+
+  // // @compose
+  // @library
+  // def buildHeap(l: List, h: Heap): Heap = {
+  //   require(hasLeftistProperty(h))
+  //   l match {
+  //     case Nil() => h
+  //     case Cons(x, xs) => buildHeap(xs, insert(x, h))
+  //   }
+  // } ensuring (res => hasLeftistProperty(res) && heapSize(res) >= heapSize(h) &&
+  //     // rec <= 1 * listSize(l) + 1 &&
+  //     // tpr <= ? * log(heapSize(res)) + ? &&
+  //     // time <= ? * (listSize(l) * log(heapSize(res))) + ? * log(heapSize(res)) + ? * listSize(l) + ?)
+  //     (((-20 * listSize(l) + -260 * log(heapSize(res86._1))) + time) + -130 * (listSize(l) * log(heapSize(res86._1)))) + -40 <= 0)
+
+  def findMax(h: Heap) : BigInt = {
+    require(hasLeftistProperty(h) && h != Leaf())
+    h match {
+      case Node(_,m,_,_) => m
+      case Leaf() => -1000
+    }
+  }
+
+  @library
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h) && h != Leaf())
+    h match {
+      case Node(_,_,l,r) => merge(l, r)
+      case l @ Leaf() => l
+    }
+  } ensuring(res => hasLeftistProperty(res) && heapSize(h) - 1 == heapSize(res) && time <= 70 * leftRightHeight(h) + 7)
+
+  // @compose
+  def removeElements(h : Heap, l : List) : List = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Leaf() => l
+      case _ => removeElements(removeMax(h),Cons(findMax(h),l))
+    }
+  } ensuring(res => heapSize(h) + listSize(l) == listSize(res) &&
+      /*rec <= ? * heapSize(h) + ? &&*/
+      tpr <= ? * log(heapSize(h)) + ? /*&&
+      time <= ? * (heapSize(h) * log(heapSize(h))) + ? * heapSize(h) + ? * log(heapSize(h)) + ?*/)
+}
diff --git a/testcases/orb-testcases/composition/InsertionSort.scala b/testcases/orb-testcases/composition/InsertionSort.scala
new file mode 100644
index 000000000..483d30cbe
--- /dev/null
+++ b/testcases/orb-testcases/composition/InsertionSort.scala
@@ -0,0 +1,30 @@
+import leon.invariant._
+import leon.instrumentation._
+import leon.annotation._
+
+object InsertionSort {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail:List) extends List
+  case class Nil() extends List
+
+  def size(l : List) : BigInt = (l match {
+    case Cons(_, xs) => 1 + size(xs)
+    case _ => 0
+  })
+
+  def sortedIns(e: BigInt, l: List): List = {
+    l match {
+      case Cons(x,xs) => if (x <= e) Cons(x,sortedIns(e, xs)) else Cons(e, l)
+      case _ => Cons(e,Nil())
+    }
+  } ensuring(res => size(res) == size(l) + 1 && time <= ? * size(l) + ?)
+
+  @compose
+  def sort(l: List): List = (l match {
+    case Cons(x,xs) => sortedIns(x, sort(xs))
+    case _ => Nil()
+  }) ensuring(res => size(res) == size(l) &&
+        time <= ? * (size(l) * size(l)) + ? &&
+        rec <= ? * size(l) + ? &&
+        tpr <= ? * size(l) + ?)
+}
diff --git a/testcases/orb-testcases/composition/LeftistHeap.scala b/testcases/orb-testcases/composition/LeftistHeap.scala
new file mode 100644
index 000000000..5c2f2555a
--- /dev/null
+++ b/testcases/orb-testcases/composition/LeftistHeap.scala
@@ -0,0 +1,113 @@
+import leon.invariant._
+import leon.instrumentation._
+import leon.annotation._
+
+object LeftistHeap {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+
+  sealed abstract class Heap
+  case class Leaf() extends Heap
+  case class Node(rk : BigInt, value: BigInt, left: Heap, right: Heap) extends Heap
+
+  private def rightHeight(h: Heap) : BigInt = h match {
+    case Leaf() => 0
+    case Node(_,_,_,r) => rightHeight(r) + 1
+  }
+
+  private def rank(h: Heap) : BigInt = h match {
+    case Leaf() => 0
+    case Node(rk,_,_,_) => rk
+  }
+
+  private def hasLeftistProperty(h: Heap) : Boolean = (h match {
+    case Leaf() => true
+    case Node(_,_,l,r) => hasLeftistProperty(l) && hasLeftistProperty(r) && rightHeight(l) >= rightHeight(r) && (rank(h) == rightHeight(h))
+  })
+
+  @monotonic
+  def twopower(x: BigInt) : BigInt = {
+    require(x >= 0)
+    if(x < 1) 1
+    else
+      2* twopower(x - 1)
+  }
+
+  def heapSize(t: Heap): BigInt = {
+    require(hasLeftistProperty(t))
+    (t match {
+      case Leaf() => 0
+      case Node(_,v, l, r) => heapSize(l) + 1 + heapSize(r)
+    })
+  } ensuring (res => tmpl((a,b) => twopower(rightHeight(t)) <= a*res + b)/* _ >= 0*/)
+
+  def leftRightHeight(h: Heap) : BigInt = {h match {
+    case Leaf() => 0
+    case Node(_,_,l,r) => rightHeight(l)
+  }}
+
+  def listSize(l : List) : BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + listSize(xs)
+  }) ensuring(_ >= 0)
+
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,_,l,r) => merge(l, r)
+      case l @ Leaf() => l
+    }
+  } ensuring(res => /*hasLeftistProperty(res)*/ /*&& (if (h != Leaf()) heapSize(res) == heapSize(h) - 1 else true) &&*/ tmpl((a,b) => time <= a*leftRightHeight(h) + b))
+
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    h1 match {
+      case Leaf() => h2
+      case Node(_, v1, l1, r1) => h2 match {
+        case Leaf() => h1
+        case Node(_, v2, l2, r2) =>
+          if(v1 > v2)
+            makeT(v1, l1, merge(r1, h2))
+          else
+            makeT(v2, l2, merge(h1, r2))
+      }
+    }
+  } ensuring(res => hasLeftistProperty(res) && tmpl((a,b,c) => time <= a*rightHeight(h1) + b*rightHeight(h2) + c))
+
+  private def makeT(value: BigInt, left: Heap, right: Heap) : Heap = {
+    if(rank(left) >= rank(right))
+      Node(rank(right) + 1, value, left, right)
+    else
+      Node(rank(left) + 1, value, right, left)
+  }
+
+  def insert(element: BigInt, heap: Heap) : Heap = {
+    require(hasLeftistProperty(heap))
+    merge(Node(1, element, Leaf(), Leaf()), heap)
+  } ensuring(res => hasLeftistProperty(res) && tmpl((a,b,c) => time <= a*rightHeight(heap) + c))
+
+  /*def buildHeap(l : List, h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    l match {
+      case Nil() => h
+      case Cons(x,xs) => buildHeap(xs, insert(x, h))
+    }
+  } ensuring(res => hasLeftistProperty(res) && heapSize(h) + listSize(l) == heapSize(res) tmpl((a, b, c) => nonRecTime <= a*rightHeight(h) + b && rec <= listSize(l) + c))
+
+  def findMax(h: Heap) : BigInt = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,m,_,_) => m
+      case Leaf() => -1000
+    }
+  }
+
+  def removeElements(h : Heap, l : List) : List = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Leaf() => l
+      case _ => removeElements(removeMax(h),Cons(findMax(h),l))
+    }
+  }*/ //ensuring(res => /*heapSize(h) + listSize(l) == listSize(res)*/ tmpl((a, b, c) => nonRecTime <= a*leftRightHeight(h) + b /*&& rec <= heapSize(h) + c*/))
+}
diff --git a/testcases/orb-testcases/composition/MergeSort.scala b/testcases/orb-testcases/composition/MergeSort.scala
new file mode 100644
index 000000000..971237608
--- /dev/null
+++ b/testcases/orb-testcases/composition/MergeSort.scala
@@ -0,0 +1,150 @@
+import leon.invariant._
+import leon.instrumentation._
+<<<<<<< HEAD
+
+=======
+>>>>>>> b03689012b84b65708b49a01c70e68ceb6f413bf
+import leon.annotation._
+
+object MergeSort {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+<<<<<<< HEAD
+
+  @monotonic
+  def log(x: BigInt) : BigInt = {
+    require(x >= 0)
+    if(x <= 1) -1
+    else {
+      // val k = x/2
+      // 1 + log(x - k)
+      1 + log(x / 2)
+    }
+  } ensuring(res => true && res >= -1)
+
+  def size(list:List): BigInt = {list match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }} ensuring(res => true && res >= 0)
+=======
+
+  def size(list:List): BigInt = {list match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }} ensuring(res => res >= 0)
+>>>>>>> b03689012b84b65708b49a01c70e68ceb6f413bf
+
+  def length(l:List): BigInt = {
+    l match {
+      case Nil() => 0
+      case Cons(x,xs) => 1 + length(xs)
+    }
+<<<<<<< HEAD
+  } ensuring(res => res == size(l) /*&& tmpl((a,b) => time <= a*size(l) + b)*/)
+=======
+  } ensuring(res => res == size(l) && time <= ? *size(l) + ?)
+>>>>>>> b03689012b84b65708b49a01c70e68ceb6f413bf
+
+  def split(l:List,n:BigInt): (List,List) = {
+    require(n >= 0 && n <= size(l))
+    if (n <= 0) (Nil(),l)
+    else
+<<<<<<< HEAD
+    l match {
+        case Nil() => (Nil(),l)
+        case Cons(x,xs) => {
+          if(n == 1) (Cons(x,Nil()), xs)
+          else {
+            val (fst,snd) = split(xs, n-1)
+            (Cons(x,fst), snd)
+          }
+        }
+    }
+  } ensuring(res => size(res._2) == size(l) - n && size(res._1) == n && size(res._2) + size(res._1) == size(l) /*&& tmpl((a,b) => time <= a*n +b)*/)
+=======
+	l match {
+      case Nil() => (Nil(),l)
+      case Cons(x,xs) => {
+        if(n == 1) (Cons(x,Nil()), xs)
+        else {
+          val (fst,snd) = split(xs, n-1)
+          (Cons(x,fst), snd)
+        }
+      }
+	}
+  } ensuring(res => size(res._2) + size(res._1) == size(l) && time <= ? *n + ?)
+>>>>>>> b03689012b84b65708b49a01c70e68ceb6f413bf
+
+  def merge(aList:List, bList:List):List = (bList match {
+    case Nil() => aList
+    case Cons(x,xs) =>
+<<<<<<< HEAD
+      aList match {
+        case Nil() => bList
+        case Cons(y,ys) =>
+          if (y < x)
+            Cons(y,merge(ys, bList))
+          else
+            Cons(x,merge(aList, xs))
+     }
+  }) ensuring(res => size(aList) + size(bList) == size(res) /*&& tmpl((a,b,c) => time <= a*size(aList) + b*size(bList) + c)*/)
+
+  // @compose
+=======
+    	 aList match {
+   	       case Nil() => bList
+   	       case Cons(y,ys) =>
+    	        if (y < x)
+    		   Cons(y,merge(ys, bList))
+     		else
+		   Cons(x,merge(aList, xs))
+   	 }
+  }) ensuring(res => size(aList)+size(bList) == size(res) && time <= ? *size(aList) + ? *size(bList) + ?)
+
+  @compose
+>>>>>>> b03689012b84b65708b49a01c70e68ceb6f413bf
+  def mergeSort(list:List):List = {
+    list match {
+      case Cons(x,Nil()) => list
+      case Cons(_,Cons(_,_)) =>
+<<<<<<< HEAD
+        val lby2 = length(list)/2
+        val (fst,snd) = split(list,lby2)
+        merge(mergeSort(fst),mergeSort(snd))
+
+      case _ => list
+  }} ensuring(res => size(res) == size(list) &&
+       //time <= ? * (size(list) * size(list)) + ? &&
+       (if (size(list) >= 10) rec <= 1 * size(list) + 2 * log(size(list)) + 2 else true) &&
+       //tpr <= ? * size(list) + ?
+       true)
+
+
+  // def mergeSort(list : List): (List, BigInt) = {
+  //   val bd =
+  //     list match {
+  //       case Cons(x,Nil()) => (list, BigInt(0))
+  //       case Cons(_,Cons(_,_)) => {
+  //         val e23 = split(list, length(list) / BigInt(2));
+  //         val e32 = mergeSort(e23._1);
+  //         val e30 = mergeSort(e23._2);
+  //         (merge(e32._1, e30._1), ((BigInt(2) + e32._2) + e30._2))
+  //       }
+  //       case _ => (list, BigInt(0))
+  //     };
+  //   (bd._1, bd._2)
+  // }  ensuring(res => size(res._1) == size(list) &&
+  //      //time <= ? * (size(list) * size(list)) + ? &&
+  //      (if (size(list) >= 10) res._2 <= 1 * size(list) + 2 * log(size(list)) + 2 else true) &&
+  //      //tpr <= ? * size(list) + ?
+  //      true)
+=======
+         val lby2 = length(list)/2
+    	 val (fst,snd) = split(list,lby2)
+    	 merge(mergeSort(fst),mergeSort(snd))
+
+      case _ => list
+  }} ensuring(res => time <= ? *(size(list)*size(list)) + b && tpr <= ? *size(list) + ? && rec <= ? *size(list))
+>>>>>>> b03689012b84b65708b49a01c70e68ceb6f413bf
+}
diff --git a/testcases/orb-testcases/composition/QuickSort.scala b/testcases/orb-testcases/composition/QuickSort.scala
new file mode 100644
index 000000000..cff28d0a1
--- /dev/null
+++ b/testcases/orb-testcases/composition/QuickSort.scala
@@ -0,0 +1,44 @@
+import leon.invariant._
+import leon.instrumentation._
+import leon.annotation._
+
+object QuickSort {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+
+  def size(l:List): BigInt = {l match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }}
+
+  case class Triple(fst:List,snd:List, trd: List)
+
+  def append(aList:List,bList:List): List = {aList match {
+    case Nil() => bList
+    case Cons(x, xs) => Cons(x,append(xs,bList))
+  }} ensuring(res => size(res) == size(aList) + size(bList) && time <= ? *size(aList) + ?)
+
+  def partition(n:BigInt,l:List) : Triple = (l match {
+    case Nil() => Triple(Nil(), Nil(), Nil())
+    case Cons(x,xs) => {
+      val t = partition(n,xs)
+      if (n < x) Triple(t.fst, t.snd, Cons(x,t.trd))
+      else if(n == x) Triple(t.fst, Cons(x,t.snd), t.trd)
+      else Triple(Cons(x,t.fst), t.snd, t.trd)
+    }
+ }) ensuring(res => (size(l) == size(res.fst) + size(res.snd) + size(res.trd)) && time <= ? *size(l) + ?)
+
+  @compose
+  def quickSort(l:List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,Nil()) => l
+    case Cons(x,xs) => {
+      val t = partition(x, xs)
+      append(append(quickSort(t.fst), Cons(x, t.snd)), quickSort(t.trd))
+    }
+    case _ => l
+  })ensuring(res => size(res) == size(l) && time <= ? *(size(l)*size(l)) + ? *size(l) + ? &&
+      tpr <= ? *size(l) + ? && rec <= ? *size(l))
+}
+
diff --git a/testcases/orb-testcases/composition/Z3-exception-output.txt b/testcases/orb-testcases/composition/Z3-exception-output.txt
new file mode 100644
index 000000000..e1dab02bb
--- /dev/null
+++ b/testcases/orb-testcases/composition/Z3-exception-output.txt
@@ -0,0 +1,68 @@
+ Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
+[Warning ] Second case - Z3 AST: 281474976710656 tpe: BigInt
+[Warning ] Unexpected target type for BV value: BigInt
diff --git a/testcases/orb-testcases/depth/AVLTree.scala b/testcases/orb-testcases/depth/AVLTree.scala
new file mode 100644
index 000000000..b9a7cf520
--- /dev/null
+++ b/testcases/orb-testcases/depth/AVLTree.scala
@@ -0,0 +1,193 @@
+import leon.instrumentation._
+import leon.invariant._
+
+
+/**
+ * created by manos and modified by ravi.
+ * BST property cannot be verified
+ */
+object AVLTree  {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(left : Tree, value : BigInt, right: Tree, rank : BigInt) extends Tree
+
+  sealed abstract class OptionBigInt
+  case class None() extends OptionBigInt
+  case class Some(i: BigInt) extends OptionBigInt
+
+  def min(i1:BigInt, i2:BigInt) : BigInt = if (i1<=i2) i1 else i2
+  def max(i1:BigInt, i2:BigInt) : BigInt = if (i1>=i2) i1 else i2
+
+  /*def twopower(x: BigInt) : BigInt = {
+    //require(x >= 0)
+    if(x < 1) 1
+    else
+      3/2 * twopower(x - 1)
+  } ensuring(res => res >= 1 && tmpl((a) => a <= 0))*/
+
+  def rank(t: Tree) : BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(_,_,_,rk) => rk
+    }
+  }
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r, _) => {
+        val hl = height(l)
+        val hr = height(r)
+        max(hl,hr) + 1
+      }
+    }
+  }
+
+  def size(t: Tree): BigInt = {
+    //require(isAVL(t))
+    (t match {
+      case Leaf() => 0
+      case Node(l, _, r,_) => size(l) + 1 + size(r)
+    })
+
+  } ensuring (res => true && tmpl((a,b) => height(t) <= a*res + b))
+
+  def rankHeight(t: Tree) : Boolean = t match {
+    case Leaf() => true
+    case Node(l,_,r,rk) => rankHeight(l) && rankHeight(r) && rk == height(t)
+  }
+
+  def balanceFactor(t : Tree) : BigInt = {
+    t match{
+      case Leaf() => 0
+      case Node(l, _, r, _) => rank(l) - rank(r)
+    }
+  }
+
+  /*def isAVL(t:Tree) : Boolean = {
+    t match {
+        case Leaf() => true
+        case Node(l,_,r,rk) =>  isAVL(l) && isAVL(r) && balanceFactor(t) >= -1 && balanceFactor(t) <= 1 && rankHeight(t) //isBST(t) &&
+      }
+  }*/
+
+  def unbalancedInsert(t: Tree, e : BigInt) : Tree = {
+    t match {
+      case Leaf() => Node(Leaf(), e, Leaf(), 1)
+      case Node(l,v,r,h) =>
+             if (e == v) t
+        else if (e <  v){
+          val newl = avlInsert(l,e)
+          Node(newl, v, r, max(rank(newl), rank(r)) + 1)
+        }
+        else {
+          val newr = avlInsert(r,e)
+          Node(l, v, newr, max(rank(l), rank(newr)) + 1)
+        }
+    }
+  }
+
+  def avlInsert(t: Tree, e : BigInt) : Tree = {
+
+    balance(unbalancedInsert(t,e))
+
+  } ensuring(res => true && tmpl((a,b) => depth <= a*height(t) + b))
+  //minbound: ensuring(res => time <= 138*height(t) + 19)
+
+  def deleteMax(t: Tree): (Tree, OptionBigInt) = {
+
+    t match {
+      case Node(Leaf(), v, Leaf(), _) => (Leaf(), Some(v))
+      case Node(l, v, Leaf(), _) => {
+        val (newl, opt) =  deleteMax(l)
+        opt match {
+          case None() => (t, None())
+          case Some(lmax) => {
+            val newt = balance(Node(newl, lmax, Leaf(), rank(newl) + 1))
+            (newt, Some(v))
+          }
+        }
+      }
+      case Node(_, _, r, _) => deleteMax(r)
+      case _ => (t, None())
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*height(t) + b))
+
+  def unbalancedDelete(t: Tree, e: BigInt): Tree = {
+    t match {
+      case Leaf() => Leaf() //not found case
+      case Node(l, v, r, h) =>
+        if (e == v) {
+          if (l == Leaf()) r
+          else if(r == Leaf()) l
+          else {
+            val (newl, opt) = deleteMax(l)
+            opt match {
+              case None() => t
+              case Some(newe) => {
+                Node(newl, newe, r, max(rank(newl), rank(r)) + 1)
+              }
+            }
+          }
+        } else if (e < v) {
+          val newl = avlDelete(l, e)
+          Node(newl, v, r, max(rank(newl), rank(r)) + 1)
+        } else {
+          val newr = avlDelete(r, e)
+          Node(l, v, newr, max(rank(l), rank(newr)) + 1)
+        }
+    }
+  }
+
+  def avlDelete(t: Tree, e: BigInt): Tree = {
+
+    balance(unbalancedDelete(t, e))
+
+  } ensuring(res => true && tmpl((a,b) => depth <= a*height(t) + b))
+
+  def balance(t:Tree) : Tree = {
+    t match {
+      case Leaf() => Leaf() // impossible...
+      case Node(l, v, r, h) =>
+        val bfactor = balanceFactor(t)
+        // at this poBigInt, the tree is unbalanced
+        if(bfactor > 1 ) { // left-heavy
+          val newL =
+            if (balanceFactor(l) < 0) { // l is right heavy
+              rotateLeft(l)
+            }
+            else l
+          rotateRight(Node(newL,v,r, max(rank(newL), rank(r)) + 1))
+        }
+        else if(bfactor < -1) {
+          val newR =
+            if (balanceFactor(r) > 0) { // r is left heavy
+              rotateRight(r)
+            }
+            else r
+          rotateLeft(Node(l,v,newR, max(rank(newR), rank(l)) + 1))
+        } else t
+      }
+  }
+
+  def rotateRight(t:Tree) = {
+    t match {
+      case Node(Node(ll, vl, rl, _),v,r, _) =>
+
+        val hr = max(rank(rl),rank(r)) + 1
+        Node(ll, vl, Node(rl,v,r,hr), max(rank(ll),hr) + 1)
+
+      case _ => t // this should not happen
+  } }
+
+
+  def rotateLeft(t:Tree) =  {
+    t match {
+      case Node(l, v, Node(lr,vr,rr,_), _) =>
+
+        val hl = max(rank(l),rank(lr)) + 1
+        Node(Node(l,v,lr,hl), vr, rr, max(hl, rank(rr)) + 1)
+      case _ => t // this should not happen
+  } }
+}
+
diff --git a/testcases/orb-testcases/depth/AmortizedQueue.scala b/testcases/orb-testcases/depth/AmortizedQueue.scala
new file mode 100644
index 000000000..1678d8980
--- /dev/null
+++ b/testcases/orb-testcases/depth/AmortizedQueue.scala
@@ -0,0 +1,86 @@
+import leon.instrumentation._
+import leon.invariant._
+
+object AmortizedQueue {
+  sealed abstract class List
+  case class Cons(head : BigInt, tail : List) extends List
+  case class Nil() extends List
+
+  case class Queue(front : List, rear : List)
+
+  def size(list : List) : BigInt = (list match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + size(xs)
+  })
+
+  def sizeList(list : List) : BigInt = (list match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + sizeList(xs)
+  }) ensuring(res => res >= 0 && tmpl((a,b) => depth <= a*size(list) + b))
+
+  def qsize(q : Queue) : BigInt = size(q.front) + size(q.rear)
+
+  def asList(q : Queue) : List = concat(q.front, reverse(q.rear))
+
+  def concat(l1 : List, l2 : List) : List = (l1 match {
+    case Nil() => l2
+    case Cons(x,xs) => Cons(x, concat(xs, l2))
+
+  }) ensuring (res => size(res) == size(l1) + size(l2) && tmpl((a,b,c) => depth <= a*size(l1) + b))
+
+  def isAmortized(q : Queue) : Boolean = sizeList(q.front) >= sizeList(q.rear)
+
+  def isEmpty(queue : Queue) : Boolean = queue match {
+    case Queue(Nil(), Nil()) => true
+    case _ => false
+  }
+
+  def reverseRec(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => reverseRec(xs, Cons(x, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => depth <= a*size(l1) + b))
+
+  def reverse(l: List): List = {
+    reverseRec(l, Nil())
+  } ensuring (res => size(l) == size(res) && tmpl((a,b) => depth <= a*size(l) + b))
+
+  def amortizedQueue(front : List, rear : List) : Queue = {
+    if (sizeList(rear) <= sizeList(front))
+      Queue(front, rear)
+    else
+      Queue(concat(front, reverse(rear)), Nil())
+  }
+
+  def enqueue(q : Queue, elem : BigInt) : Queue = ({
+
+    amortizedQueue(q.front, Cons(elem, q.rear))
+
+  }) ensuring(res =>  true && tmpl((a,b) => depth <= a*qsize(q) + b))
+
+  def dequeue(q : Queue) : Queue = {
+    require(isAmortized(q) && !isEmpty(q))
+    q match {
+      case Queue(Cons(f, fs), rear) => amortizedQueue(fs, rear)
+      case _ => Queue(Nil(),Nil())
+    }
+  } ensuring(res =>  true && tmpl((a,b) => depth <= a*qsize(q) + b))
+
+  def removeLast(l : List) : List = {
+    require(l != Nil())
+    l match {
+      case Cons(x,Nil()) => Nil()
+      case Cons(x,xs) => Cons(x, removeLast(xs))
+      case _ => Nil()
+    }
+  } ensuring(res =>  size(res) <= size(l) && tmpl((a,b) => depth <= a*size(l) + b))
+
+  def pop(q : Queue) : Queue = {
+    require(isAmortized(q) && !isEmpty(q))
+    q match {
+     case Queue(front, Cons(r,rs)) => Queue(front, rs)
+     case Queue(front, rear) => Queue(removeLast(front), rear)
+     case _ => Queue(Nil(),Nil())
+    }
+  } ensuring(res =>  true && tmpl((a,b) => depth <= a*size(q.front) + b))
+}
diff --git a/testcases/orb-testcases/depth/BinaryTrie.scala b/testcases/orb-testcases/depth/BinaryTrie.scala
new file mode 100755
index 000000000..562ab19ea
--- /dev/null
+++ b/testcases/orb-testcases/depth/BinaryTrie.scala
@@ -0,0 +1,121 @@
+import leon.instrumentation._
+import leon.invariant._
+
+import scala.collection.immutable.Set
+
+object ParallelBinaryTrie {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(nvalue: BigInt, left: Tree, right: Tree) extends Tree
+
+  sealed abstract class IList
+  case class Cons(head: BigInt, tail: IList) extends IList
+  case class Nil() extends IList
+
+  def listSize(l: IList): BigInt = (l match {
+    case Nil() => 0
+    case Cons(x, xs) => 1 + listSize(xs)
+  })
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(x, l, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def find(inp: IList, t: Tree): Tree = {
+    inp match {
+      case Nil() => t
+      case Cons(x, Nil()) => t
+      case Cons(x, xs @ Cons(y, _)) => {
+        t match {
+          case Leaf() => t
+          case Node(v, l, r) => {
+            if (y > 0) find(xs, l) else find(xs, r)
+          }
+        }
+      }
+      case _ => t
+    }
+  } ensuring (res => true && tmpl ((a, c) => depth <= a * listSize(inp) + c))
+
+  def insert(inp: IList, t: Tree): Tree = {
+    t match {
+      case Leaf() => {
+        inp match {
+          case Nil() => t
+          case Cons(x, xs) => {
+            val newch = insert(xs, Leaf())
+            newch match {
+              case Leaf() => Node(x, Leaf(), Leaf())
+              case Node(y, _, _) => if (y > 0) Node(x, newch, Leaf()) else Node(y, Leaf(), newch)
+            }
+          }
+        }
+
+      }
+      case Node(v, l, r) => {
+        inp match {
+          case Nil() => t
+          case Cons(x, Nil()) => t
+          case Cons(x, xs @ Cons(y, _)) => {
+            val ch = if (y > 0) l else r
+            if (y > 0)
+              Node(v, insert(xs, ch), r)
+            else
+              Node(v, l, insert(xs, ch))
+          }
+          case _ => t
+        }
+      }
+    }
+  } ensuring (res => true && tmpl ((a, c) => depth <= a * listSize(inp) + c))
+
+  def create(inp: IList): Tree = {
+    insert(inp, Leaf())
+  } ensuring (res => true && tmpl ((a, c) => depth <= a * listSize(inp) + c))
+
+  def delete(inp: IList, t: Tree): Tree = {
+    t match {
+        case Leaf() => {
+          inp match {
+            case Nil() => Leaf()
+            case Cons(x ,xs) => {
+              //the input is not in the tree, so do nothing
+              Leaf()
+            }
+          }
+        }
+        case Node(v, l, r) => {
+          inp match {
+            case Nil() => {
+              //the tree has extensions of the input list so do nothing
+              t
+            }
+            case Cons(x, Nil()) => {
+              //if "l" and "r" are nil, remove the node
+              if(l == Leaf() && r == Leaf()) Leaf()
+              else t
+            }
+            case Cons(x ,xs@Cons(y, _)) => {
+              val ch = if(y > 0) l else r
+              val newch = delete(xs, ch)
+              if(newch == Leaf() && ((y > 0 && r == Leaf()) || (y <= 0 && l == Leaf()))) Leaf()
+              else {
+                if(y > 0)
+        		  Node(v, newch, r)
+        	    else
+        	      Node(v, l, newch)
+              }
+            }
+            case _ => t
+        }
+      }
+    }
+  } ensuring (res => true && tmpl ((a, c) => depth <= a * listSize(inp) + c))
+}
diff --git a/testcases/orb-testcases/depth/BinomialHeap.scala b/testcases/orb-testcases/depth/BinomialHeap.scala
new file mode 100644
index 000000000..7dd9e613c
--- /dev/null
+++ b/testcases/orb-testcases/depth/BinomialHeap.scala
@@ -0,0 +1,199 @@
+/**
+ * @author Ravi
+ **/
+import leon.instrumentation._
+import leon.invariant._
+
+
+object BinomialHeap {
+  sealed abstract class BinomialTree
+  case class Node(rank: BigInt, elem: Element, children: BinomialHeap) extends BinomialTree
+
+  sealed abstract class ElementAbs
+  case class Element(n: BigInt) extends ElementAbs
+
+  sealed abstract class BinomialHeap
+  case class ConsHeap(head: BinomialTree, tail: BinomialHeap) extends BinomialHeap
+  case class NilHeap() extends BinomialHeap
+
+  sealed abstract class List
+  case class NodeL(head: BinomialHeap, tail: List) extends List
+  case class NilL() extends List
+
+  sealed abstract class OptionalTree
+  case class Some(t : BinomialTree) extends OptionalTree
+  case class None() extends OptionalTree
+
+  /* Lower or Equal than for Element structure */
+  private def leq(a: Element, b: Element) : Boolean = {
+    a match {
+      case Element(a1) => {
+        b match {
+          case Element(a2) => {
+            if(a1 <= a2) true
+            else false
+          }
+        }
+      }
+    }
+  }
+
+  /* isEmpty function of the Binomial Heap */
+  def isEmpty(t: BinomialHeap) = t match {
+    case ConsHeap(_,_) => false
+    case NilHeap() => true
+  }
+
+  /* Helper function to determine rank of a BinomialTree */
+  def rank(t: BinomialTree) : BigInt =  t match {
+    case Node(r, _, _) => r
+  }
+
+  /* Helper function to get the root element of a BinomialTree */
+  def root(t: BinomialTree) : Element = t match {
+    case Node(_, e, _) => e
+  }
+
+  /* Linking trees of equal ranks depending on the root element */
+  def link(t1: BinomialTree, t2: BinomialTree) : BinomialTree = {
+    t1 match {
+        case Node(r, x1, c1) => {
+          t2 match {
+            case Node(_, x2, c2) => {
+              if (leq(x1,x2)) {
+                  Node(r+1, x1, ConsHeap(t2, c1))
+              } else {
+                  Node(r+1, x2, ConsHeap(t1, c2))
+              }
+            }
+          }
+        }
+    }
+  }
+
+  def treeNum(h: BinomialHeap) : BigInt = {
+    h match {
+      case ConsHeap(head, tail) =>  1 + treeNum(tail)
+      case NilHeap() => 0
+    }
+  }
+
+  /* Insert a tree into a binomial heap. The tree should be correct in relation to the heap */
+  def insTree(t: BinomialTree, h: BinomialHeap) : BinomialHeap = {
+    h match {
+      case ConsHeap(head, tail) =>  {
+        if (rank(t) < rank(head)) {
+          ConsHeap(t, h)
+        } else if (rank(t) > rank(head)) {
+          ConsHeap(head, insTree(t,tail))
+        } else {
+          insTree(link(t,head), tail)
+        }
+      }
+      case NilHeap() => ConsHeap(t, NilHeap())
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*treeNum(h) + b))
+
+  /* Merge two heaps together */
+  def merge(h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    h1 match {
+      case ConsHeap(head1, tail1) => {
+        h2 match {
+          case ConsHeap(head2, tail2) => {
+            if (rank(head1) < rank(head2)) {
+              ConsHeap(head1, merge(tail1, h2))
+            } else if (rank(head2) < rank(head1)) {
+              ConsHeap(head2, merge(h1, tail2))
+            } else {
+              mergeWithCarry(link(head1, head2), tail1, tail2)
+            }
+          }
+          case NilHeap() => h1
+        }
+      }
+      case NilHeap() => h2
+    }
+  } ensuring(res => true && tmpl((a,b,c) => depth <= a*treeNum(h1) + b*treeNum(h2) + c))
+
+  def mergeWithCarry(t: BinomialTree, h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    t match {
+      case Node(r, _, _) => {
+        h1 match {
+          case ConsHeap(head1, tail1) => {
+            h2 match {
+              case ConsHeap(head2, tail2) => {
+                if (rank(head1) < rank(head2)) {
+
+                  if (rank(t) < rank(head1))
+                    ConsHeap(t, ConsHeap(head1, merge(tail1, h2)))
+                  else
+                    mergeWithCarry(link(t, head1), tail1, h2)
+
+                } else if (rank(head2) < rank(head1)) {
+
+                  if (rank(t) < rank(head2))
+                    ConsHeap(t, ConsHeap(head2, merge(h1, tail2)))
+                  else
+                    mergeWithCarry(link(t, head2), h1, tail2)
+
+                } else {
+                  ConsHeap(t, mergeWithCarry(link(head1, head2), tail1, tail2))
+                }
+              }
+              case NilHeap() => {
+                insTree(t, h1)
+              }
+            }
+          }
+          case NilHeap() => insTree(t, h2)
+        }
+      }
+    }
+  } ensuring (res => true && tmpl ((d, e, f) => depth <= d * treeNum(h1) + e * treeNum(h2) + f))
+
+  //Auxiliary helper function to simplify findMin and deleteMin
+  def removeMinTree(h: BinomialHeap): (OptionalTree, BinomialHeap) = {
+    h match {
+      case ConsHeap(head, NilHeap()) => (Some(head), NilHeap())
+      case ConsHeap(head1, tail1) => {
+        val (opthead2, tail2) = removeMinTree(tail1)
+        opthead2 match {
+          case None() => (Some(head1), tail1)
+          case Some(head2) =>
+            if (leq(root(head1), root(head2))) {
+              (Some(head1), tail1)
+            } else {
+              (Some(head2), ConsHeap(head1, tail2))
+            }
+        }
+      }
+      case _ => (None(), NilHeap())
+    }
+  } ensuring (res => treeNum(res._2) <= treeNum(h) && tmpl ((a, b) => depth <= a*treeNum(h) + b))
+
+  /*def findMin(h: BinomialHeap) : Element = {
+	  val (opt, _) = removeMinTree(h)
+	  opt match {
+	    case Some(Node(_,e,ts1)) => e
+	    case _ => Element(-1)
+	  }
+  } ensuring(res => true && tmpl((a,b) => time <= a*treeNum(h) + b))*/
+
+  def minTreeChildren(h: BinomialHeap) : BigInt = {
+    val (min, _) = removeMinTree(h)
+    min match {
+      case None() => 0
+      case Some(Node(_,_,ch)) => treeNum(ch)
+	}
+  }
+
+  // Discard the minimum element of the extracted min tree and put its children back into the heap
+  def deleteMin(h: BinomialHeap) : BinomialHeap = {
+	  val (min, ts2) = removeMinTree(h)
+	  min match {
+		case Some(Node(_,_,ts1)) => merge(ts1, ts2)
+		case _ => h
+	  }
+  } ensuring(res => true && tmpl((a,b,c) => depth <= a*minTreeChildren(h) + b*treeNum(h) + c))
+
+}
diff --git a/testcases/orb-testcases/depth/ConcatVariations.scala b/testcases/orb-testcases/depth/ConcatVariations.scala
new file mode 100644
index 000000000..aea7080d6
--- /dev/null
+++ b/testcases/orb-testcases/depth/ConcatVariations.scala
@@ -0,0 +1,42 @@
+import leon.instrumentation._
+import leon.invariant._
+
+
+object ConcatVariations {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def genL(n: BigInt): List = {
+    require(n >= 0)
+    if (n == 0) Nil()
+    else
+      Cons(n, genL(n - 1))
+  } ensuring (res => size(res) == n && tmpl((a,b) => depth <= a*n + b))
+
+  def append(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => Cons(x, append(xs, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => depth <= a*size(l1) + b))
+
+  def f_good(m: BigInt, n: BigInt): List = {
+    require(0 <= m && 0 <= n)
+    if (m == 0) Nil()
+    else append(genL(n), f_good(m - 1, n))
+
+  } ensuring(res => size(res) == n*m && tmpl((a,b,c,d) => depth <= a*(n*m) + b*n + c*m +d))
+
+  def f_worst(m: BigInt, n: BigInt): List = {
+    require(0 <= m && 0 <= n)
+
+    if (m == 0) Nil()
+    else append(f_worst(m - 1, n), genL(n))
+
+  } ensuring(res => size(res) == n*m && tmpl((a,c,d,e,f) => depth <= a*((n*m)*m)+c*(n*m)+d*n+e*m+f))
+}
diff --git a/testcases/orb-testcases/depth/Folds.scala b/testcases/orb-testcases/depth/Folds.scala
new file mode 100755
index 000000000..305446be5
--- /dev/null
+++ b/testcases/orb-testcases/depth/Folds.scala
@@ -0,0 +1,82 @@
+import leon.instrumentation._
+import leon.invariant._
+
+
+object TreeMaps {
+
+  sealed abstract class Tree
+  case class Node(left: Tree, value: BigInt, right: Tree) extends Tree
+  case class Leaf() extends Tree
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def parallelSearch(elem : BigInt, t : Tree) : Boolean = {
+    t match {
+      case Leaf() => false
+      case Node(l, x, r) =>
+        if(x == elem) true
+        else {
+          val r1 = parallelSearch(elem, r)
+          val r2 = parallelSearch(elem, l)
+          if(r1 || r2) true
+          else false
+        }
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*height(t) + b))
+
+
+  def squareMap(t : Tree) : Tree = {
+    t match {
+      case Leaf() => t
+      case Node(l, x, r) =>
+        val nl = squareMap(l)
+        val nr = squareMap(r)
+        Node(nl, x*x, nr)
+    }
+  } ensuring (res => true && tmpl((a,b) => depth <= a*height(t) + b))
+
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def fact(n : BigInt) : BigInt = {
+    require(n >= 0)
+
+    if(n == 1 || n == 0) BigInt(1)
+    else n * fact(n-1)
+
+  } ensuring(res => tmpl((a,b) => depth <= a*n + b))
+
+  def descending(l: List, k: BigInt) : Boolean = {
+    l match {
+      case Nil() => true
+      case Cons(x, t) => x > 0 && x <= k && descending(t, x-1)
+    }
+  }
+
+  def factMap(l: List, k: BigInt): List = {
+    require(descending(l, k) && k >= 0)
+
+   l match {
+    case Nil() => Nil()
+    case Cons(x, t) =>  {
+      val f = fact(x)
+      Cons(f, factMap(t, x-1))
+    }
+
+  }} ensuring(res => true && tmpl((a,b) => depth <= a*k + b))
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/depth/ForElimParallel.scala b/testcases/orb-testcases/depth/ForElimParallel.scala
new file mode 100644
index 000000000..a065af8f3
--- /dev/null
+++ b/testcases/orb-testcases/depth/ForElimParallel.scala
@@ -0,0 +1,119 @@
+import leon.instrumentation._
+import leon.invariant._
+
+
+object ForElimination {
+
+  sealed abstract class Tree
+  case class Node(left: Tree, value: Statement, right: Tree) extends Tree
+  case class Leaf() extends Tree
+
+  sealed abstract class Statement
+  case class Print(msg: BigInt, varID: BigInt) extends Statement
+  case class Assign(varID: BigInt, expr: Expression) extends Statement
+  case class Skip() extends Statement
+  case class Block(body: Tree) extends Statement
+  case class IfThenElse(expr: Expression, then: Statement, elze: Statement) extends Statement
+  case class While(expr: Expression, body: Statement) extends Statement
+  case class For(init: Statement, expr: Expression, step: Statement, body: Statement) extends Statement
+
+  sealed abstract class Expression
+  case class Var(varID: BigInt) extends Expression
+  case class BigIntLiteral(value: BigInt) extends Expression
+  case class Plus(lhs: Expression, rhs: Expression) extends Expression
+  case class Minus(lhs: Expression, rhs: Expression) extends Expression
+  case class Times(lhs: Expression, rhs: Expression) extends Expression
+  case class Division(lhs: Expression, rhs: Expression) extends Expression
+  case class Equals(lhs: Expression, rhs: Expression) extends Expression
+  case class LessThan(lhs: Expression, rhs: Expression) extends Expression
+  case class And(lhs: Expression, rhs: Expression) extends Expression
+  case class Or(lhs: Expression, rhs: Expression) extends Expression
+  case class Not(expr: Expression) extends Expression
+
+  /*def sizeStat(st: Statement) : BigInt =  st match {
+    case Block(l) => sizeList(l) + 1
+    case IfThenElse(c,th,el) => sizeStat(th) + sizeStat(el) + 1
+    case While(c,b) => sizeStat(b) + 1
+    case For(init,cond,step,body) => sizeStat(init) + sizeStat(step) + sizeStat(body)
+    case other => 1
+  }
+
+  def sizeTree(l: List) : BigInt = l match {
+    case Node(l,x,r) => sizeTree(l) + sizeTree(r) + sizeStat(x)
+    case Nil() => 0
+  }*/
+
+  def max(x: BigInt, y: BigInt) = if(x >= y) x else y
+
+  def depthStat(st: Statement) : BigInt =  st match {
+    case Block(t) => depthTree(t) + 1
+    case IfThenElse(c,th,el) => max(depthStat(th),depthStat(el)) + 1
+    case While(c,b) => depthStat(b) + 1
+    case For(init,cond,step,body) => max(max(depthStat(init),depthStat(step)),depthStat(body))
+    case other => 1
+  }
+
+  def depthTree(t: Tree) : BigInt = t match {
+    case Node(l,x,r) => max(max(depthTree(l),depthTree(r)),depthStat(x)) + 1
+    case Leaf() => 0
+  }
+
+  /*def isForFree(stat: Statement): Boolean = (stat match {
+    case Block(body) => isForFreeTree(body)
+    case IfThenElse(_, then, elze) => isForFree(then) && isForFree(elze)
+    case While(_, body) => isForFree(body)
+    case For(_,_,_,_) => false
+    case _ => true
+  })  ensuring(res => true && tmpl((a,b) => depth <= a*depthStat(stat) + b))
+
+  def isForFreeTree(t: Tree): Boolean = (t match {
+    case Leaf() => true
+    case Node(l, x, r) => isForFree(x) && isForFreeTree(l) && isForFreeTree(r)
+  })  ensuring(res => true && tmpl((a,b) => depth <= a*depthTree(t) + b))*/
+
+  /*def forLoopsWellFormedTree(t: Tree): Boolean = (t match {
+    case Leaf() => true
+    case Node(l, x, r) => forLoopsWellFormed(x) && forLoopsWellFormedTree(l) && forLoopsWellFormedTree(r)
+  }) ensuring(res => true && tmpl((a,b) => depth <= a*depthTree(t) + b))
+
+  def forLoopsWellFormed(stat: Statement): Boolean = (stat match {
+    case Block(body) => forLoopsWellFormedTree(body)
+    case IfThenElse(_, then, elze) => forLoopsWellFormed(then) && forLoopsWellFormed(elze)
+    case While(_, body) => forLoopsWellFormed(body)
+    case For(init, _, step, body) => isForFree(init) && isForFree(step) && forLoopsWellFormed(body)
+    case _ => true
+  }) ensuring(res => true && tmpl((a,b) => depth <= a*depthStat(stat) + b))*/
+
+  def eliminateWhileLoopsTree(t: Tree): Tree = {
+    t match {
+      case Leaf() => Leaf()
+      case Node(l,x,r) => Node(eliminateWhileLoopsTree(l), eliminateWhileLoops(x), eliminateWhileLoopsTree(r))
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*depthTree(t) + b))
+
+  def eliminateWhileLoops(stat: Statement): Statement = (stat match {
+    case Block(body) => Block(eliminateWhileLoopsTree(body))
+    case IfThenElse(expr, then, elze) => IfThenElse(expr, eliminateWhileLoops(then), eliminateWhileLoops(elze))
+    case While(expr, body) => For(Skip(), expr, Skip(), eliminateWhileLoops(body))
+    case For(init, expr, step, body) => For(eliminateWhileLoops(init), expr, eliminateWhileLoops(step), eliminateWhileLoops(body))
+    case other => other
+  }) ensuring(res => true && tmpl((a,b) => depth <= a*depthStat(stat) + b))
+
+  /*def eliminateForLoopsTree(t: Tree): Tree = {
+    t match {
+      case Leaf() => Leaf()
+      case Node(l,x,r) => Node(eliminateForLoopsTree(l), eliminateForLoops(x), eliminateForLoopsTree(r))
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*depthTree(t) + b))
+
+  def eliminateForLoops(stat: Statement): Statement = {
+    stat match {
+      case Block(body) => Block(eliminateForLoopsTree(body))
+      case IfThenElse(expr, then, elze) => IfThenElse(expr, eliminateForLoops(then), eliminateForLoops(elze))
+      case While(expr, body) => While(expr, eliminateForLoops(body))
+      case For(init, expr, step, body) => Block(Node(Leaf(),eliminateForLoops(init),Node(Leaf(),
+          While(expr, Block(Node(Leaf(),eliminateForLoops(body), Node(Leaf(),eliminateForLoops(step), Leaf())))),Leaf())))
+      case other => other
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*depthStat(stat) + b))*/
+}
diff --git a/testcases/orb-testcases/depth/ForElimination.scala b/testcases/orb-testcases/depth/ForElimination.scala
new file mode 100644
index 000000000..b1c5ba98f
--- /dev/null
+++ b/testcases/orb-testcases/depth/ForElimination.scala
@@ -0,0 +1,103 @@
+import leon.instrumentation._
+import leon.invariant._
+
+
+object ForElimination {
+
+  sealed abstract class List
+  case class Nil() extends List
+  case class Cons(head: Statement, tail: List) extends List
+
+  sealed abstract class Statement
+  case class Print(msg: BigInt, varID: BigInt) extends Statement
+  case class Assign(varID: BigInt, expr: Expression) extends Statement
+  case class Skip() extends Statement
+  case class Block(body: List) extends Statement
+  case class IfThenElse(expr: Expression, thenExpr: Statement, elseExpr: Statement) extends Statement
+  case class While(expr: Expression, body: Statement) extends Statement
+  case class For(init: Statement, expr: Expression, step: Statement, body: Statement) extends Statement
+
+  sealed abstract class Expression
+  case class Var(varID: BigInt) extends Expression
+  case class BigIntLiteral(value: BigInt) extends Expression
+  case class Plus(lhs: Expression, rhs: Expression) extends Expression
+  case class Minus(lhs: Expression, rhs: Expression) extends Expression
+  case class Times(lhs: Expression, rhs: Expression) extends Expression
+  case class Division(lhs: Expression, rhs: Expression) extends Expression
+  case class Equals(lhs: Expression, rhs: Expression) extends Expression
+  case class LessThan(lhs: Expression, rhs: Expression) extends Expression
+  case class And(lhs: Expression, rhs: Expression) extends Expression
+  case class Or(lhs: Expression, rhs: Expression) extends Expression
+  case class Not(expr: Expression) extends Expression
+
+  def sizeStat(st: Statement) : BigInt =  st match {
+    case Block(l) => sizeList(l) + 1
+    case IfThenElse(c,th,el) => sizeStat(th) + sizeStat(el) + 1
+    case While(c,b) => sizeStat(b) + 1
+    case For(init,cond,step,body) => sizeStat(init) + sizeStat(step) + sizeStat(body)
+    case other => 1
+  }
+
+  def sizeList(l: List) : BigInt = l match {
+    case Cons(h,t) => sizeStat(h) + sizeList(t)
+    case Nil() => 0
+  }
+
+  def isForFree(stat: Statement): Boolean = (stat match {
+    case Block(body) => isForFreeList(body)
+    case IfThenElse(_, thenExpr, elseExpr) => isForFree(thenExpr) && isForFree(elseExpr)
+    case While(_, body) => isForFree(body)
+    case For(_,_,_,_) => false
+    case _ => true
+  })  ensuring(res => true && tmpl((a,b) => depth <= a*sizeStat(stat) + b))
+
+  def isForFreeList(l: List): Boolean = (l match {
+    case Nil() => true
+    case Cons(x, xs) => isForFree(x) && isForFreeList(xs)
+  })  ensuring(res => true && tmpl((a,b) => depth <= a*sizeList(l) + b))
+
+  def forLoopsWellFormedList(l: List): Boolean = (l match {
+    case Nil() => true
+    case Cons(x, xs) => forLoopsWellFormed(x) && forLoopsWellFormedList(xs)
+  }) ensuring(res => true && tmpl((a,b) => depth <= a*sizeList(l) + b))
+
+  def forLoopsWellFormed(stat: Statement): Boolean = (stat match {
+    case Block(body) => forLoopsWellFormedList(body)
+    case IfThenElse(_, thenExpr, elseExpr) => forLoopsWellFormed(thenExpr) && forLoopsWellFormed(elseExpr)
+    case While(_, body) => forLoopsWellFormed(body)
+    case For(init, _, step, body) => isForFree(init) && isForFree(step) && forLoopsWellFormed(body)
+    case _ => true
+  }) ensuring(res => true && tmpl((a,b) => depth <= a*sizeStat(stat) + b))
+
+  def eliminateWhileLoopsList(l: List): List = {
+    l match {
+      case Nil() => Nil()
+      case Cons(x, xs) => Cons(eliminateWhileLoops(x), eliminateWhileLoopsList(xs))
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*sizeList(l) + b))
+
+  def eliminateWhileLoops(stat: Statement): Statement = (stat match {
+    case Block(body) => Block(eliminateWhileLoopsList(body))
+    case IfThenElse(expr, thenExpr, elseExpr) => IfThenElse(expr, eliminateWhileLoops(thenExpr), eliminateWhileLoops(elseExpr))
+    case While(expr, body) => For(Skip(), expr, Skip(), eliminateWhileLoops(body))
+    case For(init, expr, step, body) => For(eliminateWhileLoops(init), expr, eliminateWhileLoops(step), eliminateWhileLoops(body))
+    case other => other
+  }) ensuring(res => true && tmpl((a,b) => depth <= a*sizeStat(stat) + b))
+
+  def eliminateForLoopsList(l: List): List = {
+    l match {
+      case Nil() => Nil()
+      case Cons(x, xs) => Cons(eliminateForLoops(x), eliminateForLoopsList(xs))
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*sizeList(l) + b))
+
+  def eliminateForLoops(stat: Statement): Statement = {
+    stat match {
+      case Block(body) => Block(eliminateForLoopsList(body))
+      case IfThenElse(expr, thenExpr, elseExpr) => IfThenElse(expr, eliminateForLoops(thenExpr), eliminateForLoops(elseExpr))
+      case While(expr, body) => While(expr, eliminateForLoops(body))
+      case For(init, expr, step, body) => Block(Cons(eliminateForLoops(init), Cons(While(expr, Block(Cons(eliminateForLoops(body), Cons(eliminateForLoops(step), Nil())))), Nil())))
+      case other => other
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*sizeStat(stat) + b))
+}
diff --git a/testcases/orb-testcases/depth/InsertionSort.scala b/testcases/orb-testcases/depth/InsertionSort.scala
new file mode 100644
index 000000000..e52adc62f
--- /dev/null
+++ b/testcases/orb-testcases/depth/InsertionSort.scala
@@ -0,0 +1,28 @@
+import scala.collection.immutable.Set
+import leon.instrumentation._
+import leon.invariant._
+
+
+object InsertionSort {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+
+  def size(l : List) : BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + size(xs)
+  })
+
+  def sortedIns(e: BigInt, l: List): List = {
+    l match {
+      case Nil() => Cons(e,Nil())
+      case Cons(x,xs) => if (x <= e) Cons(x,sortedIns(e, xs)) else Cons(e, l)
+    }
+  } ensuring(res => size(res) == size(l) + 1 && tmpl((a,b) => depth <= a*size(l) +b))
+
+  def sort(l: List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,xs) => sortedIns(x, sort(xs))
+
+  }) ensuring(res => size(res) == size(l) && tmpl((a,b) => depth <= a*(size(l)*size(l)) +b))
+}
diff --git a/testcases/orb-testcases/depth/LeftistHeap.scala b/testcases/orb-testcases/depth/LeftistHeap.scala
new file mode 100644
index 000000000..06a59d2d6
--- /dev/null
+++ b/testcases/orb-testcases/depth/LeftistHeap.scala
@@ -0,0 +1,66 @@
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object LeftistHeap {
+  sealed abstract class Heap
+  case class Leaf() extends Heap
+  case class Node(rk : BigInt, value: BigInt, left: Heap, right: Heap) extends Heap
+
+  private def rightHeight(h: Heap) : BigInt = h match {
+    case Leaf() => 0
+    case Node(_,_,_,r) => rightHeight(r) + 1
+  }
+
+  private def rank(h: Heap) : BigInt = h match {
+    case Leaf() => 0
+    case Node(rk,_,_,_) => rk
+  }
+
+  private def hasLeftistProperty(h: Heap) : Boolean = (h match {
+    case Leaf() => true
+    case Node(_,_,l,r) => hasLeftistProperty(l) && hasLeftistProperty(r) && rightHeight(l) >= rightHeight(r) && (rank(h) == rightHeight(h))
+  })
+
+  def leftRightHeight(h: Heap) : BigInt = {h match {
+    case Leaf() => 0
+    case Node(_,_,l,r) => rightHeight(l)
+  }}
+
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,_,l,r) => merge(l, r)
+      case l @ Leaf() => l
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*leftRightHeight(h) + b))
+
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    h1 match {
+      case Leaf() => h2
+      case Node(_, v1, l1, r1) => h2 match {
+        case Leaf() => h1
+        case Node(_, v2, l2, r2) =>
+          if(v1 > v2)
+            makeT(v1, l1, merge(r1, h2))
+          else
+            makeT(v2, l2, merge(h1, r2))
+      }
+    }
+  } ensuring(res => true && tmpl((a,b,c) => depth <= a*rightHeight(h1) + b*rightHeight(h2) + c))
+
+  private def makeT(value: BigInt, left: Heap, right: Heap) : Heap = {
+    if(rank(left) >= rank(right))
+      Node(rank(right) + 1, value, left, right)
+    else
+      Node(rank(left) + 1, value, right, left)
+  }
+
+  def insert(element: BigInt, heap: Heap) : Heap = {
+   require(hasLeftistProperty(heap))
+
+    merge(Node(1, element, Leaf(), Leaf()), heap)
+
+  } ensuring(res => true && tmpl((a,b,c) => depth <= a*rightHeight(heap) + c))
+}
diff --git a/testcases/orb-testcases/depth/ListOperations.scala b/testcases/orb-testcases/depth/ListOperations.scala
new file mode 100644
index 000000000..9eb3c7907
--- /dev/null
+++ b/testcases/orb-testcases/depth/ListOperations.scala
@@ -0,0 +1,61 @@
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object ListOperations {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def append(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => Cons(x, append(xs, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => depth <= a*size(l1) + b))
+
+  def reverseRec(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => reverseRec(xs, Cons(x, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => depth <= a*size(l1) + b))
+
+  def reverse(l: List): List = {
+    reverseRec(l, Nil())
+
+  } ensuring (res => size(l) == size(res) && tmpl((a,b) => depth <= a*size(l) + b))
+
+  def reverse2(l: List): List = {
+    l match {
+      case Nil() => l
+      case Cons(hd, tl) => append(reverse2(tl), Cons(hd, Nil()))
+    }
+  } ensuring (res => size(res) == size(l) && tmpl((a,b) => depth <= a*(size(l)*size(l)) + b))
+
+  def remove(elem: BigInt, l: List): List = {
+    l match {
+      case Nil() => Nil()
+      case Cons(hd, tl) => if (hd == elem) remove(elem, tl) else Cons(hd, remove(elem, tl))
+    }
+  } ensuring (res => size(l) >= size(res) && tmpl((a,b) => depth <= a*size(l) + b))
+
+  def contains(list: List, elem: BigInt): Boolean = (list match {
+    case Nil() => false
+    case Cons(x, xs) => x == elem || contains(xs, elem)
+
+  }) ensuring (res => true && tmpl((a,b) => depth <= a*size(list) + b))
+
+  def distinct(l: List): List = (
+    l match {
+      case Nil() => Nil()
+      case Cons(x, xs) => {
+        val newl = distinct(xs)
+        if (contains(newl, x)) newl
+        else Cons(x, newl)
+      }
+   }) ensuring (res => size(l) >= size(res) && tmpl((a,b) => depth <= a*(size(l)*size(l)) + b))
+}
diff --git a/testcases/orb-testcases/depth/MergeSort.scala b/testcases/orb-testcases/depth/MergeSort.scala
new file mode 100644
index 000000000..de9fea534
--- /dev/null
+++ b/testcases/orb-testcases/depth/MergeSort.scala
@@ -0,0 +1,56 @@
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object MergeSort {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+
+  def size(list:List): BigInt = {list match {
+    case Nil() => BigInt(0)
+    case Cons(x,xs) => 1 + size(xs)
+  }} ensuring(res => res >= 0)
+
+  def length(l:List): BigInt = {
+    l match {
+      case Nil() => BigInt(0)
+      case Cons(x,xs) => 1 + length(xs)
+    }
+  } ensuring(res => res >= 0 && res == size(l) && tmpl((a,b) => depth <= a*size(l) + b))
+
+  def split(l:List,n:BigInt): (List,List) = {
+    require(n >= 0 && n <= size(l))
+    if (n <= 0) (Nil(),l)
+    else
+	l match {
+      case Nil() => (Nil(),l)
+      case Cons(x,xs) => {
+        val (fst,snd) = split(xs, n-1)
+        (Cons(x,fst), snd)
+      }
+	}
+  } ensuring(res => size(res._2) == size(l) - n && size(res._1) == n && tmpl((a,b) => depth <= a*n +b))
+
+  def merge(aList:List, bList:List):List = (bList match {
+    case Nil() => aList
+    case Cons(x,xs) =>
+    	 aList match {
+   	       case Nil() => bList
+   	       case Cons(y,ys) =>
+    	        if (y < x)
+    		   Cons(y,merge(ys, bList))
+     		else
+		   Cons(x,merge(aList, xs))
+   	 }
+  }) ensuring(res => size(aList)+size(bList) == size(res) && tmpl((a,b,c) => depth <= a*size(aList) + b*size(bList) + c))
+
+  def mergeSort(list:List):List = (list match {
+    case Nil() => list
+    case Cons(x,Nil()) => list
+    case _ =>
+    	 val (fst,snd) = split(list,length(list)/2)
+   	     merge(mergeSort(fst), mergeSort(snd))
+
+  }) ensuring(res => size(res) == size(list) && tmpl((a,b) => depth <= a*size(list) + b))
+}
diff --git a/testcases/orb-testcases/depth/PrimesParallel.scala b/testcases/orb-testcases/depth/PrimesParallel.scala
new file mode 100644
index 000000000..98724e972
--- /dev/null
+++ b/testcases/orb-testcases/depth/PrimesParallel.scala
@@ -0,0 +1,78 @@
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object PrimesParallel {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  //a program that removes from a list, all multiples of a number 'i' upto 'n'
+  //the depth of this program is again 1
+//  def removeMultiples(l: List, i: BigInt, n: BigInt, incr: BigInt): (List, BigInt) = {
+//    require(i >= 0 && incr >= 1 && i <= n)
+//    l match {
+//      case Nil() => (Nil(), 0)
+//      case Cons(x, t) => {
+//        if (x < i) {
+//          val (r,d) = removeMultiples(t, i, n, incr)
+//          (Cons(x, r), max(d, 2))
+//
+//        } else if (x > i) {
+//          val ni = i + incr
+//          if (ni > n) (l, 2)
+//          else {
+//            val (r,d) = removeMultiples(l, ni, n, incr)
+//            (r, max(d, 2))
+//          }
+//
+//
+//        } else {
+//          val ni = i + incr
+//          if (ni > n) (t, 2)
+//          else{
+//            val (r,d) = removeMultiples(l, ni, n, incr)
+//            (r, max(d, 2))
+//          }
+//        }
+//      }
+//    }
+//  } //ensuring (res => true && tmpl ((a) => res._2 <= a))
+  //ensuring (res => true && tmpl ((a,b) => time <= a*(size(l) + n - i) + b))
+
+  //another function with constant depth
+//  def createList(i: BigInt, n: BigInt) : (List, BigInt) = {
+//    require(i <= n)
+//    if(n == i) (Nil(), 0)
+//    else {
+//      val (r, d) = createList(i+1, n)
+//      (Cons(i, r), max(d, 2))
+//    }
+//  } //ensuring(res => true && tmpl((a) => res._2 <= a))
+  //ensuring(res => true && tmpl((a,b) => time <= a*(n-i) + b))
+
+//  def removeNonPrimes(currval: BigInt, l: List, n: BigInt, sqrtn: BigInt): (List, BigInt) = {
+//    require(currval <= sqrtn && sqrtn <= n && currval >= 1)
+//
+//    val (r,d) = removeMultiples(l, currval, n, currval)
+//    if(currval == sqrtn) {
+//      (r, d + 2)
+//    } else {
+//      val (res, t) = removeNonPrimes(currval + 1, r, n, sqrtn)
+//      (res, t + 2)
+//    }
+//  } //ensuring(res => true && tmpl((a,b) => res._2 <= a*(sqrtn - currval) + b))
+
+//  def simplePrimes(n: BigInt, sqrtn : BigInt) : (List, BigInt) = {
+//    require(sqrtn >= 2 && sqrtn <= n)
+//
+//     val (l, d1) = createList(2, n)
+//     val (resl, t2) = removeNonPrimes(2, l, n, sqrtn)
+//     (resl, d1 + t2 + 3)
+//  }  //ensuring(res => true && tmpl((a,b) => res._2 <= a*sqrtn + b))
+}
diff --git a/testcases/orb-testcases/depth/PropLogicDepth.scala b/testcases/orb-testcases/depth/PropLogicDepth.scala
new file mode 100644
index 000000000..881cd61a4
--- /dev/null
+++ b/testcases/orb-testcases/depth/PropLogicDepth.scala
@@ -0,0 +1,112 @@
+import scala.collection.immutable.Set
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object PropLogicDepth {
+
+  sealed abstract class Formula
+  case class And(lhs: Formula, rhs: Formula) extends Formula
+  case class Or(lhs: Formula, rhs: Formula) extends Formula
+  case class Implies(lhs: Formula, rhs: Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Literal(id: BigInt) extends Formula
+  case class True() extends Formula
+  case class False() extends Formula
+
+  def max(x: BigInt,y: BigInt) = if (x >= y) x else y
+
+  def nestingDepth(f: Formula) : BigInt = (f match {
+    case And(lhs, rhs) => max(nestingDepth(lhs),nestingDepth(rhs)) + 1
+    case Or(lhs, rhs) => max(nestingDepth(lhs),nestingDepth(rhs)) + 1
+    case Implies(lhs, rhs) => max(nestingDepth(lhs),nestingDepth(rhs)) + 1
+    case Not(f) => nestingDepth(f) + 1
+    case _ => 1
+  })
+
+  def removeImplies(f: Formula): Formula = (f match {
+    case And(lhs, rhs) => And(removeImplies(lhs), removeImplies(rhs))
+    case Or(lhs, rhs) => Or(removeImplies(lhs), removeImplies(rhs))
+    case Implies(lhs, rhs) => Or(Not(removeImplies(lhs)),removeImplies(rhs))
+    case Not(f) => Not(removeImplies(f))
+    case _ => f
+
+  }) ensuring((res) => true && tmpl((a,b) => depth <= a*nestingDepth(f) + b))
+
+  def nnf(formula: Formula): Formula = (formula match {
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs) => Or(nnf(lhs), nnf(rhs))
+    case Implies(lhs, rhs) => Implies(nnf(lhs), nnf(rhs))
+    case Not(And(lhs, rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs, rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Implies(lhs, rhs)) => And(nnf(lhs), nnf(Not(rhs)))
+    case Not(Not(f)) => nnf(f)
+    case Not(Literal(_)) => formula
+    case Literal(_) => formula
+    case Not(True()) => False()
+    case Not(False()) => True()
+    case _ => formula
+  }) ensuring((res) => true && tmpl((a,b) => depth <= a*nestingDepth(formula) + b))
+
+  def isNNF(f: Formula): Boolean = { f match {
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Implies(lhs, rhs) => false
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case _ => true
+  }}  ensuring((res) => true && tmpl((a,b) => depth <= a*nestingDepth(f) + b))
+
+  def simplify(f: Formula): Formula = (f match {
+    case And(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs or rhs is false, return false
+      //if lhs is true return rhs
+      //if rhs is true return lhs
+      (sl,sr) match {
+        case (False(), _) => False()
+        case (_, False()) => False()
+        case (True(), _) => sr
+        case (_, True()) => sl
+        case _ => And(sl, sr)
+      }
+    }
+    case Or(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs or rhs is true, return true
+      //if lhs is false return rhs
+      //if rhs is false return lhs
+      (sl,sr) match {
+        case (True(), _) => True()
+        case (_, True()) => True()
+        case (False(), _) => sr
+        case (_, False()) => sl
+        case _ => Or(sl, sr)
+      }
+    }
+    case Implies(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs is false return true
+      //if rhs is true return true
+      //if lhs is true return rhs
+      //if rhs is false return Not(rhs)
+      (sl,sr) match {
+        case (False(), _) => True()
+        case (_, True()) => True()
+        case (True(), _) => sr
+        case (_, False()) => Not(sl)
+        case _ => Implies(sl, sr)
+      }
+    }
+    case Not(True()) => False()
+    case Not(False()) => True()
+    case _ => f
+
+  }) ensuring((res) => true && tmpl((a,b) => depth <= a*nestingDepth(f) + b))
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/depth/QSortDepth.scala b/testcases/orb-testcases/depth/QSortDepth.scala
new file mode 100644
index 000000000..cd8f16627
--- /dev/null
+++ b/testcases/orb-testcases/depth/QSortDepth.scala
@@ -0,0 +1,41 @@
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object QSortDepth {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+
+  def size(l:List): BigInt = {l match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }}
+
+  case class Triple(fst:List,snd:List, trd: List)
+
+   def append(aList:List,bList:List): List = {aList match {
+    case Nil() => bList
+    case Cons(x, xs) => Cons(x,append(xs,bList))
+  }} ensuring(res => size(res) == size(aList) + size(bList) && tmpl((a,b) => depth <= a*size(aList) +b))
+
+  def partition(n:BigInt,l:List) : Triple = (l match {
+    case Nil() => Triple(Nil(), Nil(), Nil())
+    case Cons(x,xs) => {
+      val t = partition(n,xs)
+      if (n < x) Triple(t.fst, t.snd, Cons(x,t.trd))
+      else if(n == x) Triple(t.fst, Cons(x,t.snd), t.trd)
+      else Triple(Cons(x,t.fst), t.snd, t.trd)
+    }
+ }) ensuring(res => (size(l) == size(res.fst) + size(res.snd) + size(res.trd)) && tmpl((a,b) => depth <= a*size(l) +b))
+
+  def quickSort(l:List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,Nil()) => l
+    case Cons(x,xs) => {
+      val t = partition(x, xs)
+      append(append(quickSort(t.fst), Cons(x, t.snd)), quickSort(t.trd))
+    }
+    case _ => l
+  }) ensuring(res => size(res) == size(l) && tmpl((a,b,c) => depth <= a*(size(l)*size(l)) + b*size(l) + c))
+}
diff --git a/testcases/orb-testcases/depth/RedBlackTree.scala b/testcases/orb-testcases/depth/RedBlackTree.scala
new file mode 100755
index 000000000..9bde5ebdf
--- /dev/null
+++ b/testcases/orb-testcases/depth/RedBlackTree.scala
@@ -0,0 +1,113 @@
+import leon.instrumentation._
+import leon.invariant._
+import scala.collection.immutable.Set
+import leon.annotation._
+
+object RedBlackTree {
+  sealed abstract class Color
+  case class Red() extends Color
+  case class Black() extends Color
+
+  sealed abstract class Tree
+  case class Empty() extends Tree
+  case class Node(color: Color, left: Tree, value: BigInt, right: Tree) extends Tree
+
+  def twopower(x: BigInt) : BigInt = {
+    require(x >= 0)
+    if(x < 1) 1
+    else
+      2* twopower(x - 1)
+  }
+
+  def size(t: Tree): BigInt = {
+    require(blackBalanced(t))
+    (t match {
+      case Empty() => 0
+      case Node(_, l, v, r) => size(l) + 1 + size(r)
+    })
+  } //ensuring (res => true && tmpl((a,b) => twopower(blackHeight(t)) <= a*res + b))
+
+  def blackHeight(t : Tree) : BigInt = {
+   t match {
+    case Empty() => 0
+    case Node(Black(), l, _, _) => blackHeight(l) + 1
+    case Node(Red(), l, _, _) => blackHeight(l)
+   	}
+  }
+
+   //We consider leaves to be black by definition
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty() => true
+    case Node(Black(),_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty() => true
+    case Node(Black(), l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red(), l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case _ => false
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case _ => true
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case _ => true
+  }
+
+  // <<insert element x into the tree t>>
+  def ins(x: BigInt, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+
+    t match {
+      case Empty() => Node(Red(),Empty(),x,Empty())
+      case Node(c,a,y,b) =>
+        if(x < y) {
+        	val t1 = ins(x, a)
+        	balance(c, t1, y, b)
+        }
+        else if (x == y){
+        	Node(c,a,y,b)
+        }
+        else{
+          val t1 = ins(x, b)
+          balance(c,a,y,t1)
+        }
+    }
+  } ensuring(res => true && tmpl((a,b) => depth <= a*blackHeight(t) + b))
+
+  def makeBlack(n: Tree): Tree = {
+    n match {
+      case Node(Red(),l,v,r) => Node(Black(),l,v,r)
+      case _ => n
+    }
+  }
+
+  def add(x: BigInt, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    val t1 =  ins(x, t)
+    makeBlack(t1)
+
+  } ensuring(res => true && tmpl((a,b) => depth <= a*blackHeight(t) + b))
+
+  def balance(co: Color, l: Tree, x: BigInt, r: Tree): Tree = {
+    Node(co,l,x,r)
+     match {
+      case Node(Black(),Node(Red(),Node(Red(),a,xV,b),yV,c),zV,d) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case Node(Black(),Node(Red(),a,xV,Node(Red(),b,yV,c)),zV,d) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case Node(Black(),a,xV,Node(Red(),Node(Red(),b,yV,c),zV,d)) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case Node(Black(),a,xV,Node(Red(),b,yV,Node(Red(),c,zV,d))) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case _ => Node(co,l,x,r)
+    }
+  }
+
+
+}
diff --git a/testcases/orb-testcases/depth/SpeedBenchmarks.scala b/testcases/orb-testcases/depth/SpeedBenchmarks.scala
new file mode 100644
index 000000000..c8679d68d
--- /dev/null
+++ b/testcases/orb-testcases/depth/SpeedBenchmarks.scala
@@ -0,0 +1,109 @@
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object SpeedBenchmarks {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  sealed abstract class StringBuffer
+  case class Chunk(str: List, next: StringBuffer) extends StringBuffer
+  case class Empty() extends StringBuffer
+
+  def length(sb: StringBuffer) : BigInt = sb match {
+    case Chunk(_, next) => 1 + length(next)
+    case _ => 0
+  }
+
+  def sizeBound(sb: StringBuffer, k: BigInt) : Boolean ={
+    sb match {
+      case Chunk(str, next) => size(str) <= k && sizeBound(next, k)
+      case _ => 0 <= k
+    }
+  }
+
+  /**
+   * Fig. 1 of SPEED, POPL'09: The functional version of the implementation.
+   * Equality check of two string buffers
+   */
+  def Equals(str1: List, str2: List, s1: StringBuffer, s2: StringBuffer, k: BigInt) : Boolean = {
+    require(sizeBound(s1, k) && sizeBound(s2, k) && size(str1) <= k && size(str2) <= k && k >= 0)
+
+    (str1, str2) match {
+      case (Cons(h1,t1), Cons(h2,t2)) => {
+
+        if(h1 != h2) false
+        else Equals(t1,t2, s1,s2, k)
+      }
+      case (Cons(_,_), Nil()) => {
+        //load from s2
+        s2 match {
+          case Chunk(str, next) => Equals(str1, str, s1, next, k)
+          case Empty() => false
+        }
+      }
+      case (Nil(), Cons(_,_)) => {
+        //load from s1
+        s1 match {
+          case Chunk(str, next) => Equals(str, str2, next, s2, k)
+          case Empty() => false
+        }
+      }
+      case _ =>{
+        //load from both
+        (s1,s2) match {
+          case (Chunk(nstr1, next1),Chunk(nstr2, next2)) => Equals(nstr1, nstr2, next1, next2, k)
+          case (Empty(),Chunk(nstr2, next2)) => Equals(str1, nstr2, s1, next2, k)
+          case (Chunk(nstr1, next1), Empty()) => Equals(nstr1, str2, next1, s2, k)
+          case _ => true
+        }
+      }
+    }
+  } ensuring(res => true && tmpl((a,b,c,d,e) => depth <= a*((k+1)*(length(s1) + length(s2))) + b*size(str1) + e))
+
+  def max(x: BigInt, y: BigInt) : BigInt = if(x >= y) x else y
+
+  //Fig. 2 of Speed POPL'09
+  def Dis1(x : BigInt, y : BigInt, n: BigInt, m: BigInt) : BigInt = {
+    if(x >= n) 0
+    else {
+      if(y < m) Dis1(x, y+1, n, m)
+      else Dis1(x+1, y, n, m)
+    }
+  } ensuring(res => true && tmpl((a,b,c) => depth <= a*max(0,n-x) + b*max(0,m-y) + c))
+
+  //Fig. 2 of Speed POPL'09
+  def Dis2(x : BigInt, z : BigInt, n: BigInt) : BigInt = {
+    if(x >= n) 0
+    else {
+      if(z > x) Dis2(x+1, z, n)
+      else Dis2(x, z+1, n)
+    }
+  } ensuring(res => true && tmpl((a,b,c) => depth <= a*max(0,n-x) + b*max(0,n-z) + c))
+
+  //Pg. 138, Speed POPL'09
+  def Dis3(x : BigInt, b : Boolean, t: BigInt, n: BigInt) : BigInt = {
+    require((b && t == 1) || (!b && t == -1))
+    if(x > n || x < 0) 0
+    else {
+      if(b) Dis3(x+t, b, t, n)
+      else Dis3(x-t, b, t, n)
+    }
+  } ensuring(res => true && tmpl((a,c) => depth <= a*max(0,(n-x)) + c))
+
+  //Pg. 138, Speed POPL'09
+  def Dis4(x : BigInt, b : Boolean, t: BigInt, n: BigInt) : BigInt = {
+    if(x > n || x < 0) 0
+    else {
+      if(b) Dis4(x+t, b, t, n)
+      else Dis4(x-t, b, t, n)
+    }
+  } ensuring(res => true && tmpl((a,c,d,e) => (((b && t >= 0) || (!b && t < 0)) && depth <= a*max(0,(n-x)) + c)
+  					|| (((!b && t >= 0) || (b && t < 0)) && depth <= d*max(0,x) + e)))
+}
diff --git a/testcases/orb-testcases/depth/TreeOperations.scala b/testcases/orb-testcases/depth/TreeOperations.scala
new file mode 100755
index 000000000..d6199f163
--- /dev/null
+++ b/testcases/orb-testcases/depth/TreeOperations.scala
@@ -0,0 +1,93 @@
+import leon.instrumentation._
+import leon.invariant._
+import leon.annotation._
+
+object TreeOperations {
+
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  sealed abstract class Tree
+  case class Node(left: Tree, value: BigInt, right: Tree) extends Tree
+  case class Leaf() extends Tree
+
+  def listSize(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + listSize(t)
+  })
+
+  def size(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        size(l) + size(r) + 1
+      }
+    }
+  }
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def insert(elem: BigInt, t: Tree): Tree = {
+    t match {
+      case Leaf() => Node(Leaf(), elem, Leaf())
+      case Node(l, x, r) => if (x <= elem) Node(l, x, insert(elem, r))
+      else Node(insert(elem, l), x, r)
+    }
+  } ensuring (res => height(res) <= height(t) + 1 && tmpl((a,b) => depth <= a*height(t) + b))
+
+  def addAll(l: List, t: Tree): Tree = {
+    l match {
+      case Nil() => t
+      case Cons(x, xs) =>{
+        val newt = insert(x, t)
+        addAll(xs, newt)
+      }
+    }
+  } ensuring(res => true && tmpl((a,b,c) => depth <= a*(listSize(l) * (height(t) + listSize(l))) + b*listSize(l) + c))
+
+  def remove(elem: BigInt, t: Tree): Tree = {
+    t match {
+      case Leaf() => Leaf()
+      case Node(l, x, r) => {
+
+        if (x < elem) Node(l, x, remove(elem, r))
+        else if (x > elem) Node(remove(elem, l), x, r)
+        else {
+          t match {
+            case Node(Leaf(), x, Leaf()) => Leaf()
+            case Node(Leaf(), x, Node(_, rx, _)) => Node(Leaf(), rx, remove(rx, r))
+            case Node(Node(_, lx, _), x, r) => Node(remove(lx, l), lx, r)
+            case _ => Leaf()
+          }
+        }
+      }
+    }
+  } ensuring (res => height(res) <= height(t) && tmpl ((a, b, c) => depth <= a*height(t) + b))
+
+  def removeAll(l: List, t: Tree): Tree = {
+    l match {
+      case Nil() => t
+      case Cons(x, xs) => removeAll(xs, remove(x, t))
+    }
+  } ensuring(res => true && tmpl((a,b,c) => depth <= a*(listSize(l) * height(t)) + b*listSize(l) + c))
+
+  def contains(elem : BigInt, t : Tree) : Boolean = {
+    t match {
+      case Leaf() => false
+      case Node(l, x, r) =>
+        if(x == elem) true
+        else if (x < elem) contains(elem, r)
+        else contains(elem, l)
+    }
+  } ensuring (res => true && tmpl((a,b) => depth <= a*height(t) + b))
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/numerical/ConcatVariationsAbs.scala b/testcases/orb-testcases/numerical/ConcatVariationsAbs.scala
new file mode 100644
index 000000000..bff880ab3
--- /dev/null
+++ b/testcases/orb-testcases/numerical/ConcatVariationsAbs.scala
@@ -0,0 +1,43 @@
+import leon.invariant._
+
+object ConcatVariationsAbs {
+  def genL(n: BigInt): BigInt = {
+    require(n >= 0)
+    if (n == 0)
+      BigInt(2)
+    else
+      4 + genL(n - 1)
+  } ensuring (res => tmpl((a, b) => res <= a * n + b))
+
+  def append(l1: BigInt, l2: BigInt): BigInt = {
+    require(l1 >= 0 && l2 >= 0)
+    if (l1 == 0)
+      BigInt(3)
+    else
+      append(l1 - 1, l2 + 1) + 5
+  } ensuring (res => tmpl((a, b) => res <= a * l1 + b))
+
+  def f_good(m: BigInt, n: BigInt): BigInt = {
+    require(0 <= m && 0 <= n)
+    if (m == 0) BigInt(2)
+    else {
+      val t1 = genL(n)
+      val t2 = f_good(m - 1, n)
+      val t3 = append(n, n * (m - 1))
+      (t1 + t2 + t3 + 6)
+    }
+
+  } ensuring (res => tmpl((a, b, c, d) => res <= a * (n * m) + b * n + c * m + d))
+
+  def f_worst(m: BigInt, n: BigInt): BigInt = {
+    require(0 <= m && 0 <= n)
+    if (m == 0) BigInt(2)
+    else {
+      val t1 = genL(n)
+      val t2 = f_worst(m - 1, n)
+      val t3 = append(n * (m - 1), n)
+      (t1 + t2 + t3 + 6)
+    }
+
+  } ensuring (res => tmpl((a, c, d, e, f) => res <= a * ((n * m) * m) + c * (n * m) + d * n + e * m + f))
+}
diff --git a/testcases/orb-testcases/numerical/ListAppendAbs.scala b/testcases/orb-testcases/numerical/ListAppendAbs.scala
new file mode 100755
index 000000000..63038cc74
--- /dev/null
+++ b/testcases/orb-testcases/numerical/ListAppendAbs.scala
@@ -0,0 +1,20 @@
+import leon.invariant._
+
+object ListAppendAbs
+{
+	def app(x: BigInt) : BigInt = {
+	  require(x >=0)
+
+	  app0(x,1)
+
+	} ensuring(res => res == x + 1)
+
+	def app0(a: BigInt, b: BigInt) : BigInt = {
+	  require(a >=0 && b >=0)
+
+	  if(a <= 0)
+	    b
+	  else
+	    app0(a-1,b+1)
+	} ensuring(res => tmpl((p, q, r) => (p*res + q*a + r*b == 0 && q  != 0)))
+}
diff --git a/testcases/orb-testcases/numerical/LogarithmTest.scala b/testcases/orb-testcases/numerical/LogarithmTest.scala
new file mode 100755
index 000000000..00fdc552d
--- /dev/null
+++ b/testcases/orb-testcases/numerical/LogarithmTest.scala
@@ -0,0 +1,30 @@
+import leon.invariant._
+import leon.annotation._
+
+object LogarithmTest {
+
+  @monotonic
+  def log(x: BigInt) : BigInt = {
+    require(x >= 0)
+    if(x <= 1) BigInt(0)
+    else {
+      1 + log(x/2)
+    }
+  } ensuring(_ >= 0)
+
+  def binarySearchAbs(x: BigInt, min: BigInt, max: BigInt): BigInt = {
+    require(max - min >= 0)
+    if (max - min <= 1) BigInt(2)
+    else {
+      val mid = (min + max) / 2
+      if (x < mid) {
+        binarySearchAbs(x, min, mid) + 5
+      } else if (x > mid) {
+        binarySearchAbs(x, mid + 1, max) + 7
+      } else
+        BigInt(8)
+    }
+  } ensuring(res => tmpl((a,b) => res <= a*log(max - min) + b))
+  //ensuring(res => tmpl((a,b) => res <= 7*log(max - min) + 2))
+  //
+}
diff --git a/testcases/orb-testcases/numerical/QueueAbs.scala b/testcases/orb-testcases/numerical/QueueAbs.scala
new file mode 100644
index 000000000..a7aee3a93
--- /dev/null
+++ b/testcases/orb-testcases/numerical/QueueAbs.scala
@@ -0,0 +1,70 @@
+import leon.invariant._
+
+object AmortizedQueue {
+  def concat(l1: BigInt, l2: BigInt): BigInt = {
+    require(l1 >= 0 && l2 >= 0)
+    if (l1 == 0)
+      BigInt(3)
+    else
+      concat(l1 - 1, l2 + 1) + 5
+  } ensuring (res => tmpl((a, b) => res <= a * l1 + b))
+
+  def reverseRec(l1: BigInt, l2: BigInt): BigInt = {
+    require(l1 >= 0 && l2 >= 0)
+    if (l1 == 0)
+      BigInt(3)
+    else {
+      reverseRec(l1 - 1, l2 + 1) + 6
+    }
+  } ensuring (res => tmpl((a, b) => res <= a * l1 + b))
+
+  def reverse(l: BigInt): BigInt = {
+    require(l >= 0)
+    reverseRec(l, 0) + 1
+  } ensuring (res => tmpl((a, b) => res <= a * l + b))
+
+  def create(front: BigInt, rear: BigInt): BigInt = {
+    require(front >= 0 && rear >= 0)
+    if (rear <= front)
+      BigInt(4)
+    else {
+      val t1 = reverse(rear)
+      val t2 = concat(front, rear)
+      t1 + t2 + 7
+    }
+  }
+
+  def enqueue(q: BigInt, front: BigInt, rear: BigInt): BigInt = {
+    require(q == front + rear && q >= 0 && front >= 0 && rear >= 0)
+    create(front, rear) + 5
+  } ensuring (res => tmpl((a, b) => res <= a * q + b))
+
+  def dequeue(q: BigInt, front: BigInt, rear: BigInt): BigInt = {
+    require(q == front + rear && q >= 1 && front >= rear && rear >= 0)
+    if (front >= 1) {
+      create(front - 1, rear) + 4
+    } else {
+      //since front should be greater than rear, here rear should be 0 as well
+      BigInt(5)
+    }
+  } ensuring (res => tmpl((a, b) => res <= a * q + b))
+
+  def removeLast(l: BigInt): BigInt = {
+    require(l >= 1)
+    if (l == 1) {
+      BigInt(4)
+    } else {
+      removeLast(l - 1) + 6
+    }
+  } ensuring (res => tmpl((a, b) => res <= a * l + b))
+
+  def pop(q: BigInt, front: BigInt, rear: BigInt): BigInt = {
+    require(q == front + rear && q >= 1 && front >= rear && rear >= 0)
+    if (rear >= 1) {
+      BigInt(3)
+    } else {
+      val t1 = removeLast(front)
+      t1 + 5
+    }
+  } ensuring (res => tmpl((a, b) => res <= a * q + b))
+}
diff --git a/testcases/orb-testcases/numerical/SimpleInterProc.scala b/testcases/orb-testcases/numerical/SimpleInterProc.scala
new file mode 100755
index 000000000..b2ac527b5
--- /dev/null
+++ b/testcases/orb-testcases/numerical/SimpleInterProc.scala
@@ -0,0 +1,16 @@
+object SimpleInterProc
+{
+	def s(x: BigInt) : BigInt = {
+	  if(x < 0)
+	    makePositive(x)
+	  else
+	    s(x-1) + 1
+	} ensuring(res => res != -1)
+
+	def makePositive(y : BigInt) : BigInt = {
+	  2*negate(y)
+	}
+	def negate(c : BigInt) : BigInt={
+	  -c
+	}
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/numerical/SimpleLoop.scala b/testcases/orb-testcases/numerical/SimpleLoop.scala
new file mode 100755
index 000000000..6a2cdb3d9
--- /dev/null
+++ b/testcases/orb-testcases/numerical/SimpleLoop.scala
@@ -0,0 +1,9 @@
+object SimpleLoop
+{
+	def s(x: BigInt) : BigInt = {
+	  if(x < 0)
+	    BigInt(0)
+	  else
+	    s(x-1) + 1
+	} ensuring(res => res != -1)
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/numerical/see-saw.scala b/testcases/orb-testcases/numerical/see-saw.scala
new file mode 100644
index 000000000..894a8caed
--- /dev/null
+++ b/testcases/orb-testcases/numerical/see-saw.scala
@@ -0,0 +1,15 @@
+object SeeSaw {
+  def s(x: BigInt, y: BigInt, z: BigInt): BigInt = {
+    require(y >= 0)
+
+    if (x >= 100) {
+      y
+    } else if (x <= z) { //some condition
+      s(x + 1, y + 2, z)
+    } else if (x <= z + 9) { //some condition
+      s(x + 1, y + 3, z)
+    } else {
+      s(x + 2, y + 1, z)
+    }
+  } ensuring (res => (100 - x <= 2 * res))
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/stack/BinaryTrie.scala b/testcases/orb-testcases/stack/BinaryTrie.scala
new file mode 100644
index 000000000..f2dfd876c
--- /dev/null
+++ b/testcases/orb-testcases/stack/BinaryTrie.scala
@@ -0,0 +1,120 @@
+import leon.invariant._
+import leon.instrumentation._
+//import scala.collection.immutable.Set
+
+object BinaryTrie {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(nvalue: BigInt, left: Tree, right: Tree) extends Tree
+
+  sealed abstract class IList
+  case class Cons(head: BigInt, tail: IList) extends IList
+  case class Nil() extends IList
+
+  def listSize(l: IList): BigInt = (l match {
+    case Nil() => 0
+    case Cons(x, xs) => 1 + listSize(xs)
+  })
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(x, l, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def find(inp: IList, t: Tree): Tree = {
+    inp match {
+      case Nil() => t
+      case Cons(x, Nil()) => t
+      case Cons(x, xs @ Cons(y, _)) => {
+        t match {
+          case Leaf() => t
+          case Node(v, l, r) => {
+            if (y > 0) find(xs, l) else find(xs, r)
+          }
+        }
+      }
+      case _ => t
+    }
+  } ensuring (_ => stack <= ? * listSize(inp) + ?)
+
+  def insert(inp: IList, t: Tree): Tree = {
+    t match {
+      case Leaf() => {
+        inp match {
+          case Nil() => t
+          case Cons(x, xs) => {
+            val newch = insert(xs, Leaf())
+            newch match {
+              case Leaf() => Node(x, Leaf(), Leaf())
+              case Node(y, _, _) => if (y > 0) Node(x, newch, Leaf()) else Node(y, Leaf(), newch)
+            }
+          }
+        }
+
+      }
+      case Node(v, l, r) => {
+        inp match {
+          case Nil() => t
+          case Cons(x, Nil()) => t
+          case Cons(x, xs @ Cons(y, _)) => {
+            val ch = if (y > 0) l else r
+            if (y > 0)
+              Node(v, insert(xs, ch), r)
+            else
+              Node(v, l, insert(xs, ch))
+          }
+          case _ => t
+        }
+      }
+    }
+  } ensuring (_ => stack <= ? * listSize(inp) + ?)
+
+  def create(inp: IList): Tree = {
+    insert(inp, Leaf())
+  } ensuring (_ => stack <= ? * listSize(inp) + ?)
+
+  def delete(inp: IList, t: Tree): Tree = {
+    t match {
+        case Leaf() => {
+          inp match {
+            case Nil() => Leaf()
+            case Cons(x ,xs) => {
+              //the input is not in the tree, so do nothing
+              Leaf()
+            }
+          }
+        }
+        case Node(v, l, r) => {
+          inp match {
+            case Nil() => {
+              //the tree has extensions of the input list so do nothing
+              t
+            }
+            case Cons(x, Nil()) => {
+              //if "l" and "r" are nil, remove the node
+              if(l == Leaf() && r == Leaf()) Leaf()
+              else t
+            }
+            case Cons(x ,xs@Cons(y, _)) => {
+              val ch = if(y > 0) l else r
+              val newch = delete(xs, ch)
+              if(newch == Leaf() && ((y > 0 && r == Leaf()) || (y <= 0 && l == Leaf()))) Leaf()
+              else {
+                if(y > 0)
+        		  Node(v, newch, r)
+        	    else
+        	      Node(v, l, newch)
+              }
+            }
+            case _ => t
+        }
+      }
+    }
+  } ensuring (_ => stack <= ? * listSize(inp) + ?)
+}
diff --git a/testcases/orb-testcases/stack/BinomialHeap.scala b/testcases/orb-testcases/stack/BinomialHeap.scala
new file mode 100644
index 000000000..e18b9b143
--- /dev/null
+++ b/testcases/orb-testcases/stack/BinomialHeap.scala
@@ -0,0 +1,207 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object BinomialHeap {
+  //sealed abstract class TreeNode
+  case class TreeNode(rank: BigInt, elem: Element, children: BinomialHeap)
+  case class Element(n: BigInt)
+
+  sealed abstract class BinomialHeap
+  case class ConsHeap(head: TreeNode, tail: BinomialHeap) extends BinomialHeap
+  case class NilHeap() extends BinomialHeap
+
+  sealed abstract class List
+  case class NodeL(head: BinomialHeap, tail: List) extends List
+  case class NilL() extends List
+
+  sealed abstract class OptionalTree
+  case class Some(t : TreeNode) extends OptionalTree
+  case class None() extends OptionalTree
+
+  /* Lower or Equal than for Element structure */
+  private def leq(a: Element, b: Element) : Boolean = {
+    a match {
+      case Element(a1) => {
+        b match {
+          case Element(a2) => {
+            if(a1 <= a2) true
+            else false
+          }
+        }
+      }
+    }
+  }
+
+  /* isEmpty function of the Binomial Heap */
+  def isEmpty(t: BinomialHeap) = t match {
+    case ConsHeap(_,_) => false
+    case _ => true
+  }
+
+  /* Helper function to determine rank of a TreeNode */
+  def rank(t: TreeNode) : BigInt = t.rank /*t match {
+    case TreeNode(r, _, _) => r
+  }*/
+
+  /* Helper function to get the root element of a TreeNode */
+  def root(t: TreeNode) : Element = t.elem /*t match {
+    case TreeNode(_, e, _) => e
+  }*/
+
+  /* Linking trees of equal ranks depending on the root element */
+  def link(t1: TreeNode, t2: TreeNode): TreeNode = {
+    if (leq(t1.elem, t2.elem)) {
+      TreeNode(t1.rank + 1, t1.elem, ConsHeap(t2, t1.children))
+    } else {
+      TreeNode(t1.rank + 1, t2.elem, ConsHeap(t1, t2.children))
+    }
+  }
+
+  def treeNum(h: BinomialHeap) : BigInt = {
+    h match {
+      case ConsHeap(head, tail) =>  1 + treeNum(tail)
+      case _ => 0
+    }
+  }
+
+  /* Insert a tree into a binomial heap. The tree should be correct in relation to the heap */
+  def insTree(t: TreeNode, h: BinomialHeap) : BinomialHeap = {
+    h match {
+      case ConsHeap(head, tail) =>  {
+        if (rank(t) < rank(head)) {
+          ConsHeap(t, h)
+        } else if (rank(t) > rank(head)) {
+          ConsHeap(head, insTree(t,tail))
+        } else {
+          insTree(link(t,head), tail)
+        }
+      }
+      case _ => ConsHeap(t, NilHeap())
+    }
+  } ensuring(res => tmpl((a,b) => stack <= a*treeNum(h) + b))
+
+  /* Merge two heaps together */
+  def merge(h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    h1 match {
+      case ConsHeap(head1, tail1) => {
+        h2 match {
+          case ConsHeap(head2, tail2) => {
+            if (rank(head1) < rank(head2)) {
+              ConsHeap(head1, merge(tail1, h2))
+            } else if (rank(head2) < rank(head1)) {
+              ConsHeap(head2, merge(h1, tail2))
+            } else {
+              mergeWithCarry(link(head1, head2), tail1, tail2)
+            }
+          }
+          case _ => h1
+        }
+      }
+      case _ => h2
+    }
+  } ensuring(res => tmpl((a,b,c) => stack <= a*treeNum(h1) + b*treeNum(h2) + c))
+
+  def mergeWithCarry(t: TreeNode, h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    h1 match {
+      case ConsHeap(head1, tail1) => {
+        h2 match {
+          case ConsHeap(head2, tail2) => {
+            if (rank(head1) < rank(head2)) {
+
+              if (rank(t) < rank(head1))
+                ConsHeap(t, ConsHeap(head1, merge(tail1, h2)))
+              else
+                mergeWithCarry(link(t, head1), tail1, h2)
+
+            } else if (rank(head2) < rank(head1)) {
+
+              if (rank(t) < rank(head2))
+                ConsHeap(t, ConsHeap(head2, merge(h1, tail2)))
+              else
+                mergeWithCarry(link(t, head2), h1, tail2)
+
+            } else {
+              ConsHeap(t, mergeWithCarry(link(head1, head2), tail1, tail2))
+            }
+          }
+          case _ => {
+            insTree(t, h1)
+          }
+        }
+      }
+      case _ => insTree(t, h2)
+    }
+  } ensuring (res => tmpl((d, e, f) => stack <= d * treeNum(h1) + e * treeNum(h2) + f))
+
+  //Auxiliary helper function to simplefy findMin and deleteMin
+  def removeMinTree(h: BinomialHeap): (OptionalTree, BinomialHeap) = {
+    h match {
+      case ConsHeap(head, NilHeap()) => (Some(head), NilHeap())
+      case ConsHeap(head1, tail1) => {
+        val (opthead2, tail2) = removeMinTree(tail1)
+        opthead2 match {
+          case Some(head2) =>
+            if (leq(root(head1), root(head2))) {
+              (Some(head1), tail1)
+            } else {
+              (Some(head2), ConsHeap(head1, tail2))
+            }
+          case _ => (Some(head1), tail1)
+        }
+      }
+      case _ => (None(), NilHeap())
+    }
+  } ensuring (res => treeNum(res._2) <= treeNum(h) && tmpl((a, b) => stack <= a * treeNum(h) + b))
+
+  /*def findMin(h: BinomialHeap) : Element = {
+	  val (opt, _) = removeMinTree(h)
+	  opt match {
+	    case Some(TreeNode(_,e,ts1)) => e
+	    case _ => Element(-1)
+	  }
+  } ensuring(res => true && tmpl((a,b) => time <= a*treeNum(h) + b))*/
+
+  def minTreeChildren(h: BinomialHeap) : BigInt = {
+    val (min, _) = removeMinTree(h)
+    min match {
+      case Some(TreeNode(_,_,ch)) => treeNum(ch)
+      case _ => 0
+	}
+  }
+
+  // Discard the minimum element of the extracted min tree and put its children back into the heap
+  def deleteMin(h: BinomialHeap) : BinomialHeap = {
+	  val (min, ts2) = removeMinTree(h)
+	  min match {
+		case Some(TreeNode(_,_,ts1)) => merge(ts1, ts2)
+		case _ => h
+	  }
+  } ensuring(res => tmpl((a,b,c) => stack <= a*minTreeChildren(h) + b*treeNum(h) + c))
+
+  /*def heapSize(h: BinomialHeap) : BigInt = {
+    h match {
+      NilHeap() => 0
+      ConsHeap(head, tail) =>
+        treeSize(head) + heapSize(tail)
+    }
+  }
+
+  def treeSize(tree: TreeNode) : BigInt = {
+    val (_, _, children) = tree
+    heapSize(children) + 1
+  }
+
+  @monotonic
+  def twopower(x: BigInt) : BigInt = {
+    require(x >= 0)
+    if(x < 1) 1
+    else
+      2* twopower(x - 1)
+  }
+
+  def sizeProperty(tree: TreeNode) : BigInt = {
+    val (r, _, _) = tree
+    treeSize(tree) == twopower(r)
+  }*/
+
+}
diff --git a/testcases/orb-testcases/stack/ListOperations.scala b/testcases/orb-testcases/stack/ListOperations.scala
new file mode 100644
index 000000000..3ae4a2d17
--- /dev/null
+++ b/testcases/orb-testcases/stack/ListOperations.scala
@@ -0,0 +1,35 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object ListOperations {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def reverseRec(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => reverseRec(xs, Cons(x, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => stack <= a*size(l1) + b))
+
+  def contains(list: List, elem: BigInt): Boolean = (list match {
+    case Nil() => false
+    case Cons(x, xs) => x == elem || contains(xs, elem)
+
+  }) ensuring (res => tmpl((a,b) => stack <= a*size(list) + b))
+
+  def distinct(l: List): List = (
+    l match {
+      case Nil() => Nil()
+      case Cons(x, xs) => {
+        val newl = distinct(xs)
+        if (contains(newl, x)) newl
+        else Cons(x, newl)
+      }
+   }) ensuring (res => size(l) >= size(res) && tmpl((a,b) => stack <= a*size(l) + b))
+}
diff --git a/testcases/orb-testcases/stack/MergeSort.scala b/testcases/orb-testcases/stack/MergeSort.scala
new file mode 100644
index 000000000..7a104689f
--- /dev/null
+++ b/testcases/orb-testcases/stack/MergeSort.scala
@@ -0,0 +1,63 @@
+import leon.invariant._
+import leon.instrumentation._
+
+import leon.annotation._
+
+object MergeSort {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(list: List): BigInt = (list match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }) //ensuring(res => true && tmpl((a) => res >= 0))
+
+  def length(l: List): BigInt = {
+    l match {
+      case Nil() => BigInt(0)
+      case Cons(x,xs) => 1 + length(xs)
+    }
+  } ensuring(res => res == size(l) && tmpl((a,b) => stack <= a*size(l) + b))
+
+  def split(l: List, n: BigInt): (List, List) = {
+    require(n >= 0 && n <= size(l))
+    if (n <= 0) (Nil(),l)
+    else
+      l match {
+        case Nil() => (Nil(),l)
+        case Cons(x,xs) => {
+          if(n == 1) (Cons(x,Nil()), xs)
+          else {
+            val (fst,snd) = split(xs, n-1)
+            (Cons(x,fst), snd)
+          }
+        }
+    }
+  } ensuring(res => size(res._2) == size(l) - n && size(res._1) == n && size(res._2) + size(res._1) == size(l) && tmpl((a,b) => stack <= a*size(l) +b))
+
+  def merge(aList: List, bList: List): List = (bList match {
+    case Nil() => aList
+    case Cons(x,xs) =>
+      aList match {
+        case Nil() => bList
+        case Cons(y,ys) =>
+          if (y < x)
+            Cons(y,merge(ys, bList))
+          else
+            Cons(x,merge(aList, xs))
+     }
+  }) ensuring(res => size(aList) + size(bList) == size(res) && tmpl((a,b,c) => stack <= a*size(aList) + b*size(bList) + c))
+
+  def mergeSort(list: List): List = {
+    list match {
+      case Cons(x, Nil()) => list
+      case Cons(_, Cons(_, _)) =>
+        val lby2 = length(list) / 2
+        val (fst, snd) = split(list, lby2)
+        merge(mergeSort(fst), mergeSort(snd))
+
+      case _ => list
+    }
+  } ensuring(res => size(res) == size(list) && tmpl((a,b) => stack <= a*size(list) + b))
+}
diff --git a/testcases/orb-testcases/stack/QuickSort.scala b/testcases/orb-testcases/stack/QuickSort.scala
new file mode 100644
index 000000000..201504753
--- /dev/null
+++ b/testcases/orb-testcases/stack/QuickSort.scala
@@ -0,0 +1,41 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object QuickSort {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+
+  def size(l:List): BigInt = {l match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }}
+
+  case class Triple(fst:List,snd:List, trd: List)
+
+  def append(aList:List,bList:List): List = {aList match {
+    case Nil() => bList
+    case Cons(x, xs) => Cons(x,append(xs,bList))
+  }} ensuring(res => size(res) == size(aList) + size(bList) && tmpl((a,b) => stack <= a*size(aList) +b))
+
+  def partition(n:BigInt,l:List) : Triple = (l match {
+    case Nil() => Triple(Nil(), Nil(), Nil())
+    case Cons(x,xs) => {
+      val t = partition(n,xs)
+      if (n < x) Triple(t.fst, t.snd, Cons(x,t.trd))
+      else if(n == x) Triple(t.fst, Cons(x,t.snd), t.trd)
+      else Triple(Cons(x,t.fst), t.snd, t.trd)
+    }
+ }) ensuring(res => (size(l) == size(res.fst) + size(res.snd) + size(res.trd)) && tmpl((a,b) => stack <= a*size(l) +b))
+
+  def quickSort(l:List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,Nil()) => l
+    case Cons(x,xs) => {
+      val t = partition(x, xs)
+      append(append(quickSort(t.fst), Cons(x, t.snd)), quickSort(t.trd))
+    }
+    case _ => l
+  }) ensuring(res => size(l) == size(res) && tmpl((a,b,c,d) => stack <= a*size(l) + d))
+}
+
diff --git a/testcases/orb-testcases/stack/RedBlackTree.scala b/testcases/orb-testcases/stack/RedBlackTree.scala
new file mode 100644
index 000000000..44f84a9b3
--- /dev/null
+++ b/testcases/orb-testcases/stack/RedBlackTree.scala
@@ -0,0 +1,110 @@
+import leon.invariant._
+import leon.instrumentation._
+import scala.collection.immutable.Set
+
+object RedBlackTree {
+  sealed abstract class Color
+  case class Red() extends Color
+  case class Black() extends Color
+
+  sealed abstract class Tree
+  case class Empty() extends Tree
+  case class Node(color: Color, left: Tree, value: BigInt, right: Tree) extends Tree
+
+  def twopower(x: BigInt) : BigInt = {
+    require(x >= 0)
+    if(x < 1) 1
+    else
+      2* twopower(x - 1)
+  }
+
+  def size(t: Tree): BigInt = {
+    require(blackBalanced(t))
+    (t match {
+      case Empty() => BigInt(0)
+      case Node(_, l, v, r) => size(l) + 1 + size(r)
+    })
+  } ensuring (res => tmpl((a,b) => twopower(blackHeight(t)) <= a*res + b))
+
+  def blackHeight(t : Tree) : BigInt = {
+   t match {
+    case Node(Black(), l, _, _) => blackHeight(l) + 1
+    case Node(Red(), l, _, _) => blackHeight(l)
+    case _ => 0
+   	}
+  }
+
+   //We consider leaves to be black by definition
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty() => true
+    case Node(Black(),_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty() => true
+    case Node(Black(), l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red(), l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case _ => false
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case _ => true
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case _ => true
+  }
+
+  // <<insert element x BigInto the tree t>>
+  def ins(x: BigInt, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+
+    t match {
+      case Empty() => Node(Red(),Empty(),x,Empty())
+      case Node(c,a,y,b) =>
+        if(x < y) {
+        	val t1 = ins(x, a)
+        	balance(c, t1, y, b)
+        }
+        else if (x == y){
+        	Node(c,a,y,b)
+        }
+        else{
+          val t1 = ins(x, b)
+          balance(c,a,y,t1)
+        }
+    }
+  } ensuring(res => tmpl((a,b) => stack <= a*blackHeight(t) + b))
+
+  def makeBlack(n: Tree): Tree = {
+    n match {
+      case Node(Red(),l,v,r) => Node(Black(),l,v,r)
+      case _ => n
+    }
+  }
+
+  def add(x: BigInt, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    val t1 =  ins(x, t)
+    makeBlack(t1)
+
+  } ensuring(res => tmpl((a,b) => stack <= a*blackHeight(t) + b))
+
+  def balance(co: Color, l: Tree, x: BigInt, r: Tree): Tree = {
+    Node(co,l,x,r)
+     match {
+      case Node(Black(),Node(Red(),Node(Red(),a,xV,b),yV,c),zV,d) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case Node(Black(),Node(Red(),a,xV,Node(Red(),b,yV,c)),zV,d) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case Node(Black(),a,xV,Node(Red(),Node(Red(),b,yV,c),zV,d)) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case Node(Black(),a,xV,Node(Red(),b,yV,Node(Red(),c,zV,d))) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case _ => Node(co,l,x,r)
+    }
+  }
+}
diff --git a/testcases/orb-testcases/stack/SpeedBenchmarks.scala b/testcases/orb-testcases/stack/SpeedBenchmarks.scala
new file mode 100644
index 000000000..c1c59d592
--- /dev/null
+++ b/testcases/orb-testcases/stack/SpeedBenchmarks.scala
@@ -0,0 +1,75 @@
+import leon.invariant._
+import leon.instrumentation._
+import leon.math._
+
+object SpeedBenchmarks {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  sealed abstract class StringBuffer
+  case class Chunk(str: List, next: StringBuffer) extends StringBuffer
+  case class Empty() extends StringBuffer
+
+  def length(sb: StringBuffer) : BigInt = sb match {
+    case Chunk(_, next) => 1 + length(next)
+    case _ => 0
+  }
+
+  def sizeBound(sb: StringBuffer, k: BigInt) : Boolean ={
+    sb match {
+      case Chunk(str, next) => size(str) <= k && sizeBound(next, k)
+      case _ => 0 <= k
+    }
+  }
+
+  def sizeBuffer(sb: StringBuffer): BigInt = {
+    sb match {
+      case Chunk(str, next) => size(str) + sizeBuffer(sb)
+      case Empty() => 0
+    }
+  }
+
+  /**
+   * Fig. 1 of SPEED, POPL'09: The functional version of the implementation.
+   * Equality check of two string buffers
+   */
+  def Equals(str1: List, str2: List, s1: StringBuffer, s2: StringBuffer, k: BigInt) : Boolean = {
+    require(sizeBound(s1, k) && sizeBound(s2, k) && size(str1) <= k && size(str2) <= k && k >= 0)
+
+    (str1, str2) match {
+      case (Cons(h1,t1), Cons(h2,t2)) => {
+        if(h1 != h2) false
+        else Equals(t1,t2, s1,s2, k)
+      }
+      case (Cons(_,_), Nil()) => {
+        //load from s2
+        s2 match {
+          case Chunk(str, next) => Equals(str1, str, s1, next, k)
+          case Empty() => false
+        }
+      }
+      case (Nil(), Cons(_,_)) => {
+        //load from s1
+        s1 match {
+          case Chunk(str, next) => Equals(str, str2, next, s2, k)
+          case Empty() => false
+        }
+      }
+      case _ =>{
+        //load from both
+        (s1,s2) match {
+          case (Chunk(nstr1, next1),Chunk(nstr2, next2)) => Equals(nstr1, nstr2, next1, next2, k)
+          case (Empty(),Chunk(nstr2, next2)) => Equals(str1, nstr2, s1, next2, k)
+          case (Chunk(nstr1, next1), Empty()) => Equals(nstr1, str2, next1, s2, k)
+          case _ => true
+        }
+      }
+    }
+  } ensuring(res => tmpl((a,b,c,d,e) => stack <= a*max(sizeBuffer(s1), sizeBuffer(s2)) + c*(k+1) + e))
+}
diff --git a/testcases/orb-testcases/stack/TreeOperations.scala b/testcases/orb-testcases/stack/TreeOperations.scala
new file mode 100644
index 000000000..123031d7d
--- /dev/null
+++ b/testcases/orb-testcases/stack/TreeOperations.scala
@@ -0,0 +1,93 @@
+import leon.invariant._
+import leon.instrumentation._
+
+
+object TreeOperations {
+
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  sealed abstract class Tree
+  case class Node(left: Tree, value: BigInt, right: Tree) extends Tree
+  case class Leaf() extends Tree
+
+  def listSize(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + listSize(t)
+  })
+
+  def size(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        size(l) + size(r) + 1
+      }
+    }
+  }
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def insert(elem: BigInt, t: Tree): Tree = {
+    t match {
+      case Leaf() => Node(Leaf(), elem, Leaf())
+      case Node(l, x, r) => if (x <= elem) Node(l, x, insert(elem, r))
+      else Node(insert(elem, l), x, r)
+    }
+  } ensuring (res => height(res) <= height(t) + 1 && tmpl((a,b) => stack <= a*height(t) + b))
+
+  def addAll(l: List, t: Tree): Tree = {
+    l match {
+      case Nil() => t
+      case Cons(x, xs) =>{
+        val newt = insert(x, t)
+        addAll(xs, newt)
+      }
+    }
+  } ensuring(res => tmpl((a,b,c) => stack <= a*(listSize(l) * (height(t) + listSize(l))) + b*listSize(l) + c))
+
+  def remove(elem: BigInt, t: Tree): Tree = {
+    t match {
+      case Leaf() => Leaf()
+      case Node(l, x, r) => {
+
+        if (x < elem) Node(l, x, remove(elem, r))
+        else if (x > elem) Node(remove(elem, l), x, r)
+        else {
+          t match {
+            case Node(Leaf(), x, Leaf()) => Leaf()
+            case Node(Leaf(), x, Node(_, rx, _)) => Node(Leaf(), rx, remove(rx, r))
+            case Node(Node(_, lx, _), x, r) => Node(remove(lx, l), lx, r)
+            case _ => Leaf()
+          }
+        }
+      }
+    }
+  } ensuring (res => height(res) <= height(t) && tmpl ((a, b, c) => stack <= a*height(t) + b))
+
+  def removeAll(l: List, t: Tree): Tree = {
+    l match {
+      case Nil() => t
+      case Cons(x, xs) => removeAll(xs, remove(x, t))
+    }
+  } ensuring(res => tmpl((a,b,c) => stack <= a*(listSize(l) * height(t)) + b*listSize(l) + c))
+
+  def contains(elem : BigInt, t : Tree) : Boolean = {
+    t match {
+      case Leaf() => false
+      case Node(l, x, r) =>
+        if(x == elem) true
+        else if (x < elem) contains(elem, r)
+        else contains(elem, l)
+    }
+  } ensuring (res => tmpl((a,b) => stack <= a*height(t) + b))
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/timing/AVLTree.scala b/testcases/orb-testcases/timing/AVLTree.scala
new file mode 100644
index 000000000..d34787eba
--- /dev/null
+++ b/testcases/orb-testcases/timing/AVLTree.scala
@@ -0,0 +1,195 @@
+import leon.invariant._
+import leon.instrumentation._
+import leon.math._
+
+/**
+ * created by manos and modified by ravi.
+ * BST property cannot be verified
+ */
+object AVLTree  {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(left : Tree, value : BigInt, right: Tree, rank : BigInt) extends Tree
+
+  sealed abstract class OptionInt
+  case class None() extends OptionInt
+  case class Some(i: BigInt) extends OptionInt
+
+  //def min(i1:BigInt, i2:BigInt) : BigInt = if (i1<=i2) i1 else i2
+  //def max(i1:BigInt, i2:BigInt) : BigInt = if (i1>=i2) i1 else i2
+
+  /*def twopower(x: BigInt) : BigInt = {
+    //require(x >= 0)
+    if(x < 1) 1
+    else
+      3/2 * twopower(x - 1)
+  } ensuring(res => res >= 1 template((a) => a <= 0))*/
+
+  def rank(t: Tree) : BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(_,_,_,rk) => rk
+    }
+  } //ensuring(res => res >= 0)
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r, _) => {
+        val hl = height(l)
+        val hr = height(r)
+        max(hl,hr) + 1
+      }
+    }
+  }
+
+  def size(t: Tree): BigInt = {
+    //require(isAVL(t))
+    (t match {
+      case Leaf() => 0
+      case Node(l, _, r,_) => size(l) + 1 + size(r)
+    })
+
+  }
+  //ensuring (res => true template((a,b) => height(t) <= a*res + b))
+
+  def rankHeight(t: Tree) : Boolean = t match {
+    case Leaf() => true
+    case Node(l,_,r,rk) => rankHeight(l) && rankHeight(r) && rk == height(t)
+  }
+
+  def balanceFactor(t : Tree) : BigInt = {
+    t match{
+      case Leaf() => 0
+      case Node(l, _, r, _) => rank(l) - rank(r)
+    }
+  }
+
+  /*def isAVL(t:Tree) : Boolean = {
+    t match {
+        case Leaf() => true
+        case Node(l,_,r,rk) =>  isAVL(l) && isAVL(r) && balanceFactor(t) >= -1 && balanceFactor(t) <= 1 && rankHeight(t) //isBST(t) &&
+      }
+  }*/
+
+  def unbalancedInsert(t: Tree, e : BigInt) : Tree = {
+    t match {
+      case Leaf() => Node(Leaf(), e, Leaf(), 1)
+      case Node(l,v,r,h) =>
+             if (e == v) t
+        else if (e <  v){
+          val newl = avlInsert(l,e)
+          Node(newl, v, r, max(rank(newl), rank(r)) + 1)
+        }
+        else {
+          val newr = avlInsert(r,e)
+          Node(l, v, newr, max(rank(l), rank(newr)) + 1)
+        }
+    }
+  }
+
+  def avlInsert(t: Tree, e : BigInt) : Tree = {
+
+    balance(unbalancedInsert(t,e))
+
+  } ensuring(res => tmpl((a,b) => time <= a*height(t) + b))
+  //ensuring(res => time <= 276*height(t) + 38)
+  //minbound: ensuring(res => time <= 138*height(t) + 19)
+
+  def deletemax(t: Tree): (Tree, OptionInt) = {
+
+    t match {
+      case Node(Leaf(), v, Leaf(), _) => (Leaf(), Some(v))
+      case Node(l, v, Leaf(), _) => {
+        val (newl, opt) =  deletemax(l)
+        opt match {
+          case None() => (t, None())
+          case Some(lmax) => {
+            val newt = balance(Node(newl, lmax, Leaf(), rank(newl) + 1))
+            (newt, Some(v))
+          }
+        }
+      }
+      case Node(_, _, r, _) => deletemax(r)
+      case _ => (t, None())
+    }
+  } ensuring(res => tmpl((a,b) => time <= a*height(t) + b))
+
+  def unbalancedDelete(t: Tree, e: BigInt): Tree = {
+    t match {
+      case Leaf() => Leaf() //not found case
+      case Node(l, v, r, h) =>
+        if (e == v) {
+          if (l == Leaf()) r
+          else if(r == Leaf()) l
+          else {
+            val (newl, opt) = deletemax(l)
+            opt match {
+              case None() => t
+              case Some(newe) => {
+                Node(newl, newe, r, max(rank(newl), rank(r)) + 1)
+              }
+            }
+          }
+        } else if (e < v) {
+          val newl = avlDelete(l, e)
+          Node(newl, v, r, max(rank(newl), rank(r)) + 1)
+        } else {
+          val newr = avlDelete(r, e)
+          Node(l, v, newr, max(rank(l), rank(newr)) + 1)
+        }
+    }
+  }
+
+  def avlDelete(t: Tree, e: BigInt): Tree = {
+
+    balance(unbalancedDelete(t, e))
+
+  } ensuring(res => tmpl((a,b) => time <= a*height(t) + b))
+
+  def balance(t:Tree) : Tree = {
+    t match {
+      case Leaf() => Leaf() // impossible...
+      case Node(l, v, r, h) =>
+        val bfactor = balanceFactor(t)
+        // at this point, the tree is unbalanced
+        if(bfactor > 1 ) { // left-heavy
+          val newL =
+            if (balanceFactor(l) < 0) { // l is right heavy
+              rotateLeft(l)
+            }
+            else l
+          rotateRight(Node(newL,v,r, max(rank(newL), rank(r)) + 1))
+        }
+        else if(bfactor < -1) {
+          val newR =
+            if (balanceFactor(r) > 0) { // r is left heavy
+              rotateRight(r)
+            }
+            else r
+          rotateLeft(Node(l,v,newR, max(rank(newR), rank(l)) + 1))
+        } else t
+      }
+  }
+
+  def rotateRight(t:Tree) = {
+    t match {
+      case Node(Node(ll, vl, rl, _),v,r, _) =>
+
+        val hr = max(rank(rl),rank(r)) + 1
+        Node(ll, vl, Node(rl,v,r,hr), max(rank(ll),hr) + 1)
+
+      case _ => t // this should not happen
+  } }
+
+
+  def rotateLeft(t:Tree) =  {
+    t match {
+      case Node(l, v, Node(lr,vr,rr,_), _) =>
+
+        val hl = max(rank(l),rank(lr)) + 1
+        Node(Node(l,v,lr,hl), vr, rr, max(hl, rank(rr)) + 1)
+      case _ => t // this should not happen
+  } }
+}
+
diff --git a/testcases/orb-testcases/timing/AmortizedQueue.scala b/testcases/orb-testcases/timing/AmortizedQueue.scala
new file mode 100644
index 000000000..23b5c3572
--- /dev/null
+++ b/testcases/orb-testcases/timing/AmortizedQueue.scala
@@ -0,0 +1,88 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object AmortizedQueue {
+  sealed abstract class List
+  case class Cons(head : BigInt, tail : List) extends List
+  case class Nil() extends List
+
+  case class Queue(front : List, rear : List)
+
+  def size(list : List) : BigInt = (list match {
+    case Nil() => 0
+    case Cons(_, xs) => 1 + size(xs)
+  })
+
+  def sizeList(list: List): BigInt = {
+    list match {
+      case Nil() => BigInt(0)
+      case Cons(_, xs) => 1 + sizeList(xs)
+    }
+  }ensuring((res : BigInt) => res >= 0 && tmpl((a, b) => time <= a * size(list) + b))
+
+  def qsize(q : Queue) : BigInt = size(q.front) + size(q.rear)
+
+  def asList(q : Queue) : List = concat(q.front, reverse(q.rear))
+
+  def concat(l1 : List, l2 : List) : List = (l1 match {
+    case Nil() => l2
+    case Cons(x,xs) => Cons(x, concat(xs, l2))
+
+  }) ensuring (res => size(res) == size(l1) + size(l2) && tmpl((a,b,c) => time <= a*size(l1) + b))
+
+  def isAmortized(q : Queue) : Boolean = sizeList(q.front) >= sizeList(q.rear)
+
+  def isEmpty(queue : Queue) : Boolean = queue match {
+    case Queue(Nil(), Nil()) => true
+    case _ => false
+  }
+
+  def reverseRec(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => reverseRec(xs, Cons(x, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => time <= a*size(l1) + b))
+
+  def reverse(l: List): List = {
+    reverseRec(l, Nil())
+  } ensuring (res => size(l) == size(res) && tmpl((a,b) => time <= a*size(l) + b))
+
+  def amortizedQueue(front : List, rear : List) : Queue = {
+    if (sizeList(rear) <= sizeList(front))
+      Queue(front, rear)
+    else
+      Queue(concat(front, reverse(rear)), Nil())
+  }
+
+  def enqueue(q : Queue, elem : BigInt) : Queue = ({
+
+    amortizedQueue(q.front, Cons(elem, q.rear))
+
+  }) ensuring(res =>  true && tmpl((a,b) => time <= a*qsize(q) + b))
+
+  def dequeue(q : Queue) : Queue = {
+    require(isAmortized(q) && !isEmpty(q))
+    q match {
+      case Queue(Cons(f, fs), rear) => amortizedQueue(fs, rear)
+      case _ => Queue(Nil(),Nil())
+    }
+  } ensuring(res =>  true && tmpl((a,b) => time <= a*qsize(q) + b))
+
+  def removeLast(l : List) : List = {
+    require(l != Nil())
+    l match {
+      case Cons(x,Nil()) => Nil()
+      case Cons(x,xs) => Cons(x, removeLast(xs))
+      case _ => Nil()
+    }
+  } ensuring(res =>  size(res) <= size(l) && tmpl((a,b) => time <= a*size(l) + b))
+
+  def pop(q : Queue) : Queue = {
+    require(isAmortized(q) && !isEmpty(q))
+    q match {
+     case Queue(front, Cons(r,rs)) => Queue(front, rs)
+     case Queue(front, rear) => Queue(removeLast(front), rear)
+     case _ => Queue(Nil(),Nil())
+    }
+  } ensuring(res =>  true && tmpl((a,b) => time <= a*size(q.front) + b))
+}
diff --git a/testcases/orb-testcases/timing/BinaryTrie.scala b/testcases/orb-testcases/timing/BinaryTrie.scala
new file mode 100644
index 000000000..a1de6ee0e
--- /dev/null
+++ b/testcases/orb-testcases/timing/BinaryTrie.scala
@@ -0,0 +1,119 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object BinaryTrie {
+  sealed abstract class Tree
+  case class Leaf() extends Tree
+  case class Node(nvalue: BigInt, left: Tree, right: Tree) extends Tree
+
+  sealed abstract class IList
+  case class Cons(head: BigInt, tail: IList) extends IList
+  case class Nil() extends IList
+
+  def listSize(l: IList): BigInt = (l match {
+    case Nil() => 0
+    case Cons(x, xs) => 1 + listSize(xs)
+  })
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(x, l, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  }
+
+  def find(inp: IList, t: Tree): Tree = {
+    inp match {
+      case Nil() => t
+      case Cons(x, Nil()) => t
+      case Cons(x, xs @ Cons(y, _)) => {
+        t match {
+          case Leaf() => t
+          case Node(v, l, r) => {
+            if (y > 0) find(xs, l) else find(xs, r)
+          }
+        }
+      }
+      case _ => t
+    }
+  } ensuring (_ => time <= ? * listSize(inp) + ?)
+
+  def insert(inp: IList, t: Tree): Tree = {
+    t match {
+      case Leaf() => {
+        inp match {
+          case Nil() => t
+          case Cons(x, xs) => {
+            val newch = insert(xs, Leaf())
+            newch match {
+              case Leaf() => Node(x, Leaf(), Leaf())
+              case Node(y, _, _) => if (y > 0) Node(x, newch, Leaf()) else Node(y, Leaf(), newch)
+            }
+          }
+        }
+
+      }
+      case Node(v, l, r) => {
+        inp match {
+          case Nil() => t
+          case Cons(x, Nil()) => t
+          case Cons(x, xs @ Cons(y, _)) => {
+            val ch = if (y > 0) l else r
+            if (y > 0)
+              Node(v, insert(xs, ch), r)
+            else
+              Node(v, l, insert(xs, ch))
+          }
+          case _ => t
+        }
+      }
+    }
+  } ensuring (_ => time <= ? * listSize(inp) + ?)
+
+  def create(inp: IList): Tree = {
+    insert(inp, Leaf())
+  } ensuring (res => true && tmpl((a, c) => time <= a * listSize(inp) + c))
+
+  def delete(inp: IList, t: Tree): Tree = {
+    t match {
+        case Leaf() => {
+          inp match {
+            case Nil() => Leaf()
+            case Cons(x ,xs) => {
+              //the input is not in the tree, so do nothing
+              Leaf()
+            }
+          }
+        }
+        case Node(v, l, r) => {
+          inp match {
+            case Nil() => {
+              //the tree has extensions of the input list so do nothing
+              t
+            }
+            case Cons(x, Nil()) => {
+              //if "l" and "r" are nil, remove the node
+              if(l == Leaf() && r == Leaf()) Leaf()
+              else t
+            }
+            case Cons(x ,xs@Cons(y, _)) => {
+              val ch = if(y > 0) l else r
+              val newch = delete(xs, ch)
+              if(newch == Leaf() && ((y > 0 && r == Leaf()) || (y <= 0 && l == Leaf()))) Leaf()
+              else {
+                if(y > 0)
+        		  Node(v, newch, r)
+        	    else
+        	      Node(v, l, newch)
+              }
+            }
+            case _ => t
+        }
+      }
+    }
+  } ensuring (_ => time <= ? * listSize(inp) + ?)
+}
diff --git a/testcases/orb-testcases/timing/BinomialHeap.scala b/testcases/orb-testcases/timing/BinomialHeap.scala
new file mode 100644
index 000000000..81b990d41
--- /dev/null
+++ b/testcases/orb-testcases/timing/BinomialHeap.scala
@@ -0,0 +1,181 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object BinomialHeap {
+  //sealed abstract class TreeNode
+  case class TreeNode(rank: BigInt, elem: Element, children: BinomialHeap)
+  case class Element(n: BigInt)
+
+  sealed abstract class BinomialHeap
+  case class ConsHeap(head: TreeNode, tail: BinomialHeap) extends BinomialHeap
+  case class NilHeap() extends BinomialHeap
+
+  sealed abstract class List
+  case class NodeL(head: BinomialHeap, tail: List) extends List
+  case class NilL() extends List
+
+  sealed abstract class OptionalTree
+  case class Some(t : TreeNode) extends OptionalTree
+  case class None() extends OptionalTree
+
+  /* Lower or Equal than for Element structure */
+  private def leq(a: Element, b: Element) : Boolean = {
+    a match {
+      case Element(a1) => {
+        b match {
+          case Element(a2) => {
+            if(a1 <= a2) true
+            else false
+          }
+        }
+      }
+    }
+  }
+
+  /* isEmpty function of the Binomial Heap */
+  def isEmpty(t: BinomialHeap) = t match {
+    case ConsHeap(_,_) => false
+    case _ => true
+  }
+
+  /* Helper function to determine rank of a TreeNode */
+  def rank(t: TreeNode) : BigInt = t.rank /*t match {
+    case TreeNode(r, _, _) => r
+  }*/
+
+  /* Helper function to get the root element of a TreeNode */
+  def root(t: TreeNode) : Element = t.elem /*t match {
+    case TreeNode(_, e, _) => e
+  }*/
+
+  /* Linking trees of equal ranks depending on the root element */
+  def link(t1: TreeNode, t2: TreeNode): TreeNode = {
+    if (leq(t1.elem, t2.elem)) {
+      TreeNode(t1.rank + 1, t1.elem, ConsHeap(t2, t1.children))
+    } else {
+      TreeNode(t1.rank + 1, t2.elem, ConsHeap(t1, t2.children))
+    }
+  }
+
+  def treeNum(h: BinomialHeap) : BigInt = {
+    h match {
+      case ConsHeap(head, tail) =>  1 + treeNum(tail)
+      case _ => 0
+    }
+  }
+
+  /* Insert a tree into a binomial heap. The tree should be correct in relation to the heap */
+  def insTree(t: TreeNode, h: BinomialHeap) : BinomialHeap = {
+    h match {
+      case ConsHeap(head, tail) =>  {
+        if (rank(t) < rank(head)) {
+          ConsHeap(t, h)
+        } else if (rank(t) > rank(head)) {
+          ConsHeap(head, insTree(t,tail))
+        } else {
+          insTree(link(t,head), tail)
+        }
+      }
+      case _ => ConsHeap(t, NilHeap())
+    }
+  } ensuring(_ => time <= ? * treeNum(h) + ?)
+
+  /* Merge two heaps together */
+  def merge(h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    h1 match {
+      case ConsHeap(head1, tail1) => {
+        h2 match {
+          case ConsHeap(head2, tail2) => {
+            if (rank(head1) < rank(head2)) {
+              ConsHeap(head1, merge(tail1, h2))
+            } else if (rank(head2) < rank(head1)) {
+              ConsHeap(head2, merge(h1, tail2))
+            } else {
+              mergeWithCarry(link(head1, head2), tail1, tail2)
+            }
+          }
+          case _ => h1
+        }
+      }
+      case _ => h2
+    }
+  } ensuring(_ => time <= ? * treeNum(h1) + ? * treeNum(h2) + ?)
+
+  def mergeWithCarry(t: TreeNode, h1: BinomialHeap, h2: BinomialHeap): BinomialHeap = {
+    h1 match {
+      case ConsHeap(head1, tail1) => {
+        h2 match {
+          case ConsHeap(head2, tail2) => {
+            if (rank(head1) < rank(head2)) {
+
+              if (rank(t) < rank(head1))
+                ConsHeap(t, ConsHeap(head1, merge(tail1, h2)))
+              else
+                mergeWithCarry(link(t, head1), tail1, h2)
+
+            } else if (rank(head2) < rank(head1)) {
+
+              if (rank(t) < rank(head2))
+                ConsHeap(t, ConsHeap(head2, merge(h1, tail2)))
+              else
+                mergeWithCarry(link(t, head2), h1, tail2)
+
+            } else {
+              ConsHeap(t, mergeWithCarry(link(head1, head2), tail1, tail2))
+            }
+          }
+          case _ => {
+            insTree(t, h1)
+          }
+        }
+      }
+      case _ => insTree(t, h2)
+    }
+  } ensuring (_ => time <= ? * treeNum(h1) + ? * treeNum(h2) + ?)
+
+  //Auxiliary helper function to simplefy findMin and deleteMin
+  def removeMinTree(h: BinomialHeap): (OptionalTree, BinomialHeap) = {
+    h match {
+      case ConsHeap(head, NilHeap()) => (Some(head), NilHeap())
+      case ConsHeap(head1, tail1) => {
+        val (opthead2, tail2) = removeMinTree(tail1)
+        opthead2 match {
+          case Some(head2) =>
+            if (leq(root(head1), root(head2))) {
+              (Some(head1), tail1)
+            } else {
+              (Some(head2), ConsHeap(head1, tail2))
+            }
+          case _ => (Some(head1), tail1)
+        }
+      }
+      case _ => (None(), NilHeap())
+    }
+  } ensuring (res => treeNum(res._2) <= treeNum(h) && time <= ? * treeNum(h) + ?)
+
+  /*def findMin(h: BinomialHeap) : Element = {
+	  val (opt, _) = removeMinTree(h)
+	  opt match {
+	    case Some(TreeNode(_,e,ts1)) => e
+	    case _ => Element(-1)
+	  }
+  } ensuring(res => true && tmpl((a,b) => time <= a*treeNum(h) + b))*/
+
+  def minTreeChildren(h: BinomialHeap) : BigInt = {
+    val (min, _) = removeMinTree(h)
+    min match {
+      case Some(TreeNode(_,_,ch)) => treeNum(ch)
+      case _ => 0
+	  }
+  }
+
+  // Discard the minimum element of the extracted min tree and put its children back into the heap
+  def deleteMin(h: BinomialHeap) : BinomialHeap = {
+	  val (min, ts2) = removeMinTree(h)
+	  min match {
+		case Some(TreeNode(_,_,ts1)) => merge(ts1, ts2)
+		case _ => h
+	  }
+  } ensuring(_ => time <= ? * minTreeChildren(h) + ? * treeNum(h) + ?)
+
+}
diff --git a/testcases/orb-testcases/timing/ConcTrees.scala b/testcases/orb-testcases/timing/ConcTrees.scala
new file mode 100644
index 000000000..914578929
--- /dev/null
+++ b/testcases/orb-testcases/timing/ConcTrees.scala
@@ -0,0 +1,536 @@
+package conctrees
+
+import leon.instrumentation._
+import leon.collection._
+import leon.lang._
+import ListSpecs._
+import leon.annotation._
+import leon.invariant._
+
+object ConcTrees {
+
+  def max(x: BigInt, y: BigInt): BigInt = if (x >= y) x else y
+  def abs(x: BigInt): BigInt = if (x < 0) -x else x
+
+  sealed abstract class Conc[T] {
+
+    def isEmpty: Boolean = {
+      this == Empty[T]()
+    }
+
+    def isLeaf: Boolean = {
+      this match {
+        case Empty() => true
+        case Single(_) => true
+        case _ => false
+      }
+    }
+
+    def isNormalized: Boolean = this match {
+      case Append(_, _) => false
+      case _ => true
+    }
+
+    def valid: Boolean = {
+      concInv && balanced && appendInv
+    }
+
+    /**
+     * (a) left and right trees of conc node should be non-empty
+     * (b) they cannot be append nodes
+     */
+    def concInv: Boolean = this match {
+      case CC(l, r) =>
+        !l.isEmpty && !r.isEmpty &&
+        l.isNormalized && r.isNormalized &&
+        l.concInv && r.concInv
+      case _ => true
+    }
+
+    def balanced: Boolean = {
+      this match {
+        case CC(l, r) =>
+          l.level - r.level >= -1 && l.level - r.level <= 1 &&
+          l.balanced && r.balanced
+        case _ => true
+      }
+    }
+
+    /**
+     * (a) Right subtree of an append node is not an append node
+     * (b) If the tree is of the form a@Append(b@Append(_,_),_) then
+     *    a.right.level < b.right.level
+     * (c) left and right are not empty
+     */
+    def appendInv: Boolean = this match {
+      case Append(l, r) =>
+      !l.isEmpty && !r.isEmpty &&
+      l.valid && r.valid &&
+      r.isNormalized &&
+      (l match {
+        case Append(_, lr) =>
+        lr.level > r.level
+        case _ =>
+        l.level > r.level
+        })
+      case _ => true
+    }
+
+    val level: BigInt = {
+      (this match {
+        case Empty() => 0
+        case Single(x) => 0
+        case CC(l, r) =>
+          1 + max(l.level, r.level)
+        case Append(l, r) =>
+          1 + max(l.level, r.level)
+      }): BigInt
+    } ensuring (_ >= 0)
+
+    val size: BigInt = {
+      (this match {
+        case Empty() => 0
+        case Single(x) => 1
+        case CC(l, r) =>
+          l.size + r.size
+        case Append(l, r) =>
+          l.size + r.size
+      }): BigInt
+    } ensuring (_ >= 0)
+
+    def toList: List[T] = {
+      this match {
+        case Empty() => Nil[T]()
+        case Single(x) => Cons(x, Nil[T]())
+        case CC(l, r) =>
+          l.toList ++ r.toList // note: left elements precede the right elements in the list
+        case Append(l, r) =>
+          l.toList ++ r.toList
+      }
+    } ensuring (res => res.size == this.size)
+  }
+
+  case class Empty[T]() extends Conc[T]
+  case class Single[T](x: T) extends Conc[T]
+  case class CC[T](left: Conc[T], right: Conc[T]) extends Conc[T]
+  case class Append[T](left: Conc[T], right: Conc[T]) extends Conc[T]
+
+  /*class Chunk(val array: Array[T], val size: Int, val k: Int) extends Leaf[T] {
+    def level = 0
+    override def toString = s"Chunk(${array.mkString("", ", ", "")}; $size; $k)"
+    }*/
+
+  def lookup[T](xs: Conc[T], i: BigInt): T = {
+    require(xs.valid && !xs.isEmpty && i >= 0 && i < xs.size)
+    xs match {
+      case Single(x) => x
+      case CC(l, r) =>
+        if (i < l.size) {
+          lookup(l, i)
+        } else {
+          lookup(r, i - l.size)
+        }
+      case Append(l, r) =>
+        if (i < l.size) {
+          lookup(l, i)
+        } else {
+          lookup(r, i - l.size)
+        }
+    }
+  } ensuring (res => tmpl((a,b) => time <= a*xs.level + b) && // lookup time is linear in the height
+    res == xs.toList(i) && // correctness
+    instAppendIndexAxiom(xs, i)) // an auxiliary axiom instantiation that is required for the proof
+
+  // @library
+  def instAppendIndexAxiom[T](xs: Conc[T], i: BigInt): Boolean = {
+    require(0 <= i && i < xs.size)
+    xs match {
+      case CC(l, r) =>
+        appendIndex(l.toList, r.toList, i)
+      case Append(l, r) =>
+        appendIndex(l.toList, r.toList, i)
+      case _ => true
+    }
+  }.holds
+
+  @library
+  def update[T](xs: Conc[T], i: BigInt, y: T): Conc[T] = {
+    require(xs.valid && !xs.isEmpty && i >= 0 && i < xs.size)
+    xs match {
+      case Single(x) => Single(y)
+      case CC(l, r) =>
+        if (i < l.size)
+          CC(update(l, i, y), r)
+        else
+          CC(l, update(r, i - l.size, y))
+      case Append(l, r) =>
+        if (i < l.size)
+          Append(update(l, i, y), r)
+        else
+          Append(l, update(r, i - l.size, y))
+    }
+  } ensuring (res => res.level == xs.level && // heights of the input and output trees are equal
+   res.valid && // tree invariants are preserved
+   tmpl((a,b) => time <= a*xs.level + b) && // update time is linear in the height of the tree
+   res.toList == xs.toList.updated(i, y) && // correctness
+   numTrees(res) == numTrees(xs) && //auxiliary property that preserves the potential function
+   instAppendUpdateAxiom(xs, i, y)) // an auxiliary axiom instantiation
+
+  @library
+  def instAppendUpdateAxiom[T](xs: Conc[T], i: BigInt, y: T): Boolean = {
+    require(i >= 0 && i < xs.size)
+    xs match {
+      case CC(l, r) =>
+        appendUpdate(l.toList, r.toList, i, y)
+      case Append(l, r) =>
+        appendUpdate(l.toList, r.toList, i, y)
+      case _ => true
+    }
+  }.holds
+
+  /**
+  * A generic concat that applies to general concTrees
+  */
+  @library
+  def concat[T](xs: Conc[T], ys: Conc[T]): Conc[T] = {
+    require(xs.valid && ys.valid)
+    concatNormalized(normalize(xs), normalize(ys))
+  }
+
+  /**
+  * This concat applies only to normalized trees.
+  * This prevents concat from being recursive
+  */
+  @library
+  def concatNormalized[T](xs: Conc[T], ys: Conc[T]): Conc[T] = {
+    require(xs.valid && ys.valid &&
+      xs.isNormalized && ys.isNormalized)
+    (xs, ys) match {
+      case (xs, Empty()) => xs
+      case (Empty(), ys) => ys
+      case _ =>
+        concatNonEmpty(xs, ys)
+    }
+  } ensuring (res => res.valid && // tree invariants
+   res.level <= max(xs.level, ys.level) + 1 && // height invariants
+   res.level >= max(xs.level, ys.level) &&
+   (res.toList == xs.toList ++ ys.toList) && // correctness
+   res.isNormalized //auxiliary properties
+   )
+
+  //@library
+  def concatNonEmpty[T](xs: Conc[T], ys: Conc[T]): Conc[T] = {
+    require(xs.valid && ys.valid &&
+      xs.isNormalized && ys.isNormalized &&
+      !xs.isEmpty && !ys.isEmpty)
+
+    val diff = ys.level - xs.level
+    if (diff >= -1 && diff <= 1)
+      CC(xs, ys)
+    else if (diff < -1) {
+      // ys is smaller than xs
+      xs match {
+        case CC(l, r) =>
+          if (l.level >= r.level)
+            CC(l, concatNonEmpty(r, ys))
+          else {
+            r match {
+              case CC(rl, rr) =>
+                val nrr = concatNonEmpty(rr, ys)
+                if (nrr.level == xs.level - 3)
+                  CC(l, CC(rl, nrr))
+                else
+                  CC(CC(l, rl), nrr)
+            }
+          }
+      }
+    } else {
+      ys match {
+        case CC(l, r) =>
+          if (r.level >= l.level)
+            CC(concatNonEmpty(xs, l), r)
+          else {
+            l match {
+              case CC(ll, lr) =>
+                val nll = concatNonEmpty(xs, ll)
+                if (nll.level == ys.level - 3)
+                  CC(CC(nll, lr), r)
+                else
+                  CC(nll, CC(lr, r))
+            }
+          }
+      }
+    }
+  } ensuring (res => tmpl((a,b) => time <= a*abs(xs.level - ys.level) + b) && // time bound
+   res.level <= max(xs.level, ys.level) + 1 && // height invariants
+   res.level >= max(xs.level, ys.level) &&
+   res.balanced && res.appendInv && res.concInv && //this is should not be needed. But, seems necessary for leon
+   res.valid && // tree invariant is preserved
+   res.toList == xs.toList ++ ys.toList && // correctness
+   res.isNormalized && // auxiliary properties
+   appendAssocInst(xs, ys) // instantiation of an axiom
+   )
+
+  @library
+  def appendAssocInst[T](xs: Conc[T], ys: Conc[T]): Boolean = {
+    (xs match {
+      case CC(l, r) =>
+        appendAssoc(l.toList, r.toList, ys.toList) && //instantiation of associativity of concatenation
+        (r match {
+          case CC(rl, rr) =>
+            appendAssoc(rl.toList, rr.toList, ys.toList) &&
+            appendAssoc(l.toList, rl.toList, rr.toList ++ ys.toList)
+          case _ => true
+        })
+      case _ => true
+    }) &&
+    (ys match {
+      case CC(l, r) =>
+        appendAssoc(xs.toList, l.toList, r.toList) &&
+        (l match {
+          case CC(ll, lr) =>
+            appendAssoc(xs.toList, ll.toList, lr.toList) &&
+            appendAssoc(xs.toList ++ ll.toList, lr.toList, r.toList)
+          case _ => true
+        })
+      case _ => true
+    })
+  }.holds
+
+   @library
+  def insert[T](xs: Conc[T], i: BigInt, y: T): Conc[T] = {
+    require(xs.valid && i >= 0 && i <= xs.size &&
+      xs.isNormalized) //note the precondition
+    xs match {
+      case Empty() => Single(y)
+      case Single(x) =>
+        if (i == 0)
+          CC(Single(y), xs)
+        else
+          CC(xs, Single(y))
+      case CC(l, r) if i < l.size =>
+        concatNonEmpty(insert(l, i, y), r)
+      case CC(l, r) =>
+        concatNonEmpty(l, insert(r, i - l.size, y))
+    }
+  } ensuring (res => res.valid && res.isNormalized && // tree invariants
+   res.level - xs.level <= 1 && res.level >= xs.level && // height of the output tree is at most 1 greater than that of the input tree
+   tmpl((a,b) => time <= a*xs.level + b) && // time is linear in the height of the tree
+   res.toList == xs.toList.insertAt(i, y) && // correctness
+   insertAppendAxiomInst(xs, i, y) // instantiation of an axiom
+   )
+
+  @library
+  def insertAppendAxiomInst[T](xs: Conc[T], i: BigInt, y: T): Boolean = {
+    require(i >= 0 && i <= xs.size)
+    xs match {
+      case CC(l, r) => appendInsert(l.toList, r.toList, i, y)
+      case _ => true
+    }
+  }.holds
+
+  //TODO: why with instrumentation we are not able prove the running time here ? (performance bug ?)
+  @library
+  def split[T](xs: Conc[T], n: BigInt): (Conc[T], Conc[T]) = {
+    require(xs.valid && xs.isNormalized)
+    xs match {
+      case Empty() =>
+        (Empty(), Empty())
+      case s @ Single(x) =>
+        if (n <= 0) { //a minor fix
+          (Empty(), s)
+        } else {
+          (s, Empty())
+        }
+      case CC(l, r) =>
+        if (n < l.size) {
+          val (ll, lr) = split(l, n)
+          (ll, concatNormalized(lr, r))
+        } else if (n > l.size) {
+            val (rl, rr) = split(r, n - l.size)
+            (concatNormalized(l, rl), rr)
+        } else {
+          (l, r)
+        }
+    }
+  } ensuring (res => res._1.valid && res._2.valid && // tree invariants are preserved
+   res._1.isNormalized && res._2.isNormalized &&
+   xs.level >= res._1.level && xs.level >= res._2.level && // height bounds of the resulting tree
+   tmpl((a,b,c,d) => time <= a*xs.level + b*res._1.level + c*res._2.level + d) && // time is linear in height
+   res._1.toList == xs.toList.take(n) && res._2.toList == xs.toList.drop(n) && // correctness
+   instSplitAxiom(xs, n) // instantiation of an axiom
+   )
+
+  @library
+  def instSplitAxiom[T](xs: Conc[T], n: BigInt): Boolean = {
+    xs match {
+      case CC(l, r) =>
+        appendTakeDrop(l.toList, r.toList, n)
+      case _ => true
+    }
+  }.holds
+
+   @library
+  def append[T](xs: Conc[T], x: T): Conc[T] = {
+    require(xs.valid)
+    val ys = Single[T](x)
+    xs match {
+      case xs @ Append(_, _) =>
+        appendPriv(xs, ys)
+      case CC(_, _) =>
+        Append(xs, ys) //creating an append node
+      case Empty() =>
+        ys
+      case Single(_) =>
+        CC(xs, ys)
+    }
+  } ensuring (res => res.valid && //conctree invariants
+   res.toList == xs.toList ++ Cons(x, Nil[T]()) && //correctness
+   res.level <= xs.level + 1 &&
+   tmpl((a,b,c) => time <= a*numTrees(xs) - b*numTrees(res) + c) //time bound (worst case)
+   )
+
+  /**
+  * This is a private method and is not exposed to the
+  * clients of conc trees
+  */
+  @library
+  def appendPriv[T](xs: Append[T], ys: Conc[T]): Conc[T] = {
+    require(xs.valid && ys.valid &&
+      !ys.isEmpty && ys.isNormalized &&
+      xs.right.level >= ys.level)
+
+   if (xs.right.level > ys.level)
+     Append(xs, ys)
+   else {
+      val zs = CC(xs.right, ys)
+      xs.left match {
+        case l @ Append(_, _) =>
+          appendPriv(l, zs)
+        case l if l.level <= zs.level => //note: here < is not possible
+          CC(l, zs)
+        case l =>
+          Append(l, zs)
+      }
+    }
+  } ensuring (res => res.valid && //conc tree invariants
+   res.toList == xs.toList ++ ys.toList && //correctness invariants
+   res.level <= xs.level + 1 &&
+   tmpl((a,b,c) => time <= a*numTrees(xs) - b*numTrees(res) + c) && //time bound (worst case)
+   appendAssocInst2(xs, ys))
+
+  @library
+  def appendAssocInst2[T](xs: Conc[T], ys: Conc[T]): Boolean = {
+    xs match {
+      case CC(l, r) =>
+        appendAssoc(l.toList, r.toList, ys.toList)
+      case Append(l, r) =>
+        appendAssoc(l.toList, r.toList, ys.toList)
+      case _ => true
+    }
+  }.holds
+
+   @library
+  def numTrees[T](t: Conc[T]): BigInt = {
+    t match {
+      case Append(l, r) => numTrees(l) + 1
+      case _ => BigInt(1)
+    }
+  } ensuring (res => res >= 0)
+
+  @library
+  def normalize[T](t: Conc[T]): Conc[T] = {
+    require(t.valid)
+    t match {
+      case Append(l @ Append(_, _), r) =>
+        wrap(l, r)
+      case Append(l, r) =>
+        concatNormalized(l, r)
+      case _ => t
+    }
+  } ensuring (res => res.valid &&
+    res.isNormalized &&
+    res.toList == t.toList && //correctness
+    res.size == t.size && res.level <= t.level && //normalize preserves level and size
+    tmpl((a,b) => time <= a*t.level + b) //time bound (a little over approximate)
+    )
+
+       @library
+       def wrap[T](xs: Append[T], ys: Conc[T]): Conc[T] = {
+         require(xs.valid && ys.valid && ys.isNormalized &&
+           xs.right.level >= ys.level)
+         val nr = concatNormalized(xs.right, ys)
+         xs.left match {
+           case l @ Append(_, _) =>
+           wrap(l, nr)
+           case l =>
+           concatNormalized(l, nr)
+         }
+         } ensuring (res => res.valid &&
+           res.isNormalized &&
+   res.toList == xs.toList ++ ys.toList && //correctness
+   res.size == xs.size + ys.size && //other auxiliary properties
+   res.level <= xs.level &&
+   tmpl((a,b,c) => time <= a*xs.level - b*ys.level + c) && //time bound
+   appendAssocInst2(xs, ys)) //some lemma instantiations
+
+  /**
+  * A class that represents an operation on a concTree.
+  * opid - an integer that denotes the function that has to be performed e.g. append, insert, update ...
+  *     opid <= 0 => the operation is lookup
+  *       opid == 1 => the operation is update
+  *       opid == 2 => the operation is insert
+  *       opid == 3 => the operation is split
+  *        opid >= 4 => the operation is append
+  * index, x - denote the arguments the function given by opid
+  */
+  case class Operation[T](opid: BigInt, /*argument to the operations*/ index: BigInt /*for lookup, update, insert, split*/ ,
+   x: T /*for update, insert, append*/ )
+
+  /**
+  * Proving amortized running time of 'Append' when used ephimerally.
+  * ops- a arbitrary sequence of operations,
+  * noaps - number of append operations in the list
+  */
+  def performOperations[T](xs: Conc[T], ops: List[Operation[T]], noaps: BigInt): Conc[T] = {
+    require(xs.valid && noaps >= 0)
+    ops match {
+      case Cons(Operation(id, i, _), tail) if id <= 0 =>
+        //we need to perform a lookup operation, but do the operation only if
+        //preconditions hold
+        // val _ = if (0 <= i && i < xs.size)
+        //     lookup(xs, i)
+        //   else BigInt(0)
+            performOperations(xs, tail, noaps) //returns the time taken by appends in the remaining operations
+
+      case Cons(Operation(id, i, x), tail) if id == 1 =>
+        val newt = if (0 <= i && i < xs.size)
+            update(xs, i, x)
+          else xs
+            //note that only the return value is used by the subsequent operations (emphimeral use)
+            performOperations(newt, tail, noaps)
+
+      case Cons(Operation(id, i, x), tail) if id == 2 =>
+        val newt = if (0 <= i && i <= xs.size)
+            insert(normalize(xs), i, x)
+          else xs
+            performOperations(newt, tail, noaps)
+
+      case Cons(Operation(id, n, _), tail) if id == 3 =>
+        //use the larger tree to perform the remaining operations
+        val (newl, newr) = split(normalize(xs), n)
+        val newt = if (newl.size >= newr.size) newl else newr
+        performOperations(newt, tail, noaps)
+
+      case Cons(Operation(id, _, x), tail) if noaps > 0 =>
+        //here, we need to perform append operation
+        val newt = append(xs, x)
+        val r = performOperations(newt, tail, noaps - 1)
+        r //time taken by this append and those that follow it
+
+      case _ =>
+        xs
+    }
+  } ensuring (res => tmpl((a, b) => time <= a*noaps + b*numTrees(xs)))
+//res._2 <= noaps + 2*nops*(xs.level + res._1.level)+ numTrees(xs)
+}
diff --git a/testcases/orb-testcases/timing/ConcatVariations.scala b/testcases/orb-testcases/timing/ConcatVariations.scala
new file mode 100644
index 000000000..a94fb418a
--- /dev/null
+++ b/testcases/orb-testcases/timing/ConcatVariations.scala
@@ -0,0 +1,42 @@
+import leon.invariant._
+import leon.instrumentation._
+
+
+object ConcatVariations {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def genL(n: BigInt): List = {
+    require(n >= 0)
+    if (n == 0) Nil()
+    else
+      Cons(n, genL(n - 1))
+  } ensuring (res => size(res) == n && tmpl((a,b) => time <= a*n + b))
+
+  def append(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => Cons(x, append(xs, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => time <= a*size(l1) + b))
+
+  def f_good(m: BigInt, n: BigInt): List = {
+    require(0 <= m && 0 <= n)
+    if (m == 0) Nil()
+    else append(genL(n), f_good(m - 1, n))
+
+  } ensuring(res => size(res) == n*m && tmpl((a,b,c,d) => time <= a*(n*m) + b*n + c*m +d))
+
+  def f_worst(m: BigInt, n: BigInt): List = {
+    require(0 <= m && 0 <= n)
+
+    if (m == 0) Nil()
+    else append(f_worst(m - 1, n), genL(n))
+
+  } ensuring(res => size(res) == n*m && tmpl((a,c,d,e,f) => time <= a*((n*m)*m)+c*(n*m)+d*n+e*m+f))
+}
diff --git a/testcases/orb-testcases/timing/ConstantPropagation.scala b/testcases/orb-testcases/timing/ConstantPropagation.scala
new file mode 100644
index 000000000..76af84834
--- /dev/null
+++ b/testcases/orb-testcases/timing/ConstantPropagation.scala
@@ -0,0 +1,290 @@
+import leon.lang._
+import leon.annotation._
+import leon.collection._
+import leon._
+import leon.invariant._
+import leon.instrumentation._
+
+object IntLattice {
+  abstract class Element
+  case class Bot() extends Element
+  case class Top() extends Element
+  case class BigIntVal(x: BigInt) extends Element
+
+  def height: BigInt = {
+    /**
+     * A number that depends on the lattice definition.
+     * In simplest case it has height 3 (_|_ (bot) <= BigInts <= T (top))
+     */
+    3
+  }
+
+  def join(oldVal: Element, newVal: Element) = (oldVal, newVal) match {
+    case (Bot(), any) => any // bot is the identity for join
+    case (any, Bot()) => any
+    case (Top(), _) => Top() // top joined with anything is top
+    case (_, Top()) => Top()
+    case (BigIntVal(x), BigIntVal(y)) if (x == y) => BigIntVal(y)
+    case _ =>
+      //here old and new vals are different BigIntegers
+      Top()
+  }
+}
+
+object LatticeOps {
+  import IntLattice._
+
+  def add(a: Element, b: Element): Element = {
+    (a, b) match {
+      case (Bot(), _) => Bot()
+      case (_, Bot()) => Bot()
+      case (Top(), _) => Top()
+      case (_, Top()) => Top()
+      case (BigIntVal(x), BigIntVal(y)) => BigIntVal(x + y)
+    }
+  }
+
+  def multiply(a: Element, b: Element): Element = {
+    (a, b) match {
+      case (_, BigIntVal(x)) if x == 0 => BigIntVal(0)
+      case (BigIntVal(x), _) if x == 0 => BigIntVal(0)
+      case (Bot(), _) => Bot()
+      case (_, Bot()) => Bot()
+      case (Top(), _) => Top()
+      case (_, Top()) => Top()
+      case (BigIntVal(x), BigIntVal(y)) => BigIntVal(x * y)
+    }
+  }
+}
+
+object ConstantPropagation {
+  import IntLattice._
+  import LatticeOps._
+
+  abstract class Expr
+  case class Times(lhs: Expr, rhs: Expr) extends Expr
+  case class Plus(lhs: Expr, rhs: Expr) extends Expr
+  case class BigIntLiteral(v: BigInt) extends Expr
+  case class FunctionCall(calleeId: BigInt, args: List[Expr]) extends Expr
+  case class IfThenElse(cond: Expr, thenExpr: Expr, elseExpr: Expr) extends Expr
+  case class Identifier(id: BigInt) extends Expr
+
+  /**
+   * Definition of a function AST
+   */
+  case class Function(id: BigInt, params: List[Expr], body: Expr)
+
+  /**
+   * Assuming that the functions are ordered from callee to
+   * caller and there is no mutual recursion
+   */
+  case class Program(funcs: List[Function])
+
+  def size(l: List[Function]): BigInt = {
+    l match {
+      case Cons(_, t) => 1 + size(t)
+      case Nil() => 0
+    }
+  }
+
+  def sizeExprList(exprs: List[Expr]): BigInt = {
+    exprs match {
+      case Nil() => 0
+      case Cons(currExpr, otherExprs) => sizeExpr(currExpr) + sizeExprList(otherExprs)
+    }
+  }
+
+  def sizeExpr(e: Expr): BigInt = {
+    e match {
+      case Plus(l, r) => 1 + sizeExpr(l) + sizeExpr(r)
+      case Times(l, r) => 1 + sizeExpr(l) + sizeExpr(r)
+      case FunctionCall(c, args) => {
+        1 + sizeExprList(args)
+      }
+      case IfThenElse(c, th, el) =>
+        1 + sizeExpr(c) + sizeExpr(th) + sizeExpr(el)
+      case _ => 1
+    }
+  }
+
+  def sizeFuncList(funcs: List[Function]): BigInt = {
+    funcs match {
+      case Nil() => 0
+      case Cons(currFunc, otherFuncs) =>
+        1 + sizeExpr(currFunc.body) + sizeFuncList(otherFuncs)
+    }
+  }
+
+  def initToBot(l: List[Function]): List[(BigInt /*function id*/ , Element)] = {
+    l match {
+      case Nil() => Nil[(BigInt /*function id*/ , Element)]()
+      case Cons(fun, tail) => Cons((fun.id, Bot()), initToBot(tail))
+    }
+  } ensuring (_ => time <= ? * size(l) + ?)
+
+  def foldConstants(p: Program): Program = {
+    val initVals = initToBot(p.funcs)
+    val fvals = computeSummaries(p, initToBot(p.funcs), height)
+    val newfuns = transformFuns(p.funcs, fvals)
+    Program(newfuns)
+  } ensuring(_ => time <= ? * (sizeFuncList(p.funcs)*height) + ? * height + ? * size(p.funcs) + ?)
+
+  /**
+   * The initVals is the initial values for the
+   * values of the functions
+   */
+  def computeSummaries(p: Program, initVals: List[(BigInt /*function id*/ , Element)], noIters: BigInt): List[(BigInt /*function id*/ , Element)] = {
+    require(noIters >= 0)
+    if (noIters <= 0) {
+      initVals
+    } else
+      computeSummaries(p, analyzeFuns(p.funcs, initVals, initVals), noIters - 1)
+  } ensuring(_ => time <= ? * (sizeFuncList(p.funcs)*noIters) + ? * noIters + ?)
+
+  /**
+   * Initial fvals and oldVals are the same
+   * but as the function progresses, fvals will only have the olds values
+   * of the functions that are yet to be processed, whereas oldVals will remain the same.
+   */
+  def analyzeFuns(funcs: List[Function], fvals: List[(BigInt, Element)], oldVals: List[(BigInt, Element)]): List[(BigInt, Element)] = {
+    (funcs, fvals) match {
+      case (Cons(f, otherFuns), Cons((fid, fval), otherVals)) =>
+        val newval = analyzeFunction(f, oldVals)
+        val approxVal = join(fval, newval) //creates an approximation of newVal to ensure convergence
+        Cons((fid, approxVal), analyzeFuns (otherFuns, otherVals, oldVals))
+      case _ =>
+        Nil[(BigInt, Element)]() //this also handles precondition violations e.g. lists aren't of same size etc.
+    }
+  } ensuring (_ => time <= ? * sizeFuncList(funcs) + ?)
+
+  @library
+  def getFunctionVal(funcId: BigInt, funcVals: List[(BigInt, Element)]): Element = {
+    funcVals match {
+      case Nil() => Bot()
+      case Cons((currFuncId, currFuncVal), otherFuncVals) if (currFuncId == funcId) => currFuncVal
+      case Cons(_, otherFuncVals) =>
+        getFunctionVal(funcId, otherFuncVals)
+    }
+  } ensuring (_ => time <= 1)
+
+
+  def analyzeExprList(l: List[Expr], funcVals: List[(BigInt, Element)]): List[Element] = {
+    l match {
+      case Nil() => Nil[Element]()
+      case Cons(expr, otherExprs) => Cons(analyzeExpr(expr, funcVals), analyzeExprList(otherExprs, funcVals))
+    }
+  } ensuring (_ => time <= ? * sizeExprList(l) + ?)
+
+  /**
+   * Returns the value of the expression when "Abstractly Interpreted"
+   * using the lattice.
+   */
+  def analyzeExpr(e: Expr, funcVals: List[(BigInt, Element)]): Element = {
+    e match {
+      case Times(lhs: Expr, rhs: Expr) => {
+        val lval = analyzeExpr(lhs, funcVals)
+        val rval = analyzeExpr(rhs, funcVals)
+        multiply(lval, rval)
+      }
+      case Plus(lhs: Expr, rhs: Expr) => {
+        val lval = analyzeExpr(lhs, funcVals)
+        val rval = analyzeExpr(rhs, funcVals)
+        add(lval, rval)
+      }
+      case FunctionCall(id, args: List[Expr]) => {
+        getFunctionVal(id, funcVals)
+      }
+      case IfThenElse(c, th, el) => {
+        //analyze then and else branches and join their values
+        //TODO: this can be made more precise e.g. if 'c' is
+        //a non-zero value it can only execute the then branch.
+        val v1 = analyzeExpr(th, funcVals)
+        val v2 = analyzeExpr(el, funcVals)
+        join(v1, v2)
+      }
+      case lit @ BigIntLiteral(v) =>
+        BigIntVal(v)
+
+      case Identifier(_) => Bot()
+    }
+  } ensuring (_ => time <= ? * sizeExpr(e) + ?)
+
+
+  def analyzeFunction(f: Function, oldVals: List[(BigInt, Element)]): Element = {
+    // traverse the body of the function and simplify constants
+    // for function calls assume the value given by oldVals
+    // also for if-then-else statments, take a join of the values along if and else branches
+    // assume that bot op any = bot and top op any = top (but this can be made more precise).
+    analyzeExpr(f.body, oldVals)
+  } ensuring (_ => time <= ? * sizeExpr(f.body) + ?)
+
+
+  def transformExprList(l: List[Expr], funcVals: List[(BigInt, Element)]): List[Expr] = {
+    l match {
+      case Nil() => Nil[Expr]()
+      case Cons(expr, otherExprs) => Cons(transformExpr(expr, funcVals),
+        transformExprList(otherExprs, funcVals))
+    }
+  } ensuring (_ => time <= ? * sizeExprList(l) + ?)
+
+  /**
+   * Returns the folded expression
+   */
+  def transformExpr(e: Expr, funcVals: List[(BigInt, Element)]): Expr = {
+    e match {
+      case Times(lhs: Expr, rhs: Expr) => {
+        val foldedLHS = transformExpr(lhs, funcVals)
+        val foldedRHS = transformExpr(rhs, funcVals)
+        (foldedLHS, foldedRHS) match {
+          case (BigIntLiteral(x), BigIntLiteral(y)) =>
+            BigIntLiteral(x * y)
+          case _ =>
+            Times(foldedLHS, foldedRHS)
+        }
+      }
+      case Plus(lhs: Expr, rhs: Expr) => {
+        val foldedLHS = transformExpr(lhs, funcVals)
+        val foldedRHS = transformExpr(rhs, funcVals)
+        (foldedLHS, foldedRHS) match {
+          case (BigIntLiteral(x), BigIntLiteral(y)) =>
+            BigIntLiteral(x + y)
+          case _ =>
+            Plus(foldedLHS, foldedRHS)
+        }
+      }
+      case FunctionCall(calleeid, args: List[Expr]) => {
+        getFunctionVal(calleeid, funcVals) match {
+          case BigIntVal(x) =>
+            BigIntLiteral(x)
+          case _ =>
+            val foldedArgs = transformExprList(args, funcVals)
+            FunctionCall(calleeid, foldedArgs)
+        }
+      }
+      case IfThenElse(c, th, el) => {
+        val foldedCond = transformExpr(c, funcVals)
+        val foldedTh = transformExpr(th, funcVals)
+        val foldedEl = transformExpr(el, funcVals)
+        foldedCond match {
+          case BigIntLiteral(x) => {
+            if (x != 0) foldedTh
+            else foldedEl
+          }
+          case _ => IfThenElse(foldedCond, foldedTh, foldedEl)
+        }
+      }
+      case _ => e
+    }
+  } ensuring (_ => time <= ? * sizeExpr(e) + ?)
+
+
+  def transformFuns(funcs: List[Function], fvals: List[(BigInt, Element)]): List[Function] = {
+    funcs match {
+      case Cons(f, otherFuns) =>
+        val newfun = Function(f.id, f.params, transformExpr(f.body, fvals))
+        Cons(newfun, transformFuns(otherFuns, fvals))
+      case _ =>
+        Nil[Function]()
+    }
+  } ensuring (_ => time <= ? * sizeFuncList(funcs) + ?)
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/timing/Folds.scala b/testcases/orb-testcases/timing/Folds.scala
new file mode 100644
index 000000000..2dac7e266
--- /dev/null
+++ b/testcases/orb-testcases/timing/Folds.scala
@@ -0,0 +1,77 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object TreeMaps {
+
+  sealed abstract class Tree
+  case class Node(left: Tree, value: BigInt, right: Tree) extends Tree
+  case class Leaf() extends Tree
+
+  def size(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => size(l) + size(r) + 1
+    }
+  }
+
+  def parallelSearch(elem : BigInt, t : Tree) : Boolean = {
+    t match {
+      case Node(l, x, r) =>
+        if(x == elem) true
+        else {
+          val r1 = parallelSearch(elem, r)
+          val r2 = parallelSearch(elem, l)
+          if(r1 || r2) true
+          else false
+        }
+      case Leaf() => false
+    }
+  } ensuring(res => true && tmpl((a,b) => time <= a*size(t) + b))
+
+
+  def squareMap(t : Tree) : Tree = {
+    t match {
+      case Node(l, x, r) =>
+        val nl = squareMap(l)
+        val nr = squareMap(r)
+        Node(nl, x*x, nr)
+      case _ => t
+    }
+  } ensuring (res => true && tmpl((a,b) => time <= a*size(t) + b))
+
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def fact(n : BigInt) : BigInt = {
+    require(n >= 0)
+
+    if(n == 1 || n == 0) BigInt(1)
+    else n * fact(n-1)
+
+  } ensuring(res => true && tmpl((a,b) => time <= a*n + b))
+
+  def descending(l: List, k: BigInt) : Boolean = {
+    l match {
+      case Nil() => true
+      case Cons(x, t) => x > 0 && x <= k && descending(t, x-1)
+    }
+  }
+
+  def factMap(l: List, k: BigInt): List = {
+    require(descending(l, k) && k >= 0)
+
+   l match {
+    case Nil() => Nil()
+    case Cons(x, t) =>  {
+      val f = fact(x)
+      Cons(f, factMap(t, x-1))
+    }
+
+  }} ensuring(res => true && tmpl((a,b) => time <= a*(k*k) + b))
+}
\ No newline at end of file
diff --git a/testcases/orb-testcases/timing/ForElimination.scala b/testcases/orb-testcases/timing/ForElimination.scala
new file mode 100644
index 000000000..c76da1507
--- /dev/null
+++ b/testcases/orb-testcases/timing/ForElimination.scala
@@ -0,0 +1,102 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object ForElimination {
+
+  sealed abstract class List
+  case class Nil() extends List
+  case class Cons(head: Statement, tail: List) extends List
+
+  sealed abstract class Statement
+  case class Print(msg: BigInt, varID: BigInt) extends Statement
+  case class Assign(varID: BigInt, expr: Expression) extends Statement
+  case class Skip() extends Statement
+  case class Block(body: List) extends Statement
+  case class IfThenElse(expr: Expression, thenExpr: Statement, elseExpr: Statement) extends Statement
+  case class While(expr: Expression, body: Statement) extends Statement
+  case class For(init: Statement, expr: Expression, step: Statement, body: Statement) extends Statement
+
+  sealed abstract class Expression
+  case class Var(varID: BigInt) extends Expression
+  case class IntLiteral(value: BigInt) extends Expression
+  case class Plus(lhs: Expression, rhs: Expression) extends Expression
+  case class Minus(lhs: Expression, rhs: Expression) extends Expression
+  case class Times(lhs: Expression, rhs: Expression) extends Expression
+  case class Division(lhs: Expression, rhs: Expression) extends Expression
+  case class Equals(lhs: Expression, rhs: Expression) extends Expression
+  case class LessThan(lhs: Expression, rhs: Expression) extends Expression
+  case class And(lhs: Expression, rhs: Expression) extends Expression
+  case class Or(lhs: Expression, rhs: Expression) extends Expression
+  case class Not(expr: Expression) extends Expression
+
+  def sizeStat(st: Statement) : BigInt =  st match {
+    case Block(l) => sizeList(l) + 1
+    case IfThenElse(c,th,el) => sizeStat(th) + sizeStat(el) + 1
+    case While(c,b) => sizeStat(b) + 1
+    case For(init,cond,step,body) => sizeStat(init) + sizeStat(step) + sizeStat(body)
+    case other => 1
+  }
+
+  def sizeList(l: List) : BigInt = l match {
+    case Cons(h,t) => sizeStat(h) + sizeList(t)
+    case Nil() => 0
+  }
+
+  def isForFree(stat: Statement): Boolean = (stat match {
+    case Block(body) => isForFreeList(body)
+    case IfThenElse(_, thenExpr, elseExpr) => isForFree(thenExpr) && isForFree(elseExpr)
+    case While(_, body) => isForFree(body)
+    case For(_,_,_,_) => false
+    case _ => true
+  })  ensuring(res => true && tmpl((a,b) => time <= a*sizeStat(stat) + b))
+
+  def isForFreeList(l: List): Boolean = (l match {
+    case Nil() => true
+    case Cons(x, xs) => isForFree(x) && isForFreeList(xs)
+  })  ensuring(res => true && tmpl((a,b) => time <= a*sizeList(l) + b))
+
+  def forLoopsWellFormedList(l: List): Boolean = (l match {
+    case Nil() => true
+    case Cons(x, xs) => forLoopsWellFormed(x) && forLoopsWellFormedList(xs)
+  }) ensuring(res => true && tmpl((a,b) => time <= a*sizeList(l) + b))
+
+  def forLoopsWellFormed(stat: Statement): Boolean = (stat match {
+    case Block(body) => forLoopsWellFormedList(body)
+    case IfThenElse(_, thenExpr, elseExpr) => forLoopsWellFormed(thenExpr) && forLoopsWellFormed(elseExpr)
+    case While(_, body) => forLoopsWellFormed(body)
+    case For(init, _, step, body) => isForFree(init) && isForFree(step) && forLoopsWellFormed(body)
+    case _ => true
+  }) ensuring(res => true && tmpl((a,b) => time <= a*sizeStat(stat) + b))
+
+  def eliminateWhileLoopsList(l: List): List = {
+    l match {
+      case Nil() => Nil()
+      case Cons(x, xs) => Cons(eliminateWhileLoops(x), eliminateWhileLoopsList(xs))
+    }
+  } ensuring(res => true && tmpl((a,b) => time <= a*sizeList(l) + b))
+
+  def eliminateWhileLoops(stat: Statement): Statement = (stat match {
+    case Block(body) => Block(eliminateWhileLoopsList(body))
+    case IfThenElse(expr, thenExpr, elseExpr) => IfThenElse(expr, eliminateWhileLoops(thenExpr), eliminateWhileLoops(elseExpr))
+    case While(expr, body) => For(Skip(), expr, Skip(), eliminateWhileLoops(body))
+    case For(init, expr, step, body) => For(eliminateWhileLoops(init), expr, eliminateWhileLoops(step), eliminateWhileLoops(body))
+    case other => other
+  }) ensuring(res => true && tmpl((a,b) => time <= a*sizeStat(stat) + b))
+
+  def eliminateForLoopsList(l: List): List = {
+    l match {
+      case Nil() => Nil()
+      case Cons(x, xs) => Cons(eliminateForLoops(x), eliminateForLoopsList(xs))
+    }
+  } ensuring(res => true && tmpl((a,b) => time <= a*sizeList(l) + b))
+
+  def eliminateForLoops(stat: Statement): Statement = {
+    stat match {
+      case Block(body) => Block(eliminateForLoopsList(body))
+      case IfThenElse(expr, thenExpr, elseExpr) => IfThenElse(expr, eliminateForLoops(thenExpr), eliminateForLoops(elseExpr))
+      case While(expr, body) => While(expr, eliminateForLoops(body))
+      case For(init, expr, step, body) => Block(Cons(eliminateForLoops(init), Cons(While(expr, Block(Cons(eliminateForLoops(body), Cons(eliminateForLoops(step), Nil())))), Nil())))
+      case other => other
+    }
+  } ensuring(res => true && tmpl((a,b) => time <= a*sizeStat(stat) + b))
+}
diff --git a/testcases/orb-testcases/timing/InsertionSort.scala b/testcases/orb-testcases/timing/InsertionSort.scala
new file mode 100644
index 000000000..8fd79a2e8
--- /dev/null
+++ b/testcases/orb-testcases/timing/InsertionSort.scala
@@ -0,0 +1,26 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object InsertionSort {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail:List) extends List
+  case class Nil() extends List
+
+  def size(l : List) : BigInt = (l match {
+    case Cons(_, xs) => 1 + size(xs)
+    case _ => 0
+  })
+
+  def sortedIns(e: BigInt, l: List): List = {
+    l match {
+      case Cons(x,xs) => if (x <= e) Cons(x,sortedIns(e, xs)) else Cons(e, l)
+      case _ => Cons(e,Nil())
+    }
+  } ensuring(res => size(res) == size(l) + 1 && tmpl((a,b) => time <= a*size(l) +b && depth <=  a*size(l) +b))
+
+  def sort(l: List): List = (l match {
+    case Cons(x,xs) => sortedIns(x, sort(xs))
+    case _ => Nil()
+
+  }) ensuring(res => size(res) == size(l) && tmpl((a,b) => time <= a*(size(l)*size(l)) +b && rec <= a*size(l) + b))
+}
diff --git a/testcases/orb-testcases/timing/LeftistHeap.scala b/testcases/orb-testcases/timing/LeftistHeap.scala
new file mode 100644
index 000000000..2d3cd389a
--- /dev/null
+++ b/testcases/orb-testcases/timing/LeftistHeap.scala
@@ -0,0 +1,82 @@
+import leon.invariant._
+import leon.instrumentation._
+import leon.annotation._
+
+object LeftistHeap {
+  sealed abstract class Heap
+  case class Leaf() extends Heap
+  case class Node(rk : BigInt, value: BigInt, left: Heap, right: Heap) extends Heap
+
+  private def rightHeight(h: Heap) : BigInt = h match {
+    case Leaf() => 0
+    case Node(_,_,_,r) => rightHeight(r) + 1
+  }
+
+  private def rank(h: Heap) : BigInt = h match {
+    case Leaf() => 0
+    case Node(rk,_,_,_) => rk
+  }
+
+  private def hasLeftistProperty(h: Heap) : Boolean = (h match {
+    case Leaf() => true
+    case Node(_,_,l,r) => hasLeftistProperty(l) && hasLeftistProperty(r) && rightHeight(l) >= rightHeight(r) && (rank(h) == rightHeight(h))
+  })
+
+  @monotonic
+  def twopower(x: BigInt) : BigInt = {
+    require(x >= 0)
+    if(x < 1) 1
+    else
+      2* twopower(x - 1)
+  }
+
+  def size(t: Heap): BigInt = {
+    require(hasLeftistProperty(t))
+    (t match {
+      case Leaf() => BigInt(0)
+      case Node(_,v, l, r) => size(l) + 1 + size(r)
+    })
+  } ensuring (res => true && tmpl((a,b) => twopower(rightHeight(t)) <= a*res + b))
+
+  def leftRightHeight(h: Heap) : BigInt = {h match {
+    case Leaf() => 0
+    case Node(_,_,l,r) => rightHeight(l)
+  }}
+
+  def removeMax(h: Heap) : Heap = {
+    require(hasLeftistProperty(h))
+    h match {
+      case Node(_,_,l,r) => merge(l, r)
+      case l @ Leaf() => l
+    }
+  } ensuring(res => true && tmpl((a,b) => time <= a*leftRightHeight(h) + b))
+
+  private def merge(h1: Heap, h2: Heap) : Heap = {
+    require(hasLeftistProperty(h1) && hasLeftistProperty(h2))
+    h1 match {
+      case Leaf() => h2
+      case Node(_, v1, l1, r1) => h2 match {
+        case Leaf() => h1
+        case Node(_, v2, l2, r2) =>
+          if(v1 > v2)
+            makeT(v1, l1, merge(r1, h2))
+          else
+            makeT(v2, l2, merge(h1, r2))
+      }
+    }
+  } ensuring(res => true && tmpl((a,b,c) => time <= a*rightHeight(h1) + b*rightHeight(h2) + c))
+
+  private def makeT(value: BigInt, left: Heap, right: Heap) : Heap = {
+    if(rank(left) >= rank(right))
+      Node(rank(right) + 1, value, left, right)
+    else
+      Node(rank(left) + 1, value, right, left)
+  }
+
+  def insert(element: BigInt, heap: Heap) : Heap = {
+   require(hasLeftistProperty(heap))
+
+    merge(Node(1, element, Leaf(), Leaf()), heap)
+
+  } ensuring(res => true && tmpl((a,b,c) => time <= a*rightHeight(heap) + c))
+}
diff --git a/testcases/orb-testcases/timing/ListOperations.scala b/testcases/orb-testcases/timing/ListOperations.scala
new file mode 100644
index 000000000..444029464
--- /dev/null
+++ b/testcases/orb-testcases/timing/ListOperations.scala
@@ -0,0 +1,61 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object ListOperations {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  def append(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => Cons(x, append(xs, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => time <= a*size(l1) + b))
+
+  def reverseRec(l1: List, l2: List): List = (l1 match {
+    case Nil() => l2
+    case Cons(x, xs) => reverseRec(xs, Cons(x, l2))
+
+  }) ensuring (res =>  size(l1) + size(l2) == size(res) && tmpl((a,b) => time <= a*size(l1) + b))
+  //ensuring (res =>  size(l1) + size(l2) == size(res) && time <= 4*size(l1) + 1)
+
+  def reverse(l: List): List = {
+    reverseRec(l, Nil())
+
+  } ensuring (res => size(l) == size(res) && tmpl((a,b) => time <= a*size(l) + b))
+
+  def reverse2(l: List): List = {
+    l match {
+      case Nil() => l
+      case Cons(hd, tl) => append(reverse2(tl), Cons(hd, Nil()))
+    }
+  } ensuring (res => size(res) == size(l) && tmpl((a,b) => time <= a*(size(l)*size(l)) + b))
+
+  def remove(elem: BigInt, l: List): List = {
+    l match {
+      case Nil() => Nil()
+      case Cons(hd, tl) => if (hd == elem) remove(elem, tl) else Cons(hd, remove(elem, tl))
+    }
+  } ensuring (res => size(l) >= size(res) && tmpl((a,b) => time <= a*size(l) + b))
+
+  def contains(list: List, elem: BigInt): Boolean = (list match {
+    case Nil() => false
+    case Cons(x, xs) => x == elem || contains(xs, elem)
+
+  }) ensuring (res => true && tmpl((a,b) => time <= a*size(list) + b))
+
+  def distinct(l: List): List = (
+    l match {
+      case Nil() => Nil()
+      case Cons(x, xs) => {
+        val newl = distinct(xs)
+        if (contains(newl, x)) newl
+        else Cons(x, newl)
+      }
+   }) ensuring (res => size(l) >= size(res) && tmpl((a,b) => time <= a*(size(l)*size(l)) + b))
+}
diff --git a/testcases/orb-testcases/timing/MergeSort.scala b/testcases/orb-testcases/timing/MergeSort.scala
new file mode 100644
index 000000000..aa900aada
--- /dev/null
+++ b/testcases/orb-testcases/timing/MergeSort.scala
@@ -0,0 +1,76 @@
+import leon.invariant._
+import leon.instrumentation._
+
+import leon.annotation._
+
+object MergeSort {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+
+  //case class Pair(fst:List,snd:List)
+
+  @monotonic
+  def log(x: BigInt) : BigInt = {
+    require(x >= 0)
+    if(x <= 1) 0
+    else {
+      val k = x/2
+      1 + log(x - k)
+    }
+  } ensuring(res => true && tmpl((a) => res >= 0))
+
+  def size(list:List): BigInt = {list match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }} ensuring(res => true && tmpl((a) => res >= 0))
+
+  def length(l:List): BigInt = {
+    l match {
+      case Nil() => 0
+      case Cons(x,xs) => 1 + length(xs)
+    }
+  } ensuring(res => res == size(l) && tmpl((a,b) => time <= a*size(l) + b))
+
+  def split(l:List,n:BigInt): (List,List) = {
+    require(n >= 0 && n <= size(l))
+    if (n <= 0) (Nil(),l)
+    else
+	l match {
+      case Nil() => (Nil(),l)
+      case Cons(x,xs) => {
+        if(n == 1) (Cons(x,Nil()), xs)
+        else {
+          val (fst,snd) = split(xs, n-1)
+          (Cons(x,fst), snd)
+        }
+      }
+	}
+  } ensuring(res => size(res._2) == size(l) - n && size(res._1) == n && tmpl((a,b) => time <= a*n +b))
+
+  def merge(aList:List, bList:List):List = (bList match {
+    case Nil() => aList
+    case Cons(x,xs) =>
+    	 aList match {
+   	       case Nil() => bList
+   	       case Cons(y,ys) =>
+    	        if (y < x)
+    		   Cons(y,merge(ys, bList))
+     		else
+		   Cons(x,merge(aList, xs))
+   	 }
+  }) ensuring(res => size(aList)+size(bList) == size(res) && tmpl((a,b,c) => time <= a*size(aList) + b*size(bList) + c))
+
+  def mergeSort(list:List):List = {
+    list match {
+      case Cons(x,Nil()) => list
+      case Cons(_,Cons(_,_)) =>
+         val lby2 = length(list)/2
+    	 val (fst,snd) = split(list,lby2)
+      	 //merge(mergeSort(fst,l), mergeSort(snd,len - l))
+    	 merge(mergeSort(fst),mergeSort(snd))
+
+      case _ => list
+
+  }} ensuring(res => true && tmpl((a,b) => time <= a*(size(list)*log(size(list))) + b))
+}
diff --git a/testcases/orb-testcases/timing/PropositionalLogic.scala b/testcases/orb-testcases/timing/PropositionalLogic.scala
new file mode 100644
index 000000000..22dfdcdec
--- /dev/null
+++ b/testcases/orb-testcases/timing/PropositionalLogic.scala
@@ -0,0 +1,115 @@
+import scala.collection.immutable.Set
+import leon.invariant._
+import leon.instrumentation._
+
+object PropositionalLogic {
+
+  sealed abstract class Formula
+  case class And(lhs: Formula, rhs: Formula) extends Formula
+  case class Or(lhs: Formula, rhs: Formula) extends Formula
+  case class Implies(lhs: Formula, rhs: Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Literal(id: BigInt) extends Formula
+  case class True() extends Formula
+  case class False() extends Formula
+
+  case class Pair(f: Formula, b: Boolean)
+
+  sealed abstract class List
+  case class Cons(x: Pair, xs: List) extends List
+  case class Nil() extends List
+
+  def size(f : Formula) : BigInt = (f match {
+    case And(lhs, rhs) => size(lhs) + size(rhs) + 1
+    case Or(lhs, rhs) => size(lhs) + size(rhs) + 1
+    case Implies(lhs, rhs) => size(lhs) + size(rhs) + 1
+    case Not(f) => size(f) + 1
+    case _ => 1
+  })
+
+  def removeImplies(f: Formula): Formula = (f match {
+    case And(lhs, rhs) => And(removeImplies(lhs), removeImplies(rhs))
+    case Or(lhs, rhs) => Or(removeImplies(lhs), removeImplies(rhs))
+    case Implies(lhs, rhs) => Or(Not(removeImplies(lhs)),removeImplies(rhs))
+    case Not(f) => Not(removeImplies(f))
+    case _ => f
+
+  }) ensuring(_ => time <= ? * size(f) + ?)
+
+  def nnf(formula: Formula): Formula = (formula match {
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs) => Or(nnf(lhs), nnf(rhs))
+    case Implies(lhs, rhs) => Implies(nnf(lhs), nnf(rhs))
+    case Not(And(lhs, rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs, rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Implies(lhs, rhs)) => And(nnf(lhs), nnf(Not(rhs)))
+    case Not(Not(f)) => nnf(f)
+    case Not(Literal(_)) => formula
+    case Literal(_) => formula
+    case Not(True()) => False()
+    case Not(False()) => True()
+    case _ => formula
+  }) ensuring(_ => time <= ? * size(formula) + ?)
+
+  def isNNF(f: Formula): Boolean = { f match {
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Implies(lhs, rhs) => false
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case _ => true
+  }} ensuring(_ => time <= ? * size(f) + ?)
+
+  def simplify(f: Formula): Formula = (f match {
+    case And(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs or rhs is false, return false
+      //if lhs is true return rhs
+      //if rhs is true return lhs
+      (sl,sr) match {
+        case (False(), _) => False()
+        case (_, False()) => False()
+        case (True(), _) => sr
+        case (_, True()) => sl
+        case _ => And(sl, sr)
+      }
+    }
+    case Or(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs or rhs is true, return true
+      //if lhs is false return rhs
+      //if rhs is false return lhs
+      (sl,sr) match {
+        case (True(), _) => True()
+        case (_, True()) => True()
+        case (False(), _) => sr
+        case (_, False()) => sl
+        case _ => Or(sl, sr)
+      }
+    }
+    case Implies(lhs, rhs) => {
+      val sl = simplify(lhs)
+      val sr = simplify(rhs)
+
+      //if lhs is false return true
+      //if rhs is true return true
+      //if lhs is true return rhs
+      //if rhs is false return Not(rhs)
+      (sl,sr) match {
+        case (False(), _) => True()
+        case (_, True()) => True()
+        case (True(), _) => sr
+        case (_, False()) => Not(sl)
+        case _ => Implies(sl, sr)
+      }
+    }
+    case Not(True()) => False()
+    case Not(False()) => True()
+    case _ => f
+
+  }) ensuring(_ => time <= ? *size(f) + ?)
+}
diff --git a/testcases/orb-testcases/timing/QuickSort.scala b/testcases/orb-testcases/timing/QuickSort.scala
new file mode 100644
index 000000000..2f4101dc8
--- /dev/null
+++ b/testcases/orb-testcases/timing/QuickSort.scala
@@ -0,0 +1,43 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object QuickSort {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+
+  def size(l:List): BigInt = {l match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }}
+
+  case class Triple(fst:List,snd:List, trd: List)
+
+  def append(aList:List,bList:List): List = {aList match {
+    case Nil() => bList
+    case Cons(x, xs) => Cons(x,append(xs,bList))
+  }} ensuring(res => size(res) == size(aList) + size(bList) && tmpl((a,b) => time <= a*size(aList) +b))
+
+  def partition(n:BigInt,l:List) : Triple = (l match {
+    case Nil() => Triple(Nil(), Nil(), Nil())
+    case Cons(x,xs) => {
+      val t = partition(n,xs)
+      if (n < x) Triple(t.fst, t.snd, Cons(x,t.trd))
+      else if(n == x) Triple(t.fst, Cons(x,t.snd), t.trd)
+      else Triple(Cons(x,t.fst), t.snd, t.trd)
+    }
+ }) ensuring(res => (size(l) == size(res.fst) + size(res.snd) + size(res.trd)) && tmpl((a,b) => time <= a*size(l) +b))
+
+ //Unable to prove n^2  upper bound :-(
+  def quickSort(l:List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,Nil()) => l
+    case Cons(x,xs) => {
+      val t = partition(x, xs)
+      append(append(quickSort(t.fst), Cons(x, t.snd)), quickSort(t.trd))
+    }
+    case _ => l
+  })
+  //ensuring(res => size(l) == size(res) && tmpl((a,b,c,d) => time <= a*(size(l)*size(l)) + c*size(l) + d))
+}
+
diff --git a/testcases/orb-testcases/timing/RedBlackTree.scala b/testcases/orb-testcases/timing/RedBlackTree.scala
new file mode 100644
index 000000000..7ad0a1088
--- /dev/null
+++ b/testcases/orb-testcases/timing/RedBlackTree.scala
@@ -0,0 +1,112 @@
+import leon.invariant._
+import leon.instrumentation._
+import scala.collection.immutable.Set
+
+object RedBlackTree {
+  sealed abstract class Color
+  case class Red() extends Color
+  case class Black() extends Color
+
+  sealed abstract class Tree
+  case class Empty() extends Tree
+  case class Node(color: Color, left: Tree, value: BigInt, right: Tree) extends Tree
+
+  def twopower(x: BigInt) : BigInt = {
+    require(x >= 0)
+    if(x < 1) 1
+    else
+      2* twopower(x - 1)
+  }
+
+  def size(t: Tree): BigInt = {
+    require(blackBalanced(t))
+    (t match {
+      case Empty() => BigInt(0)
+      case Node(_, l, v, r) => size(l) + 1 + size(r)
+    })
+  } ensuring (res => tmpl((a,b) => twopower(blackHeight(t)) <= a*res + b))
+
+  def blackHeight(t : Tree) : BigInt = {
+   t match {
+    case Node(Black(), l, _, _) => blackHeight(l) + 1
+    case Node(Red(), l, _, _) => blackHeight(l)
+    case _ => 0
+   	}
+  }
+
+   //We consider leaves to be black by definition
+  def isBlack(t: Tree) : Boolean = t match {
+    case Empty() => true
+    case Node(Black(),_,_,_) => true
+    case _ => false
+  }
+
+  def redNodesHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Empty() => true
+    case Node(Black(), l, _, r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case Node(Red(), l, _, r) => isBlack(l) && isBlack(r) && redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case _ => false
+  }
+
+  def redDescHaveBlackChildren(t: Tree) : Boolean = t match {
+    case Node(_,l,_,r) => redNodesHaveBlackChildren(l) && redNodesHaveBlackChildren(r)
+    case _ => true
+  }
+
+  def blackBalanced(t : Tree) : Boolean = t match {
+    case Node(_,l,_,r) => blackBalanced(l) && blackBalanced(r) && blackHeight(l) == blackHeight(r)
+    case _ => true
+  }
+
+  // <<insert element x BigInto the tree t>>
+  def ins(x: BigInt, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t))
+
+    t match {
+      case Empty() => Node(Red(),Empty(),x,Empty())
+      case Node(c,a,y,b) =>
+        if(x < y) {
+        	val t1 = ins(x, a)
+        	balance(c, t1, y, b)
+        }
+        else if (x == y){
+        	Node(c,a,y,b)
+        }
+        else{
+          val t1 = ins(x, b)
+          balance(c,a,y,t1)
+        }
+    }
+  } ensuring(res => tmpl((a,b) => time <= a*blackHeight(t) + b))
+
+  def makeBlack(n: Tree): Tree = {
+    n match {
+      case Node(Red(),l,v,r) => Node(Black(),l,v,r)
+      case _ => n
+    }
+  }
+
+  def add(x: BigInt, t: Tree): Tree = {
+    require(redNodesHaveBlackChildren(t) && blackBalanced(t) )
+    val t1 =  ins(x, t)
+    makeBlack(t1)
+
+  } ensuring(res => tmpl((a,b) => time <= a*blackHeight(t) + b))
+
+  def balance(co: Color, l: Tree, x: BigInt, r: Tree): Tree = {
+    Node(co,l,x,r)
+     match {
+      case Node(Black(),Node(Red(),Node(Red(),a,xV,b),yV,c),zV,d) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case Node(Black(),Node(Red(),a,xV,Node(Red(),b,yV,c)),zV,d) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case Node(Black(),a,xV,Node(Red(),Node(Red(),b,yV,c),zV,d)) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case Node(Black(),a,xV,Node(Red(),b,yV,Node(Red(),c,zV,d))) =>
+        Node(Red(),Node(Black(),a,xV,b),yV,Node(Black(),c,zV,d))
+      case _ => Node(co,l,x,r)
+    }
+  }
+
+
+}
diff --git a/testcases/orb-testcases/timing/SortingCombined.scala b/testcases/orb-testcases/timing/SortingCombined.scala
new file mode 100644
index 000000000..914d997af
--- /dev/null
+++ b/testcases/orb-testcases/timing/SortingCombined.scala
@@ -0,0 +1,116 @@
+import leon.invariant._
+import leon.instrumentation._
+import leon.annotation._
+
+object Sort {
+  sealed abstract class List
+  case class Cons(head:BigInt,tail:List) extends List
+  case class Nil() extends List
+
+  //case class Pair(fst:List,snd:List)
+
+  // @monotonic
+  def log(x: BigInt) : BigInt = {
+    //require(x >= 0)
+    if(x <= 1) 0
+    else 1 + log(x/2)
+  } //ensuring(res=> true && tmpl((b) => res >= b))
+
+  def size(list:List): BigInt = {list match {
+    case Nil() => 0
+    case Cons(x,xs) => 1 + size(xs)
+  }}
+
+  def length(l:List): BigInt = {
+    l match {
+      case Nil() => 0
+      case Cons(x,xs) => 1 + length(xs)
+    }
+  } ensuring(res => res == size(l) && tmpl((a,b) => time <= a*size(l) + b))
+
+  def split(l:List,n:BigInt): (List,List) = {
+    require(n >= 0 && n <= size(l))
+    if (n <= 0) (Nil(),l)
+    else
+	l match {
+      case Nil() => (Nil(),l)
+      case Cons(x,xs) => {
+        if(n == 1) (Cons(x,Nil()), xs)
+        else {
+          val (fst,snd) = split(xs, n-1)
+          (Cons(x,fst), snd)
+        }
+      }
+	}
+  } ensuring(res => size(res._2) == size(l) - n && size(res._1) == n && tmpl((a,b) => time <= a*n +b))
+
+  def merge(aList:List, bList:List):List = (bList match {
+    case Nil() => aList
+    case Cons(x,xs) =>
+    	 aList match {
+   	       case Nil() => bList
+   	       case Cons(y,ys) =>
+    	        if (y < x)
+    		   Cons(y,merge(ys, bList))
+     		else
+		   Cons(x,merge(aList, xs))
+   	 }
+  }) ensuring(res => size(aList)+size(bList) == size(res) && tmpl((a,b,c) => time <= a*size(aList) + b*size(bList) + c))
+
+  def mergeSort(list:List, len: BigInt):List = {
+    require(len == size(list))
+
+    list match {
+      case Cons(x,Nil()) => list
+      case Cons(_,Cons(_,_)) =>
+         val l = len/2
+    	 val (fst,snd) = split(list,l)
+      	 merge(mergeSort(fst,l), mergeSort(snd,len - l))
+
+      case _ => list
+
+  }} //ensuring(res => size(res) == size(list) && tmpl((a,b,c) => time <= a*(size(list)*size(list)) + c))
+      //&& tmpl((a,b) => time <= a*size(list) + b))
+  //ensuring(res => true && tmpl((a,b) => time <= a*(size(list)*log(size(list))) + b))
+  case class Triple(fst:List,snd:List, trd: List)
+
+  def append(aList:List,bList:List): List = {aList match {
+    case Nil() => bList
+    case Cons(x, xs) => Cons(x,append(xs,bList))
+  }} ensuring(res => size(res) == size(aList) + size(bList) && tmpl((a,b) => time <= a*size(aList) +b))
+
+  def partition(n:BigInt,l:List) : Triple = (l match {
+    case Nil() => Triple(Nil(), Nil(), Nil())
+    case Cons(x,xs) => {
+      val t = partition(n,xs)
+      if (n < x) Triple(t.fst, t.snd, Cons(x,t.trd))
+      else if(n == x) Triple(t.fst, Cons(x,t.snd), t.trd)
+      else Triple(Cons(x,t.fst), t.snd, t.trd)
+    }
+ }) ensuring(res => (size(l) == size(res.fst) + size(res.snd) + size(res.trd)) && tmpl((a,b) => time <= a*size(l) +b))
+
+ //Unable to prove n^2  upper bound :-(
+  def quickSort(l:List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,Nil()) => l
+    case Cons(x,xs) => {
+      val t = partition(x, xs)
+      append(append(quickSort(t.fst), Cons(x, t.snd)), quickSort(t.trd))
+    }
+    case _ => l
+  })
+
+  def sortedIns(e: BigInt, l: List): List = {
+    l match {
+      case Nil() => Cons(e,Nil())
+      case Cons(x,xs) => if (x <= e) Cons(x,sortedIns(e, xs)) else Cons(e, l)
+    }
+  } ensuring(res => size(res) == size(l) + 1 && tmpl((a,b) => time <= a*size(l) +b))
+
+  def sort(l: List): List = (l match {
+    case Nil() => Nil()
+    case Cons(x,xs) => sortedIns(x, sort(xs))
+
+  }) ensuring(res => size(res) == size(l) && tmpl((a,b) => time <= a*(size(l)*size(l)) +b))
+
+}
diff --git a/testcases/orb-testcases/timing/SpeedBenchmarks.scala b/testcases/orb-testcases/timing/SpeedBenchmarks.scala
new file mode 100644
index 000000000..a7349ab26
--- /dev/null
+++ b/testcases/orb-testcases/timing/SpeedBenchmarks.scala
@@ -0,0 +1,109 @@
+import leon.invariant._
+import leon.instrumentation._
+
+object SpeedBenchmarks {
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  def size(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + size(t)
+  })
+
+  sealed abstract class StringBuffer
+  case class Chunk(str: List, next: StringBuffer) extends StringBuffer
+  case class Empty() extends StringBuffer
+
+  def length(sb: StringBuffer) : BigInt = sb match {
+    case Chunk(_, next) => 1 + length(next)
+    case _ => 0
+  }
+
+  def sizeBound(sb: StringBuffer, k: BigInt) : Boolean ={
+    sb match {
+      case Chunk(str, next) => size(str) <= k && sizeBound(next, k)
+      case _ => 0 <= k
+    }
+  }
+
+  /**
+   * Fig. 1 of SPEED, POPL'09: The functional version of the implementation.
+   * Equality check of two string buffers
+   */
+  def Equals(str1: List, str2: List, s1: StringBuffer, s2: StringBuffer, k: BigInt) : Boolean = {
+    require(sizeBound(s1, k) && sizeBound(s2, k) && size(str1) <= k && size(str2) <= k && k >= 0)
+
+    (str1, str2) match {
+      case (Cons(h1,t1), Cons(h2,t2)) => {
+
+        if(h1 != h2) false
+        else Equals(t1,t2, s1,s2, k)
+      }
+      case (Cons(_,_), Nil()) => {
+        //load from s2
+        s2 match {
+          case Chunk(str, next) => Equals(str1, str, s1, next, k)
+          case Empty() => false
+        }
+      }
+      case (Nil(), Cons(_,_)) => {
+        //load from s1
+        s1 match {
+          case Chunk(str, next) => Equals(str, str2, next, s2, k)
+          case Empty() => false
+        }
+      }
+      case _ =>{
+        //load from both
+        (s1,s2) match {
+          case (Chunk(nstr1, next1),Chunk(nstr2, next2)) => Equals(nstr1, nstr2, next1, next2, k)
+          case (Empty(),Chunk(nstr2, next2)) => Equals(str1, nstr2, s1, next2, k)
+          case (Chunk(nstr1, next1), Empty()) => Equals(nstr1, str2, next1, s2, k)
+          case _ => true
+        }
+      }
+    }
+  } ensuring(res => true && tmpl((a,b,c,d,e) => time <= a*((k+1)*(length(s1) + length(s2))) + b*size(str1) + e))
+  //ensuring(res => true && tmpl((a,b,c,d,e) => time <= a*(k*(length(s1) + length(s2))) + b*size(str1) + c*length(s1) + d*length(s2) + e))
+
+  def max(x: BigInt, y: BigInt) : BigInt = if(x >= y) x else y
+
+  //Fig. 2 of Speed POPL'09
+  def Dis1(x : BigInt, y : BigInt, n: BigInt, m: BigInt) : BigInt = {
+    if(x >= n) 0
+    else {
+      if(y < m) Dis1(x, y+1, n, m)
+      else Dis1(x+1, y, n, m)
+    }
+  } ensuring(res => true && tmpl((a,b,c) => time <= a*max(0,n-x) + b*max(0,m-y) + c))
+
+  //Fig. 2 of Speed POPL'09
+  def Dis2(x : BigInt, z : BigInt, n: BigInt) : BigInt = {
+    if(x >= n) 0
+    else {
+      if(z > x) Dis2(x+1, z, n)
+      else Dis2(x, z+1, n)
+    }
+  } ensuring(res => true && tmpl((a,b,c) => time <= a*max(0,n-x) + b*max(0,n-z) + c))
+
+  //Pg. 138, Speed POPL'09
+  def Dis3(x : BigInt, b : Boolean, t: BigInt, n: BigInt) : BigInt = {
+    require((b && t == 1) || (!b && t == -1))
+    if(x > n || x < 0) 0
+    else {
+      if(b) Dis3(x+t, b, t, n)
+      else Dis3(x-t, b, t, n)
+    }
+  } ensuring(res => true && tmpl((a,c) => time <= a*max(0,(n-x)) + c))
+
+  //Pg. 138, Speed POPL'09
+  def Dis4(x : BigInt, b : Boolean, t: BigInt, n: BigInt) : BigInt = {
+    if(x > n || x < 0) 0
+    else {
+      if(b) Dis4(x+t, b, t, n)
+      else Dis4(x-t, b, t, n)
+    }
+  } ensuring(res => true && tmpl((a,c,d,e) => (((b && t >= 0) || (!b && t < 0)) && time <= a*max(0,(n-x)) + c)
+  					|| (((!b && t >= 0) || (b && t < 0)) && time <= d*max(0,x) + e)))
+}
diff --git a/testcases/orb-testcases/timing/TreeOperations.scala b/testcases/orb-testcases/timing/TreeOperations.scala
new file mode 100644
index 000000000..2e73dcd77
--- /dev/null
+++ b/testcases/orb-testcases/timing/TreeOperations.scala
@@ -0,0 +1,93 @@
+import leon.invariant._
+import leon.instrumentation._
+
+
+object TreeOperations {
+
+  sealed abstract class List
+  case class Cons(head: BigInt, tail: List) extends List
+  case class Nil() extends List
+
+  sealed abstract class Tree
+  case class Node(left: Tree, value: BigInt, right: Tree) extends Tree
+  case class Leaf() extends Tree
+
+  def listSize(l: List): BigInt = (l match {
+    case Nil() => 0
+    case Cons(_, t) => 1 + listSize(t)
+  })
+
+  def size(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        size(l) + size(r) + 1
+      }
+    }
+  }
+
+  def height(t: Tree): BigInt = {
+    t match {
+      case Leaf() => 0
+      case Node(l, x, r) => {
+        val hl = height(l)
+        val hr = height(r)
+        if (hl > hr) hl + 1 else hr + 1
+      }
+    }
+  } 
+
+  def insert(elem: BigInt, t: Tree): Tree = {
+    t match {
+      case Leaf() => Node(Leaf(), elem, Leaf())
+      case Node(l, x, r) => if (x <= elem) Node(l, x, insert(elem, r))
+      else Node(insert(elem, l), x, r)
+    }
+  } ensuring (res => height(res) <= height(t) + 1 && tmpl((a,b) => time <= a*height(t) + b))
+
+  def addAll(l: List, t: Tree): Tree = {
+    l match {
+      case Nil() => t
+      case Cons(x, xs) =>{
+        val newt = insert(x, t)
+        addAll(xs, newt)
+      }
+    }
+  } ensuring(res => tmpl((a,b,c) => time <= a*(listSize(l) * (height(t) + listSize(l))) + b*listSize(l) + c))
+
+  def remove(elem: BigInt, t: Tree): Tree = {
+    t match {
+      case Leaf() => Leaf()
+      case Node(l, x, r) => {
+
+        if (x < elem) Node(l, x, remove(elem, r))
+        else if (x > elem) Node(remove(elem, l), x, r)
+        else {
+          t match {
+            case Node(Leaf(), x, Leaf()) => Leaf()
+            case Node(Leaf(), x, Node(_, rx, _)) => Node(Leaf(), rx, remove(rx, r))
+            case Node(Node(_, lx, _), x, r) => Node(remove(lx, l), lx, r)
+            case _ => Leaf()
+          }
+        }
+      }
+    }
+  } ensuring (res => height(res) <= height(t) && tmpl ((a, b, c) => time <= a*height(t) + b))
+
+  def removeAll(l: List, t: Tree): Tree = {
+    l match {
+      case Nil() => t
+      case Cons(x, xs) => removeAll(xs, remove(x, t))
+    }
+  } ensuring(res => tmpl((a,b,c) => time <= a*(listSize(l) * height(t)) + b*listSize(l) + c))
+
+  def contains(elem : BigInt, t : Tree) : Boolean = {
+    t match {
+      case Leaf() => false
+      case Node(l, x, r) =>
+        if(x == elem) true
+        else if (x < elem) contains(elem, r)
+        else contains(elem, l)
+    }
+  } ensuring (res => tmpl((a,b) => time <= a*height(t) + b))
+}
\ No newline at end of file
-- 
GitLab