def test_issue_19627(): # if you use force the user must verify assert powdenest(sqrt(sin(x)**2), force=True) == sin(x) assert powdenest((x**(S.Half/y))**(2*y), force=True) == x from sympy.core.function import expand_power_base e = 1 - a expr = (exp(z/e)*x**(b/e)*y**((1 - b)/e))**e assert powdenest(expand_power_base(expr, force=True), force=True ) == x**b*y**(1 - b)*exp(z)
def calculate_series(e, x, logx=None): """ Calculates at least one term of the series of ``e`` in ``x``. This is a place that fails most often, so it is in its own function. """ from sympy.simplify.powsimp import powdenest for t in e.lseries(x, logx=logx): # bottom_up function is required for a specific case - when e is # -exp(p/(p + 1)) + exp(-p**2/(p + 1) + p) t = bottom_up(t, lambda w: getattr(w, 'normal', lambda: w)()) # And the expression # `(-sin(1/x) + sin((x + exp(x))*exp(-x)/x))*exp(x)` # from the first test of test_gruntz_eval_special needs to # be expanded. But other forms need to be have at least # factor_terms applied. `factor` accomplishes both and is # faster than using `factor_terms` for the gruntz suite. It # does not appear that use of `cancel` is necessary. # t = cancel(t, expand=False) t = t.factor() if t.has(exp) and t.has(log): t = powdenest(t) if not t.is_zero: break return t
def test_branch_bug(): from sympy.functions.special.gamma_functions import lowergamma from sympy.simplify.powsimp import powdenest # TODO gammasimp cannot prove that the factor is unity assert powdenest(integrate(erf(x**3), x, meijerg=True).diff(x), polar=True) == 2 * erf(x**3) * gamma(Rational( 2, 3)) / 3 / gamma(Rational(5, 3)) assert integrate(erf(x**3), x, meijerg=True) == \ 2*x*erf(x**3)*gamma(Rational(2, 3))/(3*gamma(Rational(5, 3))) \ - 2*gamma(Rational(2, 3))*lowergamma(Rational(2, 3), x**6)/(3*sqrt(pi)*gamma(Rational(5, 3)))
def calculate_series(e, x, logx=None): """ Calculates at least one term of the series of "e" in "x". This is a place that fails most often, so it is in its own function. """ from sympy.polys import cancel for t in e.lseries(x, logx=logx): t = cancel(t) if t.has(exp) and t.has(log): t = powdenest(t) if t.simplify(): break return t
def limitinf(e, x, leadsimp=False): """Limit e(x) for x-> oo. Explanation =========== If ``leadsimp`` is True, an attempt is made to simplify the leading term of the series expansion of ``e``. That may succeed even if ``e`` cannot be simplified. """ # rewrite e in terms of tractable functions only if not e.has(x): return e # e is a constant from sympy.simplify.powsimp import powdenest if e.has(Order): e = e.expand().removeO() if not x.is_positive or x.is_integer: # We make sure that x.is_positive is True and x.is_integer is None # so we get all the correct mathematical behavior from the expression. # We need a fresh variable. p = Dummy('p', positive=True) e = e.subs(x, p) x = p e = e.rewrite('tractable', deep=True, limitvar=x) e = powdenest(e) c0, e0 = mrv_leadterm(e, x) sig = sign(e0, x) if sig == 1: return S.Zero # e0>0: lim f = 0 elif sig == -1: # e0<0: lim f = +-oo (the sign depends on the sign of c0) if c0.match(I * Wild("a", exclude=[I])): return c0 * oo s = sign(c0, x) # the leading term shouldn't be 0: if s == 0: raise ValueError("Leading term should not be 0") return s * oo elif sig == 0: if leadsimp: c0 = c0.simplify() return limitinf(c0, x, leadsimp) # e0=0: lim f = lim c0 else: raise ValueError("{} could not be evaluated".format(sig))
def calculate_series(e, x, logx=None): """ Calculates at least one term of the series of ``e`` in ``x``. This is a place that fails most often, so it is in its own function. """ from sympy.polys import cancel from sympy.simplify import bottom_up for t in e.lseries(x, logx=logx): # bottom_up function is required for a specific case - when e is # -exp(p/(p + 1)) + exp(-p**2/(p + 1) + p). No current simplification # methods reduce this to 0 while not expanding polynomials. t = bottom_up(t, lambda w: getattr(w, 'normal', lambda: w)()) t = cancel(t, expand=False).factor() if t.has(exp) and t.has(log): t = powdenest(t) if not t.is_zero: break return t
def handle(expr): # Handle first reduces to the case # expr = 1/d, where d is an add, or d is base**p/2. # We do this by recursively calling handle on each piece. from sympy.simplify.simplify import nsimplify n, d = fraction(expr) if expr.is_Atom or (d.is_Atom and n.is_Atom): return expr elif not n.is_Atom: n = n.func(*[handle(a) for a in n.args]) return _unevaluated_Mul(n, handle(1/d)) elif n is not S.One: return _unevaluated_Mul(n, handle(1/d)) elif d.is_Mul: return _unevaluated_Mul(*[handle(1/d) for d in d.args]) # By this step, expr is 1/d, and d is not a mul. if not symbolic and d.free_symbols: return expr if ispow2(d): d2 = sqrtdenest(sqrt(d.base))**numer(d.exp) if d2 != d: return handle(1/d2) elif d.is_Pow and (d.exp.is_integer or d.base.is_positive): # (1/d**i) = (1/d)**i return handle(1/d.base)**d.exp if not (d.is_Add or ispow2(d)): return 1/d.func(*[handle(a) for a in d.args]) # handle 1/d treating d as an Add (though it may not be) keep = True # keep changes that are made # flatten it and collect radicals after checking for special # conditions d = _mexpand(d) # did it change? if d.is_Atom: return 1/d # is it a number that might be handled easily? if d.is_number: _d = nsimplify(d) if _d.is_Number and _d.equals(d): return 1/_d while True: # collect similar terms collected = defaultdict(list) for m in Add.make_args(d): # d might have become non-Add p2 = [] other = [] for i in Mul.make_args(m): if ispow2(i, log2=True): p2.append(i.base if i.exp is S.Half else i.base**(2*i.exp)) elif i is S.ImaginaryUnit: p2.append(S.NegativeOne) else: other.append(i) collected[tuple(ordered(p2))].append(Mul(*other)) rterms = list(ordered(list(collected.items()))) rterms = [(Mul(*i), Add(*j)) for i, j in rterms] nrad = len(rterms) - (1 if rterms[0][0] is S.One else 0) if nrad < 1: break elif nrad > max_terms: # there may have been invalid operations leading to this point # so don't keep changes, e.g. this expression is troublesome # in collecting terms so as not to raise the issue of 2834: # r = sqrt(sqrt(5) + 5) # eq = 1/(sqrt(5)*r + 2*sqrt(5)*sqrt(-sqrt(5) + 5) + 5*r) keep = False break if len(rterms) > 4: # in general, only 4 terms can be removed with repeated squaring # but other considerations can guide selection of radical terms # so that radicals are removed if all([x.is_Integer and (y**2).is_Rational for x, y in rterms]): nd, d = rad_rationalize(S.One, Add._from_args( [sqrt(x)*y for x, y in rterms])) n *= nd else: # is there anything else that might be attempted? keep = False break from sympy.simplify.powsimp import powsimp, powdenest num = powsimp(_num(rterms)) n *= num d *= num d = powdenest(_mexpand(d), force=symbolic) if d.is_Atom: break if not keep: return expr return _unevaluated_Mul(n, 1/d)
def equivalence_hypergeometric(A, B, func): # This method for finding the equivalence is only for 2F1 type. # We can extend it for 1F1 and 0F1 type also. x = func.args[0] # making given equation in normal form I1 = factor(cancel(A.diff(x)/2 + A**2/4 - B)) # computing shifted invariant(J1) of the equation J1 = factor(cancel(x**2*I1 + S(1)/4)) num, dem = J1.as_numer_denom() num = powdenest(expand(num)) dem = powdenest(expand(dem)) # this function will compute the different powers of variable(x) in J1. # then it will help in finding value of k. k is power of x such that we can express # J1 = x**k * J0(x**k) then all the powers in J0 become integers. def _power_counting(num): _pow = {0} for val in num: if val.has(x): if isinstance(val, Pow) and val.as_base_exp()[0] == x: _pow.add(val.as_base_exp()[1]) elif val == x: _pow.add(val.as_base_exp()[1]) else: _pow.update(_power_counting(val.args)) return _pow pow_num = _power_counting((num, )) pow_dem = _power_counting((dem, )) pow_dem.update(pow_num) _pow = pow_dem k = gcd(_pow) # computing I0 of the given equation I0 = powdenest(simplify(factor(((J1/k**2) - S(1)/4)/((x**k)**2))), force=True) I0 = factor(cancel(powdenest(I0.subs(x, x**(S(1)/k)), force=True))) num, dem = I0.as_numer_denom() max_num_pow = max(_power_counting((num, ))) dem_args = dem.args sing_point = [] dem_pow = [] # calculating singular point of I0. for arg in dem_args: if arg.has(x): if isinstance(arg, Pow): # (x-a)**n dem_pow.append(arg.as_base_exp()[1]) sing_point.append(list(roots(arg.as_base_exp()[0], x).keys())[0]) else: # (x-a) type dem_pow.append(arg.as_base_exp()[1]) sing_point.append(list(roots(arg, x).keys())[0]) dem_pow.sort() # checking if equivalence is exists or not. if equivalence(max_num_pow, dem_pow) == "2F1": return {'I0':I0, 'k':k, 'sing_point':sing_point, 'type':"2F1"} else: return None
def test_issue_5805(): arg = ((gamma(x)*hyper((), (), x))*pi)**2 assert powdenest(arg) == (pi*gamma(x)*hyper((), (), x))**2 assert arg.is_positive is None
def test_powdenest_polar(): x, y, z = symbols('x y z', polar=True) a, b, c = symbols('a b c') assert powdenest((x*y*z)**a) == x**a*y**a*z**a assert powdenest((x**a*y**b)**c) == x**(a*c)*y**(b*c) assert powdenest(((x**a)**b*y**c)**c) == x**(a*b*c)*y**(c**2)
def test_powdenest(): x, y = symbols('x,y') p, q = symbols('p q', positive=True) i, j = symbols('i,j', integer=True) assert powdenest(x) == x assert powdenest(x + 2*(x**(a*Rational(2, 3)))**(3*x)) == (x + 2*(x**(a*Rational(2, 3)))**(3*x)) assert powdenest((exp(a*Rational(2, 3)))**(3*x)) # -X-> (exp(a/3))**(6*x) assert powdenest((x**(a*Rational(2, 3)))**(3*x)) == ((x**(a*Rational(2, 3)))**(3*x)) assert powdenest(exp(3*x*log(2))) == 2**(3*x) assert powdenest(sqrt(p**2)) == p eq = p**(2*i)*q**(4*i) assert powdenest(eq) == (p*q**2)**(2*i) # -X-> (x**x)**i*(x**x)**j == x**(x*(i + j)) assert powdenest((x**x)**(i + j)) assert powdenest(exp(3*y*log(x))) == x**(3*y) assert powdenest(exp(y*(log(a) + log(b)))) == (a*b)**y assert powdenest(exp(3*(log(a) + log(b)))) == a**3*b**3 assert powdenest(((x**(2*i))**(3*y))**x) == ((x**(2*i))**(3*y))**x assert powdenest(((x**(2*i))**(3*y))**x, force=True) == x**(6*i*x*y) assert powdenest(((x**(a*Rational(2, 3)))**(3*y/i))**x) == \ (((x**(a*Rational(2, 3)))**(3*y/i))**x) assert powdenest((x**(2*i)*y**(4*i))**z, force=True) == (x*y**2)**(2*i*z) assert powdenest((p**(2*i)*q**(4*i))**j) == (p*q**2)**(2*i*j) e = ((p**(2*a))**(3*y))**x assert powdenest(e) == e e = ((x**2*y**4)**a)**(x*y) assert powdenest(e) == e e = (((x**2*y**4)**a)**(x*y))**3 assert powdenest(e) == ((x**2*y**4)**a)**(3*x*y) assert powdenest((((x**2*y**4)**a)**(x*y)), force=True) == \ (x*y**2)**(2*a*x*y) assert powdenest((((x**2*y**4)**a)**(x*y))**3, force=True) == \ (x*y**2)**(6*a*x*y) assert powdenest((x**2*y**6)**i) != (x*y**3)**(2*i) x, y = symbols('x,y', positive=True) assert powdenest((x**2*y**6)**i) == (x*y**3)**(2*i) assert powdenest((x**(i*Rational(2, 3))*y**(i/2))**(2*i)) == (x**Rational(4, 3)*y)**(i**2) assert powdenest(sqrt(x**(2*i)*y**(6*i))) == (x*y**3)**i assert powdenest(4**x) == 2**(2*x) assert powdenest((4**x)**y) == 2**(2*x*y) assert powdenest(4**x*y) == 2**(2*x)*y