Skip to content
Snippets Groups Projects
Commit f2245cc1 authored by Etienne Kneuss's avatar Etienne Kneuss
Browse files

Indirection for inlining to prevent duplicate clauses being issued to Z3

parent 37bcf2bd
No related branches found
No related tags found
No related merge requests found
...@@ -162,29 +162,27 @@ class FairZ3Solver(val context : LeonContext, val program: Program) ...@@ -162,29 +162,27 @@ class FairZ3Solver(val context : LeonContext, val program: Program)
def blockersInfo = blockersInfoStack.head def blockersInfo = blockersInfoStack.head
// Note that this computes cumulated sets.
private var unlockedStack : List[MutableSet[Z3AST]] = List(MutableSet())
def unlockedSet : MutableSet[Z3AST] = unlockedStack.head
def wasUnlocked(id : Z3AST) : Boolean = unlockedStack.head(id)
def push() { def push() {
blockersInfoStack = (MutableMap() ++ blockersInfo) :: blockersInfoStack blockersInfoStack = (MutableMap() ++ blockersInfo) :: blockersInfoStack
unlockedStack = (MutableSet() ++ unlockedStack.head) :: unlockedStack
} }
def pop(lvl: Int) { def pop(lvl: Int) {
blockersInfoStack = blockersInfoStack.drop(lvl) blockersInfoStack = blockersInfoStack.drop(lvl)
unlockedStack = unlockedStack.drop(lvl)
} }
def z3CurrentZ3Blockers = blockersInfo.map(_._2._3) def z3CurrentZ3Blockers = blockersInfo.map(_._2._3)
def finfo(fi: Z3FunctionInvocation) = {
fi.tfd.id.uniqueName+fi.args.mkString("(", ", ", ")")
}
def dumpBlockers = { def dumpBlockers = {
blockersInfo.groupBy(_._2._1).toSeq.sortBy(_._1).foreach { case (gen, entries) => blockersInfo.groupBy(_._2._1).toSeq.sortBy(_._1).foreach { case (gen, entries) =>
reporter.debug("--- "+gen) reporter.debug("--- "+gen)
for (((bast), (gen, origGen, ast, fis)) <- entries) { for (((bast), (gen, origGen, ast, fis)) <- entries) {
reporter.debug(". "+bast +" ~> "+fis.map(_.tfd.signature)) reporter.debug(f". $bast%15s ~> "+fis.map(finfo).mkString(", "))
} }
} }
} }
...@@ -202,20 +200,18 @@ class FairZ3Solver(val context : LeonContext, val program: Program) ...@@ -202,20 +200,18 @@ class FairZ3Solver(val context : LeonContext, val program: Program)
} }
private def registerBlocker(gen: Int, id: Z3AST, fis: Set[Z3FunctionInvocation]) { private def registerBlocker(gen: Int, id: Z3AST, fis: Set[Z3FunctionInvocation]) {
if (!wasUnlocked(id)) { val z3ast = z3.mkNot(id)
val z3ast = z3.mkNot(id) blockersInfo.get(id) match {
blockersInfo.get(id) match { case Some((exGen, origGen, _, exFis)) =>
case Some((exGen, origGen, _, exFis)) => // PS: when recycling `b`s, this assertion becomes dangerous.
// PS: when recycling `b`s, this assertion becomes dangerous. // It's better to simply take the max of the generations.
// It's better to simply take the max of the generations. // assert(exGen == gen, "Mixing the same id "+id+" with various generations "+ exGen+" and "+gen)
// assert(exGen == gen, "Mixing the same id "+id+" with various generations "+ exGen+" and "+gen)
val maxGen = gen max exGen val minGen = gen min exGen
blockersInfo(id) = ((maxGen, origGen, z3ast, fis++exFis)) blockersInfo(id) = ((minGen, origGen, z3ast, fis++exFis))
case None => case None =>
blockersInfo(id) = ((gen, gen, z3ast, fis)) blockersInfo(id) = ((gen, gen, z3ast, fis))
}
} }
} }
...@@ -267,35 +263,61 @@ class FairZ3Solver(val context : LeonContext, val program: Program) ...@@ -267,35 +263,61 @@ class FairZ3Solver(val context : LeonContext, val program: Program)
} }
} }
def unlock(id: Z3AST) : Seq[Z3AST] = { private var defBlockers = Map[Z3FunctionInvocation, Z3AST]()
assert(blockersInfo contains id)
assert(!wasUnlocked(id))
val (gen, origGen, _, fis) = blockersInfo(id) def unlock(ids: Seq[Z3AST]) : Seq[Z3AST] = {
assert(ids.forall(id => blockersInfo contains id))
blockersInfo -= id
var newClauses : Seq[Z3AST] = Seq.empty var newClauses : Seq[Z3AST] = Seq.empty
var reintroducedSelf : Boolean = false for (id <- ids) {
val (gen, _, _, fis) = blockersInfo(id)
blockersInfo -= id
for(fi <- fis) { var reintroducedSelf = false
val template = getTemplate(fi.tfd)
val (newExprs, newBlocks) = template.instantiate(id, fi.args)
for((i, fis2) <- newBlocks) { for (fi <- fis) {
registerBlocker(nextGeneration(gen), i, fis2) val defBlocker = defBlockers.get(fi) match {
if(i == id) { case Some(defBlocker) =>
reintroducedSelf = true // we already have defBlocker => f(args) = body
defBlocker
case None =>
// we need to define this defBlocker and link it to definition
val defBlocker = z3.mkFreshConst("d", z3.mkBoolSort)
defBlockers += fi -> defBlocker
val template = getTemplate(fi.tfd)
val (newExprs, newBlocks) = template.instantiate(defBlocker, fi.args)
for((i, fis2) <- newBlocks) {
registerBlocker(nextGeneration(gen), i, fis2)
}
newClauses ++= newExprs
defBlocker
}
// We connect it to the defBlocker: blocker => defBlocker
if (defBlocker != id) {
newClauses ++= List(z3.mkImplies(id, defBlocker))
} }
} }
newClauses ++= newExprs
} }
if(!reintroducedSelf) { context.reporter.debug(s" - ${newClauses.size} new clauses")
unlockedSet += id //context.reporter.ifDebug { debug =>
} // debug(s" - new clauses:")
// debug("@@@@")
// for (cl <- newClauses) {
// debug(""+cl)
// }
// debug("////")
//}
//dumpBlockers
//readLine()
newClauses newClauses
} }
...@@ -387,9 +409,9 @@ class FairZ3Solver(val context : LeonContext, val program: Program) ...@@ -387,9 +409,9 @@ class FairZ3Solver(val context : LeonContext, val program: Program)
reporter.debug(" - Running Z3 search...") reporter.debug(" - Running Z3 search...")
// reporter.debug("Searching in:\n"+solver.getAssertions.toSeq.mkString("\nAND\n")) //reporter.debug("Searching in:\n"+solver.getAssertions.toSeq.mkString("\nAND\n"))
// reporter.debug("Unroll. Assumptions:\n"+unrollingBank.z3CurrentZ3Blockers.mkString(" && ")) //reporter.debug("Unroll. Assumptions:\n"+unrollingBank.z3CurrentZ3Blockers.mkString(" && "))
// reporter.debug("Userland Assumptions:\n"+assumptionsAsZ3.mkString(" && ")) //reporter.debug("Userland Assumptions:\n"+assumptionsAsZ3.mkString(" && "))
solver.push() // FIXME: remove when z3 bug is fixed solver.push() // FIXME: remove when z3 bug is fixed
val res = solver.checkAssumptions((assumptionsAsZ3 ++ unrollingBank.z3CurrentZ3Blockers) :_*) val res = solver.checkAssumptions((assumptionsAsZ3 ++ unrollingBank.z3CurrentZ3Blockers) :_*)
...@@ -515,12 +537,10 @@ class FairZ3Solver(val context : LeonContext, val program: Program) ...@@ -515,12 +537,10 @@ class FairZ3Solver(val context : LeonContext, val program: Program)
reporter.debug(" - more unrollings") reporter.debug(" - more unrollings")
for(id <- toRelease) { val newClauses = unrollingBank.unlock(toRelease)
val newClauses = unrollingBank.unlock(id)
for(ncl <- newClauses) { for(ncl <- newClauses) {
solver.assertCnstr(ncl) solver.assertCnstr(ncl)
}
} }
reporter.debug(" - finished unrolling") reporter.debug(" - finished unrolling")
......
...@@ -16,7 +16,9 @@ import z3.scala._ ...@@ -16,7 +16,9 @@ import z3.scala._
import scala.collection.mutable.{Set=>MutableSet,Map=>MutableMap} import scala.collection.mutable.{Set=>MutableSet,Map=>MutableMap}
case class Z3FunctionInvocation(tfd: TypedFunDef, args: Seq[Z3AST]) case class Z3FunctionInvocation(tfd: TypedFunDef, args: Seq[Z3AST]) {
override def toString = tfd.signature + args.mkString("(", ",", ")")
}
class FunctionTemplate private( class FunctionTemplate private(
solver: FairZ3Solver, solver: FairZ3Solver,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment