def _set_function(f, x): from sympy.sets.sets import is_function_invertible_in_set # If the function is invertible, intersect the maps of the sets. if is_function_invertible_in_set(f, x): return Intersection(imageset(f, arg) for arg in x.args) else: return ImageSet(Lambda(_x, f(_x)), x)
def _set_function(f, x): from sympy.sets.sets import is_function_invertible_in_set # If the function is invertible, intersect the maps of the sets. if is_function_invertible_in_set(f, x): return Intersection(*(imageset(f, arg) for arg in x.args)) else: return ImageSet(Lambda(_x, f(_x)), x)
def _solve_as_poly(f, symbol, solveset_solver, invert_func): """ Solve the equation using polynomial techniques if it already is a polynomial equation or, with a change of variables, can be made so. """ result = None if f.is_polynomial(symbol): solns = roots(f, symbol, cubics=True, quartics=True, quintics=True, domain='EX') num_roots = sum(solns.values()) if degree(f, symbol) <= num_roots: result = FiniteSet(*solns.keys()) else: poly = Poly(f, symbol) solns = poly.all_roots() if poly.degree() <= len(solns): result = FiniteSet(*solns) else: result = ConditionSet(symbol, Eq(f, 0), S.Complexes) else: poly = Poly(f) if poly is None: result = ConditionSet(symbol, Eq(f, 0), S.Complexes) gens = [g for g in poly.gens if g.has(symbol)] if len(gens) == 1: poly = Poly(poly, gens[0]) gen = poly.gen deg = poly.degree() poly = Poly(poly.as_expr(), poly.gen, composite=True) poly_solns = FiniteSet(*roots(poly, cubics=True, quartics=True, quintics=True).keys()) if len(poly_solns) < deg: result = ConditionSet(symbol, Eq(f, 0), S.Complexes) if gen != symbol: y = Dummy('y') lhs, rhs_s = invert_func(gen, y, symbol) if lhs is symbol: result = Union(*[rhs_s.subs(y, s) for s in poly_solns]) else: result = ConditionSet(symbol, Eq(f, 0), S.Complexes) else: result = ConditionSet(symbol, Eq(f, 0), S.Complexes) if result is not None: if isinstance(result, FiniteSet): # this is to simplify solutions like -sqrt(-I) to sqrt(2)/2 # - sqrt(2)*I/2. We are not expanding for solution with free # variables because that makes the solution more complicated. For # example expand_complex(a) returns re(a) + I*im(a) if all([s.free_symbols == set() and not isinstance(s, RootOf) for s in result]): s = Dummy('s') result = imageset(Lambda(s, expand_complex(s)), result) return result else: return ConditionSet(symbol, Eq(f, 0), S.Complexes)
def _solve_as_poly(f, symbol, solveset_solver, invert_func): """ Solve the equation using polynomial techniques if it already is a polynomial equation or, with a change of variables, can be made so. """ result = None if f.is_polynomial(symbol): solns = roots(f, symbol, cubics=True, quartics=True, quintics=True, domain='EX') num_roots = sum(solns.values()) if degree(f, symbol) <= num_roots: result = FiniteSet(*solns.keys()) else: poly = Poly(f, symbol) solns = poly.all_roots() if poly.degree() <= len(solns): result = FiniteSet(*solns) else: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) else: poly = Poly(f) if poly is None: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) gens = [g for g in poly.gens if g.has(symbol)] if len(gens) == 1: poly = Poly(poly, gens[0]) gen = poly.gen deg = poly.degree() poly = Poly(poly.as_expr(), poly.gen, composite=True) poly_solns = FiniteSet(*roots(poly, cubics=True, quartics=True, quintics=True).keys()) if len(poly_solns) < deg: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) if gen != symbol: y = Dummy('y') lhs, rhs_s = invert_func(gen, y, symbol) if lhs is symbol: result = Union(*[rhs_s.subs(y, s) for s in poly_solns]) else: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) else: result = ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes) if result is not None: if isinstance(result, FiniteSet): # this is to simplify solutions like -sqrt(-I) to sqrt(2)/2 # - sqrt(2)*I/2. We are not expanding for solution with free # variables because that makes the solution more complicated. For # example expand_complex(a) returns re(a) + I*im(a) if all([s.free_symbols == set() and not isinstance(s, RootOf) for s in result]): s = Dummy('s') result = imageset(Lambda(s, expand_complex(s)), result) return result else: return ConditionSet(Lambda(symbol, Eq(f, 0)), S.Complexes)
def _invert_complex(f, g_ys, symbol): """ Helper function for invert_complex """ if not f.has(symbol): raise ValueError("Inverse of constant function doesn't exist") if f is symbol: return (f, g_ys) n = Dummy('n') if f.is_Add: # f = g + h g, h = f.as_independent(symbol) if g != S.Zero: return _invert_complex(h, imageset(Lambda(n, n - g), g_ys), symbol) if f.is_Mul: # f = g*h g, h = f.as_independent(symbol) if g != S.One: return _invert_complex(h, imageset(Lambda(n, n / g), g_ys), symbol) if hasattr(f, 'inverse') and \ not isinstance(f, TrigonometricFunction) and \ not isinstance(f, exp): if len(f.args) > 1: raise ValueError("Only functions with one argument are supported.") return _invert_complex(f.args[0], imageset(Lambda(n, f.inverse()(n)), g_ys), symbol) if isinstance(f, exp): if isinstance(g_ys, FiniteSet): exp_invs = Union(*[ imageset( Lambda(n, I * (2 * n * pi + arg(g_y)) + log(Abs(g_y))), S.Integers) for g_y in g_ys if g_y != 0 ]) return _invert_complex(f.args[0], exp_invs, symbol) return (f, g_ys)
def _invert_complex(f, g_ys, symbol): """Helper function for _invert.""" if f == symbol: return (f, g_ys) n = Dummy("n") if f.is_Add: # f = g + h g, h = f.as_independent(symbol) if g is not S.Zero: return _invert_complex(h, imageset(Lambda(n, n - g), g_ys), symbol) if f.is_Mul: # f = g*h g, h = f.as_independent(symbol) if g is not S.One: return _invert_complex(h, imageset(Lambda(n, n / g), g_ys), symbol) if hasattr(f, "inverse") and not isinstance(f, TrigonometricFunction) and not isinstance(f, exp): if len(f.args) > 1: raise ValueError("Only functions with one argument are supported.") return _invert_complex(f.args[0], imageset(Lambda(n, f.inverse()(n)), g_ys), symbol) if isinstance(f, exp): if isinstance(g_ys, FiniteSet): exp_invs = Union( *[ imageset(Lambda(n, I * (2 * n * pi + arg(g_y)) + log(Abs(g_y))), S.Integers) for g_y in g_ys if g_y != 0 ] ) return _invert_complex(f.args[0], exp_invs, symbol) return (f, g_ys)
def _invert_complex(f, g_ys, symbol): """ Helper function for invert_complex """ if not f.has(symbol): raise ValueError("Inverse of constant function doesn't exist") if f is symbol: return (f, g_ys) n = Dummy('n') if f.is_Add: # f = g + h g, h = f.as_independent(symbol) if g != S.Zero: return _invert_complex(h, imageset(Lambda(n, n - g), g_ys), symbol) if f.is_Mul: # f = g*h g, h = f.as_independent(symbol) if g != S.One: return _invert_complex(h, imageset(Lambda(n, n/g), g_ys), symbol) if hasattr(f, 'inverse') and \ not isinstance(f, C.TrigonometricFunction) and \ not isinstance(f, exp): if len(f.args) > 1: raise ValueError("Only functions with one argument are supported.") return _invert_complex(f.args[0], imageset(Lambda(n, f.inverse()(n)), g_ys), symbol) if isinstance(f, exp): if isinstance(g_ys, FiniteSet): exp_invs = Union(*[imageset(Lambda(n, I*(2*n*pi + arg(g_y)) + log(Abs(g_y))), S.Integers) for g_y in g_ys]) return _invert_complex(f.args[0], exp_invs, symbol) return (f, g_ys)
def _solve_radical(f, symbol, solveset_solver): """ Helper function to solve equations with radicals """ eq, cov = unrad(f) if not cov: result = solveset_solver(eq, symbol) - Union(*[solveset_solver(g, symbol) for g in denoms(f, [symbol])]) else: y, yeq = cov if not solveset_solver(y - I, y): yreal = Dummy("yreal", real=True) yeq = yeq.xreplace({y: yreal}) eq = eq.xreplace({y: yreal}) y = yreal g_y_s = solveset_solver(yeq, symbol) f_y_sols = solveset_solver(eq, y) result = Union(*[imageset(Lambda(y, g_y), f_y_sols) for g_y in g_y_s]) return FiniteSet(*[s for s in result if checksol(f, symbol, s) is True])
def _solve_radical(f, symbol, solveset_solver): """ Helper function to solve equations with radicals """ eq, cov = unrad(f) if not cov: result = solveset_solver(eq, symbol) - \ Union(*[solveset_solver(g, symbol) for g in denoms(f, [symbol])]) else: y, yeq = cov if not solveset_solver(y - I, y): yreal = Dummy('yreal', real=True) yeq = yeq.xreplace({y: yreal}) eq = eq.xreplace({y: yreal}) y = yreal g_y_s = solveset_solver(yeq, symbol) f_y_sols = solveset_solver(eq, y) result = Union(*[imageset(Lambda(y, g_y), f_y_sols) for g_y in g_y_s]) return FiniteSet(*[s for s in result if checksol(f, symbol, s) is True])
def _solve_radical(f, symbol, solveset_solver): """ Helper function to solve equations with radicals """ from sympy.solvers.solvers import unrad try: eq, cov, dens = unrad(f) if cov == []: result = solveset_solver(eq, symbol) - \ Union(*[solveset_solver(g, symbol) for g in dens]) else: if len(cov) > 1: raise NotImplementedError("Multivariate solver is " "not implemented.") else: y = cov[0][0] g_y_s = solveset_solver(cov[0][1], symbol) f_y_sols = solveset_solver(eq, y) result = Union(*[imageset(Lambda(y, g_y), f_y_sols) for g_y in g_y_s]) return FiniteSet(*[s for s in result if checksol(f, symbol, s) is True]) except ValueError: raise NotImplementedError
def _set_function(f, self): # noqa:F811 if not self: return S.EmptySet if not isinstance(f.expr, Expr): return if self.size == 1: return FiniteSet(f(self[0])) if f is S.IdentityFunction: return self x = f.variables[0] expr = f.expr # handle f that is linear in f's variable if x not in expr.free_symbols or x in expr.diff(x).free_symbols: return if self.start.is_finite: F = f(self.step * x + self.start) # for i in range(len(self)) else: F = f(-self.step * x + self[-1]) F = expand_mul(F) if F != expr: return imageset(x, F, Range(self.size))
def _set_function(f, self): from sympy.core.function import expand_mul if not self: return S.EmptySet if not isinstance(f.expr, Expr): return if self.size == 1: return FiniteSet(f(self[0])) if f is S.IdentityFunction: return self x = f.variables[0] expr = f.expr # handle f that is linear in f's variable if x not in expr.free_symbols or x in expr.diff(x).free_symbols: return if self.start.is_finite: F = f(self.step*x + self.start) # for i in range(len(self)) else: F = f(-self.step*x + self[-1]) F = expand_mul(F) if F != expr: return imageset(x, F, Range(self.size))
def _solve_radical(f, symbol, solveset_solver): """ Helper function to solve equations with radicals """ from sympy.solvers.solvers import unrad try: eq, cov, dens = unrad(f) if cov == []: result = solveset_solver(eq, symbol) - \ Union(*[solveset_solver(g, symbol) for g in dens]) else: if len(cov) > 1: raise NotImplementedError("Multivariate solver is " "not implemented.") else: y = cov[0][0] g_y_s = solveset_solver(cov[0][1], symbol) f_y_sols = solveset_solver(eq, y) result = Union( *[imageset(Lambda(y, g_y), f_y_sols) for g_y in g_y_s]) return FiniteSet( *[s for s in result if checksol(f, symbol, s) is True]) except ValueError: raise NotImplementedError
def _set_function(f, x): return Union(*(imageset(f, arg) for arg in x.args))
def _invert_real(f, g_ys, symbol): """ Helper function for invert_real """ if not f.has(symbol): raise ValueError("Inverse of constant function doesn't exist") if f is symbol: return (f, g_ys) n = Dummy('n') if hasattr(f, 'inverse') and not isinstance(f, TrigonometricFunction) and \ not isinstance(f, HyperbolicFunction): if len(f.args) > 1: raise ValueError("Only functions with one argument are supported.") return _invert_real(f.args[0], imageset(Lambda(n, f.inverse()(n)), g_ys), symbol) if isinstance(f, Abs): return _invert_real( f.args[0], Union( imageset(Lambda(n, n), g_ys).intersect(Interval(0, oo)), imageset(Lambda(n, -n), g_ys).intersect(Interval(-oo, 0))), symbol) if f.is_Add: # f = g + h g, h = f.as_independent(symbol) if g != S.Zero: return _invert_real(h, imageset(Lambda(n, n - g), g_ys), symbol) if f.is_Mul: # f = g*h g, h = f.as_independent(symbol) if g != S.One: return _invert_real(h, imageset(Lambda(n, n / g), g_ys), symbol) if f.is_Pow: base, expo = f.args base_has_sym = base.has(symbol) expo_has_sym = expo.has(symbol) if not expo_has_sym: res = imageset(Lambda(n, real_root(n, expo)), g_ys) if expo.is_rational: numer, denom = expo.as_numer_denom() if numer == S.One or numer == -S.One: return _invert_real(base, res, symbol) else: if numer % 2 == 0: n = Dummy('n') neg_res = imageset(Lambda(n, -n), res) return _invert_real(base, res + neg_res, symbol) else: return _invert_real(base, res, symbol) else: if not base.is_positive: raise ValueError("x**w where w is irrational is not " "defined for negative x") return _invert_real(base, res, symbol) if not base_has_sym: return _invert_real(expo, imageset(Lambda(n, log(n) / log(base)), g_ys), symbol) if isinstance(f, sin): n = Dummy('n') if isinstance(g_ys, FiniteSet): sin_invs = Union(*[imageset(Lambda(n, n*pi + (-1)**n*asin(g_y)), \ S.Integers) for g_y in g_ys]) return _invert_real(f.args[0], sin_invs, symbol) if isinstance(f, csc): n = Dummy('n') if isinstance(g_ys, FiniteSet): csc_invs = Union(*[imageset(Lambda(n, n*pi + (-1)**n*acsc(g_y)), \ S.Integers) for g_y in g_ys]) return _invert_real(f.args[0], csc_invs, symbol) if isinstance(f, cos): n = Dummy('n') if isinstance(g_ys, FiniteSet): cos_invs_f1 = Union(*[imageset(Lambda(n, 2*n*pi + acos(g_y)), \ S.Integers) for g_y in g_ys]) cos_invs_f2 = Union(*[imageset(Lambda(n, 2*n*pi - acos(g_y)), \ S.Integers) for g_y in g_ys]) cos_invs = Union(cos_invs_f1, cos_invs_f2) return _invert_real(f.args[0], cos_invs, symbol) if isinstance(f, sec): n = Dummy('n') if isinstance(g_ys, FiniteSet): sec_invs_f1 = Union(*[imageset(Lambda(n, 2*n*pi + asec(g_y)), \ S.Integers) for g_y in g_ys]) sec_invs_f2 = Union(*[imageset(Lambda(n, 2*n*pi - asec(g_y)), \ S.Integers) for g_y in g_ys]) sec_invs = Union(sec_invs_f1, sec_invs_f2) return _invert_real(f.args[0], sec_invs, symbol) if isinstance(f, tan) or isinstance(f, cot): n = Dummy('n') if isinstance(g_ys, FiniteSet): tan_cot_invs = Union(*[imageset(Lambda(n, n*pi + f.inverse()(g_y)), \ S.Integers) for g_y in g_ys]) return _invert_real(f.args[0], tan_cot_invs, symbol) return (f, g_ys)
def _(f, x): return Union(*(imageset(f, arg) for arg in x.args))
def _set_function(f, x): from sympy.functions.elementary.miscellaneous import Min, Max from sympy.solvers.solveset import solveset from sympy.core.function import diff, Lambda from sympy.series import limit from sympy.calculus.singularities import singularities from sympy.sets import Complement # TODO: handle functions with infinitely many solutions (eg, sin, tan) # TODO: handle multivariate functions expr = f.expr if len(expr.free_symbols) > 1 or len(f.variables) != 1: return var = f.variables[0] if expr.is_Piecewise: result = S.EmptySet domain_set = x for (p_expr, p_cond) in expr.args: if p_cond is true: intrvl = domain_set else: intrvl = p_cond.as_set() intrvl = Intersection(domain_set, intrvl) if p_expr.is_Number: image = FiniteSet(p_expr) else: image = imageset(Lambda(var, p_expr), intrvl) result = Union(result, image) # remove the part which has been `imaged` domain_set = Complement(domain_set, intrvl) if domain_set.is_EmptySet: break return result if not x.start.is_comparable or not x.end.is_comparable: return try: sing = [i for i in singularities(expr, var) if i.is_real and i in x] except NotImplementedError: return if x.left_open: _start = limit(expr, var, x.start, dir="+") elif x.start not in sing: _start = f(x.start) if x.right_open: _end = limit(expr, var, x.end, dir="-") elif x.end not in sing: _end = f(x.end) if len(sing) == 0: solns = list(solveset(diff(expr, var), var)) extr = [_start, _end] + [f(i) for i in solns if i.is_real and i in x] start, end = Min(*extr), Max(*extr) left_open, right_open = False, False if _start <= _end: # the minimum or maximum value can occur simultaneously # on both the edge of the interval and in some interior # point if start == _start and start not in solns: left_open = x.left_open if end == _end and end not in solns: right_open = x.right_open else: if start == _end and start not in solns: left_open = x.right_open if end == _start and end not in solns: right_open = x.left_open return Interval(start, end, left_open, right_open) else: return imageset(f, Interval(x.start, sing[0], x.left_open, True)) + \ Union(*[imageset(f, Interval(sing[i], sing[i + 1], True, True)) for i in range(0, len(sing) - 1)]) + \ imageset(f, Interval(sing[-1], x.end, True, x.right_open))
def _set_function(f, x): return Union(imageset(f, arg) for arg in x.args)
def _invert_real(f, g_ys, symbol): """ Helper function for invert_real """ if not f.has(symbol): raise ValueError("Inverse of constant function doesn't exist") if f is symbol: return (f, g_ys) n = Dummy('n') if hasattr(f, 'inverse') and not isinstance(f, C.TrigonometricFunction): if len(f.args) > 1: raise ValueError("Only functions with one argument are supported.") return _invert_real(f.args[0], imageset(Lambda(n, f.inverse()(n)), g_ys), symbol) if isinstance(f, Abs): return _invert_real(f.args[0], Union(g_ys, imageset(Lambda(n, -n), g_ys)), symbol) if f.is_Add: # f = g + h g, h = f.as_independent(symbol) if g != S.Zero: return _invert_real(h, imageset(Lambda(n, n - g), g_ys), symbol) if f.is_Mul: # f = g*h g, h = f.as_independent(symbol) if g != S.One: return _invert_real(h, imageset(Lambda(n, n/g), g_ys), symbol) if f.is_Pow: base, expo = f.args base_has_sym = base.has(symbol) expo_has_sym = expo.has(symbol) if not expo_has_sym: res = imageset(Lambda(n, Pow(n, 1/expo)), g_ys) if expo.is_rational: numer, denom = expo.as_numer_denom() if numer == S.One or numer == - S.One: return _invert_real(base, res, symbol) else: if numer % 2 == 0: n = Dummy('n') neg_res = imageset(Lambda(n, -n), res) return _invert_real(base, res + neg_res, symbol) else: return _invert_real(base, res, symbol) else: if not base.is_positive: raise ValueError("x**w where w is irrational is not" "defined for negative x") return _invert_real(base, res, symbol) if not base_has_sym: return _invert_real(expo, imageset(Lambda(n, log(n)/log(base)), g_ys), symbol) if isinstance(f, tan) or isinstance(f, cot): n = Dummy('n') if isinstance(g_ys, FiniteSet): tan_cot_invs = Union(*[imageset(Lambda(n, n*pi + f.inverse()(g_y)), S.Integers) for g_y in g_ys]) return _invert_real(f.args[0], tan_cot_invs, symbol) return (f, g_ys)
def _invert_real(f, g_ys, symbol): """ Helper function for invert_real """ if not f.has(symbol): raise ValueError("Inverse of constant function doesn't exist") if f is symbol: return (f, g_ys) n = Dummy('n') if hasattr(f, 'inverse') and not isinstance(f, TrigonometricFunction): if len(f.args) > 1: raise ValueError("Only functions with one argument are supported.") return _invert_real(f.args[0], imageset(Lambda(n, f.inverse()(n)), g_ys), symbol) if isinstance(f, Abs): g_ys = g_ys - FiniteSet(*[g_y for g_y in g_ys if g_y.is_negative]) return _invert_real(f.args[0], Union(g_ys, imageset(Lambda(n, -n), g_ys)), symbol) if f.is_Add: # f = g + h g, h = f.as_independent(symbol) if g != S.Zero: return _invert_real(h, imageset(Lambda(n, n - g), g_ys), symbol) if f.is_Mul: # f = g*h g, h = f.as_independent(symbol) if g != S.One: return _invert_real(h, imageset(Lambda(n, n / g), g_ys), symbol) if f.is_Pow: base, expo = f.args base_has_sym = base.has(symbol) expo_has_sym = expo.has(symbol) if not expo_has_sym: res = imageset(Lambda(n, Pow(n, 1 / expo)), g_ys) if expo.is_rational: numer, denom = expo.as_numer_denom() if numer == S.One or numer == -S.One: return _invert_real(base, res, symbol) else: if numer % 2 == 0: n = Dummy('n') neg_res = imageset(Lambda(n, -n), res) return _invert_real(base, res + neg_res, symbol) else: return _invert_real(base, res, symbol) else: if not base.is_positive: raise ValueError("x**w where w is irrational is not " "defined for negative x") return _invert_real(base, res, symbol) if not base_has_sym: return _invert_real(expo, imageset(Lambda(n, log(n) / log(base)), g_ys), symbol) if isinstance(f, tan) or isinstance(f, cot): n = Dummy('n') if isinstance(g_ys, FiniteSet): tan_cot_invs = Union(*[ imageset(Lambda(n, n * pi + f.inverse()(g_y)), S.Integers) for g_y in g_ys ]) return _invert_real(f.args[0], tan_cot_invs, symbol) return (f, g_ys)
def _set_function(f, x): # noqa:F811 return Union(*(imageset(f, arg) for arg in x.args))
def _set_function(f, x): # noqa:F811 # If the function is invertible, intersect the maps of the sets. if is_function_invertible_in_set(f, x): return Intersection(*(imageset(f, arg) for arg in x.args)) else: return ImageSet(Lambda(_x, f(_x)), x)
def _invert_real(f, g_ys, symbol): """Helper function for _invert.""" if f == symbol: return (f, g_ys) n = Dummy('n', real=True) if hasattr(f, 'inverse') and not isinstance(f, ( TrigonometricFunction, HyperbolicFunction, )): if len(f.args) > 1: raise ValueError("Only functions with one argument are supported.") return _invert_real(f.args[0], imageset(Lambda(n, f.inverse()(n)), g_ys), symbol) if isinstance(f, Abs): pos = Interval(0, S.Infinity) neg = Interval(S.NegativeInfinity, 0) return _invert_real(f.args[0], Union(imageset(Lambda(n, n), g_ys).intersect(pos), imageset(Lambda(n, -n), g_ys).intersect(neg)), symbol) if f.is_Add: # f = g + h g, h = f.as_independent(symbol) if g is not S.Zero: return _invert_real(h, imageset(Lambda(n, n - g), g_ys), symbol) if f.is_Mul: # f = g*h g, h = f.as_independent(symbol) if g is not S.One: return _invert_real(h, imageset(Lambda(n, n/g), g_ys), symbol) if f.is_Pow: base, expo = f.args base_has_sym = base.has(symbol) expo_has_sym = expo.has(symbol) if not expo_has_sym: res = imageset(Lambda(n, real_root(n, expo)), g_ys) if expo.is_rational: numer, denom = expo.as_numer_denom() if numer == S.One or numer == - S.One: return _invert_real(base, res, symbol) else: if numer % 2 == 0: n = Dummy('n') neg_res = imageset(Lambda(n, -n), res) return _invert_real(base, res + neg_res, symbol) else: return _invert_real(base, res, symbol) else: if not base.is_positive: raise ValueError("x**w where w is irrational is not " "defined for negative x") return _invert_real(base, res, symbol) if not base_has_sym: return _invert_real(expo, imageset(Lambda(n, log(n)/log(base)), g_ys), symbol) if isinstance(f, TrigonometricFunction): if isinstance(g_ys, FiniteSet): def inv(trig): if isinstance(f, (sin, csc)): F = asin if isinstance(f, sin) else acsc return (lambda a: n*pi + (-1)**n*F(a),) if isinstance(f, (cos, sec)): F = acos if isinstance(f, cos) else asec return ( lambda a: 2*n*pi + F(a), lambda a: 2*n*pi - F(a),) if isinstance(f, (tan, cot)): return (lambda a: n*pi + f.inverse()(a),) n = Dummy('n', integer=True) invs = S.EmptySet for L in inv(f): invs += Union(*[imageset(Lambda(n, L(g)), S.Integers) for g in g_ys]) return _invert_real(f.args[0], invs, symbol) return (f, g_ys)
def function_sets(f, x): return Union(imageset(f, arg) for arg in x.args)