SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
Preprocessor.cpp
Go to the documentation of this file.
1 #include "Preprocessor.h"
2 
4 
5 #include <algorithm>
6 
7 #include <carl-arith/constraint/Substitution.h>
8 
9 namespace smtrat::cad {
10 
12  ConstraintT cur = c;
13  assert(mCurrent.find(cur) != mCurrent.end());
14  Model m;
15  std::vector<ConstraintT> toAdd;
16  for (std::size_t tid = 0; tid < mTrailID; ++tid) {
17  auto it = mAssignments.find(mTrail[tid].first);
18  if (it != mAssignments.end()) {
19  m.emplace(it->second, mModel.at(it->second));
20  auto tmp = carl::substitute(cur, m);
21  if (tmp != cur) {
22  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Simplifying " << cur << " -> " << tmp << " with " << *it);
23  if (tmp.is_consistent() != 1) {
24  toAdd.emplace_back(tmp);
25  }
26  Origins o({cur, it->first});
27  std::sort(o.begin(), o.end());
28  mTrail.emplace_back(tmp, o);
29  mCurrent.erase(cur);
30  cur = tmp;
31  };
32  }
33  }
34  mCurrent.insert(toAdd.begin(), toAdd.end());
35 }
36 
38  assert(mTrail[mTrailID].first.is_consistent() == 0);
39  mConflict = std::set<FormulaT>();
40  std::transform(mTrail[mTrailID].second.begin(), mTrail[mTrailID].second.end(), std::inserter(*mConflict, mConflict->begin()), [](const ConstraintT& c) { return FormulaT(c); });
42 }
43 
44 carl::Variable Preprocessor::main_variable_of(const ConstraintT& c) const {
45  carl::carlVariables vars;
46  variables(c, vars);
47  for (auto v: mVars) {
48  if (vars.has(v)) return v;
49  }
50  return carl::Variable::NO_VARIABLE;
51 }
52 
54  carl::Variable v;
55  Rational r;
56  Poly p;
57  bool foundAssignment = false;
58  auto assignment = carl::get_assignment(cur);
59  if (assignment) {
60  auto mit = mModel.find(assignment->first);
61  if (mit != mModel.end()) {
62  assert(mModel.at(assignment->first).isRational() && mModel.at(assignment->first).asRational() == assignment->second);
63  return false;
64  }
65  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Newly extracted " << v << " = " << r);
66  mModel.emplace(assignment->first, assignment->second);
67  mAssignments.emplace(cur, assignment->first);
68  foundAssignment = true;
69  } else {
70  auto substitution = carl::get_substitution(cur);
71  if (substitution) {
72  auto mit = mModel.find(substitution->first);
73  if (mit != mModel.end()) {
74  return false;
75  }
76  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Newly extracted " << substitution->first << " = " << substitution->second);
77  mModel.emplace(substitution->first, carl::createSubstitution<Rational,Poly,ModelPolynomialSubstitution>(substitution->second));
78  mAssignments.emplace(cur, substitution->first);
79  foundAssignment = true;
80  }
81  }
82  if (foundAssignment) {
83  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Simplifying with new assignment");
84  std::vector<ConstraintT> toAdd;
85  for (auto it = mCurrent.begin(); it != mCurrent.end();) {
86  if (*it == cur) {
87  it = mCurrent.erase(it);
88  continue;
89  }
90  auto tmp = carl::substitute(*it, mModel);
91  if (tmp != *it) {
92  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Simplifying " << *it << " -> " << tmp);
93  if (mCurrent.find(tmp) == mCurrent.end()) {
94  if (tmp.is_consistent() != 1) {
95  toAdd.emplace_back(tmp);
96  }
97  Origins o({cur, *it});
98  std::sort(o.begin(), o.end());
99  mTrail.emplace_back(tmp, o);
100  }
101  it = mCurrent.erase(it);
102  } else ++it;
103  }
104  mCurrent.insert(toAdd.begin(), toAdd.end());
105  return true;
106  }
107  return false;
108 }
109 
111  if (cur.relation() != carl::Relation::EQ) return;
112  carl::Variable mainvar = main_variable_of(cur);
113  if (mainvar == carl::Variable::NO_VARIABLE) return;
114  auto p = carl::to_univariate_polynomial(cur.lhs(), mainvar);
115  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Identified main variable of " << p << ": " << mainvar);
116  std::vector<ConstraintT> toAdd;
117  for (const auto& c: mCurrent) {
118  if (c.relation() != carl::Relation::EQ) continue;
119  if (mainvar == main_variable_of(c)) {
120  auto q = carl::to_univariate_polynomial(c.lhs(), mainvar);
121  auto r = projection::resultant(mainvar, p, q);
122  if (!r.is_number()) {
123  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Resultant of " << p << " and " << q << " is " << r);
124  toAdd.emplace_back(Poly(r), carl::Relation::EQ);
125  Origins o({cur, c});
126  std::sort(o.begin(), o.end());
127  mTrail.emplace_back(toAdd.back(), o);
128  }
129  }
130  }
131  mCurrent.insert(toAdd.begin(), toAdd.end());
132 }
133 
135  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Adding " << c << " to" << std::endl << *this);
136  mCurrent.emplace(c);
137  mTrail.emplace_back(c, Origins());
138  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Reapplying assignments to " << c << " in" << std::endl << *this);
140 }
142  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Removing " << c << " from" << std::endl << *this);
143  std::vector<ConstraintT> removals({c});
144  for (const auto& t: mTrail) {
145  for (const auto& r: removals) {
146  auto it = std::lower_bound(t.second.begin(), t.second.end(), r);
147  if (it != t.second.end() && *it == r) {
148  removals.emplace_back(t.first);
149  break;
150  }
151  }
152  }
153  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Going to remove " << removals);
154  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Model is now " << mModel);
155  for (const auto& r: removals) {
156  auto ait = mAssignments.find(r);
157  if (ait != mAssignments.end()) {
158  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Purging " << ait->second << " from model due to " << r);
159  mModel.erase(ait->second);
160  mAssignments.erase(ait);
161  }
162  }
163  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Model is now " << mModel);
164  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Cleaning " << mCurrent);
165  for (std::size_t curID = mTrail.size(); curID > 0; --curID) {
166  const auto& cur = mTrail[curID - 1];
167  if (std::find(removals.begin(), removals.end(), cur.first) == removals.end()) {
168  continue;
169  }
170  auto it = mCurrent.find(cur.first);
171  if (it != mCurrent.end()) {
172  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Replace " << cur.first << " by " << cur.second);
173  mCurrent.erase(it);
174  mCurrent.insert(cur.second.begin(), cur.second.end());
175  } else if (cur.first.is_consistent() == 1) {
176  for (const auto& o: cur.second) {
177  auto it = std::find(removals.begin(), removals.end(), o);
178  if (it != removals.end()) {
179  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Restoring " << cur.first << " by " << cur.second);
180  mCurrent.insert(cur.second.begin(), cur.second.end());
181  break;
182  }
183  }
184  }
185  }
186  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "-> " << mCurrent);
187 
188  auto it = std::remove_if(mTrail.begin(), mTrail.end(),
189  [&removals](const auto& val){
190  return std::find(removals.begin(), removals.end(), val.first) != removals.end();
191  }
192  );
193  mTrail.erase(it, mTrail.end());
194  mTrailID = 0;
195  mModel.clear();
196  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "State after removal" << std::endl << *this);
197 }
198 
199 void Preprocessor::postprocessConflict(std::set<FormulaT>& mis) const {
200  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Postprocessing " << mis);
201  for (std::size_t curID = mTrail.size(); curID > 0; --curID) {
202  const auto& cur = mTrail[curID - 1];
203  if (cur.second.size() == 0) {
204  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Keep " << cur.first << " as original constraint.");
205  // This was an original constraint
206  continue;
207  }
208  auto it = mis.find(FormulaT(cur.first));
209  if (it != mis.end()) {
210  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Replace " << cur.first << " by " << cur.second);
211  mis.erase(it);
212  std::transform(cur.second.begin(), cur.second.end(), std::inserter(mis, mis.begin()), [](const ConstraintT& c) { return FormulaT(c); });
213  }
214  }
215  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "-> " << mis);
216 }
217 
219  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Preprocessing from" << std::endl << *this);
220  mConflict = std::nullopt;
221  while (mTrailID < mTrail.size()) {
222  auto cur = mTrail[mTrailID].first;
223  if (cur.is_consistent() == 0) {
224  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Found conflict in " << mTrail[mTrailID]);
225  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "After preprocessing:" << std::endl << *this);
227  return false;
228  }
229  auto it = mAssignments.find(cur);
230  if (it != mAssignments.end()) {
231  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Redo variable elimination for " << cur);
233  ++mTrailID;
234  continue;
235  }
236  if (mCurrent.find(cur) == mCurrent.end()) {
237  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Skip " << cur << " @ " << mTrailID << " as it has already been eliminated.");
238  ++mTrailID;
239  continue;
240  }
241  if (cur.relation() != carl::Relation::EQ) {
242  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Skip " << cur << " @ " << mTrailID << " as it is not an equality.");
243  ++mTrailID;
244  continue;
245  }
246  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Continuing with " << mTrail[mTrailID]);
247  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Current state: " << mCurrent);
248  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Variable elimination with " << cur);
249  if (settings_cadpp().disable_variable_elimination) {
250  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Variable elimination is disabled");
251  } else if (try_variable_elimination(cur)) {
252  ++mTrailID;
253  continue;
254  }
255 
256  if (settings_cadpp().disable_resultants) {
257  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "Resultant computation is disabled");
258  } else {
259  compute_resultants(cur);
260  }
261  ++mTrailID;
262 
263  }
264  SMTRAT_LOG_DEBUG("smtrat.cad.pp", "After preprocessing:" << std::endl << *this);
265  return true;
266 }
267 
268 } // namespace smtrat::cad
void addConstraint(const ConstraintT &c)
void apply_assignments(const ConstraintT &c)
carl::Variable main_variable_of(const ConstraintT &c) const
std::optional< std::set< FormulaT > > mConflict
A possibly found conflict.
Definition: Preprocessor.h:63
void removeConstraint(const ConstraintT &c)
void compute_resultants(const ConstraintT &cur)
std::size_t mTrailID
Next element to be processed.
Definition: Preprocessor.h:59
std::map< ConstraintT, carl::Variable > mAssignments
Origins for the assignments.
Definition: Preprocessor.h:53
const std::vector< carl::Variable > & mVars
Variable ordering.
Definition: Preprocessor.h:51
Trail mTrail
The trail.
Definition: Preprocessor.h:57
Model mModel
The model used for variable elimination.
Definition: Preprocessor.h:55
std::vector< ConstraintT > Origins
Definition: Preprocessor.h:47
std::set< ConstraintT > mCurrent
Current set of equalities.
Definition: Preprocessor.h:61
bool try_variable_elimination(const ConstraintT &cur)
void postprocessConflict(std::set< FormulaT > &mis) const
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:67
static bool find(V &ts, const T &t)
Definition: Alg.h:47
Poly resultant(carl::Variable variable, const Poly &p, const Poly &q)
Computes the resultant of two polynomials.
Definition: utils.h:48
const auto & settings_cadpp()
bool substitute(const FormulaT &constr, const carl::Variable var, const carl::vs::Term< Poly > &term, FormulaT &result)
Definition: VSHelper.h:138
std::vector< carl::Variable > vars(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Definition: QEQuery.h:43
carl::Formula< Poly > FormulaT
Definition: types.h:37
carl::Model< Rational, Poly > Model
Definition: model.h:13
carl::MultivariatePolynomial< Rational > Poly
Definition: types.h:25
carl::Constraint< Poly > ConstraintT
Definition: types.h:29
mpq_class Rational
Definition: types.h:19
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35