You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For polynomials with multplicities, the non-exported `Polynomials.Multroot.multroot` method can avoid some numerical issues that `roots` will have.
160
+
By design, this is not type-stable; the returned roots may be real or complex.
163
161
164
-
The `FactoredPolynomial` type stores the roots (with multiplicities) and the leading coefficent of a polynomial. In this example, the `multroot` method is used internally to identify the roots of `p` below, in the conversion from the `Polynomial` type to the `FactoredPolynomial` type:
162
+
The default `roots` function uses the eigenvalues of the
163
+
[companion](https://en.wikipedia.org/wiki/Companion_matrix) matrix for
164
+
a polynomial. This is an `𝑶(n^3)` operation.
165
165
166
-
```jldoctest
167
-
julia> p = Polynomial([24, -50, 35, -10, 1])
168
-
Polynomial(24 - 50*x + 35*x^2 - 10*x^3 + x^4)
166
+
For polynomials with `BigFloat` coefficients, the
167
+
`GenericLinearAlgebra` package can be seamlessly used:
168
+
169
+
```
170
+
julia> p = fromroots(Polynomial{BigFloat}, [1,2,3])
171
+
Polynomial(-6.0 + 11.0*x - 6.0*x^2 + 1.0*x^3)
172
+
173
+
julia> roots(p)
174
+
ERROR: MethodError: no method matching eigvals!(::Matrix{BigFloat})
* The [Hecke](https://github.com/thofma/Hecke.jl/tree/master/src) package has a `roots` function. The `Hecke` package utilizes the `Arb` library for performant, high-precision numbers:
246
+
247
+
```
248
+
julia> import Hecke # import as `roots` conflicts
249
+
250
+
julia> Qx, x = Hecke.PolynomialRing(Hecke.QQ)
251
+
(Univariate Polynomial Ring in x over Rational Field, x)
252
+
253
+
julia> q = (x-1)*(x-2)*(x-3)
254
+
x^3 - 6*x^2 + 11*x - 6
255
+
256
+
julia> Hecke.roots(q)
257
+
3-element Vector{Nemo.fmpq}:
258
+
2
259
+
1
260
+
3
261
+
```
262
+
263
+
This next polynomial has 3 real roots, 2 of which are in a cluster; `Hecke` quickly identifies them:
264
+
265
+
```
266
+
julia> p = -1 + 254*x - 16129*x^2 + 1*x^17
267
+
x^17 - 16129*x^2 + 254*x - 1
268
+
269
+
julia> filter(isreal, Hecke._roots(p, 200)) # `_roots` not `roots`
To find just the real roots of a polynomial with real coefficients there are a few additional options to solving for all the roots and filtering by `isreal`.
The output is a set of intervals. Those flagged with `:unique` are guaranteed to contain a unique root.
303
+
304
+
* The `RealPolynomialRoots` package provides a function `ANewDsc` to find isolating intervals for the roots of a square-free polynomial, specified through its coefficients:
305
+
306
+
```
307
+
julia> using RealPolynomialRoots
308
+
309
+
julia> st = ANewDsc(coeffs(p))
310
+
There were 3 isolating intervals found:
311
+
[2.62…, 3.62…]₂₅₆
312
+
[1.5…, 2.62…]₂₅₆
313
+
[-0.50…, 1.5…]₂₅₆
314
+
```
315
+
316
+
These isolating intervals can be refined to find numeric estimates for the roots over `BigFloat` values.
317
+
318
+
```
319
+
julia> refine_roots(st)
320
+
3-element Vector{BigFloat}:
321
+
2.99999999999999999999...
322
+
2.00000000000000000000...
323
+
1.00000000000000000000...
324
+
```
325
+
326
+
This specialized algorithm can identify very nearby roots. For example, returning to this Mignotte-type polynomial:
327
+
328
+
```
329
+
julia> p = SparsePolynomial(Dict(0=>-1, 1=>254, 2=>-16129, 17=>1))
For this example, `filter(isreal, Hecke._roots(p))` also isolates the three real roots, but not quite as quickly.
354
+
355
+
----
356
+
357
+
Most of the root finding algorithms have issues when the roots have
358
+
multiplicities. For example, both `ANewDsc` and `Hecke.roots` assume a
359
+
square free polynomial. For non-square free polynomials:
360
+
361
+
* The `Polynomials.Multroot.multroot` function is available (version v"1.2" or greater) for finding the roots of a polynomial and their multiplicities. This is based on work of Zeng.
362
+
363
+
Here we see `IntervalRootsFindings.roots` having trouble isolating the roots due to the multiplicites:
If its basis is implicit, then a polynomial may be seen as just a vector of coefficients. Vectors or 1-based, but, for convenience, polynomial types are 0-based, for purposes of indexing (e.g. `getindex`, `setindex!`, `eachindex`). Iteration over a polynomial steps through the underlying coefficients.
478
+
If its basis is implicit, then a polynomial may be seen as just a vector of coefficients. Vectors are 1-based, but, for convenience, most polynomial types are naturally 0-based, for purposes of indexing (e.g. `getindex`, `setindex!`, `eachindex`). Iteration over a polynomial steps through the underlying coefficients.
230
479
231
480
```jldoctest
232
481
julia> as = [1,2,3,4,5]; p = Polynomial(as);
@@ -336,7 +585,7 @@ If `q` is non-constant, such as `variable(Polynomial, :y)`, then there would be
336
585
337
586
The same conversion is done for polynomial multiplication: constant polynomials are treated as numbers; non-constant polynomials must have their symbols match.
338
587
339
-
There is an oddity though the following two computations look the same, they are technically different:
588
+
There is an oddity -- though the following two computations look the same, they are technically different:
Copy file name to clipboardExpand all lines: src/common.jl
+10-4
Original file line number
Diff line number
Diff line change
@@ -168,11 +168,17 @@ _wlstsq(vand, y, W::AbstractMatrix) = qr(vand' * W * vand) \ (vand' * W * y)
168
168
"""
169
169
roots(::AbstractPolynomial; kwargs...)
170
170
171
-
Returns the rootsof the given polynomial. This is calculated via the eigenvalues of the companion matrix. The `kwargs` are passed to the `LinearAlgeebra.eigvals` call.
171
+
Returns the roots, or zeros, of the given polynomial.
172
172
173
-
!!! note
173
+
This is calculated via the eigenvalues of the companion matrix. The `kwargs` are passed to the `LinearAlgeebra.eigvals` call.
174
+
175
+
!!! Note
176
+
177
+
The default `roots` implementation is for polynomials in the
178
+
standard basis. The companion matrix approach is reasonably fast
179
+
and accurate for modest-size polynomials. However, other packages
180
+
in the `Julia` ecosystem may be of interest and are mentioned in the documentation.
174
181
175
-
The [PolynomialRoots.jl](https://github.com/giordano/PolynomialRoots.jl) package provides an alternative that is a bit faster and a bit more accurate; the [FastPolynomialRoots](https://github.com/andreasnoack/FastPolynomialRoots.jl) provides an interface to FORTRAN code implementing an algorithm that can handle very large polynomials (it is `O(n^2)` not `O(n^3)`. The [AMRVW.jl](https://github.com/jverzani/AMRVW.jl) package implements the algorithm in Julia, allowing the use of other number types.
176
182
177
183
"""
178
184
functionroots(q::AbstractPolynomial{T}; kwargs...) where {T <:Number}
0 commit comments