carl  24.04
Computer ARithmetic Library
VariableComparison.h
Go to the documentation of this file.
1 #pragma once
2 
4 #include <carl-arith/ran/ran.h>
11 
12 #include <optional>
13 #include <tuple>
14 #include <variant>
15 
16 #include "MultivariateRoot.h"
17 
18 
19 namespace carl {
20  /**
21  * Represent a sum type/variant of an (in)equality between a
22  * variable on the left-hand side
23  * and multivariateRoot or algebraic real on the right-hand side.
24  * This is basically a special purpose atomic SMT formula.
25  * The lhs-variable must does not appear on the rhs.
26  */
27  template<typename Poly>
29  public:
32  using RAN = typename MultivariateRoot<Poly>::RAN;
33  private:
35  std::variant<MR, RAN> m_value;
37  bool m_negated;
38  public:
39  VariableComparison(Variable v, const std::variant<MR, RAN>& value, Relation rel, bool neg): m_var(v), m_value(value), m_relation(rel), m_negated(neg) {
40  assert(!std::holds_alternative<MR>(m_value) || std::get<MR>(m_value).var() == m_var);
41  assert(!needs_context_type<Poly>::value || !std::holds_alternative<RAN>(m_value));
42  }
44  assert(value.var() == m_var);
45  if constexpr(!needs_context_type<Poly>::value) {
46  if (value.is_univariate()) {
47  // If the value of type MultivariateRoot is really just univariate, we convert it to an algebraic real.
48  auto res = evaluate(value, carl::Assignment<RAN>({}));
49  if (res) {
50  m_value = *res;
51  CARL_LOG_DEBUG("carl.multivariateroot", "Evaluated " << value << "-> " << m_value);
52  }
53  }
54  }
55 
56  }
58  static_assert(!needs_context_type<Poly>::value);
59  }
60 
61  Variable var() const {
62  return m_var;
63  }
64  Relation relation() const {
65  return m_relation;
66  }
67  bool negated() const {
68  return m_negated;
69  }
70  const std::variant<MR, RAN>& value() const {
71  return m_value;
72  }
73  std::variant<MR, RAN>& value() {
74  return m_value;
75  }
76  bool is_equality() const {
77  return negated() ? relation() == Relation::NEQ : relation() == Relation::EQ;
78  }
79 
82  }
85  }
88  else return *this;
89  }
90  };
91 
92  /**
93  * Convert this variable comparison "v < root(..)" into a simpler
94  * polynomial (in)equality against zero "p(..) < 0" if that is possible.
95  * @return std::nullopt if conversion impossible.
96  */
97  template<typename Poly, std::enable_if_t<!needs_context_type<Poly>::value, bool> = true>
98  std::optional<BasicConstraint<Poly>> as_constraint(const VariableComparison<Poly>& f) {
99  Relation rel = f.negated() ? inverse(f.relation()) : f.relation();
100  if (std::holds_alternative<typename VariableComparison<Poly>::MR>(f.value())) {
101  const auto& mr = std::get<typename VariableComparison<Poly>::MR>(f.value());
102  if (mr.poly().degree(mr.var()) != 1) return std::nullopt;
103  if (mr.k() != 1) return std::nullopt;
104  auto lcoeff = mr.poly().coeff(mr.var(), 1);
105  if (!is_constant(lcoeff)) return std::nullopt;
106  auto ccoeff = mr.poly().coeff(mr.var(), 0);
107  return BasicConstraint<Poly>(Poly(f.var()) + ccoeff / lcoeff, rel);
108  } else if (!std::get<typename VariableComparison<Poly>::RAN>(f.value()).is_numeric()) return std::nullopt;
109  else return BasicConstraint<Poly>(Poly(f.var()) - Poly(std::get<typename VariableComparison<Poly>::RAN>(f.value()).value()), rel);
110  }
111 
112  /**
113  * Convert this variable comparison "v < root(..)" into a simpler
114  * polynomial (in)equality against zero "p(..) < 0" if that is possible.
115  * @return std::nullopt if conversion impossible.
116  */
117  template<typename Poly, std::enable_if_t<needs_context_type<Poly>::value, bool> = true>
118  std::optional<BasicConstraint<Poly>> as_constraint(const VariableComparison<Poly>& f) {
119  Relation rel = f.negated() ? inverse(f.relation()) : f.relation();
120  assert (std::holds_alternative<typename VariableComparison<Poly>::MR>(f.value()));
121  const auto& mr = std::get<typename VariableComparison<Poly>::MR>(f.value());
122  assert(mr.var() == mr.poly().main_var());
123  if (mr.poly().degree() != 1) return std::nullopt;
124  if (mr.k() != 1) return std::nullopt;
125  auto lcoeff = mr.poly().lcoeff();
126  if (!is_constant(lcoeff)) return std::nullopt;
127  auto ccoeff = mr.poly().coeff(0);
128  return BasicConstraint<Poly>(Poly(mr.poly().context(), f.var())*lcoeff + ccoeff, lcoeff>0 ? rel : carl::turn_around(rel));
129  }
130 
131  /**
132  * Return a polynomial containing the lhs-variable that has a same root
133  * for the this lhs-variable as the value that rhs represent, e.g. if this
134  * variable comparison is 'v < 3' then a defining polynomial could be 'v-3',
135  * because it has the same root for variable v, i.e., v=3.
136  */
137  template<typename Poly, std::enable_if_t<!needs_context_type<Poly>::value, bool> = true>
139  if (std::holds_alternative<typename VariableComparison<Poly>::RAN>(f.value())) {
140  const auto& ran = std::get<typename VariableComparison<Poly>::RAN>(f.value());
141  if (ran.is_numeric()) return Poly(f.var()) - ran.value();
142  else return Poly(carl::replace_main_variable(ran.polynomial(), f.var()));
143  } else {
144  const auto& mr = std::get<typename VariableComparison<Poly>::MR>(f.value());
145  assert(mr.var() == f.var());
146  return mr.poly();
147  }
148  }
149 
150  template<typename Poly, std::enable_if_t<needs_context_type<Poly>::value, bool> = true>
151  Poly defining_polynomial(const VariableComparison<Poly>& f) {
152  assert (std::holds_alternative<typename VariableComparison<Poly>::MR>(f.value()));
153  const auto& mr = std::get<typename VariableComparison<Poly>::MR>(f.value());
154  assert(mr.var() == f.var());
155  return mr.poly();
156  }
157 
158  template<typename Poly>
159  boost::tribool evaluate(const VariableComparison<Poly>& f, const Assignment<typename VariableComparison<Poly>::RAN>& a, bool evaluate_non_welldef = false) {
160  typename VariableComparison<Poly>::RAN lhs;
161  if (a.find(f.var()) == a.end()) return boost::indeterminate;
162  typename VariableComparison<Poly>::RAN rhs = a.at(f.var());
163  if (std::holds_alternative<typename VariableComparison<Poly>::RAN>(f.value())) {
164  lhs = std::get<typename VariableComparison<Poly>::RAN>(f.value());
165  } else {
166  if (!evaluate_non_welldef) {
167  auto res = carl::evaluate(std::get<typename VariableComparison<Poly>::MR>(f.value()), a);
168  if (!res) return boost::indeterminate;
169  else lhs = *res;
170  } else {
171  auto vars = carl::variables(std::get<typename VariableComparison<Poly>::MR>(f.value()));
172  for (const auto& v : vars) {
173  if (a.find(v) == a.end()) return boost::indeterminate;
174  }
175  auto res = carl::evaluate(std::get<typename VariableComparison<Poly>::MR>(f.value()), a);
176  if (!res) return f.negated();
177  else lhs = *res;
178  }
179  }
180  if (!f.negated()) return evaluate(rhs, f.relation(), lhs);
181  else return !evaluate(rhs, f.relation(), lhs);
182  }
183 
184  template<typename Pol>
185  inline void variables(const VariableComparison<Pol>& f, carlVariables& vars) {
186  vars.add(f.var());
188  [&vars](const typename VariableComparison<Pol>::MR& mr) { carl::variables(mr, vars); },
189  [](const typename VariableComparison<Pol>::RAN&) {}
190  }, f.value());
191  }
192 
193  template<typename Poly>
195  return lhs.relation() == rhs.relation() && lhs.var() == rhs.var() && lhs.negated() == rhs.negated() && lhs.value() == rhs.value();
196  }
197  template<typename Poly>
199  if (lhs.negated() != rhs.negated()) return !lhs.negated();
200  if (lhs.var() != rhs.var()) return lhs.var() < rhs.var();
201  if (lhs.relation() != rhs.relation()) return lhs.relation() < rhs.relation();
202  return lhs.value() < rhs.value();
203  }
204  template<typename Poly>
205  std::ostream& operator<<(std::ostream& os, const VariableComparison<Poly>& vc) {
206  return os << "(" << vc.var() << " " << (vc.negated() ? "! " : "") << vc.relation() << " " << vc.value() << ")";
207  }
208 }
209 
210 namespace std {
211  template<typename Pol>
212  struct hash<carl::VariableComparison<Pol>> {
213  std::size_t operator()(const carl::VariableComparison<Pol>& vc) const {
214  return carl::hash_all(vc.var(), vc.value(), vc.relation(), vc.negated());
215  }
216  };
217 }
Represent a dynamic root, also known as a "root expression".
Represent a real algebraic number (RAN) in one of several ways:
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
carl is the main namespace for the library.
bool operator<(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
bool is_constant(const ContextPolynomial< Coeff, Ordering, Policies > &p)
std::ostream & operator<<(std::ostream &os, const BasicConstraint< Poly > &c)
Prints the given constraint on the given stream.
std::optional< BasicConstraint< Poly > > as_constraint(const VariableComparison< Poly > &f)
Convert this variable comparison "v < root(..)" into a simpler polynomial (in)equality against zero "...
bool evaluate(const BasicConstraint< Poly > &c, const Assignment< Number > &m)
Definition: Evaluation.h:10
UnivariatePolynomial< Coeff > replace_main_variable(const UnivariatePolynomial< Coeff > &p, Variable newVar)
Replaces the main variable in a polynomial.
void visit(const Formula< Pol > &formula, Visitor func)
Recursively calls func on every subformula.
Definition: Visit.h:12
Relation inverse(Relation r)
Inverts the given relation symbol.
Definition: Relation.h:40
bool operator==(const BasicConstraint< P > &lhs, const BasicConstraint< P > &rhs)
Relation turn_around(Relation r)
Turns around the given relation symbol, in the sense that LESS (LEQ) and GREATER (GEQ) are swapped.
Definition: Relation.h:58
Poly defining_polynomial(const VariableComparison< Poly > &f)
Return a polynomial containing the lhs-variable that has a same root for the this lhs-variable as the...
std::map< Variable, T > Assignment
Definition: Common.h:13
std::size_t hash_all(Args &&... args)
Hashes an arbitrary number of values.
Definition: hash.h:71
Relation
Definition: Relation.h:20
void variables(const BasicConstraint< Pol > &c, carlVariables &vars)
auto & get(const std::string &name)
Represent a polynomial (in)equality against zero.
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
void add(Variable v)
Definition: Variables.h:141
typename Poly::RootType RAN
Represent a sum type/variant of an (in)equality between a variable on the left-hand side and multivar...
VariableComparison(Variable v, const std::variant< MR, RAN > &value, Relation rel, bool neg)
const std::variant< MR, RAN > & value() const
VariableComparison resolve_negation() const
std::variant< MR, RAN > & value()
typename MultivariateRoot< Poly >::RAN RAN
typename UnderlyingNumberType< Poly >::type Number
std::variant< MR, RAN > m_value
VariableComparison(Variable v, const RAN &value, Relation rel)
VariableComparison invert_relation() const
VariableComparison(Variable v, const MR &value, Relation rel)
VariableComparison negation() const
MultivariateRoot< Poly > MR
std::size_t operator()(const carl::VariableComparison< Pol > &vc) const
T type
A type associated with the type.
Definition: typetraits.h:77