From e439db26e15117c737f796db422b25ea6b0bc7cf Mon Sep 17 00:00:00 2001
From: ravi <ravi.kandhadai@epfl.ch>
Date: Tue, 20 Oct 2015 17:12:24 +0200
Subject: [PATCH] Adding supports for analyzing selected functions in Orb

---
 .gitignore                                    |   1 +
 .../engine/CompositionalTemplateSolver.scala  |  22 ++--
 .../invariant/engine/ConstraintTracker.scala  |   6 +-
 .../engine/InferInvariantsPhase.scala         | 117 ++++--------------
 .../invariant/engine/InferenceContext.scala   | 115 ++++++++++++++---
 .../invariant/engine/InferenceEngine.scala    |  61 ++++-----
 .../invariant/engine/InferenceReport.scala    |  12 +-
 .../invariant/engine/RefinementEngine.scala   |   3 +-
 .../invariant/engine/SpecInstatiator.scala    |   3 +-
 .../invariant/engine/TemplateEnumerator.scala |  78 ++++++------
 .../engine/UnfoldingTemplateSolver.scala      |  29 +++--
 .../factories/TemplateSolverFactory.scala     |  10 +-
 .../templateSolvers/CegisSolver.scala         |  13 +-
 .../templateSolvers/FarkasLemmaSolver.scala   |  15 +--
 .../templateSolvers/NLTemplateSolver.scala    |  14 +--
 .../NLTemplateSolverWithMult.scala            |   4 +-
 .../templateSolvers/TemplateSolver.scala      |   7 +-
 .../scala/leon/invariant/util/Minimizer.scala |  16 +--
 src/main/scala/leon/invariant/util/Util.scala |   5 +
 19 files changed, 265 insertions(+), 266 deletions(-)

diff --git a/.gitignore b/.gitignore
index 057efa0f3..4ef5b5eae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -54,3 +54,4 @@ out-classes
 
 # Isabelle
 contrib
+/bin/
diff --git a/src/main/scala/leon/invariant/engine/CompositionalTemplateSolver.scala b/src/main/scala/leon/invariant/engine/CompositionalTemplateSolver.scala
index 4c443b3f6..94ee3377c 100644
--- a/src/main/scala/leon/invariant/engine/CompositionalTemplateSolver.scala
+++ b/src/main/scala/leon/invariant/engine/CompositionalTemplateSolver.scala
@@ -21,7 +21,7 @@ import leon.invariant.factories.TemplateSolverFactory
 import leon.invariant.util.Minimizer
 import leon.solvers.Model
 
-class CompositionalTimeBoundSolver(ctx: InferenceContext, rootFd: FunDef)
+class CompositionalTimeBoundSolver(ctx: InferenceContext, prog: Program, rootFd: FunDef)
   extends FunctionTemplateSolver {
 
   val printIntermediatePrograms = false
@@ -30,7 +30,7 @@ class CompositionalTimeBoundSolver(ctx: InferenceContext, rootFd: FunDef)
   val reporter = ctx.reporter
 
   def inferTemplate(instProg: Program) = {
-    (new UnfoldingTemplateSolver(ctx.copy(program = instProg), findRoot(instProg)))()
+    (new UnfoldingTemplateSolver(ctx, instProg, findRoot(instProg)))()
   }
 
   def findRoot(prog: Program) = {
@@ -45,7 +45,7 @@ class CompositionalTimeBoundSolver(ctx: InferenceContext, rootFd: FunDef)
       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
+    val origProg = prog
     // add only rec templates for all functions
     val funToRecTmpl = origProg.definedFunctions.collect {
       case fd if fd.hasTemplate && fd == rootFd =>
@@ -81,7 +81,7 @@ class CompositionalTimeBoundSolver(ctx: InferenceContext, rootFd: FunDef)
         }.toMap
         val compProg = assignTemplateAndCojoinPost(funToTmpl, origProg)
         val compFunDef = findRoot(compProg)
-        val nctx = ctx.copy(program = compProg)
+        //val nctx = ctx.copy(program = compProg)
 
         // construct the instantiated tpr bound and check if it monotonically decreases
         val Operator(Seq(_, tprFun), _) = tprTmpl
@@ -118,13 +118,13 @@ class CompositionalTimeBoundSolver(ctx: InferenceContext, rootFd: FunDef)
         if (printIntermediatePrograms) reporter.info("Comp prog: " + compProg)
         if (debugComposition) reporter.info("Compositional VC: " + vcExpr)
 
-        val recTempSolver = new UnfoldingTemplateSolver(nctx, compFunDef) {
+        val recTempSolver = new UnfoldingTemplateSolver(ctx, compProg, compFunDef) {
           val minFunc = {
-            val mizer = new Minimizer(ctx)
+            val mizer = new Minimizer(ctx, compProg)
             Some(mizer.minimizeBounds(mizer.computeCompositionLevel(timeTmpl)) _)
           }
           override lazy val templateSolver =
-            TemplateSolverFactory.createTemplateSolver(ctx, constTracker, rootFd, minFunc)
+            TemplateSolverFactory.createTemplateSolver(ctx, compProg, constTracker, rootFd, minFunc)
           override def instantiateModel(model: Model, funcs: Seq[FunDef]) = {
             funcs.collect {
               case `compFunDef` =>
@@ -148,12 +148,12 @@ class CompositionalTimeBoundSolver(ctx: InferenceContext, rootFd: FunDef)
     }
   }
 
-  def combineMapsUsingConjunction(maps: List[Map[FunDef, Expr]]) = {
+  /*def combineMapsUsingConjunction(maps: List[Map[FunDef, Expr]], prog: Program) = {
     val combMap = new OrderedMultiMap[FunDef, Expr]
     maps.foreach {
       _.foreach {
         case (k, v) =>
-          val origFun = functionByName(k.id.name, ctx.program).get
+          val origFun = functionByName(k.id.name, prog).get
           combMap.addBinding(origFun, v)
       }
     }
@@ -161,7 +161,7 @@ class CompositionalTimeBoundSolver(ctx: InferenceContext, rootFd: FunDef)
       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]())
@@ -204,7 +204,7 @@ class CompositionalTimeBoundSolver(ctx: InferenceContext, rootFd: FunDef)
   }
 
   def inferTPRTemplate(tprProg: Program) = {
-    val tempSolver = new UnfoldingTemplateSolver(ctx.copy(program = tprProg), findRoot(tprProg)) {
+    val tempSolver = new UnfoldingTemplateSolver(ctx, tprProg, findRoot(tprProg)) {
       override def constructVC(rootFd: FunDef): (Expr, Expr) = {
         val body = Equals(getResId(rootFd).get.toVariable, matchToIfThenElse(rootFd.body.get))
         val preExpr =
diff --git a/src/main/scala/leon/invariant/engine/ConstraintTracker.scala b/src/main/scala/leon/invariant/engine/ConstraintTracker.scala
index e50b50bb8..3058a267e 100644
--- a/src/main/scala/leon/invariant/engine/ConstraintTracker.scala
+++ b/src/main/scala/leon/invariant/engine/ConstraintTracker.scala
@@ -16,13 +16,13 @@ import invariant.factories._
 import invariant.util._
 import invariant.structure._
 
-class ConstraintTracker(ctx : InferenceContext, rootFun : FunDef/*, temFactory: TemplateFactory*/) {
+class ConstraintTracker(ctx : InferenceContext, program: Program, 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*/)
+  val vcRefiner = new RefinementEngine(ctx, program, this)
+  val specInstantiator = new SpecInstantiator(ctx, program, this)
 
   def getFuncs : Seq[FunDef] = funcVCs.keys.toSeq
   def hasVC(fdef: FunDef) = funcVCs.contains(fdef)
diff --git a/src/main/scala/leon/invariant/engine/InferInvariantsPhase.scala b/src/main/scala/leon/invariant/engine/InferInvariantsPhase.scala
index 4bc1e245f..0b48c1e8c 100644
--- a/src/main/scala/leon/invariant/engine/InferInvariantsPhase.scala
+++ b/src/main/scala/leon/invariant/engine/InferInvariantsPhase.scala
@@ -14,21 +14,17 @@ import invariant.util._
 import invariant.structure.FunctionUtils._
 import invariant.structure._
 import transformations._
-import verification._
-import verification.VCKinds
 import leon.purescala.ScalaPrinter
 import leon.purescala.PrettyPrinter
 
 /**
  * @author ravi
  * This phase performs automatic invariant inference.
- * TODO: should time be implicitly made positive
  */
 object InferInvariantsPhase extends SimpleLeonPhase[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)
@@ -36,26 +32,19 @@ object InferInvariantsPhase extends SimpleLeonPhase[Program, InferenceReport] {
   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 optVCTimeout = LeonLongOptionDef("vcTimeout", "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,
+    Set(optFunctionUnroll, optWithMult, optUseReals,
+        optMinBounds, optInferTemp, optCegis, optStatsSuffix, optVCTimeout,
         optDisableInfer)
 
-  //TODO provide options for analyzing only selected functions
   def apply(ctx: LeonContext, program: Program): InferenceReport = {
-
-    //control printing of statistics
+    //default values for flags
     val dumpStats = false
-    var timeout: Int = 15
-
-    //defualt true flags
-    var modularlyAnalyze = true
+    var vcTimeout: Int = 15
     var targettedUnroll = true
-
-    //default false flags
     var tightBounds = false
     var withmult = false
     var inferTemp = false
@@ -68,89 +57,33 @@ object InferInvariantsPhase extends SimpleLeonPhase[Program, InferenceReport] {
     var autoInference = true
 
     for (opt <- ctx.options) (opt.optionDef.name, opt.value) match {
-      case ("wholeprogram", true) => 
-        modularlyAnalyze = false      
-      case ("fullunroll", true) =>         
-        targettedUnroll = false      
-      case ("minbounds", true) => 
-        tightBounds = true      
-      case ("withmult", true) => 
-        withmult = true      
-      case ("usereals", true) => 
-        usereals = true      
+      case ("fullunroll", true) =>
+        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              
-      case ("cegis", true) => 
-        useCegis = true      
-      case ("timeout", timeOut: Int) =>
-        timeout = timeOut
-      case ("stats-suffix", suffix: String) => 
-        statsSuff = suffix      
+      case ("inferTemp", true) =>
+        inferTemp = true
+      case ("cegis", true) =>
+        useCegis = true
+      case ("vcTimeout", timeOut: Int) =>
+        vcTimeout = timeOut
+      case ("stats-suffix", suffix: String) =>
+        statsSuff = suffix
       case _ =>
     }
-    
-    // (a) first run instrumentation phase
-    val instProg = InstrumentationPhase(ctx, program)
-
-    // (b) convert qmarks to tmpl functions 
-    val funToTmpl = instProg.definedFunctions.collect {
-      case fd if fd.hasTemplate =>
-        fd -> fd.getTemplate
-    }.toMap
-    val qMarksRemovedProg = Util.assignTemplateAndCojoinPost(funToTmpl, instProg, Map())
-
-    // convert nonlinearity to recursive functions
-    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)
-
-    // collect strongest relation for enumeration if defined
-    var foundStrongest = false
-    //go over all post-conditions and pick the strongest relation
-    instProg.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)
-      }
-    })
-    
     //populate the inference context and invoke inferenceEngine
-    val inferctx = new InferenceContext(program, 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)
+    val inferctx = new InferenceContext(program,  ctx,
+        targettedUnroll, autoInference, dumpStats, tightBounds,
+        withmult, usereals, inferTemp, useCegis, vcTimeout,
+        maxCegisBound, statsSuff)
     val report = (new InferenceEngine(inferctx)).run()
     //println("Final Program: \n" +PrettyPrinter.apply(report.finalProgramWoInstrumentation))
     report
   }
-
-  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 = VerificationPhase
-    val ctxWithTO = createLeonContext(ctx, "--timeout=" + timeout)
-    (verifyPipe.run(ctxWithTO, prog)._2).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
-  }
 }
diff --git a/src/main/scala/leon/invariant/engine/InferenceContext.scala b/src/main/scala/leon/invariant/engine/InferenceContext.scala
index bf3d83845..506fbb139 100644
--- a/src/main/scala/leon/invariant/engine/InferenceContext.scala
+++ b/src/main/scala/leon/invariant/engine/InferenceContext.scala
@@ -1,32 +1,107 @@
 package leon
 package invariant.engine
 
+import scala.collection.mutable.{ Map => MutableMap }
 import purescala.Definitions._
 import purescala.Expressions._
-import purescala._
+import purescala.Types._
+import purescala.ExprOps._
+import transformations._
+import invariant.structure.FunctionUtils._
+import invariant.util._
+import verification._
+import verification.VCKinds
 
 /**
  * @author ravi
  */
-case class InferenceContext(
-  val uninstrumentedProgram : Program, 
-  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)  {
+class InferenceContext(
+    val initProgram: Program,
+    val leonContext: LeonContext,
+    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 vcTimeout: Int, //in secs
+    val maxCegisBound: Int,
+    val statsSuffix: String) {
 
   val reporter = leonContext.reporter
+  val functionsToInfer = leonContext.findOption(SharedOptions.optFunctions)
+  val totalTimeout = leonContext.findOption(SharedOptions.optTimeout)
+
+  val instrumentedProg = InstrumentationPhase(leonContext, initProgram)
+  // convets qmarks to templates
+  val qMarksRemovedProg = {
+    val funToTmpl = instrumentedProg.definedFunctions.collect {
+      case fd if fd.hasTemplate =>
+        fd -> fd.getTemplate
+    }.toMap
+    Util.assignTemplateAndCojoinPost(funToTmpl, instrumentedProg, Map())
+  }
+
+  val nlelim = new NonlinearityEliminator(withmult, if (usereals) RealType else IntegerType)
+
+  val inferProgram = {
+    // convert nonlinearity to recursive functions
+    nlelim(if (usereals)
+      (new IntToRealProgram())(qMarksRemovedProg)
+    else qMarksRemovedProg)
+  }
+
+  // other utilities
+  lazy val enumerationRelation = {
+    // collect strongest relation for enumeration if defined
+    var foundStrongest = false
+    var rel: (Expr, Expr) => Expr = LessEquals.apply _
+    //go over all post-conditions and pick the strongest relation
+    instrumentedProg.definedFunctions.foreach((fd) => {
+      if (!foundStrongest && fd.hasPostcondition) {
+        val cond = fd.postcondition.get
+        postTraversal((e) => e match {
+          case Equals(_, _) => {
+            rel = Equals.apply _
+            foundStrongest = true
+          }
+          case _ => ;
+        })(cond)
+      }
+    })
+    rel
+  }
+
+  def multOp(e1: Expr, e2: Expr) = {
+    FunctionInvocation(TypedFunDef(nlelim.multFun, nlelim.multFun.tparams.map(_.tp)), Seq(e1, e2))
+  }
+
+  val validPosts = MutableMap[String, VCResult]()
+
+  /**
+   * There should be only one function with funName in the
+   * program
+   */
+  def isFunctionPostVerified(funName: String) = {
+    if (validPosts.contains(funName)) {
+      validPosts(funName).isValid
+    } else {
+      val verifyPipe = VerificationPhase
+      val ctxWithTO = Util.createLeonContext(leonContext, s"--timeout=$vcTimeout", s"--functions=$funName")
+      (true /: verifyPipe.run(ctxWithTO, qMarksRemovedProg)._2.results) {
+        case (acc, (VC(_, _, vckind), Some(vcRes))) if vcRes.isInvalid =>
+          throw new IllegalStateException(s"$vckind invalid for function $funName") // TODO: remove the exception
+        case (acc, (VC(_, _, VCKinds.Postcondition), None)) =>
+          throw new IllegalStateException(s"Postcondition verification returned unknown for function $funName") // TODO: remove the exception
+        case (acc, (VC(_, _, VCKinds.Postcondition), _)) if validPosts.contains(funName) =>
+          throw new IllegalStateException(s"Multiple postcondition VCs for function $funName") // TODO: remove the exception
+        case (acc, (VC(_, _, VCKinds.Postcondition), Some(vcRes))) =>
+          validPosts(funName) = vcRes
+          vcRes.isValid
+        case (acc, _) => acc
+      }
+    }
+  }
 }
diff --git a/src/main/scala/leon/invariant/engine/InferenceEngine.scala b/src/main/scala/leon/invariant/engine/InferenceEngine.scala
index 03202f9db..e3965bfb1 100644
--- a/src/main/scala/leon/invariant/engine/InferenceEngine.scala
+++ b/src/main/scala/leon/invariant/engine/InferenceEngine.scala
@@ -20,6 +20,7 @@ import invariant.util.Util._
 import invariant.structure._
 import invariant.structure.FunctionUtils._
 import leon.invariant.factories.TemplateFactory
+import transformations._
 
 /**
  * @author ravi
@@ -30,7 +31,7 @@ class InferenceEngine(ctx: InferenceContext) {
 
   def run(): InferenceReport = {
     val reporter = ctx.reporter
-    val program = ctx.program
+    val program = ctx.inferProgram
     reporter.info("Running Inference Engine...")
 
     //register a shutdownhook
@@ -40,15 +41,19 @@ class InferenceEngine(ctx: InferenceContext) {
     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
+    val functionsToAnalyze = ctx.functionsToInfer match {
+      case Some(rootfuns) =>
+        val rootset = rootfuns.toSet
+        val rootfds = program.definedFunctions.filter(fd => rootset(InstUtil.userFunctionName(fd)))
+        val relfuns = rootfds.flatMap(callgraph.transitiveCallees _).toSet
+        callgraph.topologicalOrder.filter{ fd => relfuns(fd) }
+      case _ =>
+        callgraph.topologicalOrder
     }
     //reporter.info("Analysis Order: " + functionsToAnalyze.map(_.id))
     var results: Map[FunDef, InferenceCondition] = null
     if (!ctx.useCegis) {
-      results = analyseProgram(functionsToAnalyze)
+      results = analyseProgram(program, functionsToAnalyze)
       //println("Inferrence did not succeeded for functions: "+functionsToAnalyze.filterNot(succeededFuncs.contains _).map(_.id))
     } else {
       var remFuncs = functionsToAnalyze
@@ -57,7 +62,7 @@ class InferenceEngine(ctx: InferenceContext) {
       breakable {
         while (b <= maxCegisBound) {
           Stats.updateCumStats(1, "CegisBoundsTried")
-          val succeededFuncs = analyseProgram(remFuncs)
+          val succeededFuncs = analyseProgram(program, remFuncs)
           remFuncs = remFuncs.filterNot(succeededFuncs.contains _)
           if (remFuncs.isEmpty) break;
           b += 5 //increase bounds in steps of 5
@@ -75,12 +80,12 @@ class InferenceEngine(ctx: InferenceContext) {
     new InferenceReport(results.map(pair => {
       val (fd, ic) = pair
       (fd -> List[VC](ic))
-    }))(ctx)
+    }), program)(ctx)
   }
 
   def dumpStats(statsSuffix: String) = {
     //pick the module id.
-    val modid = ctx.program.modules.last.id
+    val modid = ctx.inferProgram.modules.last.id
     val pw = new PrintWriter(modid + statsSuffix + ".txt")
     Stats.dumpStats(pw)
     SpecificStats.dumpOutputs(pw)
@@ -94,17 +99,20 @@ class InferenceEngine(ctx: InferenceContext) {
    * 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] = {
+  def analyseProgram(startProg: Program, 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
+        // not usef for now
+        /*val tempFactory = new TemplateFactory(Some(new TemplateEnumerator(ctx, startProg)),
+            startProg, ctx.reporter)*/
+        startProg.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)
+        startProg.definedFunctions.collect { case fd if fd.hasTemplate => fd -> fd.getTemplate }.toMap
+    val progWithTemplates = assignTemplateAndCojoinPost(funToTmpl, startProg)
     var analyzedSet = Map[FunDef, InferenceCondition]()
+
     functionsToAnalyze.filterNot((fd) => {
       (fd.annotations contains "verified") ||
         (fd.annotations contains "library") ||
@@ -117,27 +125,26 @@ class InferenceEngine(ctx: InferenceContext) {
       //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)
+              new CompositionalTimeBoundSolver(ctx, prog, funDef)
             else
-              new UnfoldingTemplateSolver(currCtx, funDef)
+              new UnfoldingTemplateSolver(ctx, prog, 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
+                val origFd = Util.functionByName(fd.id.name, startProg).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 origFd = Util.functionByName(fd.id.name, startProg).get
                 val inv = TemplateInstantiator.getAllInvariants(model.get,
                   Map(origFd -> origFd.getTemplate))
                 // record the inferred invariants
@@ -151,15 +158,13 @@ class InferenceEngine(ctx: InferenceContext) {
                 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
+              // 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)
+
             case _ =>
               reporter.info("- Exhausted all templates, cannot infer invariants")
               val ic = new InferenceCondition(None, origFun)
diff --git a/src/main/scala/leon/invariant/engine/InferenceReport.scala b/src/main/scala/leon/invariant/engine/InferenceReport.scala
index 26337c6ff..97d7de298 100644
--- a/src/main/scala/leon/invariant/engine/InferenceReport.scala
+++ b/src/main/scala/leon/invariant/engine/InferenceReport.scala
@@ -30,8 +30,8 @@ class InferenceCondition(val invariant: Option[Expr], funDef: FunDef)
   }
 }
 
-class InferenceReport(fvcs: Map[FunDef, List[VC]])(implicit ctx: InferenceContext)
-  extends VerificationReport(ctx.program, Map()) {
+class InferenceReport(fvcs: Map[FunDef, List[VC]], program: Program)(implicit ctx: InferenceContext)
+  extends VerificationReport(program, Map()) {
 
   import scala.math.Ordering.Implicits._
   val conditions: Seq[InferenceCondition] =
@@ -86,17 +86,17 @@ class InferenceReport(fvcs: Map[FunDef, List[VC]])(implicit ctx: InferenceContex
       case cd if cd.invariant.isDefined =>
         cd.fd -> cd.invariant.get
     }.toMap
-    Util.assignTemplateAndCojoinPost(funToTmpl, ctx.program)
+    Util.assignTemplateAndCojoinPost(funToTmpl, program)
   }
 
   def finalProgramWoInstrumentation: Program = {
 
-    val funToUninstFun = ctx.program.definedFunctions.foldLeft(Map[FunDef, FunDef]()) {
+    val funToUninstFun = program.definedFunctions.foldLeft(Map[FunDef, FunDef]()) {
       case (acc, fd) =>
         val uninstFunName = InstUtil.userFunctionName(fd)
         val uninstFdOpt =
           if (uninstFunName.isEmpty) None
-          else Util.functionByName(uninstFunName, ctx.uninstrumentedProgram)
+          else Util.functionByName(uninstFunName, ctx.initProgram)
         if (uninstFdOpt.isDefined) {
           acc + (fd -> uninstFdOpt.get)
         } else acc
@@ -106,6 +106,6 @@ class InferenceReport(fvcs: Map[FunDef, List[VC]])(implicit ctx: InferenceContex
         funToUninstFun(cd.fd) -> cd.prettyInv.get
     }.toMap
     //println("Function to template: " + funToTmpl.map { case (k, v) => s"${k.id.name} --> $v" }.mkString("\n"))
-    Util.assignTemplateAndCojoinPost(Map(), ctx.uninstrumentedProgram, funToPost, uniqueIdDisplay = false)
+    Util.assignTemplateAndCojoinPost(Map(), ctx.initProgram, funToPost, uniqueIdDisplay = false)
   }
 }
\ 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
index cce8a3cb4..bf07342b2 100644
--- a/src/main/scala/leon/invariant/engine/RefinementEngine.scala
+++ b/src/main/scala/leon/invariant/engine/RefinementEngine.scala
@@ -18,11 +18,10 @@ 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) {
+class RefinementEngine(ctx: InferenceContext, prog: Program, 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
diff --git a/src/main/scala/leon/invariant/engine/SpecInstatiator.scala b/src/main/scala/leon/invariant/engine/SpecInstatiator.scala
index 9961df293..f356edb81 100644
--- a/src/main/scala/leon/invariant/engine/SpecInstatiator.scala
+++ b/src/main/scala/leon/invariant/engine/SpecInstatiator.scala
@@ -22,7 +22,7 @@ import invariant.util.Util._
 import invariant.structure._
 import FunctionUtils._
 
-class SpecInstantiator(ctx: InferenceContext, ctrTracker: ConstraintTracker) {
+class SpecInstantiator(ctx: InferenceContext, program: Program, ctrTracker: ConstraintTracker) {
 
   val verbose = false
 
@@ -31,7 +31,6 @@ class SpecInstantiator(ctx: InferenceContext, ctrTracker: ConstraintTracker) {
 
   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]()
diff --git a/src/main/scala/leon/invariant/engine/TemplateEnumerator.scala b/src/main/scala/leon/invariant/engine/TemplateEnumerator.scala
index 17bfdee4b..9b21ea7b5 100644
--- a/src/main/scala/leon/invariant/engine/TemplateEnumerator.scala
+++ b/src/main/scala/leon/invariant/engine/TemplateEnumerator.scala
@@ -11,7 +11,7 @@ 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 scala.collection.mutable.{ Set => MutableSet }
 
 import invariant.templateSolvers._
 import invariant.factories._
@@ -19,39 +19,38 @@ 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
+ * 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, prog: Program) extends TemplateGenerator {
   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
-    }
+  //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]()
+  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()
-	  }
-	}
+  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()
+    }
+  }
 }
 
 /**
@@ -59,15 +58,15 @@ class TemplateEnumerator(ctx: InferenceContext) extends TemplateGenerator {
  * '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) {
+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 _
+  //LessThan
+  //LessEquals
+  //Equals.apply _
   private var currTemp: Expr = null
   private var incrStep: Int = 0
   private var typeTermMap = Map[TypeTree, MutableSet[Expr]]()
@@ -82,11 +81,10 @@ class FunctionTemplateEnumerator(rootFun: FunDef, prog: Program, op: (Expr,Expr)
   def getNextTemplate(): Expr = {
     //println("Getting next template for function: "+fd.id)
 
-    if (incrStep == MAX_INCREMENTS){
+    if (incrStep == MAX_INCREMENTS) {
       //exhausted the templates, so return
       op(currTemp, zero)
-    }
-    else {
+    } else {
 
       incrStep += 1
 
@@ -152,10 +150,10 @@ class FunctionTemplateEnumerator(rootFun: FunDef, prog: Program, op: (Expr,Expr)
       //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) {
+      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)
+          val summand = Times(t, TemplateIdFactory.freshTemplateVar(): Expr)
           if (acc == null) summand
           else
             Plus(summand, acc)
diff --git a/src/main/scala/leon/invariant/engine/UnfoldingTemplateSolver.scala b/src/main/scala/leon/invariant/engine/UnfoldingTemplateSolver.scala
index 5a806fa3c..ab05a1747 100644
--- a/src/main/scala/leon/invariant/engine/UnfoldingTemplateSolver.scala
+++ b/src/main/scala/leon/invariant/engine/UnfoldingTemplateSolver.scala
@@ -8,6 +8,7 @@ import purescala.Expressions._
 import purescala.ExprOps._
 import purescala.Extractors._
 import purescala.Types._
+import purescala.DefOps._
 import solvers._
 import solvers.z3.FairZ3Solver
 import java.io._
@@ -35,14 +36,13 @@ trait FunctionTemplateSolver {
   def apply(): Option[InferResult]
 }
 
-class UnfoldingTemplateSolver(ctx: InferenceContext, rootFd: FunDef) extends FunctionTemplateSolver {
+class UnfoldingTemplateSolver(ctx: InferenceContext, program: Program, 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)
+  lazy val constTracker = new ConstraintTracker(ctx, program, rootFd)
+  lazy val templateSolver = TemplateSolverFactory.createTemplateSolver(ctx, program, constTracker, rootFd)
 
   def constructVC(funDef: FunDef): (Expr, Expr) = {
     val body = funDef.body.get
@@ -55,15 +55,18 @@ class UnfoldingTemplateSolver(ctx: InferenceContext, rootFd: FunDef) extends Fun
       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))
+    val funName = fullName(funDef, useUniqueIds = false)(program)
+    val fullPost = matchToIfThenElse(
+      if (funDef.hasTemplate) {
+        // if the postcondition is verified do not include it in the sequent
+        if (ctx.isFunctionPostVerified(funName))
+          funDef.getTemplate
+        else
+          And(funDef.getPostWoTemplate, funDef.getTemplate)
+      } else if (!ctx.isFunctionPostVerified(funName))
+        funDef.getPostWoTemplate
+      else
+        BooleanLiteral(true))
 
     (bodyExpr, fullPost)
   }
diff --git a/src/main/scala/leon/invariant/factories/TemplateSolverFactory.scala b/src/main/scala/leon/invariant/factories/TemplateSolverFactory.scala
index 25abefa22..469317998 100644
--- a/src/main/scala/leon/invariant/factories/TemplateSolverFactory.scala
+++ b/src/main/scala/leon/invariant/factories/TemplateSolverFactory.scala
@@ -17,27 +17,27 @@ import leon.solvers.Model
 
 object TemplateSolverFactory {
 
-  def createTemplateSolver(ctx: InferenceContext, ctrack: ConstraintTracker, rootFun: FunDef,
+  def createTemplateSolver(ctx: InferenceContext, prog: Program, 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)
+      new CegisSolver(ctx, prog, 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) _)
+          Some((new Minimizer(ctx, prog)).tightenTimeBounds(rootFun.getTemplate) _)
         }
       } else
         None
       if (ctx.withmult) {
-        new NLTemplateSolverWithMult(ctx, rootFun, ctrack, minimizer)
+        new NLTemplateSolverWithMult(ctx, prog, rootFun, ctrack, minimizer)
       } else {
-        new NLTemplateSolver(ctx, rootFun, ctrack, minimizer)
+        new NLTemplateSolver(ctx, prog, rootFun, ctrack, minimizer)
       }
     }
   }
diff --git a/src/main/scala/leon/invariant/templateSolvers/CegisSolver.scala b/src/main/scala/leon/invariant/templateSolvers/CegisSolver.scala
index 305bd98e3..ac64938bc 100644
--- a/src/main/scala/leon/invariant/templateSolvers/CegisSolver.scala
+++ b/src/main/scala/leon/invariant/templateSolvers/CegisSolver.scala
@@ -18,11 +18,9 @@ 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) {
+class CegisSolver(ctx: InferenceContext, program: Program,
+  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]]) = {
 
@@ -40,7 +38,7 @@ class CegisSolver(ctx: InferenceContext,
     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)
+    val (res, _, model) = (new CegisCore(ctx, program, timeout, this)).solve(tempIds, formula, initCtr, solveAsInt = true)
     res match {
       case Some(true) => (Some(model), None)
       case Some(false) => (None, None) //no solution exists
@@ -51,7 +49,7 @@ class CegisSolver(ctx: InferenceContext,
 }
 
 class CegisCore(ctx: InferenceContext,
-  timeout: Int,
+    program: Program, timeout: Int,
   cegisSolver: TemplateSolver) {
 
   val fls = BooleanLiteral(false)
@@ -60,7 +58,6 @@ class CegisCore(ctx: InferenceContext,
   val timeoutMillis = timeout.toLong * 1000
   val dumpCandidateInvs = true
   val minimizeSum = false
-  val program = ctx.program
   val context = ctx.leonContext
   val reporter = context.reporter
 
diff --git a/src/main/scala/leon/invariant/templateSolvers/FarkasLemmaSolver.scala b/src/main/scala/leon/invariant/templateSolvers/FarkasLemmaSolver.scala
index 6e80c4749..14f62ae7c 100644
--- a/src/main/scala/leon/invariant/templateSolvers/FarkasLemmaSolver.scala
+++ b/src/main/scala/leon/invariant/templateSolvers/FarkasLemmaSolver.scala
@@ -24,7 +24,7 @@ import leon.solvers.Model
 import leon.solvers.smtlib.SMTLIBZ3Solver
 import leon.invariant.util.RealValuedExprEvaluator._
 
-class FarkasLemmaSolver(ctx: InferenceContext) {
+class FarkasLemmaSolver(ctx: InferenceContext, program: Program) {
 
   //debug flags
   val verbose = true
@@ -39,9 +39,9 @@ class FarkasLemmaSolver(ctx: InferenceContext) {
   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
+  val timeout = ctx.vcTimeout // Note: we are using vcTimeout here as well
+
   /**
    * This procedure produces a set of constraints that need to be satisfiable for the
    * conjunction ants and conseqs to be false
@@ -54,11 +54,6 @@ class FarkasLemmaSolver(ctx: InferenceContext) {
    *
    */
   def constraintsForUnsat(linearCtrs: Seq[LinearConstraint], temps: Seq[LinearTemplate]): Expr = {
-
-    //for debugging
-    /*println("#" * 20)
-    println(allAnts + " ^ " + allConseqs)
-    println("#" * 20)*/
     this.applyFarkasLemma(linearCtrs ++ temps, Seq(), true)
   }
 
@@ -263,7 +258,7 @@ class FarkasLemmaSolver(ctx: InferenceContext) {
       reporter.info("InputCtrs: " + nlctrs)
       reporter.info("SimpCtrs: " + simpctrs)
       if (this.dumpNLCtrsAsSMTLIB) {
-        val filename = ctx.program.modules.last.id + "-nlctr" + FileCountGUID.getID + ".smt2"
+        val filename = 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)
@@ -279,9 +274,7 @@ class FarkasLemmaSolver(ctx: InferenceContext) {
       throw new IllegalStateException("Not supported now. Will be in the future!")
       //new ExtendedUFSolver(leonctx, program, useBitvectors = true, bitvecSize = bvsize) with TimeoutSolver
     } else {
-      // use SMTLIBSolver to solve the constraints so that it can be timed out effectively
       new SMTLIBZ3Solver(leonctx, program) with TimeoutSolver
-      //new ExtendedUFSolver(leonctx, program) with TimeoutSolver
     }
     val solver = SimpleSolverAPI(new TimeoutSolverFactory(SolverFactory(() => innerSolver), timeout * 1000))
     if (verbose) reporter.info("solving...")
diff --git a/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala
index 47901d3b9..5063a284c 100644
--- a/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala
+++ b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolver.scala
@@ -27,8 +27,9 @@ 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])
+class NLTemplateSolver(ctx: InferenceContext, program: Program,
+    rootFun: FunDef, ctrTracker: ConstraintTracker,
+    minimizer: Option[(Expr, Model) => Model])
   extends TemplateSolver(ctx, rootFun, ctrTracker) {
 
   //flags controlling debugging
@@ -49,12 +50,11 @@ class NLTemplateSolver(ctx: InferenceContext, rootFun: FunDef, ctrTracker: Const
   val printCallConstriants = false
   val dumpInstantiatedVC = false
 
-  private val program = ctx.program
-  private val timeout = ctx.timeout
+  private val timeout = ctx.vcTimeout
   private val leonctx = ctx.leonContext
 
   //flag controlling behavior
-  private val farkasSolver = new FarkasLemmaSolver(ctx)
+  private val farkasSolver = new FarkasLemmaSolver(ctx, program)
   private val startFromEarlierModel = true
   private val disableCegis = true
   private val useIncrementalSolvingForVCs = true
@@ -355,7 +355,7 @@ class NLTemplateSolver(ctx: InferenceContext, rootFun: FunDef, ctrTracker: Const
 
   def solveWithCegis(tempIds: Set[Identifier], expr: Expr, precond: Expr, initModel: Option[Model]): (Option[Boolean], Expr, Model) = {
 
-    val cegisSolver = new CegisCore(ctx, timeout, this)
+    val cegisSolver = new CegisCore(ctx, program, 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...")
@@ -471,7 +471,7 @@ class NLTemplateSolver(ctx: InferenceContext, rootFun: FunDef, ctrTracker: Const
     }
   }
 
-  val evaluator = new DefaultEvaluator(leonctx, program) //as of now used only for debugging
+  lazy 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 = {
diff --git a/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolverWithMult.scala b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolverWithMult.scala
index 10a232e3f..f3628be51 100644
--- a/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolverWithMult.scala
+++ b/src/main/scala/leon/invariant/templateSolvers/NLTemplateSolverWithMult.scala
@@ -17,9 +17,9 @@ import invariant.factories._
 import invariant.util._
 import invariant.structure._
 
-class NLTemplateSolverWithMult(ctx : InferenceContext, rootFun: FunDef,
+class NLTemplateSolverWithMult(ctx : InferenceContext, program: Program, rootFun: FunDef,
   ctrTracker: ConstraintTracker, minimizer: Option[(Expr, Model) => Model])
-  extends NLTemplateSolver(ctx, rootFun, ctrTracker, minimizer) {
+  extends NLTemplateSolver(ctx, program, rootFun, ctrTracker, minimizer) {
 
   val axiomFactory = new AxiomFactory(ctx)
 
diff --git a/src/main/scala/leon/invariant/templateSolvers/TemplateSolver.scala b/src/main/scala/leon/invariant/templateSolvers/TemplateSolver.scala
index 9b360c2db..61bdc8bf5 100644
--- a/src/main/scala/leon/invariant/templateSolvers/TemplateSolver.scala
+++ b/src/main/scala/leon/invariant/templateSolvers/TemplateSolver.scala
@@ -33,7 +33,6 @@ abstract class TemplateSolver(ctx: InferenceContext, val rootFun: FunDef,
 
   private val dumpVCtoConsole = false
   private val dumpVCasText = false
-  private val dumpVCasSMTLIB = false
 
   /**
    * Completes a model by adding mapping to new template variables
@@ -73,7 +72,7 @@ abstract class TemplateSolver(ctx: InferenceContext, val rootFun: FunDef,
       val vc = if (ctx.usereals)
         ExpressionTransformer.IntLiteralToReal(getVCForFun(fd))
       else getVCForFun(fd)
-      if (dumpVCtoConsole || dumpVCasText || dumpVCasSMTLIB) {
+      if (dumpVCtoConsole || dumpVCasText) {
         //val simpForm = simplifyArithmetic(vc)
         val filename = "vc-" + FileCountGUID.getID
         if (dumpVCtoConsole) {
@@ -87,10 +86,6 @@ abstract class TemplateSolver(ctx: InferenceContext, val rootFun: FunDef,
           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) {
diff --git a/src/main/scala/leon/invariant/util/Minimizer.scala b/src/main/scala/leon/invariant/util/Minimizer.scala
index 78e82db2d..cec35bff1 100644
--- a/src/main/scala/leon/invariant/util/Minimizer.scala
+++ b/src/main/scala/leon/invariant/util/Minimizer.scala
@@ -17,7 +17,7 @@ import invariant.factories._
 import leon.invariant.templateSolvers.ExtendedUFSolver
 import leon.invariant.util.RealValuedExprEvaluator._
 
-class Minimizer(ctx: InferenceContext) {
+class Minimizer(ctx: InferenceContext, program: Program) {
 
   val verbose = false
   val debugMinimization = false
@@ -26,14 +26,11 @@ class Minimizer(ctx: InferenceContext) {
    * 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 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
 
@@ -59,8 +56,7 @@ class Minimizer(ctx: InferenceContext) {
     // note: use smtlib solvers so that they can be timedout
     val solver = SimpleSolverAPI(
       new TimeoutSolverFactory(SolverFactory(() =>
-        new SMTLIBZ3Solver(leonctx, program) with TimeoutSolver), ctx.timeout * 1000))
-        //new ExtendedUFSolver(leonctx, program) with TimeoutSolver), ctx.timeout * 1000))
+        new SMTLIBZ3Solver(leonctx, program) with TimeoutSolver), ctx.vcTimeout * 1000))
 
     reporter.info("minimizing...")
     var currentModel = initModel
@@ -151,7 +147,7 @@ class Minimizer(ctx: InferenceContext) {
       val (res, newModel) = solver.solveSAT(And(nlctr, Equals(tvar, flval)))
       res match {
         case Some(true) => Some(newModel)
-        case _ => None
+        case _          => None
       }
     } else None
   }
@@ -191,10 +187,10 @@ class Minimizer(ctx: InferenceContext) {
           0
         }
         case FunctionInvocation(_, args) => 1 + args.foldLeft(0)((acc, arg) => acc + functionNesting(arg))
-        case t: Terminal => 0
+        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))
+        case Operator(args, _)           => args.foldLeft(0)((acc, arg) => acc + functionNesting(arg))
       }
     }
     functionNesting(template)
diff --git a/src/main/scala/leon/invariant/util/Util.scala b/src/main/scala/leon/invariant/util/Util.scala
index 5a101569e..53af2083a 100644
--- a/src/main/scala/leon/invariant/util/Util.scala
+++ b/src/main/scala/leon/invariant/util/Util.scala
@@ -98,6 +98,11 @@ object Util {
   val tru = BooleanLiteral(true)
   val fls = BooleanLiteral(false)
 
+  def createLeonContext(ctx: LeonContext, opts: String*): LeonContext = {
+    Main.processOptions(opts.toList).copy(reporter = ctx.reporter,
+      interruptManager = ctx.interruptManager, files = ctx.files, timers = ctx.timers)
+  }
+
   /**
    * Here, we exclude empty units that do not have any modules and empty
    * modules that do not have any definitions
-- 
GitLab