Beispiel #1
0
 def testPolyint(self):
     p = pypol.poly1d([4, -3, 4, 1])
     py.test.raises(ValueError, lambda: funcs.polyint(ONE, -1))
     assert funcs.polyint(ONE) == x
     assert funcs.polyint(TWO) == 2*x
     assert funcs.polyint(p) == pypol.poly1d([1, -1, 2, 1, 0])
     assert funcs.polyint(p, 2) == funcs.polyint(funcs.polyint(p)) \
                                == pypol.polynomial('+ 1/5x^5 - 1/4x^4 + 2/3x^3 + 1/2x^2')
Beispiel #2
0
def abel(n, variable='a'):
    '''
    Returns the *n-th* Abel polynomial in ``x`` and *variable*.

    :raises: :exc:`ValueError` if *n* is negative
    :rtype: :class:`pypol.Polynomial`

    **Examples**

    ::

        >>> abel(0)
         + 1
        >>> abel(1)
         + x
        >>> abel(2)
         + x^2 - 2ax
        >>> abel(5)
         + x^5 - 20ax^4 + 150a^2x^3 - 500a^3x^2 + 625a^4x
        >>> abel(9)
         + x^9 - 72ax^8 + 2268a^2x^7 - 40824a^3x^6 + 459270a^4x^5 - 3306744a^5x^4 + 14880348a^6x^3 - 38263752a^7x^2 + 43046721a^8x

    .. versionadded:: 0.3
    '''

    if n < 0:
        raise ValueError('Abel polynomials only defined for n >= 0')
    if n == 0:
        return ONE
    if n == 1:
        return x
    p = poly1d([n])
    return x * (x - p*variable) ** (n - 1)
Beispiel #3
0
def quartic(poly):
    '''
    Finds all four roots of a fourth-degree polynomial *poly*::

    :raises: :exc:`AssertionError` if the polynomial's degree is not 4
    :rtype: 4 numbers (integer, float or complex) in a tuple

    **Examples**

    When all the roots are real::

        >>> from pypol.roots import *
        >>> from pypol.funcs import from_roots
        >>> p = from_roots([1, -4, 2, 3])
        >>> p
        + x^4 - 2x^3 - 13x^2 + 38x - 24
        >>> quartic(p)
        [1, 3.0, -4.0, 2.0]
        >>> map(p, quartic(p))
        [0, 0.0, 0.0, 0.0]
        >>> p = from_roots([-1, 42, 2, -19239])
        >>> p
        + x^4 + 19196x^3 - 827237x^2 + 769644x + 1616076
        >>> quartic(p)
        [-1, 42.0, -19239.0, 2.0]
        >>> map(p, quartic(p))
        [0, 0.0, 3.0, 0.0]

    Otherwise, if there are complex roots it loses precision and this is due to floating point numbers::

        >>> from pypol import *
        >>> from pypol.roots import *
        >>> 
        >>> p = poly1d([1, -3, 4, 2, 1])
        >>> p
        + x^4 - 3x^3 + 4x^2 + 2x + 1
        >>> quartic(p)
        ((1.7399843312651568+1.5686034407060976j), (1.7399843312651568-1.5686034407060976j), (-0.23998433126515695+0.35301727734776445j), (-0.23998433126515695-0.35301727734776445j))
        >>> map(p, quartic(p))
        [(8.8817841970012523e-16+8.4376949871511897e-15j), (8.8817841970012523e-16-8.4376949871511897e-15j), (8.3266726846886741e-15-2.7755575615628914e-15j), (8.3266726846886741e-15+2.7755575615628914e-15j)]
        >>> p = poly1d([4, -3, 4, 2, 1])
        >>> p
        + 4x^4 - 3x^3 + 4x^2 + 2x + 1
        >>> quartic(p)
        ((0.62277368382725595+1.0277469284099872j), (0.62277368382725595-1.0277469284099872j), (-0.24777368382725601+0.33425306402324328j), (-0.24777368382725601-0.33425306402324328j))
        >>> map(p, quartic(p))
        [(-2.5313084961453569e-14+3.730349362740526e-14j), (-2.5313084961453569e-14-3.730349362740526e-14j), (1.354472090042691e-14-1.2101430968414206e-14j), (1.354472090042691e-14+1.2101430968414206e-14j)]

    **References**

    `MathWorld <http://mathworld.wolfram.com/QuarticEquation.html>`_
    '''

    assert poly.degree == 4, 'The polynomial\'s degree must be 4'
    if len(poly.coefficients) == 5:
        a, b, c, d, e = poly.coefficients
    else:
        a, b, c, d, e = map(getattr(poly, 'get'), [4, 3, 2, 1, 0])

    poly = poly1d([a, b, c, d, e])
    if not poly(1):
        roots = [1]
        roots.extend(cubic(poly / 'x - 1'))
        return roots
    if not poly(-1):
        roots = [-1]
        roots.extend(cubic(poly / 'x + 1'))
        return roots
    #if b == d == 0: # biquadratic ## DECOMMENT THIS?
    #    l = poly.letters[0]
    #    for m in poly.monomials:
    #        m[1][l] = m[1][l] / 2
    #    print poly
    #    poly_ = poly(x=monomial(z=1))
    #    return quadratic(poly_)
    if (a, b) == (0, 0):
        return quadratic(Polynomial(poly[2:]))
    if a == 0:
        return cubic(Polynomial(poly[1:]))

    poly = poly.div_all(a, int=True)
    if len(poly.coefficients) == 5:
        a, b, c, d, e = map(float, poly.coefficients)
    else:
        a, b, c, d, e = map(float, map(getattr(poly, 'get'), [4, 3, 2, 1, 0]))

    f = c - 3*b**2 / 8
    g = d + b**3 / 8 - b*c / 2
    h = e - 3*b**4 / 256 + b**2 * c / 16 - b*d / 4
    y = monomial(y=1)
    eq = y**3 + (f / 2) * y**2 + ((f**2 - 4*h)/16)*y - g**2 / 64
    y1, y2, y3 = cubic(eq)
    roots = [cmath.sqrt(r) for r in (y1, y2, y3) if isinstance(r, complex)]
    if len(roots) >= 2:
        p, q = roots[:2]
    else:
        try:
            p, q = map(math.sqrt, [r for r in (y1, y2, y3) if r][:2])
        except ValueError:
            p, q = map(cmath.sqrt, [r for r in (y1, y2, y3) if r][:2])
    r = -g / (8*p*q)
    s = b / (4*a)
    x1 = p + q + r - s
    x2 = p - q - r - s
    x3 = - p + q - r - s
    x4 = - p - q + r - s
    return x1, x2, x3, x4
Beispiel #4
0
def cubic(poly):
    '''
    Finds the three roots of the polynomial *poly* solving the equation: :math:`ax^3 + bx^2 + cx + d = 0`.

    :raises: :exc:`AssertionError` if the polynomial's degree is not 3.
    :rtype: 3 numbers (integer, float or complex) in a tuple

    **Examples**

    ::

        >>> k = poly1d([3, -2, 45, -1])
        >>> k
        + 3x^3 - 2x^2 + 45x - 1
        >>> cubic(k)
        (0.022243478406449024, (0.3222115941301088+3.8576995055778323j), (0.3222115941301088-3.8576995055778323j))
        >>> k = poly1d([-9, 12, -2, -34])
        >>> k
        - 9x^3 + 12x^2 - 2x - 34
        >>> cubic(k)
        (-1.182116114781928, (1.2577247240576306+1.2703952413531459j), (1.2577247240576306-1.2703952413531459j))
        >>> k = poly1d([1, 1, 1, 1])
        >>> cubic(k)
        (-1.0, (5.551115123125783e-17+0.9999999999999999j), (5.551115123125783e-17-0.9999999999999999j))
        >>> k(-1.)
        0.0
        >>> k = poly1d([-1, 1, 0, 1])
        >>> cubic(k)
        (1.4655712318767669, (-0.23278561593838348+0.7925519925154489j), (-0.23278561593838348-0.7925519925154489j))
        >>> k(cubic(k)[0])
        3.9968028886505635e-15

    **References**

    `Wikipedia <http://en.wikipedia.org/wiki/Cubic_function>`_ | `MathWorld <http://mathworld.wolfram.com/CubicFormula.html>`_ | `1728 <http://www.1728.com/cubic.htm>`_
    '''

    poly = poly.filter()
    assert poly.degree == 3, 'The polynomial\'s degree must be 3'
    if len(poly.coefficients) == 4:
        a, b, c, d = poly.coefficients
    else:
        a, b, c, d = map(getattr(poly, 'get'), [3, 2, 1, 0])

    if a == 0:
        poly = poly1d([a, b, c, d])
        return quadratic(poly)
    f = ((3*c / a) - (b**2 / a**2)) / 3
    g = ((2*b**3 / a**3) - (9*b*c / a**2) + (27*d / a)) / 27
    h = (g**2 / 4) + (f**3 / 27)
    if h > 0: # only 1 root is real
        b_3a = - (b / (3*a))
        r = -(g / 2) + math.sqrt(h)
        if r < 0:
            s = -((-r) ** (1/3))
        else:
            s = r ** (1/3)
        t = -(g / 2) - math.sqrt(h)
        if t < 0:
            u = - ((-t) ** (1/3))
        else:
            u = t ** (1/3)

        x1 = (s + u) + b_3a
        x2 = complex(-(s + u) / 2 + b_3a, (s - u) * math.sqrt(3) / 2)
        x3 = complex(-(s + u) / 2 + b_3a, -(s - u) * math.sqrt(3) / 2)

        if poly(x1) and not poly(round(x1)):
            x1 = round(x1)
        return x1, x2, x3

    if f == g == h == 0: # all 3 roots are real and equal
        d_a = d / a
        if d_a < 0:
            x1 = x2 = x3 = (-d_a) ** (1/3)
        else:
            x1 = x2 = x3 = -((d / a) ** (1/3))

        x1 = x1*1e14; x1 = round(x1); x1 = (x1/1e14)
        x2 = x2*1e14; x2 = round(x2); x2 = (x2/1e14)
        x3 = x3*1e14; x3 = round(x3); x3 = (x3/1e14)

        return x1, x2, x3

    if h <= 0: # all 3 roots are real
        i = math.sqrt((g**2 / 4) - h)
        j_ = i ** (1 / 3)
        k = math.acos(-(g / (2*i)))
        l = -j_
        m = math.cos(k / 3)
        n = math.sqrt(3) * math.sin(k / 3)
        p = -(b / (3*a))
        x1 = 2*j_ * math.cos(k / 3) + p
        x2 = l * (m + n) + p
        x3 = l * (m - n) + p

        x1 = x1*1e14; x1 = round(x1); x1 = (x1/1e14)
        x2 = x2*1e14; x2 = round(x2); x2 = (x2/1e14)
        x3 = x3*1e14; x3 = round(x3); x3 = (x3/1e14)

        if poly(x1) and not poly(round(x1)):
            x1 = round(x1)
        if poly(x2) and not poly(round(x2)):
            x2 = round(x2)
        if poly(x3) and not poly(round(x3)):
            x3 = round(x3)
        return x1, x2, x3
Beispiel #5
0
 def testPolyder(self):
     p = pypol.poly1d([1]*4)
     assert pypol.poly1d([3, 2, 1]) == funcs.polyder(p)
     assert pypol.poly1d([6, 2]) == funcs.polyder(p, 2)
     assert pypol.poly1d([6]) == funcs.polyder(p, 3)
Beispiel #6
0
 def testDivisible(self):
     p = pypol.poly1d([2, 6, -4, 8]) * x
     assert funcs.divisible(p, p.gcd())