Exemplo n.º 1
0
def ratint_ratpart(f, g, x):
    """Horowitz-Ostrogradsky algorithm.

       Given a field K and polynomials f and g in K[x], such that f and g
       are coprime and deg(f) < deg(g), returns fractions A and B in K(x),
       such that f/g = A' + B and B has square-free denominator.

    """
    f = Poly(f, x)
    g = Poly(g, x)

    u, v, _ = g.cofactors(g.diff())

    n = u.degree()
    m = v.degree()
    d = g.degree()

    A_coeffs = [ Dummy('a' + str(n-i)) for i in xrange(0, n) ]
    B_coeffs = [ Dummy('b' + str(m-i)) for i in xrange(0, m) ]

    C_coeffs = A_coeffs + B_coeffs

    A = Poly(A_coeffs, x, domain=ZZ[C_coeffs])
    B = Poly(B_coeffs, x, domain=ZZ[C_coeffs])

    H = f - A.diff()*v + A*(u.diff()*v).exquo(u) - B*u

    result = solve(H.coeffs(), C_coeffs)

    A = A.as_basic().subs(result)
    B = B.as_basic().subs(result)

    rat_part = cancel(A/u.as_basic(), x)
    log_part = cancel(B/v.as_basic(), x)

    return rat_part, log_part
Exemplo n.º 2
0
def ratint_ratpart(f, g, x):
    """Horowitz-Ostrogradsky algorithm.

       Given a field K and polynomials f and g in K[x], such that f and g
       are coprime and deg(f) < deg(g), returns fractions A and B in K(x),
       such that f/g = A' + B and B has square-free denominator.

    """
    f = Poly(f, x)
    g = Poly(g, x)

    u, v, _ = g.cofactors(g.diff())

    n = u.degree()
    m = v.degree()
    d = g.degree()

    A_coeffs = [Dummy('a' + str(n - i)) for i in xrange(0, n)]
    B_coeffs = [Dummy('b' + str(m - i)) for i in xrange(0, m)]

    C_coeffs = A_coeffs + B_coeffs

    A = Poly(A_coeffs, x, domain=ZZ[C_coeffs])
    B = Poly(B_coeffs, x, domain=ZZ[C_coeffs])

    H = f - A.diff() * v + A * (u.diff() * v).exquo(u) - B * u

    result = solve(H.coeffs(), C_coeffs)

    A = A.as_basic().subs(result)
    B = B.as_basic().subs(result)

    rat_part = cancel(A / u.as_basic(), x)
    log_part = cancel(B / v.as_basic(), x)

    return rat_part, log_part
Exemplo n.º 3
0
def roots(f, *gens, **flags):
    """Computes symbolic roots of a univariate polynomial.

       Given a univariate polynomial f with symbolic coefficients (or
       a list of the polynomial's coefficients), returns a dictionary
       with its roots and their multiplicities.

       Only roots expressible via radicals will be returned.  To get
       a complete set of roots use RootOf class or numerical methods
       instead. By default cubic and quartic formulas are used in
       the algorithm. To disable them because of unreadable output
       set `cubics=False` or `quartics=False` respectively.

       To get roots from a specific domain set the `filter` flag with
       one of the following specifiers: Z, Q, R, I, C. By default all
       roots are returned (this is equivalent to setting `filter='C'`).

       By default a dictionary is returned giving a compact result in
       case of multiple roots.  However to get a tuple containing all
       those roots set the `multiple` flag to True.

       Examples
       ========

           >>> from sympy import Poly, roots
           >>> from sympy.abc import x, y

           >>> roots(x**2 - 1, x)
           {1: 1, -1: 1}

           >>> p = Poly(x**2-1, x)
           >>> roots(p)
           {1: 1, -1: 1}

           >>> p = Poly(x**2-y, x, y)

           >>> roots(Poly(p, x))
           {y**(1/2): 1, -y**(1/2): 1}

           >>> roots(x**2 - y, x)
           {y**(1/2): 1, -y**(1/2): 1}

           >>> roots([1, 0, -1])
           {1: 1, -1: 1}

    """
    multiple = flags.get('multiple', False)

    if isinstance(f, list):
        if gens:
            raise ValueError('redundant generators given')

        x = Dummy('x')

        poly, i = {}, len(f)-1

        for coeff in f:
            poly[i], i = sympify(coeff), i-1

        f = Poly(poly, x, field=True)
    else:
        try:
            f = Poly(f, *gens, **flags)
        except GeneratorsNeeded:
            if multiple:
                return []
            else:
                return {}

        if f.is_multivariate:
            raise PolynomialError('multivariate polynomials are not supported')

        f, x = f.to_field(), f.gen

    def _update_dict(result, root, k):
        if root in result:
            result[root] += k
        else:
            result[root] = k

    def _try_decompose(f):
        """Find roots using functional decomposition. """
        factors = f.decompose()
        result, g = {}, factors[0]

        for h, i in g.sqf_list()[1]:
            for r in _try_heuristics(h):
                _update_dict(result, r, i)

        for factor in factors[1:]:
            last, result = result.copy(), {}

            for last_r, i in last.iteritems():
                g = factor - Poly(last_r, x)

                for h, j in g.sqf_list()[1]:
                    for r in _try_heuristics(h):
                        _update_dict(result, r, i*j)

        return result

    def _try_heuristics(f):
        """Find roots using formulas and some tricks. """
        if f.is_ground:
            return []
        if f.is_monomial:
            return [S(0)]*f.degree()

        if f.length() == 2:
            if f.degree() == 1:
                return map(cancel, roots_linear(f))
            else:
                return roots_binomial(f)

        result = []

        for i in [S(-1), S(1)]:
            if f.eval(i).expand().is_zero:
                f = f.exquo(Poly(x-1, x))
                result.append(i)
                break

        n = f.degree()

        if n == 1:
            result += map(cancel, roots_linear(f))
        elif n == 2:
            result += map(cancel, roots_quadratic(f))
        elif n == 3 and flags.get('cubics', True):
            result += roots_cubic(f)
        elif n == 4 and flags.get('quartics', True):
            result += roots_quartic(f)

        return result

    if f.is_monomial == 1:
        if f.is_ground:
            if multiple:
                return []
            else:
                return {}
        else:
            result = { S(0) : f.degree() }
    else:
        (k,), f = f.terms_gcd()

        if not k:
            zeros = {}
        else:
            zeros = { S(0) : k }

        result = {}

        if f.length() == 2:
            if f.degree() == 1:
                result[cancel(roots_linear(f)[0])] = 1
            else:
                for r in roots_binomial(f):
                    _update_dict(result, r, 1)
        elif f.degree() == 2:
            for r in roots_quadratic(f):
                _update_dict(result, cancel(r), 1)
        else:
            _, factors = Poly(f.as_basic()).factor_list()

            if len(factors) == 1 and factors[0][1] == 1:
                result = _try_decompose(f)
            else:
                for factor, k in factors:
                    for r in _try_heuristics(Poly(factor, x, field=True)):
                        _update_dict(result, r, k)

        result.update(zeros)

    filter = flags.get('filter', None)

    if filter not in [None, 'C']:
        handlers = {
            'Z' : lambda r: r.is_Integer,
            'Q' : lambda r: r.is_Rational,
            'R' : lambda r: r.is_real,
            'I' : lambda r: r.is_imaginary,
        }

        try:
            query = handlers[filter]
        except KeyError:
            raise ValueError("Invalid filter: %s" % filter)

        for zero in dict(result).iterkeys():
            if not query(zero):
                del result[zero]

    predicate = flags.get('predicate', None)

    if predicate is not None:
        for zero in dict(result).iterkeys():
            if not predicate(zero):
                del result[zero]

    if not multiple:
        return result
    else:
        zeros = []

        for zero, k in result.iteritems():
            zeros.extend([zero]*k)

        return zeros