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 _solve_abs(f, symbol, domain): """ Helper function to solve equation involving absolute value function """ if not domain.is_subset(S.Reals): raise ValueError( filldedent(''' Absolute values cannot be inverted in the complex domain.''')) p, q, r = Wild('p'), Wild('q'), Wild('r') pattern_match = f.match(p * Abs(q) + r) or {} if not pattern_match.get(p, S.Zero).is_zero: f_p, f_q, f_r = pattern_match[p], pattern_match[q], pattern_match[r] q_pos_cond = solve_univariate_inequality(f_q >= 0, symbol, relational=False) q_neg_cond = solve_univariate_inequality(f_q < 0, symbol, relational=False) sols_q_pos = solveset_real(f_p * f_q + f_r, symbol).intersect(q_pos_cond) sols_q_neg = solveset_real(f_p * (-f_q) + f_r, symbol).intersect(q_neg_cond) return Union(sols_q_pos, sols_q_neg) else: return ConditionSet(symbol, Eq(f, 0), domain)
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 draw_curve_plotly(curve: _ParametricCurve, num=50, domain=(-1, 1), exist_range=[(None, None), (None, None), (None, None)], color_func=(lambda curve: curve.curvature().simplify()), fig=None, line=dict(width=4, showscale=True), mode="lines", *arg, **kwarg): from numpy import linspace from sympy import lambdify, Interval from sympy.sets.sets import Union from sympy.solvers.inequalities import solve_univariate_inequality import plotly.graph_objects as go domain = Interval(*domain).intersect(Interval(*curve.sym_limit(0))) for i, lim in enumerate(exist_range): if lim[0] is not None: domain = solve_univariate_inequality(lim[0] < curve.expr(i), curve.sym(0), relational=False, domain=domain) if lim[1] is not None: domain = solve_univariate_inequality(lim[1] > curve.expr(i), curve.sym(0), relational=False, domain=domain) if isinstance(domain, Union): domain = domain.args[0] domain_ = linspace(float(domain.start), float(domain.end), num=num) values_ = lambdify(curve.sym(0), curve.expr(), 'numpy')(domain_) if color_func is not None: colors_ = lambdify(curve.sym(0), color_func(curve), 'numpy')(domain_) kwarg['x'] = values_[0] kwarg['y'] = values_[1] kwarg['z'] = values_[2] kwarg['line'] = line if color_func is not None: kwarg['line']['color'] = colors_ kwarg['mode'] = mode if fig is None: fig = go.Figure(data=go.Scatter3d(*arg, **kwarg)) else: fig.add_trace(go.Scatter3d(*arg, **kwarg)) fig.update_layout( scene=dict(aspectratio=dict(x=1, y=1, z=1), aspectmode='data')) return fig
def _eval_as_set(self): # self is univariate and periodicity(self, x) in (0, None) from sympy.solvers.inequalities import solve_univariate_inequality syms = self.free_symbols assert len(syms) == 1 x = syms.pop() return solve_univariate_inequality(self, x, relational=False)
def as_set(self): """ Rewrites univariate inequality in terms of real sets Examples ======== >>> from sympy import Symbol, Eq >>> x = Symbol('x', real=True) >>> (x > 0).as_set() Interval.open(0, oo) >>> Eq(x, 0).as_set() {0} """ from sympy.solvers.inequalities import solve_univariate_inequality syms = self.free_symbols if len(syms) == 1: sym = syms.pop() else: raise NotImplementedError("Sorry, Relational.as_set procedure" " is not yet implemented for" " multivariate expressions") return solve_univariate_inequality(self, sym, relational=False)
def _solve_abs(f, symbol): """ Helper function to solve equation involving absolute value function """ p, q, r = Wild('p'), Wild('q'), Wild('r') pattern_match = f.match(p*Abs(q) + r) or {} if not pattern_match.get(p, S.Zero).is_zero: f_p, f_q, f_r = pattern_match[p], pattern_match[q], pattern_match[r] q_pos_cond = solve_univariate_inequality(f_q >= 0, symbol, relational=False) q_neg_cond = solve_univariate_inequality(f_q < 0, symbol, relational=False) sols_q_pos = solveset_real(f_p*f_q + f_r, symbol).intersect(q_pos_cond) sols_q_neg = solveset_real(f_p*(-f_q) + f_r, symbol).intersect(q_neg_cond) return Union(sols_q_pos, sols_q_neg) else: return ConditionSet(symbol, Eq(f, 0), S.Complexes)
def _solve_abs(f, symbol): """ Helper function to solve equation involving absolute value function """ from sympy.solvers.inequalities import solve_univariate_inequality assert f.has(Abs) p, q, r = Wild('p'), Wild('q'), Wild('r') pattern_match = f.match(p*Abs(q) + r) if not pattern_match[p].is_zero: f_p, f_q, f_r = pattern_match[p], pattern_match[q], pattern_match[r] q_pos_cond = solve_univariate_inequality(f_q >= 0, symbol, relational=False) q_neg_cond = solve_univariate_inequality(f_q < 0, symbol, relational=False) sols_q_pos = solveset_real(f_p*f_q + f_r, symbol).intersect(q_pos_cond) sols_q_neg = solveset_real(f_p*(-f_q) + f_r, symbol).intersect(q_neg_cond) return Union(sols_q_pos, sols_q_neg) else: raise NotImplementedError
def _solve_abs(f, symbol, domain): """ Helper function to solve equation involving absolute value function """ if not domain.is_subset(S.Reals): raise ValueError(filldedent(''' Absolute values cannot be inverted in the complex domain.''')) p, q, r = Wild('p'), Wild('q'), Wild('r') pattern_match = f.match(p*Abs(q) + r) or {} if not pattern_match.get(p, S.Zero).is_zero: f_p, f_q, f_r = pattern_match[p], pattern_match[q], pattern_match[r] q_pos_cond = solve_univariate_inequality(f_q >= 0, symbol, relational=False) q_neg_cond = solve_univariate_inequality(f_q < 0, symbol, relational=False) sols_q_pos = solveset_real(f_p*f_q + f_r, symbol).intersect(q_pos_cond) sols_q_neg = solveset_real(f_p*(-f_q) + f_r, symbol).intersect(q_neg_cond) return Union(sols_q_pos, sols_q_neg) else: return ConditionSet(symbol, Eq(f, 0), domain)
def _eval_as_set(self): # self is univariate and periodicity(self, x) in (0, None) from sympy.solvers.inequalities import solve_univariate_inequality from sympy.sets.conditionset import ConditionSet syms = self.free_symbols assert len(syms) == 1 x = syms.pop() try: xset = solve_univariate_inequality(self, x, relational=False) except NotImplementedError: # solve_univariate_inequality raises NotImplementedError for # unsolvable equations/inequalities. xset = ConditionSet(x, self, S.Reals) return xset
def is_convex(f, *syms, **kwargs): """Determines the convexity of the function passed in the argument. Parameters ========== f : Expr The concerned function. syms : Tuple of symbols The variables with respect to which the convexity is to be determined. domain : Interval, optional The domain over which the convexity of the function has to be checked. If unspecified, S.Reals will be the default domain. Returns ======= Boolean The method returns `True` if the function is convex otherwise it returns `False`. Raises ====== NotImplementedError The check for the convexity of multivariate functions is not implemented yet. Notes ===== To determine concavity of a function pass `-f` as the concerned function. To determine logarithmic convexity of a function pass log(f) as concerned function. To determine logartihmic concavity of a function pass -log(f) as concerned function. Currently, convexity check of multivariate functions is not handled. Examples ======== >>> from sympy import symbols, exp, oo, Interval >>> from sympy.calculus.util import is_convex >>> x = symbols('x') >>> is_convex(exp(x), x) True >>> is_convex(x**3, x, domain = Interval(-1, oo)) False References ========== .. [1] https://en.wikipedia.org/wiki/Convex_function .. [2] http://www.ifp.illinois.edu/~angelia/L3_convfunc.pdf .. [3] https://en.wikipedia.org/wiki/Logarithmically_convex_function .. [4] https://en.wikipedia.org/wiki/Logarithmically_concave_function .. [5] https://en.wikipedia.org/wiki/Concave_function """ if len(syms) > 1: raise NotImplementedError( "The check for the convexity of multivariate functions is not implemented yet." ) f = _sympify(f) domain = kwargs.get('domain', S.Reals) var = syms[0] condition = f.diff(var, 2) < 0 if solve_univariate_inequality(condition, var, False, domain): return False return True
def ewma(): import plottool as pt import ubelt as ub import numpy as np pt.qtensure() # Investigate the span parameter span = 20 alpha = 2 / (span + 1) # how long does it take for the estimation to hit 0? # (ie, it no longer cares about the initial 1?) # about 93 iterations to get to 1e-4 # about 47 iterations to get to 1e-2 # about 24 iterations to get to 1e-1 # 20 iterations goes to .135 data = ([1] + [0] * 20 + [1] * 40 + [0] * 20 + [1] * 50 + [0] * 20 + [1] * 60 + [0] * 20 + [1] * 165 + [0] * 20 + [0]) mave = [] iter_ = iter(data) current = next(iter_) mave += [current] for x in iter_: current = (alpha * x) + (1 - alpha) * current mave += [current] if False: pt.figure(fnum=1, doclf=True) pt.plot(data) pt.plot(mave) np.where(np.array(mave) < 1e-1) import sympy as sym # span, alpha, n = sym.symbols('span, alpha, n') n = sym.symbols('n', integer=True, nonnegative=True, finite=True) span = sym.symbols('span', integer=True, nonnegative=True, finite=True) thresh = sym.symbols('thresh', real=True, nonnegative=True, finite=True) # alpha = 2 / (span + 1) a, b, c = sym.symbols('a, b, c', real=True, nonnegative=True, finite=True) sym.solve(sym.Eq(b**a, c), a) current = 1 x = 0 steps = [] for _ in range(10): current = (alpha * x) + (1 - alpha) * current steps.append(current) alpha = sym.symbols('alpha', real=True, nonnegative=True, finite=True) base = sym.symbols('base', real=True, finite=True) alpha = 2 / (span + 1) thresh_expr = (1 - alpha)**n thresthresh_exprh_expr = base**n n_expr = sym.ceiling(sym.log(thresh) / sym.log(1 - 2 / (span + 1))) sym.pprint(sym.simplify(thresh_expr)) sym.pprint(sym.simplify(n_expr)) print(sym.latex(sym.simplify(n_expr))) # def calc_n2(span, thresh): # return np.log(thresh) / np.log(1 - 2 / (span + 1)) def calc_n(span, thresh): return np.log(thresh) / np.log((span - 1) / (span + 1)) def calc_thresh_val(n, span): alpha = 2 / (span + 1) return (1 - alpha)**n span = np.arange(2, 200) n_frac = calc_n(span, thresh=.5) n = np.ceil(n_frac) calc_thresh_val(n, span) pt.figure(fnum=1, doclf=True) ydatas = ut.odict([('thresh=%f' % thresh, np.ceil(calc_n(span, thresh=thresh))) for thresh in [1e-3, .01, .1, .2, .3, .4, .5]]) pt.multi_plot( span, ydatas, xlabel='span', ylabel='n iters to acheive thresh', marker='', # num_xticks=len(span), fnum=1) pt.gca().set_aspect('equal') def both_sides(eqn, func): return sym.Eq(func(eqn.lhs), func(eqn.rhs)) eqn = sym.Eq(thresh_expr, thresh) n_expr = sym.solve(eqn, n)[0].subs(base, (1 - alpha)).subs(alpha, (2 / (span + 1))) eqn = both_sides(eqn, lambda x: sym.log(x, (1 - alpha))) lhs = eqn.lhs from sympy.solvers.inequalities import solve_univariate_inequality def eval_expr(span_value, n_value): return np.array( [thresh_expr.subs(span, span_value).subs(n, n_) for n_ in n_value], dtype=np.float) eval_expr(20, np.arange(20)) def linear(x, a, b): return a * x + b def sigmoidal_4pl(x, a, b, c, d): return d + (a - d) / (1 + (x / c)**b) def exponential(x, a, b, c): return a + b * np.exp(-c * x) import scipy.optimize # Determine how to choose span, such that you get to .01 from 1 # in n timesteps thresh_to_span_to_n = [] thresh_to_n_to_span = [] for thresh_value in ub.ProgIter([.0001, .001, .01, .1, .2, .3, .4, .5]): print('') test_vals = sorted([2, 3, 4, 5, 6]) n_to_span = [] for n_value in ub.ProgIter(test_vals): # In n iterations I want to choose a span that the expression go # less than a threshold constraint = thresh_expr.subs(n, n_value) < thresh_value solution = solve_univariate_inequality(constraint, span) try: lowbound = np.ceil(float(solution.args[0].lhs)) highbound = np.floor(float(solution.args[1].rhs)) assert lowbound <= highbound span_value = lowbound except AttributeError: span_value = np.floor(float(solution.rhs)) n_to_span.append((n_value, span_value)) # Given a threshold, find a minimum number of steps # that brings you up to that threshold given a span test_vals = sorted(set(list(range(2, 1000, 50)) + [2, 3, 4, 5, 6])) span_to_n = [] for span_value in ub.ProgIter(test_vals): constraint = thresh_expr.subs(span, span_value) < thresh_value solution = solve_univariate_inequality(constraint, n) n_value = solution.lhs span_to_n.append((span_value, n_value)) thresh_to_n_to_span.append((thresh_value, n_to_span)) thresh_to_span_to_n.append((thresh_value, span_to_n)) thresh_to_params = [] for thresh_value, span_to_n in thresh_to_span_to_n: xdata, ydata = [np.array(_, dtype=np.float) for _ in zip(*span_to_n)] p0 = (1 / np.diff((ydata - ydata[0])[1:]).mean(), ydata[0]) func = linear popt, pcov = scipy.optimize.curve_fit(func, xdata, ydata, p0) # popt, pcov = scipy.optimize.curve_fit(exponential, xdata, ydata) if False: yhat = func(xdata, *popt) pt.figure(fnum=1, doclf=True) pt.plot(xdata, ydata, label='measured') pt.plot(xdata, yhat, label='predicteed') pt.legend() # slope = np.diff(ydata).mean() # pt.plot(d) thresh_to_params.append((thresh_value, popt)) # pt.plt.plot(*zip(*thresh_to_slope), 'x-') # for thresh_value=.01, we get a rough line with slop ~2.302, # for thresh_value=.5, we get a line with slop ~34.66 # if we want to get to 0 in n timesteps, with a thresh_value of # choose span=f(thresh_value) * (n + 2)) # f is some inverse exponential # 0.0001, 460.551314197147 # 0.001, 345.413485647860, # 0.01, 230.275657098573, # 0.1, 115.137828549287, # 0.2, 80.4778885203347, # 0.3, 60.2031233261536, # 0.4, 45.8179484913827, # 0.5, 34.6599400289520 # Seems to be 4PL symetrical sigmoid # f(x) = -66500.85 + (66515.88 - -66500.85) / (1 + (x/0.8604672)^0.001503716) # f(x) = -66500.85 + (66515.88 - -66500.85)/(1 + (x/0.8604672)^0.001503716) def f(x): return -66500.85 + (66515.88 - -66500.85) / (1 + (x / 0.8604672)**0.001503716) # return (10000 * (-6.65 + (13.3015) / (1 + (x/0.86) ** 0.00150))) # f(.5) * (n - 1) # f( solve_rational_inequalities(thresh_expr < .01, n)
def solveset(f, symbol=None, domain=S.Complexes): """Solves a given inequality or equation with set as output Parameters ========== f : Expr or a relational. The target equation or inequality symbol : Symbol The variable for which the equation is solved domain : Set The domain over which the equation is solved Returns ======= Set A set of values for `symbol` for which `f` is True or is equal to zero. An `EmptySet` is returned if `f` is False or nonzero. A `ConditionSet` is returned as unsolved object if algorithms to evaluatee complete solution are not yet implemented. `solveset` claims to be complete in the solution set that it returns. Raises ====== NotImplementedError The algorithms to solve inequalities in complex domain are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report to the github issue tracker. Notes ===== Python interprets 0 and 1 as False and True, respectively, but in this function they refer to solutions of an expression. So 0 and 1 return the Domain and EmptySet, respectively, while True and False return the opposite (as they are assumed to be solutions of relational expressions). See Also ======== solveset_real: solver for real domain solveset_complex: solver for complex domain Examples ======== >>> from sympy import exp, sin, Symbol, pprint, S >>> from sympy.solvers.solveset import solveset, solveset_real * The default domain is complex. Not specifying a domain will lead to the solving of the equation in the complex domain (and this is not affected by the assumptions on the symbol): >>> x = Symbol('x') >>> pprint(solveset(exp(x) - 1, x), use_unicode=False) {2*n*I*pi | n in Integers()} >>> x = Symbol('x', real=True) >>> pprint(solveset(exp(x) - 1, x), use_unicode=False) {2*n*I*pi | n in Integers()} * If you want to use `solveset` to solve the equation in the real domain, provide a real domain. (Using `solveset\_real` does this automatically.) >>> R = S.Reals >>> x = Symbol('x') >>> solveset(exp(x) - 1, x, R) {0} >>> solveset_real(exp(x) - 1, x) {0} The solution is mostly unaffected by assumptions on the symbol, but there may be some slight difference: >>> pprint(solveset(sin(x)/x,x), use_unicode=False) ({2*n*pi | n in Integers()} \ {0}) U ({2*n*pi + pi | n in Integers()} \ {0}) >>> p = Symbol('p', positive=True) >>> pprint(solveset(sin(p)/p, p), use_unicode=False) {2*n*pi | n in Integers()} U {2*n*pi + pi | n in Integers()} * Inequalities can be solved over the real domain only. Use of a complex domain leads to a NotImplementedError. >>> solveset(exp(x) > 1, x, R) (0, oo) """ f = sympify(f) if f is S.true: return domain if f is S.false: return S.EmptySet if not isinstance(f, (Expr, Number)): raise ValueError("%s is not a valid SymPy expression" % (f)) free_symbols = f.free_symbols if not free_symbols: b = Eq(f, 0) if b is S.true: return domain elif b is S.false: return S.EmptySet else: raise NotImplementedError(filldedent(''' relationship between value and 0 is unknown: %s''' % b)) if symbol is None: if len(free_symbols) == 1: symbol = free_symbols.pop() else: raise ValueError(filldedent(''' The independent variable must be specified for a multivariate equation.''')) elif not getattr(symbol, 'is_Symbol', False): raise ValueError('A Symbol must be given, not type %s: %s' % (type(symbol), symbol)) if isinstance(f, Eq): from sympy.core import Add f = Add(f.lhs, - f.rhs, evaluate=False) elif f.is_Relational: if not domain.is_subset(S.Reals): raise NotImplementedError(filldedent(''' Inequalities in the complex domain are not supported. Try the real domain by setting domain=S.Reals''')) try: result = solve_univariate_inequality( f, symbol, relational=False) - _invalid_solutions( f, symbol, domain) except NotImplementedError: result = ConditionSet(symbol, f, domain) return result return _solveset(f, symbol, domain, _check=True)
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. Parameters ========== f : Expr The concerned function. symbol : Symbol The variable for which the intervals are to be determined. domain : Interval The domain over which the continuity of the symbol has to be checked. 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.open(-oo, 0), Interval.open(0, oo)) >>> continuous_domain(tan(x), x, Interval(0, pi)) Union(Interval.Ropen(0, pi/2), Interval.Lopen(pi/2, pi)) >>> continuous_domain(sqrt(x - 2), x, Interval(-5, 5)) Interval(2, 5) >>> continuous_domain(log(2*x - 1), x, S.Reals) Interval.open(1/2, oo) Returns ======= Interval Union of all intervals where the function is continuous. Raises ====== NotImplementedError If the method to determine continuity of such a function has not yet been developed. """ 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, denomin = _has_rational_power(atom, symbol) constraint = S.EmptySet if predicate and denomin == 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) + \ solveset(denom(together(f)), symbol, domain) else: for atom in f.atoms(Pow): predicate, denomin = _has_rational_power(atom, symbol) if predicate and denomin == 2: sings = solveset(1/f, symbol, domain) +\ solveset(denom(together(f)), symbol, domain) break else: sings = Intersection(solveset(1/f, symbol), domain) + \ solveset(denom(together(f)), symbol, domain) except NotImplementedError: import sys raise (NotImplementedError( "Methods for determining the continuous domains" " of this function have not been developed."), None, sys.exc_info()[2]) return domain - sings
def solveset(f, symbol=None, domain=S.Complexes): """Solves a given inequality or equation with set as output Parameters ========== f : Expr or a relational. The target equation or inequality symbol : Symbol The variable for which the equation is solved domain : Set The domain over which the equation is solved Returns ======= Set A set of values for `symbol` for which `f` is True or is equal to zero. An `EmptySet` is returned if no solution is found. A `ConditionSet` is returned as unsolved object if algorithms to evaluatee complete solution are not yet implemented. `solveset` claims to be complete in the solution set that it returns. Raises ====== NotImplementedError The algorithms to solve inequalities in complex domain are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report to the github issue tracker. `solveset` uses two underlying functions `solveset_real` and `solveset_complex` to solve equations. They are the solvers for real and complex domain respectively. `solveset` ignores the assumptions on the variable being solved for and instead, uses the `domain` parameter to decide which solver to use. See Also ======== solveset_real: solver for real domain solveset_complex: solver for complex domain Examples ======== >>> from sympy import exp, Symbol, Eq, pprint, S, solveset >>> from sympy.abc import x * The default domain is complex. Not specifying a domain will lead to the solving of the equation in the complex domain. >>> pprint(solveset(exp(x) - 1, x), use_unicode=False) {2*n*I*pi | n in Integers()} * If you want to solve equation in real domain by the `solveset` interface, then specify that the domain is real. Alternatively use `solveset\_real`. >>> x = Symbol('x') >>> solveset(exp(x) - 1, x, S.Reals) {0} >>> solveset(Eq(exp(x), 1), x, S.Reals) {0} * Inequalities can be solved over the real domain only. Use of a complex domain leads to a NotImplementedError. >>> solveset(exp(x) > 1, x, S.Reals) (0, oo) """ from sympy.solvers.inequalities import solve_univariate_inequality if symbol is None: free_symbols = f.free_symbols if len(free_symbols) == 1: symbol = free_symbols.pop() else: raise ValueError( filldedent(''' The independent variable must be specified for a multivariate equation.''')) elif not symbol.is_Symbol: raise ValueError('A Symbol must be given, not type %s: %s' % (type(symbol), symbol)) f = sympify(f) if f is S.false: return EmptySet() if f is S.true: return domain if isinstance(f, Eq): from sympy.core import Add f = Add(f.lhs, -f.rhs, evaluate=False) if f.is_Relational: if not domain.is_subset(S.Reals): raise NotImplementedError("Inequalities in the complex domain are " "not supported. Try the real domain by" "setting domain=S.Reals") try: result = solve_univariate_inequality( f, symbol, relational=False).intersection(domain) except NotImplementedError: result = ConditionSet(symbol, f, domain) return result if isinstance(f, (Expr, Number)): if domain is S.Reals: return solveset_real(f, symbol) elif domain is S.Complexes: return solveset_complex(f, symbol) elif domain.is_subset(S.Reals): return Intersection(solveset_real(f, symbol), domain) else: return Intersection(solveset_complex(f, symbol), domain)
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. Parameters ========== f : :py:class:`~.Expr` The concerned function. symbol : :py:class:`~.Symbol` The variable for which the intervals are to be determined. domain : :py:class:`~.Interval` The domain over which the continuity of the symbol has to be checked. Examples ======== >>> from sympy import Interval, Symbol, S, tan, log, pi, sqrt >>> from sympy.calculus.util import continuous_domain >>> x = Symbol('x') >>> continuous_domain(1/x, x, S.Reals) Union(Interval.open(-oo, 0), Interval.open(0, oo)) >>> continuous_domain(tan(x), x, Interval(0, pi)) Union(Interval.Ropen(0, pi/2), Interval.Lopen(pi/2, pi)) >>> continuous_domain(sqrt(x - 2), x, Interval(-5, 5)) Interval(2, 5) >>> continuous_domain(log(2*x - 1), x, S.Reals) Interval.open(1/2, oo) Returns ======= :py:class:`~.Interval` Union of all intervals where the function is continuous. Raises ====== NotImplementedError If the method to determine continuity of such a function has not yet been developed. """ from sympy.solvers.inequalities import solve_univariate_inequality if domain.is_subset(S.Reals): constrained_interval = domain for atom in f.atoms(Pow): den = atom.exp.as_numer_denom()[1] if den.is_even and den.is_nonzero: 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) return constrained_interval - singularities(f, symbol, domain)
def solveset(f, symbol=None): """Solves a given inequality or equation with set as output Parameters ========== f : Expr or a relational. The target equation or inequality symbol : Symbol The variable for which the equation is solved Returns ======= Set A set of values for `symbol` for which `f` is True or is equal to zero. An `EmptySet` is returned if no solution is found. `solveset` claims to be complete in the solution set that it returns. Raises ====== NotImplementedError The algorithms for to find the solution of the given equation are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report to the github issue tracker. `solveset` uses two underlying functions `solveset_real` and `solveset_complex` to solve equations. They are the solvers for real and complex domain respectively. The domain of the solver is decided by the assumption on the variable for which the equation is being solved. See Also ======== solveset_real: solver for real domain solveset_complex: solver for complex domain Examples ======== >>> from sympy import exp, Symbol, Eq, pprint >>> from sympy.solvers.solveset import solveset >>> from sympy.abc import x Symbols in Sympy are complex by default. A complex variable will lead to the solving of the equation in complex domain >>> pprint(solveset(exp(x) - 1, x), use_unicode=False) {2*n*I*pi | n in Integers()} If you want to solve equation in real domain by the `solveset` interface, then specify the variable to real. Alternatively use `solveset_real`. >>> x = Symbol('x', real=True) >>> solveset(exp(x) - 1, x) {0} >>> solveset(Eq(exp(x), 1), x) {0} Inequalities are always solved in the real domain irrespective of the assumption on the variable for which the inequality is solved. >>> solveset(exp(x) > 1, x) (0, oo) """ from sympy.solvers.inequalities import solve_univariate_inequality if symbol is None: free_symbols = f.free_symbols if len(free_symbols) == 1: symbol = free_symbols.pop() else: raise ValueError(filldedent(''' The independent variable must be specified for a multivariate equation.''')) elif not symbol.is_Symbol: raise ValueError('A Symbol must be given, not type %s: %s' % (type(symbol), symbol)) real = (symbol.is_real is True) f = sympify(f) if isinstance(f, Eq): f = f.lhs - f.rhs if f.is_Relational: if real is False: warnings.warn(filldedent(''' The variable you are solving for is complex but will assumed to be real since solving complex inequalities is not supported. ''')) return solve_univariate_inequality(f, symbol, relational=False) if isinstance(f, (Expr, Number)): if real is True: return solveset_real(f, symbol) else: return solveset_complex(f, symbol)
a[i, j, :] = f(np.linspace(-3, 30, 20)) assert (len(a[a < 0]) == 0) # good sign... e = (post(n * x) * u(W) - u(c / x)).subs(W, 500).subs(n, 1) f = lambdify(x, e, 'numpy') g = lambdify(rho, f(np.linspace(1.01, 20, 10)), 'numpy') m = g(np.linspace(1.2, 20, 20)) domain = Interval.Lopen(1, 4) e = (post(n * x) * u(W) > u(c / x)).subs(x, 5).subs(n, 6).subs(W, 50) solve_univariate_inequality(e, rho, domain=domain) c = exp(post(n) * log(W)) from sympy import Interval rho = Symbol('rho') x, n, W = symbols('x n W') e = (n / ((2 + n * x)**2)) * (1 / (rho - 1)) <= 1 / (x**rho) from sympy import Union domain = Union(Interval.Ropen(-50, 1), Interval.Lopen(1, 4)) solve_univariate_inequality(e.subs(n, 6).subs(x, 50), rho, domain=domain) solveset(e, rho, domain=domain)
def is_convex(f, *syms, domain=S.Reals): r"""Determines the convexity of the function passed in the argument. Parameters ========== f : :py:class:`~.Expr` The concerned function. syms : Tuple of :py:class:`~.Symbol` The variables with respect to which the convexity is to be determined. domain : :py:class:`~.Interval`, optional The domain over which the convexity of the function has to be checked. If unspecified, S.Reals will be the default domain. Returns ======= bool The method returns ``True`` if the function is convex otherwise it returns ``False``. Raises ====== NotImplementedError The check for the convexity of multivariate functions is not implemented yet. Notes ===== To determine concavity of a function pass `-f` as the concerned function. To determine logarithmic convexity of a function pass `\log(f)` as concerned function. To determine logartihmic concavity of a function pass `-\log(f)` as concerned function. Currently, convexity check of multivariate functions is not handled. Examples ======== >>> from sympy import is_convex, symbols, exp, oo, Interval >>> x = symbols('x') >>> is_convex(exp(x), x) True >>> is_convex(x**3, x, domain = Interval(-1, oo)) False >>> is_convex(1/x**2, x, domain=Interval.open(0, oo)) True References ========== .. [1] https://en.wikipedia.org/wiki/Convex_function .. [2] http://www.ifp.illinois.edu/~angelia/L3_convfunc.pdf .. [3] https://en.wikipedia.org/wiki/Logarithmically_convex_function .. [4] https://en.wikipedia.org/wiki/Logarithmically_concave_function .. [5] https://en.wikipedia.org/wiki/Concave_function """ if len(syms) > 1: raise NotImplementedError( "The check for the convexity of multivariate functions is not implemented yet." ) from sympy.solvers.inequalities import solve_univariate_inequality f = _sympify(f) var = syms[0] if any(s in domain for s in singularities(f, var)): return False condition = f.diff(var, 2) < 0 if solve_univariate_inequality(condition, var, False, domain): return False return True
def solveset(f, symbol=None): """Solves a given inequality or equation with set as output Parameters ========== f : Expr or a relational. The target equation or inequality symbol : Symbol The variable for which the equation is solved Returns ======= Set A set of values for `symbol` for which `f` is True or is equal to zero. An `EmptySet` is returned if no solution is found. `solveset` claims to be complete in the solution set that it returns. Raises ====== NotImplementedError The algorithms for to find the solution of the given equation are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report to the github issue tracker. `solveset` uses two underlying functions `solveset_real` and `solveset_complex` to solve equations. They are the solvers for real and complex domain respectively. The domain of the solver is decided by the assumption on the variable for which the equation is being solved. See Also ======== solveset_real: solver for real domain solveset_complex: solver for complex domain Examples ======== >>> from sympy import exp, Symbol, Eq, pprint >>> from sympy.solvers.solveset import solveset >>> from sympy.abc import x * Symbols in Sympy are complex by default. A complex variable will lead to the solving of the equation in complex domain. >>> pprint(solveset(exp(x) - 1, x), use_unicode=False) {2*n*I*pi | n in Integers()} * If you want to solve equation in real domain by the `solveset` interface, then specify the variable to real. Alternatively use `solveset\_real`. >>> x = Symbol('x', real=True) >>> solveset(exp(x) - 1, x) {0} >>> solveset(Eq(exp(x), 1), x) {0} * Inequalities are always solved in the real domain irrespective of the assumption on the variable for which the inequality is solved. >>> solveset(exp(x) > 1, x) (0, oo) """ from sympy.solvers.inequalities import solve_univariate_inequality if symbol is None: free_symbols = f.free_symbols if len(free_symbols) == 1: symbol = free_symbols.pop() else: raise ValueError( filldedent(''' The independent variable must be specified for a multivariate equation.''')) elif not symbol.is_Symbol: raise ValueError('A Symbol must be given, not type %s: %s' % (type(symbol), symbol)) real = (symbol.is_real is True) f = sympify(f) if f is S.false: return EmptySet() if f is S.true: if real: return S.Reals else: return S.Complex if isinstance(f, Eq): from sympy.core import Add f = Add(f.lhs, -f.rhs, evaluate=False) if f.is_Relational: if real is False: warnings.warn( filldedent(''' The variable you are solving for is complex but will assumed to be real since solving complex inequalities is not supported. ''')) return solve_univariate_inequality(f, symbol, relational=False) if isinstance(f, (Expr, Number)): if real is True: return solveset_real(f, symbol) else: return solveset_complex(f, symbol)
def solveset(f, symbol=None, domain=S.Complexes): """Solves a given inequality or equation with set as output Parameters ========== f : Expr or a relational. The target equation or inequality symbol : Symbol The variable for which the equation is solved domain : Set The domain over which the equation is solved Returns ======= Set A set of values for `symbol` for which `f` is True or is equal to zero. An `EmptySet` is returned if no solution is found. A `ConditionSet` is returned as unsolved object if algorithms to evaluatee complete solution are not yet implemented. `solveset` claims to be complete in the solution set that it returns. Raises ====== NotImplementedError The algorithms to solve inequalities in complex domain are not yet implemented. ValueError The input is not valid. RuntimeError It is a bug, please report to the github issue tracker. `solveset` uses two underlying functions `solveset_real` and `solveset_complex` to solve equations. They are the solvers for real and complex domain respectively. `solveset` ignores the assumptions on the variable being solved for and instead, uses the `domain` parameter to decide which solver to use. See Also ======== solveset_real: solver for real domain solveset_complex: solver for complex domain Examples ======== >>> from sympy import exp, Symbol, Eq, pprint, S, solveset >>> from sympy.abc import x * The default domain is complex. Not specifying a domain will lead to the solving of the equation in the complex domain. >>> pprint(solveset(exp(x) - 1, x), use_unicode=False) {2*n*I*pi | n in Integers()} * If you want to solve equation in real domain by the `solveset` interface, then specify that the domain is real. Alternatively use `solveset\_real`. >>> x = Symbol('x') >>> solveset(exp(x) - 1, x, S.Reals) {0} >>> solveset(Eq(exp(x), 1), x, S.Reals) {0} * Inequalities can be solved over the real domain only. Use of a complex domain leads to a NotImplementedError. >>> solveset(exp(x) > 1, x, S.Reals) (0, oo) """ from sympy.solvers.inequalities import solve_univariate_inequality if symbol is None: free_symbols = f.free_symbols if len(free_symbols) == 1: symbol = free_symbols.pop() else: raise ValueError(filldedent(''' The independent variable must be specified for a multivariate equation.''')) elif not symbol.is_Symbol: raise ValueError('A Symbol must be given, not type %s: %s' % (type(symbol), symbol)) f = sympify(f) if f is S.false: return EmptySet() if f is S.true: return domain if isinstance(f, Eq): from sympy.core import Add f = Add(f.lhs, - f.rhs, evaluate=False) if f.is_Relational: if not domain.is_subset(S.Reals): raise NotImplementedError("Inequalities in the complex domain are " "not supported. Try the real domain by" "setting domain=S.Reals") try: result = solve_univariate_inequality( f, symbol, relational=False).intersection(domain) except NotImplementedError: result = ConditionSet(symbol, f, domain) return result if isinstance(f, (Expr, Number)): if domain is S.Reals: return solveset_real(f, symbol) elif domain is S.Complexes: return solveset_complex(f, symbol) elif domain.is_subset(S.Reals): return Intersection(solveset_real(f, symbol), domain) else: return Intersection(solveset_complex(f, symbol), domain)
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. Parameters ========== f : Expr The concerned function. symbol : Symbol The variable for which the intervals are to be determined. domain : Interval The domain over which the continuity of the symbol has to be checked. 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.open(-oo, 0), Interval.open(0, oo)) >>> continuous_domain(tan(x), x, Interval(0, pi)) Union(Interval.Ropen(0, pi/2), Interval.Lopen(pi/2, pi)) >>> continuous_domain(sqrt(x - 2), x, Interval(-5, 5)) Interval(2, 5) >>> continuous_domain(log(2*x - 1), x, S.Reals) Interval.open(1/2, oo) Returns ======= Interval Union of all intervals where the function is continuous. Raises ====== NotImplementedError If the method to determine continuity of such a function has not yet been developed. """ 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, denomin = _has_rational_power(atom, symbol) constraint = S.EmptySet if predicate and denomin == 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) + \ solveset(denom(together(f)), symbol, domain) else: for atom in f.atoms(Pow): predicate, denomin = _has_rational_power(atom, symbol) if predicate and denomin == 2: sings = solveset(1/f, symbol, domain) +\ solveset(denom(together(f)), symbol, domain) break else: sings = Intersection(solveset(1/f, symbol), domain) + \ solveset(denom(together(f)), symbol, domain) except NotImplementedError: import sys raise (NotImplementedError("Methods for determining the continuous domains" " of this function have not been developed."), None, sys.exc_info()[2]) return domain - sings
def is_convex(f, *syms, **kwargs): """Determines the convexity of the function passed in the argument. Parameters ========== f : Expr The concerned function. syms : Tuple of symbols The variables with respect to which the convexity is to be determined. domain : Interval, optional The domain over which the convexity of the function has to be checked. If unspecified, S.Reals will be the default domain. Returns ======= Boolean The method returns `True` if the function is convex otherwise it returns `False`. Raises ====== NotImplementedError The check for the convexity of multivariate functions is not implemented yet. Notes ===== To determine concavity of a function pass `-f` as the concerned function. To determine logarithmic convexity of a function pass log(f) as concerned function. To determine logartihmic concavity of a function pass -log(f) as concerned function. Currently, convexity check of multivariate functions is not handled. Examples ======== >>> from sympy import symbols, exp, oo, Interval >>> from sympy.calculus.util import is_convex >>> x = symbols('x') >>> is_convex(exp(x), x) True >>> is_convex(x**3, x, domain = Interval(-1, oo)) False References ========== .. [1] https://en.wikipedia.org/wiki/Convex_function .. [2] http://www.ifp.illinois.edu/~angelia/L3_convfunc.pdf .. [3] https://en.wikipedia.org/wiki/Logarithmically_convex_function .. [4] https://en.wikipedia.org/wiki/Logarithmically_concave_function .. [5] https://en.wikipedia.org/wiki/Concave_function """ if len(syms) > 1: raise NotImplementedError( "The check for the convexity of multivariate functions is not implemented yet.") f = _sympify(f) domain = kwargs.get('domain', S.Reals) var = syms[0] condition = f.diff(var, 2) < 0 if solve_univariate_inequality(condition, var, False, domain): return False return True