def test_is_monotonic(): """Test whether is_monotonic returns correct value.""" assert is_monotonic(1 / (x**2 - 3 * x), Interval.open(Rational(3, 2), 3)) assert is_monotonic(1 / (x**2 - 3 * x), Interval.open(1.5, 3)) assert is_monotonic(1 / (x**2 - 3 * x), Interval.Lopen(3, oo)) assert is_monotonic(x**3 - 3 * x**2 + 4 * x, S.Reals) assert not is_monotonic(-x**2, S.Reals) assert is_monotonic(x**2 + y + 1, Interval(1, 2), x) raises(NotImplementedError, lambda: is_monotonic(x**2 + y + 1))
def test_is_strictly_decreasing(): """Test whether is_strictly_decreasing returns correct value.""" assert is_strictly_decreasing(1 / (x**2 - 3 * x), Interval.Lopen(3, oo)) assert not is_strictly_decreasing(1 / (x**2 - 3 * x), Interval.Ropen(-oo, Rational(3, 2))) assert not is_strictly_decreasing(-x**2, Interval(-oo, 0)) assert not is_strictly_decreasing(1) assert is_strictly_decreasing(1 / (x**2 - 3 * x), Interval.open(Rational(3, 2), 3)) assert is_strictly_decreasing(1 / (x**2 - 3 * x), Interval.open(1.5, 3))
def test_is_decreasing(): """Test whether is_decreasing returns correct value.""" b = Symbol('b', positive=True) assert is_decreasing(1 / (x**2 - 3 * x), Interval.open(Rational(3, 2), 3)) assert is_decreasing(1 / (x**2 - 3 * x), Interval.open(1.5, 3)) assert is_decreasing(1 / (x**2 - 3 * x), Interval.Lopen(3, oo)) assert not is_decreasing(1 / (x**2 - 3 * x), Interval.Ropen(-oo, Rational(3, 2))) assert not is_decreasing(-x**2, Interval(-oo, 0)) assert not is_decreasing(-x**2 * b, Interval(-oo, 0), x)
def test_is_strictly_increasing(): """Test whether is_strictly_increasing returns correct value.""" assert is_strictly_increasing( 4*x**3 - 6*x**2 - 72*x + 30, Interval.Ropen(-oo, -2)) assert is_strictly_increasing( 4*x**3 - 6*x**2 - 72*x + 30, Interval.Lopen(3, oo)) assert not is_strictly_increasing( 4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3)) assert not is_strictly_increasing(-x**2, Interval(0, oo)) assert not is_strictly_decreasing(1) assert is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3)) is False
def test_is_monotonic(): """Test whether is_monotonic returns correct value.""" assert is_monotonic(1/(x**2 - 3*x), Interval.open(1.5, 3)) assert is_monotonic(1/(x**2 - 3*x), Interval.Lopen(3, oo)) assert is_monotonic(x**3 - 3*x**2 + 4*x, S.Reals) assert not is_monotonic(-x**2, S.Reals) assert is_monotonic(x**2 + y + 1, Interval(1, 2), x)
def test_is_monotonic(): """Test whether is_monotonic returns correct value.""" assert is_monotonic(1 / (x**2 - 3 * x), Interval.open(1.5, 3)) assert is_monotonic(1 / (x**2 - 3 * x), Interval.Lopen(3, oo)) assert is_monotonic(x**3 - 3 * x**2 + 4 * x, S.Reals) assert not is_monotonic(-x**2, S.Reals) assert is_monotonic(x**2 + y + 1, Interval(1, 2), x)
def test_is_decreasing(): assert is_decreasing(1 / (x**2 - 3 * x), Interval.open(1.5, 3)) assert is_decreasing(1 / (x**2 - 3 * x), Interval.Lopen(3, oo)) assert is_decreasing(1 / (x**2 - 3 * x), Interval.Ropen(-oo, S(3) / 2)) is False assert is_decreasing(-x**2, Interval(-oo, 0)) is False assert is_decreasing(-x**2 * b, Interval(-oo, 0), x) is False
def test_SetExpr_Interval_div(): # TODO: some expressions cannot be calculated due to bugs (currently # commented): assert SetExpr(Interval(-3, -2)) / SetExpr(Interval(-2, 1)) == SetExpr( Interval(-oo, oo)) assert SetExpr(Interval(2, 3)) / SetExpr(Interval(-2, 2)) == SetExpr( Interval(-oo, oo)) assert SetExpr(Interval(-3, -2)) / SetExpr(Interval(0, 4)) == SetExpr( Interval(-oo, Rational(-1, 2))) assert SetExpr(Interval(2, 4)) / SetExpr(Interval(-3, 0)) == SetExpr( Interval(-oo, Rational(-2, 3))) assert SetExpr(Interval(2, 4)) / SetExpr(Interval(0, 3)) == SetExpr( Interval(Rational(2, 3), oo)) # assert SetExpr(Interval(0, 1))/SetExpr(Interval(0, 1)) == SetExpr(Interval(0, oo)) # assert SetExpr(Interval(-1, 0))/SetExpr(Interval(0, 1)) == SetExpr(Interval(-oo, 0)) assert SetExpr(Interval(-1, 2)) / SetExpr(Interval(-2, 2)) == SetExpr( Interval(-oo, oo)) assert 1 / SetExpr(Interval(-1, 2)) == SetExpr( Union(Interval(-oo, -1), Interval(S.Half, oo))) assert 1 / SetExpr(Interval(0, 2)) == SetExpr(Interval(S.Half, oo)) assert (-1) / SetExpr(Interval(0, 2)) == SetExpr( Interval(-oo, Rational(-1, 2))) assert 1 / SetExpr(Interval(-oo, 0)) == SetExpr(Interval.open(-oo, 0)) assert 1 / SetExpr(Interval(-1, 0)) == SetExpr(Interval(-oo, -1))
def test_is_strictly_increasing(): assert is_strictly_increasing(4 * x**3 - 6 * x**2 - 72 * x + 30, Interval.Ropen(-oo, -2)) assert is_strictly_increasing(4 * x**3 - 6 * x**2 - 72 * x + 30, Interval.Lopen(3, oo)) assert is_strictly_increasing(4 * x**3 - 6 * x**2 - 72 * x + 30, Interval.open(-2, 3)) is False assert is_strictly_increasing(-x**2, Interval(0, oo)) is False
def test_is_strictly_decreasing(): """Test whether is_strictly_decreasing returns correct value.""" assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) assert not is_strictly_decreasing( 1/(x**2 - 3*x), Interval.Ropen(-oo, S(3)/2)) assert not is_strictly_decreasing(-x**2, Interval(-oo, 0)) assert not is_strictly_decreasing(1) assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3))
def test_is_decreasing(): """Test whether is_decreasing returns correct value.""" b = Symbol('b', positive=True) assert is_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3)) assert is_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) assert not is_decreasing(1/(x**2 - 3*x), Interval.Ropen(-oo, S(3)/2)) assert not is_decreasing(-x**2, Interval(-oo, 0)) assert not is_decreasing(-x**2*b, Interval(-oo, 0), x)
def test_SetExpr_Interval_pow(): assert SetExpr(Interval(0, 2))**2 == SetExpr(Interval(0, 4)) assert SetExpr(Interval(-1, 1))**2 == SetExpr(Interval(0, 1)) assert SetExpr(Interval(1, 2))**2 == SetExpr(Interval(1, 4)) assert SetExpr(Interval(-1, 2))**3 == SetExpr(Interval(-1, 8)) assert SetExpr(Interval(-1, 1))**0 == SetExpr(FiniteSet(1)) #assert SetExpr(Interval(1, 2))**Rational(5, 2) == SetExpr(Interval(1, 4*sqrt(2))) #assert SetExpr(Interval(-1, 2))**Rational(1, 3) == SetExpr(Interval(-1, 2**Rational(1, 3))) #assert SetExpr(Interval(0, 2))**S.Half == SetExpr(Interval(0, sqrt(2))) #assert SetExpr(Interval(-4, 2))**Rational(2, 3) == SetExpr(Interval(0, 2*2**Rational(1, 3))) #assert SetExpr(Interval(-1, 5))**S.Half == SetExpr(Interval(0, sqrt(5))) #assert SetExpr(Interval(-oo, 2))**S.Half == SetExpr(Interval(0, sqrt(2))) #assert SetExpr(Interval(-2, 3))**(Rational(-1, 4)) == SetExpr(Interval(0, oo)) assert SetExpr(Interval(1, 5))**(-2) == SetExpr(Interval(Rational(1, 25), 1)) assert SetExpr(Interval(-1, 3))**(-2) == SetExpr(Interval(0, oo)) assert SetExpr(Interval(0, 2))**(-2) == SetExpr(Interval(Rational(1, 4), oo)) assert SetExpr(Interval(-1, 2))**(-3) == SetExpr(Union(Interval(-oo, -1), Interval(Rational(1, 8), oo))) assert SetExpr(Interval(-3, -2))**(-3) == SetExpr(Interval(Rational(-1, 8), Rational(-1, 27))) assert SetExpr(Interval(-3, -2))**(-2) == SetExpr(Interval(Rational(1, 9), Rational(1, 4))) #assert SetExpr(Interval(0, oo))**S.Half == SetExpr(Interval(0, oo)) #assert SetExpr(Interval(-oo, -1))**Rational(1, 3) == SetExpr(Interval(-oo, -1)) #assert SetExpr(Interval(-2, 3))**(Rational(-1, 3)) == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-oo, 0))**(-2) == SetExpr(Interval.open(0, oo)) assert SetExpr(Interval(-2, 0))**(-2) == SetExpr(Interval(Rational(1, 4), oo)) assert SetExpr(Interval(Rational(1, 3), S.Half))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(0, S.Half))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(S.Half, 1))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(0, 1))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(2, 3))**oo == SetExpr(FiniteSet(oo)) assert SetExpr(Interval(1, 2))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(S.Half, 3))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(Rational(-1, 3), Rational(-1, 4)))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(-1, Rational(-1, 2)))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-3, -2))**oo == SetExpr(FiniteSet(-oo, oo)) assert SetExpr(Interval(-2, -1))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-2, Rational(-1, 2)))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(Rational(-1, 2), S.Half))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(Rational(-1, 2), 1))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(Rational(-2, 3), 2))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(-1, 1))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-1, S.Half))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-1, 2))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-2, S.Half))**oo == SetExpr(Interval(-oo, oo)) assert (SetExpr(Interval(1, 2))**x).dummy_eq(SetExpr(ImageSet(Lambda(_d, _d**x), Interval(1, 2)))) assert SetExpr(Interval(2, 3))**(-oo) == SetExpr(FiniteSet(0)) assert SetExpr(Interval(0, 2))**(-oo) == SetExpr(Interval(0, oo)) assert (SetExpr(Interval(-1, 2))**(-oo)).dummy_eq(SetExpr(ImageSet(Lambda(_d, _d**(-oo)), Interval(-1, 2))))
def test_is_strictly_increasing(): """Test whether is_strictly_increasing returns correct value.""" assert is_strictly_increasing( 4*x**3 - 6*x**2 - 72*x + 30, Interval.Ropen(-oo, -2)) assert is_strictly_increasing( 4*x**3 - 6*x**2 - 72*x + 30, Interval.Lopen(3, oo)) assert not is_strictly_increasing( 4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3)) assert not is_strictly_increasing(-x**2, Interval(0, oo)) assert not is_strictly_decreasing(1)
def test_SetExpr_Interval_pow(): assert SetExpr(Interval(0, 2))**2 == SetExpr(Interval(0, 4)) assert SetExpr(Interval(-1, 1))**2 == SetExpr(Interval(0, 1)) assert SetExpr(Interval(1, 2))**2 == SetExpr(Interval(1, 4)) assert SetExpr(Interval(-1, 2))**3 == SetExpr(Interval(-1, 8)) assert SetExpr(Interval(-1, 1))**0 == SetExpr(FiniteSet(1)) #assert SetExpr(Interval(1, 2))**(S(5)/2) == SetExpr(Interval(1, 4*sqrt(2))) #assert SetExpr(Interval(-1, 2))**(S.One/3) == SetExpr(Interval(-1, 2**(S.One/3))) #assert SetExpr(Interval(0, 2))**(S.One/2) == SetExpr(Interval(0, sqrt(2))) #assert SetExpr(Interval(-4, 2))**(S(2)/3) == SetExpr(Interval(0, 2*2**(S.One/3))) #assert SetExpr(Interval(-1, 5))**(S.One/2) == SetExpr(Interval(0, sqrt(5))) #assert SetExpr(Interval(-oo, 2))**(S.One/2) == SetExpr(Interval(0, sqrt(2))) #assert SetExpr(Interval(-2, 3))**(S(-1)/4) == SetExpr(Interval(0, oo)) assert SetExpr(Interval(1, 5))**(-2) == SetExpr(Interval(S.One/25, 1)) assert SetExpr(Interval(-1, 3))**(-2) == SetExpr(Interval(0, oo)) assert SetExpr(Interval(0, 2))**(-2) == SetExpr(Interval(S.One/4, oo)) assert SetExpr(Interval(-1, 2))**(-3) == SetExpr(Union(Interval(-oo, -1), Interval(S(1)/8, oo))) assert SetExpr(Interval(-3, -2))**(-3) == SetExpr(Interval(S(-1)/8, -S.One/27)) assert SetExpr(Interval(-3, -2))**(-2) == SetExpr(Interval(S.One/9, S.One/4)) #assert SetExpr(Interval(0, oo))**(S.One/2) == SetExpr(Interval(0, oo)) #assert SetExpr(Interval(-oo, -1))**(S.One/3) == SetExpr(Interval(-oo, -1)) #assert SetExpr(Interval(-2, 3))**(-S.One/3) == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-oo, 0))**(-2) == SetExpr(Interval.open(0, oo)) assert SetExpr(Interval(-2, 0))**(-2) == SetExpr(Interval(S.One/4, oo)) assert SetExpr(Interval(S.One/3, S.One/2))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(0, S.One/2))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(S.One/2, 1))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(0, 1))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(2, 3))**oo == SetExpr(FiniteSet(oo)) assert SetExpr(Interval(1, 2))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(S.One/2, 3))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(-S.One/3, -S.One/4))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(-1, -S.One/2))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-3, -2))**oo == SetExpr(FiniteSet(-oo, oo)) assert SetExpr(Interval(-2, -1))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-2, -S.One/2))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-S.One/2, S.One/2))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(-S.One/2, 1))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(-S(2)/3, 2))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(-1, 1))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-1, S.One/2))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-1, 2))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-2, S.One/2))**oo == SetExpr(Interval(-oo, oo)) assert (SetExpr(Interval(1, 2))**x).dummy_eq(SetExpr(ImageSet(Lambda(_d, _d**x), Interval(1, 2)))) assert SetExpr(Interval(2, 3))**(-oo) == SetExpr(FiniteSet(0)) assert SetExpr(Interval(0, 2))**(-oo) == SetExpr(Interval(0, oo)) assert (SetExpr(Interval(-1, 2))**(-oo)).dummy_eq(SetExpr(ImageSet(Lambda(_d, _d**(-oo)), Interval(-1, 2))))
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 `solvify`. Notes ===== Currently, we cannot solve all the inequalities due to limitations in `solvify`. Also, the solution returned for trigonometric inequalities are restricted in its periodic interval. See Also ======== solvify: solver returning solveset solutions with solve's output API Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy import Symbol, sin, Interval, S >>> x = Symbol('x') >>> solve_univariate_inequality(x**2 >= 4, x) ((2 <= x) & (x < oo)) | ((x <= -2) & (-oo < x)) >>> 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.calculus.util import (continuous_domain, periodicity, function_range) from sympy.solvers.solvers import denoms from sympy.solvers.solveset import solveset_real, solvify # This keeps the function independent of the assumptions about `gen`. # `solveset` makes sure this function is called only when the domain is # real. d = Dummy(real=True) expr = expr.subs(gen, d) _gen = gen gen = d 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 is not None: frange = function_range(e, gen, domain) rel = expr.rel_op if rel == '<' or rel == '<=': if expr.func(frange.sup, 0): rv = domain elif not expr.func(frange.inf, 0): rv = S.EmptySet elif rel == '>' or rel == '>=': 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) if rv is None: solns = solvify(e, gen, domain) if solns is None: raise NotImplementedError(filldedent('''The inequality cannot be solved using solve_univariate_inequality.''')) singularities = [] for d in denoms(expr, gen): singularities.extend(solvify(d, gen, domain)) if not continuous: domain = continuous_domain(e, gen, domain) include_x = expr.func(0, 0) def valid(x): v = e.subs(gen, x) try: r = expr.func(v, 0) except TypeError: r = S.false if r in (S.true, S.false): return r if v.is_real is False: return S.false else: v = v.n(2) if v.is_comparable: return expr.func(v, 0) return S.false 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)) reals = _nsort(critical_points, separated=True)[0] except NotImplementedError: raise NotImplementedError('sorting of these roots is not supported') sol_sets = [S.EmptySet] start = domain.inf if 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 valid(end) and end.is_finite: sol_sets.append(FiniteSet(end)) if valid(_pt(start, end)): sol_sets.append(Interval.open(start, end)) rv = Union(*sol_sets).subs(gen, _gen) return rv if not relational else rv.as_relational(_gen)
def test_strictly_decreasing(): assert is_strictly_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3))
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 `solvify`. Notes ===== Currently, we cannot solve all the inequalities due to limitations in `solvify`. Also, the solution returned for trigonometric inequalities are restricted in its periodic interval. See Also ======== solvify: solver returning solveset solutions with solve's output API Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy import Symbol, sin, Interval, S >>> x = Symbol('x') >>> solve_univariate_inequality(x**2 >= 4, x) ((2 <= x) & (x < oo)) | ((x <= -2) & (-oo < x)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) Union(Interval(-oo, -2, True), Interval(2, oo, False, True)) >>> domain = Interval(0, S.Infinity) >>> solve_univariate_inequality(x**2 >= 4, x, False, domain) Interval(2, oo, False, True) >>> solve_univariate_inequality(sin(x) > 0, x, relational=False) Interval(0, pi, True, True) """ from sympy.calculus.util import (continuous_domain, periodicity, function_range) from sympy.solvers.solvers import denoms from sympy.solvers.solveset import solveset_real, solvify # This keeps the function independent of the assumptions about `gen`. # `solveset` makes sure this function is called only when the domain is # real. d = Dummy(real=True) expr = expr.subs(gen, d) _gen = gen gen = d 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 is not None: frange = function_range(e, gen, domain) rel = expr.rel_op if rel == '<' or rel == '<=': if expr.func(frange.sup, 0): rv = domain elif not expr.func(frange.inf, 0): rv = S.EmptySet elif rel == '>' or rel == '>=': 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) if rv is None: solns = solvify(e, gen, domain) if solns is None: raise NotImplementedError( filldedent('''The inequality cannot be solved using solve_univariate_inequality.''')) singularities = [] for d in denoms(expr, gen): singularities.extend(solvify(d, gen, domain)) if not continuous: domain = continuous_domain(e, gen, domain) include_x = expr.func(0, 0) def valid(x): v = e.subs(gen, x) try: r = expr.func(v, 0) except TypeError: r = S.false if r in (S.true, S.false): return r if v.is_real is False: return S.false else: v = v.n(2) if v.is_comparable: return expr.func(v, 0) return S.false 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)) reals = _nsort(critical_points, separated=True)[0] except NotImplementedError: raise NotImplementedError( 'sorting of these roots is not supported') sol_sets = [S.EmptySet] start = domain.inf if 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 valid(end) and end.is_finite: sol_sets.append(FiniteSet(end)) if valid(_pt(start, end)): sol_sets.append(Interval.open(start, end)) rv = Union(*sol_sets).subs(gen, _gen) return rv if not relational else rv.as_relational(_gen)
def test_strictly_decreasing(): assert is_strictly_decreasing(1 / (x**2 - 3 * x), Interval.open(1.5, 3))
def test_is_monotonic(): assert is_monotonic(1 / (x**2 - 3 * x), Interval.open(1.5, 3)) assert is_monotonic(1 / (x**2 - 3 * x), Interval.Lopen(3, oo)) assert is_monotonic(x**3 - 3 * x**2 + 4 * x, S.Reals) assert is_monotonic(-x**2, S.Reals) is False assert is_monotonic(x**2 + y + 1, Interval(1, 2), x) is True
def test_is_strictly_increasing(): assert is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.Ropen(-oo, -2)) assert is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.Lopen(3, oo)) assert is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3)) is False assert is_strictly_increasing(-x**2, Interval(0, oo)) is False
def test_Interval_arithmetic(): i12cc = SetExpr(Interval(1, 2)) i12lo = SetExpr(Interval.Lopen(1, 2)) i12ro = SetExpr(Interval.Ropen(1, 2)) i12o = SetExpr(Interval.open(1, 2)) n23cc = SetExpr(Interval(-2, 3)) n23lo = SetExpr(Interval.Lopen(-2, 3)) n23ro = SetExpr(Interval.Ropen(-2, 3)) n23o = SetExpr(Interval.open(-2, 3)) n3n2cc = SetExpr(Interval(-3, -2)) assert i12cc + i12cc == SetExpr(Interval(2, 4)) assert i12cc - i12cc == SetExpr(Interval(-1, 1)) assert i12cc * i12cc == SetExpr(Interval(1, 4)) assert i12cc / i12cc == SetExpr(Interval(S.Half, 2)) assert i12cc ** 2 == SetExpr(Interval(1, 4)) assert i12cc ** 3 == SetExpr(Interval(1, 8)) assert i12lo + i12ro == SetExpr(Interval.open(2, 4)) assert i12lo - i12ro == SetExpr(Interval.Lopen(-1, 1)) assert i12lo * i12ro == SetExpr(Interval.open(1, 4)) assert i12lo / i12ro == SetExpr(Interval.Lopen(S.Half, 2)) assert i12lo + i12lo == SetExpr(Interval.Lopen(2, 4)) assert i12lo - i12lo == SetExpr(Interval.open(-1, 1)) assert i12lo * i12lo == SetExpr(Interval.Lopen(1, 4)) assert i12lo / i12lo == SetExpr(Interval.open(S.Half, 2)) assert i12lo + i12cc == SetExpr(Interval.Lopen(2, 4)) assert i12lo - i12cc == SetExpr(Interval.Lopen(-1, 1)) assert i12lo * i12cc == SetExpr(Interval.Lopen(1, 4)) assert i12lo / i12cc == SetExpr(Interval.Lopen(S.Half, 2)) assert i12lo + i12o == SetExpr(Interval.open(2, 4)) assert i12lo - i12o == SetExpr(Interval.open(-1, 1)) assert i12lo * i12o == SetExpr(Interval.open(1, 4)) assert i12lo / i12o == SetExpr(Interval.open(S.Half, 2)) assert i12lo ** 2 == SetExpr(Interval.Lopen(1, 4)) assert i12lo ** 3 == SetExpr(Interval.Lopen(1, 8)) assert i12ro + i12ro == SetExpr(Interval.Ropen(2, 4)) assert i12ro - i12ro == SetExpr(Interval.open(-1, 1)) assert i12ro * i12ro == SetExpr(Interval.Ropen(1, 4)) assert i12ro / i12ro == SetExpr(Interval.open(S.Half, 2)) assert i12ro + i12cc == SetExpr(Interval.Ropen(2, 4)) assert i12ro - i12cc == SetExpr(Interval.Ropen(-1, 1)) assert i12ro * i12cc == SetExpr(Interval.Ropen(1, 4)) assert i12ro / i12cc == SetExpr(Interval.Ropen(S.Half, 2)) assert i12ro + i12o == SetExpr(Interval.open(2, 4)) assert i12ro - i12o == SetExpr(Interval.open(-1, 1)) assert i12ro * i12o == SetExpr(Interval.open(1, 4)) assert i12ro / i12o == SetExpr(Interval.open(S.Half, 2)) assert i12ro ** 2 == SetExpr(Interval.Ropen(1, 4)) assert i12ro ** 3 == SetExpr(Interval.Ropen(1, 8)) assert i12o + i12lo == SetExpr(Interval.open(2, 4)) assert i12o - i12lo == SetExpr(Interval.open(-1, 1)) assert i12o * i12lo == SetExpr(Interval.open(1, 4)) assert i12o / i12lo == SetExpr(Interval.open(S.Half, 2)) assert i12o + i12ro == SetExpr(Interval.open(2, 4)) assert i12o - i12ro == SetExpr(Interval.open(-1, 1)) assert i12o * i12ro == SetExpr(Interval.open(1, 4)) assert i12o / i12ro == SetExpr(Interval.open(S.Half, 2)) assert i12o + i12cc == SetExpr(Interval.open(2, 4)) assert i12o - i12cc == SetExpr(Interval.open(-1, 1)) assert i12o * i12cc == SetExpr(Interval.open(1, 4)) assert i12o / i12cc == SetExpr(Interval.open(S.Half, 2)) assert i12o ** 2 == SetExpr(Interval.open(1, 4)) assert i12o ** 3 == SetExpr(Interval.open(1, 8)) assert n23cc + n23cc == SetExpr(Interval(-4, 6)) assert n23cc - n23cc == SetExpr(Interval(-5, 5)) assert n23cc * n23cc == SetExpr(Interval(-6, 9)) assert n23cc / n23cc == SetExpr(Interval.open(-oo, oo)) assert n23cc + n23ro == SetExpr(Interval.Ropen(-4, 6)) assert n23cc - n23ro == SetExpr(Interval.Lopen(-5, 5)) assert n23cc * n23ro == SetExpr(Interval.Ropen(-6, 9)) assert n23cc / n23ro == SetExpr(Interval.Lopen(-oo, oo)) assert n23cc + n23lo == SetExpr(Interval.Lopen(-4, 6)) assert n23cc - n23lo == SetExpr(Interval.Ropen(-5, 5)) assert n23cc * n23lo == SetExpr(Interval(-6, 9)) assert n23cc / n23lo == SetExpr(Interval.open(-oo, oo)) assert n23cc + n23o == SetExpr(Interval.open(-4, 6)) assert n23cc - n23o == SetExpr(Interval.open(-5, 5)) assert n23cc * n23o == SetExpr(Interval.open(-6, 9)) assert n23cc / n23o == SetExpr(Interval.open(-oo, oo)) assert n23cc ** 2 == SetExpr(Interval(0, 9)) assert n23cc ** 3 == SetExpr(Interval(-8, 27)) n32cc = SetExpr(Interval(-3, 2)) n32lo = SetExpr(Interval.Lopen(-3, 2)) n32ro = SetExpr(Interval.Ropen(-3, 2)) assert n32cc * n32lo == SetExpr(Interval.Ropen(-6, 9)) assert n32cc * n32cc == SetExpr(Interval(-6, 9)) assert n32lo * n32cc == SetExpr(Interval.Ropen(-6, 9)) assert n32cc * n32ro == SetExpr(Interval(-6, 9)) assert n32lo * n32ro == SetExpr(Interval.Ropen(-6, 9)) assert n32cc / n32lo == SetExpr(Interval.Ropen(-oo, oo)) assert i12cc / n32lo == SetExpr(Interval.Ropen(-oo, oo)) assert n3n2cc ** 2 == SetExpr(Interval(4, 9)) assert n3n2cc ** 3 == SetExpr(Interval(-27, -8)) assert n23cc + i12cc == SetExpr(Interval(-1, 5)) assert n23cc - i12cc == SetExpr(Interval(-4, 2)) assert n23cc * i12cc == SetExpr(Interval(-4, 6)) assert n23cc / i12cc == SetExpr(Interval(-2, 3))
def test_is_strictly_decreasing(): assert is_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3)) assert is_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) assert is_decreasing(1/(x**2 - 3*x), Interval.Ropen(-oo, S(3)/2)) is False assert is_decreasing(-x**2, Interval(-oo, 0)) is False
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 `solvify`. Notes ===== Currently, we cannot solve all the inequalities due to limitations in `solvify`. Also, the solution returned for trigonometric inequalities are restricted in its periodic interval. See Also ======== solvify: solver returning solveset solutions with solve's output API Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy import Symbol, sin, Interval, S >>> x = Symbol('x') >>> solve_univariate_inequality(x**2 >= 4, x) ((2 <= x) & (x < oo)) | ((x <= -2) & (-oo < x)) >>> 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 import im from sympy.calculus.util import (continuous_domain, periodicity, function_range) from sympy.solvers.solvers import denoms from sympy.solvers.solveset import solveset_real, solvify, solveset from sympy.solvers.solvers import solve # 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_real is False: rv = S.EmptySet return rv if not relational else rv.as_relational(_gen) elif gen.is_real is None: gen = Dummy('gen', 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 is not None: frange = function_range(e, gen, domain) rel = expr.rel_op if rel == '<' or rel == '<=': if expr.func(frange.sup, 0): rv = domain elif not expr.func(frange.inf, 0): rv = S.EmptySet elif rel == '>' or rel == '>=': 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) 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): raise NotImplementedError(filldedent(''' The inequality cannot be solved using solve_univariate_inequality. ''')) 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, x) try: r = expr.func(v, 0) except TypeError: r = S.false if r in (S.true, S.false): return r if v.is_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(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: from sympy.utilities.iterables import sift sifted = sift(critical_points, lambda x: x.is_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 real values of x for which the imaginary part is 0 are taken 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_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_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 isinstance(im_sol, 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) empty = sol_sets = [S.EmptySet] start = domain.inf if 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 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)
def test_is_monotonic(): assert is_monotonic(1/(x**2 - 3*x), Interval.open(1.5, 3)) assert is_monotonic(1/(x**2 - 3*x), Interval.Lopen(3, oo)) assert is_monotonic(x**3 - 3*x**2 + 4*x, S.Reals) assert is_monotonic(-x**2, S.Reals) is False
def test_Interval_arithmetic(): i12cc = SetExpr(Interval(1, 2)) i12lo = SetExpr(Interval.Lopen(1, 2)) i12ro = SetExpr(Interval.Ropen(1, 2)) i12o = SetExpr(Interval.open(1, 2)) n23cc = SetExpr(Interval(-2, 3)) n23lo = SetExpr(Interval.Lopen(-2, 3)) n23ro = SetExpr(Interval.Ropen(-2, 3)) n23o = SetExpr(Interval.open(-2, 3)) n3n2cc = SetExpr(Interval(-3, -2)) assert i12cc + i12cc == SetExpr(Interval(2, 4)) assert i12cc - i12cc == SetExpr(Interval(-1, 1)) assert i12cc * i12cc == SetExpr(Interval(1, 4)) assert i12cc / i12cc == SetExpr(Interval(S.Half, 2)) assert i12cc**2 == SetExpr(Interval(1, 4)) assert i12cc**3 == SetExpr(Interval(1, 8)) assert i12lo + i12ro == SetExpr(Interval.open(2, 4)) assert i12lo - i12ro == SetExpr(Interval.Lopen(-1, 1)) assert i12lo * i12ro == SetExpr(Interval.open(1, 4)) assert i12lo / i12ro == SetExpr(Interval.Lopen(S.Half, 2)) assert i12lo + i12lo == SetExpr(Interval.Lopen(2, 4)) assert i12lo - i12lo == SetExpr(Interval.open(-1, 1)) assert i12lo * i12lo == SetExpr(Interval.Lopen(1, 4)) assert i12lo / i12lo == SetExpr(Interval.open(S.Half, 2)) assert i12lo + i12cc == SetExpr(Interval.Lopen(2, 4)) assert i12lo - i12cc == SetExpr(Interval.Lopen(-1, 1)) assert i12lo * i12cc == SetExpr(Interval.Lopen(1, 4)) assert i12lo / i12cc == SetExpr(Interval.Lopen(S.Half, 2)) assert i12lo + i12o == SetExpr(Interval.open(2, 4)) assert i12lo - i12o == SetExpr(Interval.open(-1, 1)) assert i12lo * i12o == SetExpr(Interval.open(1, 4)) assert i12lo / i12o == SetExpr(Interval.open(S.Half, 2)) assert i12lo**2 == SetExpr(Interval.Lopen(1, 4)) assert i12lo**3 == SetExpr(Interval.Lopen(1, 8)) assert i12ro + i12ro == SetExpr(Interval.Ropen(2, 4)) assert i12ro - i12ro == SetExpr(Interval.open(-1, 1)) assert i12ro * i12ro == SetExpr(Interval.Ropen(1, 4)) assert i12ro / i12ro == SetExpr(Interval.open(S.Half, 2)) assert i12ro + i12cc == SetExpr(Interval.Ropen(2, 4)) assert i12ro - i12cc == SetExpr(Interval.Ropen(-1, 1)) assert i12ro * i12cc == SetExpr(Interval.Ropen(1, 4)) assert i12ro / i12cc == SetExpr(Interval.Ropen(S.Half, 2)) assert i12ro + i12o == SetExpr(Interval.open(2, 4)) assert i12ro - i12o == SetExpr(Interval.open(-1, 1)) assert i12ro * i12o == SetExpr(Interval.open(1, 4)) assert i12ro / i12o == SetExpr(Interval.open(S.Half, 2)) assert i12ro**2 == SetExpr(Interval.Ropen(1, 4)) assert i12ro**3 == SetExpr(Interval.Ropen(1, 8)) assert i12o + i12lo == SetExpr(Interval.open(2, 4)) assert i12o - i12lo == SetExpr(Interval.open(-1, 1)) assert i12o * i12lo == SetExpr(Interval.open(1, 4)) assert i12o / i12lo == SetExpr(Interval.open(S.Half, 2)) assert i12o + i12ro == SetExpr(Interval.open(2, 4)) assert i12o - i12ro == SetExpr(Interval.open(-1, 1)) assert i12o * i12ro == SetExpr(Interval.open(1, 4)) assert i12o / i12ro == SetExpr(Interval.open(S.Half, 2)) assert i12o + i12cc == SetExpr(Interval.open(2, 4)) assert i12o - i12cc == SetExpr(Interval.open(-1, 1)) assert i12o * i12cc == SetExpr(Interval.open(1, 4)) assert i12o / i12cc == SetExpr(Interval.open(S.Half, 2)) assert i12o**2 == SetExpr(Interval.open(1, 4)) assert i12o**3 == SetExpr(Interval.open(1, 8)) assert n23cc + n23cc == SetExpr(Interval(-4, 6)) assert n23cc - n23cc == SetExpr(Interval(-5, 5)) assert n23cc * n23cc == SetExpr(Interval(-6, 9)) assert n23cc / n23cc == SetExpr(Interval.open(-oo, oo)) assert n23cc + n23ro == SetExpr(Interval.Ropen(-4, 6)) assert n23cc - n23ro == SetExpr(Interval.Lopen(-5, 5)) assert n23cc * n23ro == SetExpr(Interval.Ropen(-6, 9)) assert n23cc / n23ro == SetExpr(Interval.Lopen(-oo, oo)) assert n23cc + n23lo == SetExpr(Interval.Lopen(-4, 6)) assert n23cc - n23lo == SetExpr(Interval.Ropen(-5, 5)) assert n23cc * n23lo == SetExpr(Interval(-6, 9)) assert n23cc / n23lo == SetExpr(Interval.open(-oo, oo)) assert n23cc + n23o == SetExpr(Interval.open(-4, 6)) assert n23cc - n23o == SetExpr(Interval.open(-5, 5)) assert n23cc * n23o == SetExpr(Interval.open(-6, 9)) assert n23cc / n23o == SetExpr(Interval.open(-oo, oo)) assert n23cc**2 == SetExpr(Interval(0, 9)) assert n23cc**3 == SetExpr(Interval(-8, 27)) n32cc = SetExpr(Interval(-3, 2)) n32lo = SetExpr(Interval.Lopen(-3, 2)) n32ro = SetExpr(Interval.Ropen(-3, 2)) assert n32cc * n32lo == SetExpr(Interval.Ropen(-6, 9)) assert n32cc * n32cc == SetExpr(Interval(-6, 9)) assert n32lo * n32cc == SetExpr(Interval.Ropen(-6, 9)) assert n32cc * n32ro == SetExpr(Interval(-6, 9)) assert n32lo * n32ro == SetExpr(Interval.Ropen(-6, 9)) assert n32cc / n32lo == SetExpr(Interval.Ropen(-oo, oo)) assert i12cc / n32lo == SetExpr(Interval.Ropen(-oo, oo)) assert n3n2cc**2 == SetExpr(Interval(4, 9)) assert n3n2cc**3 == SetExpr(Interval(-27, -8)) assert n23cc + i12cc == SetExpr(Interval(-1, 5)) assert n23cc - i12cc == SetExpr(Interval(-4, 2)) assert n23cc * i12cc == SetExpr(Interval(-4, 6)) assert n23cc / i12cc == SetExpr(Interval(-2, 3))
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 `solvify`. Notes ===== Currently, we cannot solve all the inequalities due to limitations in `solvify`. Also, the solution returned for trigonometric inequalities are restricted in its periodic interval. See Also ======== solvify: solver returning solveset solutions with solve's output API Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy import Symbol, sin, Interval, S >>> x = Symbol('x') >>> solve_univariate_inequality(x**2 >= 4, x) ((2 <= x) & (x < oo)) | ((x <= -2) & (-oo < x)) >>> 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 import im from sympy.calculus.util import (continuous_domain, periodicity, function_range) from sympy.solvers.solvers import denoms from sympy.solvers.solveset import solveset_real, solvify, solveset from sympy.solvers.solvers import solve # 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_real is False: rv = S.EmptySet return rv if not relational else rv.as_relational(_gen) elif gen.is_real is None: gen = Dummy('gen', 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 is 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 == '<' or rel == '<=': if expr.func(frange.sup, 0): rv = domain elif not expr.func(frange.inf, 0): rv = S.EmptySet elif rel == '>' or rel == '>=': 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) 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_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: from sympy.utilities.iterables import sift sifted = sift(critical_points, lambda x: x.is_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_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_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 isinstance(im_sol, 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) empty = sol_sets = [S.EmptySet] start = domain.inf if 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 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)
def test_SetExpr_Interval_pow(): assert SetExpr(Interval(0, 2))**2 == SetExpr(Interval(0, 4)) assert SetExpr(Interval(-1, 1))**2 == SetExpr(Interval(0, 1)) assert SetExpr(Interval(1, 2))**2 == SetExpr(Interval(1, 4)) assert SetExpr(Interval(-1, 2))**3 == SetExpr(Interval(-1, 8)) assert SetExpr(Interval(-1, 1))**0 == SetExpr(FiniteSet(1)) #assert SetExpr(Interval(1, 2))**(S(5)/2) == SetExpr(Interval(1, 4*sqrt(2))) #assert SetExpr(Interval(-1, 2))**(S.One/3) == SetExpr(Interval(-1, 2**(S.One/3))) #assert SetExpr(Interval(0, 2))**(S.One/2) == SetExpr(Interval(0, sqrt(2))) #assert SetExpr(Interval(-4, 2))**(S(2)/3) == SetExpr(Interval(0, 2*2**(S.One/3))) #assert SetExpr(Interval(-1, 5))**(S.One/2) == SetExpr(Interval(0, sqrt(5))) #assert SetExpr(Interval(-oo, 2))**(S.One/2) == SetExpr(Interval(0, sqrt(2))) #assert SetExpr(Interval(-2, 3))**(S(-1)/4) == SetExpr(Interval(0, oo)) assert SetExpr(Interval(1, 5))**(-2) == SetExpr(Interval(S.One / 25, 1)) assert SetExpr(Interval(-1, 3))**(-2) == SetExpr(Interval(0, oo)) assert SetExpr(Interval(0, 2))**(-2) == SetExpr(Interval(S.One / 4, oo)) assert SetExpr(Interval(-1, 2))**(-3) == SetExpr( Union(Interval(-oo, -1), Interval(S(1) / 8, oo))) assert SetExpr(Interval(-3, -2))**(-3) == SetExpr( Interval(S(-1) / 8, -S.One / 27)) assert SetExpr(Interval(-3, -2))**(-2) == SetExpr( Interval(S.One / 9, S.One / 4)) #assert SetExpr(Interval(0, oo))**(S.One/2) == SetExpr(Interval(0, oo)) #assert SetExpr(Interval(-oo, -1))**(S.One/3) == SetExpr(Interval(-oo, -1)) #assert SetExpr(Interval(-2, 3))**(-S.One/3) == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-oo, 0))**(-2) == SetExpr(Interval.open(0, oo)) assert SetExpr(Interval(-2, 0))**(-2) == SetExpr(Interval(S.One / 4, oo)) assert SetExpr(Interval(S.One / 3, S.One / 2))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(0, S.One / 2))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(S.One / 2, 1))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(0, 1))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(2, 3))**oo == SetExpr(FiniteSet(oo)) assert SetExpr(Interval(1, 2))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(S.One / 2, 3))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(-S.One / 3, -S.One / 4))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(-1, -S.One / 2))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-3, -2))**oo == SetExpr(FiniteSet(-oo, oo)) assert SetExpr(Interval(-2, -1))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-2, -S.One / 2))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-S.One / 2, S.One / 2))**oo == SetExpr(FiniteSet(0)) assert SetExpr(Interval(-S.One / 2, 1))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(-S(2) / 3, 2))**oo == SetExpr(Interval(0, oo)) assert SetExpr(Interval(-1, 1))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-1, S.One / 2))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-1, 2))**oo == SetExpr(Interval(-oo, oo)) assert SetExpr(Interval(-2, S.One / 2))**oo == SetExpr(Interval(-oo, oo)) assert (SetExpr(Interval(1, 2))**x).dummy_eq( SetExpr(ImageSet(Lambda(_d, _d**x), Interval(1, 2)))) assert SetExpr(Interval(2, 3))**(-oo) == SetExpr(FiniteSet(0)) assert SetExpr(Interval(0, 2))**(-oo) == SetExpr(Interval(0, oo)) assert (SetExpr(Interval(-1, 2))**(-oo)).dummy_eq( SetExpr(ImageSet(Lambda(_d, _d**(-oo)), Interval(-1, 2))))