bool hasSubterm(TNode n, TNode t, bool strict = false);
/**
- * Returns true iff the node n contains a bound variable. This bound
- * variable may or may not be free.
+ * Returns true iff the node n contains a bound variable, that is a node of
+ * kind BOUND_VARIABLE. This bound variable may or may not be free.
* @param n The node under investigation
* @return true iff this node contains a bound variable
*/
bool hasBoundVar(TNode n);
/**
- * Returns true iff the node n contains a free variable.
+ * Returns true iff the node n contains a free variable, that is, a node
+ * of kind BOUND_VARIABLE that is not bound in n.
* @param n The node under investigation
* @return true iff this node contains a free variable.
*/
bool hasFreeVar(TNode n);
+/**
+ * For term n, this function collects the symbols that occur as a subterms
+ * of n. A symbol is a variable that does not have kind BOUND_VARIABLE.
+ * @param n The node under investigation
+ * @param syms The set which the symbols of n are added to
+ */
+void getSymbols(TNode n, std::unordered_set<Node, NodeHashFunction>& syms);
+/** Same as above, with a visited cache */
+void getSymbols(TNode n,
+ std::unordered_set<Node, NodeHashFunction>& syms,
+ std::unordered_set<TNode, TNodeHashFunction>& visited);
+
} // namespace expr
} // namespace CVC4
#include "expr/kind.h"
#include "expr/metakind.h"
#include "expr/node.h"
+#include "expr/node_algorithm.h"
#include "expr/node_builder.h"
#include "expr/node_self_iterator.h"
#include "options/arith_options.h"
typedef unordered_map<Node, Node, NodeHashFunction> NodeToNodeHashMap;
typedef unordered_map<Node, bool, NodeHashFunction> NodeToBoolHashMap;
+ typedef context::CDHashSet<Node, NodeHashFunction> NodeSet;
/**
* Manager for limiting time and abstract resource usage.
*/
SubstitutionMap d_abstractValueMap;
+ /**
+ * The (user-context-dependent) set of symbols that occur in at least one
+ * assertion in the current user context. This is used by the
+ * nonClausalSimplify pass.
+ */
+ NodeSet d_symsInAssertions;
+
/**
* A mapping of all abstract values (actual value |-> abstract) that
* we've handed out. This is necessary to ensure that we give the
*/
bool nonClausalSimplify();
+ /** record symbols in assertions
+ *
+ * This method is called when a set of assertions is finalized. It adds
+ * the symbols to d_symsInAssertions that occur in assertions.
+ */
+ void recordSymbolsInAssertions(const std::vector<Node>& assertions);
+
/**
* Helper function to fix up assertion list to restore invariants needed after
* ite removal.
d_assertionsProcessed(smt.d_userContext, false),
d_fakeContext(),
d_abstractValueMap(&d_fakeContext),
+ d_symsInAssertions(smt.d_userContext),
d_abstractValues(),
d_simplifyAssertionsDepth(0),
// d_needsExpandDefs(true), //TODO?
}
}
//------------------------------- end expression names
-
};/* class SmtEnginePrivate */
}/* namespace CVC4::smt */
<< assertion << endl;
}
- // If in incremental mode, add substitutions to the list of assertions
- if (substs_index > 0)
+ // add substitutions to model, or as assertions if needed (when incremental)
+ TheoryModel* m = d_smt.d_theoryEngine->getModel();
+ Assert(m != nullptr);
+ NodeManager* nm = NodeManager::currentNM();
+ NodeBuilder<> substitutionsBuilder(kind::AND);
+ for (pos = newSubstitutions.begin(); pos != newSubstitutions.end(); ++pos)
{
- NodeBuilder<> substitutionsBuilder(kind::AND);
- substitutionsBuilder << d_assertions[substs_index];
- pos = newSubstitutions.begin();
- for (; pos != newSubstitutions.end(); ++pos) {
- // Add back this substitution as an assertion
- TNode lhs = (*pos).first, rhs = newSubstitutions.apply((*pos).second);
- Node n = NodeManager::currentNM()->mkNode(kind::EQUAL, lhs, rhs);
- substitutionsBuilder << n;
- Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): will notify SAT layer of substitution: " << n << endl;
- }
- if (substitutionsBuilder.getNumChildren() > 1) {
- d_assertions.replace(substs_index,
- Rewriter::rewrite(Node(substitutionsBuilder)));
+ Node lhs = (*pos).first;
+ Node rhs = newSubstitutions.apply((*pos).second);
+ // If using incremental, we must check whether this variable has occurred
+ // before now. If it hasn't we can add this as a substitution.
+ if (substs_index == 0
+ || d_symsInAssertions.find(lhs) == d_symsInAssertions.end())
+ {
+ Trace("simplify")
+ << "SmtEnginePrivate::nonClausalSimplify(): substitute: " << lhs
+ << " " << rhs << endl;
+ m->addSubstitution(lhs, rhs);
}
- } else {
- // If not in incremental mode, must add substitutions to model
- TheoryModel* m = d_smt.d_theoryEngine->getModel();
- if(m != NULL) {
- for(pos = newSubstitutions.begin(); pos != newSubstitutions.end(); ++pos) {
- Node n = (*pos).first;
- Node v = newSubstitutions.apply((*pos).second);
- Trace("model") << "Add substitution : " << n << " " << v << endl;
- m->addSubstitution( n, v );
- }
+ else
+ {
+ // if it has, the substitution becomes an assertion
+ Node eq = nm->mkNode(kind::EQUAL, lhs, rhs);
+ Trace("simplify") << "SmtEnginePrivate::nonClausalSimplify(): "
+ "substitute: will notify SAT layer of substitution: "
+ << eq << endl;
+ substitutionsBuilder << eq;
}
}
+ // add to the last assertion if necessary
+ if (substitutionsBuilder.getNumChildren() > 0)
+ {
+ substitutionsBuilder << d_assertions[substs_index];
+ d_assertions.replace(substs_index,
+ Rewriter::rewrite(Node(substitutionsBuilder)));
+ }
NodeBuilder<> learnedBuilder(kind::AND);
Assert(d_assertions.getRealAssertionsEnd() <= d_assertions.size());
cache[n] = true;
}
+void SmtEnginePrivate::recordSymbolsInAssertions(
+ const std::vector<Node>& assertions)
+{
+ std::unordered_set<TNode, TNodeHashFunction> visited;
+ std::unordered_set<Node, NodeHashFunction> syms;
+ for (TNode cn : assertions)
+ {
+ expr::getSymbols(cn, syms, visited);
+ }
+ for (const Node& s : syms)
+ {
+ d_symsInAssertions.insert(s);
+ }
+}
bool SmtEnginePrivate::checkForBadSkolems(TNode n, TNode skolem, unordered_map<Node, bool, NodeHashFunction>& cache)
{
Trace("smt-proc") << "SmtEnginePrivate::processAssertions() end" << endl;
dumpAssertions("post-everything", d_assertions);
+ // if incremental, compute which variables are assigned
+ if (options::incrementalSolving())
+ {
+ recordSymbolsInAssertions(d_assertions.ref());
+ }
+
// Push the formula to SAT
{
Chat() << "converting to CNF..." << endl;