SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
fmplex.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <vector>
4 #include <cassert>
5 
6 #include "Matrix.h"
7 #include "Node.h"
8 
9 namespace smtrat::fmplex {
10 
11 // TODO: equality substitution
13 
17  using Row = std::vector<RowEntry>;
18 
19  struct cmp_row {
20  bool operator()(const Row& a, const Row& b) const { // TODO: this does not filter out duplicates with different lin. combs.!
21  auto it_a = a.begin(), it_b = b.begin();
22  auto end_a = a.end(), end_b = b.end();
23  while (it_a != end_a && it_b != end_b) {
24  if (it_a->col_index != it_b->col_index)
25  return it_a->col_index < it_b->col_index;
26  if (it_a->value != it_b->value)
27  return it_a->value < it_b->value;
28  ++it_a;
29  ++it_b;
30  }
31  return (it_b != end_b); // at this point: a < b only if a is at end and b is not
32  }
33  };
34 
35 
36 private:
37  std::vector<Node> m_nodes;
41  std::set<Row, cmp_row> m_found_rows;
42 
43 public:
44  FMplexElimination(const Matrix& m, std::size_t n_quantified, std::size_t n_parameters) {
45  m_first_parameter_col = n_quantified;
46  m_constant_col = n_quantified + n_parameters;
47 
48  // filter finished rows from m
49  Matrix filtered(m.n_rows(), m.n_cols());
50  for (Matrix::RowIndex i = 0; i < m.n_rows(); ++i) {
52  Row r;
53  for (const auto& e : m.row_entries(i)) {
54  if (e.col_index > delta_column()) break;
55  r.push_back(e);
56  }
57  m_found_rows.insert(r);
58  } else {
59  filtered.append_row(m.row_begin(i), m.row_end(i));
60  }
61  }
62 
63  m_total_cols = m.n_cols(); //m_constant_col + filtered.n_rows();
64 
65  // store initial Node
66  std::vector<Matrix::ColIndex> cols_to_elim;
67  for (ColIndex j = 0; j < n_quantified; ++j) cols_to_elim.push_back(j);
68  m_nodes.emplace_back(filtered, cols_to_elim);
69  }
70 
71 
73  while (!m_nodes.empty()) {
74  switch (m_nodes.back().type) {
76  return trivial_unsat_matrix();
78  auto split = split_into_independent_nodes(m_nodes.back());
79  m_nodes.pop_back();
80  m_nodes.insert(m_nodes.end(), split.begin(), split.end());
81  break;
82  }
83  case Node::Type::NBS:
84  m_nodes.back() = unbounded_elimination(m_nodes.back());
85  break;
86  case Node::Type::LBS:[[fallthrough]];
87  case Node::Type::UBS:
88  if (m_nodes.back().is_finished()) m_nodes.pop_back();
89  else m_nodes.push_back(bounded_elimination(m_nodes.back()));
90  break;
91  case Node::Type::FM:
92  if (!fm_elimination(m_nodes.back())) return trivial_unsat_matrix();
93  m_nodes.pop_back();
94  break;
95  case Node::Type::LEAF:
96  m_nodes.pop_back();
97  break;
98  }
99  }
100 
102  for (const auto& r : m_found_rows) {
103  result.append_row(r.begin(), r.end());
104  }
105 
106  return result;
107  }
108 
109 
110 private:
112  ColIndex delta_column () const { return m_constant_col + 1; }
113  ColIndex origin_column (RowIndex row) const { return delta_column() + 1 + row; }
114 
115  bool is_trivial(const Row& row) const {
116  assert(!row.empty());
117  return row.begin()->col_index >= constant_column();
118  }
119 
120  bool is_conflict(const Row& row) const {
121  assert(!row.empty());
122  assert(is_trivial(row));
123  const auto& e = row.front();
124  return (e.col_index <= delta_column()) && (e.value > 0);
125  }
126 
127  bool is_positive_combination(const Row& row) const {
128  assert(row.front().col_index <= delta_column());
129  // don't need to check for it == end because the constraint cannot be trivially true here
130  for (auto it = row.rbegin(); it->col_index > delta_column(); ++it) {
131  if (it->value < 0) return false;
132  }
133  return true;
134  }
135 
136  bool is_global_conflict(const Row& row) const {
137  return is_trivial(row) && is_conflict(row) && is_positive_combination(row);
138  }
139 
140  void collect_constraint(const Row& row) {
141  Row truncated = row;
142  for (std::size_t i = 0; ; ++i) {
143  if (truncated[i].col_index > delta_column()) {
144  truncated.resize(i);
145  break;
146  }
147  }
148  m_found_rows.insert(truncated);
149  }
150 
151  std::vector<Node> split_into_independent_nodes(const Node& n) const;
152 
154  Node bounded_elimination (Node& parent);
155  bool fm_elimination (Node& parent);
156 
159  std::vector<RowEntry> unsat_row = { RowEntry(constant_column(), Rational(1)) };
160  result.append_row(unsat_row.begin(), unsat_row.end());
161  return result;
162  }
163 };
164 
165 }
std::set< Row, cmp_row > m_found_rows
Definition: fmplex.h:41
bool is_trivial(const Row &row) const
Definition: fmplex.h:115
ColIndex delta_column() const
Definition: fmplex.h:112
std::vector< Node > m_nodes
Definition: fmplex.h:37
bool is_positive_combination(const Row &row) const
Definition: fmplex.h:127
ColIndex constant_column() const
Definition: fmplex.h:111
std::vector< Node > split_into_independent_nodes(const Node &n) const
Definition: fmplex.cpp:156
Matrix::ColIndex ColIndex
Definition: fmplex.h:15
bool fm_elimination(Node &parent)
Definition: fmplex.cpp:128
void collect_constraint(const Row &row)
Definition: fmplex.h:140
bool is_global_conflict(const Row &row) const
Definition: fmplex.h:136
bool is_conflict(const Row &row) const
Definition: fmplex.h:120
std::vector< RowEntry > Row
Definition: fmplex.h:17
Matrix trivial_unsat_matrix() const
Definition: fmplex.h:157
ColIndex origin_column(RowIndex row) const
Definition: fmplex.h:113
Node bounded_elimination(Node &parent)
Definition: fmplex.cpp:38
Matrix::RowIndex RowIndex
Definition: fmplex.h:14
FMplexElimination(const Matrix &m, std::size_t n_quantified, std::size_t n_parameters)
Definition: fmplex.h:44
Matrix::RowEntry RowEntry
Definition: fmplex.h:16
Node unbounded_elimination(Node &parent)
Definition: fmplex.cpp:5
std::size_t RowIndex
Definition: Matrix.h:13
std::size_t n_cols() const
Definition: Matrix.h:70
row_view row_entries(const RowIndex ri) const
Definition: Matrix.h:173
row_iterator row_end(RowIndex r) const
Definition: Matrix.h:161
row_iterator row_begin(RowIndex r) const
Definition: Matrix.h:160
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:91
std::size_t n_rows() const
Definition: Matrix.h:69
std::size_t ColIndex
Definition: Matrix.h:14
mpq_class Rational
Definition: Matrix.h:7
bool operator()(const Row &a, const Row &b) const
Definition: fmplex.h:20