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
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
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)))
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)
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
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
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
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