};
PropEngine::PropEngine(const Options* opts, DecisionEngine* de,
- TheoryEngine* te, Context* context)
-: d_inCheckSat(false),
+ TheoryEngine* te, Context* context) :
+ d_inCheckSat(false),
d_options(opts),
d_decisionEngine(de),
d_theoryEngine(te),
- d_context(context)
-{
+ d_context(context) {
Debug("prop") << "Constructing the PropEngine" << endl;
d_satSolver = new SatSolver(this, d_theoryEngine, d_context, d_options);
d_cnfStream = new CVC4::prop::TseitinCnfStream(d_satSolver);
Debug("prop") << "PropEngine::checkSat() => "
<< (result ? "true" : "false") << endl;
+ if(result && d_theoryEngine->isIncomplete()) {
+ return Result(Result::SAT_UNKNOWN, Result::INCOMPLETE);
+ }
return Result(result ? Result::SAT : Result::UNSAT);
}
n.getMetaKind() == kind::metakind::VARIABLE ), e,
"expected variable or defined-function application "
"in addToAssignment(),\ngot %s", e.toString().c_str() );
- if(!d_options->interactive || !d_options->produceAssignments) {
+ if(!d_options->produceAssignments) {
return false;
}
if(d_assignments == NULL) {
throw ModalException(msg);
}
+ if(d_assignments == NULL) {
+ return SExpr();
+ }
+
NodeManagerScope nms(d_nodeManager);
vector<SExpr> sexprs;
TypeNode boolType = d_nodeManager->booleanType();
*
* @param safe - whether it is safe to be interrupted
*/
- virtual void conflict(TNode n, bool safe = false) throw(Interrupted, AssertionException) = 0;
+ virtual void conflict(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) = 0;
/**
* Propagate a theory literal.
*
* @param safe - whether it is safe to be interrupted
*/
- virtual void propagate(TNode n, bool safe = false) throw(Interrupted, AssertionException) = 0;
+ virtual void propagate(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) = 0;
/**
* Tell the core that a valid theory lemma at decision level 0 has
* @param n - a theory lemma valid at decision level 0
* @param safe - whether it is safe to be interrupted
*/
- virtual void lemma(TNode n, bool safe = false) throw(Interrupted, AssertionException) = 0;
+ virtual void lemma(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) = 0;
/**
- * Tell the core to add the following valid lemma as if it were a user assertion.
- * This should NOT be called during solving, only preprocessing.
+ * Tell the core to add the following valid lemma as if it were a
+ * user assertion. This should NOT be called during solving, only
+ * preprocessing.
*
* @param n - a theory lemma valid to be asserted
* @param safe - whether it is safe to be interrupted
*/
- virtual void augmentingLemma(TNode n, bool safe = false) throw(Interrupted, AssertionException) = 0;
+ virtual void augmentingLemma(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) = 0;
/**
* Provide an explanation in response to an explanation request.
* @param n - an explanation
* @param safe - whether it is safe to be interrupted
*/
- virtual void explanation(TNode n, bool safe = false) throw(Interrupted, AssertionException) = 0;
+ virtual void explanation(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) = 0;
+
+ /**
+ * Notification from a theory that it realizes it is incomplete at
+ * this context level. If SAT is later determined by the
+ * TheoryEngine, it should actually return an UNKNOWN result.
+ */
+ virtual void setIncomplete()
+ throw(Interrupted, AssertionException) = 0;
};/* class OutputChannel */
d_propEngine(NULL),
d_theoryOut(this, ctxt),
d_hasShutDown(false),
+ d_incomplete(ctxt, false),
d_statistics() {
d_sharedTermManager = new SharedTermManager(this, ctxt);
void newFact(TNode n);
- void conflict(TNode conflictNode, bool safe) throw(theory::Interrupted, AssertionException) {
- Debug("theory") << "EngineOutputChannel::conflict(" << conflictNode << ")" << std::endl;
+ void conflict(TNode conflictNode, bool safe)
+ throw(theory::Interrupted, AssertionException) {
+ Debug("theory") << "EngineOutputChannel::conflict("
+ << conflictNode << ")" << std::endl;
d_conflictNode = conflictNode;
++(d_engine->d_statistics.d_statConflicts);
if(safe) {
}
}
- void propagate(TNode lit, bool) throw(theory::Interrupted, AssertionException) {
+ void propagate(TNode lit, bool)
+ throw(theory::Interrupted, AssertionException) {
d_propagatedLiterals.push_back(lit);
++(d_engine->d_statistics.d_statPropagate);
}
- void lemma(TNode node, bool) throw(theory::Interrupted, AssertionException) {
+ void lemma(TNode node, bool)
+ throw(theory::Interrupted, AssertionException) {
++(d_engine->d_statistics.d_statLemma);
d_engine->newLemma(node);
}
- void augmentingLemma(TNode node, bool) throw(theory::Interrupted, AssertionException) {
+ void augmentingLemma(TNode node, bool)
+ throw(theory::Interrupted, AssertionException) {
++(d_engine->d_statistics.d_statAugLemma);
d_engine->newAugmentingLemma(node);
}
- void explanation(TNode explanationNode, bool) throw(theory::Interrupted, AssertionException) {
+ void explanation(TNode explanationNode, bool)
+ throw(theory::Interrupted, AssertionException) {
d_explanationNode = explanationNode;
++(d_engine->d_statistics.d_statExplanation);
}
+
+ void setIncomplete()
+ throw(theory::Interrupted, AssertionException) {
+ d_engine->d_incomplete = true;
+ }
};/* class EngineOutputChannel */
EngineOutputChannel d_theoryOut;
*/
bool d_hasShutDown;
+ /**
+ * True if a theory has notified us of incompleteness (at this
+ * context level or below).
+ */
+ context::CDO<bool> d_incomplete;
+
/**
* Check whether a node is in the pre-rewrite cache or not.
*/
d_propEngine = propEngine;
}
+ /**
+ * Return whether or not we are incomplete (in the current context).
+ */
+ bool isIncomplete() {
+ return d_incomplete;
+ }
+
/**
* This is called at shutdown time by the SmtEngine, just before
* destruction. It is important because there are destruction
--- /dev/null
+(set-logic QF_UF)
+(declare-fun x () Bool)
+(declare-fun y () Bool)
+(assert (=> x y))
+(check-sat) ; returns sat
+(assert (=> y x))
+(assert (and x (not y)))
+(check-sat) ; returns sat --> ERROR
TS_ASSERT(j == NodeSelfIterator::selfEnd(x_and_y));
TS_ASSERT(i == x_and_y.end());
TS_ASSERT(j == x_and_y.end());
+
i = x_and_y.begin();
TS_ASSERT(i != x_and_y.end());
TS_ASSERT(*i == x);
void safePoint() throw(Interrupted, AssertionException) {}
- void conflict(TNode n, bool safe = false) throw(Interrupted, AssertionException) {
+ void conflict(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) {
push(CONFLICT, n);
}
- void propagate(TNode n, bool safe = false) throw(Interrupted, AssertionException) {
+ void propagate(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) {
push(PROPAGATE, n);
}
- void lemma(TNode n, bool safe = false) throw(Interrupted, AssertionException){
+ void lemma(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) {
push(LEMMA, n);
}
- void augmentingLemma(TNode n, bool safe = false) throw(Interrupted, AssertionException){
+ void augmentingLemma(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) {
Unreachable();
}
- void explanation(TNode n, bool safe = false) throw(Interrupted, AssertionException) {
+ void explanation(TNode n, bool safe = false)
+ throw(Interrupted, AssertionException) {
push(EXPLANATION, n);
}
+ void setIncomplete()
+ throw(Interrupted, AssertionException) {
+ Unreachable();
+ }
+
void clear() {
d_callHistory.clear();
}
void explanation(TNode n, bool safe) throw(AssertionException) {
Unimplemented();
}
+ void setIncomplete() throw(AssertionException) {
+ Unimplemented()
+ }
};/* class FakeOutputChannel */
class FakeTheory;