SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
Node.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include "../util/Matrix.h"
5 
6 namespace smtrat::qe::fmplex {
7 
8 struct Node {
12 
13  enum class Type { UNDETERMINED, CONFLICT, LEAF, LBS, UBS, NBS, FM };
14 
18  std::vector<ColIndex> cols_to_elim;
19  std::vector<RowIndex> eliminators;
20  std::set<RowIndex> ignored;
21 
23  if (matrix.n_rows() == 0 || cols_to_elim.empty()) {
24  type = Type::LEAF;
25  return;
26  }
27 
28  if (cols_to_elim.size() == 1) {
29  type = Type::FM;
30  chosen_col = cols_to_elim.front();
31  return;
32  }
33 
34  // find best column
35  std::size_t min_branches = matrix.n_rows();
36  for (const auto j : cols_to_elim) {
37  std::size_t lbs = 0, ubs = 0;
38  std::size_t ignored_lbs = 0, ignored_ubs = 0;
39  auto col_end = matrix.col_end(j);
40  for (auto col_it = matrix.col_begin(j); col_it != col_end; ++col_it) {
41  if (col_it->value < 0) {
42  if (ignored.contains(col_it.row())) ++ignored_lbs;
43  ++lbs;
44  } else {
45  if (ignored.contains(col_it.row())) ++ignored_ubs;
46  ++ubs;
47  }
48  }
49  if (lbs == 0 || ubs == 0) {
50  chosen_col = j;
51  type = Type::NBS;
52  break;
53  }
54 
55  std::size_t min_j = std::min(lbs-ignored_lbs, ubs-ignored_ubs);
56  if (min_j < min_branches) {
57  min_branches = min_j;
58  chosen_col = j;
59  type = ((lbs-ignored_lbs) == min_j) ? Type::LBS : Type::UBS;
60  }
61  }
62 
63  // gather eliminators
64  auto col_it = matrix.col_begin(chosen_col);
65  auto col_end = matrix.col_end(chosen_col);
66 
67  auto ign_it = ignored.begin();
68  switch (type) {
69  case Type::LBS:
70  for (; col_it != col_end; ++col_it) {
71  if (ign_it != ignored.end() && *ign_it == col_it.row()) ++ign_it;
72  else if (col_it->value < 0) eliminators.push_back(col_it.row());
73  }
74  break;
75  case Type::UBS:
76  for (; col_it != col_end; ++col_it){
77  if (ign_it != ignored.end() && *ign_it == col_it.row()) ++ign_it;
78  else if (col_it->value > 0) eliminators.push_back(col_it.row());
79  }
80  break;
81  case Type::NBS:
82  for (; col_it != col_end; ++col_it){
83  eliminators.push_back(col_it.row());
84  }
85  break;
86  default:
87  break;
88  }
89  }
90 
92  return (
93  matrix.n_rows() >= 10
94  && cols_to_elim.size() >= 2
95  && (cols_to_elim.size() >= 5 || matrix.n_rows() >= 20)
96  && matrix.n_rows() > cols_to_elim.size() + 1
97  );
98  }
99 
100  Node(bool is_sat) {
102  eliminators.clear();
103  }
104 
105  Node() {}
106 
107  Node(const Matrix& m, const std::vector<ColIndex>& cols)
108  : matrix(m)
109  , cols_to_elim(cols) {}
110 
111  Node(const Matrix& m, const std::vector<ColIndex>& cols, const std::set<RowIndex>& ign)
112  : matrix(m)
113  , cols_to_elim(cols)
114  , ignored(ign) {}
115 
116  Node(Matrix&& m, const std::vector<ColIndex>& cols)
117  : matrix(std::move(m))
118  , cols_to_elim(cols) {}
119 
120 
121  inline bool is_conflict() const { return type == Node::Type::CONFLICT; }
122  inline bool is_finished() const { return eliminators.empty(); }
123 
124  static Node conflict() { return Node(false); }
125  static Node leaf() { return Node(true); }
126 };
127 
128 
129 template<typename T>
130 std::ostream& print_vec(std::ostream& os, const std::vector<T>& vec) {
131  os << "[" << vec.size() << ": ";
132  for (const auto& t : vec) os << t << ", ";
133  os << "]";
134  return os;
135 }
136 
137 inline std::ostream& operator<<(std::ostream& os, const smtrat::qe::fmplex::Node& n) {
138  os << "\n========== NODE ============\n";
139  switch (n.type) {
140  using Type = smtrat::qe::fmplex::Node::Type;
141  case Type::CONFLICT: os << "CONFLICT\n"; return os;
142  case Type::LEAF: os << "Leaf\n"; return os;
143  case Type::LBS: os << "LBS"; break;
144  case Type::UBS: os << "UBS"; break;
145  case Type::NBS: os << "NBS"; break;
146  case Type::FM: os << "FM"; break;
147  case Type::UNDETERMINED: os << "Undet."; break;
148  }
149  os << "| Chose col " << n.chosen_col << " out of ";
150  print_vec(os, n.cols_to_elim);
151  os << "\n";
152  os << "Total n. rows:" << n.matrix.n_rows() << ", Eliminators: ";
153  print_vec(os, n.eliminators);
154  os << "\n\n";
155  for (std::size_t i = 0; i < n.matrix.n_rows(); ++i) {
156  std::vector<qe::util::Matrix::RowEntry> es;
157  for (const auto& e: n.matrix.row_entries(i)) es.push_back(e);
158  print_vec(os, es);
159  os << "\n";
160  }
161  os << "============================\n";
162  return os;
163 }
164 
165 }
col_iterator col_end(ColIndex c) const
Definition: Matrix.h:193
std::size_t n_rows() const
Definition: Matrix.h:67
std::size_t RowIndex
Definition: Matrix.h:11
col_iterator col_begin(ColIndex c) const
Definition: Matrix.h:192
std::size_t ColIndex
Definition: Matrix.h:12
row_view row_entries(const RowIndex ri) const
Definition: Matrix.h:171
std::ostream & operator<<(std::ostream &os, const smtrat::qe::fmplex::Node &n)
Definition: Node.h:137
std::ostream & print_vec(std::ostream &os, const std::vector< T > &vec)
Definition: Node.h:130
bool is_sat(Answer a)
Definition: types.h:58
static Node conflict()
Definition: Node.h:124
Matrix::RowIndex RowIndex
Definition: Node.h:10
void choose_elimination()
Definition: Node.h:22
bool is_finished() const
Definition: Node.h:122
bool is_suitable_for_splitting()
Definition: Node.h:91
Node(bool is_sat)
Definition: Node.h:100
static Node leaf()
Definition: Node.h:125
Matrix::ColIndex ColIndex
Definition: Node.h:11
ColIndex chosen_col
Definition: Node.h:17
std::vector< ColIndex > cols_to_elim
Definition: Node.h:18
Node(const Matrix &m, const std::vector< ColIndex > &cols, const std::set< RowIndex > &ign)
Definition: Node.h:111
std::set< RowIndex > ignored
Definition: Node.h:20
Node(const Matrix &m, const std::vector< ColIndex > &cols)
Definition: Node.h:107
bool is_conflict() const
Definition: Node.h:121
Node(Matrix &&m, const std::vector< ColIndex > &cols)
Definition: Node.h:116
std::vector< RowIndex > eliminators
Definition: Node.h:19