diff --git a/cp-demo/FirstClassConstraints.scala b/cp-demo/FirstClassConstraints.scala index ed8285df6925419ad88d47afb95200b930c5bc62..8aa77372e1fff11504ac18f40c674aaba2bdbdc4 100644 --- a/cp-demo/FirstClassConstraints.scala +++ b/cp-demo/FirstClassConstraints.scala @@ -44,7 +44,9 @@ object FirstClassConstraints { // println("has size 5: " + hasSize(5).expr) - println(hasSize(5).solve) + // println(hasSize(5).solve) + val p : Term1[Int,Boolean] = ((x: Int) => x > 5) + println(p.solve) // for (s <- hasSize(3).findAll) // println(s) } diff --git a/cp-demo/RedBlackTree.scala b/cp-demo/RedBlackTree.scala index f4b7edf230f0b1045aca9e70402fed854e0cb695..ec70cf978ea26c2d600dbbd92ed88b6a0dcb78d3 100644 --- a/cp-demo/RedBlackTree.scala +++ b/cp-demo/RedBlackTree.scala @@ -89,7 +89,7 @@ object RedBlackTree { val defaultBound = 3 val bound = if (args.isEmpty) defaultBound else args(0).toInt - enumerateAllUpTo(bound) + // enumerateAllUpTo(bound) val solutionSet = scala.collection.mutable.Set[Tree]() println("Fixing size of trees to " + (bound)) diff --git a/eval/cp/scripts/run-cp-evaluation b/eval/cp/scripts/run-cp-evaluation index 139df7cdf6463cd9949dc6933f12a1db6054fc9a..5953844c3417c07e39bcda25b085163a360bef60 100755 --- a/eval/cp/scripts/run-cp-evaluation +++ b/eval/cp/scripts/run-cp-evaluation @@ -3,7 +3,6 @@ cd ../../.. ts=`date +%F-%R` -evalFolder="eval/cp/data" demoFolder="cp-demo" #classes=( "RedBlackTree" "SortedList" ) @@ -18,6 +17,8 @@ class=${1} base=${2} limit=${3} +evalFolder="eval/cp/data/${ts}-${class}" + mkdir -p ${evalFolder} evalFileBase=${evalFolder}/${class}-${ts}-CAV @@ -31,3 +32,17 @@ do ./generate-graph ../../../${currentFile} cd ../../.. done + +evalFileBase=${evalFolder}/${class}-${ts}-CAV-scalaEval +./cp CAV scalaEval ${demoFolder}/${class}.scala || (echo "Could not compile..." && exit 1) + +for (( i=${base}; i<=${limit}; i++ )) +do + currentFile=${evalFileBase}-${i} + ./cp-runner ${class} $i | tee -a ${currentFile} + cd eval/cp/scripts + ./generate-graph ../../../${currentFile} + cd ../../.. +done + +mv eval/cp/graphs/${class}-${ts}-* ${evalFolder} diff --git a/src/cp/CPPlugin.scala b/src/cp/CPPlugin.scala index 6c0db086f8ef3a8fac3382e1782b092e8c835e39..3c8a1441859de0069129c7f22064a1ce3341ef29 100644 --- a/src/cp/CPPlugin.scala +++ b/src/cp/CPPlugin.scala @@ -27,7 +27,8 @@ class CPPlugin(val global: Global) extends Plugin { " -P:constraint-programming:PLDI PLDI 2011 settings. Now frozen. Not completely functional. See CAV." + "\n" + " -P:constraint-programming:CAV CAV 2011 settings. In progress." + "\n" + " -P:constraint-programming:prune (with CAV) Use additional SMT queries to rule out some unrollings." + "\n" + - " -P:constraint-programming:cores (with CAV) Use UNSAT cores in the unrolling/refinement step." + " -P:constraint-programming:cores (with CAV) Use UNSAT cores in the unrolling/refinement step." + "\n" + + " -P:constraint-programming:scalaEval (with CAV) Use functions stored in constraints to evaluate models." ) /** Processes the command-line options. */ @@ -46,6 +47,7 @@ class CPPlugin(val global: Global) extends Plugin { case "CAV" => { purescala.Settings.experimental = true; purescala.Settings.useInstantiator = false; purescala.Settings.useFairInstantiator = true; purescala.Settings.useBAPA = false; purescala.Settings.zeroInlining = true } case "prune" => purescala.Settings.pruneBranches = true case "cores" => purescala.Settings.useCores = true + case "scalaEval" => cp.Settings.useScalaEvaluator = true case s if s.startsWith("unrolling=") => purescala.Settings.unrollingLevel = try { s.substring("unrolling=".length, s.length).toInt } catch { case _ => 0 } case s if s.startsWith("functions=") => purescala.Settings.functionsToAnalyse = Set(splitList(s.substring("functions=".length, s.length)): _*) case s if s.startsWith("extensions=") => purescala.Settings.extensionNames = splitList(s.substring("extensions=".length, s.length)) diff --git a/src/cp/Converter.scala b/src/cp/Converter.scala index 05c14b73adc9e4ef3c870b67b2910996500305aa..ae68a22ad362b493e1ba869463330f7fa4758b42 100644 --- a/src/cp/Converter.scala +++ b/src/cp/Converter.scala @@ -4,7 +4,7 @@ import purescala.Trees._ /** A converter has functions for converting FunCheck expressions into Scala * values */ -class Converter(expr2scala : (Expr => Any)) { +class Converter(val expr2scala : (Expr => Any)) { def exprSeq2scala1[T1](exprs : Seq[Expr]) : (T1) = (expr2scala(exprs(0)).asInstanceOf[T1]) diff --git a/src/cp/RuntimeMethods.scala b/src/cp/RuntimeMethods.scala index 2905bbf25bcd9992f9927236d2537cd5bbf35887..a3a820860400a1bacbb8bbad787445e82b040577 100644 --- a/src/cp/RuntimeMethods.scala +++ b/src/cp/RuntimeMethods.scala @@ -105,6 +105,8 @@ object RuntimeMethods { purescala.Settings.useCores = recovered.useCores purescala.Settings.pruneBranches = recovered.pruneBranches purescala.Settings.solverTimeout = recovered.solverTimeout + + Settings.useScalaEvaluator = recovered.useScalaEvaluator } def inputVar(inputVarList : List[Variable], varName : String) : Variable = { diff --git a/src/cp/RuntimeSettings.scala b/src/cp/RuntimeSettings.scala index 205d85593befb834d8019b90347fa6818c772b9d..813ebb88470e61db972ff62f307bc1a20d0b91f5 100644 --- a/src/cp/RuntimeSettings.scala +++ b/src/cp/RuntimeSettings.scala @@ -12,4 +12,10 @@ package cp var useCores : Boolean = purescala.Settings.useCores var pruneBranches : Boolean = purescala.Settings.pruneBranches var solverTimeout : Option[Int] = purescala.Settings.solverTimeout + + var useScalaEvaluator : Boolean = Settings.useScalaEvaluator +} + +object Settings { + var useScalaEvaluator : Boolean = false } diff --git a/src/cp/Terms.scala b/src/cp/Terms.scala index f3752ff4264d6e57a18e93edfdbddcf8b96e9bcd..e87074319f5eee28086aeb5045ca7ad724752372 100644 --- a/src/cp/Terms.scala +++ b/src/cp/Terms.scala @@ -16,12 +16,13 @@ object Terms { /** The converting function defines how Expr values returned by the solver * will be converted back to Scala values */ val convertingFunction : (Seq[Expr] => T) + val evaluator : (Seq[Expr]) => R - def solve(implicit asBoolean: (R) => Boolean) : T = { - convertingFunction(solveExprSeq(this)) + def solve(implicit asConstraint: (Term[T,R]) => Term[T,Boolean]) : T = { + convertingFunction(solveExprSeq(asConstraint(this))) } - def find(implicit asBoolean: (R) => Boolean) : Option[T] = { + def find(implicit asConstraint: (Term[T,R]) => Term[T,Boolean]) : Option[T] = { try { Some(this.solve) } catch { @@ -30,8 +31,8 @@ object Terms { } } - def findAll(implicit asBoolean: (R) => Boolean) : Iterator[T] = { - findAllExprSeq(this).map(convertingFunction(_)) + def findAll(implicit asConstraint: (Term[T,R]) => Term[T,Boolean]) : Iterator[T] = { + findAllExprSeq(asConstraint(this)).map(convertingFunction(_)) } } @@ -118,6 +119,7 @@ object Terms { val convertingFunction = converterOf(this).exprSeq2scala1[T1] _ type t2c = (Term1[T1,R]) => Term1[T1,Boolean] val scalaFunction : (T1) => R + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(converter.expr2scala(s(0)).asInstanceOf[T1]) override def apply(x_0 : T1) : R = scalaFunction(x_0) @@ -184,6 +186,7 @@ object Terms { val convertingFunction = converterOf(this).exprSeq2scala2[T1,T2] _ type t2c = (Term2[T1,T2,R]) => Term2[T1,T2,Boolean] val scalaFunction : (T1,T2) => R + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(converter.expr2scala(s(0)).asInstanceOf[T1],converter.expr2scala(s(1)).asInstanceOf[T2]) override def apply(x_0 : T1, x_1 : T2) : R = scalaFunction(x_0, x_1) @@ -285,6 +288,7 @@ object Terms { val convertingFunction = converterOf(this).exprSeq2scala3[T1,T2,T3] _ type t2c = (Term3[T1,T2,T3,R]) => Term3[T1,T2,T3,Boolean] val scalaFunction : (T1,T2,T3) => R + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(converter.expr2scala(s(0)).asInstanceOf[T1],converter.expr2scala(s(1)).asInstanceOf[T2],converter.expr2scala(s(2)).asInstanceOf[T3]) override def apply(x_0 : T1, x_1 : T2, x_2 : T3) : R = scalaFunction(x_0, x_1, x_2) @@ -411,6 +415,7 @@ object Terms { val convertingFunction = converterOf(this).exprSeq2scala4[T1,T2,T3,T4] _ type t2c = (Term4[T1,T2,T3,T4,R]) => Term4[T1,T2,T3,T4,Boolean] val scalaFunction : (T1,T2,T3,T4) => R + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(converter.expr2scala(s(0)).asInstanceOf[T1],converter.expr2scala(s(1)).asInstanceOf[T2],converter.expr2scala(s(2)).asInstanceOf[T3],converter.expr2scala(s(3)).asInstanceOf[T4]) override def apply(x_0 : T1, x_1 : T2, x_2 : T3, x_3 : T4) : R = scalaFunction(x_0, x_1, x_2, x_3) @@ -552,6 +557,7 @@ object Terms { val convertingFunction = converterOf(this).exprSeq2scala5[T1,T2,T3,T4,T5] _ type t2c = (Term5[T1,T2,T3,T4,T5,R]) => Term5[T1,T2,T3,T4,T5,Boolean] val scalaFunction : (T1,T2,T3,T4,T5) => R + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(converter.expr2scala(s(0)).asInstanceOf[T1],converter.expr2scala(s(1)).asInstanceOf[T2],converter.expr2scala(s(2)).asInstanceOf[T3],converter.expr2scala(s(3)).asInstanceOf[T4],converter.expr2scala(s(4)).asInstanceOf[T5]) override def apply(x_0 : T1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5) : R = scalaFunction(x_0, x_1, x_2, x_3, x_4) @@ -698,6 +704,7 @@ object Terms { val convertingFunction = converterOf(this).exprSeq2scala6[T1,T2,T3,T4,T5,T6] _ type t2c = (Term6[T1,T2,T3,T4,T5,T6,R]) => Term6[T1,T2,T3,T4,T5,T6,Boolean] val scalaFunction : (T1,T2,T3,T4,T5,T6) => R + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(converter.expr2scala(s(0)).asInstanceOf[T1],converter.expr2scala(s(1)).asInstanceOf[T2],converter.expr2scala(s(2)).asInstanceOf[T3],converter.expr2scala(s(3)).asInstanceOf[T4],converter.expr2scala(s(4)).asInstanceOf[T5],converter.expr2scala(s(5)).asInstanceOf[T6]) override def apply(x_0 : T1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5, x_5 : T6) : R = scalaFunction(x_0, x_1, x_2, x_3, x_4, x_5) @@ -839,6 +846,7 @@ object Terms { val convertingFunction = converterOf(this).exprSeq2scala7[T1,T2,T3,T4,T5,T6,T7] _ type t2c = (Term7[T1,T2,T3,T4,T5,T6,T7,R]) => Term7[T1,T2,T3,T4,T5,T6,T7,Boolean] val scalaFunction : (T1,T2,T3,T4,T5,T6,T7) => R + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(converter.expr2scala(s(0)).asInstanceOf[T1],converter.expr2scala(s(1)).asInstanceOf[T2],converter.expr2scala(s(2)).asInstanceOf[T3],converter.expr2scala(s(3)).asInstanceOf[T4],converter.expr2scala(s(4)).asInstanceOf[T5],converter.expr2scala(s(5)).asInstanceOf[T6],converter.expr2scala(s(6)).asInstanceOf[T7]) override def apply(x_0 : T1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5, x_5 : T6, x_6 : T7) : R = scalaFunction(x_0, x_1, x_2, x_3, x_4, x_5, x_6) @@ -965,6 +973,7 @@ object Terms { val convertingFunction = converterOf(this).exprSeq2scala8[T1,T2,T3,T4,T5,T6,T7,T8] _ type t2c = (Term8[T1,T2,T3,T4,T5,T6,T7,T8,R]) => Term8[T1,T2,T3,T4,T5,T6,T7,T8,Boolean] val scalaFunction : (T1,T2,T3,T4,T5,T6,T7,T8) => R + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(converter.expr2scala(s(0)).asInstanceOf[T1],converter.expr2scala(s(1)).asInstanceOf[T2],converter.expr2scala(s(2)).asInstanceOf[T3],converter.expr2scala(s(3)).asInstanceOf[T4],converter.expr2scala(s(4)).asInstanceOf[T5],converter.expr2scala(s(5)).asInstanceOf[T6],converter.expr2scala(s(6)).asInstanceOf[T7],converter.expr2scala(s(7)).asInstanceOf[T8]) override def apply(x_0 : T1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5, x_5 : T6, x_6 : T7, x_7 : T8) : R = scalaFunction(x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7) @@ -1066,6 +1075,7 @@ object Terms { val convertingFunction = converterOf(this).exprSeq2scala9[T1,T2,T3,T4,T5,T6,T7,T8,T9] _ type t2c = (Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,R]) => Term9[T1,T2,T3,T4,T5,T6,T7,T8,T9,Boolean] val scalaFunction : (T1,T2,T3,T4,T5,T6,T7,T8,T9) => R + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(converter.expr2scala(s(0)).asInstanceOf[T1],converter.expr2scala(s(1)).asInstanceOf[T2],converter.expr2scala(s(2)).asInstanceOf[T3],converter.expr2scala(s(3)).asInstanceOf[T4],converter.expr2scala(s(4)).asInstanceOf[T5],converter.expr2scala(s(5)).asInstanceOf[T6],converter.expr2scala(s(6)).asInstanceOf[T7],converter.expr2scala(s(7)).asInstanceOf[T8],converter.expr2scala(s(8)).asInstanceOf[T9]) override def apply(x_0 : T1, x_1 : T2, x_2 : T3, x_3 : T4, x_4 : T5, x_5 : T6, x_6 : T7, x_7 : T8, x_8 : T9) : R = scalaFunction(x_0, x_1, x_2, x_3, x_4, x_5, x_6, x_7, x_8) @@ -1351,14 +1361,20 @@ object Terms { case None => simplestValue(varId.getType) } + private def evaluator(constraint : Term[_,Boolean], ids : Seq[Identifier]) : Option[(Map[Identifier,Expr])=>Boolean] = { + if (cp.Settings.useScalaEvaluator) { + Some((m : Map[Identifier,Expr]) => constraint.evaluator(ids.map(modelValue(_, m)))) + } else None + } + /** Return a solution as a sequence of expressions */ - private def solveExprSeq(c : Term[_,_]) : Seq[Expr] = { - val constraint = c.asInstanceOf[Constraint[_]] + private def solveExprSeq(constraint : Term[_,Boolean]) : Seq[Expr] = { val solver = newSolver(programOf(constraint)) val (freshOutputIDs, expr) = combineConstraint(constraint) - val (outcome, model) = solver.restartAndDecideWithModel(expr, false) + solver.restartZ3 + val (outcome, model) = solver.decideWithModel(expr, false, evaluator(constraint, freshOutputIDs)) outcome match { case Some(false) => @@ -1385,12 +1401,11 @@ object Terms { } /** Return an iterator of solutions as sequences of expressions */ - private def findAllExprSeq(c : Term[_,_]) : Iterator[Seq[Expr]] = { - val constraint = c.asInstanceOf[Constraint[_]] + private def findAllExprSeq(constraint : Term[_,Boolean]) : Iterator[Seq[Expr]] = { val program = programOf(constraint) val (freshOutputIDs, expr) = combineConstraint(constraint) - val modelIterator = solutionsIterator(program, expr, freshOutputIDs.toSet) + val modelIterator = solutionsIterator(program, expr, freshOutputIDs, evaluator(constraint, freshOutputIDs)) val exprIterator = modelIterator.map(model => freshOutputIDs.map(id => model(id))) exprIterator @@ -1419,7 +1434,7 @@ object Terms { val minValue = minimizingModelAndValue(program, toCheck, outputVars, minExpr)._2 val minValConstraint = And(expr, Equals(minExpr, IntLiteral(minValue))) - val minValModelIterator = solutionsIterator(program, minValConstraint, outputVars.toSet) + val minValModelIterator = solutionsIterator(program, minValConstraint, outputVars) val minValExprIterator = minValModelIterator.map(model => outputVars.map(id => model(id))) minValExprIterator ++ findAllMinimizingExprSeq(program, expr, outputVars, minExpr, Some(minValue)) @@ -1447,7 +1462,8 @@ object Terms { // println(" hi : " + hi) // println val toCheck = expr :: LessEquals(minExpr, IntLiteral(pivot)) :: Nil - val (outcome, model) = solver.restartAndDecideWithModel(And(toCheck), false) + solver.restartZ3 + val (outcome, model) = solver.decideWithModel(And(toCheck), false) outcome match { case Some(false) => @@ -1484,7 +1500,8 @@ object Terms { // We declare a variable to hold the value to minimize: val minExprID = purescala.Common.FreshIdentifier("minExpr").setType(purescala.TypeTrees.Int32Type) - solver.restartAndDecideWithModel(And(expr :: Equals(minExpr, Variable(minExprID)) :: Nil), false) match { + solver.restartZ3 + solver.decideWithModel(And(expr :: Equals(minExpr, Variable(minExprID)) :: Nil), false) match { case (Some(false), model) => // there is a satisfying assignment val minExprVal = modelValue(minExprID, model) match { @@ -1501,7 +1518,7 @@ object Terms { } } /** Returns an iterator of interpretations for each identifier in the specified set */ - private def solutionsIterator(program : Program, predicate : Expr, outputVariables : Set[Identifier]) : Iterator[Map[Identifier, Expr]] = { + private def solutionsIterator(program : Program, predicate : Expr, outputVariables : Seq[Identifier], evaluator : Option[(Map[Identifier,Expr]) => Boolean] = None) : Iterator[Map[Identifier, Expr]] = { val solver = newSolver(program) solver.restartZ3 @@ -1514,12 +1531,13 @@ object Terms { var addedNegations: Expr = BooleanLiteral(true) var toCheck: Expr = predicate + var toUseAsEvaluator : Option[(Map[Identifier,Expr]) => Boolean] = evaluator override def hasNext : Boolean = nextModel match { case None => // Check whether there are any more models val stopwatch = new Stopwatch("hasNext", false).start - val (outcome, model) = solver.decideWithModel(toCheck, false) + val (outcome, model) = solver.decideWithModel(toCheck, false, toUseAsEvaluator) stopwatch.stop stopwatch.writeToSummary val toReturn = (outcome match { @@ -1535,8 +1553,9 @@ object Terms { } } nextModel = Some(Some(completeModel)) - val newModelEqualities = And(outputVariables.map(ov => Equals(Variable(ov), completeModel(ov))).toList) + val newModelEqualities = And(outputVariables.map(ov => Equals(Variable(ov), completeModel(ov)))) toCheck = negate(newModelEqualities) + toUseAsEvaluator = toUseAsEvaluator.map(e => ((m : Map[Identifier,Expr]) => e(m) && !m.forall{ case (k,v) => completeModel.get(k) == Some(v) })) true case Some(true) => // there are definitely no more solutions @@ -1572,8 +1591,9 @@ object Terms { } } - val newModelEqualities = And(outputVariables.map(ov => Equals(Variable(ov), completeModel(ov))).toList) + val newModelEqualities = And(outputVariables.map(ov => Equals(Variable(ov), completeModel(ov)))) toCheck = negate(newModelEqualities) + toUseAsEvaluator = toUseAsEvaluator.map(e => ((m : Map[Identifier,Expr]) => e(m) && !m.forall{ case (k,v) => completeModel.get(k) == Some(v) })) completeModel case Some(true) => // Definitely no more solutions diff --git a/src/cp/Utils.scala b/src/cp/Utils.scala index d372744289f4cb1e89073db9ac354605a22d7aa7..a362eff4b4d25db2579e4603e2e2dff627348cb7 100644 --- a/src/cp/Utils.scala +++ b/src/cp/Utils.scala @@ -59,11 +59,13 @@ object Utils { val (applyParams, applyArgs) = traitArgParams.zipWithIndex.map{ case (p, i) => ("x_%d : %s" format (i, p), "x_%d" format (i)) }.unzip + val evaluatorArgs = traitArgParams.zipWithIndex.map{ case (p, i) => "converter.expr2scala(s(%d)).asInstanceOf[%s]" format (i, p) } val termTraitString = """sealed trait %s extends Term[%s,%s] with Function%d[%s] { val convertingFunction = converterOf(this).exprSeq2scala%d[%s] _ type t2c = (%s) => %s val scalaFunction : %s => %s + val evaluator : (Seq[Expr]) => R = (s : Seq[Expr]) => scalaFunction(%s) override def apply(%s) : R = scalaFunction(%s) @@ -76,7 +78,13 @@ object Utils { %s %s -}""" format (traitName, termClassParamTuple, "R", arity, traitParams.mkString(","), arity, traitArgParamsString, traitName, booleanTraitName, termClassParamTuple, "R", applyParams.mkString(", "), applyArgs.mkString(", "), indent(orMethod), indent(andMethod), indent(notMethod), indent(minimizingMethod), indent(composeMethods)) +}""" format (traitName, termClassParamTuple, "R", arity, traitParams.mkString(","), + arity, traitArgParamsString, + traitName, booleanTraitName, + termClassParamTuple, "R", + evaluatorArgs.mkString(","), + applyParams.mkString(", "), applyArgs.mkString(", "), + indent(orMethod), indent(andMethod), indent(notMethod), indent(minimizingMethod), indent(composeMethods)) termTraitString } diff --git a/src/purescala/Evaluator.scala b/src/purescala/Evaluator.scala index c624b4f9b01736f9ba76f7b8cadc0ced64568277..3a9ab97acf8d4cb6948ae69c1a83a599bc2e6f48 100644 --- a/src/purescala/Evaluator.scala +++ b/src/purescala/Evaluator.scala @@ -25,7 +25,7 @@ object Evaluator { val finalResult = None } - def eval(context: EvaluationContext, expression: Expr, maxSteps: Int=500000) : EvaluationResult = { + def eval(context: EvaluationContext, expression: Expr, evaluator: Option[(EvaluationContext)=>Boolean], maxSteps: Int=500000) : EvaluationResult = { case class RuntimeErrorEx(msg: String) extends Exception case class InfiniteComputationEx() extends Exception case class TypeErrorEx(typeError: TypeError) extends Exception @@ -240,12 +240,21 @@ object Evaluator { } } - try { - OK(rec(context, expression)) - } catch { - case RuntimeErrorEx(msg) => RuntimeError(msg) - case InfiniteComputationEx() => InfiniteComputation() - case TypeErrorEx(te) => te + evaluator match { + case Some(evalFun) => + try { + OK(BooleanLiteral(evalFun(context))) + } catch { + case e: Exception => RuntimeError(e.getMessage) + } + case None => + try { + OK(rec(context, expression)) + } catch { + case RuntimeErrorEx(msg) => RuntimeError(msg) + case InfiniteComputationEx() => InfiniteComputation() + case TypeErrorEx(te) => te + } } } diff --git a/src/purescala/FairZ3Solver.scala b/src/purescala/FairZ3Solver.scala index 6371d0a309372832a1270b958ffe5e1e43f263ea..37d8d2f36d026844e36300d4e247ee64f827f96e 100644 --- a/src/purescala/FairZ3Solver.scala +++ b/src/purescala/FairZ3Solver.scala @@ -304,12 +304,7 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac decideWithModel(vc, forValidity)._1 } - def restartAndDecideWithModel(vc: Expr, forValidity: Boolean): (Option[Boolean], Map[Identifier,Expr]) = { - restartZ3 - decideWithModel(vc, forValidity) - } - - def decideWithModel(vc: Expr, forValidity: Boolean): (Option[Boolean], Map[Identifier,Expr]) = { + def decideWithModel(vc: Expr, forValidity: Boolean, evaluator: Option[(Map[Identifier,Expr])=> Boolean] = None): (Option[Boolean], Map[Identifier,Expr]) = { val initializationStopwatch = new Stopwatch("init", false) val blocking2Z3Stopwatch = new Stopwatch("blocking-set-to-z3", false) val z3SearchStopwatch = new Stopwatch("z3-search-1", false) @@ -423,7 +418,7 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac } case (Some(true), m) => { // SAT validatingStopwatch.start - val (trueModel, model) = validateAndDeleteModel(m, toCheckAgainstModels, varsInVC) + val (trueModel, model) = validateAndDeleteModel(m, toCheckAgainstModels, varsInVC, evaluator) validatingStopwatch.stop if (trueModel) { @@ -464,7 +459,7 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac foundAnswer(Some(true)) } else { // we might have been lucky :D - val (wereWeLucky, cleanModel) = validateAndDeleteModel(m2, toCheckAgainstModels, varsInVC) + val (wereWeLucky, cleanModel) = validateAndDeleteModel(m2, toCheckAgainstModels, varsInVC, evaluator) if(wereWeLucky) { foundAnswer(Some(false), cleanModel) } @@ -581,14 +576,14 @@ class FairZ3Solver(val reporter: Reporter) extends Solver(reporter) with Abstrac } } - private def validateAndDeleteModel(model: Z3Model, formula: Expr, variables: Set[Identifier]) : (Boolean, Map[Identifier,Expr]) = { + private def validateAndDeleteModel(model: Z3Model, formula: Expr, variables: Set[Identifier], evaluator: Option[(Map[Identifier,Expr])=>Boolean]) : (Boolean, Map[Identifier,Expr]) = { import Evaluator._ val asMap = modelToMap(model, variables) model.delete lazy val modelAsString = asMap.toList.map(p => p._1 + " -> " + p._2).mkString("\n") - val evalResult = eval(asMap, formula) + val evalResult = eval(asMap, formula, evaluator) evalResult match { case OK(BooleanLiteral(true)) => { diff --git a/src/purescala/Z3Solver.scala b/src/purescala/Z3Solver.scala index bcb868d46b2c4daaf943c12cfc97b258bc6ee000..f6f9a424fd2fa6c17d873e9d69e5b7eb5b7c959e 100644 --- a/src/purescala/Z3Solver.scala +++ b/src/purescala/Z3Solver.scala @@ -470,7 +470,7 @@ class Z3Solver(val reporter: Reporter) extends Solver(reporter) with AbstractZ3S //println("(I'm going to pretend this never happened...)") - val evalResult = eval(asMap, toCheckAgainstModels) + val evalResult = eval(asMap, toCheckAgainstModels, None) evalResult match {