def test_range_interval_intersection(): p = symbols('p', positive=True) assert isinstance(Range(3).intersect(Interval(p, p + 2)), Intersection) assert Range(4).intersect(Interval(0, 3)) == Range(4) assert Range(4).intersect(Interval(-oo, oo)) == Range(4) assert Range(4).intersect(Interval(1, oo)) == Range(1, 4) assert Range(4).intersect(Interval(1.1, oo)) == Range(2, 4) assert Range(4).intersect(Interval(0.1, 3)) == Range(1, 4) assert Range(4).intersect(Interval(0.1, 3.1)) == Range(1, 4) assert Range(4).intersect(Interval.open(0, 3)) == Range(1, 3) assert Range(4).intersect(Interval.open(0.1, 0.5)) is S.EmptySet
def test_continuous_domain(): x = Symbol('x') assert continuous_domain(sin(x), x, Interval(0, 2*pi)) == Interval(0, 2*pi) assert continuous_domain(tan(x), x, Interval(0, 2*pi)) == \ Union(Interval(0, pi/2, False, True), Interval(pi/2, 3*pi/2, True, True), Interval(3*pi/2, 2*pi, True, False)) assert continuous_domain((x - 1)/((x - 1)**2), x, S.Reals) == \ Union(Interval(-oo, 1, True, True), Interval(1, oo, True, True)) assert continuous_domain(log(x) + log(4*x - 1), x, S.Reals) == \ Interval(1/4, oo, True, True) assert continuous_domain(1/sqrt(x - 3), x, S.Reals) == Interval(3, oo, True, True) assert continuous_domain(1/x - 2, x, S.Reals) == \ Union(Interval.open(-oo, 0), Interval.open(0, oo)) assert continuous_domain(1/(x**2 - 4) + 2, x, S.Reals) == \ Union(Interval.open(-oo, -2), Interval.open(-2, 2), Interval.open(2, oo))
def test_continuous_domain(): x = Symbol('x') assert continuous_domain(sin(x), x, Interval(0, 2*pi)) == Interval(0, 2*pi) assert continuous_domain(tan(x), x, Interval(0, 2*pi)) == \ Union(Interval(0, pi/2, False, True), Interval(pi/2, pi*Rational(3, 2), True, True), Interval(pi*Rational(3, 2), 2*pi, True, False)) assert continuous_domain((x - 1)/((x - 1)**2), x, S.Reals) == \ Union(Interval(-oo, 1, True, True), Interval(1, oo, True, True)) assert continuous_domain(log(x) + log(4*x - 1), x, S.Reals) == \ Interval(Rational(1, 4), oo, True, True) assert continuous_domain(1/sqrt(x - 3), x, S.Reals) == Interval(3, oo, True, True) assert continuous_domain(1/x - 2, x, S.Reals) == \ Union(Interval.open(-oo, 0), Interval.open(0, oo)) assert continuous_domain(1/(x**2 - 4) + 2, x, S.Reals) == \ Union(Interval.open(-oo, -2), Interval.open(-2, 2), Interval.open(2, oo))
def test_range_interval_intersection(): p = symbols('p', positive=True) assert isinstance(Range(3).intersect(Interval(p, p + 2)), Intersection) assert Range(4).intersect(Interval(0, 3)) == Range(4) assert Range(4).intersect(Interval(-oo, oo)) == Range(4) assert Range(4).intersect(Interval(1, oo)) == Range(1, 4) assert Range(4).intersect(Interval(1.1, oo)) == Range(2, 4) assert Range(4).intersect(Interval(0.1, 3)) == Range(1, 4) assert Range(4).intersect(Interval(0.1, 3.1)) == Range(1, 4) assert Range(4).intersect(Interval.open(0, 3)) == Range(1, 3) assert Range(4).intersect(Interval.open(0.1, 0.5)) is S.EmptySet # Null Range intersections assert Range(0).intersect(Interval(0.2, 0.8)) is S.EmptySet assert Range(0).intersect(Interval(-oo, oo)) is S.EmptySet
def test_is_convex(): assert is_convex(1/x, x, domain=Interval.open(0, oo)) == True assert is_convex(1/x, x, domain=Interval(-oo, 0)) == False assert is_convex(x**2, x, domain=Interval(0, oo)) == True assert is_convex(1/x**3, x, domain=Interval.Lopen(0, oo)) == True assert is_convex(-1/x**3, x, domain=Interval.Ropen(-oo, 0)) == True assert is_convex(log(x), x) == False raises(NotImplementedError, lambda: is_convex(log(x), x, a))
def test_trig_inequalities(): # all the inequalities are solved in a periodic interval. assert isolve(sin(x) < S.Half, x, relational=False) == \ Union(Interval(0, pi/6, False, True), Interval.open(pi*Rational(5, 6), 2*pi)) assert isolve(sin(x) > S.Half, x, relational=False) == \ Interval(pi/6, pi*Rational(5, 6), True, True) assert isolve(cos(x) < S.Zero, x, relational=False) == \ Interval(pi/2, pi*Rational(3, 2), True, True) assert isolve(cos(x) >= S.Zero, x, relational=False) == \ Union(Interval(0, pi/2), Interval.Ropen(pi*Rational(3, 2), 2*pi)) assert isolve(tan(x) < S.One, x, relational=False) == \ Union(Interval.Ropen(0, pi/4), Interval.open(pi/2, pi)) assert isolve(sin(x) <= S.Zero, x, relational=False) == \ Union(FiniteSet(S.Zero), Interval.Ropen(pi, 2*pi)) assert isolve(sin(x) <= S.One, x, relational=False) == S.Reals assert isolve(cos(x) < S(-2), x, relational=False) == S.EmptySet assert isolve(sin(x) >= S.NegativeOne, x, relational=False) == S.Reals assert isolve(cos(x) > S.One, x, relational=False) == S.EmptySet
def test_bool_as_set(): assert ITE(y <= 0, False, y >= 1).as_set() == Interval(1, oo) assert And(x <= 2, x >= -2).as_set() == Interval(-2, 2) assert Or(x >= 2, x <= -2).as_set() == Interval(-oo, -2) + Interval(2, oo) assert Not(x > 2).as_set() == Interval(-oo, 2) # issue 10240 assert Not(And(x > 2, x < 3)).as_set() == \ Union(Interval(-oo, 2), Interval(3, oo)) assert true.as_set() == S.UniversalSet assert false.as_set() == EmptySet() assert x.as_set() == S.UniversalSet assert And(Or(x < 1, x > 3), x < 2).as_set() == Interval.open(-oo, 1) assert And(x < 1, sin(x) < 3).as_set() == (x < 1).as_set() raises(NotImplementedError, lambda: (sin(x) < 1).as_set())
def test_function_range(): x, y, a, b = symbols('x y a b') assert function_range(sin(x), x, Interval(-pi/2, pi/2) ) == Interval(-1, 1) assert function_range(sin(x), x, Interval(0, pi) ) == Interval(0, 1) assert function_range(tan(x), x, Interval(0, pi) ) == Interval(-oo, oo) assert function_range(tan(x), x, Interval(pi/2, pi) ) == Interval(-oo, 0) assert function_range((x + 3)/(x - 2), x, Interval(-5, 5) ) == Union(Interval(-oo, Rational(2, 7)), Interval(Rational(8, 3), oo)) assert function_range(1/(x**2), x, Interval(-1, 1) ) == Interval(1, oo) assert function_range(exp(x), x, Interval(-1, 1) ) == Interval(exp(-1), exp(1)) assert function_range(log(x) - x, x, S.Reals ) == Interval(-oo, -1) assert function_range(sqrt(3*x - 1), x, Interval(0, 2) ) == Interval(0, sqrt(5)) assert function_range(x*(x - 1) - (x**2 - x), x, S.Reals ) == FiniteSet(0) assert function_range(x*(x - 1) - (x**2 - x) + y, x, S.Reals ) == FiniteSet(y) assert function_range(sin(x), x, Union(Interval(-5, -3), FiniteSet(4)) ) == Union(Interval(-sin(3), 1), FiniteSet(sin(4))) assert function_range(cos(x), x, Interval(-oo, -4) ) == Interval(-1, 1) assert function_range(cos(x), x, S.EmptySet) == S.EmptySet assert function_range(x/sqrt(x**2+1), x, S.Reals) == Interval.open(-1,1) raises(NotImplementedError, lambda : function_range( exp(x)*(sin(x) - cos(x))/2 - x, x, S.Reals)) raises(NotImplementedError, lambda : function_range( sin(x) + x, x, S.Reals)) # issue 13273 raises(NotImplementedError, lambda : function_range( log(x), x, S.Integers)) raises(NotImplementedError, lambda : function_range( sin(x)/2, x, S.Naturals))
def test_normalize_theta_set(): # Interval assert normalize_theta_set(Interval(pi, 2*pi)) == \ Union(FiniteSet(0), Interval.Ropen(pi, 2*pi)) assert normalize_theta_set(Interval(9 * pi / 2, 5 * pi)) == Interval(pi / 2, pi) assert normalize_theta_set(Interval(-3 * pi / 2, pi / 2)) == Interval.Ropen(0, 2 * pi) assert normalize_theta_set(Interval.open(-3*pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval.open(-7*pi/2, -3*pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) assert normalize_theta_set(Interval.open(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(3*pi/2, 2*pi)) assert normalize_theta_set(Interval(-4 * pi, 3 * pi)) == Interval.Ropen(0, 2 * pi) assert normalize_theta_set(Interval(-3 * pi / 2, -pi / 2)) == Interval( pi / 2, 3 * pi / 2) assert normalize_theta_set(Interval.open(0, 2 * pi)) == Interval.open( 0, 2 * pi) assert normalize_theta_set(Interval.Ropen(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) assert normalize_theta_set(Interval.Lopen(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.open(3*pi/2, 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) assert normalize_theta_set(Interval.open(4 * pi, 9 * pi / 2)) == Interval.open( 0, pi / 2) assert normalize_theta_set(Interval.Lopen(4 * pi, 9 * pi / 2)) == Interval.Lopen( 0, pi / 2) assert normalize_theta_set(Interval.Ropen(4 * pi, 9 * pi / 2)) == Interval.Ropen( 0, pi / 2) assert normalize_theta_set(Interval.open(3*pi, 5*pi)) == \ Union(Interval.Ropen(0, pi), Interval.open(pi, 2*pi)) # FiniteSet assert normalize_theta_set(FiniteSet(0, pi, 3 * pi)) == FiniteSet(0, pi) assert normalize_theta_set(FiniteSet(0, pi / 2, pi, 2 * pi)) == FiniteSet(0, pi / 2, pi) assert normalize_theta_set(FiniteSet(0, -pi / 2, -pi, -2 * pi)) == FiniteSet( 0, pi, 3 * pi / 2) assert normalize_theta_set(FiniteSet(-3*pi/2, pi/2)) == \ FiniteSet(pi/2) assert normalize_theta_set(FiniteSet(2 * pi)) == FiniteSet(0) # Unions assert normalize_theta_set(Union(Interval(0, pi/3), Interval(pi/2, pi))) == \ Union(Interval(0, pi/3), Interval(pi/2, pi)) assert normalize_theta_set(Union(Interval(0, pi), Interval(2*pi, 7*pi/3))) == \ Interval(0, pi) # ValueError for non-real sets raises(ValueError, lambda: normalize_theta_set(S.Complexes))
def test_normalize_theta_set(): # Interval assert normalize_theta_set(Interval(pi, 2*pi)) == \ Union(FiniteSet(0), Interval.Ropen(pi, 2*pi)) assert normalize_theta_set(Interval(9*pi/2, 5*pi)) == Interval(pi/2, pi) assert normalize_theta_set(Interval(-3*pi/2, pi/2)) == Interval.Ropen(0, 2*pi) assert normalize_theta_set(Interval.open(-3*pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval.open(-7*pi/2, -3*pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) assert normalize_theta_set(Interval.open(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(3*pi/2, 2*pi)) assert normalize_theta_set(Interval(-4*pi, 3*pi)) == Interval.Ropen(0, 2*pi) assert normalize_theta_set(Interval(-3*pi/2, -pi/2)) == Interval(pi/2, 3*pi/2) assert normalize_theta_set(Interval.open(0, 2*pi)) == Interval.open(0, 2*pi) assert normalize_theta_set(Interval.Ropen(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) assert normalize_theta_set(Interval.Lopen(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.open(3*pi/2, 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(3*pi/2, 2*pi)) assert normalize_theta_set(Interval.open(4*pi, 9*pi/2)) == Interval.open(0, pi/2) assert normalize_theta_set(Interval.Lopen(4*pi, 9*pi/2)) == Interval.Lopen(0, pi/2) assert normalize_theta_set(Interval.Ropen(4*pi, 9*pi/2)) == Interval.Ropen(0, pi/2) assert normalize_theta_set(Interval.open(3*pi, 5*pi)) == \ Union(Interval.Ropen(0, pi), Interval.open(pi, 2*pi)) # FiniteSet assert normalize_theta_set(FiniteSet(0, pi, 3*pi)) == FiniteSet(0, pi) assert normalize_theta_set(FiniteSet(0, pi/2, pi, 2*pi)) == FiniteSet(0, pi/2, pi) assert normalize_theta_set(FiniteSet(0, -pi/2, -pi, -2*pi)) == FiniteSet(0, pi, 3*pi/2) assert normalize_theta_set(FiniteSet(-3*pi/2, pi/2)) == \ FiniteSet(pi/2) assert normalize_theta_set(FiniteSet(2*pi)) == FiniteSet(0) # Unions assert normalize_theta_set(Union(Interval(0, pi/3), Interval(pi/2, pi))) == \ Union(Interval(0, pi/3), Interval(pi/2, pi)) assert normalize_theta_set(Union(Interval(0, pi), Interval(2*pi, 7*pi/3))) == \ Interval(0, pi) # ValueError for non-real sets raises(ValueError, lambda: normalize_theta_set(S.Complexes))
def test_normalize_theta_set(): # Interval assert normalize_theta_set(Interval(pi, 2*pi)) == \ Union(FiniteSet(0), Interval.Ropen(pi, 2*pi)) assert normalize_theta_set(Interval(pi * Rational(9, 2), 5 * pi)) == Interval(pi / 2, pi) assert normalize_theta_set(Interval(pi * Rational(-3, 2), pi / 2)) == Interval.Ropen(0, 2 * pi) assert normalize_theta_set(Interval.open(pi*Rational(-3, 2), pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval.open(pi*Rational(-7, 2), pi*Rational(-3, 2))) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi/2, 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval.open(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.open(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval(-4 * pi, 3 * pi)) == Interval.Ropen(0, 2 * pi) assert normalize_theta_set(Interval(pi * Rational(-3, 2), -pi / 2)) == Interval( pi / 2, pi * Rational(3, 2)) assert normalize_theta_set(Interval.open(0, 2 * pi)) == Interval.open( 0, 2 * pi) assert normalize_theta_set(Interval.Ropen(-pi/2, pi/2)) == \ Union(Interval.Ropen(0, pi/2), Interval.Ropen(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval.Lopen(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.open(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval.Ropen(pi*Rational(3, 2), 2*pi)) assert normalize_theta_set(Interval.open( 4 * pi, pi * Rational(9, 2))) == Interval.open(0, pi / 2) assert normalize_theta_set(Interval.Lopen( 4 * pi, pi * Rational(9, 2))) == Interval.Lopen(0, pi / 2) assert normalize_theta_set(Interval.Ropen( 4 * pi, pi * Rational(9, 2))) == Interval.Ropen(0, pi / 2) assert normalize_theta_set(Interval.open(3*pi, 5*pi)) == \ Union(Interval.Ropen(0, pi), Interval.open(pi, 2*pi)) # FiniteSet assert normalize_theta_set(FiniteSet(0, pi, 3 * pi)) == FiniteSet(0, pi) assert normalize_theta_set(FiniteSet(0, pi / 2, pi, 2 * pi)) == FiniteSet(0, pi / 2, pi) assert normalize_theta_set(FiniteSet(0, -pi / 2, -pi, -2 * pi)) == FiniteSet( 0, pi, pi * Rational(3, 2)) assert normalize_theta_set(FiniteSet(pi*Rational(-3, 2), pi/2)) == \ FiniteSet(pi/2) assert normalize_theta_set(FiniteSet(2 * pi)) == FiniteSet(0) # Unions assert normalize_theta_set(Union(Interval(0, pi/3), Interval(pi/2, pi))) == \ Union(Interval(0, pi/3), Interval(pi/2, pi)) assert normalize_theta_set(Union(Interval(0, pi), Interval(2*pi, pi*Rational(7, 3)))) == \ Interval(0, pi) # ValueError for non-real sets raises(ValueError, lambda: normalize_theta_set(S.Complexes)) # NotImplementedError for subset of reals raises(NotImplementedError, lambda: normalize_theta_set(Interval(0, 1))) # NotImplementedError without pi as coefficient raises(NotImplementedError, lambda: normalize_theta_set(Interval(1, 2 * pi))) raises(NotImplementedError, lambda: normalize_theta_set(Interval(2 * pi, 10))) raises(NotImplementedError, lambda: normalize_theta_set(FiniteSet(0, 3, 3 * pi)))
def solve_univariate_inequality(expr, gen, relational=True, domain=S.Reals, continuous=False): """Solves a real univariate inequality. Parameters ========== expr : Relational The target inequality gen : Symbol The variable for which the inequality is solved relational : bool A Relational type output is expected or not domain : Set The domain over which the equation is solved continuous: bool True if expr is known to be continuous over the given domain (and so continuous_domain() doesn't need to be called on it) Raises ====== NotImplementedError The solution of the inequality cannot be determined due to limitation in :func:`sympy.solvers.solveset.solvify`. Notes ===== Currently, we cannot solve all the inequalities due to limitations in :func:`sympy.solvers.solveset.solvify`. Also, the solution returned for trigonometric inequalities are restricted in its periodic interval. See Also ======== sympy.solvers.solveset.solvify: solver returning solveset solutions with solve's output API Examples ======== >>> from sympy import solve_univariate_inequality, Symbol, sin, Interval, S >>> x = Symbol('x') >>> solve_univariate_inequality(x**2 >= 4, x) ((2 <= x) & (x < oo)) | ((-oo < x) & (x <= -2)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) Union(Interval(-oo, -2), Interval(2, oo)) >>> domain = Interval(0, S.Infinity) >>> solve_univariate_inequality(x**2 >= 4, x, False, domain) Interval(2, oo) >>> solve_univariate_inequality(sin(x) > 0, x, relational=False) Interval.open(0, pi) """ from sympy.solvers.solvers import denoms if domain.is_subset(S.Reals) is False: raise NotImplementedError( filldedent(''' Inequalities in the complex domain are not supported. Try the real domain by setting domain=S.Reals''')) elif domain is not S.Reals: rv = solve_univariate_inequality( expr, gen, relational=False, continuous=continuous).intersection(domain) if relational: rv = rv.as_relational(gen) return rv else: pass # continue with attempt to solve in Real domain # This keeps the function independent of the assumptions about `gen`. # `solveset` makes sure this function is called only when the domain is # real. _gen = gen _domain = domain if gen.is_extended_real is False: rv = S.EmptySet return rv if not relational else rv.as_relational(_gen) elif gen.is_extended_real is None: gen = Dummy('gen', extended_real=True) try: expr = expr.xreplace({_gen: gen}) except TypeError: raise TypeError( filldedent(''' When gen is real, the relational has a complex part which leads to an invalid comparison like I < 0. ''')) rv = None if expr is S.true: rv = domain elif expr is S.false: rv = S.EmptySet else: e = expr.lhs - expr.rhs period = periodicity(e, gen) if period == S.Zero: e = expand_mul(e) const = expr.func(e, 0) if const is S.true: rv = domain elif const is S.false: rv = S.EmptySet elif period is not None: frange = function_range(e, gen, domain) rel = expr.rel_op if rel in ('<', '<='): if expr.func(frange.sup, 0): rv = domain elif not expr.func(frange.inf, 0): rv = S.EmptySet elif rel in ('>', '>='): if expr.func(frange.inf, 0): rv = domain elif not expr.func(frange.sup, 0): rv = S.EmptySet inf, sup = domain.inf, domain.sup if sup - inf is S.Infinity: domain = Interval(0, period, False, True).intersect(_domain) _domain = domain if rv is None: n, d = e.as_numer_denom() try: if gen not in n.free_symbols and len(e.free_symbols) > 1: raise ValueError # this might raise ValueError on its own # or it might give None... solns = solvify(e, gen, domain) if solns is None: # in which case we raise ValueError raise ValueError except (ValueError, NotImplementedError): # replace gen with generic x since it's # univariate anyway raise NotImplementedError( filldedent(''' The inequality, %s, cannot be solved using solve_univariate_inequality. ''' % expr.subs(gen, Symbol('x')))) expanded_e = expand_mul(e) def valid(x): # this is used to see if gen=x satisfies the # relational by substituting it into the # expanded form and testing against 0, e.g. # if expr = x*(x + 1) < 2 then e = x*(x + 1) - 2 # and expanded_e = x**2 + x - 2; the test is # whether a given value of x satisfies # x**2 + x - 2 < 0 # # expanded_e, expr and gen used from enclosing scope v = expanded_e.subs(gen, expand_mul(x)) try: r = expr.func(v, 0) except TypeError: r = S.false if r in (S.true, S.false): return r if v.is_extended_real is False: return S.false else: v = v.n(2) if v.is_comparable: return expr.func(v, 0) # not comparable or couldn't be evaluated raise NotImplementedError( 'relationship did not evaluate: %s' % r) singularities = [] for d in denoms(expr, gen): singularities.extend(solvify(d, gen, domain)) if not continuous: domain = continuous_domain(expanded_e, gen, domain) include_x = '=' in expr.rel_op and expr.rel_op != '!=' try: discontinuities = set(domain.boundary - FiniteSet(domain.inf, domain.sup)) # remove points that are not between inf and sup of domain critical_points = FiniteSet( *(solns + singularities + list(discontinuities))).intersection( Interval(domain.inf, domain.sup, domain.inf not in domain, domain.sup not in domain)) if all(r.is_number for r in critical_points): reals = _nsort(critical_points, separated=True)[0] else: sifted = sift(critical_points, lambda x: x.is_extended_real) if sifted[None]: # there were some roots that weren't known # to be real raise NotImplementedError try: reals = sifted[True] if len(reals) > 1: reals = list(sorted(reals)) except TypeError: raise NotImplementedError except NotImplementedError: raise NotImplementedError( 'sorting of these roots is not supported') # If expr contains imaginary coefficients, only take real # values of x for which the imaginary part is 0 make_real = S.Reals if im(expanded_e) != S.Zero: check = True im_sol = FiniteSet() try: a = solveset(im(expanded_e), gen, domain) if not isinstance(a, Interval): for z in a: if z not in singularities and valid( z) and z.is_extended_real: im_sol += FiniteSet(z) else: start, end = a.inf, a.sup for z in _nsort(critical_points + FiniteSet(end)): valid_start = valid(start) if start != end: valid_z = valid(z) pt = _pt(start, z) if pt not in singularities and pt.is_extended_real and valid( pt): if valid_start and valid_z: im_sol += Interval(start, z) elif valid_start: im_sol += Interval.Ropen(start, z) elif valid_z: im_sol += Interval.Lopen(start, z) else: im_sol += Interval.open(start, z) start = z for s in singularities: im_sol -= FiniteSet(s) except (TypeError): im_sol = S.Reals check = False if im_sol is S.EmptySet: raise ValueError( filldedent(''' %s contains imaginary parts which cannot be made 0 for any value of %s satisfying the inequality, leading to relations like I < 0. ''' % (expr.subs(gen, _gen), _gen))) make_real = make_real.intersect(im_sol) sol_sets = [S.EmptySet] start = domain.inf if start in domain and valid(start) and start.is_finite: sol_sets.append(FiniteSet(start)) for x in reals: end = x if valid(_pt(start, end)): sol_sets.append(Interval(start, end, True, True)) if x in singularities: singularities.remove(x) else: if x in discontinuities: discontinuities.remove(x) _valid = valid(x) else: # it's a solution _valid = include_x if _valid: sol_sets.append(FiniteSet(x)) start = end end = domain.sup if end in domain and valid(end) and end.is_finite: sol_sets.append(FiniteSet(end)) if valid(_pt(start, end)): sol_sets.append(Interval.open(start, end)) if im(expanded_e) != S.Zero and check: rv = (make_real).intersect(_domain) else: rv = Intersection((Union(*sol_sets)), make_real, _domain).subs(gen, _gen) return rv if not relational else rv.as_relational(_gen)