def test_issue_9522(): x = Symbol('x') expr1 = Eq(1/(x**2 - 4) + x, 1/(x**2 - 4) + 2) expr2 = Eq(1/x + x, 1/x) assert solveset(expr1, x, S.Reals) == EmptySet() assert solveset(expr2, x, S.Reals) == EmptySet()
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
def test_issue_9522(): x = Symbol("x", real=True) expr1 = Eq(1 / (x ** 2 - 4) + x, 1 / (x ** 2 - 4) + 2) expr2 = Eq(1 / x + x, 1 / x) assert solveset(expr1, x) == EmptySet() assert solveset(expr2, x) == EmptySet()
def test_issue_9556(): x = Symbol("x", real=True) b = Symbol("b", positive=True) assert solveset(Abs(x) + 1, x) == EmptySet() assert solveset(Abs(x) + b, x) == EmptySet() assert solveset(Eq(b, -1), b) == EmptySet()
def test_issue_9556(): x = Symbol('x') b = Symbol('b', positive=True) assert solveset(Abs(x) + 1, x, S.Reals) == EmptySet() assert solveset(Abs(x) + b, x, S.Reals) == EmptySet() assert solveset(Eq(b, -1), b, S.Reals) == EmptySet()
def test_issue_9778(): assert solveset(x ** 3 + 1, x, S.Reals) == FiniteSet(-1) assert solveset(x ** (S(3) / 5) + 1, x, S.Reals) == S.EmptySet assert solveset(x ** 3 + y, x, S.Reals) == Intersection( Interval(-oo, oo), FiniteSet((-y) ** (S(1) / 3) * Piecewise((1, Ne(-im(y), 0)), ((-1) ** (S(2) / 3), -y < 0), (1, True))), )
def test_issue_9611(): x = Symbol("x") a = Symbol("a") y = Symbol("y") assert solveset(Eq(x - x + a, a), x, S.Reals) == S.Reals assert solveset(Eq(y - y + a, a), y) == S.Complexes
def test_issue_9611(): x = Symbol('x') a = Symbol('a') y = Symbol('y') assert solveset(Eq(x - x + a, a), x, S.Reals) == S.Reals assert solveset(Eq(y - y + a, a), y) == S.Complexes
def test_issue_9611(): x = Symbol("x", real=True) a = Symbol("a", real=True) y = Symbol("y") assert solveset(Eq(x - x + a, a), x) == S.Reals assert solveset(Eq(y - y + a, a), y) == S.Complex
def contains(self, other): """ Is the other GeometryEntity contained within this Segment? Examples ======== >>> from sympy import Point, Segment >>> p1, p2 = Point(0, 1), Point(3, 4) >>> s = Segment(p1, p2) >>> s2 = Segment(p2, p1) >>> s.contains(s2) True """ if isinstance(other, Segment): return other.p1 in self and other.p2 in self elif isinstance(other, Point): if Point.is_collinear(self.p1, self.p2, other): t = Dummy('t') x, y = self.arbitrary_point(t).args if self.p1.x != self.p2.x: ti = list(solveset(x - other.x, t))[0] else: ti = list(solveset(y - other.y, t))[0] if ti.is_number: return 0 <= ti <= 1 return None return False
def continuous_domain(f, symbol, domain): """ Returns the intervals in the given domain for which the function is continuous. This method is limited by the ability to determine the various singularities and discontinuities of the given function. Examples ======== >>> from sympy import Symbol, S, tan, log, pi, sqrt >>> from sympy.sets import Interval >>> from sympy.calculus.util import continuous_domain >>> x = Symbol('x') >>> continuous_domain(1/x, x, S.Reals) (-oo, 0) U (0, oo) >>> continuous_domain(tan(x), x, Interval(0, pi)) [0, pi/2) U (pi/2, pi] >>> continuous_domain(sqrt(x - 2), x, Interval(-5, 5)) [2, 5] >>> continuous_domain(log(2*x - 1), x, S.Reals) (1/2, oo) """ from sympy.solvers.inequalities import solve_univariate_inequality from sympy.solvers.solveset import solveset, _has_rational_power if domain.is_subset(S.Reals): constrained_interval = domain for atom in f.atoms(Pow): predicate, denom = _has_rational_power(atom, symbol) constraint = S.EmptySet if predicate and denom == 2: constraint = solve_univariate_inequality(atom.base >= 0, symbol).as_set() constrained_interval = Intersection(constraint, constrained_interval) for atom in f.atoms(log): constraint = solve_univariate_inequality(atom.args[0] > 0, symbol).as_set() constrained_interval = Intersection(constraint, constrained_interval) domain = constrained_interval try: sings = S.EmptySet for atom in f.atoms(Pow): predicate, denom = _has_rational_power(atom, symbol) if predicate and denom == 2: sings = solveset(1/f, symbol, domain) break else: sings = Intersection(solveset(1/f, symbol), domain) except: raise NotImplementedError("Methods for determining the continuous domains" " of this function has not been developed.") return domain - sings
def _contains(self, other): from sympy.matrices import Matrix from sympy.solvers.solveset import solveset, linsolve from sympy.utilities.iterables import iterable, cartes L = self.lamda if self._is_multivariate(): if not iterable(L.expr): if iterable(other): return S.false return other.as_numer_denom() in self.func( Lambda(L.variables, L.expr.as_numer_denom()), self.base_set) if len(L.expr) != len(self.lamda.variables): raise NotImplementedError(filldedent(''' Dimensions of input and output of Lambda are different.''')) eqs = [expr - val for val, expr in zip(other, L.expr)] variables = L.variables free = set(variables) if all(i.is_number for i in list(Matrix(eqs).jacobian(variables))): solns = list(linsolve([e - val for e, val in zip(L.expr, other)], variables)) else: syms = [e.free_symbols & free for e in eqs] solns = {} for i, (e, s, v) in enumerate(zip(eqs, syms, other)): if not s: if e != v: return S.false solns[vars[i]] = [v] continue elif len(s) == 1: sy = s.pop() sol = solveset(e, sy) if sol is S.EmptySet: return S.false elif isinstance(sol, FiniteSet): solns[sy] = list(sol) else: raise NotImplementedError else: raise NotImplementedError solns = cartes(*[solns[s] for s in variables]) else: # assume scalar -> scalar mapping solnsSet = solveset(L.expr - other, L.variables[0]) if solnsSet.is_FiniteSet: solns = list(solnsSet) else: raise NotImplementedError(filldedent(''' Determining whether an ImageSet contains %s has not been implemented.''' % func_name(other))) for soln in solns: try: if soln in self.base_set: return S.true except TypeError: return self.base_set.contains(soln.evalf()) return S.false
def test_issue_11174(): r, t = symbols('r t') eq = z**2 + exp(2*x) - sin(y) soln = Intersection(S.Reals, FiniteSet(log(-z**2 + sin(y))/2)) assert solveset(eq, x, S.Reals) == soln eq = sqrt(r)*Abs(tan(t))/sqrt(tan(t)**2 + 1) + x*tan(t) s = -sqrt(r)*Abs(tan(t))/(sqrt(tan(t)**2 + 1)*tan(t)) soln = Intersection(S.Reals, FiniteSet(s)) assert solveset(eq, x, S.Reals) == soln
def test_invert_real(): x = Symbol('x', real=True) x = Dummy(real=True) n = Symbol('n') d = Dummy() assert solveset(abs(x) - n, x) == solveset(abs(x) - d, x) == EmptySet() n = Symbol('n', real=True) assert invert_real(x + 3, y, x) == (x, FiniteSet(y - 3)) assert invert_real(x*3, y, x) == (x, FiniteSet(y / 3)) assert invert_real(exp(x), y, x) == (x, FiniteSet(log(y))) assert invert_real(exp(3*x), y, x) == (x, FiniteSet(log(y) / 3)) assert invert_real(exp(x + 3), y, x) == (x, FiniteSet(log(y) - 3)) assert invert_real(exp(x) + 3, y, x) == (x, FiniteSet(log(y - 3))) assert invert_real(exp(x)*3, y, x) == (x, FiniteSet(log(y / 3))) assert invert_real(log(x), y, x) == (x, FiniteSet(exp(y))) assert invert_real(log(3*x), y, x) == (x, FiniteSet(exp(y) / 3)) assert invert_real(log(x + 3), y, x) == (x, FiniteSet(exp(y) - 3)) assert invert_real(Abs(x), y, x) == (x, FiniteSet(-y, y)) assert invert_real(2**x, y, x) == (x, FiniteSet(log(y)/log(2))) assert invert_real(2**exp(x), y, x) == (x, FiniteSet(log(log(y)/log(2)))) assert invert_real(x**2, y, x) == (x, FiniteSet(sqrt(y), -sqrt(y))) assert invert_real(x**Rational(1, 2), y, x) == (x, FiniteSet(y**2)) raises(ValueError, lambda: invert_real(x, x, x)) raises(ValueError, lambda: invert_real(x**pi, y, x)) raises(ValueError, lambda: invert_real(S.One, y, x)) assert invert_real(x**31 + x, y, x) == (x**31 + x, FiniteSet(y)) assert invert_real(Abs(x**31 + x + 1), y, x) == (x**31 + x, FiniteSet(-y - 1, y - 1)) assert invert_real(tan(x), y, x) == \ (x, imageset(Lambda(n, n*pi + atan(y)), S.Integers)) assert invert_real(tan(exp(x)), y, x) == \ (x, imageset(Lambda(n, log(n*pi + atan(y))), S.Integers)) assert invert_real(cot(x), y, x) == \ (x, imageset(Lambda(n, n*pi + acot(y)), S.Integers)) assert invert_real(cot(exp(x)), y, x) == \ (x, imageset(Lambda(n, log(n*pi + acot(y))), S.Integers)) assert invert_real(tan(tan(x)), y, x) == \ (tan(x), imageset(Lambda(n, n*pi + atan(y)), S.Integers)) x = Symbol('x', positive=True) assert invert_real(x**pi, y, x) == (x, FiniteSet(y**(1/pi)))
def test_piecewise(): eq = Piecewise((x - 2, Gt(x, 2)), (2 - x, True)) - 3 assert set(solveset_real(eq, x)) == set(FiniteSet(-1, 5)) absxm3 = Piecewise((x - 3, S(0) <= x - 3), (3 - x, S(0) > x - 3)) y = Symbol("y", positive=True) assert solveset_real(absxm3 - y, x) == FiniteSet(-y + 3, y + 3) f = Piecewise(((x - 2) ** 2, x >= 0), (0, True)) assert solveset(f, x, domain=S.Reals) == Union(FiniteSet(2), Interval(-oo, 0, True, True)) assert solveset(Piecewise((x + 1, x > 0), (I, True)) - I, x) == Interval(-oo, 0)
def test_conditonset(): assert solveset(Eq(sin(x)**2 + cos(x)**2, 1), x, domain=S.Reals) == \ ConditionSet(x, True, S.Reals) assert solveset(Eq(x**2 + x*sin(x), 1), x, domain=S.Reals) == \ ConditionSet(x, Eq(x*(x + sin(x)) - 1, 0), S.Reals) assert solveset(Eq(sin(Abs(x)), x), x, domain=S.Reals) == \ ConditionSet(x, Eq(-x + sin(Abs(x)), 0), Interval(-oo, oo)) assert solveset(Eq(-I*(exp(I*x) - exp(-I*x))/2, 1), x) == \ imageset(Lambda(n, 2*n*pi + pi/2), S.Integers) assert solveset(x + sin(x) > 1, x, domain=S.Reals) == \ ConditionSet(x, x + sin(x) > 1, S.Reals)
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 _eval_subs(self, old, new): if old in self.variables: newexpr = self.expr.subs(old, new) i = self.variables.index(old) newvars = list(self.variables) newpt = list(self.point) if new.is_Symbol: newvars[i] = new else: syms = new.free_symbols if len(syms) == 1 or old in syms: if old in syms: var = self.variables[i] else: var = syms.pop() # First, try to substitute self.point in the "new" # expr to see if this is a fixed point. # E.g. O(y).subs(y, sin(x)) point = new.subs(var, self.point[i]) if point != self.point[i]: from sympy.solvers.solveset import solveset d = Dummy() sol = solveset(old - new.subs(var, d), d) res = [dict(zip((d, ), sol))] point = d.subs(res[0]).limit(old, self.point[i]) newvars[i] = var newpt[i] = point elif old not in syms: del newvars[i], newpt[i] if not syms and new == self.point[i]: newvars.extend(syms) newpt.extend([S.Zero]*len(syms)) else: return return Order(newexpr, *zip(newvars, newpt))
def is_strictly_decreasing(f, interval=S.Reals, symbol=None): """ Returns if a function is strictly decreasing or not, in the given ``Interval``. Examples ======== >>> from sympy import is_strictly_decreasing >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_strictly_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_strictly_decreasing(1/(x**2 - 3*x), Interval.Ropen(-oo, S(3)/2)) False >>> is_strictly_decreasing(-x**2, Interval(-oo, 0)) False >>> is_strictly_decreasing(-x**2 + y, Interval(-oo, 0), x) False """ f = sympify(f) free_sym = f.free_symbols if symbol is None: if len(free_sym) > 1: raise NotImplementedError('is_strictly_decreasing has not yet been implemented ' 'for all multivariate expressions') elif len(free_sym) == 0: return False symbol = free_sym.pop() df = f.diff(symbol) df_neg_interval = solveset(df < 0, symbol, domain=S.Reals) return interval.is_subset(df_neg_interval)
def singularities(expr, sym): """ Finds singularities for a function. Currently supported functions are: - univariate rational(real or complex) functions Examples ======== >>> from sympy.calculus.singularities import singularities >>> from sympy import Symbol, I, sqrt >>> x = Symbol('x', real=True) >>> y = Symbol('y', real=False) >>> singularities(x**2 + x + 1, x) EmptySet() >>> singularities(1/(x + 1), x) {-1} >>> singularities(1/(y**2 + 1), y) {-I, I} >>> singularities(1/(y**3 + 1), y) {-1, 1/2 - sqrt(3)*I/2, 1/2 + sqrt(3)*I/2} References ========== .. [1] http://en.wikipedia.org/wiki/Mathematical_singularity """ if not expr.is_rational_function(sym): raise NotImplementedError("Algorithms finding singularities for" " non rational functions are not yet" " implemented") else: return solveset(simplify(1/expr), sym)
def test_solve_trig(): from sympy.abc import n assert solveset_real(sin(x), x) == Union( imageset(Lambda(n, 2 * pi * n), S.Integers), imageset(Lambda(n, 2 * pi * n + pi), S.Integers) ) assert solveset_real(sin(x) - 1, x) == imageset(Lambda(n, 2 * pi * n + pi / 2), S.Integers) assert solveset_real(cos(x), x) == Union( imageset(Lambda(n, 2 * pi * n - pi / 2), S.Integers), imageset(Lambda(n, 2 * pi * n + pi / 2), S.Integers) ) assert solveset_real(sin(x) + cos(x), x) == Union( imageset(Lambda(n, 2 * n * pi - pi / 4), S.Integers), imageset(Lambda(n, 2 * n * pi + 3 * pi / 4), S.Integers) ) assert solveset_real(sin(x) ** 2 + cos(x) ** 2, x) == S.EmptySet assert solveset_complex(cos(x) - S.Half, x) == Union( imageset(Lambda(n, 2 * n * pi + pi / 3), S.Integers), imageset(Lambda(n, 2 * n * pi - pi / 3), S.Integers) ) y, a = symbols("y,a") assert solveset(sin(y + a) - sin(y), a, domain=S.Reals) == Union( imageset(Lambda(n, 2 * n * pi), S.Integers), imageset(Lambda(n, -I * (I * (2 * n * pi + arg(-exp(-2 * I * y))) + 2 * im(y))), S.Integers), )
def is_monotonic(expression, interval=S.Reals, symbol=None): """ Return whether the function is monotonic in the given interval. Examples ======== >>> from sympy import is_monotonic >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_monotonic(1/(x**2 - 3*x), Interval.open(1.5, 3)) True >>> is_monotonic(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_monotonic(x**3 - 3*x**2 + 4*x, S.Reals) True >>> is_monotonic(-x**2, S.Reals) False >>> is_monotonic(x**2 + y + 1, Interval(1, 2), x) True """ expression = sympify(expression) free = expression.free_symbols if symbol is None and len(free) > 1: raise NotImplementedError( 'is_monotonic has not yet been implemented' ' for all multivariate expressions.' ) x = symbol or (free.pop() if free else Symbol('x')) turning_points = solveset(expression.diff(x), x, interval) return interval.intersection(turning_points) is S.EmptySet
def singularities(expr, sym): """ Finds singularities for a function. Currently supported functions are: - univariate real rational functions Examples ======== >>> from sympy.calculus.singularities import singularities >>> from sympy import Symbol >>> x = Symbol('x', real=True) >>> singularities(x**2 + x + 1, x) () >>> singularities(1/(x + 1), x) (-1,) References ========== .. [1] http://en.wikipedia.org/wiki/Mathematical_singularity """ if not expr.is_rational_function(sym): raise NotImplementedError("Algorithms finding singularities for" " non rational functions are not yet" " implemented") else: return tuple(sorted(solveset(simplify(1/expr), sym)))
def is_strictly_decreasing(f, interval=S.Reals): """ Returns if a function is decreasing or not, in the given ``Interval``. Examples ======== >>> from sympy import is_decreasing >>> from sympy.abc import x >>> from sympy import S, Interval, oo >>> is_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3)) True >>> is_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_decreasing(1/(x**2 - 3*x), Interval.Ropen(-oo, S(3)/2)) False >>> is_decreasing(-x**2, Interval(-oo, 0)) False """ if len(f.free_symbols) > 1: raise NotImplementedError('is_strictly_decreasing has not yet been ' 'implemented for multivariate expressions') symbol = f.free_symbols.pop() df = f.diff(symbol) df_neg_interval = solveset(df < 0, symbol, domain=S.Reals) return interval.is_subset(df_neg_interval)
def test_nfloat(): from sympy.core.basic import _aresame from sympy.polys.rootoftools import rootof x = Symbol("x") eq = x**(S(4)/3) + 4*x**(S(1)/3)/3 assert _aresame(nfloat(eq), x**(S(4)/3) + (4.0/3)*x**(S(1)/3)) assert _aresame(nfloat(eq, exponent=True), x**(4.0/3) + (4.0/3)*x**(1.0/3)) eq = x**(S(4)/3) + 4*x**(x/3)/3 assert _aresame(nfloat(eq), x**(S(4)/3) + (4.0/3)*x**(x/3)) big = 12345678901234567890 # specify precision to match value used in nfloat Float_big = Float(big, 15) assert _aresame(nfloat(big), Float_big) assert _aresame(nfloat(big*x), Float_big*x) assert _aresame(nfloat(x**big, exponent=True), x**Float_big) assert nfloat({x: sqrt(2)}) == {x: nfloat(sqrt(2))} assert nfloat({sqrt(2): x}) == {sqrt(2): x} assert nfloat(cos(x + sqrt(2))) == cos(x + nfloat(sqrt(2))) # issue 6342 f = S('x*lamda + lamda**3*(x/2 + 1/2) + lamda**2 + 1/4') assert not any(a.free_symbols for a in solveset(f.subs(x, -0.139))) # issue 6632 assert nfloat(-100000*sqrt(2500000001) + 5000000001) == \ 9.99999999800000e-11 # issue 7122 eq = cos(3*x**4 + y)*rootof(x**5 + 3*x**3 + 1, 0) assert str(nfloat(eq, exponent=False, n=1)) == '-0.7*cos(3.0*x**4 + y)'
def is_strictly_increasing(f, interval=S.Reals): """ Returns if a function is strictly increasing or not, in the given ``Interval``. Examples ======== >>> from sympy import is_strictly_increasing >>> from sympy.abc import x >>> from sympy import Interval, oo >>> is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.Ropen(-oo, -2)) True >>> is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.Lopen(3, oo)) True >>> is_strictly_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval.open(-2, 3)) False >>> is_strictly_increasing(-x**2, Interval(0, oo)) False """ if len(f.free_symbols) > 1: raise NotImplementedError('is_strictly_increasing has not yet been ' 'implemented for multivariate expressions') symbol = f.free_symbols.pop() df = f.diff(symbol) df_pos_interval = solveset(df > 0, symbol, domain=S.Reals) return interval.is_subset(df_pos_interval)
def test_improve_coverage(): from sympy.solvers.solveset import _has_rational_power x = Symbol('x', real=True) y = exp(x+1/x**2) raises(NotImplementedError, lambda: solveset(y**2+y, x)) assert _has_rational_power(sin(x)*exp(x) + 1, x) == (False, S.One) assert _has_rational_power((sin(x)**2)*(exp(x) + 1)**3, x) == (False, S.One)
def is_monotonic(expression, interval=S.Reals, symbol=None): """ Return whether the function is monotonic in the given interval. Parameters ========== expression : Expr The target function which is being checked. interval : Set, optional The range of values in which we are testing (defaults to set of all real numbers). symbol : Symbol, optional The symbol present in expression which gets varied over the given range. Returns ======= Boolean True if ``expression`` is monotonic in the given ``interval``, False otherwise. Raises ====== NotImplementedError Monotonicity check has not been implemented for the queried function. Examples ======== >>> from sympy import is_monotonic >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_monotonic(1/(x**2 - 3*x), Interval.open(1.5, 3)) True >>> is_monotonic(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_monotonic(x**3 - 3*x**2 + 4*x, S.Reals) True >>> is_monotonic(-x**2, S.Reals) False >>> is_monotonic(x**2 + y + 1, Interval(1, 2), x) True """ expression = sympify(expression) free = expression.free_symbols if symbol is None and len(free) > 1: raise NotImplementedError( 'is_monotonic has not yet been implemented' ' for all multivariate expressions.' ) variable = symbol or (free.pop() if free else Symbol('x')) turning_points = solveset(expression.diff(variable), variable, interval) return interval.intersection(turning_points) is S.EmptySet
def test_solve_abs(): assert solveset_real(Abs(x) - 2, x) == FiniteSet(-2, 2) assert solveset_real(Abs(x + 3) - 2 * Abs(x - 3), x) == FiniteSet(1, 9) assert solveset_real(2 * Abs(x) - Abs(x - 1), x) == FiniteSet(-1, Rational(1, 3)) assert solveset_real(Abs(x - 7) - 8, x) == FiniteSet(-S(1), S(15)) # issue 9565. Note: solveset_real does not solve this as it is # solveset's job to handle Relationals assert solveset(Abs((x - 1) / (x - 5)) <= S(1) / 3, domain=S.Reals) == Interval(-1, 2) # issue #10069 eq = abs(1 / (x - 1)) - 1 > 0 u = Union(Interval.open(0, 1), Interval.open(1, 2)) assert solveset_real(eq, x) == u assert solveset(eq, x, domain=S.Reals) == u raises(ValueError, lambda: solveset(abs(x) - 1, x))
def test_improve_coverage(): from sympy.solvers.solveset import _has_rational_power x = Symbol('x') y = exp(x+1/x**2) solution = solveset(y**2+y, x, S.Reals) unsolved_object = ConditionSet(x, Eq((exp((x**3 + 1)/x**2) + 1)*exp((x**3 + 1)/x**2), 0), S.Reals) assert solution == unsolved_object assert _has_rational_power(sin(x)*exp(x) + 1, x) == (False, S.One) assert _has_rational_power((sin(x)**2)*(exp(x) + 1)**3, x) == (False, S.One)
def is_increasing(f, interval=S.Reals, symbol=None): """ Returns if a function is increasing or not, in the given ``Interval``. Examples ======== >>> from sympy import is_increasing >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_increasing(x**3 - 3*x**2 + 4*x, S.Reals) True >>> is_increasing(-x**2, Interval(-oo, 0)) True >>> is_increasing(-x**2, Interval(0, oo)) False >>> is_increasing(4*x**3 - 6*x**2 - 72*x + 30, Interval(-2, 3)) False >>> is_increasing(x**2 + y, Interval(1, 2), x) True """ f = sympify(f) free_sym = f.free_symbols if symbol is None: if len(free_sym) > 1: raise NotImplementedError('is_increasing has not yet been implemented ' 'for all multivariate expressions') if len(free_sym) == 0: return True symbol = free_sym.pop() df = f.diff(symbol) df_nonneg_interval = solveset(df >= 0, symbol, domain=S.Reals) return interval.is_subset(df_nonneg_interval)
def is_decreasing(f, interval=S.Reals, symbol=None): """ Returns if a function is decreasing or not, in the given ``Interval``. Examples ======== >>> from sympy import is_decreasing >>> from sympy.abc import x, y >>> from sympy import S, Interval, oo >>> is_decreasing(1/(x**2 - 3*x), Interval.open(1.5, 3)) True >>> is_decreasing(1/(x**2 - 3*x), Interval.Lopen(3, oo)) True >>> is_decreasing(1/(x**2 - 3*x), Interval.Ropen(-oo, S(3)/2)) False >>> is_decreasing(-x**2, Interval(-oo, 0)) False >>> is_decreasing(-x**2 + y, Interval(-oo, 0), x) False """ f = sympify(f) free_sym = f.free_symbols if symbol is None: if len(free_sym) > 1: raise NotImplementedError('is_decreasing has not yet been implemented ' 'for all multivariate expressions') elif len(free_sym) == 0: return True symbol = free_sym.pop() df = f.diff(symbol) df_nonpos_interval = solveset(df <= 0, symbol, domain=S.Reals) return interval.is_subset(df_nonpos_interval)
def singularities(expression, symbol): """ Find singularities of a given function. Currently supported functions are: - univariate rational (real or complex) functions Examples ======== >>> from sympy.calculus.singularities import singularities >>> from sympy import Symbol, I, sqrt >>> x = Symbol('x', real=True) >>> y = Symbol('y', real=False) >>> singularities(x**2 + x + 1, x) EmptySet() >>> singularities(1/(x + 1), x) {-1} >>> singularities(1/(y**2 + 1), y) {-I, I} >>> singularities(1/(y**3 + 1), y) {-1, 1/2 - sqrt(3)*I/2, 1/2 + sqrt(3)*I/2} References ========== .. [1] http://en.wikipedia.org/wiki/Mathematical_singularity """ if not expression.is_rational_function(symbol): raise NotImplementedError( "Algorithms finding singularities for non-rational" " functions are not yet implemented." ) else: return solveset(simplify(1 / expression), symbol)
def test_conditonset(): assert solveset(Eq(sin(x)**2 + cos(x)**2, 1), x, domain=S.Reals) == \ ConditionSet(x, True, S.Reals) assert solveset(Eq(x**2 + x*sin(x), 1), x, domain=S.Reals) == \ ConditionSet(x, Eq(x*(x + sin(x)) - 1, 0), S.Reals) assert solveset(Eq(sin(Abs(x)), x), x, domain=S.Reals) == \ ConditionSet(x, Eq(-x + sin(Abs(x)), 0), Interval(-oo, oo)) assert solveset(Eq(-I*(exp(I*x) - exp(-I*x))/2, 1), x) == \ imageset(Lambda(n, 2*n*pi + pi/2), S.Integers) assert solveset(x + sin(x) > 1, x, domain=S.Reals) == \ ConditionSet(x, x + sin(x) > 1, S.Reals) y, a = symbols('y,a') assert solveset(sin(y + a) - sin(y), a, domain=S.Reals) == \ ConditionSet(a, Eq(-sin(y) + sin(y + a), 0), S.Reals)
def test_solveset(): x = Symbol('x') raises(ValueError, lambda: solveset(x + y)) raises(ValueError, lambda: solveset(x, 1)) assert solveset(0, domain=S.Reals) == S.Reals assert solveset(1) == S.EmptySet assert solveset(True, domain=S.Reals) == S.Reals # issue 10197 assert solveset(False, domain=S.Reals) == S.EmptySet assert solveset(exp(x) - 1, domain=S.Reals) == FiniteSet(0) assert solveset(exp(x) - 1, x, S.Reals) == FiniteSet(0) assert solveset(Eq(exp(x), 1), x, S.Reals) == FiniteSet(0) assert solveset(x - 1 >= 0, x, S.Reals) == Interval(1, oo) assert solveset(exp(x) - 1 >= 0, x, S.Reals) == Interval(0, oo) assert solveset(exp(x) - 1, x) == imageset(Lambda(n, 2 * I * pi * n), S.Integers) assert solveset(Eq(exp(x), 1), x) == imageset(Lambda(n, 2 * I * pi * n), S.Integers)
def test_solve_trig_abs(): assert solveset(Eq(sin(Abs(x)), 1), x, domain=S.Reals) == \ Union(ImageSet(Lambda(n, n*pi + (-1)**n*pi/2), S.Naturals0), ImageSet(Lambda(n, -n*pi - (-1)**n*pi/2), S.Naturals0))
def test_sol_zero_real(): assert solveset_real(0, x) == S.Reals assert solveset(0, x, Interval(1, 2)) == Interval(1, 2) assert solveset_real(-x**2 - 2 * x + (x + 1)**2 - 1, x) == S.Reals
def function_range(f, symbol, domain): """ Finds the range of a function in a given domain. This method is limited by the ability to determine the singularities and determine limits. Examples ======== >>> from sympy import Symbol, S, exp, log, pi, sqrt, sin, tan >>> from sympy.sets import Interval >>> from sympy.calculus.util import function_range >>> x = Symbol('x') >>> function_range(sin(x), x, Interval(0, 2*pi)) Interval(-1, 1) >>> function_range(tan(x), x, Interval(-pi/2, pi/2)) Interval(-oo, oo, True, True) >>> function_range(1/x, x, S.Reals) Interval(-oo, oo, True, True) >>> function_range(exp(x), x, S.Reals) Interval(0, oo, True, True) >>> function_range(log(x), x, S.Reals) Interval(-oo, oo, True, True) >>> function_range(sqrt(x), x , Interval(-5, 9)) Interval(0, 3) """ from sympy.solvers.solveset import solveset vals = S.EmptySet period = periodicity(f, symbol) if not any(period is i for i in (None, S.Zero)): inf = domain.inf inf_period = S.Zero if inf.is_infinite else inf sup_period = inf_period + period periodic_interval = Interval(inf_period, sup_period) domain = domain.intersect(periodic_interval) intervals = continuous_domain(f, symbol, domain) range_int = S.EmptySet if isinstance(intervals, Interval): interval_iter = (intervals,) else: interval_iter = intervals.args for interval in interval_iter: critical_points = S.EmptySet critical_values = S.EmptySet bounds = ((interval.left_open, interval.inf, '+'), (interval.right_open, interval.sup, '-')) for is_open, limit_point, direction in bounds: if is_open: critical_values += FiniteSet(limit(f, symbol, limit_point, direction)) vals += critical_values else: vals += FiniteSet(f.subs(symbol, limit_point)) critical_points += solveset(f.diff(symbol), symbol, domain) for critical_point in critical_points: vals += FiniteSet(f.subs(symbol, critical_point)) left_open, right_open = False, False if critical_values is not S.EmptySet: if critical_values.inf == vals.inf: left_open = True if critical_values.sup == vals.sup: right_open = True range_int += Interval(vals.inf, vals.sup, left_open, right_open) return range_int
def _intersect(self, other): from sympy.solvers.diophantine import diophantine if self.base_set is S.Integers: g = None if isinstance(other, ImageSet) and other.base_set is S.Integers: g = other.lamda.expr m = other.lamda.variables[0] elif other is S.Integers: m = g = Dummy('x') if g is not None: f = self.lamda.expr n = self.lamda.variables[0] # Diophantine sorts the solutions according to the alphabetic # order of the variable names, since the result should not depend # on the variable name, they are replaced by the dummy variables # below a, b = Dummy('a'), Dummy('b') f, g = f.subs(n, a), g.subs(m, b) solns_set = diophantine(f - g) if solns_set == set(): return EmptySet() solns = list(diophantine(f - g)) if len(solns) != 1: return # since 'a' < 'b', select soln for n nsol = solns[0][0] t = nsol.free_symbols.pop() return imageset(Lambda(n, f.subs(a, nsol.subs(t, n))), S.Integers) if other == S.Reals: from sympy.solvers.solveset import solveset_real from sympy.core.function import expand_complex if len(self.lamda.variables) > 1: return None f = self.lamda.expr n = self.lamda.variables[0] n_ = Dummy(n.name, real=True) f_ = f.subs(n, n_) re, im = f_.as_real_imag() im = expand_complex(im) return imageset(Lambda(n_, re), self.base_set.intersect(solveset_real(im, n_))) elif isinstance(other, Interval): from sympy.solvers.solveset import (invert_real, invert_complex, solveset) f = self.lamda.expr n = self.lamda.variables[0] base_set = self.base_set new_inf, new_sup = None, None new_lopen, new_ropen = other.left_open, other.right_open if f.is_real: inverter = invert_real else: inverter = invert_complex g1, h1 = inverter(f, other.inf, n) g2, h2 = inverter(f, other.sup, n) if all(isinstance(i, FiniteSet) for i in (h1, h2)): if g1 == n: if len(h1) == 1: new_inf = h1.args[0] if g2 == n: if len(h2) == 1: new_sup = h2.args[0] # TODO: Design a technique to handle multiple-inverse # functions # Any of the new boundary values cannot be determined if any(i is None for i in (new_sup, new_inf)): return range_set = S.EmptySet if all(i.is_real for i in (new_sup, new_inf)): # this assumes continuity of underlying function # however fixes the case when it is decreasing if new_inf > new_sup: new_inf, new_sup = new_sup, new_inf new_interval = Interval(new_inf, new_sup, new_lopen, new_ropen) range_set = base_set._intersect(new_interval) else: if other.is_subset(S.Reals): solutions = solveset(f, n, S.Reals) if not isinstance(range_set, (ImageSet, ConditionSet)): range_set = solutions._intersect(other) else: return if range_set is S.EmptySet: return S.EmptySet elif isinstance(range_set, Range) and range_set.size is not S.Infinity: range_set = FiniteSet(*list(range_set)) if range_set is not None: return imageset(Lambda(n, f), range_set) return else: return
def test_issue_12429(): eq = solveset(log(x)/x<=0,x,S.Reals) sol = Interval(0, 1, True) assert eq == sol
def singularities(expression, symbol): """ Find singularities of a given function. Parameters ========== expression : Expr The target function in which singularities need to be found. symbol : Symbol The symbol over the values of which the singularity in expression in being searched for. Returns ======= Set A set of values for ``symbol`` for which ``expression`` has a singularity. An ``EmptySet`` is returned if ``expression`` has no singularities for any given value of ``Symbol``. Raises ====== NotImplementedError The algorithm to find singularities for irrational functions has not been implemented yet. Notes ===== This function does not find non-isolated singularities nor does it find branch points of the expression. Currently supported functions are: - univariate rational (real or complex) functions References ========== .. [1] https://en.wikipedia.org/wiki/Mathematical_singularity Examples ======== >>> from sympy.calculus.singularities import singularities >>> from sympy import Symbol >>> x = Symbol('x', real=True) >>> y = Symbol('y', real=False) >>> singularities(x**2 + x + 1, x) EmptySet() >>> singularities(1/(x + 1), x) {-1} >>> singularities(1/(y**2 + 1), y) {-I, I} >>> singularities(1/(y**3 + 1), y) {-1, 1/2 - sqrt(3)*I/2, 1/2 + sqrt(3)*I/2} """ if not expression.is_rational_function(symbol): raise NotImplementedError( "Algorithms finding singularities for non-rational" " functions are not yet implemented." ) else: domain = Reals if symbol.is_real else S.Complexes return solveset(simplify(1 / expression), symbol, domain)
def intersection_sets(self, other): # noqa:F811 from sympy.solvers.diophantine import diophantine # Only handle the straight-forward univariate case if (len(self.lamda.variables) > 1 or self.lamda.signature != self.lamda.variables): return None base_set = self.base_sets[0] # Intersection between ImageSets with Integers as base set # For {f(n) : n in Integers} & {g(m) : m in Integers} we solve the # diophantine equations f(n)=g(m). # If the solutions for n are {h(t) : t in Integers} then we return # {f(h(t)) : t in integers}. # If the solutions for n are {n_1, n_2, ..., n_k} then we return # {f(n_i) : 1 <= i <= k}. if base_set is S.Integers: gm = None if isinstance(other, ImageSet) and other.base_sets == (S.Integers, ): gm = other.lamda.expr var = other.lamda.variables[0] # Symbol of second ImageSet lambda must be distinct from first m = Dummy('m') gm = gm.subs(var, m) elif other is S.Integers: m = gm = Dummy('m') if gm is not None: fn = self.lamda.expr n = self.lamda.variables[0] try: solns = list(diophantine(fn - gm, syms=(n, m), permute=True)) except (TypeError, NotImplementedError): # TypeError if equation not polynomial with rational coeff. # NotImplementedError if correct format but no solver. return # 3 cases are possible for solns: # - empty set, # - one or more parametric (infinite) solutions, # - a finite number of (non-parametric) solution couples. # Among those, there is one type of solution set that is # not helpful here: multiple parametric solutions. if len(solns) == 0: return EmptySet elif any(not isinstance(s, int) and s.free_symbols for tupl in solns for s in tupl): if len(solns) == 1: soln, solm = solns[0] (t, ) = soln.free_symbols expr = fn.subs(n, soln.subs(t, n)).expand() return imageset(Lambda(n, expr), S.Integers) else: return else: return FiniteSet(*(fn.subs(n, s[0]) for s in solns)) if other == S.Reals: from sympy.solvers.solveset import solveset_real from sympy.core.function import expand_complex f = self.lamda.expr n = self.lamda.variables[0] n_ = Dummy(n.name, real=True) f_ = f.subs(n, n_) re, im = f_.as_real_imag() im = expand_complex(im) re = re.subs(n_, n) im = im.subs(n_, n) ifree = im.free_symbols lam = Lambda(n, re) if not im: # allow re-evaluation # of self in this case to make # the result canonical pass elif im.is_zero is False: return S.EmptySet elif ifree != {n}: return None else: # univarite imaginary part in same variable base_set = base_set.intersect(solveset_real(im, n)) return imageset(lam, base_set) elif isinstance(other, Interval): from sympy.solvers.solveset import (invert_real, invert_complex, solveset) f = self.lamda.expr n = self.lamda.variables[0] new_inf, new_sup = None, None new_lopen, new_ropen = other.left_open, other.right_open if f.is_real: inverter = invert_real else: inverter = invert_complex g1, h1 = inverter(f, other.inf, n) g2, h2 = inverter(f, other.sup, n) if all(isinstance(i, FiniteSet) for i in (h1, h2)): if g1 == n: if len(h1) == 1: new_inf = h1.args[0] if g2 == n: if len(h2) == 1: new_sup = h2.args[0] # TODO: Design a technique to handle multiple-inverse # functions # Any of the new boundary values cannot be determined if any(i is None for i in (new_sup, new_inf)): return range_set = S.EmptySet if all(i.is_real for i in (new_sup, new_inf)): # this assumes continuity of underlying function # however fixes the case when it is decreasing if new_inf > new_sup: new_inf, new_sup = new_sup, new_inf new_interval = Interval(new_inf, new_sup, new_lopen, new_ropen) range_set = base_set.intersect(new_interval) else: if other.is_subset(S.Reals): solutions = solveset(f, n, S.Reals) if not isinstance(range_set, (ImageSet, ConditionSet)): range_set = solutions.intersect(other) else: return if range_set is S.EmptySet: return S.EmptySet elif isinstance(range_set, Range) and range_set.size is not S.Infinity: range_set = FiniteSet(*list(range_set)) if range_set is not None: return imageset(Lambda(n, f), range_set) return else: return
def test_issue_9913(): assert solveset(2*x + 1/(x - 10)**2, x, S.Reals) == \ FiniteSet(-(3*sqrt(24081)/4 + S(4027)/4)**(S(1)/3)/3 - 100/ (3*(3*sqrt(24081)/4 + S(4027)/4)**(S(1)/3)) + S(20)/3)
def test_issue_9849(): assert solveset(Abs(sin(x)) + 1, x, S.Reals) == S.EmptySet
def test_issue_failing_pow(): assert solveset(x**(S(3) / 2) + 4, x, S.Reals) == S.EmptySet
def test_issue_9778(): assert solveset(x**3 + 1, x, S.Reals) == FiniteSet(-1) assert solveset(x**(S(3) / 5) + 1, x, S.Reals) == S.EmptySet assert solveset(x**3 + y, x, S.Reals) == Intersection(Interval(-oo, oo), \ FiniteSet((-y)**(S(1)/3)*Piecewise((1, Ne(-im(y), 0)), ((-1)**(S(2)/3), -y < 0), (1, True))))
def given(expr, condition=None, **kwargs): r""" Conditional Random Expression From a random expression and a condition on that expression creates a new probability space from the condition and returns the same expression on that conditional probability space. Examples ======== >>> from sympy.stats import given, density, Die >>> X = Die('X', 6) >>> Y = given(X, X > 3) >>> density(Y).dict {4: 1/3, 5: 1/3, 6: 1/3} Following convention, if the condition is a random symbol then that symbol is considered fixed. >>> from sympy.stats import Normal >>> from sympy import pprint >>> from sympy.abc import z >>> X = Normal('X', 0, 1) >>> Y = Normal('Y', 0, 1) >>> pprint(density(X + Y, Y)(z), use_unicode=False) 2 -(-Y + z) ----------- ___ 2 \/ 2 *e ------------------ ____ 2*\/ pi """ if not is_random(condition) or pspace_independent(expr, condition): return expr if isinstance(condition, RandomSymbol): condition = Eq(condition, condition.symbol) condsymbols = random_symbols(condition) if (isinstance(condition, Equality) and len(condsymbols) == 1 and not isinstance(pspace(expr).domain, ConditionalDomain)): rv = tuple(condsymbols)[0] results = solveset(condition, rv) if isinstance(results, Intersection) and S.Reals in results.args: results = list(results.args[1]) sums = 0 for res in results: temp = expr.subs(rv, res) if temp == True: return True if temp != False: # XXX: This seems nonsensical but preserves existing behaviour # after the change that Relational is no longer a subclass of # Expr. Here expr is sometimes Relational and sometimes Expr # but we are trying to add them with +=. This needs to be # fixed somehow. if sums == 0 and isinstance(expr, Relational): sums = expr.subs(rv, res) else: sums += expr.subs(rv, res) if sums == 0: return False return sums # Get full probability space of both the expression and the condition fullspace = pspace(Tuple(expr, condition)) # Build new space given the condition space = fullspace.conditional_space(condition, **kwargs) # Dictionary to swap out RandomSymbols in expr with new RandomSymbols # That point to the new conditional space swapdict = rs_swap(fullspace.values, space.values) # Swap random variables in the expression expr = expr.xreplace(swapdict) return expr
def test_conditionset_equality(): ''' Checking equality of different representations of ConditionSet''' assert solveset(Eq(tan(x), y), x) == ConditionSet(x, Eq(tan(x), y), S.Complexes)
def test_solveset_domain(): x = Symbol('x') assert solveset(x**2 - x - 6, x, Interval(0, oo)) == FiniteSet(3) assert solveset(x**2 - 1, x, Interval(0, oo)) == FiniteSet(1) assert solveset(x**4 - 16, x, Interval(0, 10)) == FiniteSet(2)
def test_nfloat(): from sympy.core.basic import _aresame from sympy.polys.rootoftools import rootof x = Symbol("x") eq = x**Rational(4, 3) + 4 * x**(S.One / 3) / 3 assert _aresame(nfloat(eq), x**Rational(4, 3) + (4.0 / 3) * x**(S.One / 3)) assert _aresame(nfloat(eq, exponent=True), x**(4.0 / 3) + (4.0 / 3) * x**(1.0 / 3)) eq = x**Rational(4, 3) + 4 * x**(x / 3) / 3 assert _aresame(nfloat(eq), x**Rational(4, 3) + (4.0 / 3) * x**(x / 3)) big = 12345678901234567890 # specify precision to match value used in nfloat Float_big = Float(big, 15) assert _aresame(nfloat(big), Float_big) assert _aresame(nfloat(big * x), Float_big * x) assert _aresame(nfloat(x**big, exponent=True), x**Float_big) assert nfloat(cos(x + sqrt(2))) == cos(x + nfloat(sqrt(2))) # issue 6342 f = S('x*lamda + lamda**3*(x/2 + 1/2) + lamda**2 + 1/4') assert not any(a.free_symbols for a in solveset(f.subs(x, -0.139))) # issue 6632 assert nfloat(-100000*sqrt(2500000001) + 5000000001) == \ 9.99999999800000e-11 # issue 7122 eq = cos(3 * x**4 + y) * rootof(x**5 + 3 * x**3 + 1, 0) assert str(nfloat(eq, exponent=False, n=1)) == '-0.7*cos(3.0*x**4 + y)' # issue 10933 for ti in (dict, Dict): d = ti({S.Half: S.Half}) n = nfloat(d) assert isinstance(n, ti) assert _aresame(list(n.items()).pop(), (S.Half, Float(.5))) for ti in (dict, Dict): d = ti({S.Half: S.Half}) n = nfloat(d, dkeys=True) assert isinstance(n, ti) assert _aresame(list(n.items()).pop(), (Float(.5), Float(.5))) d = [S.Half] n = nfloat(d) assert type(n) is list assert _aresame(n[0], Float(.5)) assert _aresame(nfloat(Eq(x, S.Half)).rhs, Float(.5)) assert _aresame(nfloat(S(True)), S(True)) assert _aresame(nfloat(Tuple(S.Half))[0], Float(.5)) assert nfloat(Eq((3 - I)**2 / 2 + I, 0)) == S.false # pass along kwargs assert nfloat([{S.Half: x}], dkeys=True) == [{Float(0.5): x}] # Issue 17706 A = MutableMatrix([[1, 2], [3, 4]]) B = MutableMatrix( [[Float('1.0', precision=53), Float('2.0', precision=53)], [Float('3.0', precision=53), Float('4.0', precision=53)]]) assert _aresame(nfloat(A), B) A = ImmutableMatrix([[1, 2], [3, 4]]) B = ImmutableMatrix( [[Float('1.0', precision=53), Float('2.0', precision=53)], [Float('3.0', precision=53), Float('4.0', precision=53)]]) assert _aresame(nfloat(A), B)
def intersection_sets(self, other): from sympy.solvers.diophantine import diophantine # Only handle the straight-forward univariate case if (len(self.lamda.variables) > 1 or self.lamda.signature != self.lamda.variables): return None base_set = self.base_sets[0] # Intersection between ImageSets with Integers as base set # For {f(n) : n in Integers} & {g(m) : m in Integers} we solve the # diophantine equations f(n)=g(m). # If the solutions for n are {h(t) : t in Integers} then we return # {f(h(t)) : t in integers}. if base_set is S.Integers: gm = None if isinstance(other, ImageSet) and other.base_sets == (S.Integers, ): gm = other.lamda.expr m = other.lamda.variables[0] elif other is S.Integers: m = gm = Dummy('x') if gm is not None: fn = self.lamda.expr n = self.lamda.variables[0] solns = list(diophantine(fn - gm, syms=(n, m))) if len(solns) == 0: return EmptySet elif len(solns) != 1: return else: soln, solm = solns[0] (t, ) = soln.free_symbols expr = fn.subs(n, soln.subs(t, n)) return imageset(Lambda(n, expr), S.Integers) if other == S.Reals: from sympy.solvers.solveset import solveset_real from sympy.core.function import expand_complex f = self.lamda.expr n = self.lamda.variables[0] n_ = Dummy(n.name, real=True) f_ = f.subs(n, n_) re, im = f_.as_real_imag() im = expand_complex(im) re = re.subs(n_, n) im = im.subs(n_, n) ifree = im.free_symbols lam = Lambda(n, re) if not im: # allow re-evaluation # of self in this case to make # the result canonical pass elif im.is_zero is False: return S.EmptySet elif ifree != {n}: return None else: # univarite imaginary part in same variable base_set = base_set.intersect(solveset_real(im, n)) return imageset(lam, base_set) elif isinstance(other, Interval): from sympy.solvers.solveset import (invert_real, invert_complex, solveset) f = self.lamda.expr n = self.lamda.variables[0] new_inf, new_sup = None, None new_lopen, new_ropen = other.left_open, other.right_open if f.is_real: inverter = invert_real else: inverter = invert_complex g1, h1 = inverter(f, other.inf, n) g2, h2 = inverter(f, other.sup, n) if all(isinstance(i, FiniteSet) for i in (h1, h2)): if g1 == n: if len(h1) == 1: new_inf = h1.args[0] if g2 == n: if len(h2) == 1: new_sup = h2.args[0] # TODO: Design a technique to handle multiple-inverse # functions # Any of the new boundary values cannot be determined if any(i is None for i in (new_sup, new_inf)): return range_set = S.EmptySet if all(i.is_real for i in (new_sup, new_inf)): # this assumes continuity of underlying function # however fixes the case when it is decreasing if new_inf > new_sup: new_inf, new_sup = new_sup, new_inf new_interval = Interval(new_inf, new_sup, new_lopen, new_ropen) range_set = base_set.intersect(new_interval) else: if other.is_subset(S.Reals): solutions = solveset(f, n, S.Reals) if not isinstance(range_set, (ImageSet, ConditionSet)): range_set = solutions.intersect(other) else: return if range_set is S.EmptySet: return S.EmptySet elif isinstance(range_set, Range) and range_set.size is not S.Infinity: range_set = FiniteSet(*list(range_set)) if range_set is not None: return imageset(Lambda(n, f), range_set) return else: return
def test_issue_10671_12466(): assert solveset(sin(y), y, Interval(0, pi)) == FiniteSet(0, pi) i = Interval(1, 10) assert solveset((1 / x).diff(x) < 0, x, i) == i assert solveset((log(x - 6)/x) <= 0, x, S.Reals) == \ Interval.Lopen(6, 7)
def test_issue_8715(): eq = x + 1 / x > -2 + 1 / x assert solveset(eq, x, S.Reals) == \ (Interval.open(-2, oo) - FiniteSet(0)) assert solveset(eq.subs(x,log(x)), x, S.Reals) == \ Interval.open(exp(-2), oo) - FiniteSet(1)
def test_invert_real(): x = Symbol('x', real=True) y = Symbol('y') n = Symbol('n') def ireal(x, s=S.Reals): return Intersection(s, x) minus_n = Intersection(Interval(-oo, 0), FiniteSet(-n)) plus_n = Intersection(Interval(0, oo), FiniteSet(n)) assert solveset(abs(x) - n, x, S.Reals) == Union(minus_n, plus_n) assert invert_real(exp(x), y, x) == (x, ireal(FiniteSet(log(y)))) y = Symbol('y', positive=True) n = Symbol('n', real=True) assert invert_real(x + 3, y, x) == (x, FiniteSet(y - 3)) assert invert_real(x * 3, y, x) == (x, FiniteSet(y / 3)) assert invert_real(exp(x), y, x) == (x, FiniteSet(log(y))) assert invert_real(exp(3 * x), y, x) == (x, FiniteSet(log(y) / 3)) assert invert_real(exp(x + 3), y, x) == (x, FiniteSet(log(y) - 3)) assert invert_real(exp(x) + 3, y, x) == (x, ireal(FiniteSet(log(y - 3)))) assert invert_real(exp(x) * 3, y, x) == (x, FiniteSet(log(y / 3))) assert invert_real(log(x), y, x) == (x, FiniteSet(exp(y))) assert invert_real(log(3 * x), y, x) == (x, FiniteSet(exp(y) / 3)) assert invert_real(log(x + 3), y, x) == (x, FiniteSet(exp(y) - 3)) minus_y = Intersection(Interval(-oo, 0), FiniteSet(-y)) plus_y = Intersection(Interval(0, oo), FiniteSet(y)) assert invert_real(Abs(x), y, x) == (x, Union(minus_y, plus_y)) assert invert_real(2**x, y, x) == (x, FiniteSet(log(y) / log(2))) assert invert_real(2**exp(x), y, x) == (x, ireal(FiniteSet(log(log(y) / log(2))))) assert invert_real(x**2, y, x) == (x, FiniteSet(sqrt(y), -sqrt(y))) assert invert_real(x**Rational(1, 2), y, x) == (x, FiniteSet(y**2)) raises(ValueError, lambda: invert_real(x, x, x)) raises(ValueError, lambda: invert_real(x**pi, y, x)) raises(ValueError, lambda: invert_real(S.One, y, x)) assert invert_real(x**31 + x, y, x) == (x**31 + x, FiniteSet(y)) y_1 = Intersection(Interval(-1, oo), FiniteSet(y - 1)) y_2 = Intersection(Interval(-oo, -1), FiniteSet(-y - 1)) assert invert_real(Abs(x**31 + x + 1), y, x) == (x**31 + x, Union(y_1, y_2)) assert invert_real(sin(x), y, x) == \ (x, imageset(Lambda(n, n*pi + (-1)**n*asin(y)), S.Integers)) assert invert_real(sin(exp(x)), y, x) == \ (x, imageset(Lambda(n, log((-1)**n*asin(y) + n*pi)), S.Integers)) assert invert_real(csc(x), y, x) == \ (x, imageset(Lambda(n, n*pi + (-1)**n*acsc(y)), S.Integers)) assert invert_real(csc(exp(x)), y, x) == \ (x, imageset(Lambda(n, log((-1)**n*acsc(y) + n*pi)), S.Integers)) assert invert_real(cos(x), y, x) == \ (x, Union(imageset(Lambda(n, 2*n*pi + acos(y)), S.Integers), \ imageset(Lambda(n, 2*n*pi - acos(y)), S.Integers))) assert invert_real(cos(exp(x)), y, x) == \ (x, Union(imageset(Lambda(n, log(2*n*pi + acos(y))), S.Integers), \ imageset(Lambda(n, log(2*n*pi - acos(y))), S.Integers))) assert invert_real(sec(x), y, x) == \ (x, Union(imageset(Lambda(n, 2*n*pi + asec(y)), S.Integers), \ imageset(Lambda(n, 2*n*pi - asec(y)), S.Integers))) assert invert_real(sec(exp(x)), y, x) == \ (x, Union(imageset(Lambda(n, log(2*n*pi + asec(y))), S.Integers), \ imageset(Lambda(n, log(2*n*pi - asec(y))), S.Integers))) assert invert_real(tan(x), y, x) == \ (x, imageset(Lambda(n, n*pi + atan(y)), S.Integers)) assert invert_real(tan(exp(x)), y, x) == \ (x, imageset(Lambda(n, log(n*pi + atan(y))), S.Integers)) assert invert_real(cot(x), y, x) == \ (x, imageset(Lambda(n, n*pi + acot(y)), S.Integers)) assert invert_real(cot(exp(x)), y, x) == \ (x, imageset(Lambda(n, log(n*pi + acot(y))), S.Integers)) assert invert_real(tan(tan(x)), y, x) == \ (tan(x), imageset(Lambda(n, n*pi + atan(y)), S.Integers)) x = Symbol('x', positive=True) assert invert_real(x**pi, y, x) == (x, FiniteSet(y**(1 / pi))) # Test for ``set_h`` containing information about the domain n = Dummy('n') x = Symbol('x') h1 = Intersection(Interval(-oo, -3), FiniteSet(-a + b - 3), imageset(Lambda(n, n - a - 3), Interval(0, oo))) h2 = Intersection(Interval(-3, oo), FiniteSet(a - b - 3), imageset(Lambda(n, -n + a - 3), Interval(0, oo))) assert invert_real(Abs(Abs(x + 3) - a) - b, 0, x) == (x, Union(h1, h2))
def test_issue_10397(): assert solveset(sqrt(x), x, S.Complexes) == FiniteSet(0)
def continuous_domain(f, symbol, domain): """ Returns the intervals in the given domain for which the function is continuous. This method is limited by the ability to determine the various singularities and discontinuities of the given function. Examples ======== >>> from sympy import Symbol, S, tan, log, pi, sqrt >>> from sympy.sets import Interval >>> from sympy.calculus.util import continuous_domain >>> x = Symbol('x') >>> continuous_domain(1/x, x, S.Reals) Union(Interval(-oo, 0, True, True), Interval(0, oo, True, True)) >>> continuous_domain(tan(x), x, Interval(0, pi)) Union(Interval(0, pi/2, False, True), Interval(pi/2, pi, True)) >>> continuous_domain(sqrt(x - 2), x, Interval(-5, 5)) Interval(2, 5) >>> continuous_domain(log(2*x - 1), x, S.Reals) Interval(1/2, oo, True, True) """ from sympy.solvers.inequalities import solve_univariate_inequality from sympy.solvers.solveset import solveset, _has_rational_power if domain.is_subset(S.Reals): constrained_interval = domain for atom in f.atoms(Pow): predicate, denom = _has_rational_power(atom, symbol) constraint = S.EmptySet if predicate and denom == 2: constraint = solve_univariate_inequality(atom.base >= 0, symbol).as_set() constrained_interval = Intersection(constraint, constrained_interval) for atom in f.atoms(log): constraint = solve_univariate_inequality(atom.args[0] > 0, symbol).as_set() constrained_interval = Intersection(constraint, constrained_interval) domain = constrained_interval try: sings = S.EmptySet if f.has(Abs): sings = solveset(1/f, symbol, domain) else: for atom in f.atoms(Pow): predicate, denom = _has_rational_power(atom, symbol) if predicate and denom == 2: sings = solveset(1/f, symbol, domain) break else: sings = Intersection(solveset(1/f, symbol), domain) except: raise NotImplementedError("Methods for determining the continuous domains" " of this function have not been developed.") return domain - sings
def is_convergent(self): r"""Checks for the convergence of a Sum. We divide the study of convergence of infinite sums and products in two parts. First Part: One part is the question whether all the terms are well defined, i.e., they are finite in a sum and also non-zero in a product. Zero is the analogy of (minus) infinity in products as :math:`e^{-\infty} = 0`. Second Part: The second part is the question of convergence after infinities, and zeros in products, have been omitted assuming that their number is finite. This means that we only consider the tail of the sum or product, starting from some point after which all terms are well defined. For example, in a sum of the form: .. math:: \sum_{1 \leq i < \infty} \frac{1}{n^2 + an + b} where a and b are numbers. The routine will return true, even if there are infinities in the term sequence (at most two). An analogous product would be: .. math:: \prod_{1 \leq i < \infty} e^{\frac{1}{n^2 + an + b}} This is how convergence is interpreted. It is concerned with what happens at the limit. Finding the bad terms is another independent matter. Note: It is responsibility of user to see that the sum or product is well defined. There are various tests employed to check the convergence like divergence test, root test, integral test, alternating series test, comparison tests, Dirichlet tests. It returns true if Sum is convergent and false if divergent and NotImplementedError if it can not be checked. References ========== .. [1] https://en.wikipedia.org/wiki/Convergence_tests Examples ======== >>> from sympy import factorial, S, Sum, Symbol, oo >>> n = Symbol('n', integer=True) >>> Sum(n/(n - 1), (n, 4, 7)).is_convergent() True >>> Sum(n/(2*n + 1), (n, 1, oo)).is_convergent() False >>> Sum(factorial(n)/5**n, (n, 1, oo)).is_convergent() False >>> Sum(1/n**(S(6)/5), (n, 1, oo)).is_convergent() True See Also ======== Sum.is_absolutely_convergent() Product.is_convergent() """ from sympy import Interval, Integral, log, symbols, simplify p, q, r = symbols('p q r', cls=Wild) sym = self.limits[0][0] lower_limit = self.limits[0][1] upper_limit = self.limits[0][2] sequence_term = self.function if len(sequence_term.free_symbols) > 1: raise NotImplementedError("convergence checking for more than one symbol " "containing series is not handled") if lower_limit.is_finite and upper_limit.is_finite: return S.true # transform sym -> -sym and swap the upper_limit = S.Infinity # and lower_limit = - upper_limit if lower_limit is S.NegativeInfinity: if upper_limit is S.Infinity: return Sum(sequence_term, (sym, 0, S.Infinity)).is_convergent() and \ Sum(sequence_term, (sym, S.NegativeInfinity, 0)).is_convergent() sequence_term = simplify(sequence_term.xreplace({sym: -sym})) lower_limit = -upper_limit upper_limit = S.Infinity sym_ = Dummy(sym.name, integer=True, positive=True) sequence_term = sequence_term.xreplace({sym: sym_}) sym = sym_ interval = Interval(lower_limit, upper_limit) # Piecewise function handle if sequence_term.is_Piecewise: for func, cond in sequence_term.args: # see if it represents something going to oo if cond == True or cond.as_set().sup is S.Infinity: s = Sum(func, (sym, lower_limit, upper_limit)) return s.is_convergent() return S.true ### -------- Divergence test ----------- ### try: lim_val = limit_seq(sequence_term, sym) if lim_val is not None and lim_val.is_zero is False: return S.false except NotImplementedError: pass try: lim_val_abs = limit_seq(abs(sequence_term), sym) if lim_val_abs is not None and lim_val_abs.is_zero is False: return S.false except NotImplementedError: pass order = O(sequence_term, (sym, S.Infinity)) ### --------- p-series test (1/n**p) ---------- ### p1_series_test = order.expr.match(sym**p) if p1_series_test is not None: if p1_series_test[p] < -1: return S.true if p1_series_test[p] >= -1: return S.false p2_series_test = order.expr.match((1/sym)**p) if p2_series_test is not None: if p2_series_test[p] > 1: return S.true if p2_series_test[p] <= 1: return S.false ### ------------- comparison test ------------- ### # 1/(n**p*log(n)**q*log(log(n))**r) comparison n_log_test = order.expr.match(1/(sym**p*log(sym)**q*log(log(sym))**r)) if n_log_test is not None: if (n_log_test[p] > 1 or (n_log_test[p] == 1 and n_log_test[q] > 1) or (n_log_test[p] == n_log_test[q] == 1 and n_log_test[r] > 1)): return S.true return S.false ### ------------- Limit comparison test -----------### # (1/n) comparison try: lim_comp = limit_seq(sym*sequence_term, sym) if lim_comp is not None and lim_comp.is_number and lim_comp > 0: return S.false except NotImplementedError: pass ### ----------- ratio test ---------------- ### next_sequence_term = sequence_term.xreplace({sym: sym + 1}) ratio = combsimp(powsimp(next_sequence_term/sequence_term)) try: lim_ratio = limit_seq(ratio, sym) if lim_ratio is not None and lim_ratio.is_number: if abs(lim_ratio) > 1: return S.false if abs(lim_ratio) < 1: return S.true except NotImplementedError: pass ### ----------- root test ---------------- ### # lim = Limit(abs(sequence_term)**(1/sym), sym, S.Infinity) try: lim_evaluated = limit_seq(abs(sequence_term)**(1/sym), sym) if lim_evaluated is not None and lim_evaluated.is_number: if lim_evaluated < 1: return S.true if lim_evaluated > 1: return S.false except NotImplementedError: pass ### ------------- alternating series test ----------- ### dict_val = sequence_term.match((-1)**(sym + p)*q) if not dict_val[p].has(sym) and is_decreasing(dict_val[q], interval): return S.true ### ------------- integral test -------------- ### check_interval = None maxima = solveset(sequence_term.diff(sym), sym, interval) if not maxima: check_interval = interval elif isinstance(maxima, FiniteSet) and maxima.sup.is_number: check_interval = Interval(maxima.sup, interval.sup) if (check_interval is not None and (is_decreasing(sequence_term, check_interval) or is_decreasing(-sequence_term, check_interval))): integral_val = Integral( sequence_term, (sym, lower_limit, upper_limit)) try: integral_val_evaluated = integral_val.doit() if integral_val_evaluated.is_number: return S(integral_val_evaluated.is_finite) except NotImplementedError: pass ### ----- Dirichlet and bounded times convergent tests ----- ### # TODO # # Dirichlet_test # https://en.wikipedia.org/wiki/Dirichlet%27s_test # # Bounded times convergent test # It is based on comparison theorems for series. # In particular, if the general term of a series can # be written as a product of two terms a_n and b_n # and if a_n is bounded and if Sum(b_n) is absolutely # convergent, then the original series Sum(a_n * b_n) # is absolutely convergent and so convergent. # # The following code can grows like 2**n where n is the # number of args in order.expr # Possibly combined with the potentially slow checks # inside the loop, could make this test extremely slow # for larger summation expressions. if order.expr.is_Mul: args = order.expr.args argset = set(args) ### -------------- Dirichlet tests -------------- ### m = Dummy('m', integer=True) def _dirichlet_test(g_n): try: ing_val = limit_seq(Sum(g_n, (sym, interval.inf, m)).doit(), m) if ing_val is not None and ing_val.is_finite: return S.true except NotImplementedError: pass ### -------- bounded times convergent test ---------### def _bounded_convergent_test(g1_n, g2_n): try: lim_val = limit_seq(g1_n, sym) if lim_val is not None and (lim_val.is_finite or ( isinstance(lim_val, AccumulationBounds) and (lim_val.max - lim_val.min).is_finite)): if Sum(g2_n, (sym, lower_limit, upper_limit)).is_absolutely_convergent(): return S.true except NotImplementedError: pass for n in range(1, len(argset)): for a_tuple in itertools.combinations(args, n): b_set = argset - set(a_tuple) a_n = Mul(*a_tuple) b_n = Mul(*b_set) if is_decreasing(a_n, interval): dirich = _dirichlet_test(b_n) if dirich is not None: return dirich bc_test = _bounded_convergent_test(a_n, b_n) if bc_test is not None: return bc_test _sym = self.limits[0][0] sequence_term = sequence_term.xreplace({sym: _sym}) raise NotImplementedError("The algorithm to find the Sum convergence of %s " "is not yet implemented" % (sequence_term))
def test_simplification(): eq = x + (a - b) / (-2 * a + 2 * b) assert solveset(eq, x) == FiniteSet(S.Half) assert solveset(eq, x, S.Reals) == FiniteSet(S.Half)
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_10555(): f = Function('f') assert solveset(f(x) - pi/2, x, S.Reals) == \ ConditionSet(x, Eq(2*f(x) - pi, 0), S.Reals)