From 51e98a2a553c20a1d351045cffe549d9f868e46b Mon Sep 17 00:00:00 2001 From: "Emmanouil (Manos) Koukoutos" <emmanouil.koukoutos@epfl.ch> Date: Fri, 16 Jan 2015 15:54:54 +0100 Subject: [PATCH] Don't repair valid functions --- src/main/scala/leon/repair/Repairman.scala | 203 +++++++++++---------- 1 file changed, 103 insertions(+), 100 deletions(-) diff --git a/src/main/scala/leon/repair/Repairman.scala b/src/main/scala/leon/repair/Repairman.scala index 93d0c5936..e80100f78 100644 --- a/src/main/scala/leon/repair/Repairman.scala +++ b/src/main/scala/leon/repair/Repairman.scala @@ -2,7 +2,7 @@ package leon package repair - + import purescala.Common._ import purescala.Definitions._ import purescala.Trees._ @@ -31,84 +31,95 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout implicit val debugSection = DebugSectionRepair + private object VRes { + trait VerificationResult + case object Valid extends VerificationResult + case class NotValid(passing : List[Example], failing : List[Example]) extends VerificationResult + } + + import VRes._ + def repair() = { reporter.info(ASCIIHelpers.title("1. Discovering tests for "+fd.id)) val t1 = new Timer().start - val (passingTests, failingTests) = discoverTests - - reporter.info(f" - Passing: ${passingTests.size}%3d") - reporter.info(f" - Failing: ${failingTests.size}%3d") - - reporter.info("Finished in "+t1.stop+"ms") - - - reporter.info(ASCIIHelpers.title("2. Locating/Focusing synthesis problem")) - val t2 = new Timer().start - val synth = getSynthesizer(passingTests, failingTests) - val ci = synth.ci - val p = synth.problem - - var solutions = List[Solution]() - - reporter.info("Finished in "+t2.stop+"ms") - reporter.info(ASCIIHelpers.title("3. Synthesizing")) - reporter.info(p) - - - synth.synthesize() match { - case (search, sols) => - for (sol <- sols) { - - // Validate solution if not trusted - if (!sol.isTrusted) { - reporter.info("Found untrusted solution! Verifying...") - val (npr, fds) = synth.solutionToProgram(sol) - - getVerificationCounterExamples(fds.head, npr) match { - case Some(ces) => - reporter.error("I ended up finding this counter example:\n"+ces.mkString(" | ")) - - case None => + discoverTests match { + case Valid => + reporter.info(s"Function ${fd.id} is found valid, no repair needed!") + case NotValid(passingTests, failingTests) => + reporter.info(f" - Passing: ${passingTests.size}%3d") + reporter.info(f" - Failing: ${failingTests.size}%3d") + + reporter.info("Finished in "+t1.stop+"ms") + + + reporter.info(ASCIIHelpers.title("2. Locating/Focusing synthesis problem")) + val t2 = new Timer().start + val synth = getSynthesizer(passingTests, failingTests) + val ci = synth.ci + val p = synth.problem + + var solutions = List[Solution]() + + reporter.info("Finished in "+t2.stop+"ms") + reporter.info(ASCIIHelpers.title("3. Synthesizing")) + reporter.info(p) + + + synth.synthesize() match { + case (search, sols) => + for (sol <- sols) { + + // Validate solution if not trusted + if (!sol.isTrusted) { + reporter.info("Found untrusted solution! Verifying...") + val (npr, fds) = synth.solutionToProgram(sol) + + getVerificationCounterExamples(fds.head, npr) match { + case NotValid(_, ces) if !ces.isEmpty => + reporter.error("I ended up finding this counter example:\n"+ces.mkString(" | ")) + + case _ => + solutions ::= sol + reporter.info("Solution was not trusted but verification passed!") + } + } else { + reporter.info("Found trusted solution!") solutions ::= sol - reporter.info("Solution was not trusted but verification passed!") + } } - } else { - reporter.info("Found trusted solution!") - solutions ::= sol - } - } - - if (synth.settings.generateDerivationTrees) { - val dot = new DotGenerator(search.g) - dot.writeFile("derivation"+DotGenerator.nextId()+".dot") - } - - if (solutions.isEmpty) { - reporter.error(ASCIIHelpers.title("Failed to repair!")) - } else { - reporter.info(ASCIIHelpers.title("Repair successful:")) - for ((sol, i) <- solutions.reverse.zipWithIndex) { - reporter.info(ASCIIHelpers.subTitle("Solution "+(i+1)+":")) - val expr = sol.toSimplifiedExpr(ctx, program) - reporter.info(ScalaPrinter(expr)); - } - reporter.info(ASCIIHelpers.title("In context:")) - - - for ((sol, i) <- solutions.reverse.zipWithIndex) { - reporter.info(ASCIIHelpers.subTitle("Solution "+(i+1)+":")) - val expr = sol.toSimplifiedExpr(ctx, program) - val nfd = fd.duplicate; - - nfd.body = fd.body.map { b => - replace(Map(ci.source -> expr), b) + + if (synth.settings.generateDerivationTrees) { + val dot = new DotGenerator(search.g) + dot.writeFile("derivation"+DotGenerator.nextId()+".dot") + } + + if (solutions.isEmpty) { + reporter.error(ASCIIHelpers.title("Failed to repair!")) + } else { + reporter.info(ASCIIHelpers.title("Repair successful:")) + for ((sol, i) <- solutions.reverse.zipWithIndex) { + reporter.info(ASCIIHelpers.subTitle("Solution "+(i+1)+":")) + val expr = sol.toSimplifiedExpr(ctx, program) + reporter.info(ScalaPrinter(expr)); + } + reporter.info(ASCIIHelpers.title("In context:")) + + + for ((sol, i) <- solutions.reverse.zipWithIndex) { + reporter.info(ASCIIHelpers.subTitle("Solution "+(i+1)+":")) + val expr = sol.toSimplifiedExpr(ctx, program) + val nfd = fd.duplicate; + + nfd.body = fd.body.map { b => + replace(Map(ci.source -> expr), b) + } + + reporter.info(ScalaPrinter(nfd)); + } + } - - reporter.info(ScalaPrinter(nfd)); } - - } - } + } } def getSynthesizer(passingTests: List[Example], failingTests: List[Example]): Synthesizer = { @@ -306,7 +317,7 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout focus(body, Map())(spec, out) } - def getVerificationCounterExamples(fd: FunDef, prog: Program): Option[Seq[InExample]] = { + private def getVerificationCounterExamples(fd: FunDef, prog: Program): VerificationResult = { val timeoutMs = verifTimeoutMs.getOrElse(3000L) val solver = new TimeoutSolverFactory(SolverFactory.getFromSettings(ctx, prog), timeoutMs) val vctx = VerificationContext(ctx, prog, solver, reporter) @@ -319,30 +330,20 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout interruptOn = _.counterExample.isDefined ) - var invalid = false; - var ces = List[Seq[Expr]]() - - for (vc <- vcs.getOrElse(fd, List())) { - if (vc.value == Some(false)) { - invalid = true; - - vc.counterExample match { - case Some(m) => - ces = fd.params.map(vd => m(vd.id)) :: ces; - - case _ => + val theVCs = vcs.getOrElse(fd, Nil) + + if(theVCs.forall{ _.value == Some(true) } ) { + Valid + } else { + NotValid(Nil, + theVCs.flatMap { _.counterExample map { + m => InExample(fd.params.map{vd => m(vd.id)}) } - } - } - if (invalid) { - Some(ces.map(InExample(_))) - } else { - None + }) } } - - - def discoverTests: (List[Example], List[Example]) = { + + private def discoverTests: VerificationResult = { import bonsai._ import bonsai.enumerators._ @@ -393,18 +394,20 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout // Extract passing/failing from the passes in POST val ef = new ExamplesFinder(ctx, program) - val (userPassing, userFailing) = ef.extractTests(fd) + val (userPassing, userFailing) = ef.extractTests(fd) + val passing = generatedPassing ++ userPassing // If we have no ce yet, try to verify, if it fails, we have at least one CE - val ces = (generatedFailing ++ userFailing) match { - case Seq() => getVerificationCounterExamples(fd, program) getOrElse Nil - case nonEmpty => nonEmpty + (generatedFailing ++ userFailing) match { + case Seq() => getVerificationCounterExamples(fd, program) match { + case Valid => Valid + case NotValid(_, ces) => NotValid(passing, ces) + } + case nonEmpty => NotValid(passing, nonEmpty) } - (generatedPassing ++ userPassing, ces.toList ) } - // ununsed for now, but implementation could be useful later private def disambiguate(p: Problem, sol1: Solution, sol2: Solution): Option[(InOutExample, InOutExample)] = { val s1 = sol1.toSimplifiedExpr(ctx, program) -- GitLab