carl  24.04
Computer ARithmetic Library
Contractor.h
Go to the documentation of this file.
1 #pragma once
2 
9 
10 #include <algorithm>
11 
12 
13 namespace carl {
14 namespace contractor {
15 
16 /**
17  * Represents a contraction operation of the form
18  *
19  * mRoot'th root of (mNumerator / mDenominator)
20  */
21 template<typename Polynomial>
22 class Evaluation {
23 private:
25  Polynomial mNumerator;
26  Polynomial mDenominator;
27  std::size_t mRoot;
28  std::vector<Variable> mDependees;
29 
30  bool make_integer() const {
31  return mVar.type() == VariableType::VT_INT;
32  }
33 
34  template<typename Number>
35  void add_root(const Interval<Number>& i, std::vector<Interval<Number>>& result) const {
36  if (mRoot == 1) {
37  result.emplace_back(i);
38  return;
39  }
40  auto tmp = i.root(static_cast<int>(mRoot));
41  CARL_LOG_DEBUG("carl.contractor", mRoot << "th root: " << tmp);
42  if (make_integer()) {
43  tmp = tmp.integral_part();
44  CARL_LOG_DEBUG("carl.contractor", "Strictening for integer: " << tmp);
45  }
46  if (tmp.is_empty()) {
47  CARL_LOG_DEBUG("carl.contractor", "Is empty.");
48  return;
49  }
50  if (mRoot % 2 == 0) {
51  // Also consider the negative part
52  Interval<Number> resA;
53  Interval<Number> resB;
54  if (set_union(tmp, -tmp, resA, resB)) {
55  CARL_LOG_DEBUG("carl.contractor", mRoot << "th root of " << i << " -> " << resA << " / " << resB);
56  result.emplace_back(resA);
57  result.emplace_back(resB);
58  } else {
59  CARL_LOG_DEBUG("carl.contractor", mRoot << "th root of " << i << " -> " << resA);
60  result.emplace_back(resA);
61  }
62  } else {
63  CARL_LOG_DEBUG("carl.contractor", mRoot << "th root of " << i << " -> " << tmp);
64  result.emplace_back(tmp);
65  }
66  }
67  public:
68  template<typename Number>
69  void normalize(std::vector<Interval<Number>>& intervals) const {
70  if (intervals.empty()) return;
71  CARL_LOG_DEBUG("carl.contractor", "From " << intervals);
72  std::sort(intervals.begin(), intervals.end(),
73  [](const auto& lhs, const auto& rhs) {
74  return lhs.lower() < rhs.lower();
75  }
76  );
77  std::size_t last = 0;
78  for (std::size_t i = 1; i < intervals.size(); ++i) {
79  if (set_have_intersection(intervals[last], intervals[i])) {
81  CARL_LOG_DEBUG("carl.contractor", "Combining " << intervals[last] << " and " << intervals[i]);
82  bool res = set_union(intervals[last], intervals[i], intervals[last], dummy);
83  assert(!res);
84  } else {
85  ++last;
86  }
87  }
88  intervals.resize(last + 1);
89  CARL_LOG_DEBUG("carl.contractor", "-> " << intervals);
90  }
91 public:
92  Evaluation(const Polynomial& p, Variable v):
93  mVar(v)
94  {
95  assert(p.has(v));
96  mRoot = p.degree(v);
97  for (const auto& t: p) {
98  if (t.monomial() && t.monomial()->exponent_of_variable(v) == mRoot) {
99  mDenominator += t.drop_variable(v);
100  } else {
101  mNumerator -= t;
102  }
103  }
104  CARL_LOG_DEBUG("carl.contractor", p << " with " << v << " -> " << *this);
105  carlVariables vars;
108  mDependees = vars.as_vector();
109  }
110 
111  auto var() const {
112  return mVar;
113  }
114  const auto& numerator() const {
115  return mNumerator;
116  }
117  const auto& denominator() const {
118  return mDenominator;
119  }
120  auto root() const {
121  return mRoot;
122  }
123  const auto& dependees() const {
124  return mDependees;
125  }
126 
127  /**
128  * Evaluate this contraction over the given assignment.
129  * Returns a list of resulting intervals.
130  *
131  * Allows to integrate a relation symbol as follows:
132  * - Transform relation into an interval (e.g. < 0 to = (-oo, 0))
133  * - Transform constraint to equality (e.g. p*x - q < 0 to p*x - q = h)
134  * - Evaluate with respect to interval h (e.g. x = (q + h) / p)
135  */
136  template<typename Number>
137  std::vector<Interval<Number>> evaluate(const std::map<Variable, Interval<Number>>& assignment, const Interval<Number>& h = Interval<Number>(0,0)) const {
138  std::vector<Interval<Number>> res;
139  CARL_LOG_DEBUG("carl.contractor", "Evaluating on " << assignment);
140  auto num = carl::evaluate(numerator(), assignment);
141  CARL_LOG_DEBUG("carl.contractor", numerator() << " -> " << num);
142  num += h;
143  CARL_LOG_DEBUG("carl.contractor", "Subtracting " << h << " -> " << num);
144  if (!is_one(denominator())) {
145  auto den = carl::evaluate(denominator(), assignment);;
146  CARL_LOG_DEBUG("carl.contractor", denominator() << " -> " << den);
147  Interval<Number> resA;
148  Interval<Number> resB;
149  if (num.div_ext(den, resA, resB)) {
150  Interval<Number> resC;
151  Interval<Number> resD;
152  if (set_union(resA, resB, resC, resD)) {
153  CARL_LOG_DEBUG("carl.contractor", "Got a split -> " << resC << " and " << resD);
154  add_root(resC, res);
155  add_root(resD, res);
156  } else {
157  CARL_LOG_DEBUG("carl.contractor", "Got no split -> " << resC);
158  add_root(resC, res);
159  }
160  } else {
161  CARL_LOG_DEBUG("carl.contractor", "Got no split -> " << resA);
162  add_root(resA, res);
163  }
164  } else {
165  CARL_LOG_DEBUG("carl.contractor", "Got no denominator -> " << num);
166  add_root(num, res);
167  }
168  normalize(res);
169  CARL_LOG_DEBUG("carl.contractor", "Result: " << res);
170  return res;
171  }
172 };
173 
174 template<typename Polynomial>
175 std::ostream& operator<<(std::ostream& os, const Evaluation<Polynomial>& e) {
176  if (e.root() != 1) {
177  os << e.root() << "th root of ";
178  }
179  if (!is_one(e.denominator())) {
180  os << "(" << e.numerator() << " / " << e.denominator() << ")";
181  } else {
182  os << e.numerator();
183  }
184  return os;
185 }
186 
187 template<typename Origin, typename Polynomial, typename Number = double>
188 class Contractor {
189 private:
192  Origin mOrigin;
193 public:
195  mEvaluation(c.lhs(), v),
196  mOrigin(origin)
197  {
198  switch (c.relation()) {
199  case Relation::LESS:
201  break;
202  case Relation::LEQ:
204  break;
205  case Relation::EQ:
207  break;
208  case Relation::NEQ:
209  assert(false);
211  break;
212  case Relation::GEQ:
214  break;
215  case Relation::GREATER:
217  break;
218  }
219  }
220 
221  auto var() const {
222  return mEvaluation.var();
223  }
224  const auto& dependees() const {
225  return mEvaluation.dependees();
226  }
227  const auto& origin() const {
228  return mOrigin;
229  }
230 
231  std::vector<Interval<Number>> evaluate(const std::map<Variable, Interval<Number>>& assignment) const {
232  CARL_LOG_DEBUG("carl.contractor", "Evaluating " << mEvaluation << " on " << assignment);
233  return mEvaluation.evaluate(assignment, mRelation);
234  }
235 
236  std::vector<Interval<Number>> contract(const std::map<Variable, Interval<Number>>& assignment) const {
237  auto res = evaluate(assignment);
238  assert(assignment.find(mEvaluation.var()) != assignment.end());
239  auto cur = assignment.find(mEvaluation.var())->second;
240  CARL_LOG_DEBUG("carl.contractor", "Intersecting " << res << " with " << cur);
241 
242  std::size_t last = 0;
243  for (std::size_t i = 0; i < res.size(); ++i) {
244  auto tmp = set_intersection(res[i], cur);
245  if (!tmp.is_empty()) {
246  res[last] = tmp;
247  last++;
248  }
249  }
250  res.resize(last);
251 
252  CARL_LOG_DEBUG("carl.contractor", "-> " << res);
253  return res;
254  }
255 };
256 
257 }
258 }
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
carl is the main namespace for the library.
const dtl::enabled dummy
Definition: SFINAE.h:53
bool evaluate(const BasicConstraint< Poly > &c, const Assignment< Number > &m)
Definition: Evaluation.h:10
bool set_union(const Interval< Number > &lhs, const Interval< Number > &rhs, Interval< Number > &resA, Interval< Number > &resB)
Computes the union of two intervals (can result in two distinct intervals).
Definition: SetTheory.h:187
Interval< Number > set_intersection(const Interval< Number > &lhs, const Interval< Number > &rhs)
Intersects two intervals in a set-theoretic manner.
Definition: SetTheory.h:99
bool set_have_intersection(const Interval< Number > &lhs, const Interval< Number > &rhs)
Definition: SetTheory.h:118
@ GREATER
Definition: SignCondition.h:15
@ WEAK
the given bound is compared by a weak ordering relation
@ STRICT
the given bound is compared by a strict ordering relation
@ INFTY
the given bound is interpreted as minus or plus infinity depending on whether it is the left or the r...
void variables(const BasicConstraint< Pol > &c, carlVariables &vars)
bool is_one(const Interval< Number > &i)
Check if this interval is a point-interval containing 1.
Definition: Interval.h:1462
std::ostream & operator<<(std::ostream &os, const Evaluation< Polynomial > &e)
Definition: Contractor.h:175
Represent a polynomial (in)equality against zero.
Relation relation() const
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
constexpr VariableType type() const noexcept
Retrieves the type of the variable.
Definition: Variable.h:131
const std::vector< Variable > & as_vector() const
Definition: Variables.h:168
The class which contains the interval arithmetic including trigonometric functions.
Definition: Interval.h:134
Interval< Number > root(int deg) const
Calculates the nth root of the interval with respect to natural interval arithmetic.
Represents a contraction operation of the form.
Definition: Contractor.h:22
std::vector< Interval< Number > > evaluate(const std::map< Variable, Interval< Number >> &assignment, const Interval< Number > &h=Interval< Number >(0, 0)) const
Evaluate this contraction over the given assignment.
Definition: Contractor.h:137
void add_root(const Interval< Number > &i, std::vector< Interval< Number >> &result) const
Definition: Contractor.h:35
const auto & denominator() const
Definition: Contractor.h:117
const auto & numerator() const
Definition: Contractor.h:114
const auto & dependees() const
Definition: Contractor.h:123
std::vector< Variable > mDependees
Definition: Contractor.h:28
Evaluation(const Polynomial &p, Variable v)
Definition: Contractor.h:92
void normalize(std::vector< Interval< Number >> &intervals) const
Definition: Contractor.h:69
std::vector< Interval< Number > > contract(const std::map< Variable, Interval< Number >> &assignment) const
Definition: Contractor.h:236
Interval< Number > mRelation
Definition: Contractor.h:191
Evaluation< Polynomial > mEvaluation
Definition: Contractor.h:190
const auto & origin() const
Definition: Contractor.h:227
const auto & dependees() const
Definition: Contractor.h:224
Contractor(const Origin &origin, const BasicConstraint< Polynomial > &c, Variable v)
Definition: Contractor.h:194
std::vector< Interval< Number > > evaluate(const std::map< Variable, Interval< Number >> &assignment) const
Definition: Contractor.h:231