This ensures that e.g. COMBINATION_SPLIT shows up under theory::builtin::inferencesLemmas, and -t im. It also removes outdated interfaces from OutputChannel, and makes the feature TheoryEngine::ensureLemmaAtoms more modular, which was required for making these interfaces more consistent.
It also ensures that TheoryBuiltin has an inference manager, which will simplify special casing in #6956.
Valuation valuation,
const LogicInfo& logicInfo,
ProofNodeManager* pnm)
- : Theory(THEORY_BUILTIN, c, u, out, valuation, logicInfo, pnm)
+ : Theory(THEORY_BUILTIN, c, u, out, valuation, logicInfo, pnm),
+ d_state(c, u, valuation),
+ d_im(*this, d_state, pnm, "theory::builtin::")
{
+ // indicate we are using the default theory state and inference managers
+ d_theoryState = &d_state;
+ d_inferManager = &d_im;
}
TheoryRewriter* TheoryBuiltin::getTheoryRewriter() { return &d_rewriter; }
#include "theory/builtin/proof_checker.h"
#include "theory/builtin/theory_builtin_rewriter.h"
#include "theory/theory.h"
+#include "theory/theory_inference_manager.h"
+#include "theory/theory_state.h"
namespace cvc5 {
namespace theory {
TheoryBuiltinRewriter d_rewriter;
/** Proof rule checker */
BuiltinProofRuleChecker d_checker;
+ /** A (default) theory state object */
+ TheoryState d_state;
+ /** A (default) inference manager */
+ TheoryInferenceManager d_im;
}; /* class TheoryBuiltin */
} // namespace builtin
Node conflict = d_centralEqualityEngine.mkExplainLit(lit);
Trace("eem-central") << "...explained conflict of " << lit << " ... "
<< conflict << std::endl;
- d_sharedSolver.sendConflict(TrustNode::mkTrustConflict(conflict));
+ d_sharedSolver.sendConflict(TrustNode::mkTrustConflict(conflict),
+ InferenceId::EQ_CONSTANT_MERGE);
return;
}
void EngineOutputChannel::lemma(TNode lemma, LemmaProperty p)
{
- Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma("
- << lemma << ")"
- << ", properties = " << p << std::endl;
- ++d_statistics.lemmas;
- d_engine->d_outputChannelUsed = true;
-
- TrustNode tlem = TrustNode::mkTrustLemma(lemma);
- d_engine->lemma(tlem,
- p,
- isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST,
- d_theory);
-}
-
-void EngineOutputChannel::splitLemma(TNode lemma, bool removable)
-{
- Trace("theory::lemma") << "EngineOutputChannel<" << d_theory << ">::lemma("
- << lemma << ")" << std::endl;
- ++d_statistics.lemmas;
- d_engine->d_outputChannelUsed = true;
-
- Trace("pf::explain") << "EngineOutputChannel::splitLemma( " << lemma << " )"
- << std::endl;
- TrustNode tlem = TrustNode::mkTrustLemma(lemma);
- LemmaProperty p = removable ? LemmaProperty::REMOVABLE : LemmaProperty::NONE;
- d_engine->lemma(tlem, p, d_theory);
+ trustedLemma(TrustNode::mkTrustLemma(lemma), p);
}
bool EngineOutputChannel::propagate(TNode literal)
}
++d_statistics.lemmas;
d_engine->d_outputChannelUsed = true;
+ if (isLemmaPropertySendAtoms(p))
+ {
+ d_engine->ensureLemmaAtoms(plem.getNode(), d_theory);
+ }
// now, call the normal interface for lemma
d_engine->lemma(plem,
p,
- isLemmaPropertySendAtoms(p) ? d_theory : theory::THEORY_LAST,
d_theory);
}
void lemma(TNode lemma, LemmaProperty p = LemmaProperty::NONE) override;
- void splitLemma(TNode lemma, bool removable = false) override;
-
void demandRestart() override;
void requirePhase(TNode n, bool phase) override;
return out;
}
-void OutputChannel::split(TNode n) { splitLemma(n.orNode(n.notNode())); }
-
void OutputChannel::trustedConflict(TrustNode pconf)
{
Unreachable() << "OutputChannel::trustedConflict: no implementation"
*/
virtual void lemma(TNode n, LemmaProperty p = LemmaProperty::NONE) = 0;
- /**
- * Request a split on a new theory atom. This is equivalent to
- * calling lemma({OR n (NOT n)}).
- *
- * @param n - a theory atom; must be of Boolean type
- */
- void split(TNode n);
-
- virtual void splitLemma(TNode n, bool removable = false) = 0;
-
/**
* If a decision is made on n, it must be in the phase specified.
* Note that this is enforced *globally*, i.e., it is completely
#include "theory/ee_setup_info.h"
#include "theory/logic_info.h"
#include "theory/theory_engine.h"
+#include "theory/theory_inference_manager.h"
namespace cvc5 {
namespace theory {
d_sharedTerms(&d_te, d_te.getSatContext(), d_te.getUserContext(), pnm),
d_preRegistrationVisitor(&te, d_te.getSatContext()),
d_sharedTermsVisitor(&te, d_sharedTerms, d_te.getSatContext()),
- d_out(te.theoryOf(THEORY_BUILTIN)->getOutputChannel())
+ d_im(te.theoryOf(THEORY_BUILTIN)->getInferenceManager())
{
}
{
if (value)
{
- return d_out.propagate(predicate);
+ return d_im->propagateLit(predicate);
}
- return d_out.propagate(predicate.notNode());
+ return d_im->propagateLit(predicate.notNode());
}
bool SharedSolver::propagateSharedEquality(theory::TheoryId theory,
void SharedSolver::sendLemma(TrustNode trn, TheoryId atomsTo, InferenceId id)
{
- Trace("im") << "(lemma " << id << " " << trn.getProven() << ")" << std::endl;
- d_te.lemma(trn, LemmaProperty::NONE, atomsTo);
+ // Do we need to check atoms
+ if (atomsTo != theory::THEORY_LAST)
+ {
+ d_te.ensureLemmaAtoms(trn.getNode(), atomsTo);
+ }
+ d_im->trustedLemma(trn, id);
}
-void SharedSolver::sendConflict(TrustNode trn) { d_out.trustedConflict(trn); }
+void SharedSolver::sendConflict(TrustNode trn, InferenceId id)
+{
+ d_im->trustedConflict(trn, id);
+}
} // namespace theory
} // namespace cvc5
namespace theory {
struct EeSetupInfo;
-class OutputChannel;
+class TheoryInferenceManager;
/**
* A base class for shared solver. The shared solver is the component of theory
/** Send lemma to the theory engine, atomsTo is the theory to send atoms to */
void sendLemma(TrustNode trn, TheoryId atomsTo, InferenceId id);
/** Send conflict to the theory engine */
- void sendConflict(TrustNode trn);
+ void sendConflict(TrustNode trn, InferenceId id);
protected:
/** Solver-specific pre-register shared */
PreRegisterVisitor d_preRegistrationVisitor;
/** Visitor for collecting shared terms */
SharedTermsVisitor d_sharedTermsVisitor;
- /** Output channel of theory builtin */
- OutputChannel& d_out;
+ /** Theory inference manager of theory builtin */
+ TheoryInferenceManager* d_im;
};
} // namespace theory
}
};
+void TheoryEngine::ensureLemmaAtoms(TNode n, theory::TheoryId atomsTo)
+{
+ Assert(atomsTo != THEORY_LAST);
+ Debug("theory::atoms") << "TheoryEngine::ensureLemmaAtoms(" << n << ", "
+ << atomsTo << ")" << endl;
+ AtomsCollect collectAtoms;
+ NodeVisitor<AtomsCollect>::run(collectAtoms, n);
+ ensureLemmaAtoms(collectAtoms.getAtoms(), atomsTo);
+}
+
void TheoryEngine::ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId atomsTo) {
for (unsigned i = 0; i < atoms.size(); ++ i) {
void TheoryEngine::lemma(TrustNode tlemma,
theory::LemmaProperty p,
- theory::TheoryId atomsTo,
theory::TheoryId from)
{
// For resource-limiting (also does a time check).
tlemma.debugCheckClosed("te-proof-debug", "TheoryEngine::lemma_initial");
}
- // Do we need to check atoms
- if (atomsTo != theory::THEORY_LAST) {
- Debug("theory::atoms") << "TheoryEngine::lemma(" << node << ", " << atomsTo
- << ")" << endl;
- AtomsCollect collectAtoms;
- NodeVisitor<AtomsCollect>::run(collectAtoms, node);
- ensureLemmaAtoms(collectAtoms.getAtoms(), atomsTo);
- }
-
if(Dump.isOn("t-lemmas")) {
// we dump the negation of the lemma, to show validity of the lemma
Node n = lemma.negate();
// When only one theory, the conflict should need no processing
Assert(properConflict(conflict));
// pass the trust node that was sent from the theory
- lemma(tconflict, LemmaProperty::REMOVABLE, THEORY_LAST, theoryId);
+ lemma(tconflict, LemmaProperty::REMOVABLE, theoryId);
}
}
*/
void lemma(TrustNode node,
theory::LemmaProperty p,
- theory::TheoryId atomsTo = theory::THEORY_LAST,
theory::TheoryId from = theory::THEORY_LAST);
- /** Enusre that the given atoms are send to the given theory */
- void ensureLemmaAtoms(const std::vector<TNode>& atoms, theory::TheoryId theory);
+ /** Ensure atoms from the given node are sent to the given theory */
+ void ensureLemmaAtoms(TNode n, theory::TheoryId atomsTo);
+ /** Ensure that the given atoms are sent to the given theory */
+ void ensureLemmaAtoms(const std::vector<TNode>& atoms,
+ theory::TheoryId atomsTo);
/** sort inference module */
std::unique_ptr<theory::SortInference> d_sortInfer;
void setIncomplete(theory::IncompleteId id) override {}
void handleUserAttribute(const char* attr, theory::Theory* t) override {}
- void splitLemma(TNode n, bool removable = false) override { push(LEMMA, n); }
-
void clear() { d_callHistory.clear(); }
Node getIthNode(int i) const
{
Node n = d_atom0.orNode(d_atom1);
d_outputChannel.lemma(n);
- d_outputChannel.split(d_atom0);
+ d_outputChannel.lemma(d_atom0.orNode(d_atom0.notNode()));
Node s = d_atom0.orNode(d_atom0.notNode());
ASSERT_EQ(d_outputChannel.d_callHistory.size(), 2u);
ASSERT_EQ(d_outputChannel.d_callHistory[0], std::make_pair(LEMMA, n));