예제 #1
0
    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)
예제 #2
0
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
예제 #3
0
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)
예제 #4
0
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)
예제 #5
0
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)
예제 #6
0
    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)
예제 #7
0
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))
예제 #8
0
파일: latex.py 프로젝트: songuke/sympy
    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))
예제 #9
0
    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)
예제 #10
0
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)
예제 #11
0
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)
예제 #12
0
def sqrt(arg):
    # arg = sympify(arg) is handled by Pow
    return C.Pow(arg, S.Half)
예제 #13
0
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
예제 #14
0
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
예제 #15
0
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)