carl  24.04
Computer ARithmetic Library
LPRan.cpp
Go to the documentation of this file.
1 #include "LPRan.h"
2 
3 #ifdef USE_LIBPOLY
4 
5 namespace carl {
6 
7 using NumberType = LPRealAlgebraicNumber::NumberType;
8 
9 LPRealAlgebraicNumber::~LPRealAlgebraicNumber() {
10 }
11 
12 LPRealAlgebraicNumber::LPRealAlgebraicNumber() : m_content(std::make_shared<LPRealAlgebraicNumber::Content>()) {
13  lp_value_construct_zero(get_internal());
14 }
15 
16 LPRealAlgebraicNumber::LPRealAlgebraicNumber(const lp_value_t& num) : m_content(std::make_shared<LPRealAlgebraicNumber::Content>()) {
17  lp_value_construct_copy(get_internal(), &num);
18 }
19 
20 LPRealAlgebraicNumber::LPRealAlgebraicNumber(lp_value_t&& num) : m_content(std::make_shared<LPRealAlgebraicNumber::Content>()) {
21  *get_internal() = num;
22 }
23 
24 LPRealAlgebraicNumber::LPRealAlgebraicNumber(const carl::UnivariatePolynomial<NumberType>& p, const Interval<NumberType>& i) : LPRealAlgebraicNumber() {
25  CARL_LOG_DEBUG("carl.ran.libpoly", " Create from poly: " << p << " in interval: " << i);
26 
27  lp_upolynomial_t* upoly = to_libpoly_upolynomial(p);
28  lp_interval_t* inter_poly = to_libpoly_interval(i);
29 
30  lp_algebraic_number_t* roots = new lp_algebraic_number_t[lp_upolynomial_degree(upoly)];
31  std::size_t roots_size;
32  lp_upolynomial_roots_isolate(upoly, roots, &roots_size);
33 
34  bool found = false;
35  for (std::size_t i = 0; i < roots_size; ++i) {
36  lp_value_t tmp;
37  lp_value_construct(&tmp, LP_VALUE_ALGEBRAIC, &roots[i]);
38  if (lp_interval_contains(inter_poly, &tmp)) {
39  *get_internal() = tmp;
40  found = true;
41  break;
42  }
43  lp_value_destruct(&tmp);
44  }
45  assert(found);
46 
47  for (std::size_t i = 0; i < roots_size; ++i) {
48  lp_algebraic_number_destruct(&roots[i]);
49  }
50  delete[] roots;
51 
52  lp_upolynomial_delete(upoly);
53 
54  lp_interval_destruct(inter_poly);
55  delete inter_poly;
56 }
57 
58 /**
59  * Construct from NumberType (usually mpq_class)
60  */
61 LPRealAlgebraicNumber::LPRealAlgebraicNumber(const NumberType& num) : LPRealAlgebraicNumber() {
62  lp_value_construct(get_internal(), LP_VALUE_RATIONAL, (lp_rational_t*)num.get_mpq_t());
63 }
64 
65 LPRealAlgebraicNumber::LPRealAlgebraicNumber(const LPRealAlgebraicNumber& ran) : m_content(ran.m_content) {
66 }
67 LPRealAlgebraicNumber::LPRealAlgebraicNumber(LPRealAlgebraicNumber&& ran) : m_content(std::move(ran.m_content)) {
68 }
69 LPRealAlgebraicNumber& LPRealAlgebraicNumber::operator=(const LPRealAlgebraicNumber& n) {
70  m_content = n.m_content;
71  return *this;
72 }
73 LPRealAlgebraicNumber& LPRealAlgebraicNumber::operator=(LPRealAlgebraicNumber&& n) {
74  m_content = std::move(n.m_content);
75  return *this;
76 }
77 
78 /**
79  * Create from univariate polynomial and interval with correctness checks
80  */
81 LPRealAlgebraicNumber LPRealAlgebraicNumber::create_safe(const carl::UnivariatePolynomial<NumberType>& p, const Interval<NumberType>& i) {
82  return LPRealAlgebraicNumber(p, i);
83 }
84 
85 bool is_integer(const LPRealAlgebraicNumber& n) {
86  return lp_value_is_integer(n.get_internal());
87 }
88 LPRealAlgebraicNumber::NumberType integer_below(const LPRealAlgebraicNumber& n) {
89  lp_integer_t result;
90  lp_integer_construct(&result);
91  lp_value_floor(n.get_internal(), &result);
92  NumberType num = to_rational(&result) ;
93  lp_integer_destruct(&result) ;
94  return num;
95 }
96 
97 /**
98  * @return true if the interval is a point or the poly has degree 1
99  */
100 bool LPRealAlgebraicNumber::is_numeric() const {
101  return lp_value_is_rational(get_internal());
102 }
103 
104 const UnivariatePolynomial<NumberType> LPRealAlgebraicNumber::polynomial() const {
105  assert(!is_numeric());
106  return to_carl_univariate_polynomial(get_internal()->value.a.f, auxVariable);
107 }
108 
109 const Interval<NumberType> LPRealAlgebraicNumber::interval() const {
110  if (is_numeric()) {
111  return Interval<NumberType>(value());
112  } else {
113  return Interval<NumberType>(get_lower_bound(), BoundType::STRICT, get_upper_bound(), BoundType::STRICT);
114  }
115 }
116 
117 const NumberType LPRealAlgebraicNumber::get_lower_bound() const {
118  if (is_numeric()) return value();
119  else return to_rational(&get_internal()->value.a.I.a);
120 }
121 
122 const NumberType LPRealAlgebraicNumber::get_upper_bound() const {
123  if (is_numeric()) return value();
124  else return to_rational(&get_internal()->value.a.I.b);
125 }
126 
127 /**
128  * Converts to Algebraic NumberType to Number(usually mpq_class)
129  * Asserts that the interval is a point or the poly has max degree 1
130  */
131 const NumberType LPRealAlgebraicNumber::value() const {
132  assert(is_numeric());
133  lp_rational_t result;
134  lp_rational_construct(&result);
135  lp_value_get_rational(get_internal(), &result);
136  NumberType num = to_rational(&result) ;
137  lp_rational_destruct(&result) ;
138  return num;
139 }
140 
141 /**
142  * Does not change the current value, checks the sign and returns a copy or negates if necessary
143  * @return Absolute Value of the stored RAN
144  */
145 LPRealAlgebraicNumber abs(const LPRealAlgebraicNumber& n) {
146  if (n.is_numeric()) {
147  CARL_LOG_DEBUG("carl.ran.libpoly", "Algebraic NumberType abs got numeric value");
148  return LPRealAlgebraicNumber(carl::abs(n.value()));
149  }
150 
151  int sign = lp_value_sgn(n.get_internal());
152  CARL_LOG_DEBUG("carl.ran.libpoly", "Algebraic NumberType abs got sign : " << sign << " of " << n);
153 
154  if (sign >= 0) {
155  return LPRealAlgebraicNumber(n);
156  } else {
157  lp_value_t val;
158  lp_value_construct_none(&val);
159  lp_value_neg(&val, n.get_internal());
160  auto ret = LPRealAlgebraicNumber(std::move(val));
161  return ret;
162  }
163 }
164 
165 std::size_t bitsize(const LPRealAlgebraicNumber& n) {
166  if (n.is_numeric()) {
167  return carl::bitsize(n.get_lower_bound()) + carl::bitsize(n.get_upper_bound());
168  } else {
169  return carl::bitsize(n.get_lower_bound()) + carl::bitsize(n.get_upper_bound()) + lp_upolynomial_degree(n.get_internal()->value.a.f);
170  }
171 }
172 
173 Sign sgn(const LPRealAlgebraicNumber& n) {
174  return static_cast<Sign>(lp_value_sgn(n.get_internal()));
175 }
176 
177 Sign sgn(const LPRealAlgebraicNumber&, const UnivariatePolynomial<LPRealAlgebraicNumber::NumberType>&) {
178  assert(false);
179  return Sign::ZERO;
180 }
181 
182 bool contained_in(const LPRealAlgebraicNumber& n, const Interval<LPRealAlgebraicNumber::NumberType>& i) {
183  CARL_LOG_DEBUG("carl.ran.libpoly", "ran " << n << " contained in " << i);
184  lp_interval_t* inter = to_libpoly_interval(i);
185  bool res = lp_interval_contains(inter, n.get_internal());
186  lp_interval_destruct(inter);
187  delete inter;
188  return res;
189 }
190 
191 
192 /**
193  * Refine the number until the interval width is < 1 or the number is numeric (rational)
194  * NOT CONST, the number is the same, but internally might change
195  */
196 
197 void refine(const LPRealAlgebraicNumber& n) {
198  CARL_LOG_DEBUG("carl.ran.libpoly", "Refining Algebraic NumberType : " << n);
199 
200  if (n.is_numeric()) return;
201 
202  while (lp_dyadic_interval_size(&n.get_internal()->value.a.I) > 0 && !n.is_numeric()) {
203  lp_algebraic_number_refine_const(&n.get_internal()->value.a);
204  }
205  CARL_LOG_DEBUG("carl.ran.libpoly", "Finished Refining Algebraic NumberType : " << n);
206 }
207 
208 void LPRealAlgebraicNumber::refine() const {
209  carl::refine(*this);
210 }
211 
212 NumberType branching_point(const LPRealAlgebraicNumber& n) {
213  if (n.is_numeric()) return n.value();
214  refine(n);
215  lp_dyadic_rational_t res;
216  lp_dyadic_rational_construct(&res);
217  lp_algebraic_number_get_dyadic_midpoint(&n.get_internal()->value.a, &res);
218  auto result = to_rational(&res);
219  lp_dyadic_rational_destruct(&res);
220  return result;
221 }
222 
223 
224 NumberType sample_above(const LPRealAlgebraicNumber& n) {
225  CARL_LOG_DEBUG("carl.ran.libpoly", "Sampling above: " << n);
226 
227  lp_value_t inf;
228  lp_value_construct(&inf, LP_VALUE_PLUS_INFINITY, 0);
229 
230  lp_value_t res;
231  lp_value_construct_none(&res);
232  lp_value_get_value_between(n.get_internal(), true, &inf, true, &res);
233  auto val = to_rational(&res);
234  lp_value_destruct(&res);
235  return val;
236 }
237 
238 
239 NumberType sample_below(const LPRealAlgebraicNumber& n) {
240  //return carl::ceil(n.interval_int().lower()) - 1; From Ran.h
241  CARL_LOG_DEBUG("carl.ran.libpoly", "Sampling below: " << n);
242 
243  lp_value_t inf;
244  lp_value_construct(&inf, LP_VALUE_MINUS_INFINITY, 0);
245 
246  lp_value_t res;
247  lp_value_construct_none(&res);
248  lp_value_get_value_between(&inf, true, n.get_internal(), true, &res);
249  auto val = to_rational(&res);
250  lp_value_destruct(&res);
251  return val;
252 }
253 
254 
255 NumberType sample_between(const LPRealAlgebraicNumber& lower, const LPRealAlgebraicNumber& upper) {
256  CARL_LOG_DEBUG("carl.ran.libpoly", "Sampling between: " << lower << " and " << upper);
257 
258  lp_value_t res;
259  lp_value_construct_none(&res);
260  lp_value_get_value_between(lower.get_internal(), true, upper.get_internal(), true, &res);
261  auto val = to_rational(&res);
262  lp_value_destruct(&res);
263  return val;
264 }
265 
266 NumberType sample_between(const LPRealAlgebraicNumber& lower, const NumberType& upper) {
267  CARL_LOG_DEBUG("carl.ran.libpoly", "Sampling between: " << lower << " and " << upper);
268 
269  lp_value_t v_upper;
270  lp_value_construct(&v_upper, LP_VALUE_RATIONAL, upper.get_mpq_t());
271 
272  lp_value_t res;
273  lp_value_construct_none(&res);
274  lp_value_get_value_between(lower.get_internal(), true, &v_upper, true, &res);
275 
276  lp_value_destruct(&v_upper);
277 
278  auto val = to_rational(&res);
279  lp_value_destruct(&res);
280  return val;
281 }
282 
283 NumberType sample_between(const NumberType& lower, const LPRealAlgebraicNumber& upper) {
284  CARL_LOG_DEBUG("carl.ran.libpoly", "Sampling between: " << lower << " and " << upper);
285 
286  lp_value_t v_lower;
287  lp_value_construct(&v_lower, LP_VALUE_RATIONAL, lower.get_mpq_t());
288 
289  lp_value_t res;
290  lp_value_construct_none(&res);
291  lp_value_get_value_between(&v_lower, true, upper.get_internal(), true, &res);
292 
293  lp_value_destruct(&v_lower);
294 
295  auto val = to_rational(&res);
296  lp_value_destruct(&res);
297  return val;
298 }
299 
300 NumberType floor(const LPRealAlgebraicNumber& n) {
301  CARL_LOG_DEBUG("carl.ran.libpoly", "Floor of: " << n);
302  lp_integer_t val;
303  lp_integer_construct(&val);
304  lp_value_floor(n.get_internal(), &val);
305  NumberType ret = to_rational(&val);
306  lp_integer_destruct(&val) ;
307  return ret ;
308 }
309 
310 
311 NumberType ceil(const LPRealAlgebraicNumber& n) {
312  CARL_LOG_DEBUG("carl.ran.libpoly", "Ceil of: " << n);
313  lp_integer_t val;
314  lp_integer_construct(&val);
315  lp_value_ceiling(n.get_internal(), &val);
316  NumberType ret = to_rational(&val);
317  lp_integer_destruct(&val) ;
318  return ret ;
319 }
320 
321 bool compare(const LPRealAlgebraicNumber& lhs, const LPRealAlgebraicNumber& rhs, const Relation relation) {
322  if (lhs.m_content == rhs.m_content) {
323  switch (relation) {
324  case Relation::EQ:
325  case Relation::LEQ:
326  case Relation::GEQ:
327  return true;
328  case Relation::NEQ:
329  case Relation::LESS:
330  case Relation::GREATER:
331  default:
332  return false;
333  }
334  }
335 
336  int cmp = lp_value_cmp(lhs.get_internal(), rhs.get_internal());
337  switch (relation) {
338  case Relation::EQ:
339  if (cmp == 0) lhs.m_content = rhs.m_content;
340  return cmp == 0;
341  case Relation::NEQ:
342  return cmp != 0;
343  case Relation::LESS:
344  return cmp < 0;
345  case Relation::LEQ:
346  return cmp <= 0;
347  case Relation::GREATER:
348  return cmp > 0;
349  case Relation::GEQ:
350  return cmp >= 0;
351  default:
352  assert(false);
353  return false;
354  }
355 }
356 
357 
358 const carl::Variable LPRealAlgebraicNumber::auxVariable = fresh_real_variable("__r");
359 
360 
361 bool compare(const LPRealAlgebraicNumber& lhs, const NumberType& rhs, const Relation relation) {
362  int cmp = lp_value_cmp_rational(lhs.get_internal(), (lp_rational_t*)rhs.get_mpq_t());
363 
364  switch (relation) {
365  case Relation::EQ:
366  return cmp == 0;
367  case Relation::NEQ:
368  return cmp != 0;
369  case Relation::LESS:
370  return cmp < 0;
371  case Relation::LEQ:
372  return cmp <= 0;
373  case Relation::GREATER:
374  return cmp > 0;
375  case Relation::GEQ:
376  return cmp >= 0;
377  default :
378  assert(false);
379  return false ;
380  }
381 }
382 
383 
384 std::ostream& operator<<(std::ostream& os, const LPRealAlgebraicNumber& ran) {
385  char* str = lp_value_to_string(ran.get_internal());
386  os << str;
387  free(str);
388  return os;
389 }
390 
391 }
392 
393 #endif
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
std::ostream & operator<<(std::ostream &os, const GbBenchmark< C, O, P > &b)
carl is the main namespace for the library.
Interval< Number > ceil(const Interval< Number > &_in)
Method which returns the next larger integer of the passed number or the number itself,...
Definition: Interval.h:1535
Interval< Number > abs(const Interval< Number > &_in)
Method which returns the absolute value of the passed number.
Definition: Interval.h:1511
Interval< Number > floor(const Interval< Number > &_in)
Method which returns the next smaller integer of this number or the number itself,...
Definition: Interval.h:1523
const Number & branching_point(const Number &n)
Number sample_above(const Number &n)
signed compare(const BasicConstraint< Pol > &_constraintA, const BasicConstraint< Pol > &_constraintB)
Compares _constraintA with _constraintB.
Definition: Comparison.h:25
Sign
This class represents the sign of a number .
Definition: Sign.h:20
Number integer_below(const IntRepRealAlgebraicNumber< Number > &n)
Definition: Ran.h:312
Sign sgn(const Number &n)
Obtain the sign of the given number.
Definition: Sign.h:54
Variable fresh_real_variable() noexcept
Definition: VariablePool.h:198
bool contained_in(const IntRepRealAlgebraicNumber< Number > &n, const Interval< Number > &i)
Definition: Ran.h:373
bool is_integer(const Interval< Number > &n)
Definition: Interval.h:1445
@ GREATER
Definition: SignCondition.h:15
Number sample_below(const Number &n)
std::size_t bitsize(const cln::cl_I &n)
Get the bit size of the representation of a integer.
Definition: operations.h:96
Relation
Definition: Relation.h:20
Number sample_between(const Number &lower, const Number &upper)
A Variable represents an algebraic variable that can be used throughout carl.
Definition: Variable.h:85
This class represents a univariate polynomial with coefficients of an arbitrary type.