def _eval_expand_func(self, **hints): n, z = self.args if n.is_Integer and n.is_nonnegative: if z.is_Add: coeff = z.args[0] if coeff.is_Integer: e = -(n + 1) if coeff > 0: tail = Add(*[ C.Pow(z - i, e) for i in xrange(1, int(coeff) + 1) ]) else: tail = -Add( *[C.Pow(z + i, e) for i in xrange(0, int(-coeff))]) return polygamma( n, z - coeff) + (-1)**n * C.factorial(n) * tail elif z.is_Mul: coeff, z = z.as_two_terms() if coeff.is_Integer and coeff.is_positive: tail = [ polygamma(n, z + C.Rational(i, coeff)) for i in xrange(0, int(coeff)) ] if n == 0: return Add(*tail) / coeff + log(coeff) else: return Add(*tail) / coeff**(n + 1) z *= coeff return polygamma(n, z)
def separate(expr, deep=False): """Rewrite or separate a power of product to a product of powers but without any expanding, ie. rewriting products to summations. >>> from sympy import * >>> x, y, z = symbols('x', 'y', 'z') >>> separate((x*y)**2) x**2*y**2 >>> separate((x*(y*z)**3)**2) x**2*y**6*z**6 >>> separate((x*sin(x))**y + (x*cos(x))**y) x**y*cos(x)**y + x**y*sin(x)**y >>> separate((exp(x)*exp(y))**x) exp(x**2)*exp(x*y) >>> separate((sin(x)*cos(x))**y) cos(x)**y*sin(x)**y Notice that summations are left un touched. If this is not the requested behaviour, apply 'expand' to input expression before: >>> separate(((x+y)*z)**2) z**2*(x + y)**2 >>> separate((x*y)**(1+z)) x**(1 + z)*y**(1 + z) """ expr = sympify(expr) if expr.is_Pow: terms, expo = [], separate(expr.exp, deep) if expr.base.is_Mul: t = [separate(C.Pow(t, expo), deep) for t in expr.base.args] return C.Mul(*t) elif expr.base.func is C.exp: if deep == True: return C.exp(separate(expr.base[0], deep) * expo) else: return C.exp(expr.base[0] * expo) else: return C.Pow(separate(expr.base, deep), expo) elif expr.is_Add or expr.is_Mul: return type(expr)(*[separate(t, deep) for t in expr.args]) elif expr.is_Function and deep: return expr.func(*[separate(t) for t in expr.args]) else: return expr
def real_root(arg, n=None): """Return the real nth-root of arg if possible. If n is omitted then all instances of -1**(1/odd) will be changed to -1. Examples ======== >>> from sympy import root, real_root, Rational >>> from sympy.abc import x, n >>> real_root(-8, 3) -2 >>> root(-8, 3) 2*(-1)**(1/3) >>> real_root(_) -2 See Also ======== sympy.polys.rootoftools.RootOf sympy.core.power.integer_nthroot root, sqrt """ if n is not None: n = as_int(n) rv = C.Pow(arg, Rational(1, n)) if n % 2 == 0: return rv else: rv = sympify(arg) n1pow = Transform( lambda x: S.NegativeOne, lambda x: x.is_Pow and x.base is S.NegativeOne and x.exp.is_Rational and x.exp.p == 1 and x.exp.q % 2) return rv.xreplace(n1pow)
def real_root(arg, n=None): """Return the real nth-root of arg if possible. If n is omitted then all instances of (-n)**(1/odd) will be changed to -n**(1/odd); this will only create a real root of a principle root -- the presence of other factors may cause the result to not be real. Examples ======== >>> from sympy import root, real_root, Rational >>> from sympy.abc import x, n >>> real_root(-8, 3) -2 >>> root(-8, 3) 2*(-1)**(1/3) >>> real_root(_) -2 If one creates a non-principle root and applies real_root, the result will not be real (so use with caution): >>> root(-8, 3, 2) -2*(-1)**(2/3) >>> real_root(_) -2*(-1)**(2/3) See Also ======== sympy.polys.rootoftools.RootOf sympy.core.power.integer_nthroot root, sqrt """ if n is not None: try: n = as_int(n) arg = sympify(arg) if arg.is_positive or arg.is_negative: rv = root(arg, n) else: raise ValueError except ValueError: return root(arg, n)*C.Piecewise( (S.One, ~C.Equality(C.im(arg), 0)), (C.Pow(S.NegativeOne, S.One/n)**(2*C.floor(n/2)), C.And( C.Equality(n % 2, 1), arg < 0)), (S.One, True)) else: rv = sympify(arg) n1pow = Transform(lambda x: -(-x.base)**x.exp, lambda x: x.is_Pow and x.base.is_negative and x.exp.is_Rational and x.exp.p == 1 and x.exp.q % 2) return rv.xreplace(n1pow)
def root(arg, n): """The n-th root function (a shortcut for arg**(1/n)) root(x, n) -> Returns the principal n-th root of x. Examples ======== >>> from sympy import root, Rational >>> from sympy.abc import x, n >>> root(x, 2) sqrt(x) >>> root(x, 3) x**(1/3) >>> root(x, n) x**(1/n) >>> root(x, -Rational(2, 3)) x**(-3/2) To get all n n-th roots you can use the RootOf function. The following examples show the roots of unity for n equal 2, 3 and 4: >>> from sympy import RootOf, I >>> [ RootOf(x**2-1,i) for i in (0,1) ] [-1, 1] >>> [ RootOf(x**3-1,i) for i in (0,1,2) ] [1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2] >>> [ RootOf(x**4-1,i) for i in (0,1,2,3) ] [-1, 1, -I, I] See Also ======== sympy.polys.rootoftools.RootOf sympy.core.power.integer_nthroot sqrt, real_root References ========== * http://en.wikipedia.org/wiki/Square_root * http://en.wikipedia.org/wiki/real_root * http://en.wikipedia.org/wiki/Root_of_unity * http://en.wikipedia.org/wiki/Principal_value """ n = sympify(n) return C.Pow(arg, 1 / n)
def _print_Pow(self, power): # square roots, other roots or n-th roots #test for fraction 1/n or power x**-1 if power.is_commutative: if (isinstance(power.exp, C.Rational) and power.exp.p==1 and power.exp.q !=1) or \ ( isinstance(power.exp, C.Pow) and isinstance(power.exp.args[0], C.Symbol) and power.exp.args[1]==S.NegativeOne): bpretty = self._print(power.base) #construct root sign, start with the \/ shape _zZ = xobj('/', 1) rootsign = xobj('\\', 1) + _zZ #make exponent number to put above it if isinstance(power.exp, C.Rational): exp = str(power.exp.q) if exp == '2': exp = '' else: exp = str(power.exp.args[0]) exp = exp.ljust(2) if len(exp) > 2: rootsign = ' ' * (len(exp) - 2) + rootsign #stack the exponent rootsign = stringPict(exp + '\n' + rootsign) rootsign.baseline = 0 #diagonal: length is one less than height of base linelength = bpretty.height() - 1 diagonal = stringPict('\n'.join(' ' * (linelength - i - 1) + _zZ + ' ' * i for i in range(linelength))) #put baseline just below lowest line: next to exp diagonal.baseline = linelength - 1 #make the root symbol rootsign = prettyForm(*rootsign.right(diagonal)) #set the baseline to match contents to fix the height #but if the height of bpretty is one, the rootsign must be one higher rootsign.baseline = max(1, bpretty.baseline) #build result s = prettyForm(hobj('_', 2 + bpretty.width())) s = prettyForm(*bpretty.above(s)) s = prettyForm(*s.left(rootsign)) return s elif power.exp.is_Rational and power.exp.is_negative: # Things like 1/x return prettyForm("1") / self._print( C.Pow(power.base, -power.exp)) # None of the above special forms, do a standard power b, e = power.as_base_exp() return self._print(b)**self._print(e)
def cbrt(arg): """This function computes the principial cube root of `arg`, so it's just a shortcut for `arg**Rational(1, 3)`. Examples ======== >>> from sympy import cbrt, Symbol >>> x = Symbol('x') >>> cbrt(x) x**(1/3) >>> cbrt(x)**3 x Note that cbrt(x**3) does not simplify to x. >>> cbrt(x**3) (x**3)**(1/3) This is because the two are not equal to each other in general. For example, consider `x == -1`: >>> from sympy import Eq >>> Eq(cbrt(x**3), x).subs(x, -1) False This is because cbrt computes the principal cube root, this identity does hold if `x` is positive: >>> y = Symbol('y', positive=True) >>> cbrt(y**3) y See Also ======== sympy.polys.rootoftools.RootOf, root, real_root References ========== * http://en.wikipedia.org/wiki/Cube_root * http://en.wikipedia.org/wiki/Principal_value """ return C.Pow(arg, C.Rational(1, 3))
def _print_Pow(self, expr): # Treat x**Rational(1,n) as special case if expr.exp.is_Rational and abs(expr.exp.p) == 1 and expr.exp.q != 1: base = self._print(expr.base) expq = expr.exp.q if expq == 2: tex = r"\sqrt{%s}" % base elif self._settings['itex']: tex = r"\root{%d}{%s}" % (expq,base) else: tex = r"\sqrt[%d]{%s}" % (expq,base) if expr.exp.is_negative: return r"\frac{1}{%s}" % tex else: return tex elif self._settings['fold_frac_powers'] \ and expr.exp.is_Rational \ and expr.exp.q != 1: base, p, q = self._print(expr.base), expr.exp.p, expr.exp.q return r"%s^{%s/%s}" % (base, p, q) elif expr.exp.is_Rational and expr.exp.is_negative and expr.base.is_Function: # Things like 1/x return r"\frac{%s}{%s}" % \ (1, self._print(C.Pow(expr.base, -expr.exp))) else: if expr.base.is_Function: return self._print(expr.base, self._print(expr.exp)) else: if expr.is_commutative and expr.exp == -1: #solves issue 1030 #As Mul always simplify 1/x to x**-1 #The objective is achieved with this hack #first we get the latex for -1 * expr, #which is a Mul expression tex = self._print(S.NegativeOne * expr).strip() #the result comes with a minus and a space, so we remove if tex[:1] == "-": return tex[1:].strip() if self._needs_brackets(expr.base): tex = r"\left(%s\right)^{%s}" else: tex = r"%s^{%s}" return tex % (self._print(expr.base), self._print(expr.exp))
def _print_Mul(self, product): a = [] # items in the numerator b = [] # items that are in the denominator (if any) if self.order not in ('old', 'none'): args = product.as_ordered_factors() else: args = product.args # Gather terms for numerator/denominator for item in args: if item.is_commutative and item.is_Pow and item.exp.is_Rational and item.exp.is_negative: b.append(C.Pow(item.base, -item.exp)) elif item.is_Rational and item is not S.Infinity: if item.p != 1: a.append(C.Rational(item.p)) if item.q != 1: b.append(C.Rational(item.q)) else: a.append(item) # Convert to pretty forms. Add parens to Add instances if there # is more than one term in the numer/denom for i in xrange(0, len(a)): if a[i].is_Add and len(a) > 1: a[i] = prettyForm(*self._print(a[i]).parens()) else: a[i] = self._print(a[i]) for i in xrange(0, len(b)): if b[i].is_Add and len(b) > 1: b[i] = prettyForm(*self._print(b[i]).parens()) else: b[i] = self._print(b[i]) # Construct a pretty form if len(b) == 0: return prettyForm.__mul__(*a) else: if len(a) == 0: a.append(self._print(S.One)) return prettyForm.__mul__(*a) / prettyForm.__mul__(*b)
def sqrt(arg): """The square root function sqrt(x) -> Returns the principal square root of x. Examples ======== >>> from sympy import sqrt, Symbol >>> x = Symbol('x') >>> sqrt(x) sqrt(x) >>> sqrt(x)**2 x Note that sqrt(x**2) does not simplify to x. >>> sqrt(x**2) sqrt(x**2) This is because the two are not equal to each other in general. For example, consider x == -1: >>> sqrt(x**2).subs(x, -1) 1 >>> x.subs(x, -1) -1 This is because sqrt computes the principal square root, so the square may put the argument in a different branch. This identity does hold if x is positive: >>> y = Symbol('y', positive=True) >>> sqrt(y**2) y You can force this simplification by using the powdenest() function with the force option set to True: >>> from sympy import powdenest >>> sqrt(x**2) sqrt(x**2) >>> powdenest(sqrt(x**2), force=True) x To get both branches of the square root you can use the RootOf function: >>> from sympy import RootOf >>> [ RootOf(x**2-3,i) for i in (0,1) ] [-sqrt(3), sqrt(3)] See Also ======== sympy.polys.rootoftools.RootOf, root References ========== * http://en.wikipedia.org/wiki/Square_root * http://en.wikipedia.org/wiki/Principal_value """ # arg = sympify(arg) is handled by Pow return C.Pow(arg, S.Half)
def root(arg, n): """The n-th root function (a shortcut for arg**(1/n)) root(x, n) -> Returns the principal n-th root of x. Examples ======== >>> from sympy import root, Rational >>> from sympy.abc import x, n >>> root(x, 2) sqrt(x) >>> root(x, 3) x**(1/3) >>> root(x, n) x**(1/n) >>> root(x, -Rational(2, 3)) x**(-3/2) To get all n n-th roots you can use the RootOf function. The following examples show the roots of unity for n equal 2, 3 and 4: >>> from sympy import RootOf, I >>> [ RootOf(x**2-1,i) for i in (0,1) ] [-1, 1] >>> [ RootOf(x**3-1,i) for i in (0,1,2) ] [1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2] >>> [ RootOf(x**4-1,i) for i in (0,1,2,3) ] [-1, 1, -I, I] SymPy, like other symbolic algebra systems, returns the complex root of negative numbers. This is the principal root and differs from the text-book result that one might be expecting. For example, the cube root of -8 does not come back as -2: >>> root(-8, 3) 2*(-1)**(1/3) The real_root function can be used to either make such a result real or simply return the real root in the first place: >>> from sympy import real_root >>> real_root(_) -2 >>> real_root(-32, 5) -2 See Also ======== sympy.polys.rootoftools.RootOf sympy.core.power.integer_nthroot sqrt, real_root References ========== * http://en.wikipedia.org/wiki/Square_root * http://en.wikipedia.org/wiki/real_root * http://en.wikipedia.org/wiki/Root_of_unity * http://en.wikipedia.org/wiki/Principal_value * http://mathworld.wolfram.com/CubeRoot.html """ n = sympify(n) return C.Pow(arg, 1 / n)
def sqrt(arg): # arg = sympify(arg) is handled by Pow return C.Pow(arg, S.Half)
def powsimp(expr, deep=False, combine='all'): """ == Usage == Reduces expression by combining powers with similar bases and exponents. == Notes == If deep is True then powsimp() will also simplify arguments of functions. By default deep is set to False. You can make powsimp() only combine bases or only combine exponents by changing combine='base' or combine='exp'. By default, combine='all', which does both. combine='base' will only combine:: a a a 2x x x * y => (x*y) as well as things like 2 => 4 and combine='exp' will only combine :: a b (a + b) x * x => x combine='exp' will strictly only combine exponents in the way that used to be automatic. Also use deep=True if you need the old behavior. == Examples == >>> from sympy import * >>> x,n = map(Symbol, 'xn') >>> e = x**n * (x*n)**(-n) * n >>> powsimp(e) n**(1 - n) >>> powsimp(log(e)) log(n*x**n*(n*x)**(-n)) >>> powsimp(log(e), deep=True) log(n**(1 - n)) >>> powsimp(e, combine='exp') n*x**n*(n*x)**(-n) >>> powsimp(e, combine='base') n*(1/n)**n >>> y, z = symbols('yz') >>> a = x**y*x**z*n**z*n**y >>> powsimp(a, combine='exp') n**(y + z)*x**(y + z) >>> powsimp(a, combine='base') (n*x)**y*(n*x)**z >>> powsimp(a, combine='all') (n*x)**(y + z) """ if combine not in ['all', 'exp', 'base']: raise ValueError, "combine must be one of ('all', 'exp', 'base')." if combine in ('all', 'base'): expr = separate(expr, deep) y = Symbol('y', dummy=True) if expr.is_Pow: if deep: return powsimp(y*powsimp(expr.base, deep, combine)**powsimp(\ expr.exp, deep, combine), deep, combine)/y else: return powsimp(y * expr, deep, combine) / y # Trick it into being a Mul elif expr.is_Function: if expr.func == exp and deep: # Exp should really be like Pow return powsimp(y * exp(powsimp(expr.args[0], deep, combine)), deep, combine) / y elif expr.func == exp and not deep: return powsimp(y * expr, deep, combine) / y elif deep: return expr.func(*[powsimp(t, deep, combine) for t in expr.args]) else: return expr elif expr.is_Add: return C.Add(*[powsimp(t, deep, combine) for t in expr.args]) elif expr.is_Mul: if combine in ('exp', 'all'): # Collect base/exp data, while maintaining order in the # non-commutative parts of the product if combine is 'all' and deep and any( (t.is_Add for t in expr.args)): # Once we get to 'base', there is no more 'exp', so we need to # distribute here. return powsimp(expand_mul(expr, deep=False), deep, combine) c_powers = {} nc_part = [] newexpr = sympify(1) for term in expr.args: if term.is_Add and deep: newexpr *= powsimp(term, deep, combine) else: if term.is_commutative: b, e = term.as_base_exp() c_powers[b] = c_powers.get(b, 0) + e else: nc_part.append(term) newexpr = Mul(newexpr, Mul(*(Pow(b, e) for b, e in c_powers.items()))) if combine is 'exp': return Mul(newexpr, Mul(*nc_part)) else: # combine is 'all', get stuff ready for 'base' if deep: newexpr = expand_mul(newexpr, deep=False) if newexpr.is_Add: return powsimp(Mul(*nc_part), deep, combine='base') * Add( *(powsimp(i, deep, combine='base') for i in newexpr.args)) else: return powsimp(Mul(*nc_part), deep, combine='base')*\ powsimp(newexpr, deep, combine='base') else: # combine is 'base' if deep: expr = expand_mul(expr, deep=False) if expr.is_Add: return Add(*(powsimp(i, deep, combine) for i in expr.args)) else: # Build c_powers and nc_part. These must both be lists not # dicts because exp's are not combined. c_powers = [] nc_part = [] for term in expr.args: if term.is_commutative: c_powers.append(list(term.as_base_exp())) else: nc_part.append(term) # Pull out numerical coefficients from exponent # e.g., 2**(2*x) => 4**x for i in xrange(len(c_powers)): b, e = c_powers[i] exp_c, exp_t = e.as_coeff_terms() if not (exp_c is S.One) and exp_t: c_powers[i] = [C.Pow(b, exp_c), C.Mul(*exp_t)] # Combine bases whenever they have the same exponent which is # not numeric c_exp = {} for b, e in c_powers: if e in c_exp: c_exp[e].append(b) else: c_exp[e] = [b] # Merge back in the results of the above to form a new product for e in c_exp: bases = c_exp[e] if deep: simpe = powsimp(e, deep, combine) c_exp = {} for b, ex in c_powers: if ex in c_exp: c_exp[ex].append(b) else: c_exp[ex] = [b] del c_exp[e] c_exp[simpe] = bases else: simpe = e if len(bases) > 1: for b in bases: c_powers.remove([b, e]) new_base = Mul(*bases) in_c_powers = False for i in xrange(len(c_powers)): if c_powers[i][0] == new_base: if combine == 'all': c_powers[i][1] += simpe else: c_powers.append([new_base, simpe]) in_c_powers = True if not in_c_powers: c_powers.append([new_base, simpe]) c_part = [C.Pow(b, e) for b, e in c_powers] return C.Mul(*(c_part + nc_part)) else: return expr
def collect(expr, syms, evaluate=True, exact=False): """Collect additive terms with respect to a list of symbols up to powers with rational exponents. By the term symbol here are meant arbitrary expressions, which can contain powers, products, sums etc. In other words symbol is a pattern which will be searched for in the expression's terms. This function will not apply any redundant expanding to the input expression, so user is assumed to enter expression in final form. This makes 'collect' more predictable as there is no magic behind the scenes. However it is important to note, that powers of products are converted to products of powers using 'separate' function. There are two possible types of output. First, if 'evaluate' flag is set, this function will return a single expression or else it will return a dictionary with separated symbols up to rational powers as keys and collected sub-expressions as values respectively. >>> from sympy import * >>> x, y, z = symbols('x', 'y', 'z') >>> a, b, c = symbols('a', 'b', 'c') This function can collect symbolic coefficients in polynomial or rational expressions. It will manage to find all integer or rational powers of collection variable: >>> collect(a*x**2 + b*x**2 + a*x - b*x + c, x) c + x*(a - b) + x**2*(a + b) The same result can achieved in dictionary form: >>> d = collect(a*x**2 + b*x**2 + a*x - b*x + c, x, evaluate=False) >>> d[x**2] a + b >>> d[x] a - b >>> d[sympify(1)] c You can also work with multi-variate polynomials. However remember that this function is greedy so it will care only about a single symbol at time, in specification order: >>> collect(x**2 + y*x**2 + x*y + y + a*y, [x, y]) x*y + y*(1 + a) + x**2*(1 + y) Also more complicated expressions can be used as patterns: >>> collect(a*sin(2*x) + b*sin(2*x), sin(2*x)) (a + b)*sin(2*x) >>> collect(a*x*log(x) + b*(x*log(x)), x*log(x)) x*(a + b)*log(x) It is also possible to work with symbolic powers, although it has more complicated behaviour, because in this case power's base and symbolic part of the exponent are treated as a single symbol: >>> collect(a*x**c + b*x**c, x) a*x**c + b*x**c >>> collect(a*x**c + b*x**c, x**c) x**c*(a + b) However if you incorporate rationals to the exponents, then you will get well known behaviour: >>> collect(a*x**(2*c) + b*x**(2*c), x**c) (x**2)**c*(a + b) Note also that all previously stated facts about 'collect' function apply to the exponential function, so you can get: >>> collect(a*exp(2*x) + b*exp(2*x), exp(x)) (a + b)*exp(2*x) If you are interested only in collecting specific powers of some symbols then set 'exact' flag in arguments: >>> collect(a*x**7 + b*x**7, x, exact=True) a*x**7 + b*x**7 >>> collect(a*x**7 + b*x**7, x**7, exact=True) x**7*(a + b) You can also apply this function to differential equations, where derivatives of arbitary order can be collected: >>> from sympy import Derivative as D >>> f = Function('f') (x) >>> collect(a*D(f,x) + b*D(f,x), D(f,x)) (a + b)*D(f(x), x) >>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), D(f,x)) (a + b)*D(f(x), x, x) >>> collect(a*D(D(f,x),x) + b*D(D(f,x),x), D(f,x), exact=True) a*D(f(x), x, x) + b*D(f(x), x, x) >>> collect(a*D(D(f,x),x) + b*D(D(f,x),x) + a*D(f,x) + b*D(f,x), D(f,x)) (a + b)*D(f(x), x) + (a + b)*D(f(x), x, x) Or you can even match both derivative order and exponent at time:: >>> collect(a*D(D(f,x),x)**2 + b*D(D(f,x),x)**2, D(f,x)) == \\ ... (a + b)*D(D(f,x),x)**2 True == Notes == - arguments are expected to be in expanded form, so you might have tos call expand() prior to calling this function. """ def make_expression(terms): product = [] for term, rat, sym, deriv in terms: if deriv is not None: var, order = deriv while order > 0: term, order = Derivative(term, var), order - 1 if sym is None: if rat is S.One: product.append(term) else: product.append(Pow(term, rat)) else: product.append(Pow(term, rat * sym)) return Mul(*product) def parse_derivative(deriv): # scan derivatives tower in the input expression and return # underlying function and maximal differentiation order expr, sym, order = deriv.expr, deriv.symbols[0], 1 for s in deriv.symbols[1:]: if s == sym: order += 1 else: raise NotImplementedError( 'Improve MV Derivative support in collect') while isinstance(expr, Derivative): s0 = expr.symbols[0] for s in expr.symbols: if s != s0: raise NotImplementedError( 'Improve MV Derivative support in collect') if s0 == sym: expr, order = expr.expr, order + len(expr.symbols) else: break return expr, (sym, Rational(order)) def parse_term(expr): """Parses expression expr and outputs tuple (sexpr, rat_expo, sym_expo, deriv) where: - sexpr is the base expression - rat_expo is the rational exponent that sexpr is raised to - sym_expo is the symbolic exponent that sexpr is raised to - deriv contains the derivatives the the expression for example, the output of x would be (x, 1, None, None) the output of 2**x would be (2, 1, x, None) """ rat_expo, sym_expo = S.One, None sexpr, deriv = expr, None if expr.is_Pow: if isinstance(expr.base, Derivative): sexpr, deriv = parse_derivative(expr.base) else: sexpr = expr.base if expr.exp.is_Rational: rat_expo = expr.exp elif expr.exp.is_Mul: coeff, tail = expr.exp.as_coeff_terms() if coeff.is_Rational: rat_expo, sym_expo = coeff, C.Mul(*tail) else: sym_expo = expr.exp else: sym_expo = expr.exp elif expr.func is C.exp: if expr.args[0].is_Rational: sexpr, rat_expo = S.Exp1, expr.args[0] elif expr.args[0].is_Mul: coeff, tail = expr.args[0].as_coeff_terms() if coeff.is_Rational: sexpr, rat_expo = C.exp(C.Mul(*tail)), coeff elif isinstance(expr, Derivative): sexpr, deriv = parse_derivative(expr) return sexpr, rat_expo, sym_expo, deriv def parse_expression(terms, pattern): """Parse terms searching for a pattern. terms is a list of tuples as returned by parse_terms pattern is an expression """ pattern = make_list(pattern, Mul) if len(terms) < len(pattern): # pattern is longer than matched product # so no chance for positive parsing result return None else: pattern = [parse_term(elem) for elem in pattern] elems, common_expo, has_deriv = [], None, False for elem, e_rat, e_sym, e_ord in pattern: if e_ord is not None: # there is derivative in the pattern so # there will by small performance penalty has_deriv = True for j in range(len(terms)): term, t_rat, t_sym, t_ord = terms[j] if elem.is_Number: # a constant is a match for everything break if elem == term and e_sym == t_sym: if exact == False: # we don't have to exact so find common exponent # for both expression's term and pattern's element expo = t_rat / e_rat if common_expo is None: # first time common_expo = expo else: # common exponent was negotiated before so # teher is no chance for pattern match unless # common and current exponents are equal if common_expo != expo: common_expo = 1 else: # we ought to be exact so all fields of # interest must match in very details if e_rat != t_rat or e_ord != t_ord: continue # found common term so remove it from the expression # and try to match next element in the pattern elems.append(terms[j]) del terms[j] break else: # pattern element not found return None return terms, elems, common_expo, has_deriv if evaluate: if expr.is_Mul: ret = 1 for term in expr.args: ret *= collect(term, syms, True, exact) return ret elif expr.is_Pow: b = collect(expr.base, syms, True, exact) return C.Pow(b, expr.exp) summa = [separate(i) for i in make_list(sympify(expr), Add)] if isinstance(syms, list): syms = [separate(s) for s in syms] else: syms = [separate(syms)] collected, disliked = {}, S.Zero for product in summa: terms = [parse_term(i) for i in make_list(product, Mul)] for symbol in syms: if SYMPY_DEBUG: print "DEBUG: parsing of expression %s with symbol %s " % ( str(terms), str(symbol)) result = parse_expression(terms, symbol) if SYMPY_DEBUG: print "DEBUG: returned %s" % str(result) if result is not None: terms, elems, common_expo, has_deriv = result # when there was derivative in current pattern we # will need to rebuild its expression from scratch if not has_deriv: index = 1 for elem in elems: index *= Pow(elem[0], elem[1]) if elem[2] is not None: index **= elem[2] else: index = make_expression(elems) terms = separate(make_expression(terms)) index = separate(index) if index in collected.keys(): collected[index] += terms else: collected[index] = terms break else: # none of the patterns matched disliked += product if disliked is not S.Zero: collected[S.One] = disliked if evaluate: return Add(*[a * b for a, b in collected.iteritems()]) else: return collected
def root(arg, n, k=0): """root(x, n, k) -> Returns the k-th n-th root of x, defaulting to the principle root (k=0). Examples ======== >>> from sympy import root, Rational >>> from sympy.abc import x, n >>> root(x, 2) sqrt(x) >>> root(x, 3) x**(1/3) >>> root(x, n) x**(1/n) >>> root(x, -Rational(2, 3)) x**(-3/2) To get the k-th n-th root, specify k: >>> root(-2, 3, 2) -(-1)**(2/3)*2**(1/3) To get all n n-th roots you can use the RootOf function. The following examples show the roots of unity for n equal 2, 3 and 4: >>> from sympy import RootOf, I >>> [ RootOf(x**2 - 1, i) for i in range(2) ] [-1, 1] >>> [ RootOf(x**3 - 1,i) for i in range(3) ] [1, -1/2 - sqrt(3)*I/2, -1/2 + sqrt(3)*I/2] >>> [ RootOf(x**4 - 1,i) for i in range(4) ] [-1, 1, -I, I] SymPy, like other symbolic algebra systems, returns the complex root of negative numbers. This is the principal root and differs from the text-book result that one might be expecting. For example, the cube root of -8 does not come back as -2: >>> root(-8, 3) 2*(-1)**(1/3) The real_root function can be used to either make the principle result real (or simply to return the real root directly): >>> from sympy import real_root >>> real_root(_) -2 >>> real_root(-32, 5) -2 Alternatively, the n//2-th n-th root of a negative number can be computed with root: >>> root(-32, 5, 5//2) -2 See Also ======== sympy.polys.rootoftools.RootOf sympy.core.power.integer_nthroot sqrt, real_root References ========== * http://en.wikipedia.org/wiki/Square_root * http://en.wikipedia.org/wiki/Real_root * http://en.wikipedia.org/wiki/Root_of_unity * http://en.wikipedia.org/wiki/Principal_value * http://mathworld.wolfram.com/CubeRoot.html """ n = sympify(n) if k: return C.Pow(arg, S.One/n)*S.NegativeOne**(2*k/n) return C.Pow(arg, 1/n)