From 39bcbd5bb08e10f1c5373e6635e7b8a63cbc133e Mon Sep 17 00:00:00 2001 From: "Emmanouil (Manos) Koukoutos" <emmanouil.koukoutos@epfl.ch> Date: Fri, 6 Feb 2015 20:53:30 +0100 Subject: [PATCH] Don't carry unused passing tests around --- src/main/scala/leon/repair/Repairman.scala | 93 ++++++++++------------ 1 file changed, 43 insertions(+), 50 deletions(-) diff --git a/src/main/scala/leon/repair/Repairman.scala b/src/main/scala/leon/repair/Repairman.scala index 6ac5b7f05..8f50da011 100644 --- a/src/main/scala/leon/repair/Repairman.scala +++ b/src/main/scala/leon/repair/Repairman.scala @@ -58,17 +58,53 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout 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.ifDebug { printer => + printer(new ExamplesTable("Tests failing:", failingTests).toString) + printer(new ExamplesTable("Tests passing:", passingTests).toString) + } + + // We exclude redundant failing tests, and only select the minimal tests + val minimalFailingTests = { + type FI = (FunDef, Seq[Expr]) + // We don't want tests whose invocation will call other failing tests. + // This is because they will appear erroneous, + // even though the error comes from the called test + val testEval = new RepairTrackingEvaluator(ctx, program) + failingTests foreach { ts => + testEval.eval(functionInvocation(fd, ts.ins)) + } + val test2Tests : Map[FI, Set[FI]] = testEval.fullCallGraph + /*println("About to print") + for{ + (test, tests) <-test2Tests + if (test._1 == fd) + } { + println(test._2 mkString ", ") + println(new ExamplesTable("", tests.toSeq.filter{_._1 == fd}.map{ x => InExample(x._2)}).toString) + }*/ + def isFailing(fi : FI) = !testEval.fiStatus(fi) && (fi._1 == fd) + val failing = test2Tests filter { case (from, to) => + isFailing(from) && (to forall (!isFailing(_)) ) + } + failing.keySet map { case (_, args) => InExample(args) } + } + + reporter.info(f" - Minimal Failing Set Size: ${minimalFailingTests.size}%3d") + val initTime = t1.stop result = result.copy(initTime = Some(initTime)) reporter.info("Finished in "+initTime+"ms") + reporter.ifDebug { printer => + printer(new ExamplesTable("Minimal failing:", minimalFailingTests.toSeq).toString) + } reporter.info(ASCIIHelpers.title("2. Locating/Focusing synthesis problem")) val t2 = new Timer().start - val synth = getSynthesizer(passingTests, failingTests) + val synth = getSynthesizer(minimalFailingTests.toList) val ci = synth.ci val p = synth.problem @@ -152,12 +188,11 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout result } - def getSynthesizer(passingTests: List[Example], failingTests: List[Example]): Synthesizer = { + def getSynthesizer(failingTests: List[Example]): Synthesizer = { - val body = fd.body.get; - + val body = fd.body.get - val (newBody, replacedExpr) = focusRepair(program, fd, passingTests, failingTests) + val (newBody, replacedExpr) = focusRepair(program, fd, failingTests) fd.body = Some(newBody) val size = formulaSize(body) @@ -194,12 +229,7 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout new Synthesizer(ctx, program, nci, soptions) } - private def focusRepair(program: Program, fd: FunDef, passingTests: List[Example], failingTests: List[Example]): (Expr, Expr) = { - - reporter.ifDebug { printer => - printer(new ExamplesTable("Tests failing:", failingTests).toString) - printer(new ExamplesTable("Tests passing:", passingTests).toString) - } + private def focusRepair(program: Program, fd: FunDef, failingTests: List[Example]): (Expr, Expr) = { val pre = fd.precondition.getOrElse(BooleanLiteral(true)) val args = fd.params.map(_.id) @@ -215,50 +245,13 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout val evaluator = new DefaultEvaluator(ctx, program) - // We exclude redundant failing tests, and only select the minimal tests - val minimalFailingTests = { - - type FI = (FunDef, Seq[Expr]) - - // We don't want tests whose invocation will call other failing tests. - // This is because they will appear erroneous, - // even though the error comes from the called test - val testEval = new RepairTrackingEvaluator(ctx, program) - - failingTests foreach { ts => - testEval.eval(functionInvocation(fd, ts.ins)) - } - - val test2Tests : Map[FI, Set[FI]] = testEval.fullCallGraph - - /*println("About to print") - for{ - (test, tests) <-test2Tests - if (test._1 == fd) - } { - println(test._2 mkString ", ") - println(new ExamplesTable("", tests.toSeq.filter{_._1 == fd}.map{ x => InExample(x._2)}).toString) - }*/ - - def isFailing(fi : FI) = !testEval.fiStatus(fi) && (fi._1 == fd) - val failing = test2Tests filter { case (from, to) => - isFailing(from) && (to forall (!isFailing(_)) ) - } - - failing.keySet map { case (_, args) => InExample(args) } - } - - reporter.ifDebug { printer => - printer(new ExamplesTable("Minimal failing:", minimalFailingTests.toSeq).toString) - } - // Check how an expression behaves on tests // - returns Some(true) if for all tests e evaluates to true // - returns Some(false) if for all tests e evaluates to false // - returns None otherwise def forAllTests(e: Expr, env: Map[Identifier, Expr], evaluator: Evaluator): Option[Boolean] = { var soFar : Option[Boolean] = None - minimalFailingTests.foreach { ex => + failingTests.foreach { ex => val ins = ex.ins evaluator.eval(e, env ++ (args zip ins)) match { case EvaluationResults.Successful(BooleanLiteral(b)) => -- GitLab