TimerStat d_checkModelTime;
/** time spent in checkProof() */
TimerStat d_checkProofTime;
+ /** time spent in checkUnsatCore() */
+ TimerStat d_checkUnsatCoreTime;
/** time spent in PropEngine::checkSat() */
TimerStat d_solveTime;
/** time spent in pushing/popping */
d_numAssertionsPost("smt::SmtEngine::numAssertionsPostITERemoval", 0),
d_checkModelTime("smt::SmtEngine::checkModelTime"),
d_checkProofTime("smt::SmtEngine::checkProofTime"),
+ d_checkUnsatCoreTime("smt::SmtEngine::checkUnsatCoreTime"),
d_solveTime("smt::SmtEngine::solveTime"),
d_pushPopTime("smt::SmtEngine::pushPopTime"),
d_processAssertionsTime("smt::SmtEngine::processAssertionsTime"),
StatisticsRegistry::registerStat(&d_numAssertionsPost);
StatisticsRegistry::registerStat(&d_checkModelTime);
StatisticsRegistry::registerStat(&d_checkProofTime);
+ StatisticsRegistry::registerStat(&d_checkUnsatCoreTime);
StatisticsRegistry::registerStat(&d_solveTime);
StatisticsRegistry::registerStat(&d_pushPopTime);
StatisticsRegistry::registerStat(&d_processAssertionsTime);
StatisticsRegistry::unregisterStat(&d_numAssertionsPost);
StatisticsRegistry::unregisterStat(&d_checkModelTime);
StatisticsRegistry::unregisterStat(&d_checkProofTime);
+ StatisticsRegistry::unregisterStat(&d_checkUnsatCoreTime);
StatisticsRegistry::unregisterStat(&d_solveTime);
StatisticsRegistry::unregisterStat(&d_pushPopTime);
StatisticsRegistry::unregisterStat(&d_processAssertionsTime);
d_modelGlobalCommands(),
d_modelCommands(NULL),
d_dumpCommands(),
+#ifdef CVC4_PROOF
+ d_defineCommands(),
+#endif
d_logic(),
d_originalOptions(em->getOptions()),
d_pendingPops(0),
Notice() << "SmtEngine: turning off bv-introduce-pow2 to support unsat-cores" << endl;
setOption("bv-intro-pow2", false);
}
+ if(options::repeatSimp()) {
+ if(options::repeatSimp.wasSetByUser()) {
+ throw OptionException("repeat-simp not supported with unsat cores");
+ }
+ Notice() << "SmtEngine: turning off repeat-simp to support unsat-cores" << endl;
+ setOption("repeat-simp", false);
+ }
+
}
if(options::produceAssignments() && !options::produceModels()) {
}
}
+ // strings require LIA, UF; widen the logic
+ if(d_logic.isTheoryEnabled(THEORY_STRINGS)) {
+ LogicInfo log(d_logic.getUnlockedCopy());
+ // Strings requires arith for length constraints, and also UF
+ if(!d_logic.isTheoryEnabled(THEORY_UF)) {
+ Trace("smt") << "because strings are enabled, also enabling UF" << endl;
+ log.enableTheory(THEORY_UF);
+ }
+ if(!d_logic.isTheoryEnabled(THEORY_ARITH) || d_logic.isDifferenceLogic() || !d_logic.areIntegersUsed()) {
+ Trace("smt") << "because strings are enabled, also enabling linear integer arithmetic" << endl;
+ log.enableTheory(THEORY_ARITH);
+ log.enableIntegers();
+ log.arithOnlyLinear();
+ }
+ d_logic = log;
+ d_logic.lock();
+ }
+
// by default, symmetry breaker is on only for QF_UF
if(! options::ufSymmetryBreaker.wasSetByUser()) {
bool qf_uf = d_logic.isPure(THEORY_UF) && !d_logic.isQuantified();
// Turn on multiple-pass non-clausal simplification for QF_AUFBV
if(! options::repeatSimp.wasSetByUser()) {
bool repeatSimp = !d_logic.isQuantified() &&
- (d_logic.isTheoryEnabled(THEORY_ARRAY) && d_logic.isTheoryEnabled(THEORY_UF) && d_logic.isTheoryEnabled(THEORY_BV));
+ (d_logic.isTheoryEnabled(THEORY_ARRAY) &&
+ d_logic.isTheoryEnabled(THEORY_UF) &&
+ d_logic.isTheoryEnabled(THEORY_BV)) &&
+ !options::unsatCores();
Trace("smt") << "setting repeat simplification to " << repeatSimp << endl;
options::repeatSimp.set(repeatSimp);
}
// Turn on unconstrained simplification for QF_AUFBV
- if(! options::unconstrainedSimp.wasSetByUser() || options::incrementalSolving()) {
+ if(!options::unconstrainedSimp.wasSetByUser() ||
+ options::incrementalSolving()) {
// bool qf_sat = d_logic.isPure(THEORY_BOOL) && !d_logic.isQuantified();
// bool uncSimp = false && !qf_sat && !options::incrementalSolving();
- bool uncSimp = !options::incrementalSolving() && !d_logic.isQuantified() && !options::produceModels() && !options::produceAssignments() && !options::checkModels() &&
- (d_logic.isTheoryEnabled(THEORY_ARRAY) && d_logic.isTheoryEnabled(THEORY_BV));
+ bool uncSimp = !options::incrementalSolving() &&
+ !d_logic.isQuantified() &&
+ !options::produceModels() &&
+ !options::produceAssignments() &&
+ !options::checkModels() &&
+ !options::unsatCores() &&
+ (d_logic.isTheoryEnabled(THEORY_ARRAY) && d_logic.isTheoryEnabled(THEORY_BV));
Trace("smt") << "setting unconstrained simplification to " << uncSimp << endl;
options::unconstrainedSimp.set(uncSimp);
}
SmtScope smts(this);
+ PROOF( if (options::checkUnsatCores()) {
+ d_defineCommands.push_back(c.clone());
+ });
+
+
// Substitute out any abstract values in formula
Expr form = d_private->substituteAbstractValues(Node::fromExpr(formula)).toExpr();
Trace("smt") << "SmtEnginePrivate::processAssertions()" << endl;
Debug("smt") << " d_assertions : " << d_assertions.size() << endl;
-
+
if (d_assertions.size() == 0) {
// nothing to do
return;
d_iteSkolemMap.erase(toErase.back());
toErase.pop_back();
}
- d_assertions[d_realAssertionsEnd - 1] =
- Rewriter::rewrite(Node(builder));
+ d_assertions[d_realAssertionsEnd - 1] = Rewriter::rewrite(Node(builder));
}
// For some reason this is needed for some benchmarks, such as
// http://cvc4.cs.nyu.edu/benchmarks/smtlib2/QF_AUFBV/dwp_formulas/try5_small_difret_functions_dwp_tac.re_node_set_remove_at.il.dwp.smt2
// n is the result of an unknown preprocessing step, add it to dependency map to null
ProofManager::currentPM()->addDependence(n, Node::null());
}
+ // rewrite rules are by default in the unsat core because
+ // they need to be applied until saturation
+ if(options::unsatCores() &&
+ n.getKind() == kind::REWRITE_RULE ){
+ ProofManager::currentPM()->addUnsatCore(n.toExpr());
+ }
);
// Add the normalized formula to the queue
// Dump the query if requested
if(Dump.isOn("benchmark")) {
// the expr already got dumped out if assertion-dumping is on
- Dump("benchmark") << CheckSatCommand();
+ Dump("benchmark") << CheckSatCommand(ex);
}
// Pop the context
checkProof();
}
}
+ // Check that UNSAT results generate an unsat core correctly.
+ if(options::checkUnsatCores()) {
+ if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
+ TimerStat::CodeTimer checkUnsatCoreTimer(d_stats->d_checkUnsatCoreTime);
+ checkUnsatCore();
+ }
+ }
return r;
} catch (UnsafeInterruptException& e) {
// Dump the query if requested
if(Dump.isOn("benchmark")) {
// the expr already got dumped out if assertion-dumping is on
- Dump("benchmark") << CheckSatCommand();
+ Dump("benchmark") << QueryCommand(ex);
}
// Pop the context
checkProof();
}
}
+ // Check that UNSAT results generate an unsat core correctly.
+ if(options::checkUnsatCores()) {
+ if(r.asSatisfiabilityResult().isSat() == Result::UNSAT) {
+ TimerStat::CodeTimer checkUnsatCoreTimer(d_stats->d_checkUnsatCoreTime);
+ checkUnsatCore();
+ }
+ }
return r;
} catch (UnsafeInterruptException& e) {
return m;
}
+void SmtEngine::checkUnsatCore() {
+ Assert(options::unsatCores(), "cannot check unsat core if unsat cores are turned off");
+
+ Notice() << "SmtEngine::checkUnsatCore(): generating unsat core" << endl;
+ UnsatCore core = getUnsatCore();
+
+ SmtEngine coreChecker(d_exprManager);
+ coreChecker.setLogic(getLogicInfo());
+
+ PROOF(
+ std::vector<Command*>::const_iterator itg = d_defineCommands.begin();
+ for (; itg != d_defineCommands.end(); ++itg) {
+ (*itg)->invoke(&coreChecker);
+ }
+ );
+
+ Notice() << "SmtEngine::checkUnsatCore(): pushing core assertions (size == " << core.size() << ")" << endl;
+ for(UnsatCore::iterator i = core.begin(); i != core.end(); ++i) {
+ Notice() << "SmtEngine::checkUnsatCore(): pushing core member " << *i << endl;
+ coreChecker.assertFormula(*i);
+ }
+ const bool checkUnsatCores = options::checkUnsatCores();
+ Result r;
+ try {
+ options::checkUnsatCores.set(false);
+ options::checkProofs.set(false);
+ r = coreChecker.checkSat();
+ } catch(...) {
+ options::checkUnsatCores.set(checkUnsatCores);
+ throw;
+ }
+ Notice() << "SmtEngine::checkUnsatCore(): result is " << r << endl;
+ if(r.asSatisfiabilityResult().isUnknown()) {
+ InternalError("SmtEngine::checkUnsatCore(): could not check core result unknown.");
+ }
+
+ if(r.asSatisfiabilityResult().isSat()) {
+ InternalError("SmtEngine::checkUnsatCore(): produced core was satisfiable.");
+ }
+}
+
void SmtEngine::checkModel(bool hardFailure) {
// --check-model implies --produce-assertions, which enables the
// assertion list, so we should be ok.
fi
fi
check_proofs=false
+check_unsat_cores=false
if [ "$proof" = yes ]; then
# proofs not currently supported in incremental mode, turn it off
if grep '^unsat$' "$expoutfile" &>/dev/null || grep '^valid$' "$expoutfile" &>/dev/null &>/dev/null; then
if ! expr "$CVC4_REGRESSION_ARGS $command_line" : '.*--check-proofs' &>/dev/null &&
! expr "$CVC4_REGRESSION_ARGS $command_line" : '.*--no-check-proofs' &>/dev/null &&
! expr "$CVC4_REGRESSION_ARGS $command_line" : '.*--incremental' &>/dev/null &&
- ! expr " $CVC4_REGRESSION_ARGS $command_line" : '.* -[a-zA-Z]*i' &>/dev/null; then
+ ! expr "$CVC4_REGRESSION_ARGS $command_line" : '.*--unconstrained-simp' &>/dev/null &&
+ ! expr " $CVC4_REGRESSION_ARGS $command_line" : '.* -[a-zA-Z]*i' &>/dev/null &&
+ ! expr "$benchmark" : '.*\.sy$' &>/dev/null; then
# later on, we'll run another test with --check-proofs on
check_proofs=true
fi
+ if ! expr "$CVC4_REGRESSION_ARGS $command_line" : '.*--check-unsat-cores' &>/dev/null &&
+ ! expr "$CVC4_REGRESSION_ARGS $command_line" : '.*--no-check-unsat-cores' &>/dev/null &&
+ ! expr "$CVC4_REGRESSION_ARGS $command_line" : '.*--incremental' &>/dev/null &&
+ ! expr "$CVC4_REGRESSION_ARGS $command_line" : '.*--unconstrained-simp' &>/dev/null &&
+ ! expr " $CVC4_REGRESSION_ARGS $command_line" : '.* -[a-zA-Z]*i' &>/dev/null &&
+ ! expr "$benchmark" : '.*\.sy$' &>/dev/null; then
+ # later on, we'll run another test with --check-unsat-cores on
+ check_unsat_cores=true
+ fi
fi
fi
if [ -z "$expected_error" ]; then
exitcode=1
fi
-if $check_models || $check_proofs; then
+if $check_models || $check_proofs || $check_unsat_cores; then
check_cmdline=
if $check_models; then
check_cmdline="$check_cmdline --check-models"
if $check_proofs; then
check_cmdline="$check_cmdline --check-proofs"
fi
- # at least one sat/invalid response: run an extra model/proof-checking pass
+ if $check_unsat_cores; then
+ check_cmdline="$check_cmdline --check-unsat-cores"
+ fi
+ # run an extra model/proof/core-checking pass
if ! CVC4_REGRESSION_ARGS="$CVC4_REGRESSION_ARGS$check_cmdline" "$0" $wrapper "$cvc4" "$benchmark_orig"; then
exitcode=1
fi