SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
delineation.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <map>
4 #include <vector>
5 #include <boost/container/flat_set.hpp>
6 
7 #include "roots.h"
8 
10 
13  bool is_inclusive = false;
14  bool is_optional = false;
15  std::optional<PolyRef> origin = std::nullopt;
16 };
17 inline std::ostream& operator<<(std::ostream& os, const TaggedIndexedRoot& data) {
18  os << data.root;
19  if (data.is_inclusive) os << "_incl";
20  if (data.is_optional) os << "_opt";
21  if (data.origin) os << "_{" << *data.origin << "}";
22  return os;
23 }
24 inline bool operator==(const TaggedIndexedRoot& lhs, const TaggedIndexedRoot& rhs) {
25  return lhs.root == rhs.root && lhs.is_inclusive == rhs.is_inclusive && lhs.is_optional == rhs.is_optional;
26 }
27 inline bool operator<(const TaggedIndexedRoot& lhs, const TaggedIndexedRoot& rhs) {
28  return lhs.root < rhs.root || (lhs.root == rhs.root && lhs.is_inclusive < rhs.is_inclusive) || (lhs.root == rhs.root && lhs.is_inclusive == rhs.is_inclusive && lhs.is_optional < rhs.is_optional);
29 }
30 
31 using RootMap = boost::container::flat_map<RAN, std::vector<TaggedIndexedRoot>>;
32 using RootMapPlain = boost::container::flat_map<RAN, std::vector<IndexedRoot>>;
33 
34 /**
35  * An interval of a delineation.
36  */
38  RootMap::const_iterator m_lower;
39  RootMap::const_iterator m_upper;
40  RootMap::const_iterator m_end;
43 
44  DelineationInterval(RootMap::const_iterator&& lower, RootMap::const_iterator&& upper, RootMap::const_iterator&& end, bool lower_strict, bool upper_strict) : m_lower(lower), m_upper(upper), m_end(end), m_lower_strict(lower_strict), m_upper_strict(upper_strict) {
45  assert(!is_section() || (!lower_strict && !upper_strict));
46  };
47 
48  friend class Delineation;
49 
50 public:
51  bool is_section() const {
52  return m_lower != m_end && m_upper != m_end && m_lower == m_upper;
53  }
54 
55  bool is_sector() const {
56  return !is_section();
57  }
58 
59  const auto& lower() const {
60  assert(m_lower != m_end);
61  return m_lower;
62  }
63  bool lower_unbounded() const {
64  return m_lower == m_end;
65  }
66  bool lower_strict() const {
67  return !lower_unbounded() && m_lower_strict;
68  }
69 
70  const auto& upper() const {
71  assert(m_upper != m_end);
72  return m_upper;
73  }
74  bool upper_unbounded() const {
75  return m_upper == m_end;
76  }
77  bool upper_strict() const {
78  return !upper_unbounded() && m_upper_strict;
79  }
80 
81  bool contains(const RAN& sample) const {
82  if (is_section()) {
83  return sample == lower()->first;
84  } else {
85  if (!lower_unbounded() && lower_strict() && sample <= lower()->first) return false;
86  if (!lower_unbounded() && !lower_strict() && sample < lower()->first) return false;
87  if (!upper_unbounded() && upper_strict() && sample >= upper()->first) return false;
88  if (!upper_unbounded() && !upper_strict() && sample >= upper()->first) return false;
89  return true;
90  }
91  }
92 };
93 inline std::ostream& operator<<(std::ostream& os, const DelineationInterval& data) {
94  if (data.lower_strict()) {
95  os << "(" << *data.lower();
96  } else if (data.lower_unbounded()) {
97  os << "(-oo";
98  } else {
99  os << "[" << *data.lower();
100  }
101  os << ", ";
102  if (data.upper_strict()) {
103  os << *data.upper() << ")";
104  } else if (data.upper_unbounded()) {
105  os << "oo)";
106  } else {
107  os << *data.upper() << "]";
108  }
109  return os;
110 }
111 
112 /**
113  * Represents the delineation of a set of polynomials (at a sample), that is
114  * - the ordering of all roots,
115  * - the set of nullified polynomials,
116  * - the set of polynomials without a root.
117  */
118 class Delineation {
119  friend class DelineationInterval;
120 
121  /// A map from the actual roots to indexed root expressions. Note that this map is sorted.
123  /// The set of all nullified polynomials.
124  boost::container::flat_set<PolyRef> m_polys_nullified;
125  /// The set of all polynomials without a root.
126  boost::container::flat_set<PolyRef> m_polys_nonzero;
127 
128 public:
129  /**
130  * Returns the underlying root map, which is a set of real algebraic numbers to indexed root expressions.
131  */
132  const auto& roots() const {
133  return m_roots;
134  }
135  /**
136  * The set of nullified polynomials.
137  */
138  const auto& nullified() const {
139  return m_polys_nullified;
140  }
141  /**
142  * The set of polynomials without roots.
143  */
144  const auto& nonzero() const {
145  return m_polys_nonzero;
146  }
147  bool empty() const {
148  return m_roots.empty() && m_polys_nullified.empty() && m_polys_nonzero.empty();
149  }
150 
151  /**
152  * Computes the bounds of the interval around the given sample w.r.t. this delineation.
153  */
154  auto delineate_cell(const RAN& sample) const {
155  RootMap::const_iterator lower;
156  RootMap::const_iterator upper;
157  bool lower_strict = false;
158  bool upper_strict = false;
159 
160  if (m_roots.empty()) {
161  lower = m_roots.end();
162  upper = m_roots.end();
163  } else {
164  lower = m_roots.lower_bound(sample);
165  if (lower == m_roots.end() || lower->first != sample) {
166  if (lower == m_roots.begin()) lower = m_roots.end();
167  else lower--;
168  }
169  while(lower != m_roots.end() && std::find_if(lower->second.begin(), lower->second.end(), [&](const auto& t_root) { return !t_root.is_optional; }) == lower->second.end()) {
170  if (lower == m_roots.begin()) lower = m_roots.end();
171  else lower--;
172  }
173  upper = m_roots.lower_bound(sample);
174  while(upper != m_roots.end() && std::find_if(upper->second.begin(), upper->second.end(), [&](const auto& t_root) { return !t_root.is_optional; }) == upper->second.end()) {
175  upper++;
176  }
177  /*
178  auto section = m_roots.find(sample);
179  if (section != m_roots.end()) {
180  lower = section;
181  upper = section;
182  } else {
183  upper = m_roots.upper_bound(sample);
184  if (upper == m_roots.begin()) {
185  lower = m_roots.end();
186  } else {
187  lower = upper;
188  lower--;
189  }
190  }
191  */
192  }
193 
194  if (lower != upper) {
195  if(lower != m_roots.end()) {
196  lower_strict = std::find_if(lower->second.begin(), lower->second.end(), [&](const auto& t_root) { return !t_root.is_inclusive; }) != lower->second.end();
197  }
198  if(upper != m_roots.end()) {
199  upper_strict = std::find_if(upper->second.begin(), upper->second.end(), [&](const auto& t_root) { return !t_root.is_inclusive; }) != upper->second.end();
200  }
201  }
202 
203  return DelineationInterval(std::move(lower), std::move(upper), m_roots.end(), lower_strict, upper_strict);
204  }
205 
206  void add_root(RAN root, TaggedIndexedRoot tagged_root) {
207  auto irs = m_roots.find(root);
208  if (irs == m_roots.end()) {
209  irs = m_roots.emplace(std::move(root), std::vector<TaggedIndexedRoot>()).first;
210  }
211  auto loc = std::find_if(irs->second.begin(), irs->second.end(), [&tagged_root](const auto& current) { return current.root == tagged_root.root && current.origin == tagged_root.origin; });
212  if (loc == irs->second.end()) {
213  irs->second.push_back(std::move(tagged_root));
214  } else {
215  if (!tagged_root.is_inclusive) loc->is_inclusive = false;
216  if (!tagged_root.is_optional) loc->is_optional = false;
217  }
218  }
219 
220  void remove_root(RAN root, TaggedIndexedRoot tagged_root) {
221  auto irs = m_roots.find(root);
222  if (irs == m_roots.end()) return;
223  std::erase(irs->second, tagged_root);
224  }
225 
226  void remove_roots_with_origin(RAN root, PolyRef origin, bool only_optional = false) {
227  auto irs = m_roots.find(root);
228  if (irs == m_roots.end()) return;
229  std::erase_if(irs->second, [&origin, &only_optional](const auto& current) {
230  return current.origin == origin && (!only_optional || current.is_optional);
231  });
232  }
233 
235  m_polys_nonzero.insert(poly);
236  }
237 
239  m_polys_nullified.insert(poly);
240  }
241 
242  void merge_with(const Delineation& other) {
243  for (const auto& [k, v] : other.m_roots) {
244  for (const auto& r : v) {
245  add_root(k,r);
246  }
247  }
248 
249  for (const auto& o : other.m_polys_nullified) {
251  }
252 
253  for (const auto& o : other.m_polys_nonzero) {
254  add_poly_nonzero(o);
255  }
256  }
257 };
258 inline std::ostream& operator<<(std::ostream& os, const Delineation& data) {
259  os << "(roots: " << data.roots() << "; nonzero: " << data.nonzero() << "; nullified: " << data.nullified() << ")";
260  return os;
261 }
262 
263 /**
264  * Compares the lower bounds of two DelineationIntervals. It respects whether the interval is a section or sector.
265  */
266 inline bool lower_lt_lower(const DelineationInterval& del1, const DelineationInterval& del2) {
267  if (del1.lower_unbounded()) return !del2.lower_unbounded();
268  else if (del2.lower_unbounded()) return false;
269  else if (del1.lower()->first == del2.lower()->first) return !del1.lower_strict() && del2.lower_strict();
270  else return del1.lower()->first < del2.lower()->first;
271 }
272 
273 /**
274  * Compares the lower bounds of two DelineationIntervals. It respects whether the interval is a section or sector.
275  */
276 inline bool lower_eq_lower(const DelineationInterval& del1, const DelineationInterval& del2) {
277  if (del1.lower_unbounded() && del2.lower_unbounded()) return true;
278  else if (del1.lower_unbounded() != del2.lower_unbounded()) return false;
279  else if (del1.lower()->first == del2.lower()->first) return del1.lower_strict() == del2.lower_strict();
280  else return false;
281 }
282 
283 /**
284  * Compares the upper bounds of two DelineationIntervals. It respects whether the interval is a section or sector.
285  */
286 inline bool upper_lt_upper(const DelineationInterval& del1, const DelineationInterval& del2) {
287  if (del1.upper_unbounded()) return false;
288  else if (del2.upper_unbounded()) return true;
289  else if (del1.upper()->first == del2.upper()->first) return del1.upper_strict() && !del2.upper_strict();
290  else return del1.upper()->first < del2.upper()->first;
291 }
292 
293 /**
294  * Compares an upper bound with a lower bound of DelineationIntervals. It respects whether the interval is a section or sector.
295  */
296 inline bool upper_lt_lower(const DelineationInterval& del1, const DelineationInterval& del2) {
297  if (del1.upper_unbounded()) return false;
298  if (del2.lower_unbounded()) return false;
299  if (del1.upper()->first < del2.lower()->first) return true;
300  if (del1.upper()->first == del2.lower()->first && del1.upper_strict() && del2.lower_strict()) return true;
301  return false;
302 }
303 
304 /**
305  * Compares the upper bounds of two DelineationIntervals. It respects whether the interval is a section or sector.
306  */
307 inline bool upper_eq_upper(const DelineationInterval& del1, const DelineationInterval& del2) {
308  if (del1.upper_unbounded() && del2.upper_unbounded())
309  return true;
310  else if (del1.upper_unbounded() != del2.upper_unbounded())
311  return false;
312  else if (del1.upper()->first == del2.upper()->first)
313  return del1.upper_strict() == del2.upper_strict();
314  else
315  return false;
316 }
317 
318 }
DelineationInterval(RootMap::const_iterator &&lower, RootMap::const_iterator &&upper, RootMap::const_iterator &&end, bool lower_strict, bool upper_strict)
Definition: delineation.h:44
Represents the delineation of a set of polynomials (at a sample), that is.
Definition: delineation.h:118
RootMap m_roots
A map from the actual roots to indexed root expressions. Note that this map is sorted.
Definition: delineation.h:122
void remove_roots_with_origin(RAN root, PolyRef origin, bool only_optional=false)
Definition: delineation.h:226
const auto & nonzero() const
The set of polynomials without roots.
Definition: delineation.h:144
void merge_with(const Delineation &other)
Definition: delineation.h:242
void remove_root(RAN root, TaggedIndexedRoot tagged_root)
Definition: delineation.h:220
void add_root(RAN root, TaggedIndexedRoot tagged_root)
Definition: delineation.h:206
boost::container::flat_set< PolyRef > m_polys_nonzero
The set of all polynomials without a root.
Definition: delineation.h:126
const auto & roots() const
Returns the underlying root map, which is a set of real algebraic numbers to indexed root expressions...
Definition: delineation.h:132
const auto & nullified() const
The set of nullified polynomials.
Definition: delineation.h:138
auto delineate_cell(const RAN &sample) const
Computes the bounds of the interval around the given sample w.r.t.
Definition: delineation.h:154
boost::container::flat_set< PolyRef > m_polys_nullified
The set of all nullified polynomials.
Definition: delineation.h:124
Main datastructures.
Definition: delineation.h:9
bool operator==(const TaggedIndexedRoot &lhs, const TaggedIndexedRoot &rhs)
Definition: delineation.h:24
bool upper_eq_upper(const DelineationInterval &del1, const DelineationInterval &del2)
Compares the upper bounds of two DelineationIntervals.
Definition: delineation.h:307
std::ostream & operator<<(std::ostream &os, const TaggedIndexedRoot &data)
Definition: delineation.h:17
bool upper_lt_upper(const DelineationInterval &del1, const DelineationInterval &del2)
Compares the upper bounds of two DelineationIntervals.
Definition: delineation.h:286
bool lower_lt_lower(const DelineationInterval &del1, const DelineationInterval &del2)
Compares the lower bounds of two DelineationIntervals.
Definition: delineation.h:266
boost::container::flat_map< RAN, std::vector< TaggedIndexedRoot > > RootMap
Definition: delineation.h:31
bool upper_lt_lower(const DelineationInterval &del1, const DelineationInterval &del2)
Compares an upper bound with a lower bound of DelineationIntervals.
Definition: delineation.h:296
bool lower_eq_lower(const DelineationInterval &del1, const DelineationInterval &del2)
Compares the lower bounds of two DelineationIntervals.
Definition: delineation.h:276
bool operator<(const TaggedIndexedRoot &lhs, const TaggedIndexedRoot &rhs)
Definition: delineation.h:27
boost::container::flat_map< RAN, std::vector< IndexedRoot > > RootMapPlain
Definition: delineation.h:32
Polynomial::RootType RAN
Definition: common.h:24
Represents the i-th root of a multivariate polynomial at its main variable (given an appropriate samp...
Definition: roots.h:15