From 379ac744baccc879f57c06383bd8390b3da60249 Mon Sep 17 00:00:00 2001
From: Manos Koukoutos <emmanouil.koukoutos@epfl.ch>
Date: Fri, 5 Aug 2016 18:16:14 +0200
Subject: [PATCH] PortfolioSolvers

---
 .../scala/inox/solvers/SolverResponses.scala  |  2 +-
 .../solvers/combinators/PortfolioSolver.scala | 66 +++++++++----------
 .../combinators/PortfolioSolverFactory.scala  | 29 ++++----
 3 files changed, 47 insertions(+), 50 deletions(-)

diff --git a/src/main/scala/inox/solvers/SolverResponses.scala b/src/main/scala/inox/solvers/SolverResponses.scala
index 006d2624f..ac4f84418 100644
--- a/src/main/scala/inox/solvers/SolverResponses.scala
+++ b/src/main/scala/inox/solvers/SolverResponses.scala
@@ -72,7 +72,7 @@ object SolverResponses {
     }
 
     def cast[M, C](resp: SolverResponse[M,C]): Response[M,C] = ((this, resp) match {
-      case (_, Unknown)                               => Unknown
+      case (_, Unknown)                            => Unknown
       case (Simple | Cores, Sat)                   => Sat
       case (Model  | All  , s @ SatWithModel(_))   => s
       case (Simple | Model, Unsat)                 => Unsat
diff --git a/src/main/scala/inox/solvers/combinators/PortfolioSolver.scala b/src/main/scala/inox/solvers/combinators/PortfolioSolver.scala
index 1a942fd42..61c8b1605 100644
--- a/src/main/scala/inox/solvers/combinators/PortfolioSolver.scala
+++ b/src/main/scala/inox/solvers/combinators/PortfolioSolver.scala
@@ -1,24 +1,24 @@
 /* Copyright 2009-2016 EPFL, Lausanne */
 
-package leon
+package inox
 package solvers
 package combinators
 
-import purescala.Expressions._
-import verification.VC
+import inox.solvers.SolverResponses._
 
-import utils.Interruptible
 import scala.concurrent._
 import scala.concurrent.duration._
+import scala.concurrent.ExecutionContext.Implicits.global
 
-import ExecutionContext.Implicits.global
+trait PortfolioSolver extends Solver { self =>
+  import program._
+  import trees._
 
-class PortfolioSolver[S <: Solver with Interruptible](val sctx: SolverContext, val solvers: Seq[S])
-        extends Solver with NaiveAssumptionSolver {
+  final type SubSolver = Solver { val program: self.program.type }
 
+  val solvers: Seq[SubSolver]
   val name = "Pfolio"
 
-  protected var model = Model.empty
   protected var resultSolver: Option[Solver] = None
 
   override def getResultSolver = resultSolver
@@ -27,40 +27,29 @@ class PortfolioSolver[S <: Solver with Interruptible](val sctx: SolverContext, v
     solvers.foreach(_.assertCnstr(expression))
   }
 
-  override def assertVC(vc: VC): Unit = {
-    solvers.foreach(_.assertVC(vc))
-  }
-
   override def dbg(msg: => Any) = solvers foreach (_.dbg(msg))
 
-  def check: Option[Boolean] = {
-    model = Model.empty
 
+  private def genericCheck(config: Configuration)(f: SubSolver => config.Response[Model, Cores]): config.Response[Model, Cores] = {
     reporter.debug("Running portfolio check")
     // solving
-    val fs = solvers.map { s =>
+    val fs: Seq[Future[(SubSolver, config.Response[Model, Cores])]] = solvers.map { s =>
       Future {
         try {
-          val result = s.check
-          val model: Model = if (result == Some(true)) {
-            s.getModel
-          } else {
-            Model.empty
-          }
-          (s, result, model)
+          val result = f(s)
+          (s, result)
         } catch {
           case _: StackOverflowError =>
             reporter.warning("Stack Overflow while running solver.check()!")
-            (s, None, Model.empty)
+            (s, config.cast(Unknown))
         }
       }
     }
 
-    val result = Future.find(fs)(_._2.isDefined)
+    val result = Future.find(fs)(_._2 != Unknown)
 
     val res = Await.result(result, Duration.Inf) match {
-      case Some((s, r, m)) =>
-        model = m
+      case Some((s, r)) =>
         resultSolver = s.getResultSolver
         resultSolver.foreach { solv =>
           reporter.debug("Solved with "+solv)
@@ -70,13 +59,24 @@ class PortfolioSolver[S <: Solver with Interruptible](val sctx: SolverContext, v
       case None =>
         reporter.debug("No solver succeeded")
         //fs.foreach(f => println(f.value))
-        None
+        config.cast(Unknown)
     }
 
-    fs foreach { Await.ready(_, Duration.Inf) }
+    // TODO: Decide if we really want to wait for all the solvers.
+    // I understand we interrupt them, but what if one gets stuck
+    // fs foreach { Await.ready(_, Duration.Inf) }
     res
   }
 
+
+  def check(config: Configuration): config.Response[Model, Cores] = {
+    genericCheck(config)(subSolver => subSolver.check(config))
+  }
+
+  def checkAssumptions(config: Configuration)(assumptions: Set[Trees]): config.Response[Model, Cores] = {
+    genericCheck(config)(subSolver => subSolver.checkAssumptions(config)(assumptions))
+  }
+
   def push(): Unit = {
     solvers.foreach(_.push())
   }
@@ -86,12 +86,7 @@ class PortfolioSolver[S <: Solver with Interruptible](val sctx: SolverContext, v
   }
 
   def free() = {
-    solvers.foreach(_.free)
-    model = Model.empty
-  }
-
-  def getModel: Model = {
-    model
+    solvers.foreach(_.free())
   }
 
   def interrupt(): Unit = {
@@ -103,7 +98,6 @@ class PortfolioSolver[S <: Solver with Interruptible](val sctx: SolverContext, v
   }
 
   def reset() = {
-    solvers.foreach(_.reset)
-    model = Model.empty
+    solvers.foreach(_.reset())
   }
 }
diff --git a/src/main/scala/inox/solvers/combinators/PortfolioSolverFactory.scala b/src/main/scala/inox/solvers/combinators/PortfolioSolverFactory.scala
index 2c5f8df14..411240eca 100644
--- a/src/main/scala/inox/solvers/combinators/PortfolioSolverFactory.scala
+++ b/src/main/scala/inox/solvers/combinators/PortfolioSolverFactory.scala
@@ -1,26 +1,29 @@
 /* Copyright 2009-2016 EPFL, Lausanne */
 
-package leon
+package inox
 package solvers
 package combinators
 
 import scala.reflect.runtime.universe._
 
-class PortfolioSolverFactory[S <: Solver](ctx: SolverContext, sfs: Seq[SolverFactory[S]])
-  extends SolverFactory[PortfolioSolver[S] with TimeoutSolver] {
+trait PortfolioSolverFactory extends SolverFactory { self =>
 
-  def getNewSolver(): PortfolioSolver[S] with TimeoutSolver = {
-    new PortfolioSolver[S](ctx, sfs.map(_.getNewSolver())) with TimeoutSolver
-  }
+  final type PT = program.type
+  override type S = PortfolioSolver { val program: PT }
+  final type SF = SolverFactory { val program: PT }
+
+  val sfs: Seq[SF]
 
-  override def reclaim(s: Solver) = s match {
-    case ps: PortfolioSolver[_] =>
-      sfs.zip(ps.solvers).foreach { case (sf, s) =>
-        sf.reclaim(s)
-      }
+  def getNewSolver(): S = {
+    new PortfolioSolver {
+      val program: PT = self.program
+      val solvers = sfs map (_.getNewSolver())
+      val options: SolverOptions = solvers.head.options
+    }
+  }
 
-    case _ =>
-      ctx.context.reporter.error("Failed to reclaim a non-portfolio solver.")
+  override def reclaim(s: S) = sfs.zip(s.solvers).foreach { case (sf, s) =>
+    sf.reclaim(s)
   }
 
   val name = sfs.map(_.name).mkString("Pfolio(", ",", ")")
-- 
GitLab