SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
MCSATMixin.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "../SolverTypes.h"
4 
5 #include "BaseBackend.h"
6 #include "../ClauseChecker.h"
7 
8 #include "MCSATStatistics.h"
9 
10 #include <carl-formula/model/Assignment.h>
11 
13 
14 #include <functional>
15 #include <map>
16 #include <set>
17 #include <vector>
18 
19 namespace smtrat {
20 namespace mcsat {
21 
22 using carl::operator<<;
23 
28  std::function<int(Minisat::Var)> getDecisionLevel;
29  std::function<int(Minisat::Var)> getTrailIndex;
31  std::function<const Minisat::Clause&(Minisat::CRef)> getClause;
32  std::function<const Minisat::vec<Minisat::CRef>&()> getClauses;
33  std::function<const Minisat::vec<Minisat::CRef>&()> getLearntClauses;
34  std::function<bool(Minisat::Var)> isTheoryAbstraction;
35  std::function<bool(const FormulaT&)> isAbstractedFormula;
36  std::function<Minisat::Var(const FormulaT&)> abstractVariable;
37  std::function<const FormulaT&(Minisat::Var)> reabstractVariable;
38  std::function<const FormulaT&(Minisat::Lit)> reabstractLiteral;
39  std::function<const Minisat::vec<Minisat::Watcher>&(Minisat::Lit)> getWatches;
40  std::function<Minisat::Var()> newVar;
41 };
42 struct TheoryLevel {
43  /// Theory variable for this level
44  carl::Variable variable = carl::Variable::NO_VARIABLE;
45  /// Literal that assigns this theory variable
47  /// Boolean variables univariate in this theory variable
48  std::vector<Minisat::Var> decidedVariables;
49 };
50 
51 template<typename Settings>
52 class MCSATMixin {
53 
54 private:
56 
57  /**
58  * The first entry of the stack always contains an entry for the non-theory
59  * variables: the variable is set to NO_VARIABLE and the lists contain
60  * variables that do not contain any theory variables.
61  */
62  using TheoryStackT = std::vector<TheoryLevel>;
64 
65  /// Theory levels for Boolean variables
66  std::vector<size_t> mTheoryLevels;
67 
68  /// Variables that are not univariate in any variable yet.
69  std::vector<Minisat::Var> mUndecidedVariables;
70 
71  /// Variables that are inconsistent in the current theory level
72  std::vector<Minisat::Var> mInconsistentVariables;
73 
74  /// Semantically propagated variables that are not yet inserted into the trail
75  std::set<Minisat::Var> mSemanticPropagations;
76 
77  std::map<Minisat::Var, std::vector<Minisat::Var>> mVarDeps;
78 
80 
81  struct VarMapping {
82  std::map<Minisat::Var, carl::Variable> minisatToCarl;
83  std::map<carl::Variable, Minisat::Var> carlToMinisat;
84 
85  void insert(const carl::Variable& carlVar, Minisat::Var minisatVar) {
88  }
89 
90  bool has(Minisat::Var v) const {
91  return minisatToCarl.find(v) != minisatToCarl.end();
92  }
93 
94  bool has(const carl::Variable& v) const {
95  return carlToMinisat.find(v) != carlToMinisat.end();
96  }
97 
98  const carl::Variable& carlVar(Minisat::Var v) const {
99  return minisatToCarl.at(v);
100  }
101 
102  Minisat::Var minisatVar(const carl::Variable& v) const {
103  return carlToMinisat.at(v);
104  }
105 
106  std::vector<Minisat::Var> minisatVars() const {
107  std::vector<Minisat::Var> res;
108  for(auto it = minisatToCarl.begin(); it != minisatToCarl.end(); ++it) {
109  res.push_back(it->first);
110  }
111  return res;
112  }
113  };
115 
116  #ifdef SMTRAT_DEVOPTION_Statistics
117  MCSATStatistics& mStatistics;
118  #endif
119 
120  /*
121  struct ModelAssignmentCache { // TODO reintroduce model assignment cache
122  ModelValues mContent;
123  Model mModel;
124  const Model& mBaseModel;
125 
126  ModelAssignmentCache(const Model& baseModel) : mBaseModel(baseModel) {
127  mModel = mBaseModel;
128  }
129 
130  bool empty() const {
131  return mContent.empty();
132  }
133 
134  void clear() {
135  mContent.clear();
136  mModel = mBaseModel;
137  }
138 
139  void cache(const ModelValues& val) {
140  assert(empty());
141  mModel = mBaseModel;
142  mContent = val;
143  for (const auto& assignment : content()) {
144  mModel.emplace(assignment.first, assignment.second);
145  }
146  }
147 
148  const ModelValues& content() const {
149  return mContent;
150  }
151 
152  const Model& model() const {
153  return mModel;
154  }
155  };
156  /// Cache for the next model assignemt(s)
157  ModelAssignmentCache mModelAssignmentCache;
158  */
159 
160  struct VarProperties {
161  std::optional<std::size_t> maxDegree = std::nullopt;
162  std::optional<std::vector<Minisat::Var>> theoryVars = std::nullopt;
163  };
164  /// Cache for static information about variables
165  std::vector<VarProperties> mVarPropertyCache;
166 
167 private:
168  // ***** private helper methods
169 
170  /// Updates lookup for the current level
172  /// Pop a theory decision
174 
175  std::size_t varid(Minisat::Var var) const {
176  assert(var >= 0);
177  return static_cast<std::size_t>(var);
178  }
179 public:
180 
181  template<typename BaseModule>
182  explicit MCSATMixin(BaseModule& baseModule):
183  mGetter({
184  [&baseModule](Minisat::Var v){ return baseModule.value(v); },
185  [&baseModule](Minisat::Lit l){ return baseModule.value(l); },
186  [&baseModule](Minisat::Var l){ return baseModule.bool_value(l); },
187  [&baseModule](Minisat::Var v){ return baseModule.vardata[v].level; },
188  [&baseModule](Minisat::Var v){ return baseModule.vardata[v].mTrailIndex; },
189  [&baseModule](Minisat::Var v){ return baseModule.reason(v); },
190  [&baseModule](Minisat::CRef c) -> const auto& { return baseModule.ca[c]; },
191  [&baseModule]() -> const auto& { return baseModule.clauses; },
192  [&baseModule]() -> const auto& { return baseModule.learnts; },
193  [&baseModule](Minisat::Var v){ return (baseModule.mBooleanConstraintMap.size() > v) && (baseModule.mBooleanConstraintMap[v].first != nullptr); },
194  [&baseModule](const FormulaT& f) { return baseModule.mConstraintLiteralMap.count(f) > 0; },
195  [&baseModule](const FormulaT& f) { return var(baseModule.mConstraintLiteralMap.at(f).front()); },
196  [&baseModule](Minisat::Var v) -> const auto& { return baseModule.mBooleanConstraintMap[v].first->reabstraction; },
197  [&baseModule](Minisat::Lit l) -> const auto& { return sign(l) ? baseModule.mBooleanConstraintMap[var(l)].second->reabstraction : baseModule.mBooleanConstraintMap[var(l)].first->reabstraction; },
198  [&baseModule](Minisat::Lit l) -> const auto& { return baseModule.watches[l]; },
199  [&baseModule]() -> Minisat::Var { baseModule.mBooleanConstraintMap.push( std::make_pair( nullptr, nullptr ) ); return baseModule.newVar(true,true,0,false); }
200  }),
202 #ifdef SMTRAT_DEVOPTION_Statistics
203  , mStatistics(baseModule.mMCSATStatistics)
204 #endif
205  // mModelAssignmentCache(model())
206  {}
207 
208  std::size_t level() const {
209  return mTheoryStack.size() - 1;
210  }
211  const Model& model() const {
212  return mBackend.getModel();
213  }
214  const std::vector<Minisat::Var>& undecidedBooleanVariables() const {
215  return mUndecidedVariables;
216  }
217  bool isAssignedTheoryVariable(const carl::Variable& var) const {
218  return std::find(mBackend.assignedVariables().begin(), mBackend.assignedVariables().end(), var) != mBackend.assignedVariables().end();
219  }
221  return mBackend.assignedVariables().size() == mBackend.variables().size();
222  }
223  /// Returns the respective theory level
224  const TheoryLevel& get(std::size_t level) const {
225  assert(level < mTheoryStack.size());
226  return mTheoryStack[level];
227  }
228  /// Returns the current theory level
229  const TheoryLevel& current() const {
230  return mTheoryStack.back();
231  }
233  return mTheoryStack.back();
234  }
235  /// Retrieve already decided theory variables
236  carl::Variable variable(std::size_t level) const {
237  SMTRAT_LOG_TRACE("smtrat.sat.mcsat", "Obtaining variable " << level);
238  assert(level < mTheoryStack.size());
239  if (level == 0) return carl::Variable::NO_VARIABLE;
240  return get(level).variable;
241  }
242 
243  // ***** Modifier
244 
245  /**
246  * Add a new constraint.
247  */
249  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Assigned " << lit);
250  if (!mGetter.isTheoryAbstraction(var(lit))) return;
251  const auto& f = mGetter.reabstractLiteral(lit);
252  if (f.type() == carl::FormulaType::VARASSIGN) {
253  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Skipping assignment.");
254  return;
255  }
256  assert(evaluateLiteral(lit) != l_False);
257  /*
258  if (!mModelAssignmentCache.empty()) {
259  #ifdef SMTRAT_DEVOPTION_Statistics
260  mStatistics.modelAssignmentCacheHit();
261  #endif
262 
263  auto res = carl::evaluate(f, mModelAssignmentCache.model());
264  if (!res.isBool() || !res.asBool()) {
265  mModelAssignmentCache.clear(); // clear model assignment cache
266  }
267  }
268  */
269  mBackend.pushConstraint(f);
270  mSemanticPropagations.erase(var(lit));
271  }
272  /**
273  * Remove the last constraint. f must be the same as the one passed to the last call of pushConstraint().
274  */
276  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Unassigned " << lit);
277  if (!mGetter.isTheoryAbstraction(var(lit))) return;
278  const auto& f = mGetter.reabstractLiteral(lit);
279  if (f.type() == carl::FormulaType::VARASSIGN) {
280  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Skipping assignment.");
281  return;
282  }
283  mBackend.popConstraint(f);
284 
285  auto iter = std::find(mInconsistentVariables.begin(), mInconsistentVariables.end(), var(lit));
286  if (iter != mInconsistentVariables.end())
287  mInconsistentVariables.erase(iter);
288 
289  if (theoryLevel(var(lit)) < std::numeric_limits<std::size_t>::max()) {
290  mSemanticPropagations.insert(var(lit));
291  }
292  }
293 
294  /// Add a variable, return the level it was inserted on
296 
297  /// Getter for semantic propagations
299  if (mSemanticPropagations.empty()) {
300  return var_Undef;
301  } else {
302  return *mSemanticPropagations.begin();
303  }
304  }
305 
306  // ***** Auxiliary getter
307 
308  /// Checks whether the given formula is univariate on the given level
309  bool isFormulaUnivariate(const FormulaT& formula, std::size_t level) const;
310 
311  /// Push a theory decision
312  void pushTheoryDecision(const FormulaT& assignment, Minisat::Lit decisionLiteral);
313  /// Backtracks to the theory decision represented by the given literal.
314  bool backtrackTo(Minisat::Lit literal);
315 
316  // ***** Helper methods
317 
318  /// Evaluate a literal in the theory, set lastReason to last theory decision involved.
320 
321  std::pair<bool, std::optional<Explanation>> isBooleanDecisionFeasible(Minisat::Lit lit, bool always_explain = false);
322 
323  std::pair<boost::tribool, std::optional<Explanation>> propagateBooleanDomain(Minisat::Lit lit);
324 
325  std::optional<Explanation> isFeasible(const carl::Variable& var) {
326  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Checking whether trail is feasible (w.r.t. " << var << ")");
327  /*
328  AssignmentOrConflict res;
329  if (!mModelAssignmentCache.empty()) {
330  #ifdef SMTRAT_DEVOPTION_Statistics
331  mStatistics.modelAssignmentCacheHit();
332  #endif
333  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Found cached assignment.");
334  return std::nullopt;
335  } else { */
336  auto res = mBackend.findAssignment(var);
337  if (std::holds_alternative<ModelValues>(res)) {
338  // mModelAssignmentCache.cache(std::get<ModelValues>(res));
339  return std::nullopt;
340  } else {
341  const auto& confl = std::get<FormulasT>(res);
342  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Explaining " << confl);
343  return mBackend.explain(var, confl);
344  }
345  // }
346  }
347 
348  std::variant<Explanation,FormulasT> makeTheoryDecision(const carl::Variable& var) {
349  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Obtaining assignment");
350  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", mBackend);
352  // if (mModelAssignmentCache.empty()) {
353  res = mBackend.findAssignment(var);
354  /*} else {
355  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Found cached assignment.");
356  #ifdef SMTRAT_DEVOPTION_Statistics
357  mStatistics.modelAssignmentCacheHit();
358  #endif
359  res = mModelAssignmentCache.content();
360  mModelAssignmentCache.clear();
361  }*/
362  if (std::holds_alternative<ModelValues>(res)) {
363  const auto& values = std::get<ModelValues>(res);
364  SMTRAT_LOG_INFO("smtrat.sat.mcsat", "-> " << values);
365  FormulasT reprs;
366  for (const auto& value : values) {
367  FormulaT repr = carl::representingFormula(value.first, value.second);
368  reprs.push_back(std::move(repr));
369  }
370  return reprs;
371  } else {
372  const auto& confl = std::get<FormulasT>(res);
373  auto explanation = mBackend.explain(var, confl);
374  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Got a conflict: " << explanation);
375  return explanation;
376  }
377  }
378 
379  /**
380  * Checks if any inconsistency was detected.
381  */
382  bool is_consistent() {
383  return mInconsistentVariables.empty();
384  }
385 
388  }
389 
390  /**
391  * Checks if the trail is consistent after the assignment on the current level.
392  * The trail must be consistent on the previous level.
393  *
394  * Returns std::nullopt if consistent and an explanation.
395  */
396  std::optional<Explanation> explainInconsistency() {
397  if (is_consistent()) {
398  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Trail is still consistent");
399  return std::nullopt;
400  } else {
401  const auto& conflvar = mInconsistentVariables.front();
402  auto val = mGetter.getBoolVarValue(conflvar);
403  assert(val != l_Undef);
404  const auto confl = (val == l_True) ? mGetter.reabstractVariable(conflvar) : mGetter.reabstractVariable(conflvar).negated();
405 
406  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Inconsistent: " << confl << " evaluates to false");
407  // pick any unassigned variable in confl (it must exist, otherwise the AssignmentFinder is incorrect)
408 
409  auto vars = carl::arithmetic_variables(confl);
410  for (const auto& avar : mBackend.assignedVariables())
411  vars.erase(avar);
412  assert(vars.size() > 0);
413  auto explanation = mBackend.explain(*(vars.begin()), {confl});
414  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Got a conflict: " << explanation);
415  return explanation;
416  }
417  }
418 
420  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Current state: " << (*this));
421  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Explaining " << literal << " under " << mBackend.getModel());
422  const auto& f = mGetter.reabstractLiteral(literal);
423 
424  carl::carlVariables vars;
425  carl::variables(f,vars);
426  for (const auto& v : mBackend.assignedVariables())
427  vars.erase(v);
428  assert(vars.size() == 1);
429  carl::Variable tvar = *(vars.begin());
430 
431  auto conflict = mBackend.isInfeasible(tvar, !f);
432  assert(std::holds_alternative<FormulasT>(conflict));
433  auto& confl = std::get<FormulasT>(conflict);
434  assert( std::find(confl.begin(), confl.end(), !f) != confl.end() );
435  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Explaining " << f << " from " << confl);
436  auto res = mBackend.explain(tvar, !f, confl);
437  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Explaining " << f << " by " << res);
438  // f is part of the conflict, because the trail is feasible without f:
439  if (std::holds_alternative<FormulaT>(res)) {
440  if (std::get<FormulaT>(res).is_false()) {
441  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Explanation failed.");
442  } else {
443  assert(std::get<FormulaT>(res).contains(f));
444  }
445  }
446  else {
447  assert(std::get<ClauseChain>(res).chain().back().clause().contains(f));
448  }
449  return res;
450  }
451 
452  template<typename Constraints>
453  void initVariables(const Constraints& c) {
454  if (mBackend.variables().empty()) {
455  carl::carlVariables vars;
456  std::map<carl::Variable,carl::Variables> deps;
457  for (int i = 0; i < c.size(); ++i) {
458  if (c[i].first == nullptr) continue;
459  if (c[i].first->reabstraction.type() == carl::FormulaType::CONSTRAINT) {
460  const ConstraintT& constr = c[i].first->reabstraction.constraint();
461  carl::variables(constr, vars);
462  } else if (c[i].first->reabstraction.type() == carl::FormulaType::VARCOMPARE) {
463  const auto& constr = c[i].first->reabstraction.variable_comparison();
464  carl::variables(constr, vars);
465  if (std::holds_alternative<carl::MultivariateRoot<Poly>>(constr.value())) {
466  auto dep_vars = carl::variables(constr);
467  dep_vars.erase(constr.var());
468  deps.try_emplace(constr.var()).first->second.insert(dep_vars.begin(), dep_vars.end());
469  }
470  }
471  }
472  mBackend.initVariables(vars.as_set());
473  for (const carl::Variable& theoryVar : vars) {
474  if (!mTheoryVarMapping.has(theoryVar)) {
476  mTheoryVarMapping.insert(theoryVar, minisatVar);
477  }
478  }
479  for (const auto& p : deps) {
480  std::vector<Minisat::Var> d;
481  for (const auto& v : p.second) {
482  d.push_back(mTheoryVarMapping.minisatVar(v));
483  }
484  mVarDeps.emplace(mTheoryVarMapping.minisatVar(p.first), std::move(d));
485  }
486  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Got variables " << mBackend.variables() << " with dependencies " << mVarDeps);
487  }
488  }
489 
490  bool isTheoryVar(Minisat::Var v) const {
491  return mTheoryVarMapping.has(v);
492  }
493 
494  const carl::Variable& carlVar(Minisat::Var v) const {
495  return mTheoryVarMapping.carlVar(v);
496  }
497 
498  Minisat::Var minisatVar(const carl::Variable& v) const {
499  return mTheoryVarMapping.minisatVar(v);
500  }
501 
502  std::vector<Minisat::Var> theoryVarAbstractions() const {
504  }
505 
507  auto e = mVarDeps.find(v);
508  if (e == mVarDeps.end()) return false;
509  auto d = std::find_if(e->second.begin(), e->second.end(), [this](const auto& c) {
510  return !this->isAssignedTheoryVariable(this->carlVar(c));
511  });
512  return (d != e->second.end());
513  }
514 
515  // ***** Auxliary getter
516 
517  std::size_t theoryLevel(Minisat::Var var) const {
519  return 0;
520  }
521  assert(varid(var) < mTheoryLevels.size());
522  return mTheoryLevels[varid(var)];
523  }
524 
525  std::size_t computeTheoryLevel(Minisat::Var var) const {
527  return 0;
528  }
530  }
531 
532  std::size_t computeTheoryLevel(const FormulaT& f) const {
533  SMTRAT_LOG_TRACE("smtrat.sat.mcsat", "Computing theory level for " << f);
534  if constexpr(!Settings::early_evaluation) {
535  auto poly_variables = f.variables();
536  if (poly_variables.empty()) {
537  return 0;
538  }
539  for (std::size_t level = 1; level < mTheoryStack.size(); ++level) {
540  poly_variables.erase(mTheoryStack[level].variable);
541  if (poly_variables.empty()) return level;
542  }
543  SMTRAT_LOG_TRACE("smtrat.sat.mcsat", f << " is undecided.");
544  return std::numeric_limits<std::size_t>::max();
545  } else {
546  carl::carlVariables vars;
547  carl::variables(f,vars);
548  if (vars.empty()) {
549  SMTRAT_LOG_TRACE("smtrat.sat.mcsat", f << " has no variable, thus on level 0");
550  return 0;
551  }
552 
553  Model m = model();
554  if (!carl::evaluate(f, m).isBool()) {
555  SMTRAT_LOG_TRACE("smtrat.sat.mcsat", f << " is undecided.");
556  return std::numeric_limits<std::size_t>::max();
557  }
558  for (std::size_t lvl = level(); lvl > 0; lvl--) {
559  if (variable(lvl) == carl::Variable::NO_VARIABLE) continue;
560  m.erase(variable(lvl));
561  if (!vars.has(variable(lvl))) continue;
562  if (!carl::evaluate(f, m).isBool()) {
563  return lvl;
564  }
565  }
566  assert(false);
567  return 0;
568  }
569  }
570 
573  return Minisat::lit_Undef;
574  }
575  std::size_t level = theoryLevel(var);
576  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Theory level of " << var << " is " << level);
577  if (level >= mTheoryStack.size()) return Minisat::lit_Undef;
578  return get(level).decisionLiteral;
579  }
580 
582  auto lit = getDecisionLiteral(variable);
583  if (lit == Minisat::lit_Undef) {
584  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", variable << " was not assigned yet.");
585  return std::numeric_limits<int>::max();
586  }
587  return mGetter.getTrailIndex(var(lit));
588  }
589 
591  if (!mGetter.isTheoryAbstraction(v)) {
592  return std::numeric_limits<int>::max();
593  }
594  auto lit = getDecisionLiteral(v);
595  if (lit == Minisat::lit_Undef) {
596  return std::numeric_limits<int>::max();
597  }
598  return mGetter.getDecisionLevel(var(lit));
599  }
600 
601  bool fullConsistencyCheck() const {
602  const auto& trail = mBackend.getTrail();
603  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", "Checking trail against " << trail.model());
604  auto evaluator = [&trail](const auto& c){
605  auto res = carl::evaluate(c, trail.model());
606  SMTRAT_LOG_DEBUG("smtrat.sat.mcsat", c << " evaluates to " << res);
607  if (res.isBool()) {
608  if (!res.asBool()) return false;
609  }
610  return true;
611  };
612  for (const auto& c: trail.constraints()) {
613  if (!mBackend.isActive(c)) continue;
614  //auto category = mcsat::constraint_type::categorize(c, model(), carl::Variable::NO_VARIABLE);
615  //if (category != mcsat::ConstraintType::Assigned) continue;
616  if (!Settings::early_evaluation && computeTheoryLevel(FormulaT(c)) > level()) continue;
617  if (!evaluator(c)) return false;
618  }
619  for (const auto& b: trail.mvBounds()) {
620  if (!mBackend.isActive(b)) continue;
621  //auto category = mcsat::constraint_type::categorize(b, model(), carl::Variable::NO_VARIABLE);
622  //if (category != mcsat::ConstraintType::Assigned) continue;
623  if (!Settings::early_evaluation && computeTheoryLevel(FormulaT(b)) > level()) continue;
624  if (!evaluator(b)) return false;
625  }
626  return true;
627  }
628 
629  std::size_t maxDegree(const Minisat::Var& var) {
630  std::size_t v = varid(var);
631  assert(v < mVarPropertyCache.size());
632 
633  if (mVarPropertyCache[v].maxDegree == std::nullopt) {
635  mVarPropertyCache[v].maxDegree = 0;
636  } else {
637  const auto& reabstraction = mGetter.reabstractVariable(var);
638  if (reabstraction.type() == carl::FormulaType::CONSTRAINT) {
639  const auto& constr = reabstraction.constraint();
640  auto vars = carl::arithmetic_variables(reabstraction);
641  std::size_t maxDeg = 0;
642  for (const auto& tvar : vars) {
643  std::size_t deg = constr.lhs().degree(tvar);
644  if (deg > maxDeg) maxDeg = deg;
645  }
646  mVarPropertyCache[v].maxDegree = maxDeg;
647  } else if (reabstraction.type() == carl::FormulaType::VARCOMPARE) {
648  mVarPropertyCache[v].maxDegree = std::numeric_limits<std::size_t>::max();
649  } else {
650  assert(false);
651  }
652 
653  }
654  }
655 
656  assert(mVarPropertyCache[v].maxDegree != std::nullopt);
657  return *mVarPropertyCache[v].maxDegree;
658  }
659 
660  std::vector<Minisat::Var> theoryVars(const Minisat::Var& var) {
661  std::size_t v = varid(var);
662  assert(v < mVarPropertyCache.size());
663 
664  if (mVarPropertyCache[v].theoryVars == std::nullopt) {
665  if (!mGetter.isTheoryAbstraction(static_cast<int>(v))) {
666  mVarPropertyCache[v].theoryVars = std::vector<Minisat::Var>();
667  } else {
668  const auto& reabstraction = mGetter.reabstractVariable(var);
669  auto tvars = carl::arithmetic_variables(reabstraction);
670  std::vector<Minisat::Var> vars;
671  for (const auto& tvar : tvars) {
672  vars.push_back(minisatVar(tvar));
673  }
674  mVarPropertyCache[v].theoryVars = vars;
675  }
676  }
677 
678  assert(mVarPropertyCache[v].theoryVars != std::nullopt);
679  return *mVarPropertyCache[v].theoryVars;
680  }
681 
682  // ***** Output
683  /// Prints a single clause
684  void printClause(std::ostream& os, Minisat::CRef clause) const;
685  template<typename Sett>
686  friend std::ostream& operator<<(std::ostream& os, const MCSATMixin<Sett>& mcm);
687 };
688 
689 }
690 }
691 
692 #include "MCSATMixin.tpp"
#define var_Undef
Definition: SolverTypes.h:43
#define l_True
Definition: SolverTypes.h:97
#define l_Undef
Definition: SolverTypes.h:99
#define l_False
Definition: SolverTypes.h:98
bool theoryAssignmentComplete() const
Definition: MCSATMixin.h:220
std::vector< size_t > mTheoryLevels
Theory levels for Boolean variables.
Definition: MCSATMixin.h:66
bool hasUnassignedDep(Minisat::Var v) const
Definition: MCSATMixin.h:506
std::size_t computeTheoryLevel(const FormulaT &f) const
Definition: MCSATMixin.h:532
bool isAssignedTheoryVariable(const carl::Variable &var) const
Definition: MCSATMixin.h:217
Minisat::lbool evaluateLiteral(Minisat::Lit lit) const
Evaluate a literal in the theory, set lastReason to last theory decision involved.
friend std::ostream & operator<<(std::ostream &os, const MCSATMixin< Sett > &mcm)
bool isTheoryVar(Minisat::Var v) const
Definition: MCSATMixin.h:490
bool fullConsistencyCheck() const
Definition: MCSATMixin.h:601
std::pair< bool, std::optional< Explanation > > isBooleanDecisionFeasible(Minisat::Lit lit, bool always_explain=false)
std::map< Minisat::Var, std::vector< Minisat::Var > > mVarDeps
Definition: MCSATMixin.h:77
std::vector< Minisat::Var > mInconsistentVariables
Variables that are inconsistent in the current theory level.
Definition: MCSATMixin.h:72
const std::vector< Minisat::Var > & undecidedBooleanVariables() const
Definition: MCSATMixin.h:214
int assignedAtTrailIndex(Minisat::Var variable) const
Definition: MCSATMixin.h:581
bool is_consistent()
Checks if any inconsistency was detected.
Definition: MCSATMixin.h:382
void pushTheoryDecision(const FormulaT &assignment, Minisat::Lit decisionLiteral)
Push a theory decision.
std::vector< TheoryLevel > TheoryStackT
The first entry of the stack always contains an entry for the non-theory variables: the variable is s...
Definition: MCSATMixin.h:62
TheoryLevel & current()
Definition: MCSATMixin.h:232
const TheoryLevel & get(std::size_t level) const
Returns the respective theory level.
Definition: MCSATMixin.h:224
bool backtrackTo(Minisat::Lit literal)
Backtracks to the theory decision represented by the given literal.
MCSATBackend< Settings > mBackend
Definition: MCSATMixin.h:79
Minisat::Lit getDecisionLiteral(Minisat::Var var) const
Definition: MCSATMixin.h:571
void undoBooleanAssignment(Minisat::Lit lit)
Remove the last constraint.
Definition: MCSATMixin.h:275
int decisionLevel(Minisat::Var v) const
Definition: MCSATMixin.h:590
std::optional< Explanation > isFeasible(const carl::Variable &var)
Definition: MCSATMixin.h:325
std::size_t computeTheoryLevel(Minisat::Var var) const
Definition: MCSATMixin.h:525
void updateCurrentLevel()
Updates lookup for the current level.
const TheoryLevel & current() const
Returns the current theory level.
Definition: MCSATMixin.h:229
std::size_t level() const
Definition: MCSATMixin.h:208
std::vector< Minisat::Var > theoryVarAbstractions() const
Definition: MCSATMixin.h:502
void printClause(std::ostream &os, Minisat::CRef clause) const
Prints a single clause.
void popTheoryDecision()
Pop a theory decision.
void doBooleanAssignment(Minisat::Lit lit)
Add a new constraint.
Definition: MCSATMixin.h:248
Minisat::Var minisatVar(const carl::Variable &v) const
Definition: MCSATMixin.h:498
InformationGetter mGetter
Definition: MCSATMixin.h:55
std::size_t theoryLevel(Minisat::Var var) const
Definition: MCSATMixin.h:517
std::set< Minisat::Var > mSemanticPropagations
Semantically propagated variables that are not yet inserted into the trail.
Definition: MCSATMixin.h:75
std::variant< Explanation, FormulasT > makeTheoryDecision(const carl::Variable &var)
Definition: MCSATMixin.h:348
carl::Variable variable(std::size_t level) const
Retrieve already decided theory variables.
Definition: MCSATMixin.h:236
VarMapping mTheoryVarMapping
Definition: MCSATMixin.h:114
MCSATMixin(BaseModule &baseModule)
Definition: MCSATMixin.h:182
TheoryStackT mTheoryStack
Definition: MCSATMixin.h:63
std::pair< boost::tribool, std::optional< Explanation > > propagateBooleanDomain(Minisat::Lit lit)
std::size_t addBooleanVariable(Minisat::Var variable)
Add a variable, return the level it was inserted on.
std::vector< Minisat::Var > theoryVars(const Minisat::Var &var)
Definition: MCSATMixin.h:660
const Model & model() const
Definition: MCSATMixin.h:211
void initVariables(const Constraints &c)
Definition: MCSATMixin.h:453
Minisat::Var topSemanticPropagation()
Getter for semantic propagations.
Definition: MCSATMixin.h:298
const carl::Variable & carlVar(Minisat::Var v) const
Definition: MCSATMixin.h:494
std::size_t varid(Minisat::Var var) const
Definition: MCSATMixin.h:175
bool is_consistent(Minisat::Var v)
Definition: MCSATMixin.h:386
std::vector< Minisat::Var > mUndecidedVariables
Variables that are not univariate in any variable yet.
Definition: MCSATMixin.h:69
bool isFormulaUnivariate(const FormulaT &formula, std::size_t level) const
Checks whether the given formula is univariate on the given level.
Explanation explainTheoryPropagation(Minisat::Lit literal)
Definition: MCSATMixin.h:419
std::optional< Explanation > explainInconsistency()
Checks if the trail is consistent after the assignment on the current level.
Definition: MCSATMixin.h:396
std::size_t maxDegree(const Minisat::Var &var)
Definition: MCSATMixin.h:629
std::vector< VarProperties > mVarPropertyCache
Cache for static information about variables.
Definition: MCSATMixin.h:165
int Var
Definition: SolverTypes.h:42
int var(Lit p)
Definition: SolverTypes.h:64
static bool find(V &ts, const T &t)
Definition: Alg.h:47
RegionAllocator< uint32_t >::Ref CRef
Definition: SolverTypes.h:142
bool sign(Lit p)
Definition: SolverTypes.h:63
const Lit lit_Undef
Definition: SolverTypes.h:72
Rational evaluate(carl::Variable v, const Poly &p, const Rational &r)
Definition: utils.h:11
bool contains(const std::vector< TagPoly > &polys, const Poly &poly)
Definition: utils.h:314
std::variant< FormulaT, ClauseChain > Explanation
Definition: smtrat-mcsat.h:14
std::variant< ModelValues, FormulasT > AssignmentOrConflict
Definition: smtrat-mcsat.h:13
std::vector< carl::Variable > vars(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Definition: QEQuery.h:43
Class to create the formulas for axioms.
carl::Formula< Poly > FormulaT
Definition: types.h:37
carl::Model< Rational, Poly > Model
Definition: model.h:13
carl::Constraint< Poly > ConstraintT
Definition: types.h:29
carl::Formulas< Poly > FormulasT
Definition: types.h:39
#define SMTRAT_LOG_TRACE(channel, msg)
Definition: logging.h:36
#define SMTRAT_LOG_INFO(channel, msg)
Definition: logging.h:34
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35
std::function< const FormulaT &(Minisat::Var)> reabstractVariable
Definition: MCSATMixin.h:37
std::function< int(Minisat::Var)> getDecisionLevel
Definition: MCSATMixin.h:28
std::function< const Minisat::vec< Minisat::Watcher > &(Minisat::Lit)> getWatches
Definition: MCSATMixin.h:39
std::function< Minisat::Var()> newVar
Definition: MCSATMixin.h:40
std::function< Minisat::lbool(Minisat::Var)> getVarValue
Definition: MCSATMixin.h:25
std::function< bool(const FormulaT &)> isAbstractedFormula
Definition: MCSATMixin.h:35
std::function< Minisat::lbool(Minisat::Var)> getBoolVarValue
Definition: MCSATMixin.h:27
std::function< const FormulaT &(Minisat::Lit)> reabstractLiteral
Definition: MCSATMixin.h:38
std::function< Minisat::Var(const FormulaT &)> abstractVariable
Definition: MCSATMixin.h:36
std::function< const Minisat::Clause &(Minisat::CRef)> getClause
Definition: MCSATMixin.h:31
std::function< int(Minisat::Var)> getTrailIndex
Definition: MCSATMixin.h:29
std::function< const Minisat::vec< Minisat::CRef > &()> getLearntClauses
Definition: MCSATMixin.h:33
std::function< Minisat::CRef(Minisat::Var)> getReason
Definition: MCSATMixin.h:30
std::function< const Minisat::vec< Minisat::CRef > &()> getClauses
Definition: MCSATMixin.h:32
std::function< Minisat::lbool(Minisat::Lit)> getLitValue
Definition: MCSATMixin.h:26
std::function< bool(Minisat::Var)> isTheoryAbstraction
Definition: MCSATMixin.h:34
bool has(const carl::Variable &v) const
Definition: MCSATMixin.h:94
Minisat::Var minisatVar(const carl::Variable &v) const
Definition: MCSATMixin.h:102
std::vector< Minisat::Var > minisatVars() const
Definition: MCSATMixin.h:106
std::map< carl::Variable, Minisat::Var > carlToMinisat
Definition: MCSATMixin.h:83
bool has(Minisat::Var v) const
Definition: MCSATMixin.h:90
std::map< Minisat::Var, carl::Variable > minisatToCarl
Definition: MCSATMixin.h:82
const carl::Variable & carlVar(Minisat::Var v) const
Definition: MCSATMixin.h:98
void insert(const carl::Variable &carlVar, Minisat::Var minisatVar)
Definition: MCSATMixin.h:85
std::optional< std::size_t > maxDegree
Definition: MCSATMixin.h:161
std::optional< std::vector< Minisat::Var > > theoryVars
Definition: MCSATMixin.h:162
carl::Variable variable
Theory variable for this level.
Definition: MCSATMixin.h:44
std::vector< Minisat::Var > decidedVariables
Boolean variables univariate in this theory variable.
Definition: MCSATMixin.h:48
Minisat::Lit decisionLiteral
Literal that assigns this theory variable.
Definition: MCSATMixin.h:46