Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wiseplat
GitHub Repository: wiseplat/python-code
Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/numpy/polynomial/polynomial.py
7763 views
1
"""
2
=================================================
3
Power Series (:mod:`numpy.polynomial.polynomial`)
4
=================================================
5
6
This module provides a number of objects (mostly functions) useful for
7
dealing with polynomials, including a `Polynomial` class that
8
encapsulates the usual arithmetic operations. (General information
9
on how this module represents and works with polynomial objects is in
10
the docstring for its "parent" sub-package, `numpy.polynomial`).
11
12
Classes
13
-------
14
.. autosummary::
15
:toctree: generated/
16
17
Polynomial
18
19
Constants
20
---------
21
.. autosummary::
22
:toctree: generated/
23
24
polydomain
25
polyzero
26
polyone
27
polyx
28
29
Arithmetic
30
----------
31
.. autosummary::
32
:toctree: generated/
33
34
polyadd
35
polysub
36
polymulx
37
polymul
38
polydiv
39
polypow
40
polyval
41
polyval2d
42
polyval3d
43
polygrid2d
44
polygrid3d
45
46
Calculus
47
--------
48
.. autosummary::
49
:toctree: generated/
50
51
polyder
52
polyint
53
54
Misc Functions
55
--------------
56
.. autosummary::
57
:toctree: generated/
58
59
polyfromroots
60
polyroots
61
polyvalfromroots
62
polyvander
63
polyvander2d
64
polyvander3d
65
polycompanion
66
polyfit
67
polytrim
68
polyline
69
70
See Also
71
--------
72
`numpy.polynomial`
73
74
"""
75
__all__ = [
76
'polyzero', 'polyone', 'polyx', 'polydomain', 'polyline', 'polyadd',
77
'polysub', 'polymulx', 'polymul', 'polydiv', 'polypow', 'polyval',
78
'polyvalfromroots', 'polyder', 'polyint', 'polyfromroots', 'polyvander',
79
'polyfit', 'polytrim', 'polyroots', 'Polynomial', 'polyval2d', 'polyval3d',
80
'polygrid2d', 'polygrid3d', 'polyvander2d', 'polyvander3d']
81
82
import numpy as np
83
import numpy.linalg as la
84
from numpy.core.multiarray import normalize_axis_index
85
86
from . import polyutils as pu
87
from ._polybase import ABCPolyBase
88
89
polytrim = pu.trimcoef
90
91
#
92
# These are constant arrays are of integer type so as to be compatible
93
# with the widest range of other types, such as Decimal.
94
#
95
96
# Polynomial default domain.
97
polydomain = np.array([-1, 1])
98
99
# Polynomial coefficients representing zero.
100
polyzero = np.array([0])
101
102
# Polynomial coefficients representing one.
103
polyone = np.array([1])
104
105
# Polynomial coefficients representing the identity x.
106
polyx = np.array([0, 1])
107
108
#
109
# Polynomial series functions
110
#
111
112
113
def polyline(off, scl):
114
"""
115
Returns an array representing a linear polynomial.
116
117
Parameters
118
----------
119
off, scl : scalars
120
The "y-intercept" and "slope" of the line, respectively.
121
122
Returns
123
-------
124
y : ndarray
125
This module's representation of the linear polynomial ``off +
126
scl*x``.
127
128
See Also
129
--------
130
numpy.polynomial.chebyshev.chebline
131
numpy.polynomial.legendre.legline
132
numpy.polynomial.laguerre.lagline
133
numpy.polynomial.hermite.hermline
134
numpy.polynomial.hermite_e.hermeline
135
136
Examples
137
--------
138
>>> from numpy.polynomial import polynomial as P
139
>>> P.polyline(1,-1)
140
array([ 1, -1])
141
>>> P.polyval(1, P.polyline(1,-1)) # should be 0
142
0.0
143
144
"""
145
if scl != 0:
146
return np.array([off, scl])
147
else:
148
return np.array([off])
149
150
151
def polyfromroots(roots):
152
"""
153
Generate a monic polynomial with given roots.
154
155
Return the coefficients of the polynomial
156
157
.. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),
158
159
where the ``r_n`` are the roots specified in `roots`. If a zero has
160
multiplicity n, then it must appear in `roots` n times. For instance,
161
if 2 is a root of multiplicity three and 3 is a root of multiplicity 2,
162
then `roots` looks something like [2, 2, 2, 3, 3]. The roots can appear
163
in any order.
164
165
If the returned coefficients are `c`, then
166
167
.. math:: p(x) = c_0 + c_1 * x + ... + x^n
168
169
The coefficient of the last term is 1 for monic polynomials in this
170
form.
171
172
Parameters
173
----------
174
roots : array_like
175
Sequence containing the roots.
176
177
Returns
178
-------
179
out : ndarray
180
1-D array of the polynomial's coefficients If all the roots are
181
real, then `out` is also real, otherwise it is complex. (see
182
Examples below).
183
184
See Also
185
--------
186
numpy.polynomial.chebyshev.chebfromroots
187
numpy.polynomial.legendre.legfromroots
188
numpy.polynomial.laguerre.lagfromroots
189
numpy.polynomial.hermite.hermfromroots
190
numpy.polynomial.hermite_e.hermefromroots
191
192
Notes
193
-----
194
The coefficients are determined by multiplying together linear factors
195
of the form ``(x - r_i)``, i.e.
196
197
.. math:: p(x) = (x - r_0) (x - r_1) ... (x - r_n)
198
199
where ``n == len(roots) - 1``; note that this implies that ``1`` is always
200
returned for :math:`a_n`.
201
202
Examples
203
--------
204
>>> from numpy.polynomial import polynomial as P
205
>>> P.polyfromroots((-1,0,1)) # x(x - 1)(x + 1) = x^3 - x
206
array([ 0., -1., 0., 1.])
207
>>> j = complex(0,1)
208
>>> P.polyfromroots((-j,j)) # complex returned, though values are real
209
array([1.+0.j, 0.+0.j, 1.+0.j])
210
211
"""
212
return pu._fromroots(polyline, polymul, roots)
213
214
215
def polyadd(c1, c2):
216
"""
217
Add one polynomial to another.
218
219
Returns the sum of two polynomials `c1` + `c2`. The arguments are
220
sequences of coefficients from lowest order term to highest, i.e.,
221
[1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.
222
223
Parameters
224
----------
225
c1, c2 : array_like
226
1-D arrays of polynomial coefficients ordered from low to high.
227
228
Returns
229
-------
230
out : ndarray
231
The coefficient array representing their sum.
232
233
See Also
234
--------
235
polysub, polymulx, polymul, polydiv, polypow
236
237
Examples
238
--------
239
>>> from numpy.polynomial import polynomial as P
240
>>> c1 = (1,2,3)
241
>>> c2 = (3,2,1)
242
>>> sum = P.polyadd(c1,c2); sum
243
array([4., 4., 4.])
244
>>> P.polyval(2, sum) # 4 + 4(2) + 4(2**2)
245
28.0
246
247
"""
248
return pu._add(c1, c2)
249
250
251
def polysub(c1, c2):
252
"""
253
Subtract one polynomial from another.
254
255
Returns the difference of two polynomials `c1` - `c2`. The arguments
256
are sequences of coefficients from lowest order term to highest, i.e.,
257
[1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.
258
259
Parameters
260
----------
261
c1, c2 : array_like
262
1-D arrays of polynomial coefficients ordered from low to
263
high.
264
265
Returns
266
-------
267
out : ndarray
268
Of coefficients representing their difference.
269
270
See Also
271
--------
272
polyadd, polymulx, polymul, polydiv, polypow
273
274
Examples
275
--------
276
>>> from numpy.polynomial import polynomial as P
277
>>> c1 = (1,2,3)
278
>>> c2 = (3,2,1)
279
>>> P.polysub(c1,c2)
280
array([-2., 0., 2.])
281
>>> P.polysub(c2,c1) # -P.polysub(c1,c2)
282
array([ 2., 0., -2.])
283
284
"""
285
return pu._sub(c1, c2)
286
287
288
def polymulx(c):
289
"""Multiply a polynomial by x.
290
291
Multiply the polynomial `c` by x, where x is the independent
292
variable.
293
294
295
Parameters
296
----------
297
c : array_like
298
1-D array of polynomial coefficients ordered from low to
299
high.
300
301
Returns
302
-------
303
out : ndarray
304
Array representing the result of the multiplication.
305
306
See Also
307
--------
308
polyadd, polysub, polymul, polydiv, polypow
309
310
Notes
311
-----
312
313
.. versionadded:: 1.5.0
314
315
"""
316
# c is a trimmed copy
317
[c] = pu.as_series([c])
318
# The zero series needs special treatment
319
if len(c) == 1 and c[0] == 0:
320
return c
321
322
prd = np.empty(len(c) + 1, dtype=c.dtype)
323
prd[0] = c[0]*0
324
prd[1:] = c
325
return prd
326
327
328
def polymul(c1, c2):
329
"""
330
Multiply one polynomial by another.
331
332
Returns the product of two polynomials `c1` * `c2`. The arguments are
333
sequences of coefficients, from lowest order term to highest, e.g.,
334
[1,2,3] represents the polynomial ``1 + 2*x + 3*x**2.``
335
336
Parameters
337
----------
338
c1, c2 : array_like
339
1-D arrays of coefficients representing a polynomial, relative to the
340
"standard" basis, and ordered from lowest order term to highest.
341
342
Returns
343
-------
344
out : ndarray
345
Of the coefficients of their product.
346
347
See Also
348
--------
349
polyadd, polysub, polymulx, polydiv, polypow
350
351
Examples
352
--------
353
>>> from numpy.polynomial import polynomial as P
354
>>> c1 = (1,2,3)
355
>>> c2 = (3,2,1)
356
>>> P.polymul(c1,c2)
357
array([ 3., 8., 14., 8., 3.])
358
359
"""
360
# c1, c2 are trimmed copies
361
[c1, c2] = pu.as_series([c1, c2])
362
ret = np.convolve(c1, c2)
363
return pu.trimseq(ret)
364
365
366
def polydiv(c1, c2):
367
"""
368
Divide one polynomial by another.
369
370
Returns the quotient-with-remainder of two polynomials `c1` / `c2`.
371
The arguments are sequences of coefficients, from lowest order term
372
to highest, e.g., [1,2,3] represents ``1 + 2*x + 3*x**2``.
373
374
Parameters
375
----------
376
c1, c2 : array_like
377
1-D arrays of polynomial coefficients ordered from low to high.
378
379
Returns
380
-------
381
[quo, rem] : ndarrays
382
Of coefficient series representing the quotient and remainder.
383
384
See Also
385
--------
386
polyadd, polysub, polymulx, polymul, polypow
387
388
Examples
389
--------
390
>>> from numpy.polynomial import polynomial as P
391
>>> c1 = (1,2,3)
392
>>> c2 = (3,2,1)
393
>>> P.polydiv(c1,c2)
394
(array([3.]), array([-8., -4.]))
395
>>> P.polydiv(c2,c1)
396
(array([ 0.33333333]), array([ 2.66666667, 1.33333333])) # may vary
397
398
"""
399
# c1, c2 are trimmed copies
400
[c1, c2] = pu.as_series([c1, c2])
401
if c2[-1] == 0:
402
raise ZeroDivisionError()
403
404
# note: this is more efficient than `pu._div(polymul, c1, c2)`
405
lc1 = len(c1)
406
lc2 = len(c2)
407
if lc1 < lc2:
408
return c1[:1]*0, c1
409
elif lc2 == 1:
410
return c1/c2[-1], c1[:1]*0
411
else:
412
dlen = lc1 - lc2
413
scl = c2[-1]
414
c2 = c2[:-1]/scl
415
i = dlen
416
j = lc1 - 1
417
while i >= 0:
418
c1[i:j] -= c2*c1[j]
419
i -= 1
420
j -= 1
421
return c1[j+1:]/scl, pu.trimseq(c1[:j+1])
422
423
424
def polypow(c, pow, maxpower=None):
425
"""Raise a polynomial to a power.
426
427
Returns the polynomial `c` raised to the power `pow`. The argument
428
`c` is a sequence of coefficients ordered from low to high. i.e.,
429
[1,2,3] is the series ``1 + 2*x + 3*x**2.``
430
431
Parameters
432
----------
433
c : array_like
434
1-D array of array of series coefficients ordered from low to
435
high degree.
436
pow : integer
437
Power to which the series will be raised
438
maxpower : integer, optional
439
Maximum power allowed. This is mainly to limit growth of the series
440
to unmanageable size. Default is 16
441
442
Returns
443
-------
444
coef : ndarray
445
Power series of power.
446
447
See Also
448
--------
449
polyadd, polysub, polymulx, polymul, polydiv
450
451
Examples
452
--------
453
>>> from numpy.polynomial import polynomial as P
454
>>> P.polypow([1,2,3], 2)
455
array([ 1., 4., 10., 12., 9.])
456
457
"""
458
# note: this is more efficient than `pu._pow(polymul, c1, c2)`, as it
459
# avoids calling `as_series` repeatedly
460
return pu._pow(np.convolve, c, pow, maxpower)
461
462
463
def polyder(c, m=1, scl=1, axis=0):
464
"""
465
Differentiate a polynomial.
466
467
Returns the polynomial coefficients `c` differentiated `m` times along
468
`axis`. At each iteration the result is multiplied by `scl` (the
469
scaling factor is for use in a linear change of variable). The
470
argument `c` is an array of coefficients from low to high degree along
471
each axis, e.g., [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``
472
while [[1,2],[1,2]] represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is
473
``x`` and axis=1 is ``y``.
474
475
Parameters
476
----------
477
c : array_like
478
Array of polynomial coefficients. If c is multidimensional the
479
different axis correspond to different variables with the degree
480
in each axis given by the corresponding index.
481
m : int, optional
482
Number of derivatives taken, must be non-negative. (Default: 1)
483
scl : scalar, optional
484
Each differentiation is multiplied by `scl`. The end result is
485
multiplication by ``scl**m``. This is for use in a linear change
486
of variable. (Default: 1)
487
axis : int, optional
488
Axis over which the derivative is taken. (Default: 0).
489
490
.. versionadded:: 1.7.0
491
492
Returns
493
-------
494
der : ndarray
495
Polynomial coefficients of the derivative.
496
497
See Also
498
--------
499
polyint
500
501
Examples
502
--------
503
>>> from numpy.polynomial import polynomial as P
504
>>> c = (1,2,3,4) # 1 + 2x + 3x**2 + 4x**3
505
>>> P.polyder(c) # (d/dx)(c) = 2 + 6x + 12x**2
506
array([ 2., 6., 12.])
507
>>> P.polyder(c,3) # (d**3/dx**3)(c) = 24
508
array([24.])
509
>>> P.polyder(c,scl=-1) # (d/d(-x))(c) = -2 - 6x - 12x**2
510
array([ -2., -6., -12.])
511
>>> P.polyder(c,2,-1) # (d**2/d(-x)**2)(c) = 6 + 24x
512
array([ 6., 24.])
513
514
"""
515
c = np.array(c, ndmin=1, copy=True)
516
if c.dtype.char in '?bBhHiIlLqQpP':
517
# astype fails with NA
518
c = c + 0.0
519
cdt = c.dtype
520
cnt = pu._deprecate_as_int(m, "the order of derivation")
521
iaxis = pu._deprecate_as_int(axis, "the axis")
522
if cnt < 0:
523
raise ValueError("The order of derivation must be non-negative")
524
iaxis = normalize_axis_index(iaxis, c.ndim)
525
526
if cnt == 0:
527
return c
528
529
c = np.moveaxis(c, iaxis, 0)
530
n = len(c)
531
if cnt >= n:
532
c = c[:1]*0
533
else:
534
for i in range(cnt):
535
n = n - 1
536
c *= scl
537
der = np.empty((n,) + c.shape[1:], dtype=cdt)
538
for j in range(n, 0, -1):
539
der[j - 1] = j*c[j]
540
c = der
541
c = np.moveaxis(c, 0, iaxis)
542
return c
543
544
545
def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
546
"""
547
Integrate a polynomial.
548
549
Returns the polynomial coefficients `c` integrated `m` times from
550
`lbnd` along `axis`. At each iteration the resulting series is
551
**multiplied** by `scl` and an integration constant, `k`, is added.
552
The scaling factor is for use in a linear change of variable. ("Buyer
553
beware": note that, depending on what one is doing, one may want `scl`
554
to be the reciprocal of what one might expect; for more information,
555
see the Notes section below.) The argument `c` is an array of
556
coefficients, from low to high degree along each axis, e.g., [1,2,3]
557
represents the polynomial ``1 + 2*x + 3*x**2`` while [[1,2],[1,2]]
558
represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is ``x`` and axis=1 is
559
``y``.
560
561
Parameters
562
----------
563
c : array_like
564
1-D array of polynomial coefficients, ordered from low to high.
565
m : int, optional
566
Order of integration, must be positive. (Default: 1)
567
k : {[], list, scalar}, optional
568
Integration constant(s). The value of the first integral at zero
569
is the first value in the list, the value of the second integral
570
at zero is the second value, etc. If ``k == []`` (the default),
571
all constants are set to zero. If ``m == 1``, a single scalar can
572
be given instead of a list.
573
lbnd : scalar, optional
574
The lower bound of the integral. (Default: 0)
575
scl : scalar, optional
576
Following each integration the result is *multiplied* by `scl`
577
before the integration constant is added. (Default: 1)
578
axis : int, optional
579
Axis over which the integral is taken. (Default: 0).
580
581
.. versionadded:: 1.7.0
582
583
Returns
584
-------
585
S : ndarray
586
Coefficient array of the integral.
587
588
Raises
589
------
590
ValueError
591
If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or
592
``np.ndim(scl) != 0``.
593
594
See Also
595
--------
596
polyder
597
598
Notes
599
-----
600
Note that the result of each integration is *multiplied* by `scl`. Why
601
is this important to note? Say one is making a linear change of
602
variable :math:`u = ax + b` in an integral relative to `x`. Then
603
:math:`dx = du/a`, so one will need to set `scl` equal to
604
:math:`1/a` - perhaps not what one would have first thought.
605
606
Examples
607
--------
608
>>> from numpy.polynomial import polynomial as P
609
>>> c = (1,2,3)
610
>>> P.polyint(c) # should return array([0, 1, 1, 1])
611
array([0., 1., 1., 1.])
612
>>> P.polyint(c,3) # should return array([0, 0, 0, 1/6, 1/12, 1/20])
613
array([ 0. , 0. , 0. , 0.16666667, 0.08333333, # may vary
614
0.05 ])
615
>>> P.polyint(c,k=3) # should return array([3, 1, 1, 1])
616
array([3., 1., 1., 1.])
617
>>> P.polyint(c,lbnd=-2) # should return array([6, 1, 1, 1])
618
array([6., 1., 1., 1.])
619
>>> P.polyint(c,scl=-2) # should return array([0, -2, -2, -2])
620
array([ 0., -2., -2., -2.])
621
622
"""
623
c = np.array(c, ndmin=1, copy=True)
624
if c.dtype.char in '?bBhHiIlLqQpP':
625
# astype doesn't preserve mask attribute.
626
c = c + 0.0
627
cdt = c.dtype
628
if not np.iterable(k):
629
k = [k]
630
cnt = pu._deprecate_as_int(m, "the order of integration")
631
iaxis = pu._deprecate_as_int(axis, "the axis")
632
if cnt < 0:
633
raise ValueError("The order of integration must be non-negative")
634
if len(k) > cnt:
635
raise ValueError("Too many integration constants")
636
if np.ndim(lbnd) != 0:
637
raise ValueError("lbnd must be a scalar.")
638
if np.ndim(scl) != 0:
639
raise ValueError("scl must be a scalar.")
640
iaxis = normalize_axis_index(iaxis, c.ndim)
641
642
if cnt == 0:
643
return c
644
645
k = list(k) + [0]*(cnt - len(k))
646
c = np.moveaxis(c, iaxis, 0)
647
for i in range(cnt):
648
n = len(c)
649
c *= scl
650
if n == 1 and np.all(c[0] == 0):
651
c[0] += k[i]
652
else:
653
tmp = np.empty((n + 1,) + c.shape[1:], dtype=cdt)
654
tmp[0] = c[0]*0
655
tmp[1] = c[0]
656
for j in range(1, n):
657
tmp[j + 1] = c[j]/(j + 1)
658
tmp[0] += k[i] - polyval(lbnd, tmp)
659
c = tmp
660
c = np.moveaxis(c, 0, iaxis)
661
return c
662
663
664
def polyval(x, c, tensor=True):
665
"""
666
Evaluate a polynomial at points x.
667
668
If `c` is of length `n + 1`, this function returns the value
669
670
.. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n
671
672
The parameter `x` is converted to an array only if it is a tuple or a
673
list, otherwise it is treated as a scalar. In either case, either `x`
674
or its elements must support multiplication and addition both with
675
themselves and with the elements of `c`.
676
677
If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If
678
`c` is multidimensional, then the shape of the result depends on the
679
value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +
680
x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that
681
scalars have shape (,).
682
683
Trailing zeros in the coefficients will be used in the evaluation, so
684
they should be avoided if efficiency is a concern.
685
686
Parameters
687
----------
688
x : array_like, compatible object
689
If `x` is a list or tuple, it is converted to an ndarray, otherwise
690
it is left unchanged and treated as a scalar. In either case, `x`
691
or its elements must support addition and multiplication with
692
with themselves and with the elements of `c`.
693
c : array_like
694
Array of coefficients ordered so that the coefficients for terms of
695
degree n are contained in c[n]. If `c` is multidimensional the
696
remaining indices enumerate multiple polynomials. In the two
697
dimensional case the coefficients may be thought of as stored in
698
the columns of `c`.
699
tensor : boolean, optional
700
If True, the shape of the coefficient array is extended with ones
701
on the right, one for each dimension of `x`. Scalars have dimension 0
702
for this action. The result is that every column of coefficients in
703
`c` is evaluated for every element of `x`. If False, `x` is broadcast
704
over the columns of `c` for the evaluation. This keyword is useful
705
when `c` is multidimensional. The default value is True.
706
707
.. versionadded:: 1.7.0
708
709
Returns
710
-------
711
values : ndarray, compatible object
712
The shape of the returned array is described above.
713
714
See Also
715
--------
716
polyval2d, polygrid2d, polyval3d, polygrid3d
717
718
Notes
719
-----
720
The evaluation uses Horner's method.
721
722
Examples
723
--------
724
>>> from numpy.polynomial.polynomial import polyval
725
>>> polyval(1, [1,2,3])
726
6.0
727
>>> a = np.arange(4).reshape(2,2)
728
>>> a
729
array([[0, 1],
730
[2, 3]])
731
>>> polyval(a, [1,2,3])
732
array([[ 1., 6.],
733
[17., 34.]])
734
>>> coef = np.arange(4).reshape(2,2) # multidimensional coefficients
735
>>> coef
736
array([[0, 1],
737
[2, 3]])
738
>>> polyval([1,2], coef, tensor=True)
739
array([[2., 4.],
740
[4., 7.]])
741
>>> polyval([1,2], coef, tensor=False)
742
array([2., 7.])
743
744
"""
745
c = np.array(c, ndmin=1, copy=False)
746
if c.dtype.char in '?bBhHiIlLqQpP':
747
# astype fails with NA
748
c = c + 0.0
749
if isinstance(x, (tuple, list)):
750
x = np.asarray(x)
751
if isinstance(x, np.ndarray) and tensor:
752
c = c.reshape(c.shape + (1,)*x.ndim)
753
754
c0 = c[-1] + x*0
755
for i in range(2, len(c) + 1):
756
c0 = c[-i] + c0*x
757
return c0
758
759
760
def polyvalfromroots(x, r, tensor=True):
761
"""
762
Evaluate a polynomial specified by its roots at points x.
763
764
If `r` is of length `N`, this function returns the value
765
766
.. math:: p(x) = \\prod_{n=1}^{N} (x - r_n)
767
768
The parameter `x` is converted to an array only if it is a tuple or a
769
list, otherwise it is treated as a scalar. In either case, either `x`
770
or its elements must support multiplication and addition both with
771
themselves and with the elements of `r`.
772
773
If `r` is a 1-D array, then `p(x)` will have the same shape as `x`. If `r`
774
is multidimensional, then the shape of the result depends on the value of
775
`tensor`. If `tensor is ``True`` the shape will be r.shape[1:] + x.shape;
776
that is, each polynomial is evaluated at every value of `x`. If `tensor` is
777
``False``, the shape will be r.shape[1:]; that is, each polynomial is
778
evaluated only for the corresponding broadcast value of `x`. Note that
779
scalars have shape (,).
780
781
.. versionadded:: 1.12
782
783
Parameters
784
----------
785
x : array_like, compatible object
786
If `x` is a list or tuple, it is converted to an ndarray, otherwise
787
it is left unchanged and treated as a scalar. In either case, `x`
788
or its elements must support addition and multiplication with
789
with themselves and with the elements of `r`.
790
r : array_like
791
Array of roots. If `r` is multidimensional the first index is the
792
root index, while the remaining indices enumerate multiple
793
polynomials. For instance, in the two dimensional case the roots
794
of each polynomial may be thought of as stored in the columns of `r`.
795
tensor : boolean, optional
796
If True, the shape of the roots array is extended with ones on the
797
right, one for each dimension of `x`. Scalars have dimension 0 for this
798
action. The result is that every column of coefficients in `r` is
799
evaluated for every element of `x`. If False, `x` is broadcast over the
800
columns of `r` for the evaluation. This keyword is useful when `r` is
801
multidimensional. The default value is True.
802
803
Returns
804
-------
805
values : ndarray, compatible object
806
The shape of the returned array is described above.
807
808
See Also
809
--------
810
polyroots, polyfromroots, polyval
811
812
Examples
813
--------
814
>>> from numpy.polynomial.polynomial import polyvalfromroots
815
>>> polyvalfromroots(1, [1,2,3])
816
0.0
817
>>> a = np.arange(4).reshape(2,2)
818
>>> a
819
array([[0, 1],
820
[2, 3]])
821
>>> polyvalfromroots(a, [-1, 0, 1])
822
array([[-0., 0.],
823
[ 6., 24.]])
824
>>> r = np.arange(-2, 2).reshape(2,2) # multidimensional coefficients
825
>>> r # each column of r defines one polynomial
826
array([[-2, -1],
827
[ 0, 1]])
828
>>> b = [-2, 1]
829
>>> polyvalfromroots(b, r, tensor=True)
830
array([[-0., 3.],
831
[ 3., 0.]])
832
>>> polyvalfromroots(b, r, tensor=False)
833
array([-0., 0.])
834
"""
835
r = np.array(r, ndmin=1, copy=False)
836
if r.dtype.char in '?bBhHiIlLqQpP':
837
r = r.astype(np.double)
838
if isinstance(x, (tuple, list)):
839
x = np.asarray(x)
840
if isinstance(x, np.ndarray):
841
if tensor:
842
r = r.reshape(r.shape + (1,)*x.ndim)
843
elif x.ndim >= r.ndim:
844
raise ValueError("x.ndim must be < r.ndim when tensor == False")
845
return np.prod(x - r, axis=0)
846
847
848
def polyval2d(x, y, c):
849
"""
850
Evaluate a 2-D polynomial at points (x, y).
851
852
This function returns the value
853
854
.. math:: p(x,y) = \\sum_{i,j} c_{i,j} * x^i * y^j
855
856
The parameters `x` and `y` are converted to arrays only if they are
857
tuples or a lists, otherwise they are treated as a scalars and they
858
must have the same shape after conversion. In either case, either `x`
859
and `y` or their elements must support multiplication and addition both
860
with themselves and with the elements of `c`.
861
862
If `c` has fewer than two dimensions, ones are implicitly appended to
863
its shape to make it 2-D. The shape of the result will be c.shape[2:] +
864
x.shape.
865
866
Parameters
867
----------
868
x, y : array_like, compatible objects
869
The two dimensional series is evaluated at the points `(x, y)`,
870
where `x` and `y` must have the same shape. If `x` or `y` is a list
871
or tuple, it is first converted to an ndarray, otherwise it is left
872
unchanged and, if it isn't an ndarray, it is treated as a scalar.
873
c : array_like
874
Array of coefficients ordered so that the coefficient of the term
875
of multi-degree i,j is contained in `c[i,j]`. If `c` has
876
dimension greater than two the remaining indices enumerate multiple
877
sets of coefficients.
878
879
Returns
880
-------
881
values : ndarray, compatible object
882
The values of the two dimensional polynomial at points formed with
883
pairs of corresponding values from `x` and `y`.
884
885
See Also
886
--------
887
polyval, polygrid2d, polyval3d, polygrid3d
888
889
Notes
890
-----
891
892
.. versionadded:: 1.7.0
893
894
"""
895
return pu._valnd(polyval, c, x, y)
896
897
898
def polygrid2d(x, y, c):
899
"""
900
Evaluate a 2-D polynomial on the Cartesian product of x and y.
901
902
This function returns the values:
903
904
.. math:: p(a,b) = \\sum_{i,j} c_{i,j} * a^i * b^j
905
906
where the points `(a, b)` consist of all pairs formed by taking
907
`a` from `x` and `b` from `y`. The resulting points form a grid with
908
`x` in the first dimension and `y` in the second.
909
910
The parameters `x` and `y` are converted to arrays only if they are
911
tuples or a lists, otherwise they are treated as a scalars. In either
912
case, either `x` and `y` or their elements must support multiplication
913
and addition both with themselves and with the elements of `c`.
914
915
If `c` has fewer than two dimensions, ones are implicitly appended to
916
its shape to make it 2-D. The shape of the result will be c.shape[2:] +
917
x.shape + y.shape.
918
919
Parameters
920
----------
921
x, y : array_like, compatible objects
922
The two dimensional series is evaluated at the points in the
923
Cartesian product of `x` and `y`. If `x` or `y` is a list or
924
tuple, it is first converted to an ndarray, otherwise it is left
925
unchanged and, if it isn't an ndarray, it is treated as a scalar.
926
c : array_like
927
Array of coefficients ordered so that the coefficients for terms of
928
degree i,j are contained in ``c[i,j]``. If `c` has dimension
929
greater than two the remaining indices enumerate multiple sets of
930
coefficients.
931
932
Returns
933
-------
934
values : ndarray, compatible object
935
The values of the two dimensional polynomial at points in the Cartesian
936
product of `x` and `y`.
937
938
See Also
939
--------
940
polyval, polyval2d, polyval3d, polygrid3d
941
942
Notes
943
-----
944
945
.. versionadded:: 1.7.0
946
947
"""
948
return pu._gridnd(polyval, c, x, y)
949
950
951
def polyval3d(x, y, z, c):
952
"""
953
Evaluate a 3-D polynomial at points (x, y, z).
954
955
This function returns the values:
956
957
.. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * x^i * y^j * z^k
958
959
The parameters `x`, `y`, and `z` are converted to arrays only if
960
they are tuples or a lists, otherwise they are treated as a scalars and
961
they must have the same shape after conversion. In either case, either
962
`x`, `y`, and `z` or their elements must support multiplication and
963
addition both with themselves and with the elements of `c`.
964
965
If `c` has fewer than 3 dimensions, ones are implicitly appended to its
966
shape to make it 3-D. The shape of the result will be c.shape[3:] +
967
x.shape.
968
969
Parameters
970
----------
971
x, y, z : array_like, compatible object
972
The three dimensional series is evaluated at the points
973
`(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If
974
any of `x`, `y`, or `z` is a list or tuple, it is first converted
975
to an ndarray, otherwise it is left unchanged and if it isn't an
976
ndarray it is treated as a scalar.
977
c : array_like
978
Array of coefficients ordered so that the coefficient of the term of
979
multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension
980
greater than 3 the remaining indices enumerate multiple sets of
981
coefficients.
982
983
Returns
984
-------
985
values : ndarray, compatible object
986
The values of the multidimensional polynomial on points formed with
987
triples of corresponding values from `x`, `y`, and `z`.
988
989
See Also
990
--------
991
polyval, polyval2d, polygrid2d, polygrid3d
992
993
Notes
994
-----
995
996
.. versionadded:: 1.7.0
997
998
"""
999
return pu._valnd(polyval, c, x, y, z)
1000
1001
1002
def polygrid3d(x, y, z, c):
1003
"""
1004
Evaluate a 3-D polynomial on the Cartesian product of x, y and z.
1005
1006
This function returns the values:
1007
1008
.. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * a^i * b^j * c^k
1009
1010
where the points `(a, b, c)` consist of all triples formed by taking
1011
`a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form
1012
a grid with `x` in the first dimension, `y` in the second, and `z` in
1013
the third.
1014
1015
The parameters `x`, `y`, and `z` are converted to arrays only if they
1016
are tuples or a lists, otherwise they are treated as a scalars. In
1017
either case, either `x`, `y`, and `z` or their elements must support
1018
multiplication and addition both with themselves and with the elements
1019
of `c`.
1020
1021
If `c` has fewer than three dimensions, ones are implicitly appended to
1022
its shape to make it 3-D. The shape of the result will be c.shape[3:] +
1023
x.shape + y.shape + z.shape.
1024
1025
Parameters
1026
----------
1027
x, y, z : array_like, compatible objects
1028
The three dimensional series is evaluated at the points in the
1029
Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a
1030
list or tuple, it is first converted to an ndarray, otherwise it is
1031
left unchanged and, if it isn't an ndarray, it is treated as a
1032
scalar.
1033
c : array_like
1034
Array of coefficients ordered so that the coefficients for terms of
1035
degree i,j are contained in ``c[i,j]``. If `c` has dimension
1036
greater than two the remaining indices enumerate multiple sets of
1037
coefficients.
1038
1039
Returns
1040
-------
1041
values : ndarray, compatible object
1042
The values of the two dimensional polynomial at points in the Cartesian
1043
product of `x` and `y`.
1044
1045
See Also
1046
--------
1047
polyval, polyval2d, polygrid2d, polyval3d
1048
1049
Notes
1050
-----
1051
1052
.. versionadded:: 1.7.0
1053
1054
"""
1055
return pu._gridnd(polyval, c, x, y, z)
1056
1057
1058
def polyvander(x, deg):
1059
"""Vandermonde matrix of given degree.
1060
1061
Returns the Vandermonde matrix of degree `deg` and sample points
1062
`x`. The Vandermonde matrix is defined by
1063
1064
.. math:: V[..., i] = x^i,
1065
1066
where `0 <= i <= deg`. The leading indices of `V` index the elements of
1067
`x` and the last index is the power of `x`.
1068
1069
If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the
1070
matrix ``V = polyvander(x, n)``, then ``np.dot(V, c)`` and
1071
``polyval(x, c)`` are the same up to roundoff. This equivalence is
1072
useful both for least squares fitting and for the evaluation of a large
1073
number of polynomials of the same degree and sample points.
1074
1075
Parameters
1076
----------
1077
x : array_like
1078
Array of points. The dtype is converted to float64 or complex128
1079
depending on whether any of the elements are complex. If `x` is
1080
scalar it is converted to a 1-D array.
1081
deg : int
1082
Degree of the resulting matrix.
1083
1084
Returns
1085
-------
1086
vander : ndarray.
1087
The Vandermonde matrix. The shape of the returned matrix is
1088
``x.shape + (deg + 1,)``, where the last index is the power of `x`.
1089
The dtype will be the same as the converted `x`.
1090
1091
See Also
1092
--------
1093
polyvander2d, polyvander3d
1094
1095
"""
1096
ideg = pu._deprecate_as_int(deg, "deg")
1097
if ideg < 0:
1098
raise ValueError("deg must be non-negative")
1099
1100
x = np.array(x, copy=False, ndmin=1) + 0.0
1101
dims = (ideg + 1,) + x.shape
1102
dtyp = x.dtype
1103
v = np.empty(dims, dtype=dtyp)
1104
v[0] = x*0 + 1
1105
if ideg > 0:
1106
v[1] = x
1107
for i in range(2, ideg + 1):
1108
v[i] = v[i-1]*x
1109
return np.moveaxis(v, 0, -1)
1110
1111
1112
def polyvander2d(x, y, deg):
1113
"""Pseudo-Vandermonde matrix of given degrees.
1114
1115
Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1116
points `(x, y)`. The pseudo-Vandermonde matrix is defined by
1117
1118
.. math:: V[..., (deg[1] + 1)*i + j] = x^i * y^j,
1119
1120
where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of
1121
`V` index the points `(x, y)` and the last index encodes the powers of
1122
`x` and `y`.
1123
1124
If ``V = polyvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`
1125
correspond to the elements of a 2-D coefficient array `c` of shape
1126
(xdeg + 1, ydeg + 1) in the order
1127
1128
.. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...
1129
1130
and ``np.dot(V, c.flat)`` and ``polyval2d(x, y, c)`` will be the same
1131
up to roundoff. This equivalence is useful both for least squares
1132
fitting and for the evaluation of a large number of 2-D polynomials
1133
of the same degrees and sample points.
1134
1135
Parameters
1136
----------
1137
x, y : array_like
1138
Arrays of point coordinates, all of the same shape. The dtypes
1139
will be converted to either float64 or complex128 depending on
1140
whether any of the elements are complex. Scalars are converted to
1141
1-D arrays.
1142
deg : list of ints
1143
List of maximum degrees of the form [x_deg, y_deg].
1144
1145
Returns
1146
-------
1147
vander2d : ndarray
1148
The shape of the returned matrix is ``x.shape + (order,)``, where
1149
:math:`order = (deg[0]+1)*(deg([1]+1)`. The dtype will be the same
1150
as the converted `x` and `y`.
1151
1152
See Also
1153
--------
1154
polyvander, polyvander3d, polyval2d, polyval3d
1155
1156
"""
1157
return pu._vander_nd_flat((polyvander, polyvander), (x, y), deg)
1158
1159
1160
def polyvander3d(x, y, z, deg):
1161
"""Pseudo-Vandermonde matrix of given degrees.
1162
1163
Returns the pseudo-Vandermonde matrix of degrees `deg` and sample
1164
points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,
1165
then The pseudo-Vandermonde matrix is defined by
1166
1167
.. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = x^i * y^j * z^k,
1168
1169
where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading
1170
indices of `V` index the points `(x, y, z)` and the last index encodes
1171
the powers of `x`, `y`, and `z`.
1172
1173
If ``V = polyvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns
1174
of `V` correspond to the elements of a 3-D coefficient array `c` of
1175
shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order
1176
1177
.. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...
1178
1179
and ``np.dot(V, c.flat)`` and ``polyval3d(x, y, z, c)`` will be the
1180
same up to roundoff. This equivalence is useful both for least squares
1181
fitting and for the evaluation of a large number of 3-D polynomials
1182
of the same degrees and sample points.
1183
1184
Parameters
1185
----------
1186
x, y, z : array_like
1187
Arrays of point coordinates, all of the same shape. The dtypes will
1188
be converted to either float64 or complex128 depending on whether
1189
any of the elements are complex. Scalars are converted to 1-D
1190
arrays.
1191
deg : list of ints
1192
List of maximum degrees of the form [x_deg, y_deg, z_deg].
1193
1194
Returns
1195
-------
1196
vander3d : ndarray
1197
The shape of the returned matrix is ``x.shape + (order,)``, where
1198
:math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`. The dtype will
1199
be the same as the converted `x`, `y`, and `z`.
1200
1201
See Also
1202
--------
1203
polyvander, polyvander3d, polyval2d, polyval3d
1204
1205
Notes
1206
-----
1207
1208
.. versionadded:: 1.7.0
1209
1210
"""
1211
return pu._vander_nd_flat((polyvander, polyvander, polyvander), (x, y, z), deg)
1212
1213
1214
def polyfit(x, y, deg, rcond=None, full=False, w=None):
1215
"""
1216
Least-squares fit of a polynomial to data.
1217
1218
Return the coefficients of a polynomial of degree `deg` that is the
1219
least squares fit to the data values `y` given at points `x`. If `y` is
1220
1-D the returned coefficients will also be 1-D. If `y` is 2-D multiple
1221
fits are done, one for each column of `y`, and the resulting
1222
coefficients are stored in the corresponding columns of a 2-D return.
1223
The fitted polynomial(s) are in the form
1224
1225
.. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n,
1226
1227
where `n` is `deg`.
1228
1229
Parameters
1230
----------
1231
x : array_like, shape (`M`,)
1232
x-coordinates of the `M` sample (data) points ``(x[i], y[i])``.
1233
y : array_like, shape (`M`,) or (`M`, `K`)
1234
y-coordinates of the sample points. Several sets of sample points
1235
sharing the same x-coordinates can be (independently) fit with one
1236
call to `polyfit` by passing in for `y` a 2-D array that contains
1237
one data set per column.
1238
deg : int or 1-D array_like
1239
Degree(s) of the fitting polynomials. If `deg` is a single integer
1240
all terms up to and including the `deg`'th term are included in the
1241
fit. For NumPy versions >= 1.11.0 a list of integers specifying the
1242
degrees of the terms to include may be used instead.
1243
rcond : float, optional
1244
Relative condition number of the fit. Singular values smaller
1245
than `rcond`, relative to the largest singular value, will be
1246
ignored. The default value is ``len(x)*eps``, where `eps` is the
1247
relative precision of the platform's float type, about 2e-16 in
1248
most cases.
1249
full : bool, optional
1250
Switch determining the nature of the return value. When ``False``
1251
(the default) just the coefficients are returned; when ``True``,
1252
diagnostic information from the singular value decomposition (used
1253
to solve the fit's matrix equation) is also returned.
1254
w : array_like, shape (`M`,), optional
1255
Weights. If not None, the weight ``w[i]`` applies to the unsquared
1256
residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are
1257
chosen so that the errors of the products ``w[i]*y[i]`` all have the
1258
same variance. When using inverse-variance weighting, use
1259
``w[i] = 1/sigma(y[i])``. The default value is None.
1260
1261
.. versionadded:: 1.5.0
1262
1263
Returns
1264
-------
1265
coef : ndarray, shape (`deg` + 1,) or (`deg` + 1, `K`)
1266
Polynomial coefficients ordered from low to high. If `y` was 2-D,
1267
the coefficients in column `k` of `coef` represent the polynomial
1268
fit to the data in `y`'s `k`-th column.
1269
1270
[residuals, rank, singular_values, rcond] : list
1271
These values are only returned if ``full == True``
1272
1273
- residuals -- sum of squared residuals of the least squares fit
1274
- rank -- the numerical rank of the scaled Vandermonde matrix
1275
- singular_values -- singular values of the scaled Vandermonde matrix
1276
- rcond -- value of `rcond`.
1277
1278
For more details, see `numpy.linalg.lstsq`.
1279
1280
Raises
1281
------
1282
RankWarning
1283
Raised if the matrix in the least-squares fit is rank deficient.
1284
The warning is only raised if ``full == False``. The warnings can
1285
be turned off by:
1286
1287
>>> import warnings
1288
>>> warnings.simplefilter('ignore', np.RankWarning)
1289
1290
See Also
1291
--------
1292
numpy.polynomial.chebyshev.chebfit
1293
numpy.polynomial.legendre.legfit
1294
numpy.polynomial.laguerre.lagfit
1295
numpy.polynomial.hermite.hermfit
1296
numpy.polynomial.hermite_e.hermefit
1297
polyval : Evaluates a polynomial.
1298
polyvander : Vandermonde matrix for powers.
1299
numpy.linalg.lstsq : Computes a least-squares fit from the matrix.
1300
scipy.interpolate.UnivariateSpline : Computes spline fits.
1301
1302
Notes
1303
-----
1304
The solution is the coefficients of the polynomial `p` that minimizes
1305
the sum of the weighted squared errors
1306
1307
.. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,
1308
1309
where the :math:`w_j` are the weights. This problem is solved by
1310
setting up the (typically) over-determined matrix equation:
1311
1312
.. math:: V(x) * c = w * y,
1313
1314
where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the
1315
coefficients to be solved for, `w` are the weights, and `y` are the
1316
observed values. This equation is then solved using the singular value
1317
decomposition of `V`.
1318
1319
If some of the singular values of `V` are so small that they are
1320
neglected (and `full` == ``False``), a `RankWarning` will be raised.
1321
This means that the coefficient values may be poorly determined.
1322
Fitting to a lower order polynomial will usually get rid of the warning
1323
(but may not be what you want, of course; if you have independent
1324
reason(s) for choosing the degree which isn't working, you may have to:
1325
a) reconsider those reasons, and/or b) reconsider the quality of your
1326
data). The `rcond` parameter can also be set to a value smaller than
1327
its default, but the resulting fit may be spurious and have large
1328
contributions from roundoff error.
1329
1330
Polynomial fits using double precision tend to "fail" at about
1331
(polynomial) degree 20. Fits using Chebyshev or Legendre series are
1332
generally better conditioned, but much can still depend on the
1333
distribution of the sample points and the smoothness of the data. If
1334
the quality of the fit is inadequate, splines may be a good
1335
alternative.
1336
1337
Examples
1338
--------
1339
>>> np.random.seed(123)
1340
>>> from numpy.polynomial import polynomial as P
1341
>>> x = np.linspace(-1,1,51) # x "data": [-1, -0.96, ..., 0.96, 1]
1342
>>> y = x**3 - x + np.random.randn(len(x)) # x^3 - x + N(0,1) "noise"
1343
>>> c, stats = P.polyfit(x,y,3,full=True)
1344
>>> np.random.seed(123)
1345
>>> c # c[0], c[2] should be approx. 0, c[1] approx. -1, c[3] approx. 1
1346
array([ 0.01909725, -1.30598256, -0.00577963, 1.02644286]) # may vary
1347
>>> stats # note the large SSR, explaining the rather poor results
1348
[array([ 38.06116253]), 4, array([ 1.38446749, 1.32119158, 0.50443316, # may vary
1349
0.28853036]), 1.1324274851176597e-014]
1350
1351
Same thing without the added noise
1352
1353
>>> y = x**3 - x
1354
>>> c, stats = P.polyfit(x,y,3,full=True)
1355
>>> c # c[0], c[2] should be "very close to 0", c[1] ~= -1, c[3] ~= 1
1356
array([-6.36925336e-18, -1.00000000e+00, -4.08053781e-16, 1.00000000e+00])
1357
>>> stats # note the minuscule SSR
1358
[array([ 7.46346754e-31]), 4, array([ 1.38446749, 1.32119158, # may vary
1359
0.50443316, 0.28853036]), 1.1324274851176597e-014]
1360
1361
"""
1362
return pu._fit(polyvander, x, y, deg, rcond, full, w)
1363
1364
1365
def polycompanion(c):
1366
"""
1367
Return the companion matrix of c.
1368
1369
The companion matrix for power series cannot be made symmetric by
1370
scaling the basis, so this function differs from those for the
1371
orthogonal polynomials.
1372
1373
Parameters
1374
----------
1375
c : array_like
1376
1-D array of polynomial coefficients ordered from low to high
1377
degree.
1378
1379
Returns
1380
-------
1381
mat : ndarray
1382
Companion matrix of dimensions (deg, deg).
1383
1384
Notes
1385
-----
1386
1387
.. versionadded:: 1.7.0
1388
1389
"""
1390
# c is a trimmed copy
1391
[c] = pu.as_series([c])
1392
if len(c) < 2:
1393
raise ValueError('Series must have maximum degree of at least 1.')
1394
if len(c) == 2:
1395
return np.array([[-c[0]/c[1]]])
1396
1397
n = len(c) - 1
1398
mat = np.zeros((n, n), dtype=c.dtype)
1399
bot = mat.reshape(-1)[n::n+1]
1400
bot[...] = 1
1401
mat[:, -1] -= c[:-1]/c[-1]
1402
return mat
1403
1404
1405
def polyroots(c):
1406
"""
1407
Compute the roots of a polynomial.
1408
1409
Return the roots (a.k.a. "zeros") of the polynomial
1410
1411
.. math:: p(x) = \\sum_i c[i] * x^i.
1412
1413
Parameters
1414
----------
1415
c : 1-D array_like
1416
1-D array of polynomial coefficients.
1417
1418
Returns
1419
-------
1420
out : ndarray
1421
Array of the roots of the polynomial. If all the roots are real,
1422
then `out` is also real, otherwise it is complex.
1423
1424
See Also
1425
--------
1426
numpy.polynomial.chebyshev.chebroots
1427
numpy.polynomial.legendre.legroots
1428
numpy.polynomial.laguerre.lagroots
1429
numpy.polynomial.hermite.hermroots
1430
numpy.polynomial.hermite_e.hermeroots
1431
1432
Notes
1433
-----
1434
The root estimates are obtained as the eigenvalues of the companion
1435
matrix, Roots far from the origin of the complex plane may have large
1436
errors due to the numerical instability of the power series for such
1437
values. Roots with multiplicity greater than 1 will also show larger
1438
errors as the value of the series near such points is relatively
1439
insensitive to errors in the roots. Isolated roots near the origin can
1440
be improved by a few iterations of Newton's method.
1441
1442
Examples
1443
--------
1444
>>> import numpy.polynomial.polynomial as poly
1445
>>> poly.polyroots(poly.polyfromroots((-1,0,1)))
1446
array([-1., 0., 1.])
1447
>>> poly.polyroots(poly.polyfromroots((-1,0,1))).dtype
1448
dtype('float64')
1449
>>> j = complex(0,1)
1450
>>> poly.polyroots(poly.polyfromroots((-j,0,j)))
1451
array([ 0.00000000e+00+0.j, 0.00000000e+00+1.j, 2.77555756e-17-1.j]) # may vary
1452
1453
"""
1454
# c is a trimmed copy
1455
[c] = pu.as_series([c])
1456
if len(c) < 2:
1457
return np.array([], dtype=c.dtype)
1458
if len(c) == 2:
1459
return np.array([-c[0]/c[1]])
1460
1461
# rotated companion matrix reduces error
1462
m = polycompanion(c)[::-1,::-1]
1463
r = la.eigvals(m)
1464
r.sort()
1465
return r
1466
1467
1468
#
1469
# polynomial class
1470
#
1471
1472
class Polynomial(ABCPolyBase):
1473
"""A power series class.
1474
1475
The Polynomial class provides the standard Python numerical methods
1476
'+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the
1477
attributes and methods listed in the `ABCPolyBase` documentation.
1478
1479
Parameters
1480
----------
1481
coef : array_like
1482
Polynomial coefficients in order of increasing degree, i.e.,
1483
``(1, 2, 3)`` give ``1 + 2*x + 3*x**2``.
1484
domain : (2,) array_like, optional
1485
Domain to use. The interval ``[domain[0], domain[1]]`` is mapped
1486
to the interval ``[window[0], window[1]]`` by shifting and scaling.
1487
The default value is [-1, 1].
1488
window : (2,) array_like, optional
1489
Window, see `domain` for its use. The default value is [-1, 1].
1490
1491
.. versionadded:: 1.6.0
1492
1493
"""
1494
# Virtual Functions
1495
_add = staticmethod(polyadd)
1496
_sub = staticmethod(polysub)
1497
_mul = staticmethod(polymul)
1498
_div = staticmethod(polydiv)
1499
_pow = staticmethod(polypow)
1500
_val = staticmethod(polyval)
1501
_int = staticmethod(polyint)
1502
_der = staticmethod(polyder)
1503
_fit = staticmethod(polyfit)
1504
_line = staticmethod(polyline)
1505
_roots = staticmethod(polyroots)
1506
_fromroots = staticmethod(polyfromroots)
1507
1508
# Virtual properties
1509
domain = np.array(polydomain)
1510
window = np.array(polydomain)
1511
basis_name = None
1512
1513
@classmethod
1514
def _str_term_unicode(cls, i, arg_str):
1515
return f"ยท{arg_str}{i.translate(cls._superscript_mapping)}"
1516
1517
@staticmethod
1518
def _str_term_ascii(i, arg_str):
1519
return f" {arg_str}**{i}"
1520
1521
@staticmethod
1522
def _repr_latex_term(i, arg_str, needs_parens):
1523
if needs_parens:
1524
arg_str = rf"\left({arg_str}\right)"
1525
if i == 0:
1526
return '1'
1527
elif i == 1:
1528
return arg_str
1529
else:
1530
return f"{arg_str}^{{{i}}}"
1531
1532