Beispiel #1
0
    def __new__(cls, expr, variables, point, **assumptions):
        if not ordered_iter(variables, Tuple):
            variables = [variables]
        variables = Tuple(*sympify(variables))

        if uniq(variables) != variables:
            repeated = repeated = [
                v for v in set(variables) if list(variables).count(v) > 1
            ]
            raise ValueError('cannot substitute expressions %s more than '
                             'once.' % repeated)

        if not ordered_iter(point, Tuple):
            point = [point]
        point = Tuple(*sympify(point))

        if len(point) != len(variables):
            raise ValueError('Number of point values must be the same as '
                             'the number of variables.')

        # it's necessary to use dummy variables internally
        new_variables = Tuple(*[
            arg.as_dummy() if arg.is_Symbol else C.Dummy(str(arg))
            for arg in variables
        ])
        expr = sympify(expr).subs(tuple(zip(variables, new_variables)))

        if expr.is_commutative:
            assumptions['commutative'] = True

        obj = Expr.__new__(cls, expr, new_variables, point, **assumptions)
        return obj
Beispiel #2
0
    def eval(cls, *args):
        obj = Expr.__new__(cls, *args)
        #use dummy variables internally, just to be sure
        nargs = len(args) - 1

        expression = args[nargs]
        funargs = [C.Dummy(arg.name) for arg in args[:nargs]]
        #probably could use something like foldl here
        for arg, funarg in zip(args[:nargs], funargs):
            expression = expression.subs(arg, funarg)
        funargs.append(expression)
        obj._args = tuple(funargs)

        return obj
Beispiel #3
0
    def __new__(cls, variables, expr):
        try:
            variables = Tuple(*variables)
        except TypeError:
            variables = Tuple(variables)
        if len(variables) == 1 and variables[0] == expr:
            return S.IdentityFunction

        #use dummy variables internally, just to be sure
        new_variables = [C.Dummy(arg.name) for arg in variables]
        expr = sympify(expr).subs(tuple(zip(variables, new_variables)))

        obj = Expr.__new__(cls, Tuple(*new_variables), expr)
        return obj
Beispiel #4
0
 def fdiff(self, argindex=1):
     if self.nargs is not None:
         if isinstance(self.nargs, tuple):
             nargs = self.nargs[-1]
         else:
             nargs = self.nargs
         if not (1 <= argindex <= nargs):
             raise ArgumentIndexError(self, argindex)
     u = self.args[argindex - 1]
     if u.is_Symbol:
         uself = self
     else:
         u = C.Dummy('u')
         uself = self.func(u)
     return Derivative(uself, u, evaluate=False)
Beispiel #5
0
 def fdiff(self, argindex=1):
     if self.nargs is not None:
         if isinstance(self.nargs, tuple):
             nargs = self.nargs[-1]
         else:
             nargs = self.nargs
         if not (1 <= argindex <= nargs):
             raise ArgumentIndexError(self, argindex)
     if not self.args[argindex - 1].is_Symbol:
         # See issue 1525 and issue 1620 and issue 2501
         arg_dummy = C.Dummy('xi_%i' % argindex)
         return Subs(
             Derivative(self.subs(self.args[argindex - 1], arg_dummy),
                        arg_dummy), arg_dummy, self.args[argindex - 1])
     return Derivative(self, self.args[argindex - 1], evaluate=False)
Beispiel #6
0
 def fdiff(self, argindex=1):
     if self.nargs is not None:
         if isinstance(self.nargs, tuple):
             nargs = self.nargs[-1]
         else:
             nargs = self.nargs
         if not (1<=argindex<=nargs):
             raise TypeError("argument index %r is out of range [1,%s]" % (argindex,nargs))
     u = self.args[argindex - 1]
     if u.is_Symbol:
         uself = self
     else:
         u = C.Dummy('u')
         uself = self.func(u)
     return Derivative(uself, u, evaluate=False)
Beispiel #7
0
    def getn(self):
        """
        Returns the order of the expression.

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

        Example:
        >>> from sympy import O
        >>> from sympy.abc import x
        >>> (1 + x + O(x**2)).getn()
        2
        >>> (1 + x).getn()
        >>>

        """
        o = self.getO()
        if o is None:
            return None
        elif o.is_Order:
            o = o.expr
            if o is S.One:
                return S.Zero
            if o.is_Symbol:
                return S.One
            if o.is_Pow:
                return o.args[1]
            if o.is_Mul: # x**n*log(x)**n or x**n/log(x)**n
                for oi in o.args:
                    if oi.is_Symbol:
                        return S.One
                    if oi.is_Pow:
                        syms = oi.atoms(C.Symbol)
                        if len(syms) == 1:
                            x = syms.pop()
                            oi = oi.subs(x, C.Dummy('x', positive=True))
                            if oi.base.is_Symbol and oi.exp.is_Rational:
                                return abs(oi.exp)

        raise NotImplementedError('not sure of order of %s' % o)
Beispiel #8
0
    def __eq__(self, other):
        if not isinstance(other, Subs):
            return False
        if (len(self.point) != len(other.point)
                or self.free_symbols != other.free_symbols
                or sorted(self.point) != sorted(other.point)):
            return False

        # non-repeated point args
        selfargs = [
            v[0] for v in sorted(zip(self.variables, self.point),
                                 key=lambda v: v[1])
            if list(self.point.args).count(v[1]) == 1
        ]
        otherargs = [
            v[0] for v in sorted(zip(other.variables, other.point),
                                 key=lambda v: v[1])
            if list(other.point.args).count(v[1]) == 1
        ]
        # find repeated point values and subs each associated variable
        # for a single symbol
        selfrepargs = []
        otherrepargs = []
        if uniq(self.point) != self.point:
            repeated = uniq(
                [v for v in self.point if list(self.point.args).count(v) > 1])
            repswap = dict(
                zip(repeated, [C.Dummy() for _ in xrange(len(repeated))]))
            selfrepargs = [(self.variables[i], repswap[v])
                           for i, v in enumerate(self.point) if v in repeated]
            otherrepargs = [(other.variables[i], repswap[v])
                            for i, v in enumerate(other.point)
                            if v in repeated]

        return self.expr.subs(selfrepargs) == other.expr.subs(
            tuple(zip(otherargs, selfargs))).subs(otherrepargs)
Beispiel #9
0
    def subs(self, *args, **kwargs):
        """
        Substitutes old for new in an expression after sympifying args.

        `args` is either:
          - two arguments, e.g. foo.subs(old, new)
          - one iterable argument, e.g. foo.subs(iterable). The iterable may be
             o an iterable container with (old, new) pairs. In this case the
               replacements are processed in the order given with successive
               patterns possibly affecting replacements already made.
             o a dict or set whose key/value items correspond to old/new pairs.
               In this case the old/new pairs will be sorted by op count and in
               case of a tie, by number of args and the default_sort_key. The
               resulting sorted list is then processed as an iterable container
               (see previous).

        If the keyword ``simultaneous`` is True, the subexpressions will not be
        evaluated until all the substitutions have been made.

        Examples
        ========

        >>> from sympy import pi, exp
        >>> from sympy.abc import x, y
        >>> (1 + x*y).subs(x, pi)
        pi*y + 1
        >>> (1 + x*y).subs({x:pi, y:2})
        1 + 2*pi
        >>> (1 + x*y).subs([(x, pi), (y, 2)])
        1 + 2*pi
        >>> reps = [(y, x**2), (x, 2)]
        >>> (x + y).subs(reps)
        6
        >>> (x + y).subs(reversed(reps))
        x**2 + 2

        >>> (x**2 + x**4).subs(x**2, y)
        y**2 + y

        To replace only the x**2 but not the x**4, use xreplace:

        >>> (x**2 + x**4).xreplace({x**2: y})
        x**4 + y

        To delay evaluation until all substitutions have been made,
        set the keyword ``simultaneous`` to True:

        >>> (x/y).subs([(x, 0), (y, 0)])
        0
        >>> (x/y).subs([(x, 0), (y, 0)], simultaneous=True)
        nan

        This has the added feature of not allowing subsequent substitutions
        to affect those already made:

        >>> ((x + y)/y).subs({x + y: y, y: x + y})
        1
        >>> ((x + y)/y).subs({x + y: y, y: x + y}, simultaneous=True)
        y/(x + y)

        In order to obtain a canonical result, unordered iterables are
        sorted by count_op length, number of arguments and by the
        default_sort_key to break any ties. All other iterables are left
        unsorted.

        >>> from sympy import sqrt, sin, cos, exp
        >>> from sympy.abc import a, b, c, d, e

        >>> A = (sqrt(sin(2*x)), a)
        >>> B = (sin(2*x), b)
        >>> C = (cos(2*x), c)
        >>> D = (x, d)
        >>> E = (exp(x), e)

        >>> expr = sqrt(sin(2*x))*sin(exp(x)*x)*cos(2*x) + sin(2*x)

        >>> expr.subs(dict([A,B,C,D,E]))
        a*c*sin(d*e) + b

        See Also
        ========
        replace: replacement capable of doing wildcard-like matching,
                 parsing of match, and conditional replacements
        xreplace: exact node replacement in expr tree; also capable of
                  using matching rules

        """
        from sympy.core.containers import Dict
        from sympy.utilities import default_sort_key

        unordered = False
        if len(args) == 1:
            sequence = args[0]
            if isinstance(sequence, set):
                unordered = True
            elif isinstance(sequence, (Dict, dict)):
                unordered = True
                sequence = sequence.items()
            elif not iterable(sequence):
                from sympy.utilities.misc import filldedent
                raise ValueError(
                    filldedent("""
                   When a single argument is passed to subs
                   it should be an iterable of (old, new) tuples."""))
        elif len(args) == 2:
            sequence = [args]
        else:
            raise ValueError("subs accepts either 1 or 2 arguments")

        sequence = list(sequence)
        for i in range(len(sequence)):
            o, n = sequence[i]
            so, sn = sympify(o), sympify(n)
            if not isinstance(so, Basic):
                if type(o) is str:
                    so = C.Symbol(o)
            sequence[i] = (so, sn)
            if _aresame(so, sn):
                sequence[i] = None
                continue
        sequence = filter(None, sequence)

        if unordered:
            sequence = dict(sequence)
            if not all(k.is_Atom for k in sequence):
                d = {}
                for o, n in sequence.iteritems():
                    try:
                        ops = o.count_ops(), len(o.args)
                    except TypeError:
                        ops = (0, 0)
                    d.setdefault(ops, []).append((o, n))
                newseq = []
                for k in sorted(d.keys(), reverse=True):
                    newseq.extend(
                        sorted([v[0] for v in d[k]], key=default_sort_key))
                sequence = [(k, sequence[k]) for k in newseq]
                del newseq, d
            else:
                sequence = sorted([(k, v) for (k, v) in sequence.iteritems()],
                                  key=default_sort_key)

        if kwargs.pop('simultaneous',
                      False):  # XXX should this be the default for dict subs?
            reps = {}
            rv = self
            for old, new in sequence:
                d = C.Dummy()
                rv = rv._subs(old, d)
                reps[d] = new
                if not isinstance(rv, Basic):
                    break
            return rv.xreplace(reps)
        else:
            rv = self
            for old, new in sequence:
                rv = rv._subs(old, new)
                if not isinstance(rv, Basic):
                    break
            return rv