From ad4973722815928bfda74292973eb01437ddaa61 Mon Sep 17 00:00:00 2001 From: Nicolas Voirol <voirol.nicolas@gmail.com> Date: Fri, 4 Nov 2016 12:57:56 +0100 Subject: [PATCH] Reworked lambda equality for models returned by underlying solvers --- src/main/scala/inox/ast/SymbolOps.scala | 15 +++++++-------- .../scala/inox/solvers/smtlib/SMTLIBTarget.scala | 3 ++- .../solvers/unrolling/TemplateGenerator.scala | 6 +++--- .../inox/solvers/unrolling/UnrollingSolver.scala | 3 ++- .../scala/inox/solvers/z3/AbstractZ3Solver.scala | 2 +- 5 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/main/scala/inox/ast/SymbolOps.scala b/src/main/scala/inox/ast/SymbolOps.scala index 199330771..9e170a10a 100644 --- a/src/main/scala/inox/ast/SymbolOps.scala +++ b/src/main/scala/inox/ast/SymbolOps.scala @@ -198,7 +198,7 @@ trait SymbolOps { self: TypeOps => /** Ensures the closure [[l]] can only be equal to some other closure if they share * the same integer identifier [[id]]. This method makes sure this property is * preserved after going through [[normalizeStructure(Lambda)]]. */ - def uniquateClosure(id: BigInt, res: Lambda): Lambda = { + def uniquateClosure(id: Int, res: Lambda): Lambda = { def allArgs(l: Lambda): Seq[ValDef] = l.args ++ (l.body match { case l2: Lambda => allArgs(l2) case _ => Seq.empty @@ -207,13 +207,12 @@ trait SymbolOps { self: TypeOps => val resArgs = allArgs(res) if (resArgs.isEmpty) res else { /* @nv: This is a hack to ensure that the notion of equality we define on closures - * is respected by those returned by the model. The second `Let` is necessary - * to keep [[normalizeStructure(Lambda)]] from lifting the first one out of - * the closure's body. */ - Lambda(res.args, - Let(ValDef(FreshIdentifier("id"), IntegerType), IntegerLiteral(id), - Let(ValDef(FreshIdentifier("denormalize"), resArgs.head.tpe), resArgs.head.toVariable, - res.body))) + * is respected by those returned by the model. */ + Lambda(res.args, Let( + ValDef(FreshIdentifier("id"), tupleTypeWrap(List.fill(id)(resArgs.head.tpe))), + tupleWrap(List.fill(id)(resArgs.head.toVariable)), + res.body + )) } } diff --git a/src/main/scala/inox/solvers/smtlib/SMTLIBTarget.scala b/src/main/scala/inox/solvers/smtlib/SMTLIBTarget.scala index 2b71f2ccf..dfbeebdaa 100644 --- a/src/main/scala/inox/solvers/smtlib/SMTLIBTarget.scala +++ b/src/main/scala/inox/solvers/smtlib/SMTLIBTarget.scala @@ -477,7 +477,8 @@ trait SMTLIBTarget extends Interruptible with ADTManagers { def extractLambda(n: BigInt, ft: FunctionType): Lambda = { val FunctionType(from, to) = ft - uniquateClosure(n, (lambdas.getB(ft) match { + val count = if (n < 0) -2 * n.toInt else 2 * n.toInt + 1 + uniquateClosure(count, (lambdas.getB(ft) match { case None => simplestValue(ft) case Some(dynLambda) => letDefs.get(dynLambda) match { case None => simplestValue(ft) diff --git a/src/main/scala/inox/solvers/unrolling/TemplateGenerator.scala b/src/main/scala/inox/solvers/unrolling/TemplateGenerator.scala index 12e758e6a..37e41c6aa 100644 --- a/src/main/scala/inox/solvers/unrolling/TemplateGenerator.scala +++ b/src/main/scala/inox/solvers/unrolling/TemplateGenerator.scala @@ -287,14 +287,14 @@ trait TemplateGenerator { self: Templates => case _ => (Seq.empty, e) } - extractBody(struct) match { + !l.getType.isInstanceOf[FunctionType] && (extractBody(struct) match { case (params, ApplicationExtractor(caller: Variable, args)) => (params.map(_.toVariable) == args) && (deps.get(caller) match { - case Some(_: Application | _: FunctionInvocation) => true + case Some(_: Application | _: FunctionInvocation | _: Variable) => true case _ => false }) case _ => false - } + }) } val depsByScope: Seq[(Variable, Expr)] = { diff --git a/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala b/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala index 28081283e..e08ece074 100644 --- a/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala +++ b/src/main/scala/inox/solvers/unrolling/UnrollingSolver.scala @@ -325,7 +325,8 @@ trait AbstractUnrollingSolver extends Solver { self => )=> Left(img) }) match { case Some(Right(enc)) => wrapped.eval(enc, tpe).get match { - case Lambda(_, Let(_, IntegerLiteral(n), _)) => uniquateClosure(n, lambda) + case Lambda(_, Let(_, Tuple(es), _)) => + uniquateClosure(if (es.size % 2 == 0) -es.size / 2 else es.size / 2, lambda) case l => scala.sys.error("Unexpected extracted lambda format: " + l) } case Some(Left(img)) => img diff --git a/src/main/scala/inox/solvers/z3/AbstractZ3Solver.scala b/src/main/scala/inox/solvers/z3/AbstractZ3Solver.scala index 59a16643c..034d53dc2 100644 --- a/src/main/scala/inox/solvers/z3/AbstractZ3Solver.scala +++ b/src/main/scala/inox/solvers/z3/AbstractZ3Solver.scala @@ -581,7 +581,7 @@ trait AbstractZ3Solver } else { tpe match { case ft @ FunctionType(fts, tt) => - val n = BigInt(t.toString.split("!").last.init) + val n = t.toString.split("!").last.init.toInt uniquateClosure(n, (lambdas.getB(ft) match { case None => simplestValue(ft) case Some(decl) => model.getFuncInterpretations.find(_._1 == decl) match { -- GitLab