carl  24.04
Computer ARithmetic Library
RootBounds.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include "Degree.h"
4 
5 #include "../UnivariatePolynomial.h"
6 
7 #include <algorithm>
8 #include <numeric>
9 
10 namespace carl {
11 
12 /*
13  * Computes an upper bounds on the absolute value of the real roots of the given univariate polynomial due to Cauchy.
14  *
15  * The bound is defined as $\f 1 + \frac{\max \{ |a_0|, ..., |a_{n-1}| \}}{|a_n|} $\f where $a_n \neq 0$ is the leading coefficient.
16  * If $p = 0$, we return $0$.
17  */
18 template<typename Coeff>
20  static_assert(is_field_type<Coeff>::value, "Cauchy bounds are only defined for field-coefficients");
22 
23  auto it = std::max_element(p.coefficients().begin(), std::prev(p.coefficients().end()),
24  [](const auto& a, const auto& b){ return carl::abs(a) < carl::abs(b); }
25  );
26  return 1 + carl::abs(*it) / carl::abs(p.lcoeff());
27 }
28 
29 /*
30  * Computes an upper bounds on the absolute value of the real roots of the given univariate polynomial due to Hirst and Macey @cite Hirst1997.
31  *
32  * The bound is defined as $\f max\{ 1, (|a_0| + ... + |a_{n-1}|)/|a_n| \} $\f where $a_n \neq 0$ is the leading coefficient.
33  */
34 template<typename Coeff>
36  static_assert(is_field_type<Coeff>::value, "HirstMacey bounds are only defined for field-coefficients");
38  auto sum = std::accumulate(
39  p.coefficients().begin(),
40  std::prev(p.coefficients().end()),
42  [](const auto& a, const auto& b){
43  return static_cast<Coeff>(a + carl::abs(b));
44  }
45  );
46  return std::max(carl::constant_one<Coeff>::get(), sum / carl::abs(p.lcoeff()));
47 }
48 
49 /*
50  * Computes an upper bounds on the absolute value of the real roots of the given univariate polynomial due to Lagrange @cite Mignotte2002.
51  *
52  * The bound is defined as $\f 2 \cdot max\{ \frac{|a_0|}{|a_n|}^{1/n}, ..., \frac{|a_{n-1}|}{|a_n|}^{1} \} $\f where $a_n \neq 0$ is the leading coefficient.
53  */
54 template<typename Coeff>
56  static_assert(is_field_type<Coeff>::value, "Lagrange bounds are only defined for field-coefficients");
58 
59  Coeff max;
60  Coeff lc = carl::abs(p.lcoeff());
61  for (std::size_t i = 1; i <= p.degree(); ++i) {
62  if (carl::is_zero(p.coefficients()[p.degree()-i])) continue;
63  auto cur = carl::abs(p.coefficients()[p.degree()-i]) / lc;
64  if (i > 1) {
65  cur = carl::root_safe(cur, i).second;
66  }
67  max = std::max(max, cur);
68  }
69  return 2 * max;
70 }
71 
72 /*
73  * Computes an upper bound on the value of the positive real roots of the given univariate polynomial due to Lagrange.
74  *
75  * See https://en.wikipedia.org/wiki/Geometrical_properties_of_polynomial_roots#Other_bounds
76  *
77  * The bound is defined as $\f 2 * \max \{ \frac{-a_{n-k}}{a_n}^{1/k} \mid 1 \leq k \leq n, a_k < 0 \} $\f where $a_n > 0$ is the leading coefficient.
78  * If a_n < 0, the coefficients are multiplied by -1 as this does not change the roots. Accordingly, it is then defined as
79  * $\f 2 * \max \{ \frac{-a_{n-k}}{a_n}^{1/k} \mid 1 \leq k \leq n, a_k > 0 \} $\f where $a_n < 0$ is the leading coefficient.
80  * If the set in $\max$ is empty, then there are no positive real roots and we return $0$.
81  * If $p$ is constant, we return $0$.
82  */
83 template<typename Coeff>
85 
86  static_assert(is_field_type<Coeff>::value, "Lagrange bounds are only defined for field-coefficients");
88 
89  Coeff max;
90  Coeff lc = p.lcoeff();
91 
92  for (std::size_t i = 1; i <= p.degree(); ++i) {
93  if (carl::is_zero(p.coefficients()[p.degree()-i])) continue;
94  if (carl::is_positive(lc * p.coefficients()[p.degree()-i])) continue;
95 
96  auto cur = carl::abs(p.coefficients()[p.degree()-i]) / carl::abs(lc);
97  if (i > 1) {
98  cur = carl::root_safe(cur, i).second;
99  }
100  max = std::max(max, cur);
101  }
102  return 2 * max;
103 }
104 
105 /**
106  * Computes a lower bound on the value of the positive real roots of the given univariate polynomial.
107  *
108  * Let \f$Q(x) = x^q*P(1/x)\f$. Then \f$P(1/a) = 0 \rightarrow Q(a) = 0\f$. Thus for any b it holds
109  * \f$ (\forall a > 0, Q(a) = 0. a <= b) \rightarrow (\forall a > 0, P(a) = 0. 1/b <= a) \f$, that is,
110  * if b is an upper bound of the positive real roots of Q, then 1/b is a lower bound on the positive real roots of P.
111  * Note that the coefficients of Q are the ones of P in reverse order.
112  */
113 template<typename Coeff>
116  if (r == 0) return 0;
117  return 1/r;
118 }
119 
120 /**
121  * Computes an upper bound on the value of the negative real roots of the given univariate polynomial.
122  *
123  * Note that the positive roots of P(-x) are the negative roots of P(x).
124  *
125  */
126 template<typename Coeff>
129 }
130 
131 }
Implements utility functions concerning the (total) degree of monomials, terms and polynomials.
States if a type is a field.
Definition: typetraits.h:132
carl is the main namespace for the library.
Interval< Number > abs(const Interval< Number > &_in)
Method which returns the absolute value of the passed number.
Definition: Interval.h:1511
bool is_positive(const cln::cl_I &n)
Definition: operations.h:39
bool is_constant(const ContextPolynomial< Coeff, Ordering, Policies > &p)
std::pair< cln::cl_RA, cln::cl_RA > root_safe(const cln::cl_RA &a, uint n)
bool is_zero(const Interval< Number > &i)
Check if this interval is a point-interval containing 0.
Definition: Interval.h:1453
Coeff hirstMaceyBound(const UnivariatePolynomial< Coeff > &p)
Definition: RootBounds.h:35
Coeff lagrangePositiveUpperBound(const UnivariatePolynomial< Coeff > &p)
Definition: RootBounds.h:84
typename UnderlyingNumberType< P >::type Coeff
Coeff lagrangePositiveLowerBound(const UnivariatePolynomial< Coeff > &p)
Computes a lower bound on the value of the positive real roots of the given univariate polynomial.
Definition: RootBounds.h:114
Coeff lagrangeBound(const UnivariatePolynomial< Coeff > &p)
Definition: RootBounds.h:55
Coeff lagrangeNegativeUpperBound(const UnivariatePolynomial< Coeff > &p)
Computes an upper bound on the value of the negative real roots of the given univariate polynomial.
Definition: RootBounds.h:127
Coeff cauchyBound(const UnivariatePolynomial< Coeff > &p)
Definition: RootBounds.h:19
static const T & get()
Definition: constants.h:42
This class represents a univariate polynomial with coefficients of an arbitrary type.
const std::vector< Coefficient > & coefficients() const &
Retrieves the coefficients defining this polynomial.
const Coefficient & lcoeff() const
Returns the leading coefficient.
UnivariatePolynomial reverse_coefficients() const
Reverse coefficients safely.
uint degree() const
Get the maximal exponent of the main variable.
UnivariatePolynomial negate_variable() const
Constructs a new polynomial q such that where p is this polynomial.