d_passes["theory-rewrite-eq"]->apply(&assertions);
// apply theory preprocess, which includes ITE removal
d_passes["theory-preprocess"]->apply(&assertions);
- // This is needed because when solving incrementally, removeITEs may
- // introduce skolems that were solved for earlier and thus appear in the
- // substitution map.
- d_passes["apply-substs"]->apply(&assertions);
+ // notice that we do not apply substitutions as a last step here, since
+ // the range of substitutions is not theory-preprocessed.
if (options::bitblastMode() == options::BitblastMode::EAGER)
{
}
void TheoryArithPrivate::setupAtom(TNode atom) {
- Assert(isRelationOperator(atom.getKind()));
+ Assert(isRelationOperator(atom.getKind())) << atom;
Assert(Comparison::isNormalAtom(atom));
Assert(!isSetup(atom));
Assert(!d_constraintDatabase.hasLiteral(atom));
d_logicInfo(te.getLogicInfo()),
d_sharedTerms(&d_te, d_te.getSatContext(), d_te.getUserContext(), pnm),
d_preRegistrationVisitor(&te, d_te.getSatContext()),
- d_sharedTermsVisitor(&te, d_sharedTerms)
+ d_sharedTermsVisitor(&te, d_sharedTerms, d_te.getSatContext())
{
}
void SharedSolver::preRegister(TNode atom)
{
+ Trace("theory") << "SharedSolver::preRegister atom " << atom << std::endl;
// This method uses two different implementations for preregistering terms,
// which depends on whether sharing is enabled.
// If sharing is disabled, we use PreRegisterVisitor, which keeps a global
// Theory::preRegisterTerm possibly multiple times.
NodeVisitor<PreRegisterVisitor>::run(d_preRegistrationVisitor, atom);
}
+ Trace("theory") << "SharedSolver::preRegister atom finished" << std::endl;
}
void SharedSolver::preNotifySharedFact(TNode atom)
TheoryIdSet visitedTheories = d_visited[current];
// call the preregistration on current, parent or type theories and update
- // visitedTheories.
- preRegister(d_engine, visitedTheories, current, parent);
+ // visitedTheories. The set of preregistering theories coincides with
+ // visitedTheories here.
+ preRegister(d_engine, visitedTheories, current, parent, visitedTheories);
Debug("register::internal")
<< "PreRegisterVisitor::visit(" << current << "," << parent
void PreRegisterVisitor::preRegister(TheoryEngine* te,
TheoryIdSet& visitedTheories,
TNode current,
- TNode parent)
+ TNode parent,
+ TheoryIdSet preregTheories)
{
// Preregister with the current theory, if necessary
TheoryId currentTheoryId = Theory::theoryOf(current);
- preRegisterWithTheory(te, visitedTheories, currentTheoryId, current, parent);
+ preRegisterWithTheory(
+ te, visitedTheories, currentTheoryId, current, parent, preregTheories);
if (current != parent)
{
// preregister with parent theory, if necessary
TheoryId parentTheoryId = Theory::theoryOf(parent);
- preRegisterWithTheory(te, visitedTheories, parentTheoryId, current, parent);
+ preRegisterWithTheory(
+ te, visitedTheories, parentTheoryId, current, parent, preregTheories);
// Note that if enclosed by different theories it's shared, for example,
// in read(a, f(a)), f(a) should be shared with integers.
{
// preregister with the type's theory, if necessary
TheoryId typeTheoryId = Theory::theoryOf(type);
- preRegisterWithTheory(te, visitedTheories, typeTheoryId, current, parent);
+ preRegisterWithTheory(
+ te, visitedTheories, typeTheoryId, current, parent, preregTheories);
}
}
}
TheoryIdSet& visitedTheories,
TheoryId id,
TNode current,
- TNode parent)
+ TNode parent,
+ TheoryIdSet preregTheories)
{
if (TheoryIdSetUtil::setContains(id, visitedTheories))
{
- // already registered
+ // already visited
+ return;
+ }
+ visitedTheories = TheoryIdSetUtil::setInsert(id, visitedTheories);
+ if (TheoryIdSetUtil::setContains(id, preregTheories))
+ {
+ // already pregregistered
return;
}
if (Configuration::isAssertionBuild())
}
}
// call the theory's preRegisterTerm method
- visitedTheories = TheoryIdSetUtil::setInsert(id, visitedTheories);
Theory* th = te->theoryOf(id);
th->preRegisterTerm(current);
}
Debug("register::internal") << toString() << std::endl;
}
TheoryIdSet visitedTheories = d_visited[current];
+ TheoryIdSet preregTheories = d_preregistered[current];
// preregister the term with the current, parent or type theories, as needed
- PreRegisterVisitor::preRegister(d_engine, visitedTheories, current, parent);
+ PreRegisterVisitor::preRegister(
+ d_engine, visitedTheories, current, parent, preregTheories);
// Record the new theories that we visited
d_visited[current] = visitedTheories;
+ // add visited theories to those who have preregistered
+ d_preregistered[current] =
+ TheoryIdSetUtil::setUnion(preregTheories, visitedTheories);
+
// If there is more than two theories and a new one has been added notify the shared terms database
TheoryId currentTheoryId = Theory::theoryOf(current);
if (TheoryIdSetUtil::setDifference(
/** required to instantiate template for NodeVisitor */
using return_type = void;
- PreRegisterVisitor(TheoryEngine* engine, context::Context* context)
- : d_engine(engine), d_visited(context)
+ PreRegisterVisitor(TheoryEngine* engine, context::Context* c)
+ : d_engine(engine), d_visited(c)
{
}
* @param visitedTheories The theories that have already preregistered current
* @param current The term to preregister
* @param parent The parent term of current
+ * @param preregTheories The theories that have already preregistered current.
+ * If there is no theory sharing, this coincides with visitedTheories.
+ * Otherwise, visitedTheories may be a subset of preregTheories.
*/
static void preRegister(TheoryEngine* te,
theory::TheoryIdSet& visitedTheories,
TNode current,
- TNode parent);
+ TNode parent,
+ theory::TheoryIdSet preregTheories);
private:
/**
theory::TheoryIdSet& visitedTheories,
theory::TheoryId id,
TNode current,
- TNode parent);
+ TNode parent,
+ theory::TheoryIdSet preregTheories);
};
* been visited already, we need to visit it again, since we need to associate it with both atoms.
*/
class SharedTermsVisitor {
-
- /**
- * Cache from preprocessing of atoms.
- */
- typedef std::unordered_map<TNode, theory::TheoryIdSet, TNodeHashFunction>
- TNodeVisitedMap;
- TNodeVisitedMap d_visited;
-
+ using TNodeVisitedMap =
+ std::unordered_map<TNode, theory::TheoryIdSet, TNodeHashFunction>;
+ using TNodeToTheorySetMap =
+ context::CDHashMap<TNode, theory::TheoryIdSet, TNodeHashFunction>;
/**
* String representation of the visited map, for debugging purposes.
*/
/** required to instantiate template for NodeVisitor */
using return_type = void;
- SharedTermsVisitor(TheoryEngine* te, SharedTermsDatabase& sharedTerms)
- : d_engine(te), d_sharedTerms(sharedTerms)
+ SharedTermsVisitor(TheoryEngine* te,
+ SharedTermsDatabase& sharedTerms,
+ context::Context* c)
+ : d_engine(te), d_sharedTerms(sharedTerms), d_preregistered(c)
{
}
TheoryEngine* d_engine;
/** The shared terms database */
SharedTermsDatabase& d_sharedTerms;
+ /** Cache of nodes we have visited in this traversal */
+ TNodeVisitedMap d_visited;
+ /** (Global) cache of nodes we have preregistered in this SAT context */
+ TNodeToTheorySetMap d_preregistered;
};
--- /dev/null
+; COMMAND-LINE: -i
+; EXPECT: sat
+(set-logic ALL)
+(set-option :strings-lazy-pp false)
+(declare-fun ufbi4 (Bool Bool Bool Bool) Int)
+(declare-fun str0 () String)
+(declare-fun str8 () String)
+(declare-fun i16 () Int)
+(assert (= (str.to_int str0) (ufbi4 false true false (= 0 i16))))
+(push)
+(assert (= str8 (str.from_int (str.to_int str0))))
+(push)
+(check-sat)