diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala index 9f373400770d59fa5019e516e3b5b1bcb4cb5fc4..e60d36f5310762d9e5aa56e3b9b55c13abc9ddc4 100644 --- a/src/main/scala/leon/purescala/TreeOps.scala +++ b/src/main/scala/leon/purescala/TreeOps.scala @@ -853,10 +853,10 @@ object TreeOps { case LiteralPattern(Some(id), lit) => Map(id -> in) } - private def convertMatchToIfThenElse(expr: Expr) : Expr = { + private def convertMatchToIfThenElse(expr: Expr): Expr = { - def rewritePM(e: Expr) : Option[Expr] = e match { - case m @ MatchExpr(scrut, cases) => { + def rewritePM(e: Expr): Option[Expr] = e match { + case m @ MatchExpr(scrut, cases) => // println("Rewriting the following PM: " + e) val condsAndRhs = for(cse <- cases) yield { @@ -879,11 +879,19 @@ object TreeOps { }) Some(bigIte) - } + + case p: Passes => + // This introduces a MatchExpr + Some(p.asConstraint) + + case g: Gives => + // This introduces a MatchExpr + Some(g.asMatch) + case _ => None } - postMap(rewritePM)(expr) + preMap(rewritePM)(expr) } def matchCasePathConditions(m: MatchExpr, pathCond: List[Expr]) : Seq[List[Expr]] = { @@ -1381,14 +1389,6 @@ object TreeOps { new ChooseCollectorWithPaths().traverse(e).map(_._1).toList } - def containsChoose(e: Expr): Boolean = { - preTraversal{ - case Choose(_, _, None) => return true - case _ => - }(e) - false - } - def isDeterministic(e: Expr): Boolean = { preTraversal{ case Choose(_, _, None) => return false diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala index 171d8cc04280aacd79832671ba2caec875549072..421d97600d994c5d513537c26714338fd4407104 100644 --- a/src/main/scala/leon/purescala/Trees.scala +++ b/src/main/scala/leon/purescala/Trees.scala @@ -192,10 +192,14 @@ object Trees { } case class Gives(scrutinee: Expr, cases : Seq[MatchCase]) extends MatchLike { - def asIncompleteMatch = { + def asMatchWithHole = { val theHole = SimpleCase(WildcardPattern(None), Hole(this.getType, Seq())) MatchExpr(scrutinee, cases :+ theHole) } + + def asMatch = { + matchExpr(scrutinee, cases) + } } case class Passes(in: Expr, out : Expr, cases : Seq[MatchCase]) extends Expr { diff --git a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala index 09ce38e76a3637588753334a4c05e25de2a4846c..cdad71b8859c2dcb0e2be28f778f9234a3be3bf3 100644 --- a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala +++ b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala @@ -223,7 +223,9 @@ class TemplateGenerator[T](val encoder: TemplateEncoder[T]) { val rb = rec(pathVar, replace(mapping.toMap, b)) rb - case m : MatchExpr => sys.error("MatchExpr's should have been eliminated.") + case m : MatchExpr => sys.error("'MatchExpr's should have been eliminated before generating templates.") + case p : Passes => sys.error("'Passes's should have been eliminated before generating templates.") + case g : Gives => sys.error("'Gives' should have been eliminated before generating templates.") case i @ Implies(lhs, rhs) => implies(rec(pathVar, lhs), rec(pathVar, rhs)) diff --git a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala index ac0719cd63ff41723c7ee4d0edd583ead42d0e39..51dc20d565bb58e70573a26cb744fec0cbd1cc5a 100644 --- a/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala +++ b/src/main/scala/leon/solvers/z3/AbstractZ3Solver.scala @@ -501,8 +501,8 @@ trait AbstractZ3Solver case me @ MatchExpr(s, cs) => rec(matchToIfThenElse(me)) - case Gives(scrut, tests) => - rec(matchToIfThenElse(matchExpr(scrut, tests))) + case g @ Gives(scrut, tests) => + rec(g.asMatch) case tu @ Tuple(args) => typeToSort(tu.getType) // Make sure we generate sort & meta info diff --git a/src/main/scala/leon/synthesis/ConvertHoles.scala b/src/main/scala/leon/synthesis/ConvertHoles.scala index 375b6dfe17a929ac4d6378f58d09360f3345526e..a7051f4930d1d587aee7affbab58cc43f0afdfa3 100644 --- a/src/main/scala/leon/synthesis/ConvertHoles.scala +++ b/src/main/scala/leon/synthesis/ConvertHoles.scala @@ -63,7 +63,7 @@ object ConvertHoles extends LeonPhase[Program, Program] { val withoutHoles = preMap { case p : Gives if treatGives => - Some(p.asIncompleteMatch) + Some(p.asMatchWithHole) case h : Hole => val (expr, ids) = toExpr(h) diff --git a/src/main/scala/leon/synthesis/rules/CegisLike.scala b/src/main/scala/leon/synthesis/rules/CegisLike.scala index 1e6cc3a0bcfb89405b3eb86639604959bac68d14..98d7b68cd7d3c9aca6ddfc5408b600d408de197b 100644 --- a/src/main/scala/leon/synthesis/rules/CegisLike.scala +++ b/src/main/scala/leon/synthesis/rules/CegisLike.scala @@ -42,9 +42,6 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { def getParams(sctx: SynthesisContext, p: Problem): CegisParams def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { - - def debugPrinter(t: Tree) = ScalaPrinter(t, PrinterOptions(printUniqueIds = true)) - val exSolverTo = 2000L val cexSolverTo = 2000L @@ -59,7 +56,6 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { val useOptTimeout = sctx.settings.cegisUseOptTimeout val useVanuatoo = sctx.settings.cegisUseVanuatoo val useCETests = sctx.settings.cegisUseCETests - val useCEPruning = sctx.settings.cegisUseCEPruning // Limits the number of programs CEGIS will specifically validate individually val validateUpTo = 5 @@ -279,12 +275,6 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { val affected = prog0.callGraph.transitiveCallers(chFd).toSet ++ Set(chFd, cTreeFd, phiFd) ++ fullSol.defs - //println("Affected:") - //for (fd <- affected) { - // println(" - "+debugPrinter(fd.id)) - //} - - cTreeFd.body = None phiFd.body = Some( letTuple(p.xs, @@ -319,13 +309,6 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { case _ => None }) - //println("FunDef Map:") - //for ((f, t) <- fdMap2) { - // println("- "+debugPrinter(f.id)+" -> "+debugPrinter(t.id)) - //} - - //println("Program:") - //println(debugPrinter(prog2)) programCTree = prog2 cTreeFd = fdMap2(cTreeFd) @@ -415,9 +398,6 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { hctx.ci.ch.impl = Some(fullSol.guardedTerm) - //println("Validating Solution "+sol) - //println(debugPrinter(prog)) - val cnstr = and(p.pc, letTuple(p.xs, sol, Not(p.phi))) //println("Solving for: "+cnstr) @@ -428,6 +408,14 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { case Some(true) => excludeProgram(bs) val model = solver.getModel + //println("Found counter example: ") + //for ((s, v) <- model) { + // println(" "+s.asString+" -> "+v.asString) + //} + + //val evaluator = new DefaultEvaluator(ctx, prog) + //println(evaluator.eval(cnstr, model)) + Some(p.as.map(a => model.getOrElse(a, simplestValue(a.getType)))) case Some(false) => @@ -830,20 +818,6 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { baseExampleInputs.iterator ++ cachedInputIterator } - // Keep track of collected cores to filter programs to test - var collectedCores = Set[Set[Identifier]]() - - //val initExClause = and(pc, p.phi, Variable(initGuard)) - //val initCExClause = and(pc, not(p.phi), Variable(initGuard)) - - //// solver1 is used for the initial SAT queries - //var solver1 = sctx.newSolver.setTimeout(exSolverTo) - //solver1.assertCnstr(initExClause) - - //// solver2 is used for validating a candidate program, or finding new inputs - //var solver2 = sctx.newSolver.setTimeout(cexSolverTo) - //solver2.assertCnstr(initCExClause) - val tpe = tupleTypeWrap(p.xs.map(_.getType)) try { @@ -858,11 +832,7 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { } // Compute all programs that have not been excluded yet - var prunedPrograms: Set[Set[Identifier]] = if (useCEPruning) { - ndProgram.allPrograms.filterNot(p => collectedCores.exists(c => c.subsetOf(p))).toSet - } else { - Set() - } + var prunedPrograms: Set[Set[Identifier]] = ndProgram.allPrograms.toSet val nInitial = prunedPrograms.size sctx.reporter.debug("#Programs: "+nInitial) @@ -881,7 +851,7 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { var wrongPrograms = Set[Set[Identifier]](); // We further filter the set of working programs to remove those that fail on known examples - if (useCEPruning && hasInputExamples()) { + if (hasInputExamples()) { for (bs <- prunedPrograms if !interruptManager.isInterrupted()) { var valid = true val examples = allInputExamples() @@ -967,10 +937,8 @@ abstract class CEGISLike[T <% Typed](name: String) extends Rule(name) { baseExampleInputs += inputsCE // Retest whether the newly found C-E invalidates all programs - if (useCEPruning) { - if (prunedPrograms.forall(p => !ndProgram.testForProgram(p)(inputsCE))) { - skipCESearch = true - } + if (prunedPrograms.forall(p => !ndProgram.testForProgram(p)(inputsCE))) { + skipCESearch = true } case Some(None) =>