This PR eliminates all uses of assertions pipeline that are not proper, which two-fold:
(1) The assertion list should never be modified in a custom way (without going through replace / push_back),
(2) Places where an assertion is "conjoined" to an existing spot in the vector should use conjoin instead of replace.
This is required for proper proof generation.
This fixes CVC4/cvc4-projects#75.
*/
void clear();
- /** TODO (projects #75): remove this */
- Node& operator[](size_t i) { return d_nodes[i]; }
- /** Get the assertion at index i */
const Node& operator[](size_t i) const { return d_nodes[i]; }
/**
/** Same as above, with TrustNode */
void pushBackTrusted(theory::TrustNode trn);
- /** TODO (projects #75): remove this */
- std::vector<Node>& ref() { return d_nodes; }
-
/**
* Get the constant reference to the underlying assertions. It is only
* possible to modify these via the replace methods below.
* @param n The substitution node
* @param pg The proof generator that can provide a proof of n.
*/
- void addSubstitutionNode(Node n, ProofGenerator* pgen = nullptr);
+ void addSubstitutionNode(Node n, ProofGenerator* pg = nullptr);
/**
* Conjoin n to the assertion vector at position i. This replaces
for (size_t i = 0, size = assertions->size(); i < size; ++i)
{
Node old = (*assertions)[i];
- assertions->replace(i, usVarsToBVVars.apply((*assertions)[i]));
- Trace("uninterpretedSorts-to-bv")
- << " " << old << " => " << (*assertions)[i] << "\n";
+ Node newA = usVarsToBVVars.apply((*assertions)[i]);
+ if (newA != old)
+ {
+ assertions->replace(i, newA);
+ Trace("uninterpretedSorts-to-bv")
+ << " " << old << " => " << (*assertions)[i] << "\n";
+ }
}
}
}
}
std::unordered_map<Node, Node, NodeHashFunction> subst;
- std::vector<Node>& atpp = assertionsToPreprocess->ref();
+ NodeManager* nm = NodeManager::currentNM();
for (const auto& eq : equations)
{
if (eq.second.size() <= 1) { continue; }
<< std::endl;
if (ret != BVGauss::Result::INVALID)
{
- NodeManager *nm = NodeManager::currentNM();
if (ret == BVGauss::Result::NONE)
{
- atpp.clear();
- atpp.push_back(nm->mkConst<bool>(false));
+ assertionsToPreprocess->clear();
+ Node n = nm->mkConst<bool>(false);
+ assertionsToPreprocess->push_back(n);
+ return PreprocessingPassResult::CONFLICT;
}
else
{
{
Node a = nm->mkNode(kind::EQUAL, p.first, p.second);
Trace("bv-gauss-elim") << "added assertion: " << a << std::endl;
- atpp.push_back(a);
+ // add new assertion
+ assertionsToPreprocess->push_back(a);
}
}
}
if (!subst.empty())
{
/* delete (= substitute with true) obsolete assertions */
- for (auto& a : atpp)
+ const std::vector<Node>& aref = assertionsToPreprocess->ref();
+ for (size_t i = 0, asize = aref.size(); i < asize; ++i)
{
- a = a.substitute(subst.begin(), subst.end());
+ Node a = aref[i];
+ Node as = a.substitute(subst.begin(), subst.end());
+ // replace the assertion
+ assertionsToPreprocess->replace(i, as);
}
}
return PreprocessingPassResult::NO_CONFLICT;
namespace preprocessing {
namespace passes {
-Node GlobalNegate::simplify(std::vector<Node>& assertions, NodeManager* nm)
+Node GlobalNegate::simplify(const std::vector<Node>& assertions,
+ NodeManager* nm)
{
Assert(!assertions.empty());
Trace("cegqi-gn") << "Global negate : " << std::endl;
AssertionPipeline* assertionsToPreprocess) override;
private:
- Node simplify(std::vector<Node>& assertions, NodeManager* nm);
+ Node simplify(const std::vector<Node>& assertions, NodeManager* nm);
};
} // namespace passes
// add lambda lifting axioms as a conjunction to the first assertion
if (!axioms.empty())
{
- Node orig = (*assertionsToPreprocess)[0];
- axioms.push_back(orig);
- Node conj = nm->mkNode(AND, axioms);
+ Node conj = nm->mkAnd(axioms);
conj = theory::Rewriter::rewrite(conj);
Assert(!expr::hasFreeVar(conj));
- assertionsToPreprocess->replace(0, conj);
+ assertionsToPreprocess->conjoin(0, conj);
}
axioms.clear();
// add new axioms as a conjunction to the first assertion
if (!axioms.empty())
{
- Node orig = (*assertionsToPreprocess)[0];
- axioms.push_back(orig);
- Node conj = nm->mkNode(AND, axioms);
+ Node conj = nm->mkAnd(axioms);
conj = theory::Rewriter::rewrite(conj);
Assert(!expr::hasFreeVar(conj));
- assertionsToPreprocess->replace(0, conj);
+ assertionsToPreprocess->conjoin(0, conj);
}
return PreprocessingPassResult::NO_CONFLICT;
TrustNode trn = d_preprocContext->getIteRemover()->run(
(*assertions)[i], newAsserts, newSkolems, true);
// process
- assertions->replace(i, trn.getNode());
+ assertions->replaceTrusted(i, trn);
Assert(newSkolems.size() == newAsserts.size());
for (unsigned j = 0, nnasserts = newAsserts.size(); j < nnasserts; j++)
{
imap[newSkolems[j]] = assertions->size();
- assertions->ref().push_back(newAsserts[j].getNode());
+ assertions->pushBackTrusted(newAsserts[j]);
}
}
for (unsigned i = 0, size = assertions->size(); i < size; ++i)
{
if (options::compressItes())
{
- result = d_iteUtilities.compress(assertionsToPreprocess->ref());
+ result = d_iteUtilities.compress(assertionsToPreprocess);
}
if (result)
{
Node more = aiteu.reduceConstantIteByGCD(res);
Debug("arith::ite::red") << " gcd->" << more << endl;
- (*assertionsToPreprocess)[i] = Rewriter::rewrite(more);
+ Node morer = Rewriter::rewrite(more);
+ assertionsToPreprocess->replace(i, morer);
}
}
}
<< " ->" << res << endl;
Node more = aiteu.reduceConstantIteByGCD(res);
Debug("arith::ite::red") << " gcd->" << more << endl;
- (*assertionsToPreprocess)[i] = Rewriter::rewrite(more);
+ Node morer = Rewriter::rewrite(more);
+ assertionsToPreprocess->replace(i, morer);
}
}
}
for (unsigned i = 0; i < size; ++i)
{
Node a = (*assertionsToPreprocess)[i];
- assertionsToPreprocess->replace(i, purifyNlTerms(a, cache, bcache, var_eq));
- Trace("nl-ext-purify") << "Purify : " << a << " -> "
- << (*assertionsToPreprocess)[i] << "\n";
+ Node ap = purifyNlTerms(a, cache, bcache, var_eq);
+ if (a != ap)
+ {
+ assertionsToPreprocess->replace(i, ap);
+ Trace("nl-ext-purify")
+ << "Purify : " << a << " -> " << (*assertionsToPreprocess)[i] << "\n";
+ }
}
if (!var_eq.empty())
{
unsigned lastIndex = size - 1;
- var_eq.insert(var_eq.begin(), (*assertionsToPreprocess)[lastIndex]);
- assertionsToPreprocess->replace(
- lastIndex, NodeManager::currentNM()->mkNode(kind::AND, var_eq));
+ Node veq = NodeManager::currentNM()->mkAnd(var_eq);
+ assertionsToPreprocess->conjoin(lastIndex, veq);
}
return PreprocessingPassResult::NO_CONFLICT;
}
}
}
- NodeBuilder<> learnedBuilder(kind::AND);
Assert(assertionsToPreprocess->getRealAssertionsEnd()
<= assertionsToPreprocess->size());
- learnedBuilder << (*assertionsToPreprocess)
- [assertionsToPreprocess->getRealAssertionsEnd() - 1];
+ std::vector<Node> learnedLitsToConjoin;
for (size_t i = 0; i < learned_literals.size(); ++i)
{
continue;
}
s.insert(learned);
- learnedBuilder << learned;
+ learnedLitsToConjoin.push_back(learned);
Trace("non-clausal-simplify")
<< "non-clausal learned : " << learned << std::endl;
}
continue;
}
s.insert(cProp);
- learnedBuilder << cProp;
+ learnedLitsToConjoin.push_back(cProp);
Trace("non-clausal-simplify")
<< "non-clausal constant propagation : " << cProp << std::endl;
}
// substituting
top_level_substs.addSubstitutions(newSubstitutions);
- if (learnedBuilder.getNumChildren() > 1)
+ if (!learnedLitsToConjoin.empty())
{
- assertionsToPreprocess->replace(
- assertionsToPreprocess->getRealAssertionsEnd() - 1,
- Rewriter::rewrite(Node(learnedBuilder)));
+ size_t replIndex = assertionsToPreprocess->getRealAssertionsEnd() - 1;
+ Node newConj = NodeManager::currentNM()->mkAnd(learnedLitsToConjoin);
+ assertionsToPreprocess->conjoin(replIndex, newConj);
}
propagator->setNeedsFinish(true);
bool success;
do
{
- success = simplify(assertionsToPreprocess->ref(), true);
+ success = simplify(assertionsToPreprocess, true);
} while (success);
finalizeDefinitions();
clearMaps();
d_ground_macros = false;
}
-bool QuantifierMacros::simplify( std::vector< Node >& assertions, bool doRewrite ){
+bool QuantifierMacros::simplify(AssertionPipeline* ap, bool doRewrite)
+{
+ const std::vector<Node>& assertions = ap->ref();
unsigned rmax =
options::macrosQuantMode() == options::MacrosQuantMode::ALL ? 2 : 1;
for( unsigned r=0; r<rmax; r++ ){
}
}
}
- assertions[i] = curr;
+ ap->replace(i, curr);
retVal = true;
}
}
bool reqComplete);
void addMacro(Node op, Node n, std::vector<Node>& opc);
void debugMacroDefinition(Node oo, Node n);
- bool simplify(std::vector<Node>& assertions, bool doRewrite = false);
+ /**
+ * This applies macro elimination to the given pipeline, which discovers
+ * whether there are any quantified formulas corresponding to macros.
+ *
+ * @param ap The pipeline to apply macros to.
+ * @param doRewrite Whether we also wish to rewrite the assertions based on
+ * the discovered macro definitions.
+ * @return Whether new definitions were inferred and we rewrote the assertions
+ * based on them.
+ */
+ bool simplify(AssertionPipeline* ap, bool doRewrite = false);
Node simplify(Node n);
void finalizeDefinitions();
void clearMaps();
return PreprocessingPassResult::NO_CONFLICT;
}
-bool SygusInference::solveSygus(std::vector<Node>& assertions,
+bool SygusInference::solveSygus(const std::vector<Node>& assertions,
std::vector<Node>& funs,
std::vector<Node>& sols)
{
* If this function returns true, then we add all uninterpreted symbols s in
* assertions to funs and their corresponding solution to sols.
*/
- bool solveSygus(std::vector<Node>& assertions,
+ bool solveSygus(const std::vector<Node>& assertions,
std::vector<Node>& funs,
std::vector<Node>& sols);
};
{
Trace("srs-input") << "Synthesize rewrite rules from assertions..."
<< std::endl;
- std::vector<Node>& assertions = assertionsToPreprocess->ref();
+ const std::vector<Node>& assertions = assertionsToPreprocess->ref();
if (assertions.empty())
{
return PreprocessingPassResult::NO_CONFLICT;
{
d_preprocContext->spendResource(ResourceManager::Resource::PreprocessStep);
- std::vector<Node>& assertions = assertionsToPreprocess->ref();
+ const std::vector<Node>& assertions = assertionsToPreprocess->ref();
d_context->push();
{
processUnconstrained();
// d_substitutions.print(Message.getStream());
- for (Node& assertion : assertions)
+ for (size_t i = 0, asize = assertions.size(); i < asize; ++i)
{
- assertion = Rewriter::rewrite(d_substitutions.apply(assertion));
+ Node a = assertions[i];
+ Node as = Rewriter::rewrite(d_substitutions.apply(a));
+ // replace the assertion
+ assertionsToPreprocess->replace(i, as);
}
}
}
/* returns false if an assertion is discovered to be equal to false. */
-bool ITEUtilities::compress(std::vector<Node>& assertions)
+bool ITEUtilities::compress(AssertionPipeline* assertionsToPreprocess)
{
if (d_compressor == NULL)
{
d_compressor = new ITECompressor(d_containsVisitor.get());
}
- return d_compressor->compress(assertions);
+ return d_compressor->compress(assertionsToPreprocess);
}
Node ITEUtilities::simplifyWithCare(TNode e)
}
}
-bool ITECompressor::compress(std::vector<Node>& assertions)
+bool ITECompressor::compress(AssertionPipeline* assertionsToPreprocess)
{
reset();
- d_assertions = &assertions;
- d_incoming.computeReachability(assertions);
+ d_assertions = assertionsToPreprocess;
+ d_incoming.computeReachability(assertionsToPreprocess->ref());
++(d_statistics.d_compressCalls);
Chat() << "Computed reachability" << endl;
bool nofalses = true;
+ const std::vector<Node>& assertions = assertionsToPreprocess->ref();
size_t original_size = assertions.size();
Chat() << "compressing " << original_size << endl;
for (size_t i = 0; i < original_size && nofalses; ++i)
Node assertion = assertions[i];
Node compressed = compressBoolean(assertion);
Node rewritten = theory::Rewriter::rewrite(compressed);
- assertions[i] = rewritten;
+ // replace
+ assertionsToPreprocess->replace(i, rewritten);
Assert(!d_contains->containsTermITE(rewritten));
nofalses = (rewritten != d_false);
#include <vector>
#include "expr/node.h"
+#include "preprocessing/assertion_pipeline.h"
#include "util/hash.h"
#include "util/statistics_registry.h"
bool simpIteDidALotOfWorkHeuristic() const;
/* returns false if an assertion is discovered to be equal to false. */
- bool compress(std::vector<Node>& assertions);
+ bool compress(AssertionPipeline* assertionsToPreprocess);
Node simplifyWithCare(TNode e);
~ITECompressor();
/* returns false if an assertion is discovered to be equal to false. */
- bool compress(std::vector<Node>& assertions);
+ bool compress(AssertionPipeline* assertionsToPreprocess);
/* garbage Collects the compressor. */
void garbageCollect();
Node d_true; /* Copy of true. */
Node d_false; /* Copy of false. */
ContainsTermITEVisitor* d_contains;
- std::vector<Node>* d_assertions;
+ AssertionPipeline* d_assertions;
IncomingArcCounter d_incoming;
typedef std::unordered_map<Node, Node, NodeHashFunction> NodeMap;
// assertion
IteSkolemMap::iterator it = iskMap.begin();
IteSkolemMap::iterator iend = iskMap.end();
- NodeBuilder<> builder(AND);
- builder << assertions[assertions.getRealAssertionsEnd() - 1];
+ std::vector<Node> newConj;
vector<TNode> toErase;
for (; it != iend; ++it)
{
}
}
// Move this iteExpr into the main assertions
- builder << assertions[(*it).second];
- assertions[(*it).second] = d_true;
+ newConj.push_back(assertions[(*it).second]);
+ assertions.replace((*it).second, d_true);
toErase.push_back((*it).first);
}
- if (builder.getNumChildren() > 1)
+ if (!newConj.empty())
{
while (!toErase.empty())
{
iskMap.erase(toErase.back());
toErase.pop_back();
}
- assertions[assertions.getRealAssertionsEnd() - 1] =
- Rewriter::rewrite(Node(builder));
+ size_t index = assertions.getRealAssertionsEnd() - 1;
+ Node newAssertion = NodeManager::currentNM()->mkAnd(newConj);
+ assertions.conjoin(index, newAssertion);
}
// TODO(b/1256): For some reason this is needed for some benchmarks, such
// as