Exemplo n.º 1
0
def sortable_proxy(
    poly: PolyLike,
    graded: bool = False,
    reverse: bool = False,
) -> numpy.ndarray:
    """
    Create a numerical proxy for a polynomial to allow compare.

    As polynomials are not inherently sortable, values are sorted using the
    highest `lexicographical` ordering. Between the values that have the same
    highest ordering, the elements are sorted using the coefficients. This also
    ensures that the method behaves as expected with ``numpy.ndarray``.

    Args:
        poly:
            Polynomial to convert into something sortable.
        graded:
            Graded sorting, meaning the indices are always sorted by the index
            sum. E.g. ``q0**2*q1**2*q2**2`` has an exponent sum of 6, and will
            therefore be consider larger than both ``q0**3*q1*q2``,
            ``q0*q1**3*q2`` and ``q0*q1*z**3``.
        reverse:
            Reverses lexicographical sorting meaning that ``q0*q1**3`` is
            considered bigger than ``q0**3*q1``, instead of the opposite.

    Returns:
        Integer array where ``a > b`` is retained for the giving rule of
        ``ordering``.

    Examples:
        >>> q0, q1 = numpoly.variable(2)
        >>> poly = numpoly.polynomial(
        ...     [q0**2, 2*q0, 3*q1, 4*q0, 5])
        >>> numpoly.sortable_proxy(poly)
        array([3, 1, 4, 2, 0])
        >>> numpoly.sortable_proxy(poly, reverse=True)
        array([4, 2, 1, 3, 0])
        >>> numpoly.sortable_proxy([8, 4, 10, -100])
        array([2, 1, 3, 0])
        >>> numpoly.sortable_proxy([[8, 4], [10, -100]])
        array([[2, 1],
               [3, 0]])

    """
    poly = numpoly.aspolynomial(poly)
    coefficients = poly.coefficients
    proxy = numpy.tile(-1, poly.shape)
    largest = numpoly.lead_exponent(poly, graded=graded, reverse=reverse)

    for idx in numpoly.glexsort(
            poly.exponents.T, graded=graded, reverse=reverse):

        indices = numpy.all(largest == poly.exponents[idx], axis=-1)
        values = numpy.argsort(coefficients[idx][indices])
        proxy[indices] = numpy.argsort(values)+numpy.max(proxy)+1

    proxy = numpy.argsort(numpy.argsort(proxy.ravel())).reshape(proxy.shape)
    return proxy
Exemplo n.º 2
0
def lead_exponent(
    poly: PolyLike,
    graded: bool = False,
    reverse: bool = False,
) -> numpy.ndarray:
    """
    Find the lead exponents for each polynomial.

    As polynomials are not inherently sortable, values are sorted using the
    highest `lexicographical` ordering. Between the values that have the same
    highest ordering, the elements are sorted using the coefficients.

    Args:
        poly:
            Polynomial to locate exponents on.
        graded:
            Graded sorting, meaning the indices are always sorted by the index
            sum. E.g. ``q0**2*q1**2*q2**2`` has an exponent sum of 6, and will
            therefore be consider larger than both ``q0**3*q1*q2``,
            ``q0*q1**3*q2`` and ``q0*q1*z**3``.
        reverse:
            Reverses lexicographical sorting meaning that ``q0*q1**3`` is
            considered bigger than ``q0**3*q1``, instead of the opposite.

    Returns:
        Integer array with the largest exponents in the polynomials. The
        shape is ``poly.shape + (len(poly.names),)``. The extra dimension
        is used to indicate the exponent for the different indeterminants.

    Examples:
        >>> q0 = numpoly.variable()
        >>> numpoly.lead_exponent([1, q0+1, q0**2+q0+1]).T
        array([[0, 1, 2]])
        >>> q0, q1 = numpoly.variable(2)
        >>> numpoly.lead_exponent(
        ...     [1, q0, q1, q0*q1, q0**3-1]).T
        array([[0, 1, 0, 1, 3],
               [0, 0, 1, 1, 0]])

    """
    poly_ = numpoly.aspolynomial(poly)
    shape = poly_.shape
    poly = poly_.ravel()
    out = numpy.zeros(poly_.shape + (len(poly_.names), ), dtype=int)
    if not poly_.size:
        return out
    for idx in numpoly.glexsort(poly_.exponents.T,
                                graded=graded,
                                reverse=reverse):
        out[poly_.coefficients[idx] != 0] = poly_.exponents[idx]
    return out.reshape(shape + (len(poly_.names), ))
Exemplo n.º 3
0
def lead_coefficient(
        poly: PolyLike,
        graded: bool = False,
        reverse: bool = False,
) -> numpy.ndarray:
    """
    Find the lead coefficients for each polynomial.

    As polynomials are not inherently sortable, values are sorted using the
    highest `lexicographical` ordering. Between the values that have the same
    highest ordering, the elements are sorted using the coefficients.

    Args:
        poly:
            Polynomial to locate coefficients on.
        graded:
            Graded sorting, meaning the indices are always sorted by the index
            sum. E.g. ``q0**2*q1**2*q2**2`` has an exponent sum of 6, and will
            therefore be consider larger than both ``q0**3*q1*q2``,
            ``q0*q1**3*q2`` and ``q0*q1*z**3``.
        reverse:
            Reverses lexicographical sorting meaning that ``q0*q1**3`` is
            considered bigger than ``q0**3*q1``, instead of the opposite.

    Returns:
        Array of same shape and type as `poly`, containing all the lead
        coefficients.

    Examples:
        >>> q0, q1 = numpoly.variable(2)
        >>> numpoly.lead_coefficient(q0+2*q0**2+3*q0**3)
        3
        >>> numpoly.lead_coefficient([1-4*q1+q0, 2*q0**2-q1, 4])
        array([-4, -1,  4])

    """
    poly = numpoly.aspolynomial(poly)
    out = numpy.zeros(poly.shape, dtype=poly.dtype)
    if not out.size:
        return out
    for idx in numpoly.glexsort(
            poly.exponents.T, graded=graded, reverse=reverse):
        values = poly.coefficients[idx]
        indices = values != 0
        out[indices] = values[indices]
    if not poly.shape:
        out = out.item()
    return out
Exemplo n.º 4
0
def _to_string(
    poly: ndpoly,
    precision: float,
    suppress_small: bool,
) -> List[str]:
    """Backend for to_string."""
    exponents = poly.exponents.copy()
    coefficients = poly.coefficients
    options = numpoly.get_options()
    output: List[str] = []
    indices = numpoly.glexsort(
        exponents.T,
        graded=options["display_graded"],
        reverse=options["display_reverse"],
    )
    if options["display_inverse"]:
        indices = indices[::-1]
    for idx in indices:

        if not coefficients[idx]:
            continue
        if suppress_small and abs(coefficients[idx]) < 10**-precision:
            continue

        if coefficients[idx] == 1 and any(exponents[idx]):
            out = ""
        elif coefficients[idx] == -1 and any(exponents[idx]):
            out = "-"
        else:
            out = str(coefficients[idx])

        exps_and_names = list(zip(exponents[idx], poly.names))
        for exponent, indeterminant in exps_and_names:
            if exponent:
                if out not in ("", "-"):
                    out += options["display_multiply"]
                out += indeterminant
            if exponent > 1:
                out += options["display_exponent"] + str(exponent)
        if output and float(coefficients[idx]) >= 0:
            out = "+" + out
        output.append(out)

    return output
Exemplo n.º 5
0
def test_glexsort():
    indices = numpy.array([[0, 0, 0, 1, 2, 1],
                           [1, 2, 0, 0, 0, 1]])
    assert numpy.all(indices.T[numpoly.glexsort(indices)].T ==
                     [[0, 1, 2, 0, 1, 0],
                      [0, 0, 0, 1, 1, 2]])
    assert numpy.all(indices.T[numpoly.glexsort(indices, graded=True)].T ==
                     [[0, 1, 0, 2, 1, 0],
                      [0, 0, 1, 0, 1, 2]])
    assert numpy.all(indices.T[numpoly.glexsort(indices, reverse=True)].T ==
                     [[0, 0, 0, 1, 1, 2],
                      [0, 1, 2, 0, 1, 0]])
    assert numpy.all(indices.T[numpoly.glexsort(indices, graded=True, reverse=True)].T ==
                     [[0, 0, 1, 0, 1, 2],
                      [0, 1, 0, 2, 1, 0]])

    indices = numpy.array([4, 5, 6, 3, 2, 1])
    assert numpy.all(numpoly.glexsort(indices) == [5, 4, 3, 0, 1, 2])
    indices = numpy.array([[4, 5, 6, 3, 2, 1]])
    assert numpy.all(numpoly.glexsort(indices) == [5, 4, 3, 0, 1, 2])
Exemplo n.º 6
0
def greater(
    x1: PolyLike,
    x2: PolyLike,
    out: Optional[numpy.ndarray] = None,
    **kwargs: Any,
) -> numpy.ndarray:
    """
    Return the truth value of (x1 > x2) element-wise.

    Args:
        x1, x2:
            Input arrays. If ``x1.shape != x2.shape``, they must be
            broadcastable to a common shape (which becomes the shape of the
            output).
        out:
            A location into which the result is stored. If provided, it must
            have a shape that the inputs broadcast to. If not provided or
            `None`, a freshly-allocated array is returned. A tuple (possible
            only as a keyword argument) must have length equal to the number of
            outputs.
        where:
            This condition is broadcast over the input. At locations where the
            condition is True, the `out` array will be set to the ufunc result.
            Elsewhere, the `out` array will retain its original value. Note
            that if an uninitialized `out` array is created via the default
            ``out=None``, locations within it where the condition is False will
            remain uninitialized.
        kwargs:
            Keyword args passed to numpy.ufunc.

    Returns:
        Output array, element-wise comparison of `x1` and `x2`. Typically of
        type bool, unless ``dtype=object`` is passed. This is a scalar if both
        `x1` and `x2` are scalars.

    Examples:
        >>> q0, q1 = numpoly.variable(2)
        >>> numpoly.greater(3, 4)
        False
        >>> numpoly.greater(4*q0, 3*q0)
        True
        >>> numpoly.greater(q0, q1)
        False
        >>> numpoly.greater(q0**2, q0)
        True
        >>> numpoly.greater([1, q0, q0**2, q0**3], q1)
        array([False, False,  True,  True])
        >>> numpoly.greater(q0+1, q0-1)
        True
        >>> numpoly.greater(q0, q0)
        False

    """
    x1, x2 = numpoly.align_polynomials(x1, x2)
    coefficients1 = x1.coefficients
    coefficients2 = x2.coefficients
    if out is None:
        out = numpy.greater(coefficients1[0], coefficients2[0], **kwargs)
    if not out.shape:
        return greater(x1.ravel(), x2.ravel(), out=out.ravel()).item()

    options = numpoly.get_options()
    for idx in numpoly.glexsort(x1.exponents.T,
                                graded=options["sort_graded"],
                                reverse=options["sort_reverse"]):

        indices = (coefficients1[idx] != 0) | (coefficients2[idx] != 0)
        indices &= coefficients1[idx] != coefficients2[idx]
        out[indices] = numpy.greater(coefficients1[idx], coefficients2[idx],
                                     **kwargs)[indices]
    return out
Exemplo n.º 7
0
def minimum(
    x1: PolyLike,
    x2: PolyLike,
    out: Optional[ndpoly] = None,
    **kwargs: Any,
) -> ndpoly:
    """
    Element-wise minimum of array elements.

    Compare two arrays and returns a new array containing the element-wise
    minima. If one of the elements being compared is a NaN, then that
    element is returned. If both elements are NaNs then the first is
    returned. The latter distinction is important for complex NaNs, which
    are defined as at least one of the real or imaginary parts being a NaN.
    The net effect is that NaNs are propagated.

    Args:
        x1, x2 :
            The arrays holding the elements to be compared. If ``x1.shape !=
            x2.shape``, they must be broadcastable to a common shape (which
            becomes the shape of the output).
        out:
            A location into which the result is stored. If provided, it must
            have a shape that the inputs broadcast to. If not provided or
            `None`, a freshly-allocated array is returned. A tuple (possible
            only as a keyword argument) must have length equal to the number of
            outputs.
        where:
            This condition is broadcast over the input. At locations where the
            condition is True, the `out` array will be set to the ufunc result.
            Elsewhere, the `out` array will retain its original value. Note
            that if an uninitialized `out` array is created via the default
            ``out=None``, locations within it where the condition is False will
            remain uninitialized.
        kwargs:
            Keyword args passed to numpy.ufunc.

    Returns:
        The minimum of `x1` and `x2`, element-wise. This is a scalar if
        both `x1` and `x2` are scalars.

    Examples:
        >>> q0, q1 = numpoly.variable(2)
        >>> numpoly.minimum(3, 4)
        polynomial(3)
        >>> numpoly.minimum(4*q0, 3*q0)
        polynomial(3*q0)
        >>> numpoly.minimum(q0, q1)
        polynomial(q0)
        >>> numpoly.minimum(q0**2, q0)
        polynomial(q0)
        >>> numpoly.minimum([1, q0, q0**2, q0**3], q1)
        polynomial([1, q0, q1, q1])
        >>> numpoly.minimum(q0+1, q0-1)
        polynomial(q0-1)

    """
    del out
    x1, x2 = numpoly.align_polynomials(x1, x2)
    coefficients1 = x1.coefficients
    coefficients2 = x2.coefficients
    out_ = numpy.zeros(x1.shape, dtype=bool)

    options = numpoly.get_options()
    for idx in numpoly.glexsort(x1.exponents.T,
                                graded=options["sort_graded"],
                                reverse=options["sort_reverse"]):

        indices = (coefficients1[idx] != 0) | (coefficients2[idx] != 0)
        indices = coefficients1[idx] != coefficients2[idx]
        out_[indices] = (coefficients1[idx] < coefficients2[idx])[indices]
    return numpoly.where(out_, x1, x2)