Buckets:
ktongue/docker_container / simsite /venv /lib /python3.14 /site-packages /numpy /polynomial /_polybase.py
| """ | |
| Abstract base class for the various polynomial Classes. | |
| The ABCPolyBase class provides the methods needed to implement the common API | |
| for the various polynomial classes. It operates as a mixin, but uses the | |
| abc module from the stdlib, hence it is only available for Python >= 2.6. | |
| """ | |
| import abc | |
| import numbers | |
| import os | |
| from collections.abc import Callable | |
| import numpy as np | |
| from . import polyutils as pu | |
| __all__ = ['ABCPolyBase'] | |
| class ABCPolyBase(abc.ABC): | |
| """An abstract base class for immutable series classes. | |
| ABCPolyBase provides the standard Python numerical methods | |
| '+', '-', '*', '//', '%', 'divmod', '**', and '()' along with the | |
| methods listed below. | |
| Parameters | |
| ---------- | |
| coef : array_like | |
| Series coefficients in order of increasing degree, i.e., | |
| ``(1, 2, 3)`` gives ``1*P_0(x) + 2*P_1(x) + 3*P_2(x)``, where | |
| ``P_i`` is the basis polynomials of degree ``i``. | |
| domain : (2,) array_like, optional | |
| Domain to use. The interval ``[domain[0], domain[1]]`` is mapped | |
| to the interval ``[window[0], window[1]]`` by shifting and scaling. | |
| The default value is the derived class domain. | |
| window : (2,) array_like, optional | |
| Window, see domain for its use. The default value is the | |
| derived class window. | |
| symbol : str, optional | |
| Symbol used to represent the independent variable in string | |
| representations of the polynomial expression, e.g. for printing. | |
| The symbol must be a valid Python identifier. Default value is 'x'. | |
| .. versionadded:: 1.24 | |
| Attributes | |
| ---------- | |
| coef : (N,) ndarray | |
| Series coefficients in order of increasing degree. | |
| domain : (2,) ndarray | |
| Domain that is mapped to window. | |
| window : (2,) ndarray | |
| Window that domain is mapped to. | |
| symbol : str | |
| Symbol representing the independent variable. | |
| Class Attributes | |
| ---------------- | |
| maxpower : int | |
| Maximum power allowed, i.e., the largest number ``n`` such that | |
| ``p(x)**n`` is allowed. This is to limit runaway polynomial size. | |
| domain : (2,) ndarray | |
| Default domain of the class. | |
| window : (2,) ndarray | |
| Default window of the class. | |
| """ | |
| # Not hashable | |
| __hash__ = None | |
| # Opt out of numpy ufuncs and Python ops with ndarray subclasses. | |
| __array_ufunc__ = None | |
| # Limit runaway size. T_n^m has degree n*m | |
| maxpower = 100 | |
| # Unicode character mappings for improved __str__ | |
| _superscript_mapping = str.maketrans({ | |
| "0": "⁰", | |
| "1": "¹", | |
| "2": "²", | |
| "3": "³", | |
| "4": "⁴", | |
| "5": "⁵", | |
| "6": "⁶", | |
| "7": "⁷", | |
| "8": "⁸", | |
| "9": "⁹" | |
| }) | |
| _subscript_mapping = str.maketrans({ | |
| "0": "₀", | |
| "1": "₁", | |
| "2": "₂", | |
| "3": "₃", | |
| "4": "₄", | |
| "5": "₅", | |
| "6": "₆", | |
| "7": "₇", | |
| "8": "₈", | |
| "9": "₉" | |
| }) | |
| # Some fonts don't support full unicode character ranges necessary for | |
| # the full set of superscripts and subscripts, including common/default | |
| # fonts in Windows shells/terminals. Therefore, default to ascii-only | |
| # printing on windows. | |
| _use_unicode = not os.name == 'nt' | |
| def symbol(self): | |
| return self._symbol | |
| def domain(self): | |
| pass | |
| def window(self): | |
| pass | |
| def basis_name(self): | |
| pass | |
| def _add(c1, c2): | |
| pass | |
| def _sub(c1, c2): | |
| pass | |
| def _mul(c1, c2): | |
| pass | |
| def _div(c1, c2): | |
| pass | |
| def _pow(c, pow, maxpower=None): | |
| pass | |
| def _val(x, c): | |
| pass | |
| def _int(c, m, k, lbnd, scl): | |
| pass | |
| def _der(c, m, scl): | |
| pass | |
| def _fit(x, y, deg, rcond, full): | |
| pass | |
| def _line(off, scl): | |
| pass | |
| def _roots(c): | |
| pass | |
| def _fromroots(r): | |
| pass | |
| def has_samecoef(self, other): | |
| """Check if coefficients match. | |
| Parameters | |
| ---------- | |
| other : class instance | |
| The other class must have the ``coef`` attribute. | |
| Returns | |
| ------- | |
| bool : boolean | |
| True if the coefficients are the same, False otherwise. | |
| """ | |
| return ( | |
| len(self.coef) == len(other.coef) | |
| and np.all(self.coef == other.coef) | |
| ) | |
| def has_samedomain(self, other): | |
| """Check if domains match. | |
| Parameters | |
| ---------- | |
| other : class instance | |
| The other class must have the ``domain`` attribute. | |
| Returns | |
| ------- | |
| bool : boolean | |
| True if the domains are the same, False otherwise. | |
| """ | |
| return np.all(self.domain == other.domain) | |
| def has_samewindow(self, other): | |
| """Check if windows match. | |
| Parameters | |
| ---------- | |
| other : class instance | |
| The other class must have the ``window`` attribute. | |
| Returns | |
| ------- | |
| bool : boolean | |
| True if the windows are the same, False otherwise. | |
| """ | |
| return np.all(self.window == other.window) | |
| def has_sametype(self, other): | |
| """Check if types match. | |
| Parameters | |
| ---------- | |
| other : object | |
| Class instance. | |
| Returns | |
| ------- | |
| bool : boolean | |
| True if other is same class as self | |
| """ | |
| return isinstance(other, self.__class__) | |
| def _get_coefficients(self, other): | |
| """Interpret other as polynomial coefficients. | |
| The `other` argument is checked to see if it is of the same | |
| class as self with identical domain and window. If so, | |
| return its coefficients, otherwise return `other`. | |
| Parameters | |
| ---------- | |
| other : anything | |
| Object to be checked. | |
| Returns | |
| ------- | |
| coef | |
| The coefficients of`other` if it is a compatible instance, | |
| of ABCPolyBase, otherwise `other`. | |
| Raises | |
| ------ | |
| TypeError | |
| When `other` is an incompatible instance of ABCPolyBase. | |
| """ | |
| if isinstance(other, ABCPolyBase): | |
| if not isinstance(other, self.__class__): | |
| raise TypeError("Polynomial types differ") | |
| elif not np.all(self.domain == other.domain): | |
| raise TypeError("Domains differ") | |
| elif not np.all(self.window == other.window): | |
| raise TypeError("Windows differ") | |
| elif self.symbol != other.symbol: | |
| raise ValueError("Polynomial symbols differ") | |
| return other.coef | |
| return other | |
| def __init__(self, coef, domain=None, window=None, symbol='x'): | |
| [coef] = pu.as_series([coef], trim=False) | |
| self.coef = coef | |
| if domain is not None: | |
| [domain] = pu.as_series([domain], trim=False) | |
| if len(domain) != 2: | |
| raise ValueError("Domain has wrong number of elements.") | |
| self.domain = domain | |
| if window is not None: | |
| [window] = pu.as_series([window], trim=False) | |
| if len(window) != 2: | |
| raise ValueError("Window has wrong number of elements.") | |
| self.window = window | |
| # Validation for symbol | |
| try: | |
| if not symbol.isidentifier(): | |
| raise ValueError( | |
| "Symbol string must be a valid Python identifier" | |
| ) | |
| # If a user passes in something other than a string, the above | |
| # results in an AttributeError. Catch this and raise a more | |
| # informative exception | |
| except AttributeError: | |
| raise TypeError("Symbol must be a non-empty string") | |
| self._symbol = symbol | |
| def __repr__(self): | |
| coef = repr(self.coef)[6:-1] | |
| domain = repr(self.domain)[6:-1] | |
| window = repr(self.window)[6:-1] | |
| name = self.__class__.__name__ | |
| return (f"{name}({coef}, domain={domain}, window={window}, " | |
| f"symbol='{self.symbol}')") | |
| def __format__(self, fmt_str): | |
| if fmt_str == '': | |
| return self.__str__() | |
| if fmt_str not in ('ascii', 'unicode'): | |
| raise ValueError( | |
| f"Unsupported format string '{fmt_str}' passed to " | |
| f"{self.__class__}.__format__. Valid options are " | |
| f"'ascii' and 'unicode'" | |
| ) | |
| if fmt_str == 'ascii': | |
| return self._generate_string(self._str_term_ascii) | |
| return self._generate_string(self._str_term_unicode) | |
| def __str__(self): | |
| if self._use_unicode: | |
| return self._generate_string(self._str_term_unicode) | |
| return self._generate_string(self._str_term_ascii) | |
| def _generate_string(self, term_method): | |
| """ | |
| Generate the full string representation of the polynomial, using | |
| ``term_method`` to generate each polynomial term. | |
| """ | |
| # Get configuration for line breaks | |
| linewidth = np.get_printoptions().get('linewidth', 75) | |
| if linewidth < 1: | |
| linewidth = 1 | |
| out = pu.format_float(self.coef[0]) | |
| off, scale = self.mapparms() | |
| scaled_symbol, needs_parens = self._format_term(pu.format_float, | |
| off, scale) | |
| if needs_parens: | |
| scaled_symbol = '(' + scaled_symbol + ')' | |
| for i, coef in enumerate(self.coef[1:]): | |
| out += " " | |
| power = str(i + 1) | |
| # Polynomial coefficient | |
| # The coefficient array can be an object array with elements that | |
| # will raise a TypeError with >= 0 (e.g. strings or Python | |
| # complex). In this case, represent the coefficient as-is. | |
| try: | |
| if coef >= 0: | |
| next_term = "+ " + pu.format_float(coef, parens=True) | |
| else: | |
| next_term = "- " + pu.format_float(-coef, parens=True) | |
| except TypeError: | |
| next_term = f"+ {coef}" | |
| # Polynomial term | |
| next_term += term_method(power, scaled_symbol) | |
| # Length of the current line with next term added | |
| line_len = len(out.split('\n')[-1]) + len(next_term) | |
| # If not the last term in the polynomial, it will be two | |
| # characters longer due to the +/- with the next term | |
| if i < len(self.coef[1:]) - 1: | |
| line_len += 2 | |
| # Handle linebreaking | |
| if line_len >= linewidth: | |
| next_term = next_term.replace(" ", "\n", 1) | |
| out += next_term | |
| return out | |
| def _str_term_unicode(cls, i, arg_str): | |
| """ | |
| String representation of single polynomial term using unicode | |
| characters for superscripts and subscripts. | |
| """ | |
| if cls.basis_name is None: | |
| raise NotImplementedError( | |
| "Subclasses must define either a basis_name, or override " | |
| "_str_term_unicode(cls, i, arg_str)" | |
| ) | |
| return (f"·{cls.basis_name}{i.translate(cls._subscript_mapping)}" | |
| f"({arg_str})") | |
| def _str_term_ascii(cls, i, arg_str): | |
| """ | |
| String representation of a single polynomial term using ** and _ to | |
| represent superscripts and subscripts, respectively. | |
| """ | |
| if cls.basis_name is None: | |
| raise NotImplementedError( | |
| "Subclasses must define either a basis_name, or override " | |
| "_str_term_ascii(cls, i, arg_str)" | |
| ) | |
| return f" {cls.basis_name}_{i}({arg_str})" | |
| def _repr_latex_term(cls, i, arg_str, needs_parens): | |
| if cls.basis_name is None: | |
| raise NotImplementedError( | |
| "Subclasses must define either a basis name, or override " | |
| "_repr_latex_term(i, arg_str, needs_parens)") | |
| # since we always add parens, we don't care if the expression needs them | |
| return f"{{{cls.basis_name}}}_{{{i}}}({arg_str})" | |
| def _repr_latex_scalar(x, parens=False): | |
| # TODO: we're stuck with disabling math formatting until we handle | |
| # exponents in this function | |
| return fr'\text{{{pu.format_float(x, parens=parens)}}}' | |
| def _format_term(self, scalar_format: Callable, off: float, scale: float): | |
| """ Format a single term in the expansion """ | |
| if off == 0 and scale == 1: | |
| term = self.symbol | |
| needs_parens = False | |
| elif scale == 1: | |
| term = f"{scalar_format(off)} + {self.symbol}" | |
| needs_parens = True | |
| elif off == 0: | |
| term = f"{scalar_format(scale)}{self.symbol}" | |
| needs_parens = True | |
| else: | |
| term = ( | |
| f"{scalar_format(off)} + " | |
| f"{scalar_format(scale)}{self.symbol}" | |
| ) | |
| needs_parens = True | |
| return term, needs_parens | |
| def _repr_latex_(self): | |
| # get the scaled argument string to the basis functions | |
| off, scale = self.mapparms() | |
| term, needs_parens = self._format_term(self._repr_latex_scalar, | |
| off, scale) | |
| mute = r"\color{{LightGray}}{{{}}}".format | |
| parts = [] | |
| for i, c in enumerate(self.coef): | |
| # prevent duplication of + and - signs | |
| if i == 0: | |
| coef_str = f"{self._repr_latex_scalar(c)}" | |
| elif not isinstance(c, numbers.Real): | |
| coef_str = f" + ({self._repr_latex_scalar(c)})" | |
| elif c >= 0: | |
| coef_str = f" + {self._repr_latex_scalar(c, parens=True)}" | |
| else: | |
| coef_str = f" - {self._repr_latex_scalar(-c, parens=True)}" | |
| # produce the string for the term | |
| term_str = self._repr_latex_term(i, term, needs_parens) | |
| if term_str == '1': | |
| part = coef_str | |
| else: | |
| part = rf"{coef_str}\,{term_str}" | |
| if c == 0: | |
| part = mute(part) | |
| parts.append(part) | |
| if parts: | |
| body = ''.join(parts) | |
| else: | |
| # in case somehow there are no coefficients at all | |
| body = '0' | |
| return rf"${self.symbol} \mapsto {body}$" | |
| # Pickle and copy | |
| def __getstate__(self): | |
| ret = self.__dict__.copy() | |
| ret['coef'] = self.coef.copy() | |
| ret['domain'] = self.domain.copy() | |
| ret['window'] = self.window.copy() | |
| ret['symbol'] = self.symbol | |
| return ret | |
| def __setstate__(self, dict): | |
| self.__dict__ = dict | |
| # Call | |
| def __call__(self, arg): | |
| arg = pu.mapdomain(arg, self.domain, self.window) | |
| return self._val(arg, self.coef) | |
| def __iter__(self): | |
| return iter(self.coef) | |
| def __len__(self): | |
| return len(self.coef) | |
| # Numeric properties. | |
| def __neg__(self): | |
| return self.__class__( | |
| -self.coef, self.domain, self.window, self.symbol | |
| ) | |
| def __pos__(self): | |
| return self | |
| def __add__(self, other): | |
| othercoef = self._get_coefficients(other) | |
| try: | |
| coef = self._add(self.coef, othercoef) | |
| except Exception: | |
| return NotImplemented | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def __sub__(self, other): | |
| othercoef = self._get_coefficients(other) | |
| try: | |
| coef = self._sub(self.coef, othercoef) | |
| except Exception: | |
| return NotImplemented | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def __mul__(self, other): | |
| othercoef = self._get_coefficients(other) | |
| try: | |
| coef = self._mul(self.coef, othercoef) | |
| except Exception: | |
| return NotImplemented | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def __truediv__(self, other): | |
| # there is no true divide if the rhs is not a Number, although it | |
| # could return the first n elements of an infinite series. | |
| # It is hard to see where n would come from, though. | |
| if not isinstance(other, numbers.Number) or isinstance(other, bool): | |
| raise TypeError( | |
| f"unsupported types for true division: " | |
| f"'{type(self)}', '{type(other)}'" | |
| ) | |
| return self.__floordiv__(other) | |
| def __floordiv__(self, other): | |
| res = self.__divmod__(other) | |
| if res is NotImplemented: | |
| return res | |
| return res[0] | |
| def __mod__(self, other): | |
| res = self.__divmod__(other) | |
| if res is NotImplemented: | |
| return res | |
| return res[1] | |
| def __divmod__(self, other): | |
| othercoef = self._get_coefficients(other) | |
| try: | |
| quo, rem = self._div(self.coef, othercoef) | |
| except ZeroDivisionError: | |
| raise | |
| except Exception: | |
| return NotImplemented | |
| quo = self.__class__(quo, self.domain, self.window, self.symbol) | |
| rem = self.__class__(rem, self.domain, self.window, self.symbol) | |
| return quo, rem | |
| def __pow__(self, other): | |
| coef = self._pow(self.coef, other, maxpower=self.maxpower) | |
| res = self.__class__(coef, self.domain, self.window, self.symbol) | |
| return res | |
| def __radd__(self, other): | |
| try: | |
| coef = self._add(other, self.coef) | |
| except Exception: | |
| return NotImplemented | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def __rsub__(self, other): | |
| try: | |
| coef = self._sub(other, self.coef) | |
| except Exception: | |
| return NotImplemented | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def __rmul__(self, other): | |
| try: | |
| coef = self._mul(other, self.coef) | |
| except Exception: | |
| return NotImplemented | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def __rtruediv__(self, other): | |
| # An instance of ABCPolyBase is not considered a | |
| # Number. | |
| return NotImplemented | |
| def __rfloordiv__(self, other): | |
| res = self.__rdivmod__(other) | |
| if res is NotImplemented: | |
| return res | |
| return res[0] | |
| def __rmod__(self, other): | |
| res = self.__rdivmod__(other) | |
| if res is NotImplemented: | |
| return res | |
| return res[1] | |
| def __rdivmod__(self, other): | |
| try: | |
| quo, rem = self._div(other, self.coef) | |
| except ZeroDivisionError: | |
| raise | |
| except Exception: | |
| return NotImplemented | |
| quo = self.__class__(quo, self.domain, self.window, self.symbol) | |
| rem = self.__class__(rem, self.domain, self.window, self.symbol) | |
| return quo, rem | |
| def __eq__(self, other): | |
| res = (isinstance(other, self.__class__) and | |
| np.all(self.domain == other.domain) and | |
| np.all(self.window == other.window) and | |
| (self.coef.shape == other.coef.shape) and | |
| np.all(self.coef == other.coef) and | |
| (self.symbol == other.symbol)) | |
| return res | |
| def __ne__(self, other): | |
| return not self.__eq__(other) | |
| # | |
| # Extra methods. | |
| # | |
| def copy(self): | |
| """Return a copy. | |
| Returns | |
| ------- | |
| new_series : series | |
| Copy of self. | |
| """ | |
| return self.__class__(self.coef, self.domain, self.window, self.symbol) | |
| def degree(self): | |
| """The degree of the series. | |
| Returns | |
| ------- | |
| degree : int | |
| Degree of the series, one less than the number of coefficients. | |
| Examples | |
| -------- | |
| Create a polynomial object for ``1 + 7*x + 4*x**2``: | |
| >>> np.polynomial.set_default_printstyle("unicode") | |
| >>> poly = np.polynomial.Polynomial([1, 7, 4]) | |
| >>> print(poly) | |
| 1.0 + 7.0·x + 4.0·x² | |
| >>> poly.degree() | |
| 2 | |
| Note that this method does not check for non-zero coefficients. | |
| You must trim the polynomial to remove any trailing zeroes: | |
| >>> poly = np.polynomial.Polynomial([1, 7, 0]) | |
| >>> print(poly) | |
| 1.0 + 7.0·x + 0.0·x² | |
| >>> poly.degree() | |
| 2 | |
| >>> poly.trim().degree() | |
| 1 | |
| """ | |
| return len(self) - 1 | |
| def cutdeg(self, deg): | |
| """Truncate series to the given degree. | |
| Reduce the degree of the series to `deg` by discarding the | |
| high order terms. If `deg` is greater than the current degree a | |
| copy of the current series is returned. This can be useful in least | |
| squares where the coefficients of the high degree terms may be very | |
| small. | |
| Parameters | |
| ---------- | |
| deg : non-negative int | |
| The series is reduced to degree `deg` by discarding the high | |
| order terms. The value of `deg` must be a non-negative integer. | |
| Returns | |
| ------- | |
| new_series : series | |
| New instance of series with reduced degree. | |
| """ | |
| return self.truncate(deg + 1) | |
| def trim(self, tol=0): | |
| """Remove trailing coefficients | |
| Remove trailing coefficients until a coefficient is reached whose | |
| absolute value greater than `tol` or the beginning of the series is | |
| reached. If all the coefficients would be removed the series is set | |
| to ``[0]``. A new series instance is returned with the new | |
| coefficients. The current instance remains unchanged. | |
| Parameters | |
| ---------- | |
| tol : non-negative number. | |
| All trailing coefficients less than `tol` will be removed. | |
| Returns | |
| ------- | |
| new_series : series | |
| New instance of series with trimmed coefficients. | |
| """ | |
| coef = pu.trimcoef(self.coef, tol) | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def truncate(self, size): | |
| """Truncate series to length `size`. | |
| Reduce the series to length `size` by discarding the high | |
| degree terms. The value of `size` must be a positive integer. This | |
| can be useful in least squares where the coefficients of the | |
| high degree terms may be very small. | |
| Parameters | |
| ---------- | |
| size : positive int | |
| The series is reduced to length `size` by discarding the high | |
| degree terms. The value of `size` must be a positive integer. | |
| Returns | |
| ------- | |
| new_series : series | |
| New instance of series with truncated coefficients. | |
| """ | |
| isize = int(size) | |
| if isize != size or isize < 1: | |
| raise ValueError("size must be a positive integer") | |
| if isize >= len(self.coef): | |
| coef = self.coef | |
| else: | |
| coef = self.coef[:isize] | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def convert(self, domain=None, kind=None, window=None): | |
| """Convert series to a different kind and/or domain and/or window. | |
| Parameters | |
| ---------- | |
| domain : array_like, optional | |
| The domain of the converted series. If the value is None, | |
| the default domain of `kind` is used. | |
| kind : class, optional | |
| The polynomial series type class to which the current instance | |
| should be converted. If kind is None, then the class of the | |
| current instance is used. | |
| window : array_like, optional | |
| The window of the converted series. If the value is None, | |
| the default window of `kind` is used. | |
| Returns | |
| ------- | |
| new_series : series | |
| The returned class can be of different type than the current | |
| instance and/or have a different domain and/or different | |
| window. | |
| Notes | |
| ----- | |
| Conversion between domains and class types can result in | |
| numerically ill defined series. | |
| """ | |
| if kind is None: | |
| kind = self.__class__ | |
| if domain is None: | |
| domain = kind.domain | |
| if window is None: | |
| window = kind.window | |
| return self(kind.identity(domain, window=window, symbol=self.symbol)) | |
| def mapparms(self): | |
| """Return the mapping parameters. | |
| The returned values define a linear map ``off + scl*x`` that is | |
| applied to the input arguments before the series is evaluated. The | |
| map depends on the ``domain`` and ``window``; if the current | |
| ``domain`` is equal to the ``window`` the resulting map is the | |
| identity. If the coefficients of the series instance are to be | |
| used by themselves outside this class, then the linear function | |
| must be substituted for the ``x`` in the standard representation of | |
| the base polynomials. | |
| Returns | |
| ------- | |
| off, scl : float or complex | |
| The mapping function is defined by ``off + scl*x``. | |
| Notes | |
| ----- | |
| If the current domain is the interval ``[l1, r1]`` and the window | |
| is ``[l2, r2]``, then the linear mapping function ``L`` is | |
| defined by the equations:: | |
| L(l1) = l2 | |
| L(r1) = r2 | |
| """ | |
| return pu.mapparms(self.domain, self.window) | |
| def integ(self, m=1, k=[], lbnd=None): | |
| """Integrate. | |
| Return a series instance that is the definite integral of the | |
| current series. | |
| Parameters | |
| ---------- | |
| m : non-negative int | |
| The number of integrations to perform. | |
| k : array_like | |
| Integration constants. The first constant is applied to the | |
| first integration, the second to the second, and so on. The | |
| list of values must less than or equal to `m` in length and any | |
| missing values are set to zero. | |
| lbnd : Scalar | |
| The lower bound of the definite integral. | |
| Returns | |
| ------- | |
| new_series : series | |
| A new series representing the integral. The domain is the same | |
| as the domain of the integrated series. | |
| """ | |
| off, scl = self.mapparms() | |
| if lbnd is None: | |
| lbnd = 0 | |
| else: | |
| lbnd = off + scl * lbnd | |
| coef = self._int(self.coef, m, k, lbnd, 1. / scl) | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def deriv(self, m=1): | |
| """Differentiate. | |
| Return a series instance of that is the derivative of the current | |
| series. | |
| Parameters | |
| ---------- | |
| m : non-negative int | |
| Find the derivative of order `m`. | |
| Returns | |
| ------- | |
| new_series : series | |
| A new series representing the derivative. The domain is the same | |
| as the domain of the differentiated series. | |
| """ | |
| off, scl = self.mapparms() | |
| coef = self._der(self.coef, m, scl) | |
| return self.__class__(coef, self.domain, self.window, self.symbol) | |
| def roots(self): | |
| """Return the roots of the series polynomial. | |
| Compute the roots for the series. Note that the accuracy of the | |
| roots decreases the further outside the `domain` they lie. | |
| Returns | |
| ------- | |
| roots : ndarray | |
| Array containing the roots of the series. | |
| """ | |
| roots = self._roots(self.coef) | |
| return pu.mapdomain(roots, self.window, self.domain) | |
| def linspace(self, n=100, domain=None): | |
| """Return x, y values at equally spaced points in domain. | |
| Returns the x, y values at `n` linearly spaced points across the | |
| domain. Here y is the value of the polynomial at the points x. By | |
| default the domain is the same as that of the series instance. | |
| This method is intended mostly as a plotting aid. | |
| Parameters | |
| ---------- | |
| n : int, optional | |
| Number of point pairs to return. The default value is 100. | |
| domain : {None, array_like}, optional | |
| If not None, the specified domain is used instead of that of | |
| the calling instance. It should be of the form ``[beg,end]``. | |
| The default is None which case the class domain is used. | |
| Returns | |
| ------- | |
| x, y : ndarray | |
| x is equal to linspace(self.domain[0], self.domain[1], n) and | |
| y is the series evaluated at element of x. | |
| """ | |
| if domain is None: | |
| domain = self.domain | |
| x = np.linspace(domain[0], domain[1], n) | |
| y = self(x) | |
| return x, y | |
| def fit(cls, x, y, deg, domain=None, rcond=None, full=False, w=None, | |
| window=None, symbol='x'): | |
| """Least squares fit to data. | |
| Return a series instance that is the least squares fit to the data | |
| `y` sampled at `x`. The domain of the returned instance can be | |
| specified and this will often result in a superior fit with less | |
| chance of ill conditioning. | |
| Parameters | |
| ---------- | |
| x : array_like, shape (M,) | |
| x-coordinates of the M sample points ``(x[i], y[i])``. | |
| y : array_like, shape (M,) | |
| y-coordinates of the M sample points ``(x[i], y[i])``. | |
| deg : int or 1-D array_like | |
| Degree(s) of the fitting polynomials. If `deg` is a single integer | |
| all terms up to and including the `deg`'th term are included in the | |
| fit. For NumPy versions >= 1.11.0 a list of integers specifying the | |
| degrees of the terms to include may be used instead. | |
| domain : {None, [beg, end], []}, optional | |
| Domain to use for the returned series. If ``None``, | |
| then a minimal domain that covers the points `x` is chosen. If | |
| ``[]`` the class domain is used. The default value was the | |
| class domain in NumPy 1.4 and ``None`` in later versions. | |
| The ``[]`` option was added in numpy 1.5.0. | |
| rcond : float, optional | |
| Relative condition number of the fit. Singular values smaller | |
| than this relative to the largest singular value will be | |
| ignored. The default value is ``len(x)*eps``, where eps is the | |
| relative precision of the float type, about 2e-16 in most | |
| cases. | |
| full : bool, optional | |
| Switch determining nature of return value. When it is False | |
| (the default) just the coefficients are returned, when True | |
| diagnostic information from the singular value decomposition is | |
| also returned. | |
| w : array_like, shape (M,), optional | |
| Weights. If not None, the weight ``w[i]`` applies to the unsquared | |
| residual ``y[i] - y_hat[i]`` at ``x[i]``. Ideally the weights are | |
| chosen so that the errors of the products ``w[i]*y[i]`` all have | |
| the same variance. When using inverse-variance weighting, use | |
| ``w[i] = 1/sigma(y[i])``. The default value is None. | |
| window : {[beg, end]}, optional | |
| Window to use for the returned series. The default | |
| value is the default class domain | |
| symbol : str, optional | |
| Symbol representing the independent variable. Default is 'x'. | |
| Returns | |
| ------- | |
| new_series : series | |
| A series that represents the least squares fit to the data and | |
| has the domain and window specified in the call. If the | |
| coefficients for the unscaled and unshifted basis polynomials are | |
| of interest, do ``new_series.convert().coef``. | |
| [resid, rank, sv, rcond] : list | |
| These values are only returned if ``full == True`` | |
| - resid -- sum of squared residuals of the least squares fit | |
| - rank -- the numerical rank of the scaled Vandermonde matrix | |
| - sv -- singular values of the scaled Vandermonde matrix | |
| - rcond -- value of `rcond`. | |
| For more details, see `linalg.lstsq`. | |
| """ | |
| if domain is None: | |
| domain = pu.getdomain(x) | |
| if domain[0] == domain[1]: | |
| domain[0] -= 1 | |
| domain[1] += 1 | |
| elif isinstance(domain, list) and len(domain) == 0: | |
| domain = cls.domain | |
| if window is None: | |
| window = cls.window | |
| xnew = pu.mapdomain(x, domain, window) | |
| res = cls._fit(xnew, y, deg, w=w, rcond=rcond, full=full) | |
| if full: | |
| [coef, status] = res | |
| return ( | |
| cls(coef, domain=domain, window=window, symbol=symbol), status | |
| ) | |
| else: | |
| coef = res | |
| return cls(coef, domain=domain, window=window, symbol=symbol) | |
| def fromroots(cls, roots, domain=[], window=None, symbol='x'): | |
| """Return series instance that has the specified roots. | |
| Returns a series representing the product | |
| ``(x - r[0])*(x - r[1])*...*(x - r[n-1])``, where ``r`` is a | |
| list of roots. | |
| Parameters | |
| ---------- | |
| roots : array_like | |
| List of roots. | |
| domain : {[], None, array_like}, optional | |
| Domain for the resulting series. If None the domain is the | |
| interval from the smallest root to the largest. If [] the | |
| domain is the class domain. The default is []. | |
| window : {None, array_like}, optional | |
| Window for the returned series. If None the class window is | |
| used. The default is None. | |
| symbol : str, optional | |
| Symbol representing the independent variable. Default is 'x'. | |
| Returns | |
| ------- | |
| new_series : series | |
| Series with the specified roots. | |
| """ | |
| [roots] = pu.as_series([roots], trim=False) | |
| if domain is None: | |
| domain = pu.getdomain(roots) | |
| elif isinstance(domain, list) and len(domain) == 0: | |
| domain = cls.domain | |
| if window is None: | |
| window = cls.window | |
| deg = len(roots) | |
| off, scl = pu.mapparms(domain, window) | |
| rnew = off + scl * roots | |
| coef = cls._fromroots(rnew) / scl**deg | |
| return cls(coef, domain=domain, window=window, symbol=symbol) | |
| def identity(cls, domain=None, window=None, symbol='x'): | |
| """Identity function. | |
| If ``p`` is the returned series, then ``p(x) == x`` for all | |
| values of x. | |
| Parameters | |
| ---------- | |
| domain : {None, array_like}, optional | |
| If given, the array must be of the form ``[beg, end]``, where | |
| ``beg`` and ``end`` are the endpoints of the domain. If None is | |
| given then the class domain is used. The default is None. | |
| window : {None, array_like}, optional | |
| If given, the resulting array must be if the form | |
| ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of | |
| the window. If None is given then the class window is used. The | |
| default is None. | |
| symbol : str, optional | |
| Symbol representing the independent variable. Default is 'x'. | |
| Returns | |
| ------- | |
| new_series : series | |
| Series of representing the identity. | |
| """ | |
| if domain is None: | |
| domain = cls.domain | |
| if window is None: | |
| window = cls.window | |
| off, scl = pu.mapparms(window, domain) | |
| coef = cls._line(off, scl) | |
| return cls(coef, domain, window, symbol) | |
| def basis(cls, deg, domain=None, window=None, symbol='x'): | |
| """Series basis polynomial of degree `deg`. | |
| Returns the series representing the basis polynomial of degree `deg`. | |
| Parameters | |
| ---------- | |
| deg : int | |
| Degree of the basis polynomial for the series. Must be >= 0. | |
| domain : {None, array_like}, optional | |
| If given, the array must be of the form ``[beg, end]``, where | |
| ``beg`` and ``end`` are the endpoints of the domain. If None is | |
| given then the class domain is used. The default is None. | |
| window : {None, array_like}, optional | |
| If given, the resulting array must be if the form | |
| ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of | |
| the window. If None is given then the class window is used. The | |
| default is None. | |
| symbol : str, optional | |
| Symbol representing the independent variable. Default is 'x'. | |
| Returns | |
| ------- | |
| new_series : series | |
| A series with the coefficient of the `deg` term set to one and | |
| all others zero. | |
| """ | |
| if domain is None: | |
| domain = cls.domain | |
| if window is None: | |
| window = cls.window | |
| ideg = int(deg) | |
| if ideg != deg or ideg < 0: | |
| raise ValueError("deg must be non-negative integer") | |
| return cls([0] * ideg + [1], domain, window, symbol) | |
| def cast(cls, series, domain=None, window=None): | |
| """Convert series to series of this class. | |
| The `series` is expected to be an instance of some polynomial | |
| series of one of the types supported by by the numpy.polynomial | |
| module, but could be some other class that supports the convert | |
| method. | |
| Parameters | |
| ---------- | |
| series : series | |
| The series instance to be converted. | |
| domain : {None, array_like}, optional | |
| If given, the array must be of the form ``[beg, end]``, where | |
| ``beg`` and ``end`` are the endpoints of the domain. If None is | |
| given then the class domain is used. The default is None. | |
| window : {None, array_like}, optional | |
| If given, the resulting array must be if the form | |
| ``[beg, end]``, where ``beg`` and ``end`` are the endpoints of | |
| the window. If None is given then the class window is used. The | |
| default is None. | |
| Returns | |
| ------- | |
| new_series : series | |
| A series of the same kind as the calling class and equal to | |
| `series` when evaluated. | |
| See Also | |
| -------- | |
| convert : similar instance method | |
| """ | |
| if domain is None: | |
| domain = cls.domain | |
| if window is None: | |
| window = cls.window | |
| return series.convert(domain, cls, window) | |
Xet Storage Details
- Size:
- 39.4 kB
- Xet hash:
- 81c4b61876374b88763f8e71b5726b95cea01b0f2b44edac4140e6a92bb5e5b8
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.