Exemple #1
0
 def search(expr, test):
     if not isinstance(expr, Basic):
         try:
             return any(search(i, test) for i in expr)
         except TypeError:
             return False
     elif test(expr):
         return True
     else:
         return any(search(i, test) for i in expr.iter_basic_args())
Exemple #2
0
 def search(expr, test):
     if not isinstance(expr, Basic):
         try:
             return any(search(i, test) for i in expr)
         except TypeError:
             return False
     elif test(expr):
         return True
     else:
         return any(search(i, test) for i in expr.iter_basic_args())
Exemple #3
0
    def has(self, *patterns):
        """
        Test whether any subexpression matches any of the patterns.

        Examples:
        >>> from sympy import sin, S
        >>> from sympy.abc import x, y, z
        >>> (x**2 + sin(x*y)).has(z)
        False
        >>> (x**2 + sin(x*y)).has(x, y, z)
        True
        >>> x.has(x)
        True

        Note that ``expr.has(*patterns)`` is exactly equivalent to
        ``any(expr.has(p) for p in patterns)``. In particular, ``False`` is
        returned when the list of patterns is empty.
        >>> x.has()
        False

        """

        def search(expr, test):
            if not isinstance(expr, Basic):
                try:
                    return any(search(i, test) for i in expr)
                except TypeError:
                    return False
            elif test(expr):
                return True
            else:
                return any(search(i, test) for i in expr.iter_basic_args())

        def _match(p):
            if isinstance(p, BasicType):
                return lambda w: isinstance(w, p)
            else:
                return lambda w: p.matches(w) is not None

        patterns = map(sympify, patterns)
        return any(search(self, _match(p)) for p in patterns)
Exemple #4
0
    def has(self, *patterns):
        """
        Test whether any subexpression matches any of the patterns.

        Examples:
        >>> from sympy import sin, S
        >>> from sympy.abc import x, y, z
        >>> (x**2 + sin(x*y)).has(z)
        False
        >>> (x**2 + sin(x*y)).has(x, y, z)
        True
        >>> x.has(x)
        True

        Note that ``expr.has(*patterns)`` is exactly equivalent to
        ``any(expr.has(p) for p in patterns)``. In particular, ``False`` is
        returned when the list of patterns is empty.
        >>> x.has()
        False

        """
        def search(expr, test):
            if not isinstance(expr, Basic):
                try:
                    return any(search(i, test) for i in expr)
                except TypeError:
                    return False
            elif test(expr):
                return True
            else:
                return any(search(i, test) for i in expr.iter_basic_args())

        def _match(p):
            if isinstance(p, BasicType):
                return lambda w: isinstance(w, p)
            else:
                return lambda w: p.matches(w) is not None

        patterns = map(sympify, patterns)
        return any(search(self, _match(p)) for p in patterns)
Exemple #5
0
    def as_ordered_terms(self, order=None, data=False):
        """
        Transform an expression to an ordered list of terms.

        **Examples**

        >>> from sympy import sin, cos
        >>> from sympy.abc import x, y

        >>> (sin(x)**2*cos(x) + sin(x)**2 + 1).as_ordered_terms()
        [sin(x)**2*cos(x), sin(x)**2, 1]

        """
        from sympy.utilities import any

        key, reverse = self._parse_order(order)
        terms, gens = self.as_terms()

        if not any(term.is_Order for term, _ in terms):
            ordered = sorted(terms, key=key, reverse=not reverse)
        else:
            _terms, _order = [], []

            for term, repr in terms:
                if not term.is_Order:
                    _terms.append((term, repr))
                else:
                    _order.append((term, repr))

            ordered = sorted(_terms, key=key) \
                    + sorted(_order, key=key)

        if data:
            return ordered, gens
        else:
            return [ term for term, _ in ordered ]
Exemple #6
0
    def as_ordered_terms(self, order=None, data=False):
        """
        Transform an expression to an ordered list of terms.

        **Examples**

        >>> from sympy import sin, cos
        >>> from sympy.abc import x, y

        >>> (sin(x)**2*cos(x) + sin(x)**2 + 1).as_ordered_terms()
        [sin(x)**2*cos(x), sin(x)**2, 1]

        """
        from sympy.utilities import any

        key, reverse = self._parse_order(order)
        terms, gens = self.as_terms()

        if not any(term.is_Order for term, _ in terms):
            ordered = sorted(terms, key=key, reverse=not reverse)
        else:
            _terms, _order = [], []

            for term, repr in terms:
                if not term.is_Order:
                    _terms.append((term, repr))
                else:
                    _order.append((term, repr))

            ordered = sorted(_terms, key=key) \
                    + sorted(_order, key=key)

        if data:
            return ordered, gens
        else:
            return [term for term, _ in ordered]
Exemple #7
0
    def _eval_subs(self, old, new):

        from sympy import sign
        from sympy.simplify.simplify import powdenest

        if self == old:
            return new

        def fallback():
            """Return this value when partial subs has failed."""

            return self.__class__(*[s._eval_subs(old, new) for s in self.args])

        def breakup(eq):
            """break up powers assuming (not checking) that eq is a Mul:
                   b**(Rational*e) -> b**e, Rational
                commutatives come back as a dictionary {b**e: Rational}
                noncommutatives come back as a list [(b**e, Rational)]
            """

            (c, nc) = (dict(), list())
            for (i, a) in enumerate(
                    Mul.make_args(eq)
                    or [eq]):  # remove or [eq] after 2114 accepted
                a = powdenest(a)
                (b, e) = a.as_base_exp()
                if not e is S.One:
                    (co, _) = e.as_coeff_mul()
                    b = Pow(b, e / co)
                    e = co
                if a.is_commutative:
                    if b in c:  # handle I and -1 like things where b, e for I is -1, 1/2
                        c[b] += e
                    else:
                        c[b] = e
                else:
                    nc.append([b, e])
            return (c, nc)

        def rejoin(b, co):
            """
            Put rational back with exponent; in general this is not ok, but
            since we took it from the exponent for analysis, it's ok to put
            it back.
            """

            (b, e) = b.as_base_exp()
            return Pow(b, e * co)

        def ndiv(a, b):
            """if b divides a in an extractive way (like 1/4 divides 1/2
            but not vice versa, and 2/5 does not divide 1/3) then return
            the integer number of times it divides, else return 0.
            """

            if not b.q % a.q or not a.q % b.q:
                return int(a / b)
            return 0

        if not old.is_Mul:
            return fallback()

        # handle the leading coefficient and use it to decide if anything
        # should even be started; we always know where to find the Rational
        # so it's a quick test

        coeff = S.One
        co_self = self.args[0]
        co_old = old.args[0]
        if co_old.is_Rational and co_self.is_Rational:
            co_xmul = co_self.extract_multiplicatively(co_old)
        elif co_old.is_Rational:
            co_xmul = None
        else:
            co_xmul = True

        if not co_xmul:
            return fallback()

        (c, nc) = breakup(self)
        (old_c, old_nc) = breakup(old)

        # update the coefficients if we had an extraction

        if getattr(co_xmul, 'is_Rational', False):
            c.pop(co_self)
            c[co_xmul] = S.One
            old_c.pop(co_old)

        # do quick tests to see if we can't succeed

        ok = True
        if (
                # more non-commutative terms
                len(old_nc) > len(nc)):
            ok = False
        elif (
                # more commutative terms
                len(old_c) > len(c)):
            ok = False
        elif (
                # unmatched non-commutative bases
                set(_[0] for _ in old_nc).difference(set(_[0] for _ in nc))):
            ok = False
        elif (
                # unmatched commutative terms
                set(old_c).difference(set(c))):
            ok = False
        elif (
                # differences in sign
                any(sign(c[b]) != sign(old_c[b]) for b in old_c)):
            ok = False
        if not ok:
            return fallback()

        if not old_c:
            cdid = None
        else:
            rat = []
            for (b, old_e) in old_c.items():
                c_e = c[b]
                rat.append(ndiv(c_e, old_e))
                if not rat[-1]:
                    return fallback()
            cdid = min(rat)

        if not old_nc:
            ncdid = None
            for i in range(len(nc)):
                nc[i] = rejoin(*nc[i])
        else:
            ncdid = 0  # number of nc replacements we did
            take = len(old_nc)  # how much to look at each time
            limit = cdid or S.Infinity  # max number that we can take
            failed = []  # failed terms will need subs if other terms pass
            i = 0
            while limit and i + take <= len(nc):
                hit = False

                # the bases must be equivalent in succession, and
                # the powers must be extractively compatible on the
                # first and last factor but equal inbetween.

                rat = []
                for j in range(take):
                    if nc[i + j][0] != old_nc[j][0]:
                        break
                    elif j == 0:
                        rat.append(ndiv(nc[i + j][1], old_nc[j][1]))
                    elif j == take - 1:
                        rat.append(ndiv(nc[i + j][1], old_nc[j][1]))
                    elif nc[i + j][1] != old_nc[j][1]:
                        break
                    else:
                        rat.append(1)
                    j += 1
                else:
                    ndo = min(rat)
                    if ndo:
                        if take == 1:
                            if cdid:
                                ndo = min(cdid, ndo)
                            nc[i] = Pow(new, ndo) * rejoin(
                                nc[i][0], nc[i][1] - ndo * old_nc[0][1])
                        else:
                            ndo = 1

                            # the left residual

                            l = rejoin(nc[i][0], nc[i][1] - ndo * old_nc[0][1])

                            # eliminate all middle terms

                            mid = new

                            # the right residual (which may be the same as the middle if take == 2)

                            ir = i + take - 1
                            r = (nc[ir][0], nc[ir][1] - ndo * old_nc[-1][1])
                            if r[1]:
                                if i + take < len(nc):
                                    nc[i:i + take] = [l * mid, r]
                                else:
                                    r = rejoin(*r)
                                    nc[i:i + take] = [l * mid * r]
                            else:

                                # there was nothing left on the right

                                nc[i:i + take] = [l * mid]

                        limit -= ndo
                        ncdid += ndo
                        hit = True
                if not hit:

                    # do the subs on this failing factor

                    failed.append(i)
                i += 1
            else:

                if not ncdid:
                    return fallback()

                # although we didn't fail, certain nc terms may have
                # failed so we rebuild them after attempting a partial
                # subs on them

                failed.extend(range(i, len(nc)))
                for i in failed:
                    nc[i] = rejoin(*nc[i]).subs(old, new)

        # rebuild the expression

        if cdid is None:
            do = ncdid
        elif ncdid is None:
            do = cdid
        else:
            do = min(ncdid, cdid)

        margs = []
        for b in c:
            if b in old_c:

                # calculate the new exponent

                e = c[b] - old_c[b] * do
                margs.append(rejoin(b, e))
            else:
                margs.append(rejoin(b.subs(old, new), c[b]))
        if cdid and not ncdid:

            # in case we are replacing commutative with non-commutative,
            # we want the new term to come at the front just like the
            # rest of this routine

            margs = [Pow(new, cdid)] + margs
        return Mul(*margs) * Mul(*nc)
Exemple #8
0
    def _eval_subs(self, old, new):

        from sympy import sign
        from sympy.simplify.simplify import powdenest

        if self == old:
            return new

        def fallback():
            """Return this value when partial subs has failed."""

            return self.__class__(*[s._eval_subs(old, new) for s in
                                  self.args])

        def breakup(eq):
            """break up powers assuming (not checking) that eq is a Mul:
                   b**(Rational*e) -> b**e, Rational
                commutatives come back as a dictionary {b**e: Rational}
                noncommutatives come back as a list [(b**e, Rational)]
            """

            (c, nc) = (dict(), list())
            for (i, a) in enumerate(Mul.make_args(eq) or [eq]): # remove or [eq] after 2114 accepted
                a = powdenest(a)
                (b, e) = a.as_base_exp()
                if not e is S.One:
                    (co, _) = e.as_coeff_mul()
                    b = Pow(b, e/co)
                    e = co
                if a.is_commutative:
                    if b in c: # handle I and -1 like things where b, e for I is -1, 1/2
                        c[b] += e
                    else:
                        c[b] = e
                else:
                    nc.append([b, e])
            return (c, nc)

        def rejoin(b, co):
            """
            Put rational back with exponent; in general this is not ok, but
            since we took it from the exponent for analysis, it's ok to put
            it back.
            """

            (b, e) = b.as_base_exp()
            return Pow(b, e*co)

        def ndiv(a, b):
            """if b divides a in an extractive way (like 1/4 divides 1/2
            but not vice versa, and 2/5 does not divide 1/3) then return
            the integer number of times it divides, else return 0.
            """

            if not b.q % a.q or not a.q % b.q:
                return int(a/b)
            return 0

        if not old.is_Mul:
            return fallback()

        # handle the leading coefficient and use it to decide if anything
        # should even be started; we always know where to find the Rational
        # so it's a quick test

        coeff = S.One
        co_self = self.args[0]
        co_old = old.args[0]
        if co_old.is_Rational and co_self.is_Rational:
            co_xmul = co_self.extract_multiplicatively(co_old)
        elif co_old.is_Rational:
            co_xmul = None
        else:
            co_xmul = True

        if not co_xmul:
            return fallback()

        (c, nc) = breakup(self)
        (old_c, old_nc) = breakup(old)

        # update the coefficients if we had an extraction

        if getattr(co_xmul, 'is_Rational', False):
            c.pop(co_self)
            c[co_xmul] = S.One
            old_c.pop(co_old)

        # do quick tests to see if we can't succeed

        ok = True
        if (
            # more non-commutative terms
            len(old_nc) > len(nc)):
            ok = False
        elif (
            # more commutative terms
            len(old_c) > len(c)):
            ok = False
        elif (
            # unmatched non-commutative bases
            set(_[0] for _ in  old_nc).difference(set(_[0] for _ in nc))):
            ok = False
        elif (
            # unmatched commutative terms
            set(old_c).difference(set(c))):
            ok = False
        elif (
            # differences in sign
            any(sign(c[b]) != sign(old_c[b]) for b in old_c)):
            ok = False
        if not ok:
            return fallback()

        if not old_c:
            cdid = None
        else:
            rat = []
            for (b, old_e) in old_c.items():
                c_e = c[b]
                rat.append(ndiv(c_e, old_e))
                if not rat[-1]:
                    return fallback()
            cdid = min(rat)

        if not old_nc:
            ncdid = None
            for i in range(len(nc)):
                nc[i] = rejoin(*nc[i])
        else:
            ncdid = 0  # number of nc replacements we did
            take = len(old_nc)  # how much to look at each time
            limit = cdid or S.Infinity # max number that we can take
            failed = []  # failed terms will need subs if other terms pass
            i = 0
            while limit and i + take <= len(nc):
                hit = False

                # the bases must be equivalent in succession, and
                # the powers must be extractively compatible on the
                # first and last factor but equal inbetween.

                rat = []
                for j in range(take):
                    if nc[i + j][0] != old_nc[j][0]:
                        break
                    elif j == 0:
                        rat.append(ndiv(nc[i + j][1], old_nc[j][1]))
                    elif j == take - 1:
                        rat.append(ndiv(nc[i + j][1], old_nc[j][1]))
                    elif nc[i + j][1] != old_nc[j][1]:
                        break
                    else:
                        rat.append(1)
                    j += 1
                else:
                    ndo = min(rat)
                    if ndo:
                        if take == 1:
                            if cdid:
                                ndo = min(cdid, ndo)
                            nc[i] = Pow(new, ndo)*rejoin(nc[i][0],
                                    nc[i][1] - ndo*old_nc[0][1])
                        else:
                            ndo = 1

                            # the left residual

                            l = rejoin(nc[i][0], nc[i][1] - ndo*
                                    old_nc[0][1])

                            # eliminate all middle terms

                            mid = new

                            # the right residual (which may be the same as the middle if take == 2)

                            ir = i + take - 1
                            r = (nc[ir][0], nc[ir][1] - ndo*
                                 old_nc[-1][1])
                            if r[1]:
                                if i + take < len(nc):
                                    nc[i:i + take] = [l*mid, r]
                                else:
                                    r = rejoin(*r)
                                    nc[i:i + take] = [l*mid*r]
                            else:

                                # there was nothing left on the right

                                nc[i:i + take] = [l*mid]

                        limit -= ndo
                        ncdid += ndo
                        hit = True
                if not hit:

                    # do the subs on this failing factor

                    failed.append(i)
                i += 1
            else:

                if not ncdid:
                    return fallback()

                # although we didn't fail, certain nc terms may have
                # failed so we rebuild them after attempting a partial
                # subs on them

                failed.extend(range(i, len(nc)))
                for i in failed:
                    nc[i] = rejoin(*nc[i]).subs(old, new)

        # rebuild the expression

        if cdid is None:
            do = ncdid
        elif ncdid is None:
            do = cdid
        else:
            do = min(ncdid, cdid)

        margs = []
        for b in c:
            if b in old_c:

                # calculate the new exponent

                e = c[b] - old_c[b]*do
                margs.append(rejoin(b, e))
            else:
                margs.append(rejoin(b.subs(old, new), c[b]))
        if cdid and not ncdid:

            # in case we are replacing commutative with non-commutative,
            # we want the new term to come at the front just like the
            # rest of this routine

            margs = [Pow(new, cdid)] + margs
        return Mul(*margs)*Mul(*nc)
Exemple #9
0
    def has(self, *patterns, **flags):
        """Return True if self has any of the patterns. If the `all` flag
        is True then return True if all of the patterns are present.

           >>> from sympy import sin, S
           >>> from sympy.abc import x, y, z

           >>> (x**2 + sin(x*y)).has(z)
           False

           >>> (x**2 + sin(x*y)).has(x, y, z)
           True

           When `all` is True then True is returned only if all of the
           patterns are present:

           >>> (x**2 + sin(x*y)).has(x, y, z, all=True)
           False

           If there are no patterns, False is always returned:
           "something doesn't have nothing"

           >>> (x).has()
           False
           >>> (S.One).has()
           False


        """
        from sympy.core.symbol import Wild

        def search(expr, target, hit):
            if hasattr(expr, '__iter__') and hasattr(expr, '__len__'):
                # this 'if' clause is needed until all objects use
                # sympy containers
                for i in expr:
                    if search(i, target, hit):
                        return True
            elif not isinstance(expr, Basic):
                pass
            elif target(expr) and hit(expr):
                return True
            else:
                for term in expr.iter_basic_args():
                    if search(term, target, hit):
                        return True
            return False

        def _has(p):
            p = sympify(p)
            if isinstance(p, BasicType):
                return search(self, lambda w: isinstance(w, p), lambda w: True)
            if p.is_Atom and not isinstance(p, Wild):
                return search(self, lambda w: isinstance(w, p.func), lambda w: w in [p])
            return search(self, lambda w: p.matches(w) is not None, lambda w: True)

        if not patterns:
            return False # something doesn't have nothing

        patterns = set(patterns)

        if flags.get('all', False):
            return all(_has(p) for p in patterns)
        else:
            return any(_has(p) for p in patterns)