13#ifndef INCLUDE_STURM_SEQUENCE_HH
14#define INCLUDE_STURM_SEQUENCE_HH
30 template <
typename Real>
34 Eigen::Vector<Real, Eigen::Dynamic>;
87 this->m_intervals.clear();
90 this->m_sequence.clear();
91 this->m_sequence.reserve(p.
order());
92 this->m_sequence.emplace_back(p);
93 this->m_sequence.back().adjust_degree();
94 this->m_sequence.emplace_back(dp);
95 this->m_sequence.back().adjust_degree();
99 this->m_sequence[n_sequence],
102 if (r.
order() <= 0) {
105 this->m_sequence.emplace_back(-r);
109 for (
Integer i{0}; i < n_sequence; ++i) {
112 this->m_sequence[i] = q;
114 this->m_sequence.back().set_scalar(1);
122 return static_cast<Integer>(this->m_sequence.size());
130 return this->m_sequence[i];
141 Real v{this->m_sequence[0].evaluate(x)};
151 for (
Integer i{1}; i < n_poly; ++i) {
152 v = this->m_sequence[i].evaluate(x);
154 if (last_sign == -1) {
159 if (last_sign == 1) {
176 this->m_intervals.clear();
177 this->m_intervals.reserve(this->m_sequence.size());
180 this->m_a = I_0.a = a_in;
181 this->m_b = I_0.b = b_in;
186 Integer n_roots{std::abs(I_0.va - I_0.vb)};
189 if (n_roots == 1 && !I_0.a_on_root && !I_0.b_on_root) {
190 this->m_intervals.push_back(I_0);
193 I_1.a = I_1.b = I_0.a;
194 I_1.va = I_1.vb = I_0.va;
195 I_1.a_on_root = I_1.b_on_root =
true;
196 this->m_intervals.push_back(I_1);
199 I_1.a = I_1.b = I_0.b;
200 I_1.va = I_1.vb = I_0.vb;
201 I_1.a_on_root = I_1.b_on_root =
true;
202 this->m_intervals.push_back(I_1);
208 std::vector<Interval> I_stack;
210 I_stack.reserve(this->m_sequence.size());
211 I_stack.push_back(I_0);
212 while (I_stack.size() > 0) {
213 I_0 = I_stack.back();
216 n_roots = std::abs(I_0.va - I_0.vb);
221 I_0.b_on_root =
true;
222 this->m_intervals.push_back(I_0);
223 }
else if (I_0.b_on_root) {
226 I_0.a_on_root =
true;
227 this->m_intervals.push_back(I_0);
228 }
else if (n_roots == 1) {
229 this->m_intervals.push_back(I_0);
231 }
else if (std::abs(I_0.b - I_0.a) <=
232 static_cast<Real
>(10.0) *
233 std::numeric_limits<Real>::epsilon() *
234 std::max(
static_cast<Real
>(1.0),
235 std::max(std::abs(I_0.b), std::abs(I_0.a)))) {
236 I_1.a = I_1.b = I_0.a;
238 I_1.a_on_root = I_1.b_on_root =
true;
239 I_stack.push_back(I_1);
241 Real c{(I_0.a + I_0.b) /
static_cast<Real
>(2.0)};
245 if (I_0.va != vc || c_on_root || I_0.a_on_root) {
249 I_1.a_on_root = I_0.a_on_root;
252 I_1.b_on_root = c_on_root;
253 I_stack.push_back(I_1);
254 }
else if (c_on_root) {
256 I_1.a_on_root = I_1.b_on_root =
true;
258 I_stack.push_back(I_1);
259 }
else if (I_0.a_on_root) {
260 I_1.a = I_1.b = I_0.a;
261 I_1.a_on_root = I_1.b_on_root =
true;
263 I_stack.push_back(I_1);
267 if (I_0.vb != vc || I_0.b_on_root) {
271 I_1.a_on_root = c_on_root;
274 I_1.b_on_root = I_0.b_on_root;
275 I_stack.push_back(I_1);
276 }
else if (I_0.b_on_root) {
277 I_1.a = I_1.b = I_0.b;
278 I_1.a_on_root = I_1.b_on_root =
true;
280 I_stack.push_back(I_1);
286 std::sort(this->m_intervals.begin(),
287 this->m_intervals.end(),
289 return I_a.a < I_b.a;
304 Real leading_coeff{this->m_sequence[0].leading_coeff()};
305 Real bound{
static_cast<Real
>(1.0) +
306 this->m_sequence[0].cwiseAbs().maxCoeff() /
307 std::abs(leading_coeff)};
316 return static_cast<Integer>(this->m_intervals.size());
324 return this->m_intervals[i];
335 template <
typename SolveFunction>
337 auto function = std::function<Real(Real x)>([
this](Real x) {
338 return this->m_sequence[0].evaluate(x);
340 Vector roots(this->m_intervals.size());
342 bool converged{
false};
343 for (
auto &I : this->m_intervals) {
344 Real &r{roots.coeffRef(n++)};
347 }
else if (I.b_on_root) {
350 converged = solve_function(I.a, I.b, function, r);
352 converged || !verbose,
353 "Sturm::Sequence::refine_roots(...): failed at interval n = "
369 template <
typename Real>
372 os <<
"Sturm sequence" << std::endl;
374 os <<
"P_" << i <<
"(x) = " << s.
get(i) << std::endl;
379 os <<
"roots separation for interval [" << s.
a() <<
"," << s.
b() <<
"]"
381 for (
Integer i{0}; i < n; ++i) {
383 os <<
"I = [" << I.
a <<
", " << I.
b <<
"], V = [" << I.va <<
", "
384 << I.vb <<
"]" << std::endl;
#define STURM_ASSERT_WARNING(COND, MSG)
Definition Sturm.hh:52
Polynomial class.
Definition Poly.hh:28
void derivative(Poly &res) const
Compute the derivative of the polynomial.
Definition Poly.hh:285
Real normalize()
Normalize the polynomial.
Definition Poly.hh:326
Integer order() const
Get the order of the polynomial.
Definition Poly.hh:150
Sturm sequence class.
Definition Sequence.hh:31
Integer roots_number() const
Get the number of roots found.
Definition Sequence.hh:315
struct Interval { Real a; Real b; Integer va; Integer vb; bool a_on_root; bool b_on_root; } Interval
Definition Sequence.hh:35
Integer length() const
Get the length of the stored Sturm sequence.
Definition Sequence.hh:121
Real b() const
Get the upper bound of the interval containing the roots.
Definition Sequence.hh:79
Sequence(const Poly< Real > &p)
Class constructor for the Sturm sequence given a polynomial.
Definition Sequence.hh:63
Integer separate_roots()
Compute all the subintervals containing a single root in .
Definition Sequence.hh:302
void build(const Poly< Real > &p)
Given the polynomial build its Sturm sequence.
Definition Sequence.hh:86
Integer sign_variations(Real x, bool &on_root) const
Definition Sequence.hh:137
Real m_b
Definition Sequence.hh:48
const Interval & interval(Integer i) const
Definition Sequence.hh:323
Integer separate_roots(Real a_in, Real b_in)
Compute the subintervals containing a single root.
Definition Sequence.hh:175
Real a() const
Get the lower bound of the interval containing the roots.
Definition Sequence.hh:71
const Poly< Real > & get(Integer i) const
Get the -th polynomial of the stored Sturm sequence.
Definition Sequence.hh:129
Sequence()
Class constructor for the Sturm sequence.
Definition Sequence.hh:54
std::vector< Poly< Real > > m_sequence
Definition Sequence.hh:45
Eigen::Vector< Real, Eigen::Dynamic > Vector
Definition Sequence.hh:33
Vector refine_roots(SolveFunction &&solve_function, bool verbose=false)
Compute the roots in the intervals after the separation.
Definition Sequence.hh:336
std::vector< Interval > m_intervals
Definition Sequence.hh:46
Real m_a
Definition Sequence.hh:47
Namespace for the Sturm library.
Definition Sturm.hh:71
void divide(const Poly< Real > &p_1, const Poly< Real > &p_2, Poly< Real > &q, Poly< Real > &r)
Divide the polynomial.
Definition Poly.hh:724
std::ostream & operator<<(std::ostream &os, const Poly< Real > &p)
Print the polynomial on an output stream.
Definition Poly.hh:805
STURM_DEFAULT_INTEGER_TYPE Integer
The Integer type as used for the API.
Definition Sturm.hh:79