Ejemplo n.º 1
0
    def _eval_subs(self, old, new):
        if self == old: return new
        arg = self.args[0]
        o = old
        if old.is_Pow:  # handle (exp(3*log(x))).subs(x**2, z) -> z**(3/2)
            old = exp(old.exp * log(old.base))
        if old.func is exp:
            # exp(a*expr) .subs( exp(b*expr), y )  ->  y ** (a/b)
            a, expr_terms = self.args[0].as_coeff_terms()
            b, expr_terms_ = old.args[0].as_coeff_terms()

            if expr_terms == expr_terms_:
                return new**(a / b)

            if arg.is_Add:  # exp(2*x+a).subs(exp(3*x),y) -> y**(2/3) * exp(a)
                # exp(exp(x) + exp(x**2)).subs(exp(exp(x)), w) -> w * exp(exp(x**2))
                oarg = old.args[0]
                new_l = []
                old_al = []
                coeff2, terms2 = oarg.as_coeff_terms()
                for a in arg.args:
                    a = a._eval_subs(old, new)
                    coeff1, terms1 = a.as_coeff_terms()
                    if terms1 == terms2:
                        new_l.append(new**(coeff1 / coeff2))
                    else:
                        old_al.append(a._eval_subs(old, new))
                if new_l:
                    new_l.append(self.func(C.Add(*old_al)))
                    r = C.Mul(*new_l)
                    return r
        old = o
        return Function._eval_subs(self, old, new)
Ejemplo n.º 2
0
 def _eval_as_leading_term(self, x):
     arg = self.args[0]
     if arg.is_Add:
         return C.Mul(*[exp(f).as_leading_term(x) for f in arg.args])
     arg = self.args[0].as_leading_term(x)
     if C.Order(1, x).contains(arg):
         return S.One
     return exp(arg)
Ejemplo n.º 3
0
    def _print_Mul(self, expr):
        coeff, terms = expr.as_coeff_terms()

        if not coeff.is_negative:
            tex = ""
        else:
            coeff = -coeff
            tex = "- "

        numer, denom = fraction(C.Mul(*terms))

        def convert(terms):
            product = []

            if not terms.is_Mul:
                return str(self._print(terms))
            else:
                for term in terms.args:
                    pretty = self._print(term)

                    if term.is_Add:
                        product.append(r"\left(%s\right)" % pretty)
                    else:
                        product.append(str(pretty))

                return r" ".join(product)

        if denom is S.One:
            if coeff is not S.One:
                tex += str(self._print(coeff)) + " "

            if numer.is_Add:
                tex += r"\left(%s\right)" % convert(numer)
            else:
                tex += r"%s" % convert(numer)
        else:
            if numer is S.One:
                if coeff.is_Integer:
                    numer *= coeff.p
                elif coeff.is_Rational:
                    if coeff.p != 1:
                        numer *= coeff.p

                    denom *= coeff.q
                elif coeff is not S.One:
                    tex += str(self._print(coeff)) + " "
            else:
                if coeff.is_Rational and coeff.p == 1:
                    denom *= coeff.q
                elif coeff is not S.One:
                    tex += str(self._print(coeff)) + " "

            tex += r"\frac{%s}{%s}" % \
                (convert(numer), convert(denom))

        return tex
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
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
Ejemplo n.º 6
0
    def eval(cls, arg):
        if arg.is_Number:
            if arg is S.NaN:
                return S.NaN
            elif arg is S.Zero:
                return S.One
            elif arg is S.One:
                return S.Exp1
            elif arg is S.Infinity:
                return S.Infinity
            elif arg is S.NegativeInfinity:
                return S.Zero
        elif arg.func is log:
            return arg.args[0]
        elif arg.is_Mul:
            coeff = arg.as_coefficient(S.Pi * S.ImaginaryUnit)

            if coeff is not None:
                if (2 * coeff).is_integer:
                    if coeff.is_even:
                        return S.One
                    elif coeff.is_odd:
                        return S.NegativeOne
                    elif (coeff + S.Half).is_even:
                        return -S.ImaginaryUnit
                    elif (coeff + S.Half).is_odd:
                        return S.ImaginaryUnit
            I = S.ImaginaryUnit
            oo = S.Infinity
            a = Wild("a", exclude=[I, oo])
            r = arg.match(I * a * oo)
            if r and r[a] != 0:
                return S.NaN

        if arg.is_Add:
            args = arg.args
        else:
            args = [arg]

        included, excluded = [], []

        for arg in args:
            coeff, terms = arg.as_coeff_terms()

            if coeff is S.Infinity:
                excluded.append(coeff**C.Mul(*terms))
            else:
                coeffs, log_term = [coeff], None

                for term in terms:
                    if term.func is log:
                        if log_term is None:
                            log_term = term.args[0]
                        else:
                            log_term = None
                            break
                    elif term.is_comparable:
                        coeffs.append(term)
                    else:
                        log_term = None
                        break

                if log_term is not None:
                    excluded.append(log_term**C.Mul(*coeffs))
                else:
                    included.append(arg)

        if excluded:
            return C.Mul(*(excluded + [cls(C.Add(*included))]))
Ejemplo n.º 7
0
 def as_base_exp(self):
     return S.Exp1, C.Mul(*self.args)
Ejemplo n.º 8
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
Ejemplo n.º 9
0
    def _together(expr):

        from sympy.core.function import Function

        if expr.is_Add:
            items, coeffs, basis = [], [], {}

            for elem in expr.args:
                numer, q = fraction(_together(elem))

                denom = {}

                for term in make_list(q.expand(), Mul):
                    expo = S.One
                    coeff = S.One

                    if term.is_Pow:
                        if term.exp.is_Rational:
                            term, expo = term.base, term.exp
                        elif term.exp.is_Mul:
                            coeff, tail = term.exp.as_coeff_terms()
                            if coeff.is_Rational:
                                tail = C.Mul(*tail)
                                term, expo = Pow(term.base, tail), coeff
                        coeff = S.One
                    elif term.func is C.exp:
                        if term.args[0].is_Rational:
                            term, expo = S.Exp1, term.args[0]
                        elif term.args[0].is_Mul:
                            coeff, tail = term.args[0].as_coeff_terms()
                            if coeff.is_Rational:
                                tail = C.Mul(*tail)
                                term, expo = C.exp(tail), coeff
                        coeff = S.One
                    elif term.is_Rational:
                        coeff = Integer(term.q)
                        term = Integer(term.p)

                    if term in denom:
                        denom[term] += expo
                    else:
                        denom[term] = expo

                    if term in basis:
                        total, maxi = basis[term]

                        n_total = total + expo
                        n_maxi = max(maxi, expo)

                        basis[term] = (n_total, n_maxi)
                    else:
                        basis[term] = (expo, expo)

                    coeffs.append(coeff)
                items.append((numer, denom))

            numerator, denominator = [], []

            for (term, (total, maxi)) in basis.iteritems():
                basis[term] = (total, total - maxi)

                if term.func is C.exp:
                    denominator.append(C.exp(maxi * term.args[0]))
                else:
                    if maxi is S.One:
                        denominator.append(term)
                    else:
                        denominator.append(Pow(term, maxi))

            if all([c.is_integer for c in coeffs]):
                gcds = lambda x, y: igcd(int(x), int(y))
                common = Rational(reduce(gcds, coeffs))
            else:
                common = S.One

            product = Mul(*coeffs) / common

            for ((numer, denom), coeff) in zip(items, coeffs):

                expr, coeff = [], product / (coeff * common)

                for term in basis.iterkeys():
                    total, sub = basis[term]

                    if term in denom:
                        expo = total - denom[term] - sub
                    else:
                        expo = total - sub

                    if term.func is C.exp:
                        expr.append(C.exp(expo * term.args[0]))
                    else:
                        if expo is S.One:
                            expr.append(term)
                        else:
                            expr.append(Pow(term, expo))

                numerator.append(coeff * Mul(*([numer] + expr)))

            return Add(*numerator) / (product * Mul(*denominator))
        elif expr.is_Mul or expr.is_Pow:
            return type(expr)(*[_together(t) for t in expr.args])
        elif expr.is_Function and deep:
            return expr.func(*[_together(t) for t in expr.args])
        else:
            return expr
Ejemplo n.º 10
0
 def _eval_rewrite_as_Heaviside(self, *args):
     return C.Add(*[j*C.Mul(*[C.Heaviside(i-j) for i in args if i!=j]) \
             for j in args])
Ejemplo n.º 11
0
    def _print_Mul(self, expr):
        coeff, terms = expr.as_coeff_terms()

        if not coeff.is_negative:
            tex = ""
        else:
            coeff = -coeff
            tex = "- "

        numer, denom = fraction(C.Mul(*terms))
        seperator = self._settings['mul_symbol_latex']

        def convert(terms):
            if not terms.is_Mul:
                return str(self._print(terms))
            else:
                _tex = last_term_tex = ""
                for term in terms.args:
                    pretty = self._print(term)

                    if term.is_Add:
                        term_tex = (r"\left(%s\right)" % pretty)
                    else:
                        term_tex = str(pretty)

                    # between two digits, \times must always be used,
                    # to avoid confusion
                    if seperator == " " and \
                            re.search("[0-9][} ]*$", last_term_tex) and \
                            re.match("[{ ]*[-+0-9]", term_tex):
                        _tex += r" \times "
                    elif _tex:
                        _tex += seperator

                    _tex += term_tex
                    last_term_tex = term_tex
                return _tex

        if denom is S.One:
            if numer.is_Add:
                _tex = r"\left(%s\right)" % convert(numer)
            else:
                _tex = r"%s" % convert(numer)

            if coeff is not S.One:
                tex += str(self._print(coeff))

                # between two digits, \times must always be used, to avoid
                # confusion
                if seperator == " " and re.search("[0-9][} ]*$", tex) and \
                        re.match("[{ ]*[-+0-9]", _tex):
                    tex += r" \times " + _tex
                else:
                    tex += seperator + _tex
            else:
                tex += _tex

        else:
            if numer is S.One:
                if coeff.is_Integer:
                    numer *= coeff.p
                elif coeff.is_Rational:
                    if coeff.p != 1:
                        numer *= coeff.p

                    denom *= coeff.q
                elif coeff is not S.One:
                    tex += str(self._print(coeff)) + " "
            else:
                if coeff.is_Rational and coeff.p == 1:
                    denom *= coeff.q
                elif coeff is not S.One:
                    tex += str(self._print(coeff)) + " "

            tex += r"\frac{%s}{%s}" % \
                (convert(numer), convert(denom))

        return tex
Ejemplo n.º 12
0
    def __new__(cls, expr, *symbols, **assumptions):
        expr = sympify(expr).expand()
        if expr is S.NaN:
            return S.NaN

        if symbols:
            symbols = map(sympify, symbols)
        else:
            symbols = list(expr.atoms(C.Symbol))

        symbols.sort(Basic.compare)

        if expr.is_Order:

            new_symbols = list(expr.symbols)
            for s in symbols:
                if s not in new_symbols:
                    new_symbols.append(s)
            if len(new_symbols)==len(expr.symbols):
                return expr
            symbols = new_symbols

        elif symbols:

            symbol_map = {}
            new_symbols = []
            for s in symbols:
                if isinstance(s, C.Symbol):
                    new_symbols.append(s)
                    continue
                z = C.Symbol('z',dummy=True)
                x1,s1 = solve4linearsymbol(s, z)
                expr = expr.subs(x1,s1)
                symbol_map[z] = s
                new_symbols.append(z)

            if symbol_map:
                r = Order(expr, *new_symbols, **assumptions)
                expr = r.expr.subs(symbol_map)
                symbols = []
                for s in r.symbols:
                    if symbol_map.has_key(s):
                        symbols.append(symbol_map[s])
                    else:
                        symbols.append(s)
            else:
                if expr.is_Add:
                    lst = expr.extract_leading_order(*symbols)
                    expr = C.Add(*[f.expr for (e,f) in lst])
                else:
                    expr = expr.as_leading_term(*symbols)
                    coeff, terms = expr.as_coeff_terms()
                    if coeff is S.Zero:
                        return coeff
                    expr = C.Mul(*[t for t in terms if t.has(*symbols)])

        elif expr is not S.Zero:
            expr = S.One

        if expr is S.Zero:
            return expr

        # create Order instance:
        obj = Expr.__new__(cls, expr, *symbols, **assumptions)

        return obj
Ejemplo n.º 13
0
    def _print_Mul(self, expr):
        coeff, terms = expr.as_coeff_terms()

        if not coeff.is_negative:
            tex = ""
        else:
            coeff = -coeff
            tex = "- "

        numer, denom = fraction(C.Mul(*terms))

        mul_symbol_table = {
            None: r" ",
            "ldot": r" \,.\, ",
            "dot": r" \cdot ",
            "times": r" \times "
        }

        seperator = mul_symbol_table[self._settings['mul_symbol']]

        def convert(terms):
            product = []

            if not terms.is_Mul:
                return str(self._print(terms))
            else:
                for term in terms.args:
                    pretty = self._print(term)

                    if term.is_Add:
                        product.append(r"\left(%s\right)" % pretty)
                    else:
                        product.append(str(pretty))

                return seperator.join(product)

        if denom is S.One:
            if coeff is not S.One:
                tex += str(self._print(coeff)) + seperator

            if numer.is_Add:
                tex += r"\left(%s\right)" % convert(numer)
            else:
                tex += r"%s" % convert(numer)
        else:
            if numer is S.One:
                if coeff.is_Integer:
                    numer *= coeff.p
                elif coeff.is_Rational:
                    if coeff.p != 1:
                        numer *= coeff.p

                    denom *= coeff.q
                elif coeff is not S.One:
                    tex += str(self._print(coeff)) + " "
            else:
                if coeff.is_Rational and coeff.p == 1:
                    denom *= coeff.q
                elif coeff is not S.One:
                    tex += str(self._print(coeff)) + " "

            tex += r"\frac{%s}{%s}" % \
                (convert(numer), convert(denom))

        return tex