From 3e6458b5eac575e8f3faa5d06046d2de80bcdb95 Mon Sep 17 00:00:00 2001 From: Nicolas Voirol <voirol.nicolas@gmail.com> Date: Wed, 24 Jun 2015 13:59:34 +0200 Subject: [PATCH] Prepatations for sets/arrays/maps --- .../templates/QuantificationManager.scala | 23 +++++------ .../solvers/templates/TemplateGenerator.scala | 38 +++++++++++-------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/src/main/scala/leon/solvers/templates/QuantificationManager.scala b/src/main/scala/leon/solvers/templates/QuantificationManager.scala index 57dc368eb..3bb4374bd 100644 --- a/src/main/scala/leon/solvers/templates/QuantificationManager.scala +++ b/src/main/scala/leon/solvers/templates/QuantificationManager.scala @@ -16,6 +16,9 @@ case class Matcher[T](caller: T, tpe: TypeTree, args: Seq[T]) { override def toString = "M(" + caller + " : " + tpe + ", " + args.mkString("(",",",")") + ")" } +case class IllegalQuantificationException(expr: Expr, msg: String) + extends Exception(msg +" @ " + expr) + class QuantificationTemplate[T]( val quantificationManager: QuantificationManager[T], val start: T, @@ -147,9 +150,7 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage applications map { case (b, fas) => substituter(b) -> fas.map(fa => fa.copy(caller = substituter(fa.caller), args = fa.args.map(substituter))) }, - matchers map { case m @ Matcher(caller, _, args) => - m.copy(caller = substituter(caller), args = args.map(substituter)) - }, + matchers map (m => m.copy(caller = substituter(m.caller), args = m.args.map(substituter))), lambdas map { case (idT, template) => substituter(idT) -> template.substitute(subst) } ) } @@ -164,7 +165,7 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage val matcherMappings: Set[Set[(T, Matcher[T], Matcher[T])]] = matchers // 1. select an application in the quantified proposition for which the current app can // be bound when generating the new constraints - .filter(qm => qm.caller == caller || (qm.tpe == tpe && !known(qm.caller))) + .filter(_.tpe == tpe) // 2. build the instantiation mapping associated to the chosen current application binding .flatMap { bindingMatcher => matchers // 2.1. select all potential matches for each quantified application @@ -173,16 +174,12 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage bindingMatcher -> Set(blocker -> matcher) } else { val instances: Set[(T, Matcher[T])] = instantiated.filter { - case (b, m @ Matcher(caller, tpe, _)) => tpe == qtpe && (qcaller == caller || !known(caller)) + case (b, m @ Matcher(caller, tpe, _)) => tpe == qtpe } // concrete applications can appear multiple times in the constraint, and this is also the case // for the current application for which we are generating the constraints - val withCurrent = if (tpe == qtpe && (qcaller == caller || !known(caller))) { - instances + (blocker -> matcher) - } else instances - - println(qm -> withCurrent) + val withCurrent = if (tpe == qtpe) instances + (blocker -> matcher) else instances qm -> withCurrent } @@ -234,8 +231,8 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage def instantiateQuantification(template: QuantificationTemplate[T], substMap: Map[T, T]): Instantiation[T] = { - val instantiationSubst: Map[T, T] = substMap + - (template.guardVar -> encoder.encodeExpr(Map.empty)(BooleanLiteral(true))) + val trueT = encoder.encodeExpr(Map.empty)(BooleanLiteral(true)) + val instantiationSubst: Map[T, T] = substMap + (template.guardVar -> trueT) val substituter = encoder.substitute(instantiationSubst) val matchers = template.matchers.map { case (b, ms) => @@ -288,7 +285,7 @@ class QuantificationManager[T](encoder: TemplateEncoder[T]) extends LambdaManage val eqClause = { val qs = newQuantifications.map(_.qVar) - val newQs = if (qs.size > 1) encoder.mkAnd(qs : _*) else qs.head + val newQs = if (qs.isEmpty) trueT else if (qs.size == 1) qs.head else encoder.mkAnd(qs : _*) encoder.mkImplies(substMap(template.start), encoder.mkEquals(template.holdVar, newQs)) } diff --git a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala index 9b974a8de..9942cc3b7 100644 --- a/src/main/scala/leon/solvers/templates/TemplateGenerator.scala +++ b/src/main/scala/leon/solvers/templates/TemplateGenerator.scala @@ -281,26 +281,34 @@ class TemplateGenerator[T](val encoder: TemplateEncoder[T], Variable(lid) case f @ Forall(args, body) => - val idQuantifiers : Seq[Identifier] = args.map(_.id) - val trQuantifiers : Seq[T] = idQuantifiers.map(encoder.encodeId) + val TopLevelAnds(conjuncts) = body - val q: Identifier = FreshIdentifier("q", BooleanType) - val ph: Identifier = FreshIdentifier("ph", BooleanType) - val guard: Identifier = FreshIdentifier("guard", BooleanType) + val conjunctQs = conjuncts.map { conjunct => + val vars = variablesOf(conjunct) + val quantifiers = args.map(_.id).filter(vars).toSet - val clause = Equals(Variable(q), And(Variable(ph), Implies(Variable(guard), body))) + val idQuantifiers : Seq[Identifier] = quantifiers.toSeq + val trQuantifiers : Seq[T] = idQuantifiers.map(encoder.encodeId) - val qs: (Identifier, T) = q -> encoder.encodeId(q) - val localSubst: Map[Identifier, T] = substMap ++ condVars ++ exprVars ++ lambdaVars - val clauseSubst: Map[Identifier, T] = localSubst ++ (idQuantifiers zip trQuantifiers) - val (qConds, qExprs, qGuarded, qTemplates, qQuants) = mkClauses(pathVar, clause, clauseSubst) - assert(qQuants.isEmpty, "Unhandled nested quantification in "+clause) + val q: Identifier = FreshIdentifier("q", BooleanType) + val ph: Identifier = FreshIdentifier("ph", BooleanType) + val guard: Identifier = FreshIdentifier("guard", BooleanType) + + val clause = Equals(Variable(q), And(Variable(ph), Implies(Variable(guard), conjunct))) - val template = QuantificationTemplate[T](encoder, manager, pathVar -> encodedCond(pathVar), - qs, ph, guard, idQuantifiers zip trQuantifiers, qConds, qExprs, qGuarded, qTemplates, localSubst) - registerQuantification(template) + val qs: (Identifier, T) = q -> encoder.encodeId(q) + val localSubst: Map[Identifier, T] = substMap ++ condVars ++ exprVars ++ lambdaVars + val clauseSubst: Map[Identifier, T] = localSubst ++ (idQuantifiers zip trQuantifiers) + val (qConds, qExprs, qGuarded, qTemplates, qQuants) = mkClauses(pathVar, clause, clauseSubst) + assert(qQuants.isEmpty, "Unhandled nested quantification in "+clause) + + val template = QuantificationTemplate[T](encoder, manager, pathVar -> encodedCond(pathVar), + qs, ph, guard, idQuantifiers zip trQuantifiers, qConds, qExprs, qGuarded, qTemplates, localSubst) + registerQuantification(template) + Variable(q) + } - Variable(q) + andJoin(conjunctQs) case Operator(as, r) => r(as.map(a => rec(pathVar, a))) } -- GitLab