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