Path: blob/master/ invest-robot-contest_TinkoffBotTwitch-main/venv/lib/python3.8/site-packages/numpy/polynomial/polynomial.py
7763 views
"""1=================================================2Power Series (:mod:`numpy.polynomial.polynomial`)3=================================================45This module provides a number of objects (mostly functions) useful for6dealing with polynomials, including a `Polynomial` class that7encapsulates the usual arithmetic operations. (General information8on how this module represents and works with polynomial objects is in9the docstring for its "parent" sub-package, `numpy.polynomial`).1011Classes12-------13.. autosummary::14:toctree: generated/1516Polynomial1718Constants19---------20.. autosummary::21:toctree: generated/2223polydomain24polyzero25polyone26polyx2728Arithmetic29----------30.. autosummary::31:toctree: generated/3233polyadd34polysub35polymulx36polymul37polydiv38polypow39polyval40polyval2d41polyval3d42polygrid2d43polygrid3d4445Calculus46--------47.. autosummary::48:toctree: generated/4950polyder51polyint5253Misc Functions54--------------55.. autosummary::56:toctree: generated/5758polyfromroots59polyroots60polyvalfromroots61polyvander62polyvander2d63polyvander3d64polycompanion65polyfit66polytrim67polyline6869See Also70--------71`numpy.polynomial`7273"""74__all__ = [75'polyzero', 'polyone', 'polyx', 'polydomain', 'polyline', 'polyadd',76'polysub', 'polymulx', 'polymul', 'polydiv', 'polypow', 'polyval',77'polyvalfromroots', 'polyder', 'polyint', 'polyfromroots', 'polyvander',78'polyfit', 'polytrim', 'polyroots', 'Polynomial', 'polyval2d', 'polyval3d',79'polygrid2d', 'polygrid3d', 'polyvander2d', 'polyvander3d']8081import numpy as np82import numpy.linalg as la83from numpy.core.multiarray import normalize_axis_index8485from . import polyutils as pu86from ._polybase import ABCPolyBase8788polytrim = pu.trimcoef8990#91# These are constant arrays are of integer type so as to be compatible92# with the widest range of other types, such as Decimal.93#9495# Polynomial default domain.96polydomain = np.array([-1, 1])9798# Polynomial coefficients representing zero.99polyzero = np.array([0])100101# Polynomial coefficients representing one.102polyone = np.array([1])103104# Polynomial coefficients representing the identity x.105polyx = np.array([0, 1])106107#108# Polynomial series functions109#110111112def polyline(off, scl):113"""114Returns an array representing a linear polynomial.115116Parameters117----------118off, scl : scalars119The "y-intercept" and "slope" of the line, respectively.120121Returns122-------123y : ndarray124This module's representation of the linear polynomial ``off +125scl*x``.126127See Also128--------129numpy.polynomial.chebyshev.chebline130numpy.polynomial.legendre.legline131numpy.polynomial.laguerre.lagline132numpy.polynomial.hermite.hermline133numpy.polynomial.hermite_e.hermeline134135Examples136--------137>>> from numpy.polynomial import polynomial as P138>>> P.polyline(1,-1)139array([ 1, -1])140>>> P.polyval(1, P.polyline(1,-1)) # should be 01410.0142143"""144if scl != 0:145return np.array([off, scl])146else:147return np.array([off])148149150def polyfromroots(roots):151"""152Generate a monic polynomial with given roots.153154Return the coefficients of the polynomial155156.. math:: p(x) = (x - r_0) * (x - r_1) * ... * (x - r_n),157158where the ``r_n`` are the roots specified in `roots`. If a zero has159multiplicity n, then it must appear in `roots` n times. For instance,160if 2 is a root of multiplicity three and 3 is a root of multiplicity 2,161then `roots` looks something like [2, 2, 2, 3, 3]. The roots can appear162in any order.163164If the returned coefficients are `c`, then165166.. math:: p(x) = c_0 + c_1 * x + ... + x^n167168The coefficient of the last term is 1 for monic polynomials in this169form.170171Parameters172----------173roots : array_like174Sequence containing the roots.175176Returns177-------178out : ndarray1791-D array of the polynomial's coefficients If all the roots are180real, then `out` is also real, otherwise it is complex. (see181Examples below).182183See Also184--------185numpy.polynomial.chebyshev.chebfromroots186numpy.polynomial.legendre.legfromroots187numpy.polynomial.laguerre.lagfromroots188numpy.polynomial.hermite.hermfromroots189numpy.polynomial.hermite_e.hermefromroots190191Notes192-----193The coefficients are determined by multiplying together linear factors194of the form ``(x - r_i)``, i.e.195196.. math:: p(x) = (x - r_0) (x - r_1) ... (x - r_n)197198where ``n == len(roots) - 1``; note that this implies that ``1`` is always199returned for :math:`a_n`.200201Examples202--------203>>> from numpy.polynomial import polynomial as P204>>> P.polyfromroots((-1,0,1)) # x(x - 1)(x + 1) = x^3 - x205array([ 0., -1., 0., 1.])206>>> j = complex(0,1)207>>> P.polyfromroots((-j,j)) # complex returned, though values are real208array([1.+0.j, 0.+0.j, 1.+0.j])209210"""211return pu._fromroots(polyline, polymul, roots)212213214def polyadd(c1, c2):215"""216Add one polynomial to another.217218Returns the sum of two polynomials `c1` + `c2`. The arguments are219sequences of coefficients from lowest order term to highest, i.e.,220[1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.221222Parameters223----------224c1, c2 : array_like2251-D arrays of polynomial coefficients ordered from low to high.226227Returns228-------229out : ndarray230The coefficient array representing their sum.231232See Also233--------234polysub, polymulx, polymul, polydiv, polypow235236Examples237--------238>>> from numpy.polynomial import polynomial as P239>>> c1 = (1,2,3)240>>> c2 = (3,2,1)241>>> sum = P.polyadd(c1,c2); sum242array([4., 4., 4.])243>>> P.polyval(2, sum) # 4 + 4(2) + 4(2**2)24428.0245246"""247return pu._add(c1, c2)248249250def polysub(c1, c2):251"""252Subtract one polynomial from another.253254Returns the difference of two polynomials `c1` - `c2`. The arguments255are sequences of coefficients from lowest order term to highest, i.e.,256[1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``.257258Parameters259----------260c1, c2 : array_like2611-D arrays of polynomial coefficients ordered from low to262high.263264Returns265-------266out : ndarray267Of coefficients representing their difference.268269See Also270--------271polyadd, polymulx, polymul, polydiv, polypow272273Examples274--------275>>> from numpy.polynomial import polynomial as P276>>> c1 = (1,2,3)277>>> c2 = (3,2,1)278>>> P.polysub(c1,c2)279array([-2., 0., 2.])280>>> P.polysub(c2,c1) # -P.polysub(c1,c2)281array([ 2., 0., -2.])282283"""284return pu._sub(c1, c2)285286287def polymulx(c):288"""Multiply a polynomial by x.289290Multiply the polynomial `c` by x, where x is the independent291variable.292293294Parameters295----------296c : array_like2971-D array of polynomial coefficients ordered from low to298high.299300Returns301-------302out : ndarray303Array representing the result of the multiplication.304305See Also306--------307polyadd, polysub, polymul, polydiv, polypow308309Notes310-----311312.. versionadded:: 1.5.0313314"""315# c is a trimmed copy316[c] = pu.as_series([c])317# The zero series needs special treatment318if len(c) == 1 and c[0] == 0:319return c320321prd = np.empty(len(c) + 1, dtype=c.dtype)322prd[0] = c[0]*0323prd[1:] = c324return prd325326327def polymul(c1, c2):328"""329Multiply one polynomial by another.330331Returns the product of two polynomials `c1` * `c2`. The arguments are332sequences of coefficients, from lowest order term to highest, e.g.,333[1,2,3] represents the polynomial ``1 + 2*x + 3*x**2.``334335Parameters336----------337c1, c2 : array_like3381-D arrays of coefficients representing a polynomial, relative to the339"standard" basis, and ordered from lowest order term to highest.340341Returns342-------343out : ndarray344Of the coefficients of their product.345346See Also347--------348polyadd, polysub, polymulx, polydiv, polypow349350Examples351--------352>>> from numpy.polynomial import polynomial as P353>>> c1 = (1,2,3)354>>> c2 = (3,2,1)355>>> P.polymul(c1,c2)356array([ 3., 8., 14., 8., 3.])357358"""359# c1, c2 are trimmed copies360[c1, c2] = pu.as_series([c1, c2])361ret = np.convolve(c1, c2)362return pu.trimseq(ret)363364365def polydiv(c1, c2):366"""367Divide one polynomial by another.368369Returns the quotient-with-remainder of two polynomials `c1` / `c2`.370The arguments are sequences of coefficients, from lowest order term371to highest, e.g., [1,2,3] represents ``1 + 2*x + 3*x**2``.372373Parameters374----------375c1, c2 : array_like3761-D arrays of polynomial coefficients ordered from low to high.377378Returns379-------380[quo, rem] : ndarrays381Of coefficient series representing the quotient and remainder.382383See Also384--------385polyadd, polysub, polymulx, polymul, polypow386387Examples388--------389>>> from numpy.polynomial import polynomial as P390>>> c1 = (1,2,3)391>>> c2 = (3,2,1)392>>> P.polydiv(c1,c2)393(array([3.]), array([-8., -4.]))394>>> P.polydiv(c2,c1)395(array([ 0.33333333]), array([ 2.66666667, 1.33333333])) # may vary396397"""398# c1, c2 are trimmed copies399[c1, c2] = pu.as_series([c1, c2])400if c2[-1] == 0:401raise ZeroDivisionError()402403# note: this is more efficient than `pu._div(polymul, c1, c2)`404lc1 = len(c1)405lc2 = len(c2)406if lc1 < lc2:407return c1[:1]*0, c1408elif lc2 == 1:409return c1/c2[-1], c1[:1]*0410else:411dlen = lc1 - lc2412scl = c2[-1]413c2 = c2[:-1]/scl414i = dlen415j = lc1 - 1416while i >= 0:417c1[i:j] -= c2*c1[j]418i -= 1419j -= 1420return c1[j+1:]/scl, pu.trimseq(c1[:j+1])421422423def polypow(c, pow, maxpower=None):424"""Raise a polynomial to a power.425426Returns the polynomial `c` raised to the power `pow`. The argument427`c` is a sequence of coefficients ordered from low to high. i.e.,428[1,2,3] is the series ``1 + 2*x + 3*x**2.``429430Parameters431----------432c : array_like4331-D array of array of series coefficients ordered from low to434high degree.435pow : integer436Power to which the series will be raised437maxpower : integer, optional438Maximum power allowed. This is mainly to limit growth of the series439to unmanageable size. Default is 16440441Returns442-------443coef : ndarray444Power series of power.445446See Also447--------448polyadd, polysub, polymulx, polymul, polydiv449450Examples451--------452>>> from numpy.polynomial import polynomial as P453>>> P.polypow([1,2,3], 2)454array([ 1., 4., 10., 12., 9.])455456"""457# note: this is more efficient than `pu._pow(polymul, c1, c2)`, as it458# avoids calling `as_series` repeatedly459return pu._pow(np.convolve, c, pow, maxpower)460461462def polyder(c, m=1, scl=1, axis=0):463"""464Differentiate a polynomial.465466Returns the polynomial coefficients `c` differentiated `m` times along467`axis`. At each iteration the result is multiplied by `scl` (the468scaling factor is for use in a linear change of variable). The469argument `c` is an array of coefficients from low to high degree along470each axis, e.g., [1,2,3] represents the polynomial ``1 + 2*x + 3*x**2``471while [[1,2],[1,2]] represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is472``x`` and axis=1 is ``y``.473474Parameters475----------476c : array_like477Array of polynomial coefficients. If c is multidimensional the478different axis correspond to different variables with the degree479in each axis given by the corresponding index.480m : int, optional481Number of derivatives taken, must be non-negative. (Default: 1)482scl : scalar, optional483Each differentiation is multiplied by `scl`. The end result is484multiplication by ``scl**m``. This is for use in a linear change485of variable. (Default: 1)486axis : int, optional487Axis over which the derivative is taken. (Default: 0).488489.. versionadded:: 1.7.0490491Returns492-------493der : ndarray494Polynomial coefficients of the derivative.495496See Also497--------498polyint499500Examples501--------502>>> from numpy.polynomial import polynomial as P503>>> c = (1,2,3,4) # 1 + 2x + 3x**2 + 4x**3504>>> P.polyder(c) # (d/dx)(c) = 2 + 6x + 12x**2505array([ 2., 6., 12.])506>>> P.polyder(c,3) # (d**3/dx**3)(c) = 24507array([24.])508>>> P.polyder(c,scl=-1) # (d/d(-x))(c) = -2 - 6x - 12x**2509array([ -2., -6., -12.])510>>> P.polyder(c,2,-1) # (d**2/d(-x)**2)(c) = 6 + 24x511array([ 6., 24.])512513"""514c = np.array(c, ndmin=1, copy=True)515if c.dtype.char in '?bBhHiIlLqQpP':516# astype fails with NA517c = c + 0.0518cdt = c.dtype519cnt = pu._deprecate_as_int(m, "the order of derivation")520iaxis = pu._deprecate_as_int(axis, "the axis")521if cnt < 0:522raise ValueError("The order of derivation must be non-negative")523iaxis = normalize_axis_index(iaxis, c.ndim)524525if cnt == 0:526return c527528c = np.moveaxis(c, iaxis, 0)529n = len(c)530if cnt >= n:531c = c[:1]*0532else:533for i in range(cnt):534n = n - 1535c *= scl536der = np.empty((n,) + c.shape[1:], dtype=cdt)537for j in range(n, 0, -1):538der[j - 1] = j*c[j]539c = der540c = np.moveaxis(c, 0, iaxis)541return c542543544def polyint(c, m=1, k=[], lbnd=0, scl=1, axis=0):545"""546Integrate a polynomial.547548Returns the polynomial coefficients `c` integrated `m` times from549`lbnd` along `axis`. At each iteration the resulting series is550**multiplied** by `scl` and an integration constant, `k`, is added.551The scaling factor is for use in a linear change of variable. ("Buyer552beware": note that, depending on what one is doing, one may want `scl`553to be the reciprocal of what one might expect; for more information,554see the Notes section below.) The argument `c` is an array of555coefficients, from low to high degree along each axis, e.g., [1,2,3]556represents the polynomial ``1 + 2*x + 3*x**2`` while [[1,2],[1,2]]557represents ``1 + 1*x + 2*y + 2*x*y`` if axis=0 is ``x`` and axis=1 is558``y``.559560Parameters561----------562c : array_like5631-D array of polynomial coefficients, ordered from low to high.564m : int, optional565Order of integration, must be positive. (Default: 1)566k : {[], list, scalar}, optional567Integration constant(s). The value of the first integral at zero568is the first value in the list, the value of the second integral569at zero is the second value, etc. If ``k == []`` (the default),570all constants are set to zero. If ``m == 1``, a single scalar can571be given instead of a list.572lbnd : scalar, optional573The lower bound of the integral. (Default: 0)574scl : scalar, optional575Following each integration the result is *multiplied* by `scl`576before the integration constant is added. (Default: 1)577axis : int, optional578Axis over which the integral is taken. (Default: 0).579580.. versionadded:: 1.7.0581582Returns583-------584S : ndarray585Coefficient array of the integral.586587Raises588------589ValueError590If ``m < 1``, ``len(k) > m``, ``np.ndim(lbnd) != 0``, or591``np.ndim(scl) != 0``.592593See Also594--------595polyder596597Notes598-----599Note that the result of each integration is *multiplied* by `scl`. Why600is this important to note? Say one is making a linear change of601variable :math:`u = ax + b` in an integral relative to `x`. Then602:math:`dx = du/a`, so one will need to set `scl` equal to603:math:`1/a` - perhaps not what one would have first thought.604605Examples606--------607>>> from numpy.polynomial import polynomial as P608>>> c = (1,2,3)609>>> P.polyint(c) # should return array([0, 1, 1, 1])610array([0., 1., 1., 1.])611>>> P.polyint(c,3) # should return array([0, 0, 0, 1/6, 1/12, 1/20])612array([ 0. , 0. , 0. , 0.16666667, 0.08333333, # may vary6130.05 ])614>>> P.polyint(c,k=3) # should return array([3, 1, 1, 1])615array([3., 1., 1., 1.])616>>> P.polyint(c,lbnd=-2) # should return array([6, 1, 1, 1])617array([6., 1., 1., 1.])618>>> P.polyint(c,scl=-2) # should return array([0, -2, -2, -2])619array([ 0., -2., -2., -2.])620621"""622c = np.array(c, ndmin=1, copy=True)623if c.dtype.char in '?bBhHiIlLqQpP':624# astype doesn't preserve mask attribute.625c = c + 0.0626cdt = c.dtype627if not np.iterable(k):628k = [k]629cnt = pu._deprecate_as_int(m, "the order of integration")630iaxis = pu._deprecate_as_int(axis, "the axis")631if cnt < 0:632raise ValueError("The order of integration must be non-negative")633if len(k) > cnt:634raise ValueError("Too many integration constants")635if np.ndim(lbnd) != 0:636raise ValueError("lbnd must be a scalar.")637if np.ndim(scl) != 0:638raise ValueError("scl must be a scalar.")639iaxis = normalize_axis_index(iaxis, c.ndim)640641if cnt == 0:642return c643644k = list(k) + [0]*(cnt - len(k))645c = np.moveaxis(c, iaxis, 0)646for i in range(cnt):647n = len(c)648c *= scl649if n == 1 and np.all(c[0] == 0):650c[0] += k[i]651else:652tmp = np.empty((n + 1,) + c.shape[1:], dtype=cdt)653tmp[0] = c[0]*0654tmp[1] = c[0]655for j in range(1, n):656tmp[j + 1] = c[j]/(j + 1)657tmp[0] += k[i] - polyval(lbnd, tmp)658c = tmp659c = np.moveaxis(c, 0, iaxis)660return c661662663def polyval(x, c, tensor=True):664"""665Evaluate a polynomial at points x.666667If `c` is of length `n + 1`, this function returns the value668669.. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n670671The parameter `x` is converted to an array only if it is a tuple or a672list, otherwise it is treated as a scalar. In either case, either `x`673or its elements must support multiplication and addition both with674themselves and with the elements of `c`.675676If `c` is a 1-D array, then `p(x)` will have the same shape as `x`. If677`c` is multidimensional, then the shape of the result depends on the678value of `tensor`. If `tensor` is true the shape will be c.shape[1:] +679x.shape. If `tensor` is false the shape will be c.shape[1:]. Note that680scalars have shape (,).681682Trailing zeros in the coefficients will be used in the evaluation, so683they should be avoided if efficiency is a concern.684685Parameters686----------687x : array_like, compatible object688If `x` is a list or tuple, it is converted to an ndarray, otherwise689it is left unchanged and treated as a scalar. In either case, `x`690or its elements must support addition and multiplication with691with themselves and with the elements of `c`.692c : array_like693Array of coefficients ordered so that the coefficients for terms of694degree n are contained in c[n]. If `c` is multidimensional the695remaining indices enumerate multiple polynomials. In the two696dimensional case the coefficients may be thought of as stored in697the columns of `c`.698tensor : boolean, optional699If True, the shape of the coefficient array is extended with ones700on the right, one for each dimension of `x`. Scalars have dimension 0701for this action. The result is that every column of coefficients in702`c` is evaluated for every element of `x`. If False, `x` is broadcast703over the columns of `c` for the evaluation. This keyword is useful704when `c` is multidimensional. The default value is True.705706.. versionadded:: 1.7.0707708Returns709-------710values : ndarray, compatible object711The shape of the returned array is described above.712713See Also714--------715polyval2d, polygrid2d, polyval3d, polygrid3d716717Notes718-----719The evaluation uses Horner's method.720721Examples722--------723>>> from numpy.polynomial.polynomial import polyval724>>> polyval(1, [1,2,3])7256.0726>>> a = np.arange(4).reshape(2,2)727>>> a728array([[0, 1],729[2, 3]])730>>> polyval(a, [1,2,3])731array([[ 1., 6.],732[17., 34.]])733>>> coef = np.arange(4).reshape(2,2) # multidimensional coefficients734>>> coef735array([[0, 1],736[2, 3]])737>>> polyval([1,2], coef, tensor=True)738array([[2., 4.],739[4., 7.]])740>>> polyval([1,2], coef, tensor=False)741array([2., 7.])742743"""744c = np.array(c, ndmin=1, copy=False)745if c.dtype.char in '?bBhHiIlLqQpP':746# astype fails with NA747c = c + 0.0748if isinstance(x, (tuple, list)):749x = np.asarray(x)750if isinstance(x, np.ndarray) and tensor:751c = c.reshape(c.shape + (1,)*x.ndim)752753c0 = c[-1] + x*0754for i in range(2, len(c) + 1):755c0 = c[-i] + c0*x756return c0757758759def polyvalfromroots(x, r, tensor=True):760"""761Evaluate a polynomial specified by its roots at points x.762763If `r` is of length `N`, this function returns the value764765.. math:: p(x) = \\prod_{n=1}^{N} (x - r_n)766767The parameter `x` is converted to an array only if it is a tuple or a768list, otherwise it is treated as a scalar. In either case, either `x`769or its elements must support multiplication and addition both with770themselves and with the elements of `r`.771772If `r` is a 1-D array, then `p(x)` will have the same shape as `x`. If `r`773is multidimensional, then the shape of the result depends on the value of774`tensor`. If `tensor is ``True`` the shape will be r.shape[1:] + x.shape;775that is, each polynomial is evaluated at every value of `x`. If `tensor` is776``False``, the shape will be r.shape[1:]; that is, each polynomial is777evaluated only for the corresponding broadcast value of `x`. Note that778scalars have shape (,).779780.. versionadded:: 1.12781782Parameters783----------784x : array_like, compatible object785If `x` is a list or tuple, it is converted to an ndarray, otherwise786it is left unchanged and treated as a scalar. In either case, `x`787or its elements must support addition and multiplication with788with themselves and with the elements of `r`.789r : array_like790Array of roots. If `r` is multidimensional the first index is the791root index, while the remaining indices enumerate multiple792polynomials. For instance, in the two dimensional case the roots793of each polynomial may be thought of as stored in the columns of `r`.794tensor : boolean, optional795If True, the shape of the roots array is extended with ones on the796right, one for each dimension of `x`. Scalars have dimension 0 for this797action. The result is that every column of coefficients in `r` is798evaluated for every element of `x`. If False, `x` is broadcast over the799columns of `r` for the evaluation. This keyword is useful when `r` is800multidimensional. The default value is True.801802Returns803-------804values : ndarray, compatible object805The shape of the returned array is described above.806807See Also808--------809polyroots, polyfromroots, polyval810811Examples812--------813>>> from numpy.polynomial.polynomial import polyvalfromroots814>>> polyvalfromroots(1, [1,2,3])8150.0816>>> a = np.arange(4).reshape(2,2)817>>> a818array([[0, 1],819[2, 3]])820>>> polyvalfromroots(a, [-1, 0, 1])821array([[-0., 0.],822[ 6., 24.]])823>>> r = np.arange(-2, 2).reshape(2,2) # multidimensional coefficients824>>> r # each column of r defines one polynomial825array([[-2, -1],826[ 0, 1]])827>>> b = [-2, 1]828>>> polyvalfromroots(b, r, tensor=True)829array([[-0., 3.],830[ 3., 0.]])831>>> polyvalfromroots(b, r, tensor=False)832array([-0., 0.])833"""834r = np.array(r, ndmin=1, copy=False)835if r.dtype.char in '?bBhHiIlLqQpP':836r = r.astype(np.double)837if isinstance(x, (tuple, list)):838x = np.asarray(x)839if isinstance(x, np.ndarray):840if tensor:841r = r.reshape(r.shape + (1,)*x.ndim)842elif x.ndim >= r.ndim:843raise ValueError("x.ndim must be < r.ndim when tensor == False")844return np.prod(x - r, axis=0)845846847def polyval2d(x, y, c):848"""849Evaluate a 2-D polynomial at points (x, y).850851This function returns the value852853.. math:: p(x,y) = \\sum_{i,j} c_{i,j} * x^i * y^j854855The parameters `x` and `y` are converted to arrays only if they are856tuples or a lists, otherwise they are treated as a scalars and they857must have the same shape after conversion. In either case, either `x`858and `y` or their elements must support multiplication and addition both859with themselves and with the elements of `c`.860861If `c` has fewer than two dimensions, ones are implicitly appended to862its shape to make it 2-D. The shape of the result will be c.shape[2:] +863x.shape.864865Parameters866----------867x, y : array_like, compatible objects868The two dimensional series is evaluated at the points `(x, y)`,869where `x` and `y` must have the same shape. If `x` or `y` is a list870or tuple, it is first converted to an ndarray, otherwise it is left871unchanged and, if it isn't an ndarray, it is treated as a scalar.872c : array_like873Array of coefficients ordered so that the coefficient of the term874of multi-degree i,j is contained in `c[i,j]`. If `c` has875dimension greater than two the remaining indices enumerate multiple876sets of coefficients.877878Returns879-------880values : ndarray, compatible object881The values of the two dimensional polynomial at points formed with882pairs of corresponding values from `x` and `y`.883884See Also885--------886polyval, polygrid2d, polyval3d, polygrid3d887888Notes889-----890891.. versionadded:: 1.7.0892893"""894return pu._valnd(polyval, c, x, y)895896897def polygrid2d(x, y, c):898"""899Evaluate a 2-D polynomial on the Cartesian product of x and y.900901This function returns the values:902903.. math:: p(a,b) = \\sum_{i,j} c_{i,j} * a^i * b^j904905where the points `(a, b)` consist of all pairs formed by taking906`a` from `x` and `b` from `y`. The resulting points form a grid with907`x` in the first dimension and `y` in the second.908909The parameters `x` and `y` are converted to arrays only if they are910tuples or a lists, otherwise they are treated as a scalars. In either911case, either `x` and `y` or their elements must support multiplication912and addition both with themselves and with the elements of `c`.913914If `c` has fewer than two dimensions, ones are implicitly appended to915its shape to make it 2-D. The shape of the result will be c.shape[2:] +916x.shape + y.shape.917918Parameters919----------920x, y : array_like, compatible objects921The two dimensional series is evaluated at the points in the922Cartesian product of `x` and `y`. If `x` or `y` is a list or923tuple, it is first converted to an ndarray, otherwise it is left924unchanged and, if it isn't an ndarray, it is treated as a scalar.925c : array_like926Array of coefficients ordered so that the coefficients for terms of927degree i,j are contained in ``c[i,j]``. If `c` has dimension928greater than two the remaining indices enumerate multiple sets of929coefficients.930931Returns932-------933values : ndarray, compatible object934The values of the two dimensional polynomial at points in the Cartesian935product of `x` and `y`.936937See Also938--------939polyval, polyval2d, polyval3d, polygrid3d940941Notes942-----943944.. versionadded:: 1.7.0945946"""947return pu._gridnd(polyval, c, x, y)948949950def polyval3d(x, y, z, c):951"""952Evaluate a 3-D polynomial at points (x, y, z).953954This function returns the values:955956.. math:: p(x,y,z) = \\sum_{i,j,k} c_{i,j,k} * x^i * y^j * z^k957958The parameters `x`, `y`, and `z` are converted to arrays only if959they are tuples or a lists, otherwise they are treated as a scalars and960they must have the same shape after conversion. In either case, either961`x`, `y`, and `z` or their elements must support multiplication and962addition both with themselves and with the elements of `c`.963964If `c` has fewer than 3 dimensions, ones are implicitly appended to its965shape to make it 3-D. The shape of the result will be c.shape[3:] +966x.shape.967968Parameters969----------970x, y, z : array_like, compatible object971The three dimensional series is evaluated at the points972`(x, y, z)`, where `x`, `y`, and `z` must have the same shape. If973any of `x`, `y`, or `z` is a list or tuple, it is first converted974to an ndarray, otherwise it is left unchanged and if it isn't an975ndarray it is treated as a scalar.976c : array_like977Array of coefficients ordered so that the coefficient of the term of978multi-degree i,j,k is contained in ``c[i,j,k]``. If `c` has dimension979greater than 3 the remaining indices enumerate multiple sets of980coefficients.981982Returns983-------984values : ndarray, compatible object985The values of the multidimensional polynomial on points formed with986triples of corresponding values from `x`, `y`, and `z`.987988See Also989--------990polyval, polyval2d, polygrid2d, polygrid3d991992Notes993-----994995.. versionadded:: 1.7.0996997"""998return pu._valnd(polyval, c, x, y, z)99910001001def polygrid3d(x, y, z, c):1002"""1003Evaluate a 3-D polynomial on the Cartesian product of x, y and z.10041005This function returns the values:10061007.. math:: p(a,b,c) = \\sum_{i,j,k} c_{i,j,k} * a^i * b^j * c^k10081009where the points `(a, b, c)` consist of all triples formed by taking1010`a` from `x`, `b` from `y`, and `c` from `z`. The resulting points form1011a grid with `x` in the first dimension, `y` in the second, and `z` in1012the third.10131014The parameters `x`, `y`, and `z` are converted to arrays only if they1015are tuples or a lists, otherwise they are treated as a scalars. In1016either case, either `x`, `y`, and `z` or their elements must support1017multiplication and addition both with themselves and with the elements1018of `c`.10191020If `c` has fewer than three dimensions, ones are implicitly appended to1021its shape to make it 3-D. The shape of the result will be c.shape[3:] +1022x.shape + y.shape + z.shape.10231024Parameters1025----------1026x, y, z : array_like, compatible objects1027The three dimensional series is evaluated at the points in the1028Cartesian product of `x`, `y`, and `z`. If `x`,`y`, or `z` is a1029list or tuple, it is first converted to an ndarray, otherwise it is1030left unchanged and, if it isn't an ndarray, it is treated as a1031scalar.1032c : array_like1033Array of coefficients ordered so that the coefficients for terms of1034degree i,j are contained in ``c[i,j]``. If `c` has dimension1035greater than two the remaining indices enumerate multiple sets of1036coefficients.10371038Returns1039-------1040values : ndarray, compatible object1041The values of the two dimensional polynomial at points in the Cartesian1042product of `x` and `y`.10431044See Also1045--------1046polyval, polyval2d, polygrid2d, polyval3d10471048Notes1049-----10501051.. versionadded:: 1.7.010521053"""1054return pu._gridnd(polyval, c, x, y, z)105510561057def polyvander(x, deg):1058"""Vandermonde matrix of given degree.10591060Returns the Vandermonde matrix of degree `deg` and sample points1061`x`. The Vandermonde matrix is defined by10621063.. math:: V[..., i] = x^i,10641065where `0 <= i <= deg`. The leading indices of `V` index the elements of1066`x` and the last index is the power of `x`.10671068If `c` is a 1-D array of coefficients of length `n + 1` and `V` is the1069matrix ``V = polyvander(x, n)``, then ``np.dot(V, c)`` and1070``polyval(x, c)`` are the same up to roundoff. This equivalence is1071useful both for least squares fitting and for the evaluation of a large1072number of polynomials of the same degree and sample points.10731074Parameters1075----------1076x : array_like1077Array of points. The dtype is converted to float64 or complex1281078depending on whether any of the elements are complex. If `x` is1079scalar it is converted to a 1-D array.1080deg : int1081Degree of the resulting matrix.10821083Returns1084-------1085vander : ndarray.1086The Vandermonde matrix. The shape of the returned matrix is1087``x.shape + (deg + 1,)``, where the last index is the power of `x`.1088The dtype will be the same as the converted `x`.10891090See Also1091--------1092polyvander2d, polyvander3d10931094"""1095ideg = pu._deprecate_as_int(deg, "deg")1096if ideg < 0:1097raise ValueError("deg must be non-negative")10981099x = np.array(x, copy=False, ndmin=1) + 0.01100dims = (ideg + 1,) + x.shape1101dtyp = x.dtype1102v = np.empty(dims, dtype=dtyp)1103v[0] = x*0 + 11104if ideg > 0:1105v[1] = x1106for i in range(2, ideg + 1):1107v[i] = v[i-1]*x1108return np.moveaxis(v, 0, -1)110911101111def polyvander2d(x, y, deg):1112"""Pseudo-Vandermonde matrix of given degrees.11131114Returns the pseudo-Vandermonde matrix of degrees `deg` and sample1115points `(x, y)`. The pseudo-Vandermonde matrix is defined by11161117.. math:: V[..., (deg[1] + 1)*i + j] = x^i * y^j,11181119where `0 <= i <= deg[0]` and `0 <= j <= deg[1]`. The leading indices of1120`V` index the points `(x, y)` and the last index encodes the powers of1121`x` and `y`.11221123If ``V = polyvander2d(x, y, [xdeg, ydeg])``, then the columns of `V`1124correspond to the elements of a 2-D coefficient array `c` of shape1125(xdeg + 1, ydeg + 1) in the order11261127.. math:: c_{00}, c_{01}, c_{02} ... , c_{10}, c_{11}, c_{12} ...11281129and ``np.dot(V, c.flat)`` and ``polyval2d(x, y, c)`` will be the same1130up to roundoff. This equivalence is useful both for least squares1131fitting and for the evaluation of a large number of 2-D polynomials1132of the same degrees and sample points.11331134Parameters1135----------1136x, y : array_like1137Arrays of point coordinates, all of the same shape. The dtypes1138will be converted to either float64 or complex128 depending on1139whether any of the elements are complex. Scalars are converted to11401-D arrays.1141deg : list of ints1142List of maximum degrees of the form [x_deg, y_deg].11431144Returns1145-------1146vander2d : ndarray1147The shape of the returned matrix is ``x.shape + (order,)``, where1148:math:`order = (deg[0]+1)*(deg([1]+1)`. The dtype will be the same1149as the converted `x` and `y`.11501151See Also1152--------1153polyvander, polyvander3d, polyval2d, polyval3d11541155"""1156return pu._vander_nd_flat((polyvander, polyvander), (x, y), deg)115711581159def polyvander3d(x, y, z, deg):1160"""Pseudo-Vandermonde matrix of given degrees.11611162Returns the pseudo-Vandermonde matrix of degrees `deg` and sample1163points `(x, y, z)`. If `l, m, n` are the given degrees in `x, y, z`,1164then The pseudo-Vandermonde matrix is defined by11651166.. math:: V[..., (m+1)(n+1)i + (n+1)j + k] = x^i * y^j * z^k,11671168where `0 <= i <= l`, `0 <= j <= m`, and `0 <= j <= n`. The leading1169indices of `V` index the points `(x, y, z)` and the last index encodes1170the powers of `x`, `y`, and `z`.11711172If ``V = polyvander3d(x, y, z, [xdeg, ydeg, zdeg])``, then the columns1173of `V` correspond to the elements of a 3-D coefficient array `c` of1174shape (xdeg + 1, ydeg + 1, zdeg + 1) in the order11751176.. math:: c_{000}, c_{001}, c_{002},... , c_{010}, c_{011}, c_{012},...11771178and ``np.dot(V, c.flat)`` and ``polyval3d(x, y, z, c)`` will be the1179same up to roundoff. This equivalence is useful both for least squares1180fitting and for the evaluation of a large number of 3-D polynomials1181of the same degrees and sample points.11821183Parameters1184----------1185x, y, z : array_like1186Arrays of point coordinates, all of the same shape. The dtypes will1187be converted to either float64 or complex128 depending on whether1188any of the elements are complex. Scalars are converted to 1-D1189arrays.1190deg : list of ints1191List of maximum degrees of the form [x_deg, y_deg, z_deg].11921193Returns1194-------1195vander3d : ndarray1196The shape of the returned matrix is ``x.shape + (order,)``, where1197:math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`. The dtype will1198be the same as the converted `x`, `y`, and `z`.11991200See Also1201--------1202polyvander, polyvander3d, polyval2d, polyval3d12031204Notes1205-----12061207.. versionadded:: 1.7.012081209"""1210return pu._vander_nd_flat((polyvander, polyvander, polyvander), (x, y, z), deg)121112121213def polyfit(x, y, deg, rcond=None, full=False, w=None):1214"""1215Least-squares fit of a polynomial to data.12161217Return the coefficients of a polynomial of degree `deg` that is the1218least squares fit to the data values `y` given at points `x`. If `y` is12191-D the returned coefficients will also be 1-D. If `y` is 2-D multiple1220fits are done, one for each column of `y`, and the resulting1221coefficients are stored in the corresponding columns of a 2-D return.1222The fitted polynomial(s) are in the form12231224.. math:: p(x) = c_0 + c_1 * x + ... + c_n * x^n,12251226where `n` is `deg`.12271228Parameters1229----------1230x : array_like, shape (`M`,)1231x-coordinates of the `M` sample (data) points ``(x[i], y[i])``.1232y : array_like, shape (`M`,) or (`M`, `K`)1233y-coordinates of the sample points. Several sets of sample points1234sharing the same x-coordinates can be (independently) fit with one1235call to `polyfit` by passing in for `y` a 2-D array that contains1236one data set per column.1237deg : int or 1-D array_like1238Degree(s) of the fitting polynomials. If `deg` is a single integer1239all terms up to and including the `deg`'th term are included in the1240fit. For NumPy versions >= 1.11.0 a list of integers specifying the1241degrees of the terms to include may be used instead.1242rcond : float, optional1243Relative condition number of the fit. Singular values smaller1244than `rcond`, relative to the largest singular value, will be1245ignored. The default value is ``len(x)*eps``, where `eps` is the1246relative precision of the platform's float type, about 2e-16 in1247most cases.1248full : bool, optional1249Switch determining the nature of the return value. When ``False``1250(the default) just the coefficients are returned; when ``True``,1251diagnostic information from the singular value decomposition (used1252to solve the fit's matrix equation) is also returned.1253w : array_like, shape (`M`,), optional1254Weights. If not None, the weight ``w[i]`` applies to the unsquared1255residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are1256chosen so that the errors of the products ``w[i]*y[i]`` all have the1257same variance. When using inverse-variance weighting, use1258``w[i] = 1/sigma(y[i])``. The default value is None.12591260.. versionadded:: 1.5.012611262Returns1263-------1264coef : ndarray, shape (`deg` + 1,) or (`deg` + 1, `K`)1265Polynomial coefficients ordered from low to high. If `y` was 2-D,1266the coefficients in column `k` of `coef` represent the polynomial1267fit to the data in `y`'s `k`-th column.12681269[residuals, rank, singular_values, rcond] : list1270These values are only returned if ``full == True``12711272- residuals -- sum of squared residuals of the least squares fit1273- rank -- the numerical rank of the scaled Vandermonde matrix1274- singular_values -- singular values of the scaled Vandermonde matrix1275- rcond -- value of `rcond`.12761277For more details, see `numpy.linalg.lstsq`.12781279Raises1280------1281RankWarning1282Raised if the matrix in the least-squares fit is rank deficient.1283The warning is only raised if ``full == False``. The warnings can1284be turned off by:12851286>>> import warnings1287>>> warnings.simplefilter('ignore', np.RankWarning)12881289See Also1290--------1291numpy.polynomial.chebyshev.chebfit1292numpy.polynomial.legendre.legfit1293numpy.polynomial.laguerre.lagfit1294numpy.polynomial.hermite.hermfit1295numpy.polynomial.hermite_e.hermefit1296polyval : Evaluates a polynomial.1297polyvander : Vandermonde matrix for powers.1298numpy.linalg.lstsq : Computes a least-squares fit from the matrix.1299scipy.interpolate.UnivariateSpline : Computes spline fits.13001301Notes1302-----1303The solution is the coefficients of the polynomial `p` that minimizes1304the sum of the weighted squared errors13051306.. math:: E = \\sum_j w_j^2 * |y_j - p(x_j)|^2,13071308where the :math:`w_j` are the weights. This problem is solved by1309setting up the (typically) over-determined matrix equation:13101311.. math:: V(x) * c = w * y,13121313where `V` is the weighted pseudo Vandermonde matrix of `x`, `c` are the1314coefficients to be solved for, `w` are the weights, and `y` are the1315observed values. This equation is then solved using the singular value1316decomposition of `V`.13171318If some of the singular values of `V` are so small that they are1319neglected (and `full` == ``False``), a `RankWarning` will be raised.1320This means that the coefficient values may be poorly determined.1321Fitting to a lower order polynomial will usually get rid of the warning1322(but may not be what you want, of course; if you have independent1323reason(s) for choosing the degree which isn't working, you may have to:1324a) reconsider those reasons, and/or b) reconsider the quality of your1325data). The `rcond` parameter can also be set to a value smaller than1326its default, but the resulting fit may be spurious and have large1327contributions from roundoff error.13281329Polynomial fits using double precision tend to "fail" at about1330(polynomial) degree 20. Fits using Chebyshev or Legendre series are1331generally better conditioned, but much can still depend on the1332distribution of the sample points and the smoothness of the data. If1333the quality of the fit is inadequate, splines may be a good1334alternative.13351336Examples1337--------1338>>> np.random.seed(123)1339>>> from numpy.polynomial import polynomial as P1340>>> x = np.linspace(-1,1,51) # x "data": [-1, -0.96, ..., 0.96, 1]1341>>> y = x**3 - x + np.random.randn(len(x)) # x^3 - x + N(0,1) "noise"1342>>> c, stats = P.polyfit(x,y,3,full=True)1343>>> np.random.seed(123)1344>>> c # c[0], c[2] should be approx. 0, c[1] approx. -1, c[3] approx. 11345array([ 0.01909725, -1.30598256, -0.00577963, 1.02644286]) # may vary1346>>> stats # note the large SSR, explaining the rather poor results1347[array([ 38.06116253]), 4, array([ 1.38446749, 1.32119158, 0.50443316, # may vary13480.28853036]), 1.1324274851176597e-014]13491350Same thing without the added noise13511352>>> y = x**3 - x1353>>> c, stats = P.polyfit(x,y,3,full=True)1354>>> c # c[0], c[2] should be "very close to 0", c[1] ~= -1, c[3] ~= 11355array([-6.36925336e-18, -1.00000000e+00, -4.08053781e-16, 1.00000000e+00])1356>>> stats # note the minuscule SSR1357[array([ 7.46346754e-31]), 4, array([ 1.38446749, 1.32119158, # may vary13580.50443316, 0.28853036]), 1.1324274851176597e-014]13591360"""1361return pu._fit(polyvander, x, y, deg, rcond, full, w)136213631364def polycompanion(c):1365"""1366Return the companion matrix of c.13671368The companion matrix for power series cannot be made symmetric by1369scaling the basis, so this function differs from those for the1370orthogonal polynomials.13711372Parameters1373----------1374c : array_like13751-D array of polynomial coefficients ordered from low to high1376degree.13771378Returns1379-------1380mat : ndarray1381Companion matrix of dimensions (deg, deg).13821383Notes1384-----13851386.. versionadded:: 1.7.013871388"""1389# c is a trimmed copy1390[c] = pu.as_series([c])1391if len(c) < 2:1392raise ValueError('Series must have maximum degree of at least 1.')1393if len(c) == 2:1394return np.array([[-c[0]/c[1]]])13951396n = len(c) - 11397mat = np.zeros((n, n), dtype=c.dtype)1398bot = mat.reshape(-1)[n::n+1]1399bot[...] = 11400mat[:, -1] -= c[:-1]/c[-1]1401return mat140214031404def polyroots(c):1405"""1406Compute the roots of a polynomial.14071408Return the roots (a.k.a. "zeros") of the polynomial14091410.. math:: p(x) = \\sum_i c[i] * x^i.14111412Parameters1413----------1414c : 1-D array_like14151-D array of polynomial coefficients.14161417Returns1418-------1419out : ndarray1420Array of the roots of the polynomial. If all the roots are real,1421then `out` is also real, otherwise it is complex.14221423See Also1424--------1425numpy.polynomial.chebyshev.chebroots1426numpy.polynomial.legendre.legroots1427numpy.polynomial.laguerre.lagroots1428numpy.polynomial.hermite.hermroots1429numpy.polynomial.hermite_e.hermeroots14301431Notes1432-----1433The root estimates are obtained as the eigenvalues of the companion1434matrix, Roots far from the origin of the complex plane may have large1435errors due to the numerical instability of the power series for such1436values. Roots with multiplicity greater than 1 will also show larger1437errors as the value of the series near such points is relatively1438insensitive to errors in the roots. Isolated roots near the origin can1439be improved by a few iterations of Newton's method.14401441Examples1442--------1443>>> import numpy.polynomial.polynomial as poly1444>>> poly.polyroots(poly.polyfromroots((-1,0,1)))1445array([-1., 0., 1.])1446>>> poly.polyroots(poly.polyfromroots((-1,0,1))).dtype1447dtype('float64')1448>>> j = complex(0,1)1449>>> poly.polyroots(poly.polyfromroots((-j,0,j)))1450array([ 0.00000000e+00+0.j, 0.00000000e+00+1.j, 2.77555756e-17-1.j]) # may vary14511452"""1453# c is a trimmed copy1454[c] = pu.as_series([c])1455if len(c) < 2:1456return np.array([], dtype=c.dtype)1457if len(c) == 2:1458return np.array([-c[0]/c[1]])14591460# rotated companion matrix reduces error1461m = polycompanion(c)[::-1,::-1]1462r = la.eigvals(m)1463r.sort()1464return r146514661467#1468# polynomial class1469#14701471class Polynomial(ABCPolyBase):1472"""A power series class.14731474The Polynomial class provides the standard Python numerical methods1475'+', '-', '*', '//', '%', 'divmod', '**', and '()' as well as the1476attributes and methods listed in the `ABCPolyBase` documentation.14771478Parameters1479----------1480coef : array_like1481Polynomial coefficients in order of increasing degree, i.e.,1482``(1, 2, 3)`` give ``1 + 2*x + 3*x**2``.1483domain : (2,) array_like, optional1484Domain to use. The interval ``[domain[0], domain[1]]`` is mapped1485to the interval ``[window[0], window[1]]`` by shifting and scaling.1486The default value is [-1, 1].1487window : (2,) array_like, optional1488Window, see `domain` for its use. The default value is [-1, 1].14891490.. versionadded:: 1.6.014911492"""1493# Virtual Functions1494_add = staticmethod(polyadd)1495_sub = staticmethod(polysub)1496_mul = staticmethod(polymul)1497_div = staticmethod(polydiv)1498_pow = staticmethod(polypow)1499_val = staticmethod(polyval)1500_int = staticmethod(polyint)1501_der = staticmethod(polyder)1502_fit = staticmethod(polyfit)1503_line = staticmethod(polyline)1504_roots = staticmethod(polyroots)1505_fromroots = staticmethod(polyfromroots)15061507# Virtual properties1508domain = np.array(polydomain)1509window = np.array(polydomain)1510basis_name = None15111512@classmethod1513def _str_term_unicode(cls, i, arg_str):1514return f"ยท{arg_str}{i.translate(cls._superscript_mapping)}"15151516@staticmethod1517def _str_term_ascii(i, arg_str):1518return f" {arg_str}**{i}"15191520@staticmethod1521def _repr_latex_term(i, arg_str, needs_parens):1522if needs_parens:1523arg_str = rf"\left({arg_str}\right)"1524if i == 0:1525return '1'1526elif i == 1:1527return arg_str1528else:1529return f"{arg_str}^{{{i}}}"153015311532