def test_stationary_points(): x, y = symbols("x y") assert stationary_points(sin(x), x, Interval(-pi / 2, pi / 2)) == {-pi / 2, pi / 2} assert stationary_points(sin(x), x, Interval.Ropen(0, pi / 4)) == EmptySet() assert stationary_points( tan(x), x, ) == EmptySet() assert stationary_points(sin(x) * cos(x), x, Interval(0, pi)) == { pi / 4, pi * Rational(3, 4), } assert stationary_points(sec(x), x, Interval(0, pi)) == {0, pi} assert stationary_points((x + 3) * (x - 2), x) == FiniteSet(Rational(-1, 2)) assert stationary_points((x + 3) / (x - 2), x, Interval(-5, 5)) == EmptySet() assert stationary_points((x**2 + 3) / (x - 2), x) == {2 - sqrt(7), 2 + sqrt(7)} assert stationary_points((x**2 + 3) / (x - 2), x, Interval(0, 5)) == {2 + sqrt(7)} assert stationary_points(x**4 + x**3 - 5 * x**2, x, S.Reals) == FiniteSet(-2, 0, Rational(5, 4)) assert stationary_points(exp(x), x) == EmptySet() assert stationary_points(log(x) - x, x, S.Reals) == {1} assert stationary_points(cos(x), x, Union(Interval(0, 5), Interval(-6, -3))) == { 0, -pi, pi, } assert stationary_points(y, x, S.Reals) == S.Reals assert stationary_points(y, x, S.EmptySet) == S.EmptySet
def test_normalize_theta_set(): # Interval 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(0, 2*pi, False, True) assert normalize_theta_set(Interval(-pi/2, pi/2)) == \ Union(Interval(0, pi/2), Interval(3*pi/2, 2*pi, False, True)) assert normalize_theta_set(Interval(-4*pi, 3*pi)) == \ Interval(0, 2*pi, False, True) assert normalize_theta_set(Interval(-3*pi/2, -pi/2)) == \ Interval(pi/2, 3*pi/2) # 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) # ValueError for non-real sets raises(ValueError, lambda: normalize_theta_set(S.Complexes))
def test_ComplexRegion_contains(): # contains in ComplexRegion a = Interval(2, 3) b = Interval(4, 6) c = Interval(7, 9) c1 = ComplexRegion(a * b) c2 = ComplexRegion(Union(a * b, c * a)) assert 2.5 + 4.5 * I in c1 assert 2 + 4 * I in c1 assert 3 + 4 * I in c1 assert 8 + 2.5 * I in c2 assert 2.5 + 6.1 * I not in c1 assert 4.5 + 3.2 * I not in c1 r1 = Interval(0, 1) theta1 = Interval(0, 2 * S.Pi) c3 = ComplexRegion(r1 * theta1, polar=True) assert 0.5 + 0.6 * I in c3 assert I in c3 assert 1 in c3 assert 0 in c3 assert 1 + I not in c3 assert 1 - I not in c3
def test_ComplexRegion_union(): # Polar form c1 = ComplexRegion(Interval(0, 1) * Interval(0, 2 * S.Pi), polar=True) c2 = ComplexRegion(Interval(0, 1) * Interval(0, S.Pi), polar=True) c3 = ComplexRegion(Interval(0, oo) * Interval(0, S.Pi), polar=True) c4 = ComplexRegion(Interval(0, oo) * Interval(S.Pi, 2 * S.Pi), polar=True) p1 = Union( Interval(0, 1) * Interval(0, 2 * S.Pi), Interval(0, 1) * Interval(0, S.Pi)) p2 = Union( Interval(0, oo) * Interval(0, S.Pi), Interval(0, oo) * Interval(S.Pi, 2 * S.Pi)) assert c1.union(c2) == ComplexRegion(p1, polar=True) assert c3.union(c4) == ComplexRegion(p2, polar=True) # Rectangular form c5 = ComplexRegion(Interval(2, 5) * Interval(6, 9)) c6 = ComplexRegion(Interval(4, 6) * Interval(10, 12)) c7 = ComplexRegion(Interval(0, 10) * Interval(-10, 0)) c8 = ComplexRegion(Interval(12, 16) * Interval(14, 20)) p3 = Union( Interval(2, 5) * Interval(6, 9), Interval(4, 6) * Interval(10, 12)) p4 = Union( Interval(0, 10) * Interval(-10, 0), Interval(12, 16) * Interval(14, 20)) assert c5.union(c6) == ComplexRegion(p3) assert c7.union(c8) == ComplexRegion(p4) assert c1.union(Interval(2, 4)) == Union(c1, Interval(2, 4), evaluate=False) assert c5.union(Interval(2, 4)) == Union(c5, Interval(2, 4), evaluate=False)
def test_not_empty_in(): from sympy.abc import x a = Symbol('a', real=True) assert not_empty_in(FiniteSet(x, 2*x).intersect(Interval(1, 2, True, False)), x) == \ Interval(S(1)/2, 2, True, False) assert not_empty_in(FiniteSet(x, x**2).intersect(Interval(1, 2)), x) == \ Union(Interval(-sqrt(2), -1), Interval(1, 2)) assert not_empty_in(FiniteSet(x**2 + x, x).intersect(Interval(2, 4)), x) == \ Union(Interval(-sqrt(17)/2 - S(1)/2, -2), Interval(1, -S(1)/2 + sqrt(17)/2), Interval(2, 4)) assert not_empty_in(FiniteSet(x/(x - 1)).intersect(S.Reals), x) == Complement(S.Reals, FiniteSet(1)) assert not_empty_in(FiniteSet(a/(a - 1)).intersect(S.Reals), a) == Complement(S.Reals, FiniteSet(1)) assert not_empty_in(FiniteSet((x**2 - 3*x + 2)/(x - 1)).intersect(S.Reals), x) == \ Complement(S.Reals, FiniteSet(1)) assert not_empty_in(FiniteSet(3, 4, x/(x - 1)).intersect(Interval(2, 3)), x) == \ Union(Interval(S(3)/2, 2), FiniteSet(3)) assert not_empty_in(FiniteSet(x/(x**2 - 1)).intersect(S.Reals), x) == \ Complement(S.Reals, FiniteSet(-1, 1)) assert not_empty_in(FiniteSet(x, x**2).intersect(Union(Interval(1, 3, True, True), Interval(4, 5))), x) == \ Union(Interval(-sqrt(5), -2), Interval(-sqrt(3), -1, True, True), Interval(1, 3, True, True), Interval(4, 5)) assert not_empty_in(FiniteSet(1).intersect(Interval(3, 4)), x) == S.EmptySet assert not_empty_in(FiniteSet(x**2/(x + 2)).intersect(Interval(1, oo)), x) == \ Union(Interval(-2, -1, True, False), Interval(2, oo))
def normalize_theta_set(theta): """ Normalize a Real Set theta in the Interval [0, 2*pi). It currently supports Interval and FiniteSet. It Returns a the normalized value of theta in the Set. For Interval, a maximum of one cycle [0, 2*pi], is returned i.e. for theta equal to [0, 10*pi], returned normalized value would be [0, 2*pi). As of now it supports theta as FiniteSet and Interval. Raises ====== NotImplementedError The algorithms for Normalizing theta Set are not yet implemented. ValueError The input is not valid, i.e. the input is not a real set. RuntimeError It is a bug, please report to the github issue tracker. Examples ======== >>> from sympy.sets.fancysets import normalize_theta_set >>> from sympy import Interval, FiniteSet, pi >>> normalize_theta_set(Interval(9*pi/2, 5*pi)) [pi/2, pi] >>> normalize_theta_set(Interval(-3*pi/2, pi/2)) [0, 2*pi) >>> normalize_theta_set(Interval(-pi/2, pi/2)) [0, pi/2] U [3*pi/2, 2*pi) >>> normalize_theta_set(Interval(-4*pi, 3*pi)) [0, 2*pi) >>> normalize_theta_set(Interval(-3*pi/2, -pi/2)) [pi/2, 3*pi/2] >>> normalize_theta_set(FiniteSet(0, pi, 3*pi)) {0, pi} """ from sympy.functions.elementary.trigonometric import _pi_coeff as coeff from sympy.functions.elementary.complexes import Abs if theta.is_Interval: # one complete circle if Abs(theta.args[0] - theta.args[1]) >= 2 * S.Pi: return Interval(0, 2 * S.Pi, False, True) new_theta = [] for val in [theta.args[0], theta.args[1]]: k = coeff(val) if (not k) and (k != S.Zero): raise NotImplementedError('Normalizing theta without pi as' 'coefficient, is not Implemented.') elif k == S.Zero: if val == S.Zero: new_theta.append(S.Zero) else: # when theta is n*pi new_theta.append(2 * S.Pi) else: new_theta.append(k * S.Pi) # for negative theta if new_theta[0] > new_theta[1]: return Union(Interval(S(0), new_theta[1]), Interval(new_theta[0], 2 * S.Pi, False, True)) else: return Interval(*new_theta) elif theta.is_FiniteSet: new_theta = [] for element in theta: k = coeff(element) if (not k) and (k != S.Zero): raise NotImplementedError('Normalizing theta without pi as' 'coefficient, is not Implemented.') elif k == S.Zero: if element == S.Zero: new_theta.append(S.Zero) else: new_theta.append(k * S.Pi) return FiniteSet(*new_theta) elif theta.is_subset(S.Reals): raise NotImplementedError("Normalizing theta when, its %s is not" "Implemented" % type(theta)) else: raise ValueError(" %s is not a real set" % (theta))
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 test_NZQRC_unions(): # check that all trivial number set unions are simplified: nbrsets = (S.Naturals, S.Naturals0, S.Integers, S.Rationals, S.Reals, S.Complexes) unions = (Union(a, b) for a in nbrsets for b in nbrsets) assert all(u.is_Union is False for u in unions)
def solve_univariate_inequality(expr, gen, relational=True): """Solves a real univariate inequality. Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy.core.symbol import Symbol >>> x = Symbol('x', real=True) >>> solve_univariate_inequality(x**2 >= 4, x) Or(And(-oo < x, x <= -2), And(2 <= x, x < oo)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) (-oo, -2] U [2, oo) """ from sympy.solvers.solvers import solve, denoms e = expr.lhs - expr.rhs parts = n, d = e.as_numer_denom() if all(i.is_polynomial(gen) for i in parts): solns = solve(n, gen, check=False) singularities = solve(d, gen, check=False) else: solns = solve(e, gen, check=False) singularities = [] for d in denoms(e): singularities.extend(solve(d, gen)) 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 = S.NegativeInfinity sol_sets = [S.EmptySet] try: reals = _nsort(set(solns + singularities), separated=True)[0] except NotImplementedError: raise NotImplementedError('sorting of these roots is not supported') 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 if valid((start + end)/2 if start != S.NegativeInfinity else end - 1): 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 = S.Infinity if valid(start + 1): sol_sets.append(Interval(start, end, True, True)) rv = Union(*sol_sets) return rv if not relational else rv.as_relational(gen)
def reduce_rational_inequalities(exprs, gen, relational=True): """Reduce a system of rational inequalities with rational coefficients. Examples ======== >>> from sympy import Poly, Symbol >>> from sympy.solvers.inequalities import reduce_rational_inequalities >>> x = Symbol('x', real=True) >>> reduce_rational_inequalities([[x**2 <= 0]], x) Eq(x, 0) >>> reduce_rational_inequalities([[x + 2 > 0]], x) And(-2 < x, x < oo) >>> reduce_rational_inequalities([[(x + 2, ">")]], x) And(-2 < x, x < oo) >>> reduce_rational_inequalities([[x + 2]], x) Eq(x, -2) """ exact = True eqs = [] solution = S.EmptySet for _exprs in exprs: _eqs = [] for expr in _exprs: if isinstance(expr, tuple): expr, rel = expr else: if expr.is_Relational: expr, rel = expr.lhs - expr.rhs, expr.rel_op else: expr, rel = expr, '==' if expr is S.true: numer, denom, rel = S.Zero, S.One, '==' elif expr is S.false: numer, denom, rel = S.One, S.One, '==' else: numer, denom = expr.together().as_numer_denom() try: (numer, denom), opt = parallel_poly_from_expr( (numer, denom), gen) except PolynomialError: raise PolynomialError(filldedent(''' only polynomials and rational functions are supported in this context''')) if not opt.domain.is_Exact: numer, denom, exact = numer.to_exact(), denom.to_exact(), False domain = opt.domain.get_exact() if not (domain.is_ZZ or domain.is_QQ): expr = numer/denom expr = Relational(expr, 0, rel) solution = Union(solution, solve_univariate_inequality(expr, gen, relational=False)) else: _eqs.append(((numer, denom), rel)) eqs.append(_eqs) solution = Union(solution, solve_rational_inequalities(eqs)) if not exact: solution = solution.evalf() if relational: solution = solution.as_relational(gen) return solution
def __new__(cls, *partition): """ Generates a new partition object. This method also verifies if the arguments passed are valid and raises a ValueError if they are not. Examples ======== Creating Partition from Python lists: >>> from sympy.combinatorics.partitions import Partition >>> a = Partition([1, 2], [3]) >>> a Partition({3}, {1, 2}) >>> a.partition [[1, 2], [3]] >>> len(a) 2 >>> a.members (1, 2, 3) Creating Partition from Python sets: >>> Partition({1, 2, 3}, {4, 5}) Partition({4, 5}, {1, 2, 3}) Creating Partition from SymPy finite sets: >>> from sympy.sets.sets import FiniteSet >>> a = FiniteSet(1, 2, 3) >>> b = FiniteSet(4, 5) >>> Partition(a, b) Partition({4, 5}, {1, 2, 3}) """ args = [] dups = False for arg in partition: if isinstance(arg, list): as_set = set(arg) if len(as_set) < len(arg): dups = True break # error below arg = as_set args.append(_sympify(arg)) if not all(isinstance(part, FiniteSet) for part in args): raise ValueError( "Each argument to Partition should be " \ "a list, set, or a FiniteSet") # sort so we have a canonical reference for RGS U = Union(*args) if dups or len(U) < sum(len(arg) for arg in args): raise ValueError("Partition contained duplicate elements.") obj = FiniteSet.__new__(cls, *args) obj.members = tuple(U) obj.size = len(U) return obj
def prove(Eq): k = Symbol.k(integer=True, positive=True) n = Symbol.n(integer=True, positive=True) Eq << apply(n, k) s2 = Eq[0].lhs s2_quote = Symbol.s_quote_2(definition=Eq[0].rhs.limits[0][1]) Eq << s2_quote.this.definition Eq.s2_definition = Eq[0].subs(Eq[-1].reversed) s0 = Eq[1].lhs s0_quote = Symbol.s_quote_0(definition=Eq[1].rhs.limits[0][1]) Eq << s0_quote.this.definition Eq << Eq[1].subs(Eq[-1].reversed) s0_definition = Eq[-1] e = Symbol.e(dtype=dtype.integer.set) s0_ = image_set(Union(e, {n.set}), e, s0) plausible0 = Subset(s0_, s2, plausible=True) Eq << plausible0 Eq << Eq[-1].definition Eq << Eq[-1].this.limits[0][1].subs(s0_definition) Eq << Eq[-1].subs(Eq.s2_definition) s0_plausible = Eq[-1] Eq.s2_quote_definition = s2_quote.assertion() Eq << s0_quote.assertion() Eq << Eq[-1].split() x_abs_positive = Eq[-3] x_abs_sum = Eq[-2] x_union_s0 = Eq[-1] i = Eq[-1].lhs.limits[0][0] x = Eq[-1].variable.base Eq << Equality.define(x[k], {n}) x_k_definition = Eq[-1] Eq << Eq[-1].union(Eq[-2]) x_union = Eq[-1] Eq << x_k_definition.set Eq << Eq[-1].union(x[:k].set_comprehension()) Eq << s0_plausible.subs(Eq[-1].reversed) Eq << Eq[-1].definition.definition Eq << x_k_definition.abs() Eq << Eq[-1].subs(StrictGreaterThan(1, 0, plausible=True)) Eq << x_abs_sum + Eq[-2] Eq << (x_abs_positive & Eq[-2]) Eq << (x_union & Eq[-1] & Eq[-2]) j = Symbol.j(domain=Interval(0, k, integer=True)) B = Eq[2].lhs Eq << plausible0.subs(Eq[2].reversed) Eq << s2.this.bisect(conditionset(e, Contains({n}, e), s2)) Eq.subset_B = Subset(Eq[-1].rhs.args[0], Eq[-2].lhs, plausible=True) # unproven Eq.supset_B = Supset(Eq[-1].rhs.args[0], Eq[-2].lhs, plausible=True) # unproven Eq << Eq.supset_B.subs(Eq[2]) Eq << Eq[-1].definition.definition Eq << Eq.subset_B.subs(Eq[2]) Eq << Eq[-1].definition.definition Eq.subset_B_definition = Eq[-1] - {n.set} num_plausibles = len(Eq.plausibles_dict) Eq.plausible_notcontains = ForAll(NotContains({n}, e), (e, s0), plausible=True) Eq << Eq.plausible_notcontains.this.limits[0][1].subs(s0_definition) Eq << ~Eq[-1] Eq << Eq[-1].definition Eq << x_union_s0.union(Eq[-1].reversed).this().function.lhs.simplify() Eq << Eq[-1].subs(x_union_s0) assert num_plausibles == len(Eq.plausibles_dict) Eq << Eq.plausible_notcontains.apply( sets.notcontains.imply.equality.emptyset) Eq.s0_complement_n = Eq[-1].apply( sets.equality.imply.equality.given.emptyset.complement) Eq << Eq.subset_B_definition.subs(Eq.s0_complement_n) s2_n = Symbol('s_{2, n}', definition=Eq[-1].limits[0][1]) Eq.s2_n_definition = s2_n.this.definition Eq << s2_n.assertion() Eq << Eq[-1].subs(Eq.s2_definition).split() Eq.s2_n_assertion = Eq[-2].definition Eq << Eq[-1].subs(Eq.s2_n_assertion) Eq << Eq[-1].definition Eq.x_j_definition = Eq[-1].limits_subs(Eq[-1].variable, j).reversed Eq.x_abs_positive_s2, Eq.x_abs_sum_s2, Eq.x_union_s2 = Eq.s2_quote_definition.split( ) Eq << Eq.x_union_s2 - Eq.x_j_definition Eq << Eq[-1].this.function.lhs.args[0].bisect({j}) x_tilde = Symbol(r"\tilde{x}", shape=(k, ), dtype=dtype.integer, definition=LAMBDA[i:k](Piecewise((x[i], i < j), (x[i + 1], True)))) Eq.x_tilde_definition = x_tilde.equality_defined() Eq << Eq.x_tilde_definition.union_comprehension((i, 0, k - 1)) Eq << Eq[-1].this.rhs.args[1].limits_subs(i, i - 1) Eq.x_tilde_union = Eq[-1].subs(Eq[-3]) Eq.x_tilde_abs = Eq.x_tilde_definition.abs() Eq << Eq.x_tilde_abs.sum((i, 0, k - 1)) Eq << Eq[-1].this.rhs.args[0].limits_subs(i, i - 1) Eq.x_tilde_abs_sum = Eq[-1].subs(Eq.x_abs_sum_s2, Eq.x_j_definition.abs()) Eq << Eq.x_tilde_abs.as_Or() Eq << Eq[-1].forall((i, i < j)) Eq << Eq[-2].forall((i, i >= j)) Eq << Eq[-2].subs(Eq.x_abs_positive_s2) Eq << Eq[-2].subs(Eq.x_abs_positive_s2.limits_subs(i, i + 1)) Eq << (Eq[-1] & Eq[-2]) Eq << (Eq[-1] & Eq.x_tilde_abs_sum & Eq.x_tilde_union) Eq << Eq[-1].func( Contains(x_tilde, s0_quote), *Eq[-1].limits, plausible=True) Eq << Eq[-1].definition Eq << Eq[-1].this.function.args[0].simplify() Eq.x_tilde_set_in_s0 = Eq[-3].func(Contains( UNION.construct_finite_set(x_tilde), s0), *Eq[-3].limits, plausible=True) Eq << Eq.x_tilde_set_in_s0.subs(s0_definition) Eq << Eq[-1].definition Eq << Eq.x_tilde_definition.set.union_comprehension((i, 0, k - 1)) Eq << Eq[-1].subs(Eq.x_j_definition) Eq << Eq[-1].subs(Eq.s2_n_assertion.reversed) Eq << Eq.x_tilde_set_in_s0.subs(Eq[-1]) Eq << Eq[-1].this.limits[0].subs(Eq.s2_n_definition) Eq.subset_B_plausible = Eq.subset_B_definition.union({n.set}) Eq << Eq.subset_B_plausible.limits_assertion() Eq << Eq[-1].definition.split()[1] Eq << Eq[-1].apply(sets.contains.imply.equality.union) Eq << Eq.subset_B_plausible.subs(Eq[-1]) Eq << Eq.supset_B.subs(Eq.subset_B)
def normalize_theta_set(theta): """ Normalize a Real Set `theta` in the Interval [0, 2*pi). It returns a normalized value of theta in the Set. For Interval, a maximum of one cycle [0, 2*pi], is returned i.e. for theta equal to [0, 10*pi], returned normalized value would be [0, 2*pi). As of now intervals with end points as non-multiples of `pi` is not supported. Raises ====== NotImplementedError The algorithms for Normalizing theta Set are not yet implemented. ValueError The input is not valid, i.e. the input is not a real set. RuntimeError It is a bug, please report to the github issue tracker. Examples ======== >>> from sympy.sets.fancysets import normalize_theta_set >>> from sympy import Interval, FiniteSet, pi >>> normalize_theta_set(Interval(9*pi/2, 5*pi)) [pi/2, pi] >>> normalize_theta_set(Interval(-3*pi/2, pi/2)) [0, 2*pi) >>> normalize_theta_set(Interval(-pi/2, pi/2)) [0, pi/2] U [3*pi/2, 2*pi) >>> normalize_theta_set(Interval(-4*pi, 3*pi)) [0, 2*pi) >>> normalize_theta_set(Interval(-3*pi/2, -pi/2)) [pi/2, 3*pi/2] >>> normalize_theta_set(FiniteSet(0, pi, 3*pi)) {0, pi} """ from sympy.functions.elementary.trigonometric import _pi_coeff as coeff if theta.is_Interval: interval_len = theta.measure # one complete circle if interval_len >= 2 * S.Pi: if interval_len == 2 * S.Pi and theta.left_open and theta.right_open: k = coeff(theta.start) return Union(Interval(0, k * S.Pi, False, True), Interval(k * S.Pi, 2 * S.Pi, True, True)) return Interval(0, 2 * S.Pi, False, True) k_start, k_end = coeff(theta.start), coeff(theta.end) if k_start is None or k_end is None: raise NotImplementedError( "Normalizing theta without pi as coefficient is " "not yet implemented") new_start = k_start * S.Pi new_end = k_end * S.Pi if new_start > new_end: return Union(Interval(S.Zero, new_end, False, theta.right_open), Interval(new_start, 2 * S.Pi, theta.left_open, True)) else: return Interval(new_start, new_end, theta.left_open, theta.right_open) elif theta.is_FiniteSet: new_theta = [] for element in theta: k = coeff(element) if k is None: raise NotImplementedError('Normalizing theta without pi as ' 'coefficient, is not Implemented.') else: new_theta.append(k * S.Pi) return FiniteSet(*new_theta) elif theta.is_Union: return Union( *[normalize_theta_set(interval) for interval in theta.args]) elif theta.is_subset(S.Reals): raise NotImplementedError( "Normalizing theta when, it is of type %s is not " "implemented" % type(theta)) else: raise ValueError(" %s is not a real set" % (theta))
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 solve_univariate_inequality(expr, gen, relational=True): """Solves a real univariate inequality. Examples ======== >>> from sympy.solvers.inequalities import solve_univariate_inequality >>> from sympy.core.symbol import Symbol >>> x = Symbol('x') >>> solve_univariate_inequality(x**2 >= 4, x) Or(And(-oo < x, x <= -2), And(2 <= x, x < oo)) >>> solve_univariate_inequality(x**2 >= 4, x, relational=False) (-oo, -2] U [2, oo) """ from sympy.solvers.solvers import solve, denoms # 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 if expr is S.true: rv = S.Reals elif expr is S.false: rv = S.EmptySet else: e = expr.lhs - expr.rhs parts = n, d = e.as_numer_denom() if all(i.is_polynomial(gen) for i in parts): solns = solve(n, gen, check=False) singularities = solve(d, gen, check=False) else: solns = solve(e, gen, check=False) singularities = [] for d in denoms(e): singularities.extend(solve(d, gen)) 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 = S.NegativeInfinity sol_sets = [S.EmptySet] try: reals = _nsort(set(solns + singularities), separated=True)[0] except NotImplementedError: raise NotImplementedError('sorting of these roots is not supported') 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 = S.Infinity # 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 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 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 apply(A, B): return LessThan(abs(Union(A, B)), abs(A) + abs(B))
def apply(A, B): return GreaterThan(abs(Union(A, B)), abs(A))
def test_reduce_poly_inequalities_real_interval(): assert reduce_rational_inequalities( [[Eq(x**2, 0)]], x, relational=False) == FiniteSet(0) assert reduce_rational_inequalities( [[Le(x**2, 0)]], x, relational=False) == FiniteSet(0) assert reduce_rational_inequalities( [[Lt(x**2, 0)]], x, relational=False) == S.EmptySet assert reduce_rational_inequalities( [[Ge(x**2, 0)]], x, relational=False) == \ S.Reals if x.is_real else Interval(-oo, oo) assert reduce_rational_inequalities( [[Gt(x**2, 0)]], x, relational=False) == \ FiniteSet(0).complement(S.Reals) assert reduce_rational_inequalities( [[Ne(x**2, 0)]], x, relational=False) == \ FiniteSet(0).complement(S.Reals) assert reduce_rational_inequalities( [[Eq(x**2, 1)]], x, relational=False) == FiniteSet(-1, 1) assert reduce_rational_inequalities( [[Le(x**2, 1)]], x, relational=False) == Interval(-1, 1) assert reduce_rational_inequalities( [[Lt(x**2, 1)]], x, relational=False) == Interval(-1, 1, True, True) assert reduce_rational_inequalities( [[Ge(x**2, 1)]], x, relational=False) == \ Union(Interval(-oo, -1), Interval(1, oo)) assert reduce_rational_inequalities( [[Gt(x**2, 1)]], x, relational=False) == \ Interval(-1, 1).complement(S.Reals) assert reduce_rational_inequalities( [[Ne(x**2, 1)]], x, relational=False) == \ FiniteSet(-1, 1).complement(S.Reals) assert reduce_rational_inequalities([[Eq( x**2, 1.0)]], x, relational=False) == FiniteSet(-1.0, 1.0).evalf() assert reduce_rational_inequalities( [[Le(x**2, 1.0)]], x, relational=False) == Interval(-1.0, 1.0) assert reduce_rational_inequalities([[Lt( x**2, 1.0)]], x, relational=False) == Interval(-1.0, 1.0, True, True) assert reduce_rational_inequalities( [[Ge(x**2, 1.0)]], x, relational=False) == \ Union(Interval(-inf, -1.0), Interval(1.0, inf)) assert reduce_rational_inequalities( [[Gt(x**2, 1.0)]], x, relational=False) == \ Union(Interval(-inf, -1.0, right_open=True), Interval(1.0, inf, left_open=True)) assert reduce_rational_inequalities([[Ne( x**2, 1.0)]], x, relational=False) == \ FiniteSet(-1.0, 1.0).complement(S.Reals) s = sqrt(2) assert reduce_rational_inequalities([[Lt( x**2 - 1, 0), Gt(x**2 - 1, 0)]], x, relational=False) == S.EmptySet assert reduce_rational_inequalities([[Le(x**2 - 1, 0), Ge( x**2 - 1, 0)]], x, relational=False) == FiniteSet(-1, 1) assert reduce_rational_inequalities( [[Le(x**2 - 2, 0), Ge(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, False, False), Interval(1, s, False, False)) assert reduce_rational_inequalities( [[Le(x**2 - 2, 0), Gt(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, False, True), Interval(1, s, True, False)) assert reduce_rational_inequalities( [[Lt(x**2 - 2, 0), Ge(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, True, False), Interval(1, s, False, True)) assert reduce_rational_inequalities( [[Lt(x**2 - 2, 0), Gt(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, True, True), Interval(1, s, True, True)) assert reduce_rational_inequalities( [[Lt(x**2 - 2, 0), Ne(x**2 - 1, 0)]], x, relational=False ) == Union(Interval(-s, -1, True, True), Interval(-1, 1, True, True), Interval(1, s, True, True)) assert reduce_rational_inequalities([[Lt(x**2, -1.)]], x) is S.false
def test_codomain(): x = Symbol('x', real=True) assert codomain(x, Interval(-1, 1), x) == Interval(-1, 1) assert codomain(x, Interval(0, 1, True, True), x) == \ Interval(0, 1, True, True) assert codomain(x, Interval(1, 2, True, False), x) == Interval(1, 2, True, False) assert codomain(x, Interval(1, 2, False, True), x) == Interval(1, 2, False, True) assert codomain(x**2, Interval(-1, 1), x) == Interval(0, 1) assert codomain(x**3, Interval(0, 1), x) == Interval(0, 1) assert codomain(x / (x**2 - 4), Interval(3, 4), x) == Interval(S(1) / 3, S(3) / 5) assert codomain(1, Interval(-1, 4), x) == FiniteSet(1) assert codomain(x, Interval(-oo, oo), x) == S.Reals assert codomain(1 / x**2, FiniteSet(1, 2, -1, 0), x) == FiniteSet(1, S(1) / 4) assert codomain(x, FiniteSet(1, -1, 3, 5), x) == FiniteSet(-1, 1, 3, 5) assert codomain(x**2 - x, FiniteSet(1, -1, 3, 5, -oo), x) == \ FiniteSet(0, 2, 6, 20, oo) assert codomain(x**2 / (x - 4), FiniteSet(4), x) == S.EmptySet assert codomain(x**2 - x, FiniteSet(S(1)/2, -oo, oo, 2), x) == \ FiniteSet(S(-1)/4, 2, oo) assert codomain(x**2, Interval(-1, 1, True, True), x) == Interval(0, 1, False, True) assert codomain(x**2, Interval(-1, 1, False, True), x) == Interval(0, 1) assert codomain(x**2, Interval(-1, 1, True, False), x) == Interval(0, 1) assert codomain(1 / x, Interval(0, 1), x) == Interval(1, oo) assert codomain(1 / x, Interval(-1, 1), x) == Union(Interval(-oo, -1), Interval(1, oo)) assert codomain(1 / x**2, Interval(-1, 1), x) == Interval(1, oo) assert codomain(1 / x**2, Interval(-1, 1, True, False), x) == Interval(1, oo) assert codomain(1/x**2, Interval(-1, 1, True, True), x) == \ Interval(1, oo, True, True) assert codomain(1 / x**2, Interval(-1, 1, False, True), x) == Interval(1, oo) assert codomain(1 / x, Interval(1, 2), x) == Interval(S(1) / 2, 1) assert codomain(1/x**2, Interval(-2, -1, True, True), x) == \ Interval(S(1)/4, 1, True, True) assert codomain(x**2/(x - 4), Interval(-oo, oo), x) == \ Complement(S.Reals, Interval(0, 16, True, True)) assert codomain(x**2 / (x - 4), Interval(3, 4), x) == Interval(-oo, -9) assert codomain(-x**2 / (x - 4), Interval(3, 4), x) == Interval(9, oo) assert codomain((x**2 - x) / (x**3 - 1), S.Reals, x) == Interval(-1, S(1) / 3, False, True) assert codomain(-x**2 + 1 / x, S.Reals, x) == S.Reals assert codomain(x**2 - 1 / x, S.Reals, x) == S.Reals assert codomain(x**2, Union(Interval(1, 2), FiniteSet(3)), x) == \ Union(Interval(1, 4), FiniteSet(9)) assert codomain(x / (x**2 - 4), Union(Interval(-oo, 1), Interval(0, oo)), x) == S.Reals assert codomain(x, Union(Interval(-1, 1), FiniteSet(-oo)), x) == \ Union(Interval(-1, 1), FiniteSet(-oo)) assert codomain(x**2 - x, Interval(1, oo), x) == Interval(0, oo)
def codomain(func, domain, *syms): """ Finds the range of a real-valued function, for a real-domain Parameters ========== func: Expr The expression whose range is to be found domain: Union of Sets The real-domain for the variable involved in function syms: Tuple of symbols Symbol whose domain is given Raises ====== NotImplementedError The algorithms to find the range of the given function are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report it to the github issue tracker (https://github.com/sympy/sympy/issues). Examples ======== >>> from sympy import Symbol, S, Interval, Union, FiniteSet, codomain >>> x = Symbol('x', real=True) >>> codomain(x**2, Interval(-1, 1), x) [0, 1] >>> codomain(x/(x**2 - 4), Union(Interval(-1, 3), FiniteSet(5)), x) (-oo, 1/3] U [3/5, oo) >>> codomain(x**2/(x**2 - 4), S.Reals, x) (-oo, 0] U (1, oo) """ func = sympify(func) if not isinstance(domain, Set): raise ValueError('A Set must be given, not %s: %s' % (type(domain), domain)) # TODO: handle piecewise defined functions # TODO: handle transcendental functions # TODO: handle multivariate functions if len(syms) == 0: raise ValueError("A Symbol or a tuple of symbols must be given") if len(syms) == 1: sym = syms[0] else: raise NotImplementedError("more than one variables %s not handled" % (syms, )) if not func.has(sym): return FiniteSet(func) # this block of code can be replaced by # sing = Intersection(FiniteSet(*sing), domain.closure) # after the issue #9706 has been fixed def closure_handle(set_im, singul): if set_im.has(Interval): if not oo in set_im.boundary: if not S.NegativeInfinity in set_im.boundary: return Intersection(FiniteSet(*singul), set_im.closure) return Intersection( FiniteSet(*singul), Union(set_im, FiniteSet(max(set_im.boundary)))) else: if not S.NegativeInfinity in set_im.boundary: return Intersection( FiniteSet(*singul), Union(set_im, FiniteSet(min(set_im.boundary)))) return Intersection(FiniteSet(*singul), set_im) return Intersection(FiniteSet(*singul), set_im) # all the singularities of the function sing = solveset(func.as_numer_denom()[1], sym, domain=S.Reals) sing_in_domain = closure_handle(domain, sing) domain = Complement(domain, sing_in_domain) if domain.is_EmptySet: return EmptySet() def codomain_interval(f, set_val, *sym): symb = sym[0] df1 = diff(f, symb) df2 = diff(df1, symb) der_zero = solveset(df1, symb, domain=S.Reals) der_zero_in_dom = closure_handle(set_val, der_zero) local_maxima = set() local_minima = set() start_val = limit(f, symb, set_val.start) end_val = limit(f, symb, set_val.end, '-') if start_val is S.Infinity or end_val is S.Infinity: local_maxima = set([(oo, True)]) elif start_val is S.NegativeInfinity or end_val is S.NegativeInfinity: local_minima = set([(-oo, True)]) if (not start_val.is_real) or (not end_val.is_real): raise ValueError('Function does not contain all points of %s ' 'as its domain' % (domain)) if local_maxima == set(): if start_val > end_val: local_maxima = set([(start_val, set_val.left_open)]) elif start_val < end_val: local_maxima = set([(end_val, set_val.right_open)]) else: local_maxima = set([(start_val, set_val.left_open and set_val.right_open)]) if local_minima == set(): if start_val < end_val: local_minima = set([(start_val, set_val.left_open)]) elif start_val > end_val: local_minima = set([(end_val, set_val.right_open)]) else: local_minima = set([(start_val, set_val.left_open and set_val.right_open)]) for i in der_zero_in_dom: exist = not i in set_val if df2.subs({symb: i}) < 0: local_maxima.add((f.subs({symb: i}), exist)) elif df2.subs({symb: i}) > 0: local_minima.add((f.subs({symb: i}), exist)) maximum = (-oo, True) minimum = (oo, True) for i in local_maxima: if i[0] > maximum[0]: maximum = i elif i[0] == maximum[0]: maximum = (maximum[0], i[1] and maximum[1]) for i in local_minima: if i[0] < minimum[0]: minimum = i elif i[0] == minimum[0]: minimum = (minimum[0], i[1] and minimum[1]) return Union(Interval(minimum[0], maximum[0], minimum[1], maximum[1])) if isinstance(domain, Union): return Union(*[ codomain(func, intrvl_or_finset, sym) for intrvl_or_finset in domain.args ]) if isinstance(domain, Interval): return codomain_interval(func, domain, sym) if isinstance(domain, FiniteSet): return FiniteSet(*[ limit(func, sym, i) if i in FiniteSet(-oo, oo) else func.subs({sym: i}) for i in domain ])
def not_empty_in(finset_intersection, *syms): """ Finds the domain of the functions in `finite_set` in which the `finite_set` is not-empty Parameters ========== finset_intersection: The unevaluated intersection of FiniteSet containing real-valued functions with Union of Sets syms: Tuple of symbols Symbol for which domain is to be found Raises ====== NotImplementedError The algorithms to find the non-emptiness of the given FiniteSet are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report it to the github issue tracker (https://github.com/sympy/sympy/issues). Examples ======== >>> from sympy import FiniteSet, Interval, not_empty_in, oo >>> from sympy.abc import x >>> not_empty_in(FiniteSet(x/2).intersect(Interval(0, 1)), x) Interval(0, 2) >>> not_empty_in(FiniteSet(x, x**2).intersect(Interval(1, 2)), x) Union(Interval(-sqrt(2), -1), Interval(1, 2)) >>> not_empty_in(FiniteSet(x**2/(x + 2)).intersect(Interval(1, oo)), x) Union(Interval(-2, -1, True), Interval(2, oo, False, True)) """ # TODO: handle piecewise defined functions # TODO: handle transcendental functions # TODO: handle multivariate functions if len(syms) == 0: raise ValueError("One or more symbols must be given in syms.") if finset_intersection.is_EmptySet: return EmptySet() if isinstance(finset_intersection, Union): elm_in_sets = finset_intersection.args[0] return Union(not_empty_in(finset_intersection.args[1], *syms), elm_in_sets) if isinstance(finset_intersection, FiniteSet): finite_set = finset_intersection _sets = S.Reals else: finite_set = finset_intersection.args[1] _sets = finset_intersection.args[0] if not isinstance(finite_set, FiniteSet): raise ValueError('A FiniteSet must be given, not %s: %s' % (type(finite_set), finite_set)) if len(syms) == 1: symb = syms[0] else: raise NotImplementedError('more than one variables %s not handled' % (syms,)) def elm_domain(expr, intrvl): """ Finds the domain of an expression in any given interval """ from sympy.solvers.solveset import solveset _start = intrvl.start _end = intrvl.end _singularities = solveset(expr.as_numer_denom()[1], symb, domain=S.Reals) if intrvl.right_open: if _end is S.Infinity: _domain1 = S.Reals else: _domain1 = solveset(expr < _end, symb, domain=S.Reals) else: _domain1 = solveset(expr <= _end, symb, domain=S.Reals) if intrvl.left_open: if _start is S.NegativeInfinity: _domain2 = S.Reals else: _domain2 = solveset(expr > _start, symb, domain=S.Reals) else: _domain2 = solveset(expr >= _start, symb, domain=S.Reals) # domain in the interval expr_with_sing = Intersection(_domain1, _domain2) expr_domain = Complement(expr_with_sing, _singularities) return expr_domain if isinstance(_sets, Interval): return Union(*[elm_domain(element, _sets) for element in finite_set]) if isinstance(_sets, Union): _domain = S.EmptySet for intrvl in _sets.args: _domain_element = Union(*[elm_domain(element, intrvl) for element in finite_set]) _domain = Union(_domain, _domain_element) return _domain
def codomain_interval(f, set_val, *sym): symb = sym[0] df1 = diff(f, symb) df2 = diff(df1, symb) der_zero = solveset(df1, symb, domain=S.Reals) der_zero_in_dom = closure_handle(set_val, der_zero) local_maxima = set() local_minima = set() start_val = limit(f, symb, set_val.start) end_val = limit(f, symb, set_val.end, '-') if start_val is S.Infinity or end_val is S.Infinity: local_maxima = set([(oo, True)]) elif start_val is S.NegativeInfinity or end_val is S.NegativeInfinity: local_minima = set([(-oo, True)]) if (not start_val.is_real) or (not end_val.is_real): raise ValueError('Function does not contain all points of %s ' 'as its domain' % (domain)) if local_maxima == set(): if start_val > end_val: local_maxima = set([(start_val, set_val.left_open)]) elif start_val < end_val: local_maxima = set([(end_val, set_val.right_open)]) else: local_maxima = set([(start_val, set_val.left_open and set_val.right_open)]) if local_minima == set(): if start_val < end_val: local_minima = set([(start_val, set_val.left_open)]) elif start_val > end_val: local_minima = set([(end_val, set_val.right_open)]) else: local_minima = set([(start_val, set_val.left_open and set_val.right_open)]) for i in der_zero_in_dom: exist = not i in set_val if df2.subs({symb: i}) < 0: local_maxima.add((f.subs({symb: i}), exist)) elif df2.subs({symb: i}) > 0: local_minima.add((f.subs({symb: i}), exist)) maximum = (-oo, True) minimum = (oo, True) for i in local_maxima: if i[0] > maximum[0]: maximum = i elif i[0] == maximum[0]: maximum = (maximum[0], i[1] and maximum[1]) for i in local_minima: if i[0] < minimum[0]: minimum = i elif i[0] == minimum[0]: minimum = (minimum[0], i[1] and minimum[1]) return Union(Interval(minimum[0], maximum[0], minimum[1], maximum[1]))
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_solve_univariate_inequality(): assert isolve(x**2 >= 4, x, relational=False) == Union(Interval(-oo, -2), Interval(2, oo)) assert isolve(x**2 >= 4, x) == Or(And(Le(2, x), Lt(x, oo)), And(Le(x, -2), Lt(-oo, x))) assert isolve((x - 1)*(x - 2)*(x - 3) >= 0, x, relational=False) == \ Union(Interval(1, 2), Interval(3, oo)) assert isolve((x - 1)*(x - 2)*(x - 3) >= 0, x) == \ Or(And(Le(1, x), Le(x, 2)), And(Le(3, x), Lt(x, oo))) assert isolve((x - 1)*(x - 2)*(x - 4) < 0, x, domain = FiniteSet(0, 3)) == \ Or(Eq(x, 0), Eq(x, 3)) # issue 2785: assert isolve(x**3 - 2*x - 1 > 0, x, relational=False) == \ Union(Interval(-1, -sqrt(5)/2 + S.Half, True, True), Interval(S.Half + sqrt(5)/2, oo, True, True)) # issue 2794: assert isolve(x**3 - x**2 + x - 1 > 0, x, relational=False) == \ Interval(1, oo, True) #issue 13105 assert isolve((x + I) * (x + 2 * I) < 0, x) == Eq(x, 0) assert isolve(((x - 1) * (x - 2) + I) * ((x - 1) * (x - 2) + 2 * I) < 0, x) == Or(Eq(x, 1), Eq(x, 2)) assert isolve( (((x - 1) * (x - 2) + I) * ((x - 1) * (x - 2) + 2 * I)) / (x - 2) > 0, x) == Eq(x, 1) raises(ValueError, lambda: isolve((x**2 - 3 * x * I + 2) / x < 0, x)) # numerical testing in valid() is needed assert isolve(x**7 - x - 2 > 0, x) == \ And(rootof(x**7 - x - 2, 0) < x, x < oo) # handle numerator and denominator; although these would be handled as # rational inequalities, these test confirm that the right thing is done # when the domain is EX (e.g. when 2 is replaced with sqrt(2)) assert isolve(1 / (x - 2) > 0, x) == And(S(2) < x, x < oo) den = ((x - 1) * (x - 2)).expand() assert isolve((x - 1)/den <= 0, x) == \ (x > -oo) & (x < 2) & Ne(x, 1) n = Dummy('n') raises(NotImplementedError, lambda: isolve(Abs(x) <= n, x, relational=False)) c1 = Dummy("c1", positive=True) raises(NotImplementedError, lambda: isolve(n / c1 < 0, c1)) n = Dummy('n', negative=True) assert isolve(n / c1 > -2, c1) == (-n / 2 < c1) assert isolve(n / c1 < 0, c1) == True assert isolve(n / c1 > 0, c1) == False zero = cos(1)**2 + sin(1)**2 - 1 raises(NotImplementedError, lambda: isolve(x**2 < zero, x)) raises(NotImplementedError, lambda: isolve(x**2 < zero * I, x)) raises(NotImplementedError, lambda: isolve(1 / (x - y) < 2, x)) raises(NotImplementedError, lambda: isolve(1 / (x - y) < 0, x)) raises(TypeError, lambda: isolve(x - I < 0, x)) zero = x**2 + x - x * (x + 1) assert isolve(zero < 0, x, relational=False) is S.EmptySet assert isolve(zero <= 0, x, relational=False) is S.Reals # make sure iter_solutions gets a default value raises(NotImplementedError, lambda: isolve(Eq(cos(x)**2 + sin(x)**2, 1), x))