From 213c124874d3dd987333efee9f879dd9b35d320b Mon Sep 17 00:00:00 2001 From: Philippe Suter <philippe.suter@gmail.com> Date: Wed, 31 Oct 2012 15:25:52 +0100 Subject: [PATCH] path-aware simplifications (untested for now) --- src/main/scala/leon/purescala/TreeOps.scala | 72 +++++++++++++++++++ .../leon/test/purescala/TreeOpsTest.scala | 29 ++++++++ 2 files changed, 101 insertions(+) create mode 100644 src/test/scala/leon/test/purescala/TreeOpsTest.scala diff --git a/src/main/scala/leon/purescala/TreeOps.scala b/src/main/scala/leon/purescala/TreeOps.scala index 802d72ed9..6bc44b67c 100644 --- a/src/main/scala/leon/purescala/TreeOps.scala +++ b/src/main/scala/leon/purescala/TreeOps.scala @@ -1218,4 +1218,76 @@ object TreeOps { simplePreTransform(pre)(expr) } + + // NOTE : this is currently untested, use at your own risk ! + // (or better yet, write tests for it) + // PS + def simplifyPaths(solver : Solver)(expr : Expr) : Expr = { + def impliedBy(e : Expr, path : Seq[Expr]) : Boolean = { + solver.solve(Implies(And(path), e)) match { + case Some(true) => true + case _ => false + } + } + + def contradictedBy(e : Expr, path : Seq[Expr]) : Boolean = { + solver.solve(Implies(And(path), Not(e))) match { + case Some(true) => true + case _ => false + } + } + + def rec(e : Expr, path : Seq[Expr]): Expr = e match { + + case IfExpr(cond, then, elze) => + val rc = rec(cond, path) + rc match { + case BooleanLiteral(true) => rec(then, path) + case BooleanLiteral(false) => rec(elze, path) + case _ => IfExpr(rc, rec(then, rc +: path), rec(elze, Not(rc) +: path)) + } + + case And(es) => + var extPath = path + var continue = true + And(for(e <- es if continue) yield { + val se = rec(e, extPath) + if(se == BooleanLiteral(false)) continue = false + extPath = se +: extPath + se + }) + + case Or(es) => + var extPath = path + var continue = true + Or(for(e <- es if continue) yield { + val se = rec(e, extPath) + if(se == BooleanLiteral(true)) continue = true + extPath = se +: extPath + se + }) + + case b if b.getType == BooleanType && impliedBy(b, path) => + BooleanLiteral(true) + + case b if b.getType == BooleanType && contradictedBy(b, path) => + BooleanLiteral(false) + + case UnaryOperator(e, builder) => + builder(rec(e, path)) + + case BinaryOperator(e1, e2, builder) => + builder(rec(e1, path), rec(e2, path)) + + case NAryOperator(es, builder) => + builder(es.map(rec(_, path))) + + case t : Terminal => t + + case _ => + sys.error("Expression "+e+" ["+e.getClass+"] is not extractable") + } + + rec(expr, Nil) + } } diff --git a/src/test/scala/leon/test/purescala/TreeOpsTest.scala b/src/test/scala/leon/test/purescala/TreeOpsTest.scala new file mode 100644 index 000000000..a0ee0fdf3 --- /dev/null +++ b/src/test/scala/leon/test/purescala/TreeOpsTest.scala @@ -0,0 +1,29 @@ +package leon.test.purescala + +import leon.purescala.Common._ +import leon.purescala.Definitions._ +import leon.purescala.Trees._ +import leon.purescala.TreeOps._ +import leon.SilentReporter + +import org.scalatest.FunSuite + +class TreeOpsTest extends FunSuite { + private val silentReporter = new SilentReporter + + private val emptyProgram = Program( + FreshIdentifier("Empty"), + ObjectDef(FreshIdentifier("Empty"), Seq.empty, Seq.empty) + ) + + test("Path-aware simplifications") { + import leon.solvers.z3.UninterpretedZ3Solver + val solver = new UninterpretedZ3Solver(silentReporter) + solver.setProgram(emptyProgram) + + // TODO actually testing something here would be better, sorry + // PS + + assert(true) + } +} -- GitLab