summaryrefslogtreecommitdiff
path: root/src/theory
diff options
context:
space:
mode:
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>2021-04-27 16:25:11 -0500
committerGitHub <noreply@github.com>2021-04-27 21:25:11 +0000
commitd524948b58c4c3f61c623649049f6209b7756ed6 (patch)
treeed35c98dbcb5428b9e4ba6db18f891df985ab1a3 /src/theory
parent187bbe04f54798f84b404dc61d2a9d221130109d (diff)
Fix refutational soundness bug in quantifier prenexing (#6448)
This bug can be triggered by define-fun, quantifier macros or inferred substitutions whose RHS contain quantified formulas. This corrects the issue by ensuring that bound variables introduced for prenexing are fresh for distinct quantified formula subterms that may share quantified variables. This was reported by Geoff Sutcliffe via a TPTP run.
Diffstat (limited to 'src/theory')
-rw-r--r--src/theory/quantifiers/quantifiers_macros.cpp19
-rw-r--r--src/theory/quantifiers/quantifiers_macros.h5
-rw-r--r--src/theory/quantifiers/quantifiers_rewriter.cpp7
3 files changed, 24 insertions, 7 deletions
diff --git a/src/theory/quantifiers/quantifiers_macros.cpp b/src/theory/quantifiers/quantifiers_macros.cpp
index c7d74228f..43a404ff9 100644
--- a/src/theory/quantifiers/quantifiers_macros.cpp
+++ b/src/theory/quantifiers/quantifiers_macros.cpp
@@ -41,9 +41,9 @@ Node QuantifiersMacros::solve(Node lit, bool reqGround)
{
return Node::null();
}
- lit = lit[1];
- bool pol = lit.getKind() != NOT;
- Node n = pol ? lit : lit[0];
+ Node body = lit[1];
+ bool pol = body.getKind() != NOT;
+ Node n = pol ? body : body[0];
NodeManager* nm = NodeManager::currentNM();
if (n.getKind() == APPLY_UF)
{
@@ -54,7 +54,7 @@ Node QuantifiersMacros::solve(Node lit, bool reqGround)
Node n_def = nm->mkConst(pol);
Node fdef = solveEq(n, n_def);
Assert(!fdef.isNull());
- return fdef;
+ return returnMacro(fdef, lit);
}
}
else if (pol && n.getKind() == EQUAL)
@@ -89,14 +89,14 @@ Node QuantifiersMacros::solve(Node lit, bool reqGround)
<< "...does not contain bad (recursive) operator." << std::endl;
// must be ground UF term if mode is GROUND_UF
if (options::macrosQuantMode() != options::MacrosQuantMode::GROUND_UF
- || preservesTriggerVariables(lit, n_def))
+ || preservesTriggerVariables(body, n_def))
{
Trace("macros-debug")
<< "...respects ground-uf constraint." << std::endl;
Node fdef = solveEq(m, n_def);
if (!fdef.isNull())
{
- return fdef;
+ return returnMacro(fdef, lit);
}
}
}
@@ -278,6 +278,13 @@ Node QuantifiersMacros::solveEq(Node n, Node ndef)
return op.eqNode(fdef);
}
+Node QuantifiersMacros::returnMacro(Node fdef, Node lit) const
+{
+ Trace("macros") << "* Inferred macro " << fdef << " from " << lit
+ << std::endl;
+ return fdef;
+}
+
} // namespace quantifiers
} // namespace theory
} // namespace cvc5
diff --git a/src/theory/quantifiers/quantifiers_macros.h b/src/theory/quantifiers/quantifiers_macros.h
index 77ce91829..91b44b520 100644
--- a/src/theory/quantifiers/quantifiers_macros.h
+++ b/src/theory/quantifiers/quantifiers_macros.h
@@ -87,6 +87,11 @@ class QuantifiersMacros
* where n is of the form U(x1...xn).
*/
Node solveEq(Node n, Node ndef);
+ /**
+ * Returns the macro fdef, which originated from lit. This method is for
+ * debugging.
+ */
+ Node returnMacro(Node fdef, Node lit) const;
/** Reference to the quantifiers registry */
QuantifiersRegistry& d_qreg;
};
diff --git a/src/theory/quantifiers/quantifiers_rewriter.cpp b/src/theory/quantifiers/quantifiers_rewriter.cpp
index 123ffee7d..3df5aa65f 100644
--- a/src/theory/quantifiers/quantifiers_rewriter.cpp
+++ b/src/theory/quantifiers/quantifiers_rewriter.cpp
@@ -1267,7 +1267,12 @@ Node QuantifiersRewriter::computePrenex(
Node vv;
if (!q.isNull())
{
- Node cacheVal = BoundVarManager::getCacheValue(q, v);
+ // We cache based on the original quantified formula, the subformula
+ // that we are pulling variables from (body), and the variable v.
+ // The argument body is required since in rare cases, two subformulas
+ // may share the same variables. This is the case for define-fun
+ // or inferred substitutions that contain quantified formulas.
+ Node cacheVal = BoundVarManager::getCacheValue(q, body, v);
vv = bvm->mkBoundVar<QRewPrenexAttribute>(cacheVal, vt);
}
else
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback