def test_periodicity_check(): x = Symbol('x') y = Symbol('y') assert periodicity(tan(x), x, check=True) == pi assert periodicity(sin(x) + cos(x), x, check=True) == 2 * pi raises(NotImplementedError, lambda: periodicity(sec(x), x, check=True)) raises(NotImplementedError, lambda: periodicity(sin(x * y), x, check=True))
def test_periodicity_check(): x = Symbol('x') y = Symbol('y') assert periodicity(tan(x), x, check=True) == pi assert periodicity(sin(x) + cos(x), x, check=True) == 2*pi raises(NotImplementedError, lambda: periodicity(sec(x), x, check=True)) raises(NotImplementedError, lambda: periodicity(sin(x*y), x, check=True))
def test_periodicity_check(): x = Symbol('x') y = Symbol('y') assert periodicity(tan(x), x, check=True) == pi assert periodicity(sin(x) + cos(x), x, check=True) == 2*pi assert periodicity(sec(x), x) == 2*pi assert periodicity(sin(x*y), x) == 2*pi/abs(y) assert periodicity(Abs(sec(sec(x))), x) == 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 `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_issue_18747(): assert periodicity(exp(pi*I*(x/4+S.Half/2)), x) == 8
def test_periodicity(): x = Symbol('x') y = Symbol('y') z = Symbol('z', real=True) assert periodicity(sin(2*x), x) == pi assert periodicity((-2)*tan(4*x), x) == pi/4 assert periodicity(sin(x)**2, x) == 2*pi assert periodicity(3**tan(3*x), x) == pi/3 assert periodicity(tan(x)*cos(x), x) == 2*pi assert periodicity(sin(x)**(tan(x)), x) == 2*pi assert periodicity(tan(x)*sec(x), x) == 2*pi assert periodicity(sin(2*x)*cos(2*x) - y, x) == pi/2 assert periodicity(tan(x) + cot(x), x) == pi assert periodicity(sin(x) - cos(2*x), x) == 2*pi assert periodicity(sin(x) - 1, x) == 2*pi assert periodicity(sin(4*x) + sin(x)*cos(x), x) == pi assert periodicity(exp(sin(x)), x) == 2*pi assert periodicity(log(cot(2*x)) - sin(cos(2*x)), x) == pi assert periodicity(sin(2*x)*exp(tan(x) - csc(2*x)), x) == pi assert periodicity(cos(sec(x) - csc(2*x)), x) == 2*pi assert periodicity(tan(sin(2*x)), x) == pi assert periodicity(2*tan(x)**2, x) == pi assert periodicity(sin(x%4), x) == 4 assert periodicity(sin(x)%4, x) == 2*pi assert periodicity(tan((3*x-2)%4), x) == Rational(4, 3) assert periodicity((sqrt(2)*(x+1)+x) % 3, x) == 3 / (sqrt(2)+1) assert periodicity((x**2+1) % x, x) is None assert periodicity(sin(re(x)), x) == 2*pi assert periodicity(sin(x)**2 + cos(x)**2, x) is S.Zero assert periodicity(tan(x), y) is S.Zero assert periodicity(sin(x) + I*cos(x), x) == 2*pi assert periodicity(x - sin(2*y), y) == pi assert periodicity(exp(x), x) is None assert periodicity(exp(I*x), x) == 2*pi assert periodicity(exp(I*z), z) == 2*pi assert periodicity(exp(z), z) is None assert periodicity(exp(log(sin(z) + I*cos(2*z)), evaluate=False), z) == 2*pi assert periodicity(exp(log(sin(2*z) + I*cos(z)), evaluate=False), z) == 2*pi assert periodicity(exp(sin(z)), z) == 2*pi assert periodicity(exp(2*I*z), z) == pi assert periodicity(exp(z + I*sin(z)), z) is None assert periodicity(exp(cos(z/2) + sin(z)), z) == 4*pi assert periodicity(log(x), x) is None assert periodicity(exp(x)**sin(x), x) is None assert periodicity(sin(x)**y, y) is None assert periodicity(Abs(sin(Abs(sin(x)))), x) == pi assert all(periodicity(Abs(f(x)), x) == pi for f in ( cos, sin, sec, csc, tan, cot)) assert periodicity(Abs(sin(tan(x))), x) == pi assert periodicity(Abs(sin(sin(x) + tan(x))), x) == 2*pi assert periodicity(sin(x) > S.Half, x) == 2*pi assert periodicity(x > 2, x) is None assert periodicity(x**3 - x**2 + 1, x) is None assert periodicity(Abs(x), x) is None assert periodicity(Abs(x**2 - 1), x) is None assert periodicity((x**2 + 4)%2, x) is None assert periodicity((E**x)%3, x) is None assert periodicity(sin(expint(1, x))/expint(1, x), x) is None
def test_periodicity(): x = Symbol('x') y = Symbol('y') assert periodicity(sin(2 * x), x) == pi assert periodicity((-2) * tan(4 * x), x) == pi / 4 assert periodicity(sin(x)**2, x) == 2 * pi assert periodicity(3**tan(3 * x), x) == pi / 3 assert periodicity(tan(x) * cos(x), x) == 2 * pi assert periodicity(sin(x)**(tan(x)), x) == 2 * pi assert periodicity(tan(x) * sec(x), x) == 2 * pi assert periodicity(sin(2 * x) * cos(2 * x) - y, x) == pi / 2 assert periodicity(tan(x) + cot(x), x) == pi assert periodicity(sin(x) - cos(2 * x), x) == 2 * pi assert periodicity(sin(x) - 1, x) == 2 * pi assert periodicity(sin(4 * x) + sin(x) * cos(x), x) == pi assert periodicity(exp(sin(x)), x) == 2 * pi assert periodicity(log(cot(2 * x)) - sin(cos(2 * x)), x) == pi assert periodicity(sin(2 * x) * exp(tan(x) - csc(2 * x)), x) == pi assert periodicity(cos(sec(x) - csc(2 * x)), x) == 2 * pi assert periodicity(tan(sin(2 * x)), x) == pi assert periodicity(2 * tan(x)**2, x) == pi assert periodicity(sin(x % 4), x) == 4 assert periodicity(sin(x) % 4, x) == 2 * pi assert periodicity(tan((3 * x - 2) % 4), x) == 4 / 3 assert periodicity((sqrt(2) * (x + 1) + x) % 3, x) == 3 / (sqrt(2) + 1) assert periodicity((x**2 + 1) % x, x) == None assert periodicity(sin(x)**2 + cos(x)**2, x) == S.Zero assert periodicity(tan(x), y) == S.Zero assert periodicity(exp(x), x) is None assert periodicity(log(x), x) is None assert periodicity(exp(x)**sin(x), x) is None assert periodicity(sin(x)**y, y) is None assert periodicity(Abs(sin(Abs(sin(x)))), x) == pi assert all( periodicity(Abs(f(x)), x) == pi for f in (cos, sin, sec, csc, tan, cot)) assert periodicity(Abs(sin(tan(x))), x) == pi assert periodicity(Abs(sin(sin(x) + tan(x))), x) == 2 * pi assert periodicity(sin(x) > S.Half, x) is 2 * pi assert periodicity(x > 2, x) is None assert periodicity(x**3 - x**2 + 1, x) is None assert periodicity(Abs(x), x) is None assert periodicity(Abs(x**2 - 1), x) is None assert periodicity((x**2 + 4) % 2, x) is None assert periodicity((E**x) % 3, x) is None
def test_periodicity(): x = Symbol('x') y = Symbol('y') assert periodicity(sin(2*x), x) == pi assert periodicity((-2)*tan(4*x), x) == pi/4 assert periodicity(sin(x)**2, x) == 2*pi assert periodicity(3**tan(3*x), x) == pi/3 assert periodicity(tan(x)*cos(x), x) == 2*pi assert periodicity(sin(x)**(tan(x)), x) == 2*pi assert periodicity(tan(x)*sec(x), x) == 2*pi assert periodicity(sin(2*x)*cos(2*x) - y, x) == pi/2 assert periodicity(tan(x) + cot(x), x) == pi assert periodicity(sin(x) - cos(2*x), x) == 2*pi assert periodicity(sin(x) - 1, x) == 2*pi assert periodicity(sin(4*x) + sin(x)*cos(x), x) == pi assert periodicity(exp(sin(x)), x) == 2*pi assert periodicity(log(cot(2*x)) - sin(cos(2*x)), x) == pi assert periodicity(sin(2*x)*exp(tan(x) - csc(2*x)), x) == pi assert periodicity(cos(sec(x) - csc(2*x)), x) == 2*pi assert periodicity(tan(sin(2*x)), x) == pi assert periodicity(2*tan(x)**2, x) == pi assert periodicity(sin(x%4), x) == 4 assert periodicity(sin(x)%4, x) == 2*pi assert periodicity(tan((3*x-2)%4), x) == 4/3 assert periodicity((sqrt(2)*(x+1)+x) % 3, x) == 3 / (sqrt(2)+1) assert periodicity((x**2+1) % x, x) == None assert periodicity(sin(x)**2 + cos(x)**2, x) == S.Zero assert periodicity(tan(x), y) == S.Zero assert periodicity(exp(x), x) is None assert periodicity(log(x), x) is None assert periodicity(exp(x)**sin(x), x) is None assert periodicity(sin(x)**y, y) is None assert periodicity(Abs(sin(Abs(sin(x)))),x) == pi assert all(periodicity(Abs(f(x)),x) == pi for f in ( cos, sin, sec, csc, tan, cot)) assert periodicity(Abs(sin(tan(x))), x) == pi assert periodicity(Abs(sin(sin(x) + tan(x))), x) == 2*pi assert periodicity(sin(x) > S.Half, x) is 2*pi assert periodicity(x > 2, x) is None assert periodicity(x**3 - x**2 + 1, x) is None assert periodicity(Abs(x), x) is None assert periodicity(Abs(x**2 - 1), x) is None assert periodicity((x**2 + 4)%2, x) is None assert periodicity((E**x)%3, x) is None
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 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) (-oo, -2] U [2, oo) >>> domain = Interval(0, S.Infinity) >>> solve_univariate_inequality(x**2 >= 4, x, False, domain) [2, oo) >>> solve_univariate_inequality(sin(x) > 0, x, relational=False) (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: singularities = [] for d in denoms(e): singularities.extend(solvify(d, gen, domain)) if not continuous: domain = continuous_domain(e, gen, domain) solns = solvify(e, gen, domain) if solns is None: raise NotImplementedError( filldedent('''The inequality cannot be solved using solve_univariate_inequality.''')) 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 start = domain.inf sol_sets = [S.EmptySet] try: discontinuities = domain.boundary - FiniteSet( domain.inf, domain.sup) critical_points = set(solns + singularities + list(discontinuities)) reals = _nsort(critical_points, separated=True)[0] except NotImplementedError: raise NotImplementedError( 'sorting of these roots is not supported') if valid(start) and start.is_finite: sol_sets.append(FiniteSet(start)) for x in reals: end = x if end in [S.NegativeInfinity, S.Infinity]: if valid(S(0)): sol_sets.append(Interval(start, S.Infinity, True, True)) break pt = ((start + end) / 2 if start is not S.NegativeInfinity else (end / 2 if end.is_positive else (2 * end if end.is_negative else end - 1))) if valid(pt): sol_sets.append(Interval(start, end, True, True)) if x in singularities: singularities.remove(x) elif include_x: sol_sets.append(FiniteSet(x)) start = end end = domain.sup # in case start == -oo then there were no solutions so we just # check a point between -oo and oo (e.g. 0) else pick a point # past the last solution (which is start after the end of the # for-loop above pt = (0 if start is S.NegativeInfinity else (start / 2 if start.is_negative else (2 * start if start.is_positive else start + 1))) if pt >= end: pt = (start + end) / 2 if valid(pt): sol_sets.append(Interval(start, end, True, True)) rv = Union(*sol_sets).subs(gen, _gen) return rv if not relational else rv.as_relational(_gen)
def test_periodicity(): x = Symbol('x') y = Symbol('y') assert periodicity(sin(2*x), x) == pi assert periodicity((-2)*tan(4*x), x) == pi/4 assert periodicity(sin(x)**2, x) == 2*pi assert periodicity(3**tan(3*x), x) == pi/3 assert periodicity(tan(x)*cos(x), x) == 2*pi assert periodicity(sin(x)**(tan(x)), x) == 2*pi assert periodicity(tan(x)*sec(x), x) == 2*pi assert periodicity(sin(2*x)*cos(2*x) - y, x) == pi/2 assert periodicity(tan(x) + cot(x), x) == pi assert periodicity(sin(x) - cos(2*x), x) == 2*pi assert periodicity(sin(x) - 1, x) == 2*pi assert periodicity(sin(4*x) + sin(x)*cos(x), x) == pi assert periodicity(exp(sin(x)), x) == 2*pi assert periodicity(log(cot(2*x)) - sin(cos(2*x)), x) == pi assert periodicity(sin(2*x)*exp(tan(x) - csc(2*x)), x) == pi assert periodicity(cos(sec(x) - csc(2*x)), x) == 2*pi assert periodicity(tan(sin(2*x)), x) == pi assert periodicity(2*tan(x)**2, x) == pi assert periodicity(sin(x)**2 + cos(x)**2, x) == S.Zero assert periodicity(tan(x), y) == S.Zero assert periodicity(exp(x), x) is None assert periodicity(log(x), x) is None assert periodicity(exp(x)**sin(x), x) is None assert periodicity(sin(x)**y, y) is None
def test_periodicity(): x = Symbol('x') y = Symbol('y') z = Symbol('z', real=True) assert periodicity(sin(2*x), x) == pi assert periodicity((-2)*tan(4*x), x) == pi/4 assert periodicity(sin(x)**2, x) == 2*pi assert periodicity(3**tan(3*x), x) == pi/3 assert periodicity(tan(x)*cos(x), x) == 2*pi assert periodicity(sin(x)**(tan(x)), x) == 2*pi assert periodicity(tan(x)*sec(x), x) == 2*pi assert periodicity(sin(2*x)*cos(2*x) - y, x) == pi/2 assert periodicity(tan(x) + cot(x), x) == pi assert periodicity(sin(x) - cos(2*x), x) == 2*pi assert periodicity(sin(x) - 1, x) == 2*pi assert periodicity(sin(4*x) + sin(x)*cos(x), x) == pi assert periodicity(exp(sin(x)), x) == 2*pi assert periodicity(log(cot(2*x)) - sin(cos(2*x)), x) == pi assert periodicity(sin(2*x)*exp(tan(x) - csc(2*x)), x) == pi assert periodicity(cos(sec(x) - csc(2*x)), x) == 2*pi assert periodicity(tan(sin(2*x)), x) == pi assert periodicity(2*tan(x)**2, x) == pi assert periodicity(sin(x%4), x) == 4 assert periodicity(sin(x)%4, x) == 2*pi assert periodicity(tan((3*x-2)%4), x) == S(4)/3 assert periodicity((sqrt(2)*(x+1)+x) % 3, x) == 3 / (sqrt(2)+1) assert periodicity((x**2+1) % x, x) == None assert periodicity(sin(re(x)), x) == 2*pi assert periodicity(sin(x)**2 + cos(x)**2, x) == S.Zero assert periodicity(tan(x), y) == S.Zero assert periodicity(sin(x) + I*cos(x), x) == 2*pi assert periodicity(x - sin(2*y), y) == pi assert periodicity(exp(x), x) is None assert periodicity(exp(I*x), x) == 2*pi assert periodicity(exp(I*z), z) == 2*pi assert periodicity(exp(z), z) is None assert periodicity(exp(log(sin(z) + I*cos(2*z)), evaluate=False), z) == 2*pi assert periodicity(exp(log(sin(2*z) + I*cos(z)), evaluate=False), z) == 2*pi assert periodicity(exp(sin(z)), z) == 2*pi assert periodicity(exp(2*I*z), z) == pi assert periodicity(exp(z + I*sin(z)), z) is None assert periodicity(exp(cos(z/2) + sin(z)), z) == 4*pi assert periodicity(log(x), x) is None assert periodicity(exp(x)**sin(x), x) is None assert periodicity(sin(x)**y, y) is None assert periodicity(Abs(sin(Abs(sin(x)))), x) == pi assert all(periodicity(Abs(f(x)), x) == pi for f in ( cos, sin, sec, csc, tan, cot)) assert periodicity(Abs(sin(tan(x))), x) == pi assert periodicity(Abs(sin(sin(x) + tan(x))), x) == 2*pi assert periodicity(sin(x) > S.Half, x) is 2*pi assert periodicity(x > 2, x) is None assert periodicity(x**3 - x**2 + 1, x) is None assert periodicity(Abs(x), x) is None assert periodicity(Abs(x**2 - 1), x) is None assert periodicity((x**2 + 4)%2, x) is None assert periodicity((E**x)%3, x) is None
def test_periodicity(): x = Symbol('x') y = Symbol('y') assert periodicity(sin(2 * x), x) == pi assert periodicity((-2) * tan(4 * x), x) == pi / 4 assert periodicity(sin(x)**2, x) == 2 * pi assert periodicity(3**tan(3 * x), x) == pi / 3 assert periodicity(tan(x) * cos(x), x) == 2 * pi assert periodicity(sin(x)**(tan(x)), x) == 2 * pi assert periodicity(tan(x) * sec(x), x) == 2 * pi assert periodicity(sin(2 * x) * cos(2 * x) - y, x) == pi / 2 assert periodicity(tan(x) + cot(x), x) == pi assert periodicity(sin(x) - cos(2 * x), x) == 2 * pi assert periodicity(sin(x) - 1, x) == 2 * pi assert periodicity(sin(4 * x) + sin(x) * cos(x), x) == pi assert periodicity(exp(sin(x)), x) == 2 * pi assert periodicity(log(cot(2 * x)) - sin(cos(2 * x)), x) == pi assert periodicity(sin(2 * x) * exp(tan(x) - csc(2 * x)), x) == pi assert periodicity(cos(sec(x) - csc(2 * x)), x) == 2 * pi assert periodicity(tan(sin(2 * x)), x) == pi assert periodicity(2 * tan(x)**2, x) == pi assert periodicity(sin(x)**2 + cos(x)**2, x) == S.Zero assert periodicity(tan(x), y) == S.Zero assert periodicity(exp(x), x) is None assert periodicity(log(x), x) is None assert periodicity(exp(x)**sin(x), x) is None assert periodicity(sin(x)**y, y) is None assert periodicity(x**3 - x**2 + 1, x) is None assert periodicity(Abs(x), x) is None assert periodicity(Abs(x**2 - 1), x) is None
def test_periodicity(): x = Symbol('x') y = Symbol('y') z = Symbol('z', real=True) assert periodicity(sin(2 * x), x) == pi assert periodicity((-2) * tan(4 * x), x) == pi / 4 assert periodicity(sin(x)**2, x) == 2 * pi assert periodicity(3**tan(3 * x), x) == pi / 3 assert periodicity(tan(x) * cos(x), x) == 2 * pi assert periodicity(sin(x)**(tan(x)), x) == 2 * pi assert periodicity(tan(x) * sec(x), x) == 2 * pi assert periodicity(sin(2 * x) * cos(2 * x) - y, x) == pi / 2 assert periodicity(tan(x) + cot(x), x) == pi assert periodicity(sin(x) - cos(2 * x), x) == 2 * pi assert periodicity(sin(x) - 1, x) == 2 * pi assert periodicity(sin(4 * x) + sin(x) * cos(x), x) == pi assert periodicity(exp(sin(x)), x) == 2 * pi assert periodicity(log(cot(2 * x)) - sin(cos(2 * x)), x) == pi assert periodicity(sin(2 * x) * exp(tan(x) - csc(2 * x)), x) == pi assert periodicity(cos(sec(x) - csc(2 * x)), x) == 2 * pi assert periodicity(tan(sin(2 * x)), x) == pi assert periodicity(2 * tan(x)**2, x) == pi assert periodicity(sin(x % 4), x) == 4 assert periodicity(sin(x) % 4, x) == 2 * pi assert periodicity(tan((3 * x - 2) % 4), x) == Rational(4, 3) assert periodicity((sqrt(2) * (x + 1) + x) % 3, x) == 3 / (sqrt(2) + 1) assert periodicity((x**2 + 1) % x, x) is None assert periodicity(sin(re(x)), x) == 2 * pi assert periodicity(sin(x)**2 + cos(x)**2, x) is S.Zero assert periodicity(tan(x), y) is S.Zero assert periodicity(sin(x) + I * cos(x), x) == 2 * pi assert periodicity(x - sin(2 * y), y) == pi assert periodicity(exp(x), x) is None assert periodicity(exp(I * x), x) == 2 * pi assert periodicity(exp(I * z), z) == 2 * pi assert periodicity(exp(z), z) is None assert periodicity(exp(log(sin(z) + I * cos(2 * z)), evaluate=False), z) == 2 * pi assert periodicity(exp(log(sin(2 * z) + I * cos(z)), evaluate=False), z) == 2 * pi assert periodicity(exp(sin(z)), z) == 2 * pi assert periodicity(exp(2 * I * z), z) == pi assert periodicity(exp(z + I * sin(z)), z) is None assert periodicity(exp(cos(z / 2) + sin(z)), z) == 4 * pi assert periodicity(log(x), x) is None assert periodicity(exp(x)**sin(x), x) is None assert periodicity(sin(x)**y, y) is None assert periodicity(Abs(sin(Abs(sin(x)))), x) == pi assert all( periodicity(Abs(f(x)), x) == pi for f in (cos, sin, sec, csc, tan, cot)) assert periodicity(Abs(sin(tan(x))), x) == pi assert periodicity(Abs(sin(sin(x) + tan(x))), x) == 2 * pi assert periodicity(sin(x) > S.Half, x) == 2 * pi assert periodicity(x > 2, x) is None assert periodicity(x**3 - x**2 + 1, x) is None assert periodicity(Abs(x), x) is None assert periodicity(Abs(x**2 - 1), x) is None assert periodicity((x**2 + 4) % 2, x) is None assert periodicity((E**x) % 3, x) is None assert periodicity(sin(expint(1, x)) / expint(1, x), x) is None # returning `None` for any Piecewise p = Piecewise((0, x < -1), (x**2, x <= 1), (log(x), True)) assert periodicity(p, x) is None m = MatrixSymbol('m', 3, 3) raises(NotImplementedError, lambda: periodicity(sin(m), m)) raises(NotImplementedError, lambda: periodicity(sin(m[0, 0]), m)) raises(NotImplementedError, lambda: periodicity(sin(m), m[0, 0])) raises(NotImplementedError, lambda: periodicity(sin(m[0, 0]), m[0, 0]))
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) (-oo, -2] U [2, oo) >>> domain = Interval(0, S.Infinity) >>> solve_univariate_inequality(x**2 >= 4, x, False, domain) [2, oo) >>> solve_univariate_inequality(sin(x) > 0, x, relational=False) (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: singularities = [] for d in denoms(e): singularities.extend(solvify(d, gen, domain)) if not continuous: domain = continuous_domain(e, gen, domain) solns = solvify(e, gen, domain) if solns is None: raise NotImplementedError(filldedent('''The inequality cannot be solved using solve_univariate_inequality.''')) 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 start = domain.inf sol_sets = [S.EmptySet] try: discontinuities = domain.boundary - FiniteSet(domain.inf, domain.sup) critical_points = set(solns + singularities + list(discontinuities)) reals = _nsort(critical_points, separated=True)[0] except NotImplementedError: raise NotImplementedError('sorting of these roots is not supported') if valid(start) and start.is_finite: sol_sets.append(FiniteSet(start)) for x in reals: end = x if end in [S.NegativeInfinity, S.Infinity]: if valid(S(0)): sol_sets.append(Interval(start, S.Infinity, True, True)) break pt = ((start + end)/2 if start is not S.NegativeInfinity else (end/2 if end.is_positive else (2*end if end.is_negative else end - 1))) if valid(pt): sol_sets.append(Interval(start, end, True, True)) if x in singularities: singularities.remove(x) elif include_x: sol_sets.append(FiniteSet(x)) start = end end = domain.sup # in case start == -oo then there were no solutions so we just # check a point between -oo and oo (e.g. 0) else pick a point # past the last solution (which is start after the end of the # for-loop above pt = (0 if start is S.NegativeInfinity else (start/2 if start.is_negative else (2*start if start.is_positive else start + 1))) if pt >= end: pt = (start + end)/2 if valid(pt): sol_sets.append(Interval(start, end, True, True)) rv = Union(*sol_sets).subs(gen, _gen) return rv if not relational else rv.as_relational(_gen)