예제 #1
0
파일: series.py 프로젝트: rubik/pypol-build
def laguerre_g(n, a='a'):
    '''
    Returns the *n-th* generalized Laguerre polynomial in ``x``.

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

    **Examples**

    ::

        >>> l(0)
        + 1
        >>> l(1)
        + a + 1 - x
        >>> l(2)
        + 1/2a^2 + 3/2a - ax + 1 - 2x + 1/2x^2
        >>> l(3)
        + 1/6a^3 + a^2 - 1/2a^2x + 11/6a - 5/2ax + 1/2ax^2 + 1 - 3x - 1/6x^3 + 3/2x^2
        >>> l(2, 'k')
        + 1/2k^2 + 3/2k - kx + 1 - 2x + 1/2x^2
        >>> l(2, 'z')
        + 1/2x^2 - 2x - xz + 1 + 3/2z + 1/2z^2
        >>> l(5, 'z')
        - 1/120x^5 + 5/24x^4 + 1/24x^4z - 5/3x^3 - 3/4x^3z - 1/12x^3z^2 + 5x^2 + 47/12x^2z + x^2z^2 + 1/12x^2z^3 - 5x - 77/12xz - 71/24xz^2 - 7/12xz^3 - 1/24xz^4 + 1 + 137/60z + 15/8z^2 + 17/24z^3 + 1/8z^4 + 1/120z^5
        >>> l(5)
        + 1/120a^5 + 1/8a^4 - 1/24a^4x + 17/24a^3 - 7/12a^3x + 1/12a^3x^2 - 71/24a^2x + 15/8a^2 + a^2x^2 - 1/12a^2x^3 + 47/12ax^2 - 77/12ax + 137/60a - 3/4ax^3 + 1/24ax^4 + 5x^2 - 5/3x^3 - 5x + 1 - 1/120x^5 + 5/24x^4
        >>> l(6)
        + 1/720a^6 + 7/240a^5 - 1/120a^5x + 35/144a^4 - 1/6a^4x + 1/48a^4x^2 - 31/24a^3x + 49/48a^3 + 3/8a^3x^2 - 1/36a^3x^3 + 119/48a^2x^2 - 29/6a^2x + 203/90a^2 - 5/12a^2x^3 + 1/48a^2x^4 - 37/18ax^3 + 57/8ax^2 + 49/20a - 87/10ax + 11/48ax^4 - 1/120ax^5 + 5/8x^4 - 10/3x^3 + 1 - 6x + 15/2x^2 - 1/20x^5 + 1/720x^6


    **References**

    +---------------------------------------------------------------------+
    | `Wikipedia <http://en.wikipedia.org/wiki/Laguerre_polynomials>`_    |
    +---------------------------------------------------------------------+
    | `MathWorld <http://mathworld.wolfram.com/LaguerrePolynomial.html>`_ |
    +---------------------------------------------------------------------+

    .. versionadded:: 0.4
    '''

    if n < 0:
        raise ValueError('Generalized Laguerre polynomials only defined for n >= 0')
    if n == 0:
        return ONE
    if n == 1:
        return a + ONE - x

    a = monomial(**{a: 1})
    l1, ll = NULL, ONE
    for i in xrange(1, n + 1):
        l0, l1 = l1, ll
        ll = ((2*i - 1 + a - x) * l1 - (i - 1 + a) * l0) / monomial(i)
    return ll
예제 #2
0
파일: series.py 프로젝트: rubik/pypol-build
def laguerre(n):
    '''
    Returns the *n-th* Laguerre polynomial in ``x``.

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

    **Examples**

    ::

        >>> laguerre(0)
        + 1
        >>> laguerre(1)
        - x + 1
        >>> laguerre(2)
        + 1/2x^2 - 2x + 1
        >>> laguerre(3)
        - 1/6x^3 + 3/2x^2 - 3x + 1
        >>> laguerre(4)
        + 1/24x^4 - 2/3x^3 + 3x^2 - 4x + 1
        >>> laguerre(14)
        + 1/87178291200x^14 - 1/444787200x^13 + 13/68428800x^12 - 13/1425600x^11 + 143/518400x^10 - 143/25920x^9 + 143/1920x^8 - 143/210x^7 + 1001/240x^6 - 1001/60x^5 + 1001/24x^4 - 182/3x^3 + 91/2x^2 - 14x + 1

    Should be approximatively like a generalized Laguerre polynomial with ``a = 0`` (:func:`laguerre_g`)::

        >>> laguerre(5), laguerre_g(5)(a=0)
        (- 1/120x^5 + 5/24x^4 - 5/3x^3 + 5x^2 - 5x + 1, - 833333333333/100000000000000x^5 + 208333333333/1000000000000x^4 - 166666666667/100000000000x^3 + 5x^2 - 5x + 1)

    **References**

    `Wikipedia <http://en.wikipedia.org/wiki/Laguerre_polynomials>`_ | `MathWorld <http://mathworld.wolfram.com/LaguerrePolynomial.html>`_
    '''

    if n < 0:
        raise ValueError('Laguerre polynomials only defined for n >= 0')
    if n == 0:
        return ONE
    if n == 1:
        return ONE - x

    l1, ll = NULL, ONE
    for i in xrange(1, n + 1):
        l0, l1 = l1, ll
        ll = ((2*i - ONE - x) * l1 - (i - ONE) * l0) / monomial(i)
    return ll
예제 #3
0
파일: series.py 프로젝트: rubik/pypol-build
def gegenbauer(n, a='a'):
    '''
    Returns the *n-th* Gegenbauer polynomial in ``x``.

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

    **Examples**

    ::

        >>> gegenbauer(0)
        + 1
        >>> gegenbauer(1)
        + 2ax
        >>> gegenbauer(2)
        + 2a^2x^2 + 2ax^2 - a
        >>> 
        >>> 
        >>> gegenbauer(4)
        + 2/3a^4x^4 + 4a^3x^4 - 2a^3x^2 + 22/3a^2x^4 + 1/2a^2 - 6a^2x^2 + 4ax^4 - 4ax^2 + 1/2a

    **References**

    +-----------------------------------------------------------------------+
    | `Wikipedia <http://en.wikipedia.org/wiki/Gegenbauer_polynomials>`_    |
    +-----------------------------------------------------------------------+
    | `MathWorld <http://mathworld.wolfram.com/GegenbauerPolynomial.html>`_ |
    +-----------------------------------------------------------------------+

    .. versionadded:: 0.4
    '''

    a = monomial(**{a: 1})
    if n < 0:
        raise ValueError('Gegenbauer polynomials only defined for n >= 0')
    if n == 0:
        return ONE
    if n == 1:
        return 2*a*x
    return fractions.Fraction(1, n) * ((2*x * (n + a - ONE) * gegenbauer(n - 1) \
                                    - (n + 2*a - 2) * gegenbauer(n - 2)))
예제 #4
0
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

Requirements:
- Python 2.6 (or 2.7)
'''

import fractions

import py
import pypol
import pypol.series as series

x = pypol.monomial(x=1)
a = pypol.monomial(a=1)
NULL = pypol.Polynomial()
ONE = pypol.monomial()
TWO = pypol.monomial(2)

class TestSeries(object):
    def testFibonacci(self):
        assert series.fibonacci(1) == ONE
        assert series.fibonacci(2) == x
        assert series.fibonacci(3) == x**2 + 1
        assert series.fibonacci(4) == x**3 + 2*x
        assert series.fibonacci(5) == x**4 + 3 * x**2 + 1

    def testLucasSequence(self):
        l = series.LucasSeq(x, ONE)
예제 #5
0
파일: roots.py 프로젝트: rubik/pypol-build
def muller(poly, x_k, x_k2=None, x_k3=None, epsilon=float('-inf')):
    '''
    Finds the real roots of the polynomial *poly* starting from *x_k*.

    :param x_k2: an optional starting value
    :type x_k2: number (integer or float)
    :param x_k3: another optional starting value
    :type x_k3: number (integer or float)
    :param float epsilon: the precision. Default to `float('-inf')`, which means it will be as accurate as possible
    :rtype: number

    **Examples**

    ::

        >>> a = x.from_roots([1, -23, 2424, -2])
        >>> a
        + x^4 - 2400x^3 - 58155x^2 - 50950x + 111504
        >>> muller(a, 100)
        -2.0
        >>> muller(a, -1000)
        2424.0

    Muller's method is the most suitable for a function that finds all the roots of a polynomial::

        >>> def find_roots(poly):
            r = []
            for _ in xrange(poly.degree):
                next_root = muller(poly, 100)
                r.append(next_root)
                poly /= (x - next_root)
            return r
        
        >>> find_roots(a)
        [-2.0, -23.0, 2424.0, 1.0]
        >>> roots.quartic(a)
        [1, 2424.0, -23.0, -2.0]
        >>> a = x.from_roots([1, -1, 2323, -229, 24])
        >>> a
        + x^5 - 2118x^4 - 481712x^3 + 12769326x^2 + 481711x - 12767208
        >>> find_roots(a)
        [1.0, -1.0, -229.0, 2323.0, 24.0]

    With this function you can find the roots of polynomials of higher degrees::

        >>> a = x.from_roots([1, -1, 2323, -229, 24, -22])
        >>> a
        + x^6 - 2096x^5 - 528308x^4 + 2171662x^3 + 281406883x^2 - 2169566x - 280878576
        >>> find_roots(a)
        [-22.0, 1.0, -1.0, -229.0, 2323.0, 24.0]

    .. versionadded:: 0.5
    '''

    s = (-1 if x_k < 0 else 1)
    if not x_k2:
        x_k2 = x_k + s * .25
    if not x_k3:
        x_k3 = x_k2 + s * .25

    x = monomial(x=1)
    while True:
        w = divided_diff(poly, [x_k, x_k2]) + divided_diff(poly, [x_k, x_k3]) - divided_diff(poly, [x_k2, x_k3])
        y = poly(x_k) - w * (x - x_k) + divided_diff(poly, [x_k, x_k2, x_k3]) * (x - x_k) ** 2
        n = 2 * poly(x_k)
        k = w ** 2 - 4 * poly(x_k) * divided_diff(poly, [x_k, x_k2, x_k3])
        if k < 0:
            d_part = -math.sqrt(-k)
        else:
            d_part = math.sqrt(k)
        d = max(w + d_part, w - d_part)
        x_k1 = x_k - n / d
        if x_k1 == x_k or abs(x_k1 - x_k) < epsilon:
            return x_k1
        x_k, x_k2, x_k3 = x_k1, x_k, x_k2
예제 #6
0
파일: roots.py 프로젝트: rubik/pypol-build
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
예제 #7
0
 def testMonomial(self):
     vars = {'a': 3, 'b': 4}
     m = pypol.monomial(5, **vars)
     assert type(pypol.monomial()) == pypol.Polynomial
     assert ('a', 'b') == m.letters
     assert [5] == m.coefficients
예제 #8
0
You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

Requirements:
- Python 2.6 (or 2.7)
'''

import fractions

import py
import pypol
import pypol.funcs as funcs
from pypol import ONE, TWO, x

a = pypol.monomial(a=1)

class TestFuncs(object):
    def testDivisible(self):
        p = pypol.poly1d([2, 6, -4, 8]) * x
        assert funcs.divisible(p, p.gcd())

    def testFromRoots(self):
        p = funcs.from_roots([1, -3, 44, 45245, -2332])
        assert map(p, [1, -3, 44, 45245, -2332]) == [0, 0, 0, 0, 0]
        assert funcs.from_roots([1, -2, 3], 'o').letters == ('o',)

    def testRandomPoly(self):
        for _ in xrange(1000):
            assert type(funcs.random_poly()) == pypol.Polynomial