carl  24.04
Computer ARithmetic Library
RealRoots.cpp
Go to the documentation of this file.
1 #include "RealRoots.h"
2 
3 #ifdef USE_LIBPOLY
4 
5 #include "LPAssignment.h"
6 
7 
8 namespace carl {
9 
10 RealRootsResult<LPRealAlgebraicNumber> real_roots(
11  const LPPolynomial& polynomial,
12  const Interval<LPRealAlgebraicNumber::NumberType>& interval) {
13  CARL_LOG_DEBUG("carl.ran.libpoly", " Real roots of " << polynomial << " within " << interval);
14 
15  assert(carl::is_univariate(polynomial));
16 
17  if (carl::is_zero(polynomial)) {
18  CARL_LOG_TRACE("carl.ran.libpoly", "poly is 0 -> nullified");
20  } else if (carl::is_constant(polynomial)) {
21  CARL_LOG_TRACE("carl.ran.libpoly", "poly is constant but not zero -> no root");
23  }
24 
25  lp_upolynomial_t* upoly = lp_polynomial_to_univariate(polynomial.get_internal());
26 
27  lp_algebraic_number_t* roots = new lp_algebraic_number_t[lp_upolynomial_degree(upoly)];
28  std::size_t roots_size;
29  lp_upolynomial_roots_isolate(upoly, roots, &roots_size);
30 
31  if (roots_size == 0) {
32  delete[] roots;
33  lp_upolynomial_delete(upoly);
34  CARL_LOG_DEBUG("carl.ran.libpoly", "Poly has no roots");
36  }
37 
38  lp_interval_t* inter_poly = to_libpoly_interval(interval);
39  std::vector<LPRealAlgebraicNumber> res;
40  for (std::size_t i = 0; i < roots_size; ++i) {
41  lp_value_t tmp;
42  lp_value_construct(&tmp, LP_VALUE_ALGEBRAIC, &roots[i]);
43  if (lp_interval_contains(inter_poly, &tmp)) {
44  res.emplace_back(std::move(tmp));
45  } else {
46  lp_value_destruct(&tmp);
47  }
48  lp_algebraic_number_destruct(&roots[i]);
49  }
50 
51  lp_interval_destruct(inter_poly);
52  delete inter_poly;
53 
54  delete[] roots;
55  lp_upolynomial_delete(upoly);
56 
57  std::sort(res.begin(), res.end());
59 }
60 
61 RealRootsResult<LPRealAlgebraicNumber> real_roots(
62  const LPPolynomial& polynomial,
63  const std::map<Variable, LPRealAlgebraicNumber>& m,
64  const Interval<LPRealAlgebraicNumber::NumberType>& interval) {
65  CARL_LOG_DEBUG("carl.ran.libpoly", polynomial << " " << m << " " << interval);
66 
67  if (carl::is_univariate(polynomial)) {
68  return real_roots(polynomial, interval);
69  }
70 
71  // easy checks
72  if (carl::is_zero(polynomial)) {
73  CARL_LOG_TRACE("carl.ran.libpoly", "poly is 0 -> nullified");
75  } else if (carl::is_constant(polynomial)) {
76  CARL_LOG_TRACE("carl.ran.libpoly", "poly is constant but not zero -> no root");
78  }
79 
80  for (const auto& v : carl::variables(polynomial)) {
81  if (v != polynomial.main_var() && m.find(v) == m.end()) return RealRootsResult<LPRealAlgebraicNumber>::non_univariate_response();
82  }
83 
84  // Multivariate Polynomial
85  // build the assignment
86  Variable mainVar = polynomial.main_var();
87  auto evalMap = m;
88  evalMap.erase(mainVar);
89  lp_assignment_t& assignment = LPAssignment::getInstance().get(evalMap);
90 
91  CARL_LOG_TRACE("carl.ran.libpoly", "Call libpoly");
92  lp_value_t* roots = new lp_value_t[lp_polynomial_degree(polynomial.get_internal())];
93  std::size_t roots_size;
94  lp_polynomial_roots_isolate(polynomial.get_internal(), &assignment, roots, &roots_size);
95 
96  CARL_LOG_TRACE("carl.ran.libpoly", "Libpoly returned");
97  if (roots_size == 0) {
98  delete[] roots;
99  CARL_LOG_DEBUG("carl.ran.libpoly", " Checking for nullification -> Evaluation at " << mainVar << "= 1");
100  lp_value_t val;
101  // here we know that no value for mainVar has been set, so we can safely set it!
102  lp_value_construct_int(&val, long(1));
103  lp_assignment_set_value(&assignment, LPVariables::getInstance().lp_variable(mainVar), &val);
104  lp_value_destruct(&val);
105  auto eval_val = lp_polynomial_evaluate(polynomial.get_internal(), &assignment);
106  lp_assignment_set_value(&assignment, LPVariables::getInstance().lp_variable(mainVar), 0);
107  //CARL_LOG_DEBUG("carl.ran.libpoly", " Got eval_val " << eval_val);
108 
109  lp_value_t zero_value;
110  lp_value_construct_zero(&zero_value);
111  if (lp_value_cmp(eval_val, &zero_value) == 0) {
112  lp_value_destruct(&zero_value);
113  CARL_LOG_DEBUG("carl.ran.libpoly", "poly is 0 after substituting rational assignments -> nullified");
114  lp_value_delete(eval_val);
116  } else {
117  lp_value_destruct(&zero_value);
118  CARL_LOG_DEBUG("carl.ran.libpoly", "Poly has no roots");
119  lp_value_delete(eval_val);
121  }
122  }
123 
124  lp_interval_t* inter_poly = to_libpoly_interval(interval);
125  std::vector<LPRealAlgebraicNumber> res;
126  for (std::size_t i = 0; i < roots_size; ++i) {
127  if (lp_interval_contains(inter_poly, &roots[i])) {
128  res.emplace_back(std::move(roots[i]));
129  CARL_LOG_DEBUG("carl.ran.libpoly", " Found root " << res.back());
130  } else {
131  lp_value_destruct(&roots[i]);
132  }
133  }
134  lp_interval_destruct(inter_poly);
135  delete inter_poly;
136  delete[] roots;
137 
138  std::sort(res.begin(), res.end());
139 
141 }
142 }
143 
144 #endif
#define CARL_LOG_TRACE(channel, msg)
Definition: carl-logging.h:44
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
carl is the main namespace for the library.
bool is_constant(const ContextPolynomial< Coeff, Ordering, Policies > &p)
RealRootsResult< IntRepRealAlgebraicNumber< Number > > real_roots(const UnivariatePolynomial< Coeff > &polynomial, const Interval< Number > &interval=Interval< Number >::unbounded_interval())
Find all real roots of a univariate 'polynomial' with numeric coefficients within a given 'interval'.
Definition: RealRoots.h:25
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
void variables(const BasicConstraint< Pol > &c, carlVariables &vars)
static RealRootsResult nullified_response()
Definition: RealRoots.h:28
static RealRootsResult non_univariate_response()
Definition: RealRoots.h:31
static RealRootsResult roots_response(roots_t &&real_roots)
Definition: RealRoots.h:34
static RealRootsResult no_roots_response()
Definition: RealRoots.h:37