diff --git a/src/main/scala/leon/purescala/Trees.scala b/src/main/scala/leon/purescala/Trees.scala index 0f987e784386d4f9d52f8da6323fb9688b3c7b9b..edf082730cd7bb51dfd6ee2285232b0272aca7d8 100644 --- a/src/main/scala/leon/purescala/Trees.scala +++ b/src/main/scala/leon/purescala/Trees.scala @@ -168,8 +168,9 @@ object Trees { /* Propositional logic */ object And { def apply(l: Expr, r: Expr) : Expr = (l,r) match { - case (BooleanLiteral(true),_) => r - case (_,BooleanLiteral(true)) => l + case (BooleanLiteral(false),_) => BooleanLiteral(false) + case (BooleanLiteral(true),_) => r + case (_,BooleanLiteral(true)) => l case _ => new And(Seq(l,r)) } def apply(exprs: Seq[Expr]) : Expr = { diff --git a/src/main/scala/leon/synthesis/Heuristics.scala b/src/main/scala/leon/synthesis/Heuristics.scala index 0c92b0ed743765d92874d484911050d3a8a23e38..14352e919f5e6257721bb8e75ee37e4499735442 100644 --- a/src/main/scala/leon/synthesis/Heuristics.scala +++ b/src/main/scala/leon/synthesis/Heuristics.scala @@ -19,6 +19,23 @@ trait Heuristic { this: Rule => override def toString = "H: "+name + +} + +object HeuristicStep { + def verifyPre(synth: Synthesizer)(s: Solution): (Solution, Boolean) = { + synth.solver.solveSAT(And(Not(s.pre), s.fullTerm)) match { + case (Some(true), model) => + synth.reporter.warning("Heuristic failed to produce strongest precondition for solution: \n"+s.toExpr) + (s, false) + case _ => + (s, true) + } + } + + def apply(synth: Synthesizer, subProblems: List[Problem], onSuccess: List[Solution] => Solution) = { + RuleMultiSteps(subProblems, Nil, onSuccess.andThen(verifyPre(synth))) + } } diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala index af3e7b8053f8c2f47b52a17f517f31dfe3be341c..b79ade73cd62475a33d663df6e3ef48d60c07a97 100644 --- a/src/main/scala/leon/synthesis/Rules.scala +++ b/src/main/scala/leon/synthesis/Rules.scala @@ -30,11 +30,11 @@ case object RuleInapplicable extends RuleResult case class RuleSuccess(solution: Solution) extends RuleResult case class RuleMultiSteps(subProblems: List[Problem], steps: List[List[Solution] => List[Problem]], - onSuccess: List[Solution] => Solution) extends RuleResult + onSuccess: List[Solution] => (Solution, Boolean)) extends RuleResult object RuleStep { def apply(subProblems: List[Problem], onSuccess: List[Solution] => Solution) = { - RuleMultiSteps(subProblems, Nil, onSuccess) + RuleMultiSteps(subProblems, Nil, onSuccess.andThen((_, true))) } } diff --git a/src/main/scala/leon/synthesis/Solution.scala b/src/main/scala/leon/synthesis/Solution.scala index cf2561de50e05f13613afedbf89a193b03092e34..309addbaf21ba6b8bcb2195adf533895cbb5a67d 100644 --- a/src/main/scala/leon/synthesis/Solution.scala +++ b/src/main/scala/leon/synthesis/Solution.scala @@ -23,6 +23,9 @@ class Solution(val pre: Expr, val defs: Set[FunDef], val term: Expr) { defs.foldLeft(result){ case (t, fd) => LetDef(fd, t) } } + + def fullTerm = + defs.foldLeft(term){ case (t, fd) => LetDef(fd, t) } } object Solution { diff --git a/src/main/scala/leon/synthesis/Task.scala b/src/main/scala/leon/synthesis/Task.scala index 1176c19a7ebe56facba15555817f6804e719d3c2..c35e2bb24d904425c0663194d3ef3b641a59bde3 100644 --- a/src/main/scala/leon/synthesis/Task.scala +++ b/src/main/scala/leon/synthesis/Task.scala @@ -35,7 +35,7 @@ class Task(synth: Synthesizer, var steps: List[TaskStep] = Nil var nextSteps: List[List[Solution] => List[Problem]] = Nil - var onSuccess: List[Solution] => Solution = _ + var onSuccess: List[Solution] => (Solution, Boolean) = _ def currentStep = steps.head @@ -55,9 +55,15 @@ class Task(synth: Synthesizer, steps = new TaskStep(newProblems) :: steps } else { - solution = Some(onSuccess(solutions)) - - parent.partlySolvedBy(this, solution.get) + onSuccess(solutions) match { + case (s, true) => + solution = Some(s) + + parent.partlySolvedBy(this, solution.get) + case _ => + // solution is there, but it is incomplete (precondition not strongest) + parent.partlySolvedBy(this, Solution.choose(problem)) + } } } } @@ -94,7 +100,7 @@ class Task(synth: Synthesizer, // To each problem we assign the most basic solution, fold on all inner // steps, and then reconstruct final solution val simplestSubSolutions = interSteps.foldLeft(subProblems.map(Solution.basic(_))){ (sols, step) => step(sols).map(Solution.basic(_)) } - val simplestSolution = onSuccess(simplestSubSolutions) + val simplestSolution = onSuccess(simplestSubSolutions)._1 minComplexity = new FixedSolComplexity(parent.minComplexity.value + simplestSolution.complexity.value) val prefix = "[%-20s] ".format(Option(rule).map(_.toString).getOrElse("root")) synth.reporter.info(prefix+"Got: "+problem)