3 #include "../util/quantifier_splitting.h"
27 return FormulaT(carl::FormulaType::FALSE);
29 if (
m_nodes.back().is_suitable_for_splitting()) {
35 if (split.size() > 1) FMplexQEStatistics::get_instance().split_done();
38 m_nodes.back().choose_elimination();
71 std::vector<carl::Variable> elimination_vars;
74 elimination_vars.insert(elimination_vars.end(),
vars.begin(),
vars.end());
76 return elimination_vars;
84 auto it = row.begin();
93 if (it != row.end() && it->col_index ==
delta_column()) {
94 return FormulaT(lhs, carl::Relation::LESS);
96 return FormulaT(lhs, carl::Relation::LEQ);
103 std::size_t non_zeros = 2*constraints.size();
104 for (
const auto& f : constraints) non_zeros += f.constraint().lhs().nr_terms();
108 for (
RowIndex r = 0; r < constraints.size(); ++r) {
109 carl::Relation rel = constraints[r].constraint().relation();
112 assert(rel != carl::Relation::GREATER && rel != carl::Relation::GEQ);
113 assert(rel != carl::Relation::NEQ);
115 Poly lhs = constraints[r].constraint().lhs();
116 Rational constant_part = lhs.constant_part();
117 lhs -= constant_part;
120 for (
const auto& term : lhs) {
121 entries.emplace_back(
m_var_idx.
index(term.single_variable()), term.coeff());
124 std::sort(entries.begin(), entries.end(),
125 [](
const auto& lhs,
const auto& rhs){ return lhs.col_index < rhs.col_index; }
129 if (!carl::is_zero(constant_part)) entries.emplace_back(
constant_column(), constant_part);
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();
145 std::vector<std::size_t> pending;
149 pending.push_back(i);
152 while (!pending.empty()) {
153 std::size_t v = pending.back();
155 if (col_used[v])
continue;
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;
164 if (e.col_index == actual_col)
continue;
165 for (std::size_t j = 0; ; ++j) {
168 pending.push_back(j);
173 row_used[it.row()] =
true;
175 if (n.
ignored.contains(it.row())) {
176 result.back().ignored.insert(
result.back().matrix.n_rows());
196 if (
m_formula.type() == carl::FormulaType::CONSTRAINT) constraints.push_back(
m_formula);
197 else constraints =
m_formula.subformulas();
215 for (
const auto& c : constraints) {
216 auto vars = carl::variables(c).as_set();
217 if (std::any_of(elim_vars.begin(),
219 [&
vars](
const auto v){ return vars.contains(v); })
221 filtered.push_back(c);
224 constraints = filtered;
225 SMTRAT_LOG_DEBUG(
"smtrat.qe",
"Constraints after filtering: " << constraints);
227 if (elim_vars.empty()) {
239 std::vector<Matrix::ColIndex> elim_var_indices;
259 std::size_t n_deleted_rows = parent.
eliminators.size();
267 std::set<RowIndex> ignore;
268 auto ignore_it = parent.
ignored.begin();
271 if (col_it != col_end && r == *col_it) ++col_it;
275 if (it != parent.
ignored.end()) {
276 ignore.emplace_hint(ignore.end(), new_matr.
n_rows());
286 return Node(new_matr, new_cols, ignore);
293 for (
auto it = row.rbegin(); it->col_index >
delta_column(); ++it) {
294 if (it->value < 0)
return false;
321 std::set<RowIndex> ignore;
322 auto ignore_it = parent.
ignored.begin();
324 bool local_conflict =
false;
325 bool inserted =
false;
327 auto process_row = [&](
RowIndex r) {
329 Rational scale_elim = elim_sgn*col_it->value;
331 auto combined_row = parent.
matrix.
combine(eliminator, scale_elim, r, scale_r);
337 new_matr.
append_row(combined_row.begin(), combined_row.end());
346 else local_conflict =
true;
355 for (
RowIndex r = 0; r < eliminator; ++r) {
356 if (r == col_it.row()) {
363 if (ignore_it != parent.
ignored.end() && r == *ignore_it) {
364 if (inserted) ignore.insert(new_matr.
n_rows() - 1);
370 if ((col_it != col_end) && (r == col_it.row())) {
377 if (ignore_it != parent.
ignored.end() && r == *ignore_it) {
378 if (inserted) ignore.insert(new_matr.
n_rows() - 1);
383 parent.
ignored.insert(eliminator);
387 return Node(new_matr, new_cols, ignore);
392 std::vector<RowIndex> lbs, ubs;
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());
407 auto combined_row = parent.
matrix.
combine(l, coeff_u, u, coeff_l);
423 file <<
"H-representation\n";
433 file <<
" " << constant*(-
lcm);
437 if ((it != row_end) && (it->col_index == j)) {
438 file <<
" " << (it->value)*(-
lcm);
458 file <<
"load_package \"redlog\"$\n";
459 file <<
"rlset r$\n";
460 file <<
"rlqe(ex({x1";
471 if (first) first =
false;
472 else if (e.value > 0) file <<
"+ ";
Node bounded_elimination(Node &parent)
Eliminates the chosen column in parent using the next eliminator in parent.
ColIndex m_first_parameter_col
std::vector< Node > m_nodes
FormulaT eliminate_quantifiers()
void write_matrix_to_redlog(const Matrix &m, const std::string &filename) const
ColIndex constant_column() const
bool is_trivial(const Row &row) const
bool is_positive_combination(const Row &row)
bool fm_elimination(Node &parent)
Eliminates the chosen column in parent using Fourier-Motzkin, but discards rows with 0 coeff.
void collect_constraint(const Row &row)
truncates the given row to not contain any "origin" information and inserts the result into the set o...
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:
Matrix::RowIndex RowIndex
Matrix::ColIndex ColIndex
Node unbounded_elimination(Node &parent)
Eliminates the chosen column in parent by dropping all rows with non-zero entry in that column.
ColIndex delta_column() const
FormulaSetT m_found_conjuncts
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.
qe::util::VariableIndex m_var_idx
Matrix build_initial_matrix(const FormulasT &constraints)
Constructs a matrix from the given constraints.
ColIndex origin_column(RowIndex row) const
FormulaT constraint_from_row(const Row &row) const
std::vector< Matrix::RowEntry > Row
std::set< Row, cmp_row > m_found_rows
void build_initial_systems()
Constructs the starting nodes from m_query and m_formula as follows:
bool is_conflict(const Row &row) const
std::vector< carl::Variable > gather_elimination_variables() const
FormulasT remaining_constraints()
std::vector< carl::Variable > remaining_variables()
void reserve(std::size_t n)
col_iterator col_end(ColIndex c) const
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.
std::size_t n_rows() const
RowIndex append_row(const It &begin, const It &end)
Appends the row contained in the range between begin and end to the matrix.
std::size_t n_cols() const
std::size_t non_zeros_total() const
row_iterator row_end(RowIndex r) const
col_iterator col_begin(ColIndex c) const
row_view row_entries(const RowIndex ri) const
row_iterator row_begin(RowIndex r) const
Rational coeff(const RowIndex i, const ColIndex j) const
void sort(T *array, int size, LessThan lt)
static bool find(V &ts, const T &t)
Numeric lcm(const Numeric &_valueA, const Numeric &_valueB)
Calculates the least common multiple of the two arguments.
Numeric abs(const Numeric &_value)
Calculates the absolute value of the given Numeric.
void gcd_normalize(std::vector< Matrix::RowEntry > &row)
QuantifierType type(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
std::vector< carl::Variable > vars(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
carl::Formula< Poly > FormulaT
carl::MultivariatePolynomial< Rational > Poly
carl::Formulas< Poly > FormulasT
#define SMTRAT_LOG_DEBUG(channel, msg)
#define SMTRAT_STATISTICS_CALL(function)
void choose_elimination()
std::vector< ColIndex > cols_to_elim
std::set< RowIndex > ignored
std::vector< RowIndex > eliminators
std::size_t index(carl::Variable v) const
carl::Variable var(std::size_t i) const
void gather_variables(const FormulasT &fs)