From b986717b60e6a713b5842ec6d50e924505c53065 Mon Sep 17 00:00:00 2001 From: Etienne Kneuss <ekneuss@gmail.com> Date: Thu, 3 Jan 2013 18:29:42 +0100 Subject: [PATCH] Handle problem of costs=0 in case of missing SolutionBuilder, requires passing more info to RuleInstantiation, but it is useful anyway --- src/main/scala/leon/synthesis/CostModel.scala | 9 +++++++-- src/main/scala/leon/synthesis/Heuristics.scala | 4 ++-- src/main/scala/leon/synthesis/ParallelSearch.scala | 2 +- src/main/scala/leon/synthesis/Rules.scala | 10 +++++----- src/main/scala/leon/synthesis/SimpleSearch.scala | 10 +++++++--- .../scala/leon/synthesis/heuristics/ADTInduction.scala | 2 +- .../scala/leon/synthesis/heuristics/IntInduction.scala | 2 +- .../synthesis/heuristics/OptimisticInjection.scala | 2 +- .../leon/synthesis/heuristics/SelectiveInlining.scala | 2 +- src/main/scala/leon/synthesis/rules/ADTDual.scala | 2 +- src/main/scala/leon/synthesis/rules/ADTSplit.scala | 2 +- src/main/scala/leon/synthesis/rules/Assert.scala | 4 ++-- src/main/scala/leon/synthesis/rules/CaseSplit.scala | 2 +- src/main/scala/leon/synthesis/rules/Cegis.scala | 2 +- .../scala/leon/synthesis/rules/Disunification.scala | 2 +- .../scala/leon/synthesis/rules/EqualitySplit.scala | 2 +- src/main/scala/leon/synthesis/rules/Ground.scala | 4 ++-- .../scala/leon/synthesis/rules/IntegerEquation.scala | 4 ++-- .../leon/synthesis/rules/IntegerInequalities.scala | 4 ++-- src/main/scala/leon/synthesis/rules/OnePoint.scala | 2 +- .../scala/leon/synthesis/rules/OptimisticGround.scala | 4 ++-- .../leon/synthesis/rules/UnconstrainedOutput.scala | 2 +- src/main/scala/leon/synthesis/rules/Unification.scala | 4 ++-- src/main/scala/leon/synthesis/rules/UnusedInput.scala | 2 +- 24 files changed, 47 insertions(+), 38 deletions(-) diff --git a/src/main/scala/leon/synthesis/CostModel.scala b/src/main/scala/leon/synthesis/CostModel.scala index 11d035724..04892e750 100644 --- a/src/main/scala/leon/synthesis/CostModel.scala +++ b/src/main/scala/leon/synthesis/CostModel.scala @@ -11,11 +11,16 @@ abstract class CostModel(val name: String) { def solutionCost(s: Solution): Cost def problemCost(p: Problem): Cost - def ruleAppCost(r: Rule, app: RuleInstantiation): Cost = new Cost { + def ruleAppCost(app: RuleInstantiation): Cost = new Cost { val subSols = (1 to app.onSuccess.arity).map {i => Solution.simplest }.toList val simpleSol = app.onSuccess(subSols) - val value = simpleSol.map(solutionCost(_).value).getOrElse(0) + val value = simpleSol match { + case Some(sol) => + solutionCost(sol).value + case None => + problemCost(app.problem).value + } } } diff --git a/src/main/scala/leon/synthesis/Heuristics.scala b/src/main/scala/leon/synthesis/Heuristics.scala index cc313e629..a80831ec4 100644 --- a/src/main/scala/leon/synthesis/Heuristics.scala +++ b/src/main/scala/leon/synthesis/Heuristics.scala @@ -37,14 +37,14 @@ object HeuristicInstantiation { Some(s) } - def apply(problem: Problem, subProblems: List[Problem], onSuccess: List[Solution] => Solution) = { + def apply(problem: Problem, rule: Rule, subProblems: List[Problem], onSuccess: List[Solution] => Solution) = { val builder = new SolutionBuilder(subProblems.size) { def apply(sols: List[Solution]) = { Some(onSuccess(sols)) } } - new RuleInstantiation(builder) { + new RuleInstantiation(problem, rule, builder) { def apply(sctx: SynthesisContext) = RuleDecomposed(subProblems) } diff --git a/src/main/scala/leon/synthesis/ParallelSearch.scala b/src/main/scala/leon/synthesis/ParallelSearch.scala index f85917212..5ec24b47e 100644 --- a/src/main/scala/leon/synthesis/ParallelSearch.scala +++ b/src/main/scala/leon/synthesis/ParallelSearch.scala @@ -70,7 +70,7 @@ class ParallelSearch(synth: Synthesizer, def expandOrTask(ref: ActorRef, sctx: SynthesisContext)(t: TaskTryRules) = { val sub = rules.flatMap { r => - r.instantiateOn(sctx, t.p).map(TaskRunRule(t.p, r, _)) + r.instantiateOn(sctx, t.p).map(TaskRunRule(_)) } if (!sub.isEmpty) { diff --git a/src/main/scala/leon/synthesis/Rules.scala b/src/main/scala/leon/synthesis/Rules.scala index 3d24a3c2d..0ea37eac2 100644 --- a/src/main/scala/leon/synthesis/Rules.scala +++ b/src/main/scala/leon/synthesis/Rules.scala @@ -44,7 +44,7 @@ object SolutionBuilder { } } -abstract class RuleInstantiation(val onSuccess: SolutionBuilder) { +abstract class RuleInstantiation(val problem: Problem, val rule: Rule, val onSuccess: SolutionBuilder) { def apply(sctx: SynthesisContext): RuleApplicationResult } @@ -62,14 +62,14 @@ case class RuleDecomposed(sub: List[Problem]) extends RuleApplicationResult case object RuleApplicationImpossible extends RuleApplicationResult object RuleInstantiation { - def immediateDecomp(sub: List[Problem], onSuccess: List[Solution] => Solution) = { - new RuleInstantiation(new SolutionCombiner(sub.size, onSuccess)) { + def immediateDecomp(problem: Problem, rule: Rule, sub: List[Problem], onSuccess: List[Solution] => Solution) = { + new RuleInstantiation(problem, rule, new SolutionCombiner(sub.size, onSuccess)) { def apply(sctx: SynthesisContext) = RuleDecomposed(sub) } } - def immediateSuccess(solution: Solution) = { - new RuleInstantiation(new SolutionCombiner(0, ls => solution)) { + def immediateSuccess(problem: Problem, rule: Rule, solution: Solution) = { + new RuleInstantiation(problem, rule, new SolutionCombiner(0, ls => solution)) { def apply(sctx: SynthesisContext) = RuleSuccess(solution) } } diff --git a/src/main/scala/leon/synthesis/SimpleSearch.scala b/src/main/scala/leon/synthesis/SimpleSearch.scala index d2b658bb2..393177e77 100644 --- a/src/main/scala/leon/synthesis/SimpleSearch.scala +++ b/src/main/scala/leon/synthesis/SimpleSearch.scala @@ -3,7 +3,11 @@ package synthesis import synthesis.search._ -case class TaskRunRule(problem: Problem, rule: Rule, app: RuleInstantiation) extends AOAndTask[Solution] { +case class TaskRunRule(app: RuleInstantiation) extends AOAndTask[Solution] { + + val problem = app.problem + val rule = app.rule + def composeSolution(sols: List[Solution]): Option[Solution] = { app.onSuccess(sols) } @@ -18,7 +22,7 @@ case class TaskTryRules(p: Problem) extends AOOrTask[Solution] { case class SearchCostModel(cm: CostModel) extends AOCostModel[TaskRunRule, TaskTryRules, Solution] { def taskCost(t: AOTask[Solution]) = t match { case ttr: TaskRunRule => - cm.ruleAppCost(ttr.rule, ttr.app) + cm.ruleAppCost(ttr.app) case trr: TaskTryRules => cm.problemCost(trr.p) } @@ -59,7 +63,7 @@ class SimpleSearch(synth: Synthesizer, } def expandOrTask(t: TaskTryRules): ExpandResult[TaskRunRule] = { - val sub = rules.flatMap ( r => r.instantiateOn(sctx, t.p).map(TaskRunRule(t.p, r, _)) ) + val sub = rules.flatMap ( r => r.instantiateOn(sctx, t.p).map(TaskRunRule(_)) ) if (!sub.isEmpty) { Expanded(sub.toList) diff --git a/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala b/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala index adcbb72a2..4cb8f2285 100644 --- a/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala +++ b/src/main/scala/leon/synthesis/heuristics/ADTInduction.scala @@ -97,7 +97,7 @@ case object ADTInduction extends Rule("ADT Induction") with Heuristic { Solution(Or(globalPre), sols.flatMap(_.defs).toSet+newFun, FunctionInvocation(newFun, Variable(origId) :: oas.map(Variable(_)))) } - Some(HeuristicInstantiation(p, subProblemsInfo.map(_._1).toList, onSuccess)) + Some(HeuristicInstantiation(p, this, subProblemsInfo.map(_._1).toList, onSuccess)) } else { None } diff --git a/src/main/scala/leon/synthesis/heuristics/IntInduction.scala b/src/main/scala/leon/synthesis/heuristics/IntInduction.scala index fdcc626c4..a882fe32b 100644 --- a/src/main/scala/leon/synthesis/heuristics/IntInduction.scala +++ b/src/main/scala/leon/synthesis/heuristics/IntInduction.scala @@ -54,7 +54,7 @@ case object IntInduction extends Rule("Int Induction") with Heuristic { Solution.none } - Some(HeuristicInstantiation(p, List(subBase, subGT, subLT), onSuccess)) + Some(HeuristicInstantiation(p, this, List(subBase, subGT, subLT), onSuccess)) case _ => None } diff --git a/src/main/scala/leon/synthesis/heuristics/OptimisticInjection.scala b/src/main/scala/leon/synthesis/heuristics/OptimisticInjection.scala index a3ecedd72..1a957e402 100644 --- a/src/main/scala/leon/synthesis/heuristics/OptimisticInjection.scala +++ b/src/main/scala/leon/synthesis/heuristics/OptimisticInjection.scala @@ -36,7 +36,7 @@ case object OptimisticInjection extends Rule("Opt. Injection") with Heuristic { val sub = p.copy(phi = And(newExprs)) - Some(HeuristicInstantiation(p, List(sub), forward)) + Some(HeuristicInstantiation(p, this, List(sub), forward)) } else { None } diff --git a/src/main/scala/leon/synthesis/heuristics/SelectiveInlining.scala b/src/main/scala/leon/synthesis/heuristics/SelectiveInlining.scala index 8e91394f0..488df7355 100644 --- a/src/main/scala/leon/synthesis/heuristics/SelectiveInlining.scala +++ b/src/main/scala/leon/synthesis/heuristics/SelectiveInlining.scala @@ -36,7 +36,7 @@ case object SelectiveInlining extends Rule("Sel. Inlining") with Heuristic { val sub = p.copy(phi = And(newExprs)) - Some(HeuristicInstantiation(p, List(sub), forward)) + Some(HeuristicInstantiation(p, this, List(sub), forward)) } else { None } diff --git a/src/main/scala/leon/synthesis/rules/ADTDual.scala b/src/main/scala/leon/synthesis/rules/ADTDual.scala index 6b6dac90f..f1811f073 100644 --- a/src/main/scala/leon/synthesis/rules/ADTDual.scala +++ b/src/main/scala/leon/synthesis/rules/ADTDual.scala @@ -24,7 +24,7 @@ case object ADTDual extends Rule("ADTDual") { if (!toRemove.isEmpty) { val sub = p.copy(phi = And((exprs.toSet -- toRemove ++ toAdd.flatten).toSeq)) - List(RuleInstantiation.immediateDecomp(List(sub), forward)) + List(RuleInstantiation.immediateDecomp(p, this, List(sub), forward)) } else { Nil } diff --git a/src/main/scala/leon/synthesis/rules/ADTSplit.scala b/src/main/scala/leon/synthesis/rules/ADTSplit.scala index e94abd7f1..4680ca40b 100644 --- a/src/main/scala/leon/synthesis/rules/ADTSplit.scala +++ b/src/main/scala/leon/synthesis/rules/ADTSplit.scala @@ -70,7 +70,7 @@ case object ADTSplit extends Rule("ADT Split.") { Solution(Or(globalPre), sols.flatMap(_.defs).toSet, MatchExpr(Variable(id), cases)) } - Some(RuleInstantiation.immediateDecomp(subInfo.map(_._2).toList, onSuccess)) + Some(RuleInstantiation.immediateDecomp(p, this, subInfo.map(_._2).toList, onSuccess)) case _ => None }}.flatten diff --git a/src/main/scala/leon/synthesis/rules/Assert.scala b/src/main/scala/leon/synthesis/rules/Assert.scala index 4522067b8..d45d08903 100644 --- a/src/main/scala/leon/synthesis/rules/Assert.scala +++ b/src/main/scala/leon/synthesis/rules/Assert.scala @@ -16,11 +16,11 @@ case object Assert extends Rule("Assert") { if (!exprsA.isEmpty) { if (others.isEmpty) { - List(RuleInstantiation.immediateSuccess(Solution(And(exprsA), Set(), Tuple(p.xs.map(id => simplestValue(Variable(id))))))) + List(RuleInstantiation.immediateSuccess(p, this, Solution(And(exprsA), Set(), Tuple(p.xs.map(id => simplestValue(Variable(id))))))) } else { val sub = p.copy(pc = And(p.pc +: exprsA), phi = And(others)) - List(RuleInstantiation.immediateDecomp(List(sub), { + List(RuleInstantiation.immediateDecomp(p, this, List(sub), { case Solution(pre, defs, term) :: Nil => Solution(And(exprsA :+ pre), defs, term) case _ => Solution.none })) diff --git a/src/main/scala/leon/synthesis/rules/CaseSplit.scala b/src/main/scala/leon/synthesis/rules/CaseSplit.scala index 3850b1d74..9b3e56315 100644 --- a/src/main/scala/leon/synthesis/rules/CaseSplit.scala +++ b/src/main/scala/leon/synthesis/rules/CaseSplit.scala @@ -34,7 +34,7 @@ case object CaseSplit extends Rule("Case-Split") { Solution.none } - RuleInstantiation.immediateDecomp(subs, onSuccess) + RuleInstantiation.immediateDecomp(p, this, subs, onSuccess) } } diff --git a/src/main/scala/leon/synthesis/rules/Cegis.scala b/src/main/scala/leon/synthesis/rules/Cegis.scala index 8eafd160f..c7f84e483 100644 --- a/src/main/scala/leon/synthesis/rules/Cegis.scala +++ b/src/main/scala/leon/synthesis/rules/Cegis.scala @@ -124,7 +124,7 @@ case object CEGIS extends Rule("CEGIS") { val (exprsA, others) = ands.partition(e => (variablesOf(e) & xsSet).isEmpty) if (exprsA.isEmpty) { - val res = new RuleInstantiation(SolutionBuilder.none) { + val res = new RuleInstantiation(p, this, SolutionBuilder.none) { def apply(sctx: SynthesisContext) = { var result: Option[RuleApplicationResult] = None diff --git a/src/main/scala/leon/synthesis/rules/Disunification.scala b/src/main/scala/leon/synthesis/rules/Disunification.scala index 9ca48a9f6..4925f6000 100644 --- a/src/main/scala/leon/synthesis/rules/Disunification.scala +++ b/src/main/scala/leon/synthesis/rules/Disunification.scala @@ -26,7 +26,7 @@ object Disunification { if (!toRemove.isEmpty) { val sub = p.copy(phi = Or((exprs.toSet -- toRemove ++ toAdd.flatten).toSeq)) - List(RuleInstantiation.immediateDecomp(List(sub), forward)) + List(RuleInstantiation.immediateDecomp(p, this, List(sub), forward)) } else { Nil } diff --git a/src/main/scala/leon/synthesis/rules/EqualitySplit.scala b/src/main/scala/leon/synthesis/rules/EqualitySplit.scala index bad8bc4c4..603a48a08 100644 --- a/src/main/scala/leon/synthesis/rules/EqualitySplit.scala +++ b/src/main/scala/leon/synthesis/rules/EqualitySplit.scala @@ -48,7 +48,7 @@ case object EqualitySplit extends Rule("Eq. Split.") { Solution.none } - Some(RuleInstantiation.immediateDecomp(List(sub1, sub2), onSuccess)) + Some(RuleInstantiation.immediateDecomp(p, this, List(sub1, sub2), onSuccess)) case _ => None }).flatten diff --git a/src/main/scala/leon/synthesis/rules/Ground.scala b/src/main/scala/leon/synthesis/rules/Ground.scala index 6aefe88a8..953ad5b56 100644 --- a/src/main/scala/leon/synthesis/rules/Ground.scala +++ b/src/main/scala/leon/synthesis/rules/Ground.scala @@ -16,10 +16,10 @@ case object Ground extends Rule("Ground") { sctx.solver.solveSAT(p.phi) match { case (Some(true), model) => val sol = Solution(BooleanLiteral(true), Set(), Tuple(p.xs.map(valuateWithModel(model))).setType(tpe)) - Some(RuleInstantiation.immediateSuccess(sol)) + Some(RuleInstantiation.immediateSuccess(p, this, sol)) case (Some(false), model) => val sol = Solution(BooleanLiteral(false), Set(), Error(p.phi+" is UNSAT!").setType(tpe)) - Some(RuleInstantiation.immediateSuccess(sol)) + Some(RuleInstantiation.immediateSuccess(p, this, sol)) case _ => None } diff --git a/src/main/scala/leon/synthesis/rules/IntegerEquation.scala b/src/main/scala/leon/synthesis/rules/IntegerEquation.scala index eabbfce2e..f74e4478e 100644 --- a/src/main/scala/leon/synthesis/rules/IntegerEquation.scala +++ b/src/main/scala/leon/synthesis/rules/IntegerEquation.scala @@ -60,7 +60,7 @@ case object IntegerEquation extends Rule("Integer Equation") { case _ => Solution.none } - List(RuleInstantiation.immediateDecomp(List(newProblem), onSuccess)) + List(RuleInstantiation.immediateDecomp(problem, this, List(newProblem), onSuccess)) } else { val (eqPre0, eqWitness, freshxs) = elimVariable(eqas, normalizedEq) @@ -103,7 +103,7 @@ case object IntegerEquation extends Rule("Integer Equation") { case _ => Solution.none } - List(RuleInstantiation.immediateDecomp(List(newProblem), onSuccess)) + List(RuleInstantiation.immediateDecomp(problem, this, List(newProblem), onSuccess)) } } } diff --git a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala b/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala index 21f9dced1..7fbc67fd6 100644 --- a/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala +++ b/src/main/scala/leon/synthesis/rules/IntegerInequalities.scala @@ -131,7 +131,7 @@ case object IntegerInequalities extends Rule("Integer Inequalities") { val constraints: List[Expr] = for((ub, uc) <- upperBounds; (lb, lc) <- lowerBounds) yield LessEquals(ceilingDiv(lb, IntLiteral(lc)), floorDiv(ub, IntLiteral(uc))) val pre = And(exprNotUsed ++ constraints) - List(RuleInstantiation.immediateSuccess(Solution(pre, Set(), witness))) + List(RuleInstantiation.immediateSuccess(problem, this, Solution(pre, Set(), witness))) } else { val involvedVariables = (upperBounds++lowerBounds).foldLeft(Set[Identifier]())((acc, t) => { @@ -200,7 +200,7 @@ case object IntegerInequalities extends Rule("Integer Inequalities") { case _ => Solution.none } - List(RuleInstantiation.immediateDecomp(List(subProblem), onSuccess)) + List(RuleInstantiation.immediateDecomp(problem, this, List(subProblem), onSuccess)) } } } diff --git a/src/main/scala/leon/synthesis/rules/OnePoint.scala b/src/main/scala/leon/synthesis/rules/OnePoint.scala index 24eee3336..7f4fae9da 100644 --- a/src/main/scala/leon/synthesis/rules/OnePoint.scala +++ b/src/main/scala/leon/synthesis/rules/OnePoint.scala @@ -35,7 +35,7 @@ case object OnePoint extends Rule("One-point") { case _ => Solution.none } - List(RuleInstantiation.immediateDecomp(List(newProblem), onSuccess)) + List(RuleInstantiation.immediateDecomp(p, this, List(newProblem), onSuccess)) } else { Nil } diff --git a/src/main/scala/leon/synthesis/rules/OptimisticGround.scala b/src/main/scala/leon/synthesis/rules/OptimisticGround.scala index 460a83fe4..953afc7b2 100644 --- a/src/main/scala/leon/synthesis/rules/OptimisticGround.scala +++ b/src/main/scala/leon/synthesis/rules/OptimisticGround.scala @@ -38,7 +38,7 @@ case object OptimisticGround extends Rule("Optimistic Ground") { predicates = valuateWithModelIn(phi, ass, invalidModel) +: predicates case (Some(false), _) => - result = Some(RuleInstantiation.immediateSuccess(Solution(BooleanLiteral(true), Set(), Tuple(p.xs.map(valuateWithModel(satModel))).setType(tpe)))) + result = Some(RuleInstantiation.immediateSuccess(p, this, Solution(BooleanLiteral(true), Set(), Tuple(p.xs.map(valuateWithModel(satModel))).setType(tpe)))) case _ => continue = false @@ -47,7 +47,7 @@ case object OptimisticGround extends Rule("Optimistic Ground") { case (Some(false), _) => if (predicates.isEmpty) { - result = Some(RuleInstantiation.immediateSuccess(Solution(BooleanLiteral(false), Set(), Error(p.phi+" is UNSAT!").setType(tpe)))) + result = Some(RuleInstantiation.immediateSuccess(p, this, Solution(BooleanLiteral(false), Set(), Error(p.phi+" is UNSAT!").setType(tpe)))) } else { continue = false result = None diff --git a/src/main/scala/leon/synthesis/rules/UnconstrainedOutput.scala b/src/main/scala/leon/synthesis/rules/UnconstrainedOutput.scala index 7c8d2de15..381f73f6b 100644 --- a/src/main/scala/leon/synthesis/rules/UnconstrainedOutput.scala +++ b/src/main/scala/leon/synthesis/rules/UnconstrainedOutput.scala @@ -20,7 +20,7 @@ case object UnconstrainedOutput extends Rule("Unconstr.Output") { Solution.none } - List(RuleInstantiation.immediateDecomp(List(sub), onSuccess)) + List(RuleInstantiation.immediateDecomp(p, this, List(sub), onSuccess)) } else { Nil } diff --git a/src/main/scala/leon/synthesis/rules/Unification.scala b/src/main/scala/leon/synthesis/rules/Unification.scala index 5c8151619..9b7ea4230 100644 --- a/src/main/scala/leon/synthesis/rules/Unification.scala +++ b/src/main/scala/leon/synthesis/rules/Unification.scala @@ -27,7 +27,7 @@ object Unification { val sub = p.copy(phi = And((exprs.toSet -- toRemove ++ toAdd.flatten).toSeq)) - List(RuleInstantiation.immediateDecomp(List(sub), forward)) + List(RuleInstantiation.immediateDecomp(p, this, List(sub), forward)) } else { Nil } @@ -52,7 +52,7 @@ object Unification { if (isImpossible) { val tpe = TupleType(p.xs.map(_.getType)) - List(RuleInstantiation.immediateSuccess(Solution(BooleanLiteral(false), Set(), Error(p.phi+" is UNSAT!").setType(tpe)))) + List(RuleInstantiation.immediateSuccess(p, this, Solution(BooleanLiteral(false), Set(), Error(p.phi+" is UNSAT!").setType(tpe)))) } else { Nil } diff --git a/src/main/scala/leon/synthesis/rules/UnusedInput.scala b/src/main/scala/leon/synthesis/rules/UnusedInput.scala index 13ba585ab..b44ad3411 100644 --- a/src/main/scala/leon/synthesis/rules/UnusedInput.scala +++ b/src/main/scala/leon/synthesis/rules/UnusedInput.scala @@ -13,7 +13,7 @@ case object UnusedInput extends Rule("UnusedInput") { if (!unused.isEmpty) { val sub = p.copy(as = p.as.filterNot(unused)) - List(RuleInstantiation.immediateDecomp(List(sub), forward)) + List(RuleInstantiation.immediateDecomp(p, this, List(sub), forward)) } else { Nil } -- GitLab