コード例 #1
0
 def as_coeff_exponent(self, x):
     """ c*x**e -> c,e where x can be any symbolic expression.
     """
     x = sympify(x)
     wc = Wild('wc')
     we = Wild('we')
     p  = wc*x**we
     from sympy import collect
     s = collect(self, x)
     d = s.match(p)
     if d is not None and we in d:
         return d[wc], d[we]
     return s, S.Zero
コード例 #2
0
    def as_coefficient(self, expr):
        """Extracts symbolic coefficient at the given expression. In
           other words, this functions separates 'self' into product
           of 'expr' and 'expr'-free coefficient. If such separation
           is not possible it will return None.

           >>> from sympy import E, pi, sin, I
           >>> from sympy.abc import x, y

           >>> E.as_coefficient(E)
           1
           >>> (2*E).as_coefficient(E)
           2

           >>> (2*E + x).as_coefficient(E)
           >>> (2*sin(E)*E).as_coefficient(E)

           >>> (2*pi*I).as_coefficient(pi*I)
           2

           >>> (2*I).as_coefficient(pi*I)

        """
        if expr.is_Add:
            return None
        else:
            w = Wild('w')

            coeff = self.match(w * expr)

            if coeff is not None:
                if expr.is_Mul:
                    args = expr.args
                else:
                    args = [expr]

                if coeff[w].has(*args):
                    return None
                else:
                    return coeff[w]
            else:
                return None
コード例 #3
0
ファイル: power.py プロジェクト: jcockayne/sympy-rkern
    def _eval_nseries(self, x, x0, n):
        def geto(e):
            "Returns the O(..) symbol, or None if there is none."
            if e.is_Order:
                return e
            if e.is_Add:
                for x in e.args:
                    if x.is_Order:
                        return x

        def getn(e):
            """
            Returns the order of the expression "e".

            The order is determined either from the O(...) term. If there
            is no O(...) term, it returns None.

            Example:
            >>> getn(1+x+O(x**2))
            2
            >>> getn(1+x)
            >>>
            """
            o = geto(e)
            if o is None:
                return None
            else:
                o = o.expr
                if o.is_Symbol:
                    return Integer(1)
                if o.is_Pow:
                    return o.args[1]
                n, d = o.as_numer_denom()
                if isinstance(d, log):
                    # i.e. o = x**2/log(x)
                    if n.is_Symbol:
                        return Integer(1)
                    if n.is_Pow:
                        return n.args[1]

            raise Exception("Unimplemented")

        base, exp = self.args
        if exp.is_Integer:
            if exp > 0:
                # positive integer powers are easy to expand, e.g.:
                # sin(x)**4 = (x-x**3/3+...)**4 = ...
                return (base.nseries(x, x0, n) ** exp).expand()
            elif exp == -1:
                # this is also easy to expand using the formula:
                # 1/(1 + x) = 1 + x + x**2 + x**3 ...
                # so we need to rewrite base to the form "1+x"
                from sympy import log
                if base.has(log(x)):
                    # we need to handle the log(x) singularity:
                    assert x0 == 0
                    y = Symbol("y", dummy=True)
                    p = self.subs(log(x), -1/y)
                    if not p.has(x):
                        p = p.nseries(y, x0, n)
                        p = p.subs(y, -1/log(x))
                        return p
                base = base.nseries(x, x0, n)
                if base.has(log(x)):
                    # we need to handle the log(x) singularity:
                    assert x0 == 0
                    y = Symbol("y", dummy=True)
                    self0 = 1/base
                    p = self0.subs(log(x), -1/y)
                    if not p.has(x):
                        p = p.nseries(y, x0, n)
                        p = p.subs(y, -1/log(x))
                        return p
                prefactor = base.as_leading_term(x)
                # express "rest" as: rest = 1 + k*x**l + ... + O(x**n)
                rest = ((base-prefactor)/prefactor).expand()
                if rest == 0:
                    # if prefactor == w**4 + x**2*w**4 + 2*x*w**4, we need to
                    # factor the w**4 out using collect:
                    from sympy import collect
                    return 1/collect(prefactor, x)
                if rest.is_Order:
                    return ((1+rest)/prefactor).expand()
                if not rest.has(x):
                    return 1/(prefactor*(rest+1))
                n2 = getn(rest)
                if n2 is not None:
                    n = n2
                term2 = rest.as_leading_term(x)
                k, l = Wild("k"), Wild("l")
                r = term2.match(k*x**l)
                k, l = r[k], r[l]
                if l.is_Integer:
                    l = int(l)
                elif l.is_number:
                    l = float(l)
                else:
                    raise Exception("Not implemented")

                s = 1
                m = 1
                while l * m < n:
                    s += ((-rest)**m).expand()
                    m += 1
                r = (s/prefactor).expand()
                if n2 is None:
                    # Append O(...) because it is not included in "r"
                    from sympy import O
                    r += O(x**n)
                return r
            else:
                # negative powers are rewritten to the cases above, for example:
                # sin(x)**(-4) = 1/( sin(x)**4) = ...
                # and expand the denominator:
                denominator = (base**(-exp)).nseries(x, x0, n)
                if 1/denominator == self:
                    return self
                # now we have a type 1/f(x), that we know how to expand
                return (1/denominator).nseries(x, x0, n)

        if exp.has(x):
            import sympy
            return sympy.exp(exp*sympy.log(base)).nseries(x, x0, n)

        if base == x:
            return self

        order = C.Order(x**n, x)
        x = order.symbols[0]
        e = self.exp
        b = self.base
        ln = C.log
        exp = C.exp
        if e.has(x):
            return exp(e * ln(b)).nseries(x, x0, n)
        if b==x: return self
        b0 = b.limit(x,0)
        if b0 is S.Zero or b0.is_unbounded:
            lt = b.as_leading_term(x)
            o = order * lt**(1-e)
            bs = b.nseries(x, x0, n-e)
            if bs.is_Add:
                bs = bs.removeO()
            if bs.is_Add:
                # bs -> lt + rest -> lt * (1 + (bs/lt - 1))
                return (lt**e * ((bs/lt).expand()**e).nseries(x,
                        x0, n-e)).expand() + order
            return bs**e+order
        o2 = order * (b0**-e)
        # b -> b0 + (b-b0) -> b0 * (1 + (b/b0-1))
        z = (b/b0-1)
        #r = self._compute_oseries3(z, o2, self.taylor_term)
        x = o2.symbols[0]
        ln = C.log
        o = C.Order(z, x)
        if o is S.Zero:
            r = (1+z)
        else:
            if o.expr.is_number:
                e2 = ln(o2.expr*x)/ln(x)
            else:
                e2 = ln(o2.expr)/ln(o.expr)
            n = e2.limit(x,0) + 1
            if n.is_unbounded:
                # requested accuracy gives infinite series,
                # order is probably nonpolynomial e.g. O(exp(-1/x), x).
                r = (1+z)
            else:
                try:
                    n = int(n)
                except TypeError:
                    #well, the n is something more complicated (like 1+log(2))
                    n = int(n.evalf()) + 1
                assert n>=0,`n`
                l = []
                g = None
                for i in xrange(n+2):
                    g = self.taylor_term(i, z, g)
                    g = g.nseries(x, x0, n)
                    l.append(g)
                r = Add(*l)
        return r * b0**e + order
コード例 #4
0
    def _eval_nseries(self, x, n):
        from sympy import powsimp, collect, exp, log, O, ceiling

        b, e = self.args
        if e.is_Integer:
            if e > 0:
                # positive integer powers are easy to expand, e.g.:
                # sin(x)**4 = (x-x**3/3+...)**4 = ...
                return Pow(b._eval_nseries(x, n=n),
                           e)._eval_expand_multinomial(deep=False)
            elif e is S.NegativeOne:
                # this is also easy to expand using the formula:
                # 1/(1 + x) = 1 + x + x**2 + x**3 ...
                # so we need to rewrite base to the form "1+x"
                if b.has(log(x)):
                    # we need to handle the log(x) singularity:
                    y = Dummy("y")
                    p = self.subs(log(x), -1 / y)
                    if not p.has(x):
                        p = p._eval_nseries(y, n=n)
                        p = p.subs(y, -1 / log(x))
                        return p

                b = b._eval_nseries(x, n=n)
                if b.has(log(x)):
                    # we need to handle the log(x) singularity:
                    y = Dummy("y")
                    self0 = 1 / b
                    p = self0.subs(log(x), -1 / y)
                    if not p.has(x):
                        p = p._eval_nseries(y, n=n)
                        p = p.subs(y, -1 / log(x))
                        return p
                prefactor = b.as_leading_term(x)
                # express "rest" as: rest = 1 + k*x**l + ... + O(x**n)
                rest = ((b - prefactor) / prefactor)._eval_expand_mul()
                if rest == 0:
                    # if prefactor == w**4 + x**2*w**4 + 2*x*w**4, we need to
                    # factor the w**4 out using collect:
                    return 1 / collect(prefactor, x)
                if rest.is_Order:
                    return (1 + rest) / prefactor
                n2 = rest.getn()
                if n2 is not None:
                    n = n2

                term2 = collect(rest.as_leading_term(x), x)
                k, l = Wild("k"), Wild("l")
                r = term2.match(k * x**l)
                # if term2 is NaN then r will not contain l
                k = r.get(k, S.One)
                l = r.get(l, S.Zero)
                if l.is_Rational and l > 0:
                    pass
                elif l.is_number and l > 0:
                    l = l.evalf()
                else:
                    raise NotImplementedError()

                terms = [1 / prefactor]
                for m in xrange(1, ceiling(n / l)):
                    new_term = terms[-1] * (-rest)
                    if new_term.is_Pow:
                        new_term = new_term._eval_expand_multinomial(
                            deep=False)
                    else:
                        new_term = new_term._eval_expand_mul(deep=False)
                    terms.append(new_term)
                if n2 is None:
                    # Append O(...) because it is not included in "r"
                    terms.append(O(x**n))
                return powsimp(Add(*terms), deep=True, combine='exp')
            else:
                # negative powers are rewritten to the cases above, for example:
                # sin(x)**(-4) = 1/( sin(x)**4) = ...
                # and expand the denominator:
                denominator = (b**(-e))._eval_nseries(x, n=n)
                if 1 / denominator == self:
                    return self
                # now we have a type 1/f(x), that we know how to expand
                return (1 / denominator)._eval_nseries(x, n=n)

        if e.has(x):
            return exp(e * log(b))._eval_nseries(x, n=n)

        if b == x:
            return powsimp(self, deep=True, combine='exp')

        # work for b(x)**e where e is not an Integer and does not contain x
        # and hopefully has no other symbols

        def e2int(e):
            """return the integer value (if possible) of e and a
            flag indicating whether it is bounded or not."""
            n = e.limit(x, 0)
            unbounded = n.is_unbounded
            if not unbounded:
                # XXX was int or floor intended? int used to behave like floor
                # so int(-Rational(1, 2)) returned -1 rather than int's 0
                try:
                    n = int(n)
                except TypeError:
                    #well, the n is something more complicated (like 1+log(2))
                    try:
                        n = int(n.evalf()) + 1  # XXX why is 1 being added?
                    except TypeError:
                        pass  # hope that base allows this to be resolved
                n = _sympify(n)
            return n, unbounded

        order = O(x**n, x)
        ei, unbounded = e2int(e)
        b0 = b.limit(x, 0)
        if unbounded and (b0 is S.One or b0.has(Symbol)):
            # XXX what order
            if b0 is S.One:
                resid = (b - 1)
                if resid.is_positive:
                    return S.Infinity
                elif resid.is_negative:
                    return S.Zero
                raise ValueError('cannot determine sign of %s' % resid)

            return b0**ei

        if (b0 is S.Zero or b0.is_unbounded):
            if unbounded is not False:
                return b0**e  # XXX what order

            if not ei.is_number:  # if not, how will we proceed?
                raise ValueError('expecting numerical exponent but got %s' %
                                 ei)

            nuse = n - ei
            lt = b.as_leading_term(x)
            #  XXX o is not used -- was this to be used as o and o2 below to compute a new e?
            o = order * lt**(1 - e)
            bs = b._eval_nseries(x, n=nuse)
            if bs.is_Add:
                bs = bs.removeO()
            if bs.is_Add:
                # bs -> lt + rest -> lt*(1 + (bs/lt - 1))
                return ((Pow(lt, e) * Pow(
                    (bs / lt).expand(), e).nseries(x, n=nuse)).expand() +
                        order)

            return bs**e + order

        # either b0 is bounded but neither 1 nor 0 or e is unbounded
        # b -> b0 + (b-b0) -> b0 * (1 + (b/b0-1))
        o2 = order * (b0**-e)
        z = (b / b0 - 1)
        o = O(z, x)
        #r = self._compute_oseries3(z, o2, self.taylor_term)
        if o is S.Zero or o2 is S.Zero:
            unbounded = True
        else:
            if o.expr.is_number:
                e2 = log(o2.expr * x) / log(x)
            else:
                e2 = log(o2.expr) / log(o.expr)
            n, unbounded = e2int(e2)
        if unbounded:
            # requested accuracy gives infinite series,
            # order is probably nonpolynomial e.g. O(exp(-1/x), x).
            r = 1 + z
        else:
            l = []
            g = None
            for i in xrange(n + 2):
                g = self.taylor_term(i, z, g)
                g = g.nseries(x, n=n)
                l.append(g)
            r = Add(*l)
        return r * b0**e + order