1 #include "MCSATMixin.h"
 
    6 template<typename Settings>
 
    7 void MCSATMixin<Settings>::pushTheoryDecision(const FormulaT& assignment, Minisat::Lit decisionLiteral) {
 
    8     SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Made theory decision for " << assignment.variable_assignment().var() << ": " << decisionLiteral);
 
    9     assert(mInconsistentVariables.empty());
 
   10     mBackend.pushAssignment( assignment.variable_assignment().var(),  assignment.variable_assignment().value(), assignment);
 
   11     mTheoryStack.emplace_back();
 
   12     current().variable = assignment.variable_assignment().var();
 
   13     current().decisionLiteral = decisionLiteral;
 
   17 template<typename Settings>
 
   18 void MCSATMixin<Settings>::popTheoryDecision() {
 
   19     assert(!mTheoryStack.empty());
 
   20     mUndecidedVariables.insert(
 
   21         mUndecidedVariables.end(),
 
   22         mTheoryStack.back().decidedVariables.begin(),
 
   23         mTheoryStack.back().decidedVariables.end()
 
   25     for (const auto var : mTheoryStack.back().decidedVariables) {
 
   26         mTheoryLevels[varid(var)] = std::numeric_limits<std::size_t>::max();
 
   27         mSemanticPropagations.erase(var);
 
   29     mTheoryStack.pop_back();
 
   30     mInconsistentVariables.clear();
 
   31     // mModelAssignmentCache.clear();
 
   34 template<typename Settings>
 
   35 void MCSATMixin<Settings>::updateCurrentLevel() {
 
   36     SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Updating current level " << current().variable);
 
   38     // Check undecided variables whether they became univariate
 
   39     SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Undecided Variables: " << mUndecidedVariables);
 
   40     for (auto vit = mUndecidedVariables.begin(); vit != mUndecidedVariables.end();) {
 
   41         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Looking at " << *vit);
 
   42         if constexpr(!Settings::early_evaluation) {
 
   43             if (computeTheoryLevel(*vit) != level()) {
 
   48             if (mGetter.isTheoryAbstraction(*vit)) {
 
   49                 const auto& f = mGetter.reabstractVariable(*vit);
 
   50                 auto evalres = carl::evaluate(f, model());
 
   51                 if (!evalres.isBool()) {
 
   54                 } else if (mBackend.isActive(f) && mGetter.getBoolVarValue(*vit) != l_Undef && mGetter.getBoolVarValue(*vit) != Minisat::lbool(evalres.asBool())) {
 
   55                     SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Found inconsistent variable " << *vit);
 
   56                     mInconsistentVariables.push_back(*vit);
 
   60         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Associating " << *vit << " with " << current().variable << " at " << level());
 
   61         current().decidedVariables.push_back(*vit);
 
   62         mTheoryLevels[varid(*vit)] = level();
 
   63         if (mGetter.getBoolVarValue(*vit) == l_Undef) {
 
   64             mSemanticPropagations.insert(*vit);
 
   66         vit = mUndecidedVariables.erase(vit);
 
   68     SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "-> " << mUndecidedVariables);
 
   71 template<typename Settings>
 
   72 bool MCSATMixin<Settings>::backtrackTo(Minisat::Lit literal) {
 
   73     std::size_t lvl = level();
 
   75         if (get(lvl).decisionLiteral == literal) break;
 
   78     SMTRAT_LOG_TRACE("smtrat.sat.mcsat", "Backtracking until " << literal << " on level " << lvl);
 
   80         SMTRAT_LOG_TRACE("smtrat.sat.mcsat", "Nothing to backtrack for " << literal);
 
   84     while (level() >= lvl) {
 
   85         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Backtracking theory assignment for " << current().variable);
 
   87         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Model " << model());
 
   89         if (current().decisionLiteral != Minisat::lit_Undef) {
 
   90             mBackend.popAssignment(current().variable);
 
   97 template<typename Settings>
 
   98 Minisat::lbool MCSATMixin<Settings>::evaluateLiteral(Minisat::Lit lit) const {
 
   99     SMTRAT_LOG_TRACE("smtrat.sat.mcsat", "Evaluate " << lit);
 
  100     const FormulaT& f = mGetter.reabstractLiteral(lit);
 
  101     SMTRAT_LOG_TRACE("smtrat.sat.mcsat", "Evaluate " << f << " on " << mBackend.getModel());
 
  102     if (!Settings::early_evaluation && computeTheoryLevel(f) > level()) return l_Undef;
 
  103     SMTRAT_LOG_TRACE("smtrat.sat.mcsat", "Evaluate " << f << " on " << mBackend.getModel());
 
  104     auto res = carl::evaluate(f, mBackend.getModel());
 
  106         return res.asBool() ? l_True : l_False;
 
  108     assert(Settings::early_evaluation);
 
  113  * Checks is given literal is feasible with the current trail.
 
  115 template<typename Settings>
 
  116 std::pair<bool, std::optional<Explanation>> MCSATMixin<Settings>::isBooleanDecisionFeasible(Minisat::Lit lit, bool always_explain) {
 
  117     auto var = Minisat::var(lit);
 
  118     if (!mGetter.isTheoryAbstraction(var)) return std::make_pair(true, std::nullopt);
 
  119     const auto& f = mGetter.reabstractLiteral(lit);
 
  121     // assert that literal is consistent with the trail
 
  122     assert(evaluateLiteral(lit) != l_False);
 
  124     auto vars = carl::arithmetic_variables(f);
 
  125     for (const auto& v : mBackend.assignedVariables())
 
  128     if (vars.size() > 0) {
 
  129         carl::Variable tvar = *(vars.begin());
 
  131         auto res = mBackend.isInfeasible(tvar, f);
 
  132         if (std::holds_alternative<ModelValues>(res)) {
 
  133             /* if (mModelAssignmentCache.empty()) {
 
  134                 mModelAssignmentCache.cache(std::get<ModelValues>(res));
 
  136             SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Decision " << lit << " (" << f << ") is feasible wrt " << tvar);
 
  137             return std::make_pair(true, std::nullopt);
 
  139             auto& confl = std::get<FormulasT>(res);
 
  140             SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Decision " << lit << " (" << f << ") is infeasible wrt " << tvar << " due to " << confl);
 
  141             if (always_explain) {
 
  142                 SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Explaining " << confl);
 
  143                 return std::make_pair(false, mBackend.explain(tvar, confl));
 
  144             } else if (std::find(confl.begin(), confl.end(), f) == confl.end()) {
 
  145                 SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Conflicting core " << confl << " is independent from decision " << f);
 
  146                 return std::make_pair(false, mBackend.explain(tvar, confl));
 
  148                 SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Check if trail without " << f << " was feasible wrt " << tvar);
 
  149                 auto expl = isFeasible(tvar);
 
  151                     SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Trail without " << f << " was infeasible wrt " << tvar);
 
  152                     return std::make_pair(false, std::move(*expl));
 
  154                     SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Infeasibility wrt " << tvar << " depends truly on " << f);
 
  155                     return std::make_pair(false, std::nullopt);
 
  160         return std::make_pair(true, std::nullopt);
 
  164 template<typename Settings>
 
  165 std::pair<boost::tribool, std::optional<Explanation>> MCSATMixin<Settings>::propagateBooleanDomain(Minisat::Lit lit) {
 
  166     auto var = Minisat::var(lit);
 
  167     if (!mGetter.isTheoryAbstraction(var)) return std::make_pair(boost::indeterminate, std::nullopt);
 
  168     const auto& f = mGetter.reabstractLiteral(lit);
 
  170     auto vars = carl::arithmetic_variables(f);
 
  171     for (const auto& v : mBackend.assignedVariables())
 
  174     assert(vars.size() > 0);
 
  176     carl::Variable tvar = *(vars.begin());
 
  178     auto res_pos = mBackend.isInfeasible(tvar, f);
 
  179     auto res_neg = mBackend.isInfeasible(tvar, f.negated());
 
  181     if (std::holds_alternative<ModelValues>(res_pos) && std::holds_alternative<ModelValues>(res_neg)) {
 
  182         /* if (mModelAssignmentCache.empty()) {
 
  183             mModelAssignmentCache.cache(std::get<ModelValues>(res));
 
  185         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Decision: " << lit << " (" << f << ") and its negation are feasible wrt " << tvar);
 
  186         return std::make_pair(boost::indeterminate, std::nullopt);
 
  187     } else if (std::holds_alternative<ModelValues>(res_pos)) {
 
  188         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Propagation: " << lit << " (" << f << ") is feasible wrt " << tvar);
 
  189         return std::make_pair(true, std::nullopt);
 
  190     } else if (std::holds_alternative<ModelValues>(res_neg)) {
 
  191         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Propagation: negation of " << lit << " (" << f << ") is feasible wrt " << tvar);
 
  192         return std::make_pair(false, std::nullopt);
 
  194         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Conflict: " << lit << " (" << f << ") and its negation are infeasible wrt " << tvar << " due to " << std::get<FormulasT>(res_pos) << " resp. " << std::get<FormulasT>(res_neg));
 
  196         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Check if trail without " << f << " was feasible wrt " << tvar);
 
  197         auto expl = isFeasible(tvar);
 
  199         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Trail without " << f << " was infeasible wrt " << tvar);
 
  200         return std::make_pair(boost::indeterminate, std::move(*expl));
 
  204 template<typename Settings>
 
  205 std::size_t MCSATMixin<Settings>::addBooleanVariable(Minisat::Var variable) {
 
  206     while (mVarPropertyCache.size() <= varid(variable)) {
 
  207         mVarPropertyCache.emplace_back();
 
  210     while (mTheoryLevels.size() <= varid(variable)) {
 
  211         mTheoryLevels.emplace_back();
 
  214     std::size_t level = computeTheoryLevel(variable);
 
  215     if (!mGetter.isTheoryAbstraction(variable)) {
 
  216         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Ignoring " << variable << " as it is not a theory abstraction");
 
  219     assert(mGetter.reabstractVariable(variable).type() != carl::FormulaType::VARASSIGN);
 
  220     if (level == std::numeric_limits<std::size_t>::max()) {
 
  221         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Adding " << variable << " to undecided");
 
  222         mUndecidedVariables.push_back(variable);
 
  223         mTheoryLevels[varid(variable)] = std::numeric_limits<std::size_t>::max();
 
  225         SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Adding " << variable << " on level " << level);
 
  226         mTheoryStack[level].decidedVariables.push_back(variable);
 
  227         mTheoryLevels[varid(variable)] = level;
 
  228         mSemanticPropagations.insert(variable);
 
  233 template<typename Settings>
 
  234 bool MCSATMixin<Settings>::isFormulaUnivariate(const FormulaT& formula, std::size_t level) const {
 
  235     assert(level < mTheoryStack.size());
 
  236     auto vars = carl::arithmetic_variables(formula);
 
  237     for (std::size_t lvl = 1; lvl <= level; lvl++) {
 
  238         vars.erase(variable(lvl));
 
  240     SMTRAT_LOG_TRACE("smtrat.sat.mcsat", "Checking if " << formula << " is univariate on level " << level << ": " << vars.empty());
 
  244 template<typename Settings>
 
  245 void MCSATMixin<Settings>::printClause(std::ostream& os, Minisat::CRef clause) const {
 
  246     const Minisat::Clause& c = mGetter.getClause(clause);
 
  248     for (int i = 0; i < c.size(); i++) {
 
  249         if (i > 0) os << " ";
 
  250         if (mGetter.isTheoryAbstraction(var(c[i]))) {
 
  251             os << mGetter.reabstractLiteral(c[i]);
 
  259 template<typename Settings>
 
  260 std::ostream& operator<<(std::ostream& os, const MCSATMixin<Settings>& mcm) {
 
  261     os << "Theory Stack: " << mcm.level() << std::endl;
 
  262     for (std::size_t lvl = 0; lvl < mcm.mTheoryStack.size(); lvl++) {
 
  263         const auto& level = mcm.get(lvl);
 
  264         os << lvl << " / " << level.variable << " (" << level.decisionLiteral << ")";
 
  265         if (mcm.model().find(level.variable) != mcm.model().end()) {
 
  266             os << " = " << mcm.model().at(level.variable);
 
  268         // if (level.variable == mcm.current().variable) {
 
  269         //  os << " <<-- Current variable";
 
  272         os << "\tVariables: " << level.decidedVariables << std::endl;
 
  274     os << "Backend:" << std::endl;
 
  275     os << mcm.mBackend << std::endl;
 
  276     os << "Theory variable mapping:" << std::endl;
 
  277     os << mcm.mTheoryVarMapping.minisatToCarl << std::endl;