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

Remove dependencies on solvers

parent afd2ebad
Branches
Tags
No related merge requests found
...@@ -11,32 +11,43 @@ import purescala.ExprOps._ ...@@ -11,32 +11,43 @@ import purescala.ExprOps._
import purescala.Extractors._ import purescala.Extractors._
import purescala.Constructors._ import purescala.Constructors._
import purescala.Definitions._ import purescala.Definitions._
import solvers._
case object ADTSplit extends Rule("ADT Split.") { case object ADTSplit extends Rule("ADT Split.") {
def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
val solver = SimpleSolverAPI(hctx.sctx.solverFactory.withTimeout(200L)) // We approximate knowledge of types based on facts found at the top-level
// we don't care if the variables are known to be equal or not, we just
// don't want to split on two variables for which only one split
// alternative is viable. This should be much less expensive than making
// calls to a solver for each pair.
var facts = Map[Identifier, CaseClassType]()
def addFacts(e: Expr): Unit = e match {
case Equals(Variable(a), CaseClass(cct, _)) => facts += a -> cct
case IsInstanceOf(Variable(a), cct: CaseClassType) => facts += a -> cct
case _ =>
}
val TopLevelAnds(as) = and(p.pc, p.phi)
for (e <- as) {
addFacts(e)
}
val candidates = p.as.collect { val candidates = p.as.collect {
case IsTyped(id, act @ AbstractClassType(cd, tpes)) => case IsTyped(id, act @ AbstractClassType(cd, tpes)) =>
val optCases = for (dcd <- cd.knownDescendants.sortBy(_.id.name)) yield dcd match { val optCases = cd.knownDescendants.sortBy(_.id.name).collect {
case ccd : CaseClassDef => case ccd : CaseClassDef =>
val cct = CaseClassType(ccd, tpes) val cct = CaseClassType(ccd, tpes)
val toSat = and(p.pc, IsInstanceOf(Variable(id), cct))
val isImplied = solver.solveSAT(toSat) match { if (facts contains id) {
case (Some(false), _) => true if (cct == facts(id)) {
case _ => false Seq(ccd)
} } else {
Nil
if (!isImplied) { }
Some(ccd)
} else { } else {
None Seq(ccd)
} }
case _ =>
None
} }
val cases = optCases.flatten val cases = optCases.flatten
......
...@@ -6,6 +6,7 @@ package rules ...@@ -6,6 +6,7 @@ package rules
import leon.purescala.Common.Identifier import leon.purescala.Common.Identifier
import purescala.Expressions._ import purescala.Expressions._
import purescala.Extractors._
import purescala.Constructors._ import purescala.Constructors._
import solvers._ import solvers._
...@@ -14,31 +15,31 @@ import scala.concurrent.duration._ ...@@ -14,31 +15,31 @@ import scala.concurrent.duration._
case object EqualitySplit extends Rule("Eq. Split") { case object EqualitySplit extends Rule("Eq. Split") {
def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
val solver = SimpleSolverAPI(hctx.sctx.solverFactory.withTimeout(50.millis)) // We approximate knowledge of equality based on facts found at the top-level
// we don't care if the variables are known to be equal or not, we just
// don't want to split on two variables for which only one split
// alternative is viable. This should be much less expensive than making
// calls to a solver for each pair.
var facts = Set[Set[Identifier]]()
val candidates = p.as.groupBy(_.getType).mapValues(_.combinations(2).filter { def addFacts(e: Expr): Unit = e match {
case List(a1, a2) => case Not(e) => addFacts(e)
val toValEQ = implies(p.pc, Equals(Variable(a1), Variable(a2))) case LessThan(Variable(a), Variable(b)) => facts += Set(a,b)
case LessEquals(Variable(a), Variable(b)) => facts += Set(a,b)
val impliesEQ = solver.solveSAT(Not(toValEQ)) match { case GreaterThan(Variable(a), Variable(b)) => facts += Set(a,b)
case (Some(false), _) => true case GreaterEquals(Variable(a), Variable(b)) => facts += Set(a,b)
case _ => false case Equals(Variable(a), Variable(b)) => facts += Set(a,b)
} case _ =>
}
if (!impliesEQ) {
val toValNE = implies(p.pc, not(Equals(Variable(a1), Variable(a2))))
val impliesNE = solver.solveSAT(Not(toValNE)) match { val TopLevelAnds(as) = and(p.pc, p.phi)
case (Some(false), _) => true for (e <- as) {
case _ => false addFacts(e)
} }
!impliesNE val candidates = p.as.groupBy(_.getType).mapValues{ as =>
} else { as.combinations(2).filterNot(facts contains _.toSet)
false }.values.flatten
}
case _ => false
}).values.flatten
candidates.flatMap { candidates.flatMap {
case List(a1, a2) => case List(a1, a2) =>
......
...@@ -7,53 +7,39 @@ package rules ...@@ -7,53 +7,39 @@ package rules
import purescala.Expressions._ import purescala.Expressions._
import purescala.Types._ import purescala.Types._
import purescala.Constructors._ import purescala.Constructors._
import purescala.Extractors._
import solvers._ import purescala.Common._
import scala.concurrent.duration._ import scala.concurrent.duration._
case object InequalitySplit extends Rule("Ineq. Split.") { case object InequalitySplit extends Rule("Ineq. Split.") {
def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = { def instantiateOn(implicit hctx: SearchContext, p: Problem): Traversable[RuleInstantiation] = {
val solver = SimpleSolverAPI(hctx.sctx.solverFactory.withTimeout(50.millis)) // We approximate knowledge of equality based on facts found at the top-level
// we don't care if the variables are known to be equal or not, we just
// don't want to split on two variables for which only one split
// alternative is viable. This should be much less expensive than making
// calls to a solver for each pair.
var facts = Set[Set[Identifier]]()
def addFacts(e: Expr): Unit = e match {
case Not(e) => addFacts(e)
case LessThan(Variable(a), Variable(b)) => facts += Set(a,b)
case LessEquals(Variable(a), Variable(b)) => facts += Set(a,b)
case GreaterThan(Variable(a), Variable(b)) => facts += Set(a,b)
case GreaterEquals(Variable(a), Variable(b)) => facts += Set(a,b)
case Equals(Variable(a), Variable(b)) => facts += Set(a,b)
case _ =>
}
val TopLevelAnds(as) = and(p.pc, p.phi)
for (e <- as) {
addFacts(e)
}
val argsPairs = p.as.filter(_.getType == IntegerType).combinations(2) ++ val argsPairs = p.as.filter(_.getType == IntegerType).combinations(2) ++
p.as.filter(_.getType == Int32Type).combinations(2) p.as.filter(_.getType == Int32Type).combinations(2)
val candidates = argsPairs.toList.filter { val candidates = argsPairs.toList.filter { case List(a1, a2) => !(facts contains Set(a1, a2)) }
case List(a1, a2) =>
val toValLT = implies(p.pc, LessThan(Variable(a1), Variable(a2)))
val impliesLT = solver.solveSAT(not(toValLT)) match {
case (Some(false), _) => true
case _ => false
}
if (!impliesLT) {
val toValGT = implies(p.pc, GreaterThan(Variable(a1), Variable(a2)))
val impliesGT = solver.solveSAT(not(toValGT)) match {
case (Some(false), _) => true
case _ => false
}
if (!impliesGT) {
val toValEQ = implies(p.pc, Equals(Variable(a1), Variable(a2)))
val impliesEQ = solver.solveSAT(not(toValEQ)) match {
case (Some(false), _) => true
case _ => false
}
!impliesEQ
} else {
false
}
} else {
false
}
case _ => false
}
candidates.flatMap { candidates.flatMap {
case List(a1, a2) => case List(a1, a2) =>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment