示例#1
0
    def __new__(cls, f, index):
        if isinstance(f, RootsOf):
            f = f.poly
        elif not isinstance(f, Poly):
            raise PolynomialError("%s is not a polynomial" % f)

        if f.is_multivariate:
            raise ValueError('multivariate polynomial')

        if index < 0 or index >= f.degree():
            raise IndexError("Index must be in [0, %d] range" % (f.degree()-1))
        else:
            exact = _exact_roots(f)

            if index < len(exact):
                return exact[index]
            else:
                index = sympify(index)
                return Expr.__new__(cls, f, index)
示例#2
0
    def solve_reduced_system(system, entry=False):
        """Recursively solves reduced polynomial systems. """
        basis = poly_groebner(system)

        if len(basis) == 1 and basis[0].is_one:
            if not entry:
                return []
            else:
                return None

        univariate = filter(is_univariate, basis)

        if len(univariate) == 1:
            f = univariate.pop()
        else:
            raise PolynomialError("Not a zero-dimensional system")

        zeros = roots(Poly(f, f.symbols[-1])).keys()

        if not zeros:
            return []

        if len(basis) == 1:
            return [[zero] for zero in zeros]

        solutions = []

        for zero in zeros:
            new_system = []

            for poly in basis[:-1]:
                eq = poly.evaluate((poly.symbols[-1], zero))

                if not eq.is_zero:
                    new_system.append(eq)

            for solution in solve_reduced_system(new_system):
                solutions.append(solution + [zero])

        return solutions
示例#3
0
def reduce_rational_inequalities(exprs, gen, relational=True):
    """Reduce a system of rational inequalities with rational coefficients.

    Examples
    ========

    >>> from sympy import Poly, Symbol
    >>> from sympy.solvers.inequalities import reduce_rational_inequalities

    >>> x = Symbol('x', real=True)

    >>> reduce_rational_inequalities([[x**2 <= 0]], x)
    Eq(x, 0)

    >>> reduce_rational_inequalities([[x + 2 > 0]], x)
    (-2 < x) & (x < oo)
    >>> reduce_rational_inequalities([[(x + 2, ">")]], x)
    (-2 < x) & (x < oo)
    >>> reduce_rational_inequalities([[x + 2]], x)
    Eq(x, -2)
    """
    exact = True
    eqs = []
    solution = S.Reals if exprs else S.EmptySet
    for _exprs in exprs:
        _eqs = []

        for expr in _exprs:
            if isinstance(expr, tuple):
                expr, rel = expr
            else:
                if expr.is_Relational:
                    expr, rel = expr.lhs - expr.rhs, expr.rel_op
                else:
                    expr, rel = expr, '=='

            if expr is S.true:
                numer, denom, rel = S.Zero, S.One, '=='
            elif expr is S.false:
                numer, denom, rel = S.One, S.One, '=='
            else:
                numer, denom = expr.together().as_numer_denom()

            try:
                (numer, denom), opt = parallel_poly_from_expr((numer, denom),
                                                              gen)
            except PolynomialError:
                raise PolynomialError(
                    filldedent('''
                    only polynomials and rational functions are
                    supported in this context.
                    '''))

            if not opt.domain.is_Exact:
                numer, denom, exact = numer.to_exact(), denom.to_exact(), False

            domain = opt.domain.get_exact()

            if not (domain.is_ZZ or domain.is_QQ):
                expr = numer / denom
                expr = Relational(expr, 0, rel)
                solution &= solve_univariate_inequality(expr,
                                                        gen,
                                                        relational=False)
            else:
                _eqs.append(((numer, denom), rel))

        if _eqs:
            eqs.append(_eqs)

    if eqs:
        solution &= solve_rational_inequalities(eqs)
        exclude = solve_rational_inequalities([[((d, d.one), '==') for i in eqs
                                                for ((n, d), _) in i
                                                if d.has(gen)]])
        solution -= exclude

    if not exact and solution:
        solution = solution.evalf()

    if relational:
        solution = solution.as_relational(gen)

    return solution
示例#4
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
示例#5
0
def reduce_rational_inequalities(exprs, gen, assume=True, relational=True):
    """Reduce a system of rational inequalities with rational coefficients.

    Examples
    ========

    >>> from sympy import Poly, Symbol
    >>> from sympy.solvers.inequalities import reduce_rational_inequalities

    >>> x = Symbol('x', real=True)

    >>> reduce_rational_inequalities([[x**2 <= 0]], x)
    x == 0

    >>> reduce_rational_inequalities([[x + 2 > 0]], x)
    -2 < x
    """
    exact = True
    eqs = []

    for _exprs in exprs:
        _eqs = []

        for expr in _exprs:
            if isinstance(expr, tuple):
                expr, rel = expr
            else:
                if expr.is_Relational:
                    expr, rel = expr.lhs - expr.rhs, expr.rel_op
                else:
                    expr, rel = expr, '=='

            try:
                (numer, denom), opt = parallel_poly_from_expr(expr.together().as_numer_denom(), gen)
            except PolynomialError:
                raise PolynomialError("only polynomials and rational functions are supported in this context")

            if not opt.domain.is_Exact:
                numer, denom, exact = numer.to_exact(), denom.to_exact(), False

            domain = opt.domain.get_exact()

            if not (domain.is_ZZ or domain.is_QQ):
                raise NotImplementedError("inequality solving is not supported over %s" % opt.domain)

            _eqs.append(((numer, denom), rel))

        eqs.append(_eqs)

    solution = solve_rational_inequalities(eqs)

    if not exact:
        solution = solution.evalf()

    if not relational:
        return solution

    real = ask(Q.real(gen), assumptions=assume)

    if not real:
        result = And(solution.as_relational(re(gen)), Eq(im(gen), 0))
    else:
        result = solution.as_relational(gen)

    return result