SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
Explanation.cpp
Go to the documentation of this file.
1 #include "Explanation.h"
2 #include "OneCellCAD.h"
3 
5 
6 #include <carl-common/config.h>
7 
8 namespace smtrat {
9 namespace mcsat {
10 namespace onecellcad {
11 namespace recursive {
12 
13 
14 inline void setNullification(bool n){
16 }
17 
18 template<class Setting1, class Setting2>
19 std::optional<mcsat::Explanation> Explanation<Setting1,Setting2>::operator()(const mcsat::Bookkeeping& trail, // current assignment state
20  carl::Variable var,
21  const FormulasT& trailLiterals, bool) const {
22 
23  assert(trail.model().size() == trail.assignedVariables().size());
24 
25 #ifdef SMTRAT_DEVOPTION_Statistics
26  getStatistic().explanationCalled();
27 #endif
28 
29  #if not (defined USE_COCOA || defined USE_GINAC)
30  // OneCellCAD needs carl::irreducible_factors to be implemented
31  #warning OneCellCAD may be incorrect as USE_COCOA is disabled
32  #endif
33 
34  // compute compatible complete variable ordering
35  std::vector varOrder(trail.assignedVariables());
36  varOrder.push_back(var);
37  for (const auto& v : trail.variables()) {
38  if (std::find(varOrder.begin(), varOrder.end(), v) == varOrder.end()) {
39  varOrder.push_back(v);
40  }
41  }
42 
43  // Temp. workaround, should at least one theory-var should be assigned, otherwise no OneCell construct possible
44  // TODO remove as soon, mcsat backend handles this case.
45  if (trail.assignedVariables().size() == 0) {
46  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", " OneCellExplanation called with 0 theory-assignment");
47  FormulasT explainLiterals;
48  for (const auto& trailLiteral : trailLiterals)
49  explainLiterals.emplace_back(trailLiteral.negated());
50  return std::variant<FormulaT, ClauseChain>(FormulaT(carl::FormulaType::OR, std::move(explainLiterals)));
51  }
52  assert(trail.assignedVariables().size() > 0);
53 
54  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Starting an explanation");
55  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", trail);
56  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Number of assigned vars: " << trail.model().size());
57  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Trail literals: " << trailLiterals); //<< " Implied literal: " << impliedLiteral);
58  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Ascending variable order: " << varOrder
59  << " and eliminate down from: " << var);
60 
61  const auto& trailVariables = trail.assignedVariables();
62  std::vector<carl::Variable> fullProjectionVarOrder = varOrder;
63  std::vector<carl::Variable> oneCellCADVarOrder;
64  for (std::size_t i = 0; i < trailVariables.size(); i++)
65  oneCellCADVarOrder.emplace_back(fullProjectionVarOrder[i]);
66 
67  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Ascending OneCellVarOrder: " << oneCellCADVarOrder);
68 
69  std::size_t oneCellMaxLvl = trail.model().size() - 1; // -1, b/c we count first var = poly level 0
70  std::vector<std::vector<TagPoly>> projectionLevels(fullProjectionVarOrder.size()); // init all levels with empty vector
71 
72  std::vector<Poly> polys; // extract from trailLiterals
73  for (const auto& constraint : nlsat::helper::convertToConstraints(trailLiterals))
74  polys.emplace_back(constraint.lhs()); // constraints have the form 'poly < 0' with <, = etc.
75 
76  //Fill projectionLevels
77  for(const auto& poly : polys){
78  appendOnCorrectLevel(poly, InvarianceType::SIGN_INV, projectionLevels, varOrder);
79  }
80 
81  // Project higher level polys down to "normal" level
82  RealAlgebraicPoint<Rational> point = asRANPoint(trail).prefixPoint(oneCellMaxLvl + 1);
83  auto maxLevel = fullProjectionVarOrder.size() - 1;
84  while (projectionLevels[maxLevel].empty() && maxLevel > 0) {
85  projectionLevels.erase(projectionLevels.begin() + maxLevel);
86  maxLevel--;
87  }
88  assert(maxLevel > 0 || !projectionLevels[0].empty());
89 
90  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Polys at levels before full CAD projection:\n"
91  << projectionLevels);
92 
93  RecursiveCAD cad = RecursiveCAD(fullProjectionVarOrder, point);
94  for (std::size_t currentLvl = maxLevel; currentLvl > oneCellMaxLvl; currentLvl--) {
95  auto currentVar = fullProjectionVarOrder[currentLvl];
96  assert(currentLvl >= 1);
97 
98  if(currentLvl == oneCellMaxLvl+1){
99  bool failcheck = optimized_singleLevelFullProjection(currentVar, currentLvl, projectionLevels, cad);
100  if(!failcheck){
101  SMTRAT_LOG_WARN("smtrat.mcsat.nlsat", "OneCell construction failed");
102  return std::nullopt;
103  }
104  } else{
105  singleLevelFullProjection(fullProjectionVarOrder, currentVar, currentLvl, projectionLevels);
106  }
107 
108  projectionLevels.erase(projectionLevels.begin() + currentLvl);
109  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Polys at levels after a CAD projection at level: " << currentLvl << ":\n" << projectionLevels);
110  }
111 
112  if(Setting2::heuristic == 1){
113  // reorder polynomials in ascending order by degree
114  for (int i = (int)projectionLevels.size()-1; i >= 0; i--){
115  for(auto & tpoly : projectionLevels[i]){
116  tpoly.deg = getDegree(tpoly, fullProjectionVarOrder[i]);
117  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Add level of poly: " << tpoly.deg);
118  }
119  std::sort(projectionLevels[i].begin(), projectionLevels[i].end(), [](auto const &t1, auto const &t2) {
120  return t1.deg < t2.deg;
121  });
122  }
123  } else if(Setting2::heuristic == 2){
124  // reorder polynomials in descending order by degree
125  for (int i = (int)projectionLevels.size()-1; i >= 0; i--){
126  for(auto & tpoly : projectionLevels[i]){
127  tpoly.deg = getDegree(tpoly, fullProjectionVarOrder[i]);
128  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Add level of poly: " << tpoly.deg);
129  }
130  std::sort(projectionLevels[i].begin(), projectionLevels[i].end(), [](auto const &t1, auto const &t2) {
131  return t1.deg > t2.deg;
132  });
133  }
134  } else if(Setting2::heuristic != 0){
135  SMTRAT_LOG_WARN("smtrat.mcsat.nlsat", "Invalid heuristic input");
136  }
137  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Polys after possible reordering: \n" << projectionLevels);
138 
140  std::optional<CADCell> cellOpt = cad.pointEnclosingCADCell(projectionLevels);
141  if (!cellOpt) {
142  SMTRAT_LOG_WARN("smtrat.mcsat.nlsat", "OneCell construction failed");
143  return std::nullopt;
144  }
145 
146  auto cell = *cellOpt;
147  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Constructed cell: " << cell);
148 
149  // If we have trail literals: L_M, ... , L_M,
150  // an implied literal L
151  // and cell boundary atoms : A, .., A
152  // We construct the formula '(A & ... & A & L_M & ... & L_M) => L'
153  // in its clausal form 'E := (-A v ... v -A v -L_M v ... v -L_M v L)'
154  // as our explanation.
155  FormulasT explainLiterals;
156 
157  for (const auto& trailLiteral : trailLiterals)
158  explainLiterals.emplace_back(trailLiteral.negated());
159 
160  for (std::size_t i = 0; i < cell.size(); i++) {
161  auto& cellComponent = cell[i];
162  auto cellVariable = oneCellCADVarOrder[i];
163  if (std::holds_alternative<Section>(cellComponent)) {
164  auto section = std::get<Section>(cellComponent).boundFunction;
165  auto param = std::make_pair(section.poly(), section.k());
166  explainLiterals.emplace_back(nlsat::helper::buildEquality(cellVariable, param).negated());
167  } else {
168  auto sectorLowBound = std::get<Sector>(cellComponent).lowBound;
169  if (sectorLowBound) {
170  auto param = std::make_pair(sectorLowBound->boundFunction.poly(), sectorLowBound->boundFunction.k());
171  explainLiterals.emplace_back(nlsat::helper::buildAbove(cellVariable, param).negated());
172  }
173  auto sectorHighBound = std::get<Sector>(cellComponent).highBound;
174  if (sectorHighBound) {
175  auto param = std::make_pair(sectorHighBound->boundFunction.poly(), sectorHighBound->boundFunction.k());
176  explainLiterals.emplace_back(nlsat::helper::buildBelow(cellVariable, param).negated());
177  }
178  }
179  }
180 
181  // if (!impliedLiteral.is_false())
182  // explainLiterals.emplace_back(impliedLiteral);
183 
184  SMTRAT_LOG_DEBUG("smtrat.mcsat.nlsat", "Explain literals: " << explainLiterals);
185 #ifdef SMTRAT_DEVOPTION_Statistics
186  getStatistic().explanationSuccess();
187 #endif
188  return std::variant<FormulaT, ClauseChain>(FormulaT(carl::FormulaType::OR, std::move(explainLiterals)));
189 }
190 
191 // Instantiations
196 
197 } // namespace recursive
198 } // namespace onecellcad
199 } // namespace mcsat
200 } // namespace smtrat
Represent the trail, i.e.
Definition: Bookkeeping.h:19
const auto & assignedVariables() const
Definition: Bookkeeping.h:37
const auto & variables() const
Definition: Bookkeeping.h:49
const auto & model() const
Definition: Bookkeeping.h:34
std::optional< CADCell > pointEnclosingCADCell(const std::vector< std::vector< onecellcad::TagPoly >> &polys)
Construct a single CADCell that contains the given 'point' and is sign-invariant for the given polyno...
Definition: OneCellCAD.h:595
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:67
int var(Lit p)
Definition: SolverTypes.h:64
static bool find(V &ts, const T &t)
Definition: Alg.h:47
FormulaT buildEquality(carl::Variable var, const MVRootParams &mvp)
Construct an atomic formula representing a variable being equal to the given multivariate root.
std::set< ConstraintT > convertToConstraints(std::vector< FormulaT > constraintAtoms)
Transform constraints represented as atomic formualas into the easier to use objects of the Constrain...
FormulaT buildBelow(carl::Variable var, const MVRootParams &mvp)
Construct an atomic formula representing a variable being less than the given multivariate root.
FormulaT buildAbove(carl::Variable var, const MVRootParams &mvp)
Construct an atomic formula representing a variable being greater than the given multivariate root.
void appendOnCorrectLevel(const Poly &poly, InvarianceType tag, std::vector< std::vector< TagPoly >> &polys, std::vector< carl::Variable > variableOrder)
Definition: utils.h:186
std::size_t getDegree(TagPoly p, carl::Variable v)
Definition: utils.h:115
RealAlgebraicPoint< smtrat::Rational > asRANPoint(const mcsat::Bookkeeping &data)
Definition: utils.h:336
void singleLevelFullProjection(std::vector< carl::Variable > &variableOrder, carl::Variable mainVar, size_t currentLevel, std::vector< std::vector< TagPoly >> &projectionLevels)
Definition: utils.h:655
bool optimized_singleLevelFullProjection(carl::Variable mainVar, size_t currentLevel, std::vector< std::vector< TagPoly >> &projectionLevels, OneCellCAD &cad)
Definition: utils.h:602
Class to create the formulas for axioms.
carl::Formula< Poly > FormulaT
Definition: types.h:37
carl::Formulas< Poly > FormulasT
Definition: types.h:39
Construct a single open CAD Cell around a given point that is sign-invariant on a given set of polyno...
#define SMTRAT_LOG_WARN(channel, msg)
Definition: logging.h:33
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35
std::optional< mcsat::Explanation > operator()(const mcsat::Bookkeeping &trail, carl::Variable var, const FormulasT &trailLiterals, bool) const
Definition: Explanation.cpp:19