SMT-RAT  24.02
Toolbox for Strategic and Parallel Satisfiability-Modulo-Theories Solving
roots.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "../common.h"
4 #include "polynomials.h"
5 #include "boost/container/flat_set.hpp"
6 #include "boost/container/flat_map.hpp"
7 
9 
10 using carl::operator<<;
11 
12 /**
13  * Represents the i-th root of a multivariate polynomial at its main variable (given an appropriate sample).
14  */
15 struct IndexedRoot {
16  /// A multivariate polynomial.
18  /// The index, must be > 0.
19  size_t index;
20  IndexedRoot(PolyRef p, size_t i) : poly(p), index(i) { /*assert(i>0);*/ }
21  IndexedRoot() : IndexedRoot( PolyRef{0,0,0}, 0) {}
22 };
23 inline bool operator==(const IndexedRoot& lhs, const IndexedRoot& rhs) {
24  return lhs.poly == rhs.poly && lhs.index == rhs.index;
25 }
26 inline bool operator<(const IndexedRoot& lhs, const IndexedRoot& rhs) {
27  return lhs.poly < rhs.poly || (lhs.poly == rhs.poly && lhs.index < rhs.index);
28 }
29 inline bool operator!=(const IndexedRoot& lhs, const IndexedRoot& rhs) {
30  return !(lhs == rhs);
31 }
32 inline std::ostream& operator<<(std::ostream& os, const IndexedRoot& data) {
33  os << "root(" << data.poly << ", " << data.index << ")";
34  return os;
35 }
36 
38  /// Active linear bound from -oo to including the first intersection point (or oo if no such point exists)
40  /// List of intersection points and linear bounds which are active beginning from including the given intersection point to including the next intersection point (or oo if no such point exists); at intersection points, two bounds are active; the list needs to be sorted by intersection point
41  std::vector<std::pair<Rational,IndexedRoot>> bounds;
42 
43  bool poly_bound_at(const PolyRef& poly, const RAN& r) const {
44  if (bounds.empty()) return first.poly == poly;
45  auto it = bounds.begin();
46  while(it+1 != bounds.end() && r < (it+1)->first) it++;
47  return it->second.poly == poly;
48  }
49 };
50 
51 /**
52  * Represents the minimum function of the contained indexed root functions.
53  */
55  std::vector<std::vector<IndexedRoot>> roots;
56  void polys(boost::container::flat_set<PolyRef>& result) const {
57  for (const auto& r : roots) {
58  for (const auto& r1 : r) {
59  result.insert(r1.poly);
60  }
61  }
62  }
63  std::optional<PiecewiseLinearInfo> bounds;
64 };
65 inline bool operator==(const CompoundMinMax& lhs, const CompoundMinMax& rhs) {
66  return lhs.roots == rhs.roots;
67 }
68 inline bool operator<(const CompoundMinMax& lhs, const CompoundMinMax& rhs) {
69  return lhs.roots < rhs.roots;
70 }
71 inline bool operator!=(const CompoundMinMax& lhs, const CompoundMinMax& rhs) {
72  return !(lhs == rhs);
73 }
74 inline std::ostream& operator<<(std::ostream& os, const CompoundMinMax& data) {
75  os << "min-max(" << data.roots << ")";
76  return os;
77 }
78 
79 /**
80  * Represents the maximum function of the contained indexed root functions.
81  */
83  std::vector<std::vector<IndexedRoot>> roots;
84  void polys(boost::container::flat_set<PolyRef>& result) const {
85  for (const auto& r : roots) {
86  for (const auto& r1 : r) {
87  result.insert(r1.poly);
88  }
89  }
90  }
91  std::optional<PiecewiseLinearInfo> bounds;
92 };
93 inline bool operator==(const CompoundMaxMin& lhs, const CompoundMaxMin& rhs) {
94  return lhs.roots == rhs.roots;
95 }
96 inline bool operator<(const CompoundMaxMin& lhs, const CompoundMaxMin& rhs) {
97  return lhs.roots < rhs.roots;
98 }
99 inline bool operator!=(const CompoundMaxMin& lhs, const CompoundMaxMin& rhs) {
100  return !(lhs == rhs);
101 }
102 inline std::ostream& operator<<(std::ostream& os, const CompoundMaxMin& data) {
103  os << "max-min(" << data.roots << ")";
104  return os;
105 }
106 
108  std::variant<IndexedRoot, CompoundMinMax, CompoundMaxMin> m_data;
109 
110 public:
111  RootFunction(IndexedRoot data) : m_data(data) {};
112  RootFunction(CompoundMinMax&& data) : m_data(data) {};
113  RootFunction(CompoundMaxMin&& data) : m_data(data) {};
114  bool is_root() const { return std::holds_alternative<IndexedRoot>(m_data); }
115  bool is_cminmax() const { return std::holds_alternative<CompoundMinMax>(m_data); }
116  bool is_cmaxmin() const { return std::holds_alternative<CompoundMaxMin>(m_data); }
117  const IndexedRoot& root() const { return std::get<IndexedRoot>(m_data); }
118  const CompoundMinMax& cminmax() const { return std::get<CompoundMinMax>(m_data); }
119  const CompoundMaxMin& cmaxmin() const { return std::get<CompoundMaxMin>(m_data); }
120 
121  const auto& roots() const {
122  assert(!is_root());
123  return is_cminmax() ? cminmax().roots : cmaxmin().roots;
124  }
125 
126  void polys(boost::container::flat_set<PolyRef>& result) const {
127  if (std::holds_alternative<IndexedRoot>(m_data)) {
128  result.insert(std::get<IndexedRoot>(m_data).poly);
129  } else if (std::holds_alternative<CompoundMinMax>(m_data)) {
130  std::get<CompoundMinMax>(m_data).polys(result);
131  } else if (std::holds_alternative<CompoundMaxMin>(m_data)) {
132  std::get<CompoundMaxMin>(m_data).polys(result);
133  }
134  }
135 
136  boost::container::flat_set<PolyRef> polys() const {
137  boost::container::flat_set<PolyRef> result;
138  polys(result);
139  return result;
140  }
141 
142  bool has_poly(const PolyRef poly) const {
143  if (is_root()) {
144  return root().poly == poly;
145  } else if (is_cmaxmin()) {
146  auto it = std::find_if(cmaxmin().roots.begin(), cmaxmin().roots.end(), [&poly](const auto& roots) {
147  return std::find_if(roots.begin(), roots.end(), [&poly](const auto& root) { return root.poly == poly;}) != roots.end();
148  });
149  return !(it == cmaxmin().roots.end());
150  } else if (is_cminmax()) {
151  auto it = std::find_if(cminmax().roots.begin(), cminmax().roots.end(), [&poly](const auto& roots) {
152  return std::find_if(roots.begin(), roots.end(), [&poly](const auto& root) { return root.poly == poly;}) != roots.end();
153  });
154  return !(it == cminmax().roots.end());
155  } else {
156  assert(false);
157  return false;
158  }
159  }
160 
161  std::optional<IndexedRoot> poly_root_below(const PolyRef poly) const {
162  if (is_root() && root().poly == poly) {
163  return root();
164  } else if (is_cmaxmin()) {
165  auto it = std::find_if(cmaxmin().roots.begin(), cmaxmin().roots.end(), [&poly](const auto& roots) { return roots.size() == 1 && roots[0].poly == poly;;});
166  if (it == cmaxmin().roots.end()) return std::nullopt;
167  else return *it->begin();
168  } else {
169  return std::nullopt;
170  }
171  };
172 
173  std::optional<IndexedRoot> poly_root_above(const PolyRef poly) const {
174  if (is_root() && root().poly == poly) {
175  return root();
176  } else if (is_cminmax()) {
177  auto it = std::find_if(cminmax().roots.begin(), cminmax().roots.end(), [&poly](const auto& roots) { return roots.size() == 1 && roots[0].poly == poly;;});
178  if (it == cminmax().roots.end()) return std::nullopt;
179  else return *it->begin();
180  } else {
181  return std::nullopt;
182  }
183  };
184 
185  friend bool operator==(const RootFunction& lhs, const RootFunction& rhs);
186  friend bool operator<(const RootFunction& lhs, const RootFunction& rhs);
187  friend std::ostream& operator<<(std::ostream& os, const RootFunction& data);
188 };
189 inline bool operator==(const RootFunction& lhs, const RootFunction& rhs) {
190  return lhs.m_data == rhs.m_data;
191 }
192 inline bool operator<(const RootFunction& lhs, const RootFunction& rhs) {
193  return lhs.m_data < rhs.m_data;
194 }
195 inline bool operator!=(const RootFunction& lhs, const RootFunction& rhs) {
196  return !(lhs == rhs);
197 }
198 inline std::ostream& operator<<(std::ostream& os, const RootFunction& data) {
199  os << data.m_data;
200  return os;
201 }
202 
203 
204 /// Bound type of a SymbolicInterval.
205 class Bound {
206  enum class Type { infty, strict, weak };
208  std::optional<RootFunction> m_value;
209  Bound(Type type, std::optional<RootFunction> value) : m_type(type), m_value(value) {}
210 
211 public:
212  static Bound infty() {
213  return Bound(Type::infty, std::nullopt);
214  }
215  static Bound strict(RootFunction value) {
216  return Bound(Type::strict, value);
217  }
218  static Bound weak(RootFunction value) {
219  return Bound(Type::weak, value);
220  }
221 
222  bool is_infty() const {
223  return m_type == Type::infty;
224  }
225  bool is_strict() const {
226  return m_type == Type::strict;
227  }
228  bool is_weak() const {
229  return m_type == Type::weak;
230  }
231  const RootFunction& value() const {
232  return *m_value;
233  }
234 
235  void set_weak() {
236  if (is_strict()) m_type = Type::weak;
237  }
238 
239  bool operator==(const Bound& other) const {
240  return m_type == other.m_type && m_value == other.m_value;
241  }
242 
243  bool operator!=(const Bound& other) const {
244  return !(*this == other);
245  }
246 };
247 /**
248  * A symbolic interal whose bounds are defined by indexed root expressions. Bounds can be infty, strict or weak. A special case is a section where the lower and upper bound are equal and weak.
249  */
253 
254 public:
255  /**
256  * Constructs a section.
257  */
258  SymbolicInterval(IndexedRoot root) : m_lower(Bound::weak(root)), m_upper(Bound::weak(root)) {}
259  /**
260  * Constructs an interval with arbitrary bounds.
261  */
262  SymbolicInterval(Bound lower, Bound upper) : m_lower(lower), m_upper(upper) {
263  assert(lower != upper || !(lower.is_strict() && upper.is_strict()));
264  }
265  /**
266  * Constructs (-oo, oo).
267  */
268  SymbolicInterval() : m_lower(Bound::infty()), m_upper(Bound::infty()) {}
269 
270  bool is_section() const {
271  return m_lower == m_upper && m_lower.is_weak();
272  }
273 
274  /**
275  * In case of a section, the defining indexed root is returned.
276  */
277  const IndexedRoot& section_defining() const {
278  assert(is_section());
279  return m_lower.value().root();
280  }
281 
282  /**
283  * Return the lower bound.
284  */
285  const auto& lower() const {
286  return m_lower;
287  }
288 
289  /**
290  * Returns the upper bound.
291  */
292  const auto& upper() const {
293  return m_upper;
294  }
295 
296  void polys(boost::container::flat_set<PolyRef>& result) const {
297  if (!m_lower.is_infty()) {
298  m_lower.value().polys(result);
299  }
300  if (!m_upper.is_infty()) {
301  m_upper.value().polys(result);
302  }
303  }
304 
305  boost::container::flat_set<PolyRef> polys() const {
306  boost::container::flat_set<PolyRef> result;
307  polys(result);
308  return result;
309  }
310 
311  void set_to_closure() {
312  m_lower.set_weak();
313  m_upper.set_weak();
314  }
315 };
316 inline std::ostream& operator<<(std::ostream& os, const SymbolicInterval& data) {
317  if (data.is_section()) {
318  os << "[" << data.section_defining() << "]";
319  } else {
320  if (data.lower().is_infty()) {
321  os << "(-oo";
322  } else if (data.lower().is_weak()) {
323  os << "[" << data.lower().value();
324  } else if (data.lower().is_strict()) {
325  os << "(" << data.lower().value();
326  }
327  os << ", ";
328  if (data.upper().is_infty()) {
329  os << "oo)";
330  } else if (data.upper().is_weak()) {
331  os << data.upper().value() << "]";
332  } else if (data.upper().is_strict()) {
333  os << data.upper().value() << ")";
334  }
335  }
336  return os;
337 }
338 
339 /**
340  * Describes a covering of the real line by SymbolicIntervals (given an appropriate sample).
341  */
343  std::vector<SymbolicInterval> m_data;
344 
345 public:
346  /**
347  * Add a SymbolicInterval to the covering.
348  *
349  * The added cell needs to be the rightmost cell of the already added cells and not be contained in any of these cells (or vice versa).
350  *
351  * * The first cell needs to have -oo as left bound.
352  * * The last cell needs to have oo as right bound.
353  * * All cells need to cover the real line under an appropriate sample.
354  * * Evaluated under an appropriate sample, the left bound of the added cell c is strictly greater than the left bounds of already added cells (considering also "strictness" of the bounds).
355  * * The right bound of the added cell c needs to be greater than all right bounds of already added cells (considering also "strictness" of the bounds).
356  */
357  void add(const SymbolicInterval& c) {
358  assert(!m_data.empty() || (!c.is_section() && c.lower().is_infty()));
359  assert(m_data.empty() || c.is_section() || !c.lower().is_infty());
360  assert(m_data.empty() || m_data.back().is_section() || !m_data.back().upper().is_infty());
361  m_data.push_back(c);
362  }
363 
364  const auto& cells() const {
365  return m_data;
366  }
367 };
368 inline std::ostream& operator<<(std::ostream& os, const CoveringDescription& data) {
369  os << data.cells();
370  return os;
371 }
372 
373 /**
374  * A relation between two roots.
375  *
376  */
380  bool is_strict;
381 };
382 inline bool operator==(const IndexedRootRelation& lhs, const IndexedRootRelation& rhs) {
383  return lhs.first == rhs.first && lhs.second == rhs.second && lhs.is_strict == rhs.is_strict;
384 }
385 inline bool operator<(const IndexedRootRelation& lhs, const IndexedRootRelation& rhs) {
386  return lhs.first < rhs.first || (lhs.first == rhs.first && lhs.second < rhs.second) || (lhs.first == rhs.first && lhs.second == rhs.second && lhs.is_strict < rhs.is_strict);
387 }
388 inline std::ostream& operator<<(std::ostream& os, const IndexedRootRelation& data) {
389  os << "(";
390  os << data.first;
391  if (data.is_strict) os << " < ";
392  else os << " <= ";
393  os << data.second;
394  os << ")";
395  return os;
396 }
397 /**
398  * Describes an ordering of IndexedRoots.
399  */
401  boost::container::flat_map<RootFunction, boost::container::flat_set<RootFunction>> m_leq;
402  boost::container::flat_map<RootFunction, boost::container::flat_set<RootFunction>> m_geq;
403  boost::container::flat_map<RootFunction, boost::container::flat_set<RootFunction>> m_less;
404  boost::container::flat_map<RootFunction, boost::container::flat_set<RootFunction>> m_greater;
405 
406  std::vector<IndexedRootRelation> m_data;
407 
408  boost::container::flat_map<datastructures::PolyRef, boost::container::flat_set<datastructures::PolyRef>> m_poly_pairs;
409 
410  bool m_is_projective = false;
411 
413  m_poly_pairs.try_emplace(p1).first->second.insert(p2);
414  m_poly_pairs.try_emplace(p2).first->second.insert(p1);
415  }
416 
417 public:
418  std::optional<SymbolicInterval> biggest_cell_wrt; // a hack, stores which cell is described by this ordering
419 
420  void add_leq(RootFunction first, RootFunction second) {
421  //assert(first.poly.level == second.poly.level);
422  if (first != second) {
423  m_data.push_back(IndexedRootRelation{first, second, false});
424  if (!m_leq.contains(first)) m_leq.emplace(first, boost::container::flat_set<RootFunction>());
425  m_leq[first].insert(second);
426  if (!m_geq.contains(second)) m_geq.emplace(second, boost::container::flat_set<RootFunction>());
427  m_geq[second].insert(first);
428 
429  if (first.is_root() && second.is_root()) {
430  add_poly_pair(first.root().poly, second.root().poly);
431  }
432  }
433  }
434 
435  void add_less(RootFunction first, RootFunction second) {
436  //assert(first.poly.level == second.poly.level);
437  assert(first != second);
438  m_data.push_back(IndexedRootRelation{first, second, true});
439  if (!m_less.contains(first)) m_less.emplace(first, boost::container::flat_set<RootFunction>());
440  m_less[first].insert(second);
441  if (!m_greater.contains(second)) m_greater.emplace(second, boost::container::flat_set<RootFunction>());
442  m_greater[second].insert(first);
443 
444  if (first.is_root() && second.is_root()) {
445  add_poly_pair(first.root().poly, second.root().poly);
446  }
447  }
448 
449  void add_eq(RootFunction first, RootFunction second) {
450  //assert(first.poly.level == second.poly.level);
451  if (first == second) return;
452  add_leq(first, second);
453  add_leq(second, first);
454  }
455 
456  const auto& data() const {
457  return m_data;
458  }
459 
460  const auto& leq() const {
461  return m_leq;
462  }
463 
464  const auto& geq() const {
465  return m_leq;
466  }
467 
468  bool holds_transitive(RootFunction first, RootFunction second, bool strict) const {
469  boost::container::flat_set<RootFunction> reached({first});
470  std::vector<RootFunction> active({first});
471  if (first == second) return true;
472  while(!active.empty()) {
473  auto current = active.back();
474  active.pop_back();
475  if (!strict && m_leq.contains(current)) {
476  for (const auto& e : m_leq.at(current)) {
477  if (!reached.contains(e)) {
478  if (e == second) return true;
479  reached.insert(e);
480  active.push_back(e);
481  }
482  }
483  }
484  if (m_less.contains(current)) {
485  for (const auto& e : m_less.at(current)) {
486  if (!reached.contains(e)) {
487  if (e == second) return true;
488  reached.insert(e);
489  active.push_back(e);
490  }
491  }
492  }
493  }
494  return false;
495  }
496 
497  std::optional<RootFunction> holds_transitive(RootFunction first, PolyRef poly, bool strict) const {
498  boost::container::flat_set<RootFunction> reached({first});
499  std::vector<RootFunction> active({first});
500  std::optional<RootFunction> result;
501  if (first.poly_root_above(poly)) return first.poly_root_above(poly);
502  while(!active.empty()) {
503  auto current = active.back();
504  active.pop_back();
505  if (!strict && m_leq.contains(current)) {
506  for (const auto& e : m_leq.at(current)) {
507  if (!reached.contains(e)) {
508  auto er = e.poly_root_above(poly);
509  if (er && (!result || result->poly_root_above(poly)->index > er->index)) result = e;
510  reached.insert(e);
511  active.push_back(e);
512  }
513  }
514  }
515  if (m_less.contains(current)) {
516  for (const auto& e : m_less.at(current)) {
517  if (!reached.contains(e)) {
518  auto er = e.poly_root_above(poly);
519  if (er && (!result || result->poly_root_above(poly)->index > er->index)) result = e;
520  reached.insert(e);
521  active.push_back(e);
522  }
523  }
524  }
525  }
526  return result;
527  }
528 
529  std::optional<RootFunction> holds_transitive(PolyRef poly, RootFunction second, bool strict) const {
530  boost::container::flat_set<RootFunction> reached({second});
531  std::vector<RootFunction> active({second});
532  std::optional<RootFunction> result;
533  if (second.poly_root_below(poly)) return second.poly_root_below(poly);
534  while(!active.empty()) {
535  auto current = active.back();
536  active.pop_back();
537  if (!strict && m_geq.contains(current)) {
538  for (const auto& e : m_geq.at(current)) {
539  if (!reached.contains(e)) {
540  auto er = e.poly_root_below(poly);
541  if (er && (!result || result->poly_root_below(poly)->index < er->index)) result = e;
542  reached.insert(e);
543  active.push_back(e);
544  }
545  }
546  }
547  if (m_greater.contains(current)) {
548  for (const auto& e : m_greater.at(current)) {
549  if (!reached.contains(e)) {
550  auto er = e.poly_root_below(poly);
551  if (er && (!result || result->poly_root_below(poly)->index < er->index)) result = e;
552  reached.insert(e);
553  active.push_back(e);
554  }
555  }
556  }
557  }
558  return result;
559  }
560 
561  void polys(boost::container::flat_set<PolyRef>& result) const {
562  for (const auto& pair : m_data) {
563  pair.first.polys(result);
564  pair.second.polys(result);
565  }
566  }
567 
568  boost::container::flat_set<PolyRef> polys() const {
569  boost::container::flat_set<PolyRef> result;
570  polys(result);
571  return result;
572  }
573 
574  const boost::container::flat_set<PolyRef>& polys(const PolyRef p) const {
575  return m_poly_pairs.at(p);
576  }
577 
578  bool has_pair(const PolyRef p1, const PolyRef p2) const {
579  auto it = m_poly_pairs.find(p1);
580  if (it == m_poly_pairs.end()) return false;
581  return it->second.find(p2) != it->second.end();
582  }
583 
584  void set_projective() {
585  m_is_projective = true;
586  }
587 
588  bool is_projective() const {
589  return m_is_projective;
590  }
591 };
592 inline std::ostream& operator<<(std::ostream& os, const IndexedRootOrdering& data) {
593  os << data.data();
594  return os;
595 }
596 
597 }
Bound type of a SymbolicInterval.
Definition: roots.h:205
static Bound strict(RootFunction value)
Definition: roots.h:215
std::optional< RootFunction > m_value
Definition: roots.h:208
bool operator!=(const Bound &other) const
Definition: roots.h:243
Bound(Type type, std::optional< RootFunction > value)
Definition: roots.h:209
static Bound weak(RootFunction value)
Definition: roots.h:218
const RootFunction & value() const
Definition: roots.h:231
bool operator==(const Bound &other) const
Definition: roots.h:239
Describes a covering of the real line by SymbolicIntervals (given an appropriate sample).
Definition: roots.h:342
std::vector< SymbolicInterval > m_data
Definition: roots.h:343
void add(const SymbolicInterval &c)
Add a SymbolicInterval to the covering.
Definition: roots.h:357
Describes an ordering of IndexedRoots.
Definition: roots.h:400
void add_eq(RootFunction first, RootFunction second)
Definition: roots.h:449
void add_leq(RootFunction first, RootFunction second)
Definition: roots.h:420
std::optional< SymbolicInterval > biggest_cell_wrt
Definition: roots.h:418
boost::container::flat_map< RootFunction, boost::container::flat_set< RootFunction > > m_leq
Definition: roots.h:401
boost::container::flat_set< PolyRef > polys() const
Definition: roots.h:568
void polys(boost::container::flat_set< PolyRef > &result) const
Definition: roots.h:561
boost::container::flat_map< datastructures::PolyRef, boost::container::flat_set< datastructures::PolyRef > > m_poly_pairs
Definition: roots.h:408
boost::container::flat_map< RootFunction, boost::container::flat_set< RootFunction > > m_less
Definition: roots.h:403
std::vector< IndexedRootRelation > m_data
Definition: roots.h:406
boost::container::flat_map< RootFunction, boost::container::flat_set< RootFunction > > m_geq
Definition: roots.h:402
void add_less(RootFunction first, RootFunction second)
Definition: roots.h:435
bool holds_transitive(RootFunction first, RootFunction second, bool strict) const
Definition: roots.h:468
boost::container::flat_map< RootFunction, boost::container::flat_set< RootFunction > > m_greater
Definition: roots.h:404
std::optional< RootFunction > holds_transitive(PolyRef poly, RootFunction second, bool strict) const
Definition: roots.h:529
bool has_pair(const PolyRef p1, const PolyRef p2) const
Definition: roots.h:578
std::optional< RootFunction > holds_transitive(RootFunction first, PolyRef poly, bool strict) const
Definition: roots.h:497
const boost::container::flat_set< PolyRef > & polys(const PolyRef p) const
Definition: roots.h:574
void add_poly_pair(PolyRef p1, PolyRef p2)
Definition: roots.h:412
boost::container::flat_set< PolyRef > polys() const
Definition: roots.h:136
void polys(boost::container::flat_set< PolyRef > &result) const
Definition: roots.h:126
const CompoundMinMax & cminmax() const
Definition: roots.h:118
const IndexedRoot & root() const
Definition: roots.h:117
std::variant< IndexedRoot, CompoundMinMax, CompoundMaxMin > m_data
Definition: roots.h:108
std::optional< IndexedRoot > poly_root_above(const PolyRef poly) const
Definition: roots.h:173
const CompoundMaxMin & cmaxmin() const
Definition: roots.h:119
std::optional< IndexedRoot > poly_root_below(const PolyRef poly) const
Definition: roots.h:161
bool has_poly(const PolyRef poly) const
Definition: roots.h:142
A symbolic interal whose bounds are defined by indexed root expressions.
Definition: roots.h:250
const auto & lower() const
Return the lower bound.
Definition: roots.h:285
SymbolicInterval(Bound lower, Bound upper)
Constructs an interval with arbitrary bounds.
Definition: roots.h:262
boost::container::flat_set< PolyRef > polys() const
Definition: roots.h:305
void polys(boost::container::flat_set< PolyRef > &result) const
Definition: roots.h:296
SymbolicInterval(IndexedRoot root)
Constructs a section.
Definition: roots.h:258
const auto & upper() const
Returns the upper bound.
Definition: roots.h:292
const IndexedRoot & section_defining() const
In case of a section, the defining indexed root is returned.
Definition: roots.h:277
Main datastructures.
Definition: delineation.h:9
bool operator==(const TaggedIndexedRoot &lhs, const TaggedIndexedRoot &rhs)
Definition: delineation.h:24
std::ostream & operator<<(std::ostream &os, const TaggedIndexedRoot &data)
Definition: delineation.h:17
bool operator==(const IndexedRootRelation &lhs, const IndexedRootRelation &rhs)
Definition: roots.h:382
std::ostream & operator<<(std::ostream &os, const IndexedRootOrdering &data)
Definition: roots.h:592
bool operator<(const IndexedRootRelation &lhs, const IndexedRootRelation &rhs)
Definition: roots.h:385
bool operator<(const TaggedIndexedRoot &lhs, const TaggedIndexedRoot &rhs)
Definition: delineation.h:27
bool operator!=(const RootFunction &lhs, const RootFunction &rhs)
Definition: roots.h:195
bool operator!=(const PolyRef &lhs, const PolyRef &rhs)
Definition: polynomials.h:30
Polynomial::RootType RAN
Definition: common.h:24
QuantifierType type(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Definition: QEQuery.h:39
Represents the maximum function of the contained indexed root functions.
Definition: roots.h:82
std::optional< PiecewiseLinearInfo > bounds
Definition: roots.h:91
void polys(boost::container::flat_set< PolyRef > &result) const
Definition: roots.h:84
std::vector< std::vector< IndexedRoot > > roots
Definition: roots.h:83
Represents the minimum function of the contained indexed root functions.
Definition: roots.h:54
void polys(boost::container::flat_set< PolyRef > &result) const
Definition: roots.h:56
std::optional< PiecewiseLinearInfo > bounds
Definition: roots.h:63
std::vector< std::vector< IndexedRoot > > roots
Definition: roots.h:55
Represents the i-th root of a multivariate polynomial at its main variable (given an appropriate samp...
Definition: roots.h:15
PolyRef poly
A multivariate polynomial.
Definition: roots.h:17
size_t index
The index, must be > 0.
Definition: roots.h:19
std::vector< std::pair< Rational, IndexedRoot > > bounds
List of intersection points and linear bounds which are active beginning from including the given int...
Definition: roots.h:41
bool poly_bound_at(const PolyRef &poly, const RAN &r) const
Definition: roots.h:43
IndexedRoot first
Active linear bound from -oo to including the first intersection point (or oo if no such point exists...
Definition: roots.h:39