5 #include "boost/container/flat_set.hpp"
6 #include "boost/container/flat_map.hpp"
10 using carl::operator<<;
33 os <<
"root(" << data.
poly <<
", " << data.
index <<
")";
41 std::vector<std::pair<Rational,IndexedRoot>>
bounds;
46 while(it+1 !=
bounds.end() && r < (it+1)->first) it++;
47 return it->second.poly == poly;
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) {
63 std::optional<PiecewiseLinearInfo>
bounds;
75 os <<
"min-max(" << data.
roots <<
")";
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) {
91 std::optional<PiecewiseLinearInfo>
bounds;
100 return !(lhs == rhs);
103 os <<
"max-min(" << data.
roots <<
")";
108 std::variant<IndexedRoot, CompoundMinMax, CompoundMaxMin>
m_data;
114 bool is_root()
const {
return std::holds_alternative<IndexedRoot>(
m_data); }
127 if (std::holds_alternative<IndexedRoot>(
m_data)) {
129 }
else if (std::holds_alternative<CompoundMinMax>(
m_data)) {
131 }
else if (std::holds_alternative<CompoundMaxMin>(
m_data)) {
136 boost::container::flat_set<PolyRef>
polys()
const {
137 boost::container::flat_set<PolyRef>
result;
147 return std::find_if(roots.begin(), roots.end(), [&poly](const auto& root) { return root.poly == poly;}) !=
roots.end();
152 return std::find_if(roots.begin(), roots.end(), [&poly](const auto& root) { return root.poly == poly;}) !=
roots.end();
162 if (is_root() && root().poly == poly) {
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();
174 if (is_root() && root().poly == poly) {
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();
196 return !(lhs == rhs);
206 enum class Type { infty, strict, weak };
213 return Bound(Type::infty, std::nullopt);
216 return Bound(Type::strict, value);
219 return Bound(Type::weak, value);
223 return m_type == Type::infty;
226 return m_type == Type::strict;
229 return m_type == Type::weak;
236 if (is_strict()) m_type = Type::weak;
244 return !(*
this == other);
271 return m_lower == m_upper && m_lower.
is_weak();
278 assert(is_section());
305 boost::container::flat_set<PolyRef>
polys()
const {
306 boost::container::flat_set<PolyRef>
result;
320 if (data.
lower().is_infty()) {
322 }
else if (data.
lower().is_weak()) {
323 os <<
"[" << data.
lower().value();
324 }
else if (data.
lower().is_strict()) {
325 os <<
"(" << data.
lower().value();
328 if (data.
upper().is_infty()) {
330 }
else if (data.
upper().is_weak()) {
331 os << data.
upper().value() <<
"]";
332 }
else if (data.
upper().is_strict()) {
333 os << data.
upper().value() <<
")";
360 assert(m_data.empty() || m_data.back().is_section() || !m_data.back().upper().is_infty());
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;
408 boost::container::flat_map<datastructures::PolyRef, boost::container::flat_set<datastructures::PolyRef>>
m_poly_pairs;
410 bool m_is_projective =
false;
413 m_poly_pairs.try_emplace(p1).first->second.insert(p2);
414 m_poly_pairs.try_emplace(p2).first->second.insert(p1);
422 if (first != second) {
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);
437 assert(first != second);
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);
451 if (first == second)
return;
452 add_leq(first, second);
453 add_leq(second, first);
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();
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;
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;
498 boost::container::flat_set<RootFunction> reached({first});
499 std::vector<RootFunction> active({first});
500 std::optional<RootFunction>
result;
502 while(!active.empty()) {
503 auto current = active.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);
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);
530 boost::container::flat_set<RootFunction> reached({second});
531 std::vector<RootFunction> active({second});
532 std::optional<RootFunction>
result;
534 while(!active.empty()) {
535 auto current = active.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);
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);
562 for (
const auto& pair : m_data) {
564 pair.second.polys(
result);
568 boost::container::flat_set<PolyRef>
polys()
const {
569 boost::container::flat_set<PolyRef>
result;
574 const boost::container::flat_set<PolyRef>&
polys(
const PolyRef p)
const {
575 return m_poly_pairs.at(p);
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();
585 m_is_projective =
true;
589 return m_is_projective;
Bound type of a SymbolicInterval.
static Bound strict(RootFunction value)
std::optional< RootFunction > m_value
bool operator!=(const Bound &other) const
Bound(Type type, std::optional< RootFunction > value)
static Bound weak(RootFunction value)
const RootFunction & value() const
bool operator==(const Bound &other) const
Describes a covering of the real line by SymbolicIntervals (given an appropriate sample).
std::vector< SymbolicInterval > m_data
const auto & cells() const
void add(const SymbolicInterval &c)
Add a SymbolicInterval to the covering.
Describes an ordering of IndexedRoots.
void add_eq(RootFunction first, RootFunction second)
void add_leq(RootFunction first, RootFunction second)
std::optional< SymbolicInterval > biggest_cell_wrt
const auto & data() const
boost::container::flat_map< RootFunction, boost::container::flat_set< RootFunction > > m_leq
boost::container::flat_set< PolyRef > polys() const
void polys(boost::container::flat_set< PolyRef > &result) const
boost::container::flat_map< datastructures::PolyRef, boost::container::flat_set< datastructures::PolyRef > > m_poly_pairs
boost::container::flat_map< RootFunction, boost::container::flat_set< RootFunction > > m_less
std::vector< IndexedRootRelation > m_data
boost::container::flat_map< RootFunction, boost::container::flat_set< RootFunction > > m_geq
void add_less(RootFunction first, RootFunction second)
bool holds_transitive(RootFunction first, RootFunction second, bool strict) const
boost::container::flat_map< RootFunction, boost::container::flat_set< RootFunction > > m_greater
bool is_projective() const
std::optional< RootFunction > holds_transitive(PolyRef poly, RootFunction second, bool strict) const
bool has_pair(const PolyRef p1, const PolyRef p2) const
std::optional< RootFunction > holds_transitive(RootFunction first, PolyRef poly, bool strict) const
const boost::container::flat_set< PolyRef > & polys(const PolyRef p) const
void add_poly_pair(PolyRef p1, PolyRef p2)
boost::container::flat_set< PolyRef > polys() const
void polys(boost::container::flat_set< PolyRef > &result) const
const CompoundMinMax & cminmax() const
RootFunction(CompoundMaxMin &&data)
RootFunction(IndexedRoot data)
const auto & roots() const
const IndexedRoot & root() const
std::variant< IndexedRoot, CompoundMinMax, CompoundMaxMin > m_data
std::optional< IndexedRoot > poly_root_above(const PolyRef poly) const
const CompoundMaxMin & cmaxmin() const
RootFunction(CompoundMinMax &&data)
std::optional< IndexedRoot > poly_root_below(const PolyRef poly) const
bool has_poly(const PolyRef poly) const
A symbolic interal whose bounds are defined by indexed root expressions.
const auto & lower() const
Return the lower bound.
SymbolicInterval(Bound lower, Bound upper)
Constructs an interval with arbitrary bounds.
boost::container::flat_set< PolyRef > polys() const
void polys(boost::container::flat_set< PolyRef > &result) const
SymbolicInterval(IndexedRoot root)
Constructs a section.
const auto & upper() const
Returns the upper bound.
const IndexedRoot & section_defining() const
In case of a section, the defining indexed root is returned.
SymbolicInterval()
Constructs (-oo, oo).
bool operator==(const TaggedIndexedRoot &lhs, const TaggedIndexedRoot &rhs)
std::ostream & operator<<(std::ostream &os, const TaggedIndexedRoot &data)
bool operator==(const IndexedRootRelation &lhs, const IndexedRootRelation &rhs)
std::ostream & operator<<(std::ostream &os, const IndexedRootOrdering &data)
bool operator<(const IndexedRootRelation &lhs, const IndexedRootRelation &rhs)
bool operator<(const TaggedIndexedRoot &lhs, const TaggedIndexedRoot &rhs)
bool operator!=(const RootFunction &lhs, const RootFunction &rhs)
bool operator!=(const PolyRef &lhs, const PolyRef &rhs)
QuantifierType type(const std::pair< QuantifierType, std::vector< carl::Variable >> &p)
Represents the maximum function of the contained indexed root functions.
std::optional< PiecewiseLinearInfo > bounds
void polys(boost::container::flat_set< PolyRef > &result) const
std::vector< std::vector< IndexedRoot > > roots
Represents the minimum function of the contained indexed root functions.
void polys(boost::container::flat_set< PolyRef > &result) const
std::optional< PiecewiseLinearInfo > bounds
std::vector< std::vector< IndexedRoot > > roots
A relation between two roots.
Represents the i-th root of a multivariate polynomial at its main variable (given an appropriate samp...
PolyRef poly
A multivariate polynomial.
IndexedRoot(PolyRef p, size_t i)
size_t index
The index, must be > 0.
std::vector< std::pair< Rational, IndexedRoot > > bounds
List of intersection points and linear bounds which are active beginning from including the given int...
bool poly_bound_at(const PolyRef &poly, const RAN &r) const
IndexedRoot first
Active linear bound from -oo to including the first intersection point (or oo if no such point exists...