SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
FMplexQE.cpp
Go to the documentation of this file.
1 #include <iostream>
2 #include <fstream>
3 #include "../util/quantifier_splitting.h"
4 
5 #include "FMplexQE.h"
6 
7 /*
8  TODO: the partitioning into independent blocks (like in build_initial_system) can actually
9  be applied in each node! The stack facilitates this and allows to split blocks into
10  sub-blocks later without changing the general structure of the algorithm.
11  -> an open question here is whether the overhead for searching indep. blocks is worth it.
12  -> also: a more complex scheme where blocks are reunited requires a major restructuring.
13 */
14 
15 namespace smtrat::qe::fmplex {
16 
18  SMTRAT_LOG_DEBUG("smtrat.qe","input: " << m_query << ", " << m_formula);
19 
21 
22  while (!m_nodes.empty()) {
23  SMTRAT_LOG_DEBUG("smtrat.qe","Next node:" << m_nodes.back());
24 
25  switch (m_nodes.back().type) {
27  return FormulaT(carl::FormulaType::FALSE);
29  if (m_nodes.back().is_suitable_for_splitting()) {
30  SMTRAT_STATISTICS_CALL(FMplexQEStatistics::get_instance().split_tried());
31  auto split = split_into_independent_nodes(m_nodes.back());
32  m_nodes.pop_back();
33  m_nodes.insert(m_nodes.end(), split.begin(), split.end());
35  if (split.size() > 1) FMplexQEStatistics::get_instance().split_done();
36  )
37  } else {
38  m_nodes.back().choose_elimination();
39  }
40  break;
41  }
42  case Node::Type::NBS:
43  m_nodes.back() = unbounded_elimination(m_nodes.back());
44  break;
45  case Node::Type::LBS:[[fallthrough]];
46  case Node::Type::UBS:
47  if (m_nodes.back().is_finished()) m_nodes.pop_back();
48  else m_nodes.push_back(bounded_elimination(m_nodes.back()));
49  break;
50  case Node::Type::FM:
51  if (!fm_elimination(m_nodes.back())) return FormulaT(carl::FormulaType::FALSE);
52  m_nodes.pop_back();
53  break;
54  case Node::Type::LEAF:
55  m_nodes.pop_back();
56  break;
57  }
58  }
59 
60  SMTRAT_LOG_DEBUG("smtrat.qe","after loop");
61  if (m_found_rows.empty() && m_found_conjuncts.empty()) return FormulaT(carl::FormulaType::TRUE);
62  FormulasT conjuncts;
63  conjuncts.reserve(m_found_rows.size() + m_found_conjuncts.size());
64  for (const auto& r : m_found_rows) conjuncts.push_back(constraint_from_row(r));
65  for (const auto& c : m_found_conjuncts) conjuncts.push_back(c); // TODO: deduplication between the two sets?
66  return FormulaT(carl::FormulaType::AND, conjuncts);
67 }
68 
69 
70 std::vector<carl::Variable> FMplexQE::gather_elimination_variables() const {
71  std::vector<carl::Variable> elimination_vars;
72  for (const auto& [type, vars] : m_query) {
73  assert(type == QuantifierType::EXISTS); // Only support existential for now
74  elimination_vars.insert(elimination_vars.end(), vars.begin(), vars.end());
75  }
76  return elimination_vars;
77 }
78 
79 
81  assert(!row.empty());
82  assert(row.back().col_index <= delta_column());
83  Poly lhs;
84  auto it = row.begin();
85  for (; it != row.end() && it->col_index < constant_column(); ++it) {
86  lhs += it->value*Poly(m_var_idx.var(it->col_index));
87  }
88  if (it != row.end() && it->col_index == constant_column()) {
89  lhs += it->value;
90  ++it;
91  }
92  // This method is only applied to pos.lin. combinations, so the delta coeff will be >=0
93  if (it != row.end() && it->col_index == delta_column()) {
94  return FormulaT(lhs, carl::Relation::LESS);
95  }
96  return FormulaT(lhs, carl::Relation::LEQ);
97 }
98 
99 
101  // reserve enough space for the matrix
102  Matrix m(constraints.size(), m_var_idx.size() + constraints.size() + 2); // +2 : delta & rhs.
103  std::size_t non_zeros = 2*constraints.size(); // one origin & at most one delta for each row
104  for (const auto& f : constraints) non_zeros += f.constraint().lhs().nr_terms();
105  m.reserve(non_zeros);
106 
107  // transform each constraint into a row
108  for (RowIndex r = 0; r < constraints.size(); ++r) {
109  carl::Relation rel = constraints[r].constraint().relation();
110 
111  // smtrat automatically converts constraints to < or <=
112  assert(rel != carl::Relation::GREATER && rel != carl::Relation::GEQ);
113  assert(rel != carl::Relation::NEQ); // we don't support NEQ yet
114 
115  Poly lhs = constraints[r].constraint().lhs();
116  Rational constant_part = lhs.constant_part();
117  lhs -= constant_part;
118 
119  Row entries; // TODO: make it so that the contents of the row are actually already in the matrix data
120  for (const auto& term : lhs) {
121  entries.emplace_back(m_var_idx.index(term.single_variable()), term.coeff());
122  }
123  // the order in the polynomial may be different from the order in the var index
124  std::sort(entries.begin(), entries.end(),
125  [](const auto& lhs, const auto& rhs){ return lhs.col_index < rhs.col_index; }
126  );
127 
128  // constant part, delta, and origin
129  if (!carl::is_zero(constant_part)) entries.emplace_back(constant_column(), constant_part);
130  if (rel == carl::Relation::LESS) entries.emplace_back(delta_column(), Rational(1));
131  entries.emplace_back(origin_column(r), Rational(1));
132 
133  m.append_row(entries.begin(), entries.end());
134  }
135  return m;
136 }
137 
138 
139 std::vector<Node> FMplexQE::split_into_independent_nodes(const Node& n) const {
140  const Matrix& m = n.matrix;
141  std::vector<bool> col_used(n.cols_to_elim.size(), false);
142  std::vector<bool> row_used(m.n_rows(), false);
143  std::size_t n_unused_rows = m.n_rows();
144 
145  std::vector<std::size_t> pending;
146  std::vector<Node> result;
147 
148  for (std::size_t i = 0; i < n.cols_to_elim.size();) {
149  pending.push_back(i);
150  result.push_back(Node(Matrix(n_unused_rows, m.n_cols()), {}));
151  ++i;
152  while (!pending.empty()) {
153  std::size_t v = pending.back();
154  pending.pop_back();
155  if (col_used[v]) continue;
156  col_used[v] = true;
157  ColIndex actual_col = n.cols_to_elim[v];
158  result.back().cols_to_elim.push_back(actual_col);
159  auto col_end = m.col_end(actual_col);
160  for (auto it = m.col_begin(actual_col); it != col_end; ++it) {
161  if (row_used[it.row()]) continue;
162  for (const auto& e : m.row_entries(it.row())) {
163  if (e.col_index >= m_first_parameter_col) break;
164  if (e.col_index == actual_col) continue;
165  for (std::size_t j = 0; ; ++j) {
166  assert(j < n.cols_to_elim.size());
167  if (n.cols_to_elim[j] == e.col_index) {
168  pending.push_back(j);
169  break;
170  }
171  }
172  }
173  row_used[it.row()] = true;
174  --n_unused_rows;
175  if (n.ignored.contains(it.row())) {
176  result.back().ignored.insert(result.back().matrix.n_rows());
177  }
178  result.back().matrix.append_row(m.row_begin(it.row()), m.row_end(it.row()));
179  }
180  }
181  while (i < n.cols_to_elim.size() && col_used[i]) ++i;
182  }
183  for (Node& n : result) n.choose_elimination();
184  return result;
185  }
186 
187 
189  // gather quantified variables
190  std::vector<carl::Variable> elim_vars = gather_elimination_variables();
191  SMTRAT_LOG_DEBUG("smtrat.qe","elim vars:" << elim_vars);
192  SMTRAT_STATISTICS_CALL(FMplexQEStatistics::get_instance().vars(elim_vars.size()));
193 
194  // gather input constraints
195  FormulasT constraints;
196  if (m_formula.type() == carl::FormulaType::CONSTRAINT) constraints.push_back(m_formula);
197  else constraints = m_formula.subformulas();
198  SMTRAT_STATISTICS_CALL(FMplexQEStatistics::get_instance().input(constraints.size()));
199 
200  // eliminate variables using equalities
201  qe::util::EquationSubstitution es(constraints, elim_vars);
202  if (!es.apply()) {
203  SMTRAT_STATISTICS_CALL(FMplexQEStatistics::get_instance().elim_eq(elim_vars.size()));
204  SMTRAT_STATISTICS_CALL(FMplexQEStatistics::get_instance().eq_conflict());
205  m_nodes.push_back(Node::conflict());
206  return;
207  }
208  constraints = es.remaining_constraints();
209  elim_vars = es.remaining_variables();
210  SMTRAT_LOG_DEBUG("smtrat.qe","Constraints after es: " << constraints);
211  SMTRAT_STATISTICS_CALL(FMplexQEStatistics::get_instance().elim_eq(elim_vars.size()));
212 
213  // filter finished constraints from remaining constraints
214  FormulasT filtered;
215  for (const auto& c : constraints) {
216  auto vars = carl::variables(c).as_set();
217  if (std::any_of(elim_vars.begin(),
218  elim_vars.end(),
219  [&vars](const auto v){ return vars.contains(v); })
220  ) {
221  filtered.push_back(c);
222  } else m_found_conjuncts.insert(c);
223  }
224  constraints = filtered;
225  SMTRAT_LOG_DEBUG("smtrat.qe","Constraints after filtering: " << constraints);
226 
227  if (elim_vars.empty()) {
228  m_nodes.push_back(Node::leaf());
229  return;
230  }
231 
232 
233  // map from variables to indices
234  m_var_idx = qe::util::VariableIndex(elim_vars);
235  m_var_idx.gather_variables(constraints);
236  m_first_parameter_col = elim_vars.size();
237  SMTRAT_LOG_DEBUG("smtrat.qe","after gather variables");
238 
239  std::vector<Matrix::ColIndex> elim_var_indices;
240  for (ColIndex j = 0; j < m_first_parameter_col; ++j) elim_var_indices.push_back(j);
241  m_nodes.push_back(Node(build_initial_matrix(constraints), elim_var_indices));
242 
243  /*auto subqueries = qe::util::split_quantifiers(constraints, elim_vars);
244 
245  for (const auto& q : subqueries) {
246  // list of columns to eliminate. Initially, this are the first k columns for k = #elim vars
247  std::vector<Matrix::ColIndex> elim_var_indices;
248  for (const auto v : q.elimination_vars) elim_var_indices.push_back(m_var_idx.index(v));
249  SMTRAT_LOG_DEBUG("smtrat.qe","before return");
250  m_nodes.push_back(Node(build_initial_matrix(q.constraints), elim_var_indices));
251  }*/
252 }
253 
254 
256  auto new_cols = parent.cols_to_elim;
257  new_cols.erase(std::find(new_cols.begin(), new_cols.end(), parent.chosen_col));
258 
259  std::size_t n_deleted_rows = parent.eliminators.size();
260  Matrix new_matr(parent.matrix.n_rows() - n_deleted_rows, parent.matrix.n_cols());
261 
262  new_matr.reserve(parent.matrix.non_zeros_total() - 2*n_deleted_rows); // upper bound
263 
264  auto col_it = parent.eliminators.begin();
265  auto col_end = parent.eliminators.end();
266 
267  std::set<RowIndex> ignore;
268  auto ignore_it = parent.ignored.begin();
269 
270  for (RowIndex r = 0; r < parent.matrix.n_rows(); ++r) {
271  if (col_it != col_end && r == *col_it) ++col_it;
272  else {
273  new_matr.append_row(parent.matrix.row_begin(r), parent.matrix.row_end(r));
274  auto it = std::find(ignore_it, parent.ignored.end(), r);
275  if (it != parent.ignored.end()) {
276  ignore.emplace_hint(ignore.end(), new_matr.n_rows());
277  ignore_it = it;
278  ++ignore_it;
279  }
280  }
281  }
282 
283  parent.eliminators.clear();
284 
285  SMTRAT_STATISTICS_CALL(FMplexQEStatistics::get_instance().node(new_matr.n_rows()));
286  return Node(new_matr, new_cols, ignore);
287 }
288 
289 
291  assert(row.front().col_index <= delta_column());
292  // don't need to check for it == end because the constraint cannot be trivially true here
293  for (auto it = row.rbegin(); it->col_index > delta_column(); ++it) {
294  if (it->value < 0) return false;
295  }
296  return true;
297 }
298 
299 
301  assert(parent.type == Node::Type::LBS || parent.type == Node::Type::UBS);
302  assert(!parent.eliminators.empty());
303 
304  // remove chosen variable from elimination variables
305  auto new_cols = parent.cols_to_elim;
306  new_cols.erase(std::find(new_cols.begin(), new_cols.end(), parent.chosen_col));
307 
308  // set up new matrix
309  Matrix new_matr(parent.matrix.n_rows() - 1, parent.matrix.n_cols());
310  new_matr.reserve(parent.matrix.non_zeros_total()); // likely an overapproximation
311 
312  // eliminate using eliminator
313  RowIndex eliminator = parent.eliminators.back();
314  Rational elim_coeff = parent.matrix.coeff(eliminator, parent.chosen_col);
315  Rational elim_sgn = (parent.type == Node::Type::LBS ? Rational(1) : Rational(-1));
316  parent.eliminators.pop_back();
317 
318  auto col_it = parent.matrix.col_begin(parent.chosen_col);
319  auto col_end = parent.matrix.col_end(parent.chosen_col);
320 
321  std::set<RowIndex> ignore;
322  auto ignore_it = parent.ignored.begin();
323 
324  bool local_conflict = false; // TODO: make more elegant
325  bool inserted = false;
326 
327  auto process_row = [&](RowIndex r) {
328  inserted = false;
329  Rational scale_elim = elim_sgn*col_it->value;
330  Rational scale_r = carl::abs(elim_coeff);
331  auto combined_row = parent.matrix.combine(eliminator, scale_elim, r, scale_r);
332  qe::util::gcd_normalize(combined_row);
333 
334  if (combined_row.front().col_index < m_first_parameter_col) {
335  // row still contains quantified variables
336  inserted = true;
337  new_matr.append_row(combined_row.begin(), combined_row.end());
338  return true;
339  }
340 
341  // all quantified variables are eliminated in this row
342  // add to overall result or analyze trivial constraint
343  if (is_trivial(combined_row)) {
344  if (is_conflict(combined_row)) {
345  if (is_positive_combination(combined_row)) return false;
346  else local_conflict = true;
347  }
348  } else if (is_positive_combination(combined_row)) {
349  collect_constraint(combined_row);
350  }
351 
352  return true;
353  };
354 
355  for (RowIndex r = 0; r < eliminator; ++r) {
356  if (r == col_it.row()) {
357  if (!process_row(r)) return Node::conflict();
358  ++col_it;
359  } else {
360  inserted = true;
361  new_matr.append_row(parent.matrix.row_begin(r), parent.matrix.row_end(r));
362  }
363  if (ignore_it != parent.ignored.end() && r == *ignore_it) {
364  if (inserted) ignore.insert(new_matr.n_rows() - 1);
365  ++ignore_it;
366  }
367  }
368  ++col_it;
369  for (RowIndex r = eliminator + 1; r < parent.matrix.n_rows(); ++r) {
370  if ((col_it != col_end) && (r == col_it.row())) {
371  if (!process_row(r)) return Node::conflict();
372  ++col_it;
373  } else {
374  inserted = true;
375  new_matr.append_row(parent.matrix.row_begin(r), parent.matrix.row_end(r));
376  }
377  if (ignore_it != parent.ignored.end() && r == *ignore_it) {
378  if (inserted) ignore.insert(new_matr.n_rows() - 1);
379  ++ignore_it;
380  }
381  }
382 
383  parent.ignored.insert(eliminator);
384 
385  SMTRAT_STATISTICS_CALL(FMplexQEStatistics::get_instance().node(new_matr.n_rows()));
386  if (local_conflict) return Node::leaf();
387  return Node(new_matr, new_cols, ignore);
388 }
389 
390 
392  std::vector<RowIndex> lbs, ubs;
393  // we can ignore non-bounds since they would have been added to the result at this point
394  auto col_it = parent.matrix.col_begin(parent.chosen_col);
395  auto col_end = parent.matrix.col_end(parent.chosen_col);
396  for (; col_it != col_end; ++col_it) {
397  if (col_it->value < 0) lbs.push_back(col_it.row());
398  else ubs.push_back(col_it.row());
399  }
400 
401  SMTRAT_STATISTICS_CALL(FMplexQEStatistics::get_instance().node(lbs.size() * ubs.size()));
402 
403  for (const RowIndex l : lbs) {
404  Rational coeff_l = (-1)*parent.matrix.coeff(l, parent.chosen_col);
405  for (const RowIndex u : ubs) {
406  Rational coeff_u = parent.matrix.coeff(u, parent.chosen_col);
407  auto combined_row = parent.matrix.combine(l, coeff_u, u, coeff_l);
408  qe::util::gcd_normalize(combined_row);
409  if (is_trivial(combined_row)) {
410  if (is_conflict(combined_row) && is_positive_combination(combined_row)) return false;
411  } else if (is_positive_combination(combined_row)) {
412  collect_constraint(combined_row);
413  }
414  }
415  }
416  return true;
417 }
418 
419 
420 void FMplexQE::write_matrix_to_ine(const FMplexQE::Matrix& m, const std::string& filename) const {
421  std::ofstream file;
422  file.open(filename); // "/home/vp/Code/smtrat/build/out.ine"
423  file << "H-representation\n";
424  file << "begin\n";
425  file << m.n_rows() << " " << m_var_idx.size() + 1 << " real\n";
426  for (RowIndex i = 0; i < m.n_rows(); ++i) {
427  Rational lcm = 1;
428  Rational constant = 0;
429  for (const auto& e : m.row_entries(i)) {
430  lcm = carl::lcm(lcm.get_num(), e.value.get_den());
431  if (e.col_index == constant_column()) constant = e.value;
432  }
433  file << " " << constant*(-lcm); // first column contains the constants
434  auto it = m.row_begin(i);
435  auto row_end = m.row_end(i);
436  for (ColIndex j = 0; j < m_var_idx.size(); ++j) {
437  if ((it != row_end) && (it->col_index == j)) {
438  file << " " << (it->value)*(-lcm); // - because cdd uses >= instead of <=
439  ++it;
440  } else {
441  file << " 0";
442  }
443  }
444  file << "\n";
445  }
446  file << "end\n";
447  file << "project " << m_first_parameter_col;
448  for (std::size_t i = 1; i <= m_first_parameter_col; ++i) {
449  file << " " << i;
450  }
451  file << "\n";
452  file.close();
453 }
454 
455 void FMplexQE::write_matrix_to_redlog(const Matrix& m, const std::string& filename) const {
456  std::ofstream file;
457  file.open(filename); //"/home/vp/Code/smtrat/build/out.red"
458  file << "load_package \"redlog\"$\n";
459  file << "rlset r$\n";
460  file << "rlqe(ex({x1";
461  for (std::size_t i = 2; i <= m_first_parameter_col; ++i) {
462  file << ", x" << i;
463  }
464  file << "}, ";
465 
466  auto write_row = [&](RowIndex i){
467  bool first = true;
468  for (const auto& e : m.row_entries(i)) {
469  if (e.col_index > constant_column()) break;
470  file << " ";
471  if (first) first = false;
472  else if (e.value > 0) file << "+ ";
473  file << e.value;
474  if (e.col_index < constant_column()) file << "x" << (e.col_index + 1);
475  }
476  file << " <= 0";
477  };
478 
479  write_row(0);
480  for (RowIndex i = 1; i < m.n_rows(); ++i) {
481  file << " and ";
482  write_row(i);
483  }
484 
485  file << "));\n";
486  file << "bye;";
487  file.close();
488 }
489 
490 } // namespace smtrat::qe::fmplex
qe::util::Matrix Matrix
Definition: FMplexQE.h:16
Node bounded_elimination(Node &parent)
Eliminates the chosen column in parent using the next eliminator in parent.
Definition: FMplexQE.cpp:300
std::vector< Node > m_nodes
Definition: FMplexQE.h:40
FormulaT eliminate_quantifiers()
Definition: FMplexQE.cpp:17
void write_matrix_to_redlog(const Matrix &m, const std::string &filename) const
Definition: FMplexQE.cpp:455
ColIndex constant_column() const
Definition: FMplexQE.h:63
bool is_trivial(const Row &row) const
Definition: FMplexQE.h:67
bool is_positive_combination(const Row &row)
Definition: FMplexQE.cpp:290
bool fm_elimination(Node &parent)
Eliminates the chosen column in parent using Fourier-Motzkin, but discards rows with 0 coeff.
Definition: FMplexQE.cpp:391
void collect_constraint(const Row &row)
truncates the given row to not contain any "origin" information and inserts the result into the set o...
Definition: FMplexQE.h:86
std::vector< Node > split_into_independent_nodes(const Node &n) const
Splits the given node into multiple nodes that are independent in the following sense:
Definition: FMplexQE.cpp:139
Matrix::RowIndex RowIndex
Definition: FMplexQE.h:17
Matrix::ColIndex ColIndex
Definition: FMplexQE.h:18
Node unbounded_elimination(Node &parent)
Eliminates the chosen column in parent by dropping all rows with non-zero entry in that column.
Definition: FMplexQE.cpp:255
ColIndex delta_column() const
Definition: FMplexQE.h:64
FormulaSetT m_found_conjuncts
Definition: FMplexQE.h:41
void write_matrix_to_ine(const Matrix &m, const std::string &filename) const
writes the given qe problem as a .ine file as used in CDD lib.
Definition: FMplexQE.cpp:420
qe::util::VariableIndex m_var_idx
Definition: FMplexQE.h:42
Matrix build_initial_matrix(const FormulasT &constraints)
Constructs a matrix from the given constraints.
Definition: FMplexQE.cpp:100
ColIndex origin_column(RowIndex row) const
Definition: FMplexQE.h:65
FormulaT constraint_from_row(const Row &row) const
Definition: FMplexQE.cpp:80
std::vector< Matrix::RowEntry > Row
Definition: FMplexQE.h:19
std::set< Row, cmp_row > m_found_rows
Definition: FMplexQE.h:44
void build_initial_systems()
Constructs the starting nodes from m_query and m_formula as follows:
Definition: FMplexQE.cpp:188
bool is_conflict(const Row &row) const
Definition: FMplexQE.h:72
std::vector< carl::Variable > gather_elimination_variables() const
Definition: FMplexQE.cpp:70
std::vector< carl::Variable > remaining_variables()
void reserve(std::size_t n)
Definition: Matrix.h:65
col_iterator col_end(ColIndex c) const
Definition: Matrix.h:193
std::vector< RowEntry > combine(const RowIndex row_idx_1, const Rational &scale_1, const RowIndex row_idx_2, const Rational &scale_2) const
Computes scale_1*A_(i,-) + scale_2*A_(j,-) where i=row_idx_1, j=row_idx_2.
Definition: Matrix.h:104
std::size_t n_rows() const
Definition: Matrix.h:67
RowIndex append_row(const It &begin, const It &end)
Appends the row contained in the range between begin and end to the matrix.
Definition: Matrix.h:89
std::size_t n_cols() const
Definition: Matrix.h:68
std::size_t non_zeros_total() const
Definition: Matrix.h:72
row_iterator row_end(RowIndex r) const
Definition: Matrix.h:159
col_iterator col_begin(ColIndex c) const
Definition: Matrix.h:192
row_view row_entries(const RowIndex ri) const
Definition: Matrix.h:171
row_iterator row_begin(RowIndex r) const
Definition: Matrix.h:158
Rational coeff(const RowIndex i, const ColIndex j) const
Definition: Matrix.h:74
void sort(T *array, int size, LessThan lt)
Definition: Sort.h:67
static bool find(V &ts, const T &t)
Definition: Alg.h:47
Numeric lcm(const Numeric &_valueA, const Numeric &_valueB)
Calculates the least common multiple of the two arguments.
Definition: Numeric.cpp:302
Numeric abs(const Numeric &_value)
Calculates the absolute value of the given Numeric.
Definition: Numeric.cpp:276
void gcd_normalize(std::vector< Matrix::RowEntry > &row)
Definition: Matrix.h:215
QuantifierType type(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Definition: QEQuery.h:39
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::MultivariatePolynomial< Rational > Poly
Definition: types.h:25
carl::Formulas< Poly > FormulasT
Definition: types.h:39
mpq_class Rational
Definition: types.h:19
#define SMTRAT_LOG_DEBUG(channel, msg)
Definition: logging.h:35
#define SMTRAT_STATISTICS_CALL(function)
Definition: Statistics.h:23
static Node conflict()
Definition: Node.h:124
void choose_elimination()
Definition: Node.h:22
static Node leaf()
Definition: Node.h:125
ColIndex chosen_col
Definition: Node.h:17
std::vector< ColIndex > cols_to_elim
Definition: Node.h:18
std::set< RowIndex > ignored
Definition: Node.h:20
std::vector< RowIndex > eliminators
Definition: Node.h:19
std::size_t index(carl::Variable v) const
Definition: VariableIndex.h:28
carl::Variable var(std::size_t i) const
Definition: VariableIndex.h:33
void gather_variables(const FormulasT &fs)
Definition: VariableIndex.h:22