d_isInternalSubsolver(false),
d_pendingPops(0),
d_fullyInited(false),
- d_problemExtended(false),
d_queryMade(false),
d_needPostsolve(false),
d_earlyTheoryPP(true),
d_globalNegation(false),
d_status(),
d_expectedStatus(),
+ d_smtMode(SMT_MODE_START),
d_replayStream(NULL),
d_private(NULL),
d_statisticsRegistry(NULL),
}
}
-void SmtEngine::setProblemExtended(bool value)
+void SmtEngine::setProblemExtended()
{
- d_problemExtended = value;
- if (value) { d_assumptions.clear(); }
+ d_smtMode = SMT_MODE_ASSERT;
+ d_assumptions.clear();
}
void SmtEngine::setInfo(const std::string& key, const CVC4::SExpr& value)
throw RecoverableModalException(ss.str().c_str());
}
- if (d_status.isNull() || d_status.asSatisfiabilityResult() == Result::UNSAT
- || d_problemExtended)
+ if (d_smtMode != SMT_MODE_SAT)
{
std::stringstream ss;
ss << "Cannot " << c
bool didInternalPush = false;
- setProblemExtended(true);
+ setProblemExtended();
if (isQuery)
{
// Remember the status
d_status = r;
+ // Check against expected status
if (!d_expectedStatus.isUnknown() && !d_status.isUnknown()
&& d_status != d_expectedStatus)
{
<< d_status;
}
d_expectedStatus = Result();
-
- setProblemExtended(false);
+ // Update the SMT mode
+ if (d_status.asSatisfiabilityResult().isSat() == Result::UNSAT)
+ {
+ d_smtMode = SMT_MODE_UNSAT;
+ }
+ else
+ {
+ // Notice that unknown response moves to sat mode, since the same set
+ // of commands (get-model, get-value) are applicable to this case.
+ d_smtMode = SMT_MODE_SAT;
+ }
Trace("smt") << "SmtEngine::" << (isQuery ? "query" : "checkSat") << "("
<< assumptions << ") => " << r << endl;
"Cannot get unsat assumptions when produce-unsat-assumptions option "
"is off.");
}
- if (d_status.isNull()
- || d_status.asSatisfiabilityResult() != Result::UNSAT
- || d_problemExtended)
+ if (d_smtMode != SMT_MODE_UNSAT)
{
throw RecoverableModalException(
"Cannot get unsat assumptions unless immediately preceded by "
"Cannot get value when produce-models options is off.";
throw ModalException(msg);
}
- if(d_status.isNull() ||
- d_status.asSatisfiabilityResult() == Result::UNSAT ||
- d_problemExtended) {
+ if (d_smtMode != SMT_MODE_SAT)
+ {
const char* msg =
"Cannot get value unless immediately preceded by SAT/INVALID or UNKNOWN response.";
throw RecoverableModalException(msg);
"produce-assignments option is off.";
throw ModalException(msg);
}
- if(d_status.isNull() ||
- d_status.asSatisfiabilityResult() == Result::UNSAT ||
- d_problemExtended) {
+ if (d_smtMode != SMT_MODE_SAT)
+ {
const char* msg =
"Cannot get the current assignment unless immediately "
"preceded by SAT/INVALID or UNKNOWN response.";
throw ModalException(
"Cannot get an unsat core when produce-unsat-cores option is off.");
}
- if (d_status.isNull() || d_status.asSatisfiabilityResult() != Result::UNSAT
- || d_problemExtended)
+ if (d_smtMode != SMT_MODE_UNSAT)
{
throw RecoverableModalException(
"Cannot get an unsat core unless immediately preceded by UNSAT/VALID "
if(!options::proof()) {
throw ModalException("Cannot get a proof when produce-proofs option is off.");
}
- if(d_status.isNull() ||
- d_status.asSatisfiabilityResult() != Result::UNSAT ||
- d_problemExtended) {
+ if (d_smtMode != SMT_MODE_UNSAT)
+ {
throw RecoverableModalException(
"Cannot get a proof unless immediately preceded by UNSAT/VALID "
"response.");
d_subsolver->setLogic(l);
// assert the abduction query
d_subsolver->assertFormula(aconj.toExpr());
+ if (getAbductInternal(abd))
+ {
+ // successfully generated an abduct, update to abduct state
+ d_smtMode = SMT_MODE_ABDUCT;
+ return true;
+ }
+ // failed, we revert to the assert state
+ d_smtMode = SMT_MODE_ASSERT;
+ return false;
+}
+
+bool SmtEngine::getAbductInternal(Expr& abd)
+{
+ // should have initialized the subsolver by now
+ Assert(d_subsolver != nullptr);
Trace("sygus-abduct") << " SmtEngine::getAbduct check sat..." << std::endl;
Result r = d_subsolver->checkSat();
Trace("sygus-abduct") << " SmtEngine::getAbduct result: " << r << std::endl;
std::map<Expr, Expr>::iterator its = sols.find(d_sssf);
if (its != sols.end())
{
- Node abdn = Node::fromExpr(its->second);
Trace("sygus-abduct")
- << "SmtEngine::getAbduct: solution is " << abdn << std::endl;
+ << "SmtEngine::getAbduct: solution is " << its->second << std::endl;
+ Node abdn = Node::fromExpr(its->second);
if (abdn.getKind() == kind::LAMBDA)
{
abdn = abdn[1];
}
+ Assert(d_sssfVarlist.size() == d_sssfSyms.size());
// convert back to original
// must replace formal arguments of abd with the free variables in the
// input problem that they correspond to.
// convert to expression
abd = abdn.toExpr();
-
return true;
}
Trace("sygus-abduct") << "SmtEngine::getAbduct: could not find solution!"
// The problem isn't really "extended" yet, but this disallows
// get-model after a push, simplifying our lives somewhat and
- // staying symmtric with pop.
- setProblemExtended(true);
+ // staying symmetric with pop.
+ setProblemExtended();
d_userLevels.push_back(d_userContext->getLevel());
internalPush();
// but also it would be weird to have a legally-executed (get-model)
// that only returns a subset of the assignment (because the rest
// is no longer in scope!).
- setProblemExtended(true);
+ setProblemExtended();
AlwaysAssert(d_userContext->getLevel() > 0);
AlwaysAssert(d_userLevels.back() < d_userContext->getLevel());
*/
bool d_fullyInited;
- /**
- * Whether or not we have added any assertions/declarations/definitions,
- * or done push/pop, since the last checkSat/query, and therefore we're
- * not responsible for models or proofs.
- */
- bool d_problemExtended;
-
/**
* Whether or not a query() or checkSat() has already been made through
* this SmtEngine. If true, and incrementalSolving is false, then
*/
Result d_expectedStatus;
+ /**
+ * The current mode of the solver, see Figure 4.1 on page 52 of the
+ * SMT-LIB version 2.6 standard
+ * http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf
+ */
+ enum SmtMode
+ {
+ // the initial state of the solver
+ SMT_MODE_START,
+ // normal state of the solver, after assert/push/pop/declare/define
+ SMT_MODE_ASSERT,
+ // immediately after a check-sat returning "sat" or "unknown"
+ SMT_MODE_SAT,
+ // immediately after a check-sat returning "unsat"
+ SMT_MODE_UNSAT,
+ // immediately after a successful call to get-abduct
+ SMT_MODE_ABDUCT
+ };
+ SmtMode d_smtMode;
+
/**
* The input file name (if any) or the name set through setInfo (if any)
*/
void setDefaults();
/**
- * Sets d_problemExtended to the given value.
- * If d_problemExtended is set to true, the list of assumptions from the
- * previous call to checkSatisfiability is cleared.
+ * Sets that the problem has been extended. This sets the smt mode of the
+ * solver to SMT_MODE_ASSERT, and clears the list of assumptions from the
+ * previous call to checkSatisfiability.
*/
- void setProblemExtended(bool value);
+ void setProblemExtended();
/**
* Create theory engine, prop engine, decision engine. Called by
void debugCheckFunctionBody(Expr formula,
const std::vector<Expr>& formals,
Expr func);
+ /** get abduct internal
+ *
+ * Gets the next abduct from the internal subsolver d_subsolver. If
+ * successful, this method returns true and sets abd to that abduct.
+ *
+ * This method assumes d_subsolver has been initialized to do abduction
+ * problems.
+ */
+ bool getAbductInternal(Expr& abd);
/**
* Helper method to obtain both the heap and nil from the solver. Returns a