From 4fd59012c9ece0fb0342c0e0553dbb3faa0ae089 Mon Sep 17 00:00:00 2001 From: Etienne Kneuss <ekneuss@gmail.com> Date: Tue, 13 Nov 2012 15:37:30 +0100 Subject: [PATCH] CEGIS that works --- .../scala/leon/synthesis/Heuristics.scala | 60 ++++++++++++------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/src/main/scala/leon/synthesis/Heuristics.scala b/src/main/scala/leon/synthesis/Heuristics.scala index 718b109e5..8cd507344 100644 --- a/src/main/scala/leon/synthesis/Heuristics.scala +++ b/src/main/scala/leon/synthesis/Heuristics.scala @@ -12,7 +12,7 @@ object Heuristics { def all = Set[Synthesizer => Rule]( new OptimisticGround(_), //new IntInduction(_), - new CEGISOnSteroids(_), + new CEGIS(_), new OptimisticInjection(_) ) } @@ -197,7 +197,7 @@ class SelectiveInlining(synth: Synthesizer) extends Rule("Sel. Inlining", synth, } } -class CEGISOnSteroids(synth: Synthesizer) extends Rule("cegis w. gen.", synth, 50) with Heuristic { +class CEGIS(synth: Synthesizer) extends Rule("CEGIS", synth, 50) with Heuristic { def applyOn(task: Task): RuleResult = { val p = task.problem @@ -252,32 +252,42 @@ class CEGISOnSteroids(synth: Synthesizer) extends Rule("cegis w. gen.", synth, 5 p.as.filter(a => isSubtypeOf(a.getType, t)).map(id => (Variable(id) : Expr, Set[Identifier]())) } - case class TentativeFormula(f: Expr, recTerms: Map[Identifier, Set[Identifier]]) { + case class TentativeFormula(phi: Expr, + program: Expr, + mappings: Map[Identifier, (Identifier, Expr)], + recTerms: Map[Identifier, Set[Identifier]]) { def unroll: TentativeFormula = { - var newF = this.f + var newProgram = List[Expr]() var newRecTerms = Map[Identifier, Set[Identifier]]() + var newMappings = Map[Identifier, (Identifier, Expr)]() + for ((_, recIds) <- recTerms; recId <- recIds) { val gen = getGenerator(recId.getType) val alts = gen.altBuilder() ::: inputAlternatives(recId.getType) - println("For "+recId.getType+": "+alts) val altsWithBranches = alts.map(alt => FreshIdentifier("b", true).setType(BooleanType) -> alt) val pre = Or(altsWithBranches.map{ case (id, _) => Variable(id) }) // b1 OR b2 val cases = for((bid, (ex, rec)) <- altsWithBranches.toList) yield { // b1 => E(gen1, gen2) [b1 -> {gen1, gen2}] if (!rec.isEmpty) { newRecTerms += bid -> rec + } else { + newMappings += bid -> (recId -> ex) } + Implies(Variable(bid), Equals(Variable(recId), ex)) } - newF = And(newF, And(pre :: cases)) + newProgram = newProgram ::: pre :: cases } - TentativeFormula(newF, newRecTerms) + TentativeFormula(phi, And(program :: newProgram), mappings ++ newMappings, newRecTerms) } - def closedFormula = And(f :: recTerms.keySet.map(id => Not(Variable(id))).toList) + def bounds = recTerms.keySet.map(id => Not(Variable(id))).toList + def bss = mappings.keySet + + def entireFormula = And(phi :: program :: bounds) } var result: Option[RuleResult] = None @@ -285,38 +295,46 @@ class CEGISOnSteroids(synth: Synthesizer) extends Rule("cegis w. gen.", synth, 5 var ass = p.as.toSet var xss = p.xs.toSet - var lastF = TentativeFormula(And(p.c, p.phi), Map() ++ p.xs.map(x => x -> Set(x))) + var lastF = TentativeFormula(And(p.c, p.phi), BooleanLiteral(true), Map(), Map() ++ p.xs.map(x => x -> Set(x))) var currentF = lastF.unroll var unrolings = 0 val maxUnrolings = 2 do { - println("Was: "+lastF.closedFormula) - println("Now Trying : "+currentF.closedFormula) + println("Was: "+lastF.entireFormula) + println("Now Trying : "+currentF.entireFormula) val tpe = TupleType(p.xs.map(_.getType)) + val bss = currentF.bss var predicates: Seq[Expr] = Seq() var continue = true while (result.isEmpty && continue) { - val phi = And(currentF.closedFormula +: predicates) - synth.solver.solveSAT(phi) match { + val basePhi = currentF.entireFormula + val constrainedPhi = And(basePhi +: predicates) + println("-"*80) + println("To satisfy: "+constrainedPhi) + synth.solver.solveSAT(constrainedPhi) match { case (Some(true), satModel) => - var bss = satModel.keySet.filterNot(xss ++ ass) - println("Found candidate!: "+satModel) + println("Found candidate!: "+satModel.filterKeys(bss)) - val newPhi = valuateWithModelIn(phi, bss++xss, satModel) - println("new Phi: "+newPhi) + val fixedBss = And(bss.map(b => Equals(Variable(b), satModel(b))).toSeq) + println("Phi with fixed sat bss: "+fixedBss) - synth.solver.solveSAT(Not(newPhi)) match { + val counterPhi = Implies(And(fixedBss, currentF.program), currentF.phi) + println("Formula to validate: "+counterPhi) + + synth.solver.solveSAT(Not(counterPhi)) match { case (Some(true), invalidModel) => // Found as such as the xs break, refine predicates println("Found counter EX: "+invalidModel) - predicates = valuateWithModelIn(currentF.closedFormula, ass, invalidModel) +: predicates - println(valuateWithModelIn(currentF.closedFormula, ass, invalidModel)) + predicates = Not(And(bss.map(b => Equals(Variable(b), satModel(b))).toSeq)) +: predicates + println("Let's avoid this case: "+bss.map(b => Equals(Variable(b), satModel(b))).mkString(" ")) case (Some(false), _) => - result = Some(RuleSuccess(Solution(BooleanLiteral(true), Tuple(p.xs.map(valuateWithModel(satModel))).setType(tpe)))) + val mapping = currentF.mappings.filterKeys(satModel.mapValues(_ == BooleanLiteral(true))).values.toMap + println("Mapping: "+mapping) + result = Some(RuleSuccess(Solution(BooleanLiteral(true), Tuple(p.xs.map(valuateWithModel(mapping))).setType(tpe)))) case _ => } -- GitLab