diff --git a/src/main/scala/leon/codegen/runtime/ChooseEntryPoint.scala b/src/main/scala/leon/codegen/runtime/ChooseEntryPoint.scala index b74b46e8960f6a4eae63382464c3410f80440893..a79fe4a2d471f2a49297ac9dd4430b8d26e5d279 100644 --- a/src/main/scala/leon/codegen/runtime/ChooseEntryPoint.scala +++ b/src/main/scala/leon/codegen/runtime/ChooseEntryPoint.scala @@ -7,12 +7,12 @@ import utils._ import purescala.Expressions._ import purescala.ExprOps.valuateWithModel import purescala.Constructors._ -import solvers.TimeoutSolver -import solvers.z3._ +import solvers.SolverFactory import java.util.WeakHashMap import java.lang.ref.WeakReference import scala.collection.mutable.{HashMap => MutableMap} +import scala.concurrent.duration._ import codegen.CompilationUnit @@ -79,7 +79,7 @@ object ChooseEntryPoint { } else { val tStart = System.currentTimeMillis - val solver = (new FairZ3Solver(ctx, program) with TimeoutSolver).setTimeout(10000L) + val solver = SolverFactory.default(ctx, program).withTimeout(10.second).getNewSolver() val inputsMap = (p.as zip inputs).map { case (id, v) => diff --git a/src/main/scala/leon/repair/Repairman.scala b/src/main/scala/leon/repair/Repairman.scala index bb7c2ef9acd8e366e95a5fcaa6bba0e0954aa14d..5fbfc60a79f48fb18dde2f2336e9473ef1b8b76c 100644 --- a/src/main/scala/leon/repair/Repairman.scala +++ b/src/main/scala/leon/repair/Repairman.scala @@ -25,6 +25,8 @@ import rules._ import graph.DotGenerator import leon.utils.ASCIIHelpers.title +import scala.concurrent.duration._ + class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeoutMs: Option[Long], repairTimeoutMs: Option[Long]) { val reporter = ctx.reporter @@ -469,7 +471,7 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout None } else { val diff = and(p.pc, not(Equals(s1, s2))) - val solver = (new FairZ3Solver(ctx, program) with TimeoutSolver).setTimeout(1000) + val solver = SolverFactory.default(ctx, program).withTimeout(1.second).getNewSolver() solver.assertCnstr(diff) solver.check match { diff --git a/src/main/scala/leon/solvers/SolverFactory.scala b/src/main/scala/leon/solvers/SolverFactory.scala index 4e53b8b9e00b326645bb68daf105f8895afaf671..2b838b68bb1e92cd442794c8e19532b910d97a42 100644 --- a/src/main/scala/leon/solvers/SolverFactory.scala +++ b/src/main/scala/leon/solvers/SolverFactory.scala @@ -3,6 +3,10 @@ package leon package solvers +import combinators._ +import z3._ +import smtlib._ + import purescala.Definitions._ import scala.reflect.runtime.universe._ @@ -40,10 +44,6 @@ object SolverFactory { } def getFromName(ctx: LeonContext, program: Program)(names: String*): SolverFactory[TimeoutSolver] = { - import combinators._ - import z3._ - import smtlib._ - def getSolver(name: String): SolverFactory[TimeoutSolver] = name match { case "fairz3" => @@ -93,4 +93,16 @@ object SolverFactory { } + // Solver qualifiers that get used internally: + + // Fast solver used by simplifiactions, to discharge simple tautologies + def uninterpreted(ctx: LeonContext, program: Program): SolverFactory[TimeoutSolver] = { + SolverFactory(() => new SMTLIBSolver(ctx, program) with SMTLIBZ3Target with TimeoutSolver) + } + + // Full featured solver used by default + def default(ctx: LeonContext, program: Program): SolverFactory[TimeoutSolver] = { + getFromName(ctx, program)("fairz3") + } + } diff --git a/src/main/scala/leon/synthesis/SynthesisContext.scala b/src/main/scala/leon/synthesis/SynthesisContext.scala index d9b9a60394ad61d45ec5bf45bd25e3cd4ba65223..920901e4feb34855150d748e3a9cfb180febbb86 100644 --- a/src/main/scala/leon/synthesis/SynthesisContext.scala +++ b/src/main/scala/leon/synthesis/SynthesisContext.scala @@ -22,36 +22,20 @@ case class SynthesisContext( val rules = settings.rules - val allSolvers: Map[String, SolverFactory[SynthesisContext.SynthesisSolver]] = Map( - "fairz3" -> SolverFactory(() => new FairZ3Solver(context, program) with TimeoutAssumptionSolver), - "enum" -> SolverFactory(() => new EnumerationSolver(context, program) with TimeoutAssumptionSolver) - ) + val solverFactory = SolverFactory.getFromSettings(context, program) - val solversToUse = allSolvers.filterKeys(settings.selectedSolvers) - - val solverFactory: SolverFactory[SynthesisContext.SynthesisSolver] = solversToUse.values.toSeq match { - case Seq() => - reporter.fatalError("No solver selected. Aborting") - case Seq(value) => - value - case more => - SolverFactory( () => new PortfolioSolverSynth(context, more) with TimeoutAssumptionSolver ) - } - - def newSolver: SynthesisContext.SynthesisSolver = { + def newSolver = { solverFactory.getNewSolver() } - def newFastSolver: SynthesisContext.SynthesisSolver = { - new UninterpretedZ3Solver(context, program) with TimeoutAssumptionSolver - } - - val fastSolverFactory = SolverFactory(() => newFastSolver) + val fastSolverFactory = SolverFactory.uninterpreted(context, program) + def newFastSolver = { + fastSolverFactory.getNewSolver() + } } object SynthesisContext { - type SynthesisSolver = TimeoutAssumptionSolver with IncrementalSolver def fromSynthesizer(synth: Synthesizer) = { SynthesisContext( diff --git a/src/main/scala/leon/synthesis/SynthesisSettings.scala b/src/main/scala/leon/synthesis/SynthesisSettings.scala index 9a52e58d68319f0c1255a67d326025a9a0321c86..9d227bdb611f2ca44eb70a95ce52bc506712e160 100644 --- a/src/main/scala/leon/synthesis/SynthesisSettings.scala +++ b/src/main/scala/leon/synthesis/SynthesisSettings.scala @@ -12,7 +12,6 @@ case class SynthesisSettings( rules: Seq[Rule] = Rules.all, manualSearch: Option[String] = None, searchBound: Option[Int] = None, - selectedSolvers: Set[String] = Set("fairz3"), functions: Option[Set[String]] = None, functionsToIgnore: Set[FunDef] = Set(), diff --git a/src/main/scala/leon/synthesis/rules/CEGISLike.scala b/src/main/scala/leon/synthesis/rules/CEGISLike.scala index fce0363fb8a1d62cacb3a31e5c47f8cc0fb17614..8c5a88bf054bf841bfa4500af49d92e09a0b582c 100644 --- a/src/main/scala/leon/synthesis/rules/CEGISLike.scala +++ b/src/main/scala/leon/synthesis/rules/CEGISLike.scala @@ -392,7 +392,7 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { val cnstr = and(p.pc, letTuple(p.xs, sol, Not(p.phi))) //println("Solving for: "+cnstr) - val solver = (new FairZ3Solver(ctx, prog) with TimeoutSolver).setTimeout(cexSolverTo) + val solver = SolverFactory.default(ctx, prog).withTimeout(cexSolverTo).getNewSolver() try { solver.assertCnstr(cnstr) solver.check match { @@ -658,7 +658,7 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { } def solveForTentativeProgram(): Option[Option[Set[Identifier]]] = { - val solver = (new FairZ3Solver(ctx, programCTree) with TimeoutSolver).setTimeout(exSolverTo) + val solver = SolverFactory.default(ctx, programCTree).withTimeout(exSolverTo).getNewSolver() val cnstr = FunctionInvocation(phiFd.typed, phiFd.params.map(_.id.toVariable)) //debugCExpr(cTree) @@ -735,7 +735,7 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { } def solveForCounterExample(bs: Set[Identifier]): Option[Option[Seq[Expr]]] = { - val solver = (new FairZ3Solver(ctx, programCTree) with TimeoutSolver).setTimeout(cexSolverTo) + val solver = SolverFactory.default(ctx, programCTree).withTimeout(cexSolverTo).getNewSolver() val cnstr = FunctionInvocation(phiFd.typed, phiFd.params.map(_.id.toVariable)) val fixedBs = finiteArray(bsOrdered.map(b => BooleanLiteral(bs(b))), None, BooleanType) diff --git a/src/main/scala/leon/termination/Processor.scala b/src/main/scala/leon/termination/Processor.scala index 87637e316aca4d35581485402745be1b9ecb08a3..b6c6972f9925ad5389b99cdad6689ace103c2fa3 100644 --- a/src/main/scala/leon/termination/Processor.scala +++ b/src/main/scala/leon/termination/Processor.scala @@ -7,6 +7,8 @@ import purescala.Expressions._ import purescala.Common._ import purescala.Definitions._ +import scala.concurrent.duration._ + import leon.solvers._ import leon.solvers.z3._ @@ -35,15 +37,15 @@ trait Solvable extends Processor { val checker : TerminationChecker with Strengthener with StructuralSize - private val solver: SolverFactory[Solver] = SolverFactory(() => { + private val solver: SolverFactory[Solver] = { val program : Program = checker.program val context : LeonContext = checker.context val sizeModule : ModuleDef = ModuleDef(FreshIdentifier("$size"), checker.defs.toSeq, false) val sizeUnit : UnitDef = UnitDef(FreshIdentifier("$size"),Seq(sizeModule)) val newProgram : Program = program.copy( units = sizeUnit :: program.units) - (new FairZ3Solver(context, newProgram) with TimeoutAssumptionSolver).setTimeout(500L) - }) + SolverFactory.default(context, newProgram).withTimeout(500.millisecond) + } type Solution = (Option[Boolean], Map[Identifier, Expr]) diff --git a/src/main/scala/leon/utils/Simplifiers.scala b/src/main/scala/leon/utils/Simplifiers.scala index 2426539ec2b7f688ee0e480194b3088f02ada290..82fa58a722ea54fae129e8206074c0db95ddd8ee 100644 --- a/src/main/scala/leon/utils/Simplifiers.scala +++ b/src/main/scala/leon/utils/Simplifiers.scala @@ -7,18 +7,17 @@ import purescala.Definitions._ import purescala.Expressions._ import purescala.ExprOps._ import purescala.ScopeSimplifier -import solvers.z3.UninterpretedZ3Solver import solvers._ object Simplifiers { def bestEffort(ctx: LeonContext, p: Program)(e: Expr): Expr = { - val uninterpretedZ3 = SolverFactory(() => new UninterpretedZ3Solver(ctx, p)) + val solver = SolverFactory.uninterpreted(ctx, p) val simplifiers = List[Expr => Expr]( - simplifyTautologies(uninterpretedZ3)(_), + simplifyTautologies(solver)(_), simplifyLets, - simplifyPaths(uninterpretedZ3)(_), + simplifyPaths(solver)(_), simplifyArithmetic, evalGround(ctx, p), normalizeExpression @@ -38,10 +37,10 @@ object Simplifiers { } def namePreservingBestEffort(ctx: LeonContext, p: Program)(e: Expr): Expr = { - val uninterpretedZ3 = SolverFactory(() => new UninterpretedZ3Solver(ctx, p)) + val solver = SolverFactory.uninterpreted(ctx, p) val simplifiers = List[Expr => Expr]( - simplifyTautologies(uninterpretedZ3)(_), + simplifyTautologies(solver)(_), simplifyArithmetic, evalGround(ctx, p), normalizeExpression diff --git a/src/test/scala/leon/test/synthesis/SynthesisSuite.scala b/src/test/scala/leon/test/synthesis/SynthesisSuite.scala index c043ac0fa5026d05ff661b6bdb0b53ad1c48dbaf..b8ef5681f52ea8d138d5f76481d94bc365cdf9e2 100644 --- a/src/test/scala/leon/test/synthesis/SynthesisSuite.scala +++ b/src/test/scala/leon/test/synthesis/SynthesisSuite.scala @@ -81,9 +81,9 @@ class SynthesisSuite extends LeonTestSuite { } - def forProgram(title: String, opts: SynthesisSettings = SynthesisSettings())(content: String)(strats: PartialFunction[String, SynStrat]) { + def forProgram(title: String, opts: Seq[LeonOption[Any]] = Nil)(content: String)(strats: PartialFunction[String, SynStrat]) { test(f"Synthesizing ${nextInt()}%3d: [$title]") { - val ctx = testContext + val ctx = testContext.copy(options = opts ++ testContext.options) val pipeline = leon.utils.TemporaryInputPhase andThen leon.frontends.scalac.ExtractionPhase andThen PreprocessingPhase andThen SynthesisProblemExtractionPhase @@ -92,9 +92,12 @@ class SynthesisSuite extends LeonTestSuite { for ((f,cis) <- results; ci <- cis) { info(f"${ci.fd.id.toString}%-20s") - val sctx = SynthesisContext(ctx, opts, ci.fd, program) + val sctx = SynthesisContext(ctx, + SynthesisSettings(), + ci.fd, + program) - val p = ci.problem + val p = ci.problem if (strats.isDefinedAt(f.id.name)) { val search = new TestSearch(ctx, ci, p, strats(f.id.name)) @@ -109,7 +112,7 @@ class SynthesisSuite extends LeonTestSuite { } } - forProgram("Ground Enum", SynthesisSettings(selectedSolvers = Set("enum")))( + forProgram("Ground Enum", Seq(LeonOption(SharedOptions.optSelectedSolvers)(Set("enum"))))( """ import leon.annotation._ import leon.lang._