Exemple #1
0
 def fdiff(self, argindex=3):
     if argindex != 3:
         raise ArgumentIndexError(self, argindex)
     nap = Tuple(*[a + 1 for a in self.ap])
     nbq = Tuple(*[b + 1 for b in self.bq])
     fac = Mul(*self.ap) / Mul(*self.bq)
     return fac * hyper(nap, nbq, self.argument)
Exemple #2
0
def test_tensorsymmetry():
    sym = tensorsymmetry([1] * 2)
    sym1 = TensorSymmetry(get_symmetric_group_sgs(2))
    assert sym == sym1
    sym = tensorsymmetry([2])
    sym1 = TensorSymmetry(get_symmetric_group_sgs(2, 1))
    assert sym == sym1
    sym2 = tensorsymmetry()
    assert sym2.base == Tuple() and sym2.generators == Tuple(Permutation(1))
    pytest.raises(NotImplementedError, lambda: tensorsymmetry([2, 1]))
Exemple #3
0
    def __new__(cls, function, limits):
        fun = sympify(function)
        if not is_sequence(fun) or len(fun) != 2:
            raise ValueError("Function argument should be (x(t), y(t)) "
                "but got %s" % str(function))
        if not is_sequence(limits) or len(limits) != 3:
            raise ValueError("Limit argument should be (t, tmin, tmax) "
                "but got %s" % str(limits))

        return GeometryEntity.__new__(cls, Tuple(*fun), Tuple(*limits))
Exemple #4
0
 def _eval_rewrite_as_Sum(self, ap, bq, z):
     from diofant.functions import factorial, RisingFactorial, Piecewise
     from diofant import Sum
     n = Dummy("n", integer=True)
     rfap = Tuple(*[RisingFactorial(a, n) for a in ap])
     rfbq = Tuple(*[RisingFactorial(b, n) for b in bq])
     coeff = Mul(*rfap) / Mul(*rfbq)
     return Piecewise((Sum(coeff * z**n / factorial(n),
                           (n, 0, oo)), self.convergence_statement),
                      (self, True))
Exemple #5
0
    def __new__(cls, *args, **kwargs):
        evaluate = kwargs.get('evaluate', global_evaluate[0])

        if iterable(args[0]):
            if isinstance(args[0], Point) and not evaluate:
                return args[0]
            args = args[0]

        # unpack the arguments into a friendly Tuple
        # if we were already a Point, we're doing an excess
        # iteration, but we'll worry about efficiency later
        coords = Tuple(*args)
        if any(a.is_number and im(a) for a in coords):
            raise ValueError('Imaginary coordinates not permitted.')

        # Turn any Floats into rationals and simplify
        # any expressions before we instantiate
        if evaluate:
            coords = coords.xreplace(dict(
                [(f, simplify(nsimplify(f, rational=True)))
                for f in coords.atoms(Float)]))
        if len(coords) == 2:
            return Point2D(coords, **kwargs)
        if len(coords) == 3:
            return Point3D(coords, **kwargs)

        return GeometryEntity.__new__(cls, *coords)
Exemple #6
0
 def __new__(cls, *args, **kwargs):
     from diofant.geometry.point import Point
     args = [
         Tuple(*a)
         if is_sequence(a) and not isinstance(a, Point) else sympify(a)
         for a in args
     ]
     return Basic.__new__(cls, *args)
Exemple #7
0
def _process_limits(*symbols):
    """Process the list of symbols and convert them to canonical limits,
    storing them as Tuple(symbol, lower, upper). The orientation of
    the function is also returned when the upper limit is missing
    so (x, 1, None) becomes (x, None, 1) and the orientation is changed.
    """
    limits = []
    orientation = 1
    for V in symbols:
        if isinstance(V, (Dummy, Symbol)):
            limits.append(Tuple(V))
            continue
        elif is_sequence(V, Tuple):
            V = sympify(flatten(V))
            if V[0].is_Symbol:
                newsymbol = V[0]
                if len(V) == 2 and isinstance(V[1], Interval):
                    V[1:] = [V[1].start, V[1].end]

                if len(V) == 3:
                    if V[1] is None and V[2] is not None:
                        nlim = [V[2]]
                    elif V[1] is not None and V[2] is None:
                        orientation *= -1
                        nlim = [V[1]]
                    elif V[1] is None and V[2] is None:
                        nlim = []
                    else:
                        nlim = V[1:]
                    limits.append(Tuple(newsymbol, *nlim))
                    continue
                elif len(V) == 1 or (len(V) == 2 and V[1] is None):
                    limits.append(Tuple(newsymbol))
                    continue
                elif len(V) == 2:
                    limits.append(Tuple(newsymbol, V[1]))
                    continue

        raise ValueError('Invalid limits given: %s' % str(symbols))

    return limits, orientation
Exemple #8
0
    def __new__(cls, function, *symbols, **assumptions):
        # Any embedded piecewise functions need to be brought out to the
        # top level so that integration can go into piecewise mode at the
        # earliest possible moment.
        #
        # This constructor only differs from ExprWithLimits
        # in the application of the orientation variable.  Perhaps merge?
        function = sympify(function)
        if hasattr(function, 'func') and function.func is Equality:
            lhs = function.lhs
            rhs = function.rhs
            return Equality(cls(lhs, *symbols, **assumptions),
                            cls(rhs, *symbols, **assumptions))
        function = piecewise_fold(function)

        if function is S.NaN:
            return S.NaN

        if symbols:
            limits, orientation = _process_limits(*symbols)
        else:
            # symbol not provided -- we can still try to compute a general form
            free = function.free_symbols
            if len(free) != 1:
                raise ValueError(
                    " specify dummy variables for %s. If the integrand contains"
                    " more than one free symbol, an integration variable should"
                    " be supplied explicitly e.g., integrate(f(x, y), x)" %
                    function)
            limits, orientation = [Tuple(s) for s in free], 1

        # denest any nested calls
        while cls == type(function):
            limits = list(function.limits) + limits
            function = function.function

        obj = Expr.__new__(cls, **assumptions)
        arglist = [orientation * function]
        arglist.extend(limits)
        obj._args = tuple(arglist)

        return obj
Exemple #9
0
 def __new__(cls, *args, **kwargs):
     eval = kwargs.get('evaluate', global_evaluate[0])
     if isinstance(args[0], (Point, Point3D)):
         if not eval:
             return args[0]
         args = args[0].args
     else:
         if iterable(args[0]):
             args = args[0]
         if len(args) not in (2, 3):
             raise TypeError(
                 "Enter a 2 or 3 dimensional point")
     coords = Tuple(*args)
     if len(coords) == 2:
         coords += (S.Zero,)
     if eval:
         coords = coords.xreplace(dict(
             [(f, simplify(nsimplify(f, rational=True)))
             for f in coords.atoms(Float)]))
     return GeometryEntity.__new__(cls, *coords)
Exemple #10
0
    def __new__(cls, function, *symbols, **assumptions):
        # Any embedded piecewise functions need to be brought out to the
        # top level so that integration can go into piecewise mode at the
        # earliest possible moment.
        function = sympify(function)
        if hasattr(function, 'func') and function.func is Equality:
            lhs = function.lhs
            rhs = function.rhs
            return Equality(cls(lhs, *symbols, **assumptions),
                            cls(rhs, *symbols, **assumptions))
        function = piecewise_fold(function)

        if function is S.NaN:
            return S.NaN

        if symbols:
            limits, orientation = _process_limits(*symbols)
        else:
            # symbol not provided -- we can still try to compute a general form
            free = function.free_symbols
            if len(free) != 1:
                raise ValueError("specify dummy variables for %s" % function)
            limits, orientation = [Tuple(s) for s in free], 1

        # denest any nested calls
        while cls == type(function):
            limits = list(function.limits) + limits
            function = function.function

        # Only limits with lower and upper bounds are supported; the indefinite form
        # is not supported
        if any(len(l) != 3 or None in l for l in limits):
            raise ValueError(
                'ExprWithLimits requires values for lower and upper bounds.')

        obj = Expr.__new__(cls, **assumptions)
        arglist = [function]
        arglist.extend(limits)
        obj._args = tuple(arglist)

        return obj
Exemple #11
0
 def __new__(cls, *args, **kwargs):
     eval = kwargs.get('evaluate', global_evaluate[0])
     check = True
     if isinstance(args[0], Point2D):
         if not eval:
             return args[0]
         args = args[0].args
         check = False
     else:
         if iterable(args[0]):
             args = args[0]
         if len(args) != 2:
             raise ValueError(
                 "Only two dimensional points currently supported")
     coords = Tuple(*args)
     if check:
         if any(a.is_number and im(a) for a in coords):
             raise ValueError('Imaginary args not permitted.')
     if eval:
         coords = coords.xreplace(dict(
             [(f, simplify(nsimplify(f, rational=True)))
             for f in coords.atoms(Float)]))
     return GeometryEntity.__new__(cls, *coords)
Exemple #12
0
def verify_numerically(f, g, z=None, tol=1.0e-6, a=2, b=-1, c=3, d=1):
    """
    Test numerically that f and g agree when evaluated in the argument z.

    If z is None, all symbols will be tested. This routine does not test
    whether there are Floats present with precision higher than 15 digits
    so if there are, your results may not be what you expect due to round-
    off errors.

    Examples
    ========

    >>> from diofant import sin, cos
    >>> from diofant.abc import x
    >>> from diofant.utilities.randtest import verify_numerically as tn
    >>> tn(sin(x)**2 + cos(x)**2, 1, x)
    true
    """
    f, g, z = Tuple(f, g, z)
    z = [z] if isinstance(z, Symbol) else (f.free_symbols | g.free_symbols)
    reps = list(zip(z, [random_complex_number(a, b, c, d) for zi in z]))
    z1 = f.subs(reps).n()
    z2 = g.subs(reps).n()
    return comp(z1, z2, tol)
Exemple #13
0
    def __new__(cls, *args):
        if len(args) == 5:
            args = [(args[0], args[1]), (args[2], args[3]), args[4]]
        if len(args) != 3:
            raise TypeError("args must be either as, as', bs, bs', z or "
                            "as, bs, z")

        def tr(p):
            if len(p) != 2:
                raise TypeError("wrong argument")
            return TupleArg(_prep_tuple(p[0]), _prep_tuple(p[1]))

        arg0, arg1 = tr(args[0]), tr(args[1])
        if Tuple(arg0, arg1).has(S.Infinity, S.ComplexInfinity,
                                 S.NegativeInfinity):
            raise ValueError("G-function parameters must be finite")

        if any((a - b).is_integer and (a - b).is_positive for a in arg0[0]
               for b in arg1[0]):
            raise ValueError("no parameter a1, ..., an may differ from "
                             "any b1, ..., bm by a positive integer")

        # TODO should we check convergence conditions?
        return Function.__new__(cls, arg0, arg1, args[2])
Exemple #14
0
 def bother(self):
     """ Second set of denominator parameters. """
     return Tuple(*self.args[1][1])
Exemple #15
0
 def bq(self):
     """ Combined denominator parameters. """
     return Tuple(*(self.args[1][0] + self.args[1][1]))
Exemple #16
0
 def bm(self):
     """ First set of denominator parameters. """
     return Tuple(*self.args[1][0])
Exemple #17
0
 def aother(self):
     """ Second set of numerator parameters. """
     return Tuple(*self.args[0][1])
Exemple #18
0
 def ap(self):
     """ Combined numerator parameters. """
     return Tuple(*(self.args[0][0] + self.args[0][1]))
Exemple #19
0
    def _eval_derivative(self, sym):
        """Evaluate the derivative of the current Integral object by
        differentiating under the integral sign [1], using the Fundamental
        Theorem of Calculus [2] when possible.

        Whenever an Integral is encountered that is equivalent to zero or
        has an integrand that is independent of the variable of integration
        those integrals are performed. All others are returned as Integral
        instances which can be resolved with doit() (provided they are integrable).

        References
        ==========

        .. [1] http://en.wikipedia.org/wiki/Differentiation_under_the_integral_sign
        .. [2] http://en.wikipedia.org/wiki/Fundamental_theorem_of_calculus

        Examples
        ========

        >>> from diofant import Integral
        >>> from diofant.abc import x, y
        >>> i = Integral(x + y, y, (y, 1, x))
        >>> i.diff(x)
        Integral(x + y, (y, x)) + Integral(1, y, (y, 1, x))
        >>> i.doit().diff(x) == i.diff(x).doit()
        True
        >>> i.diff(y)
        0

        The previous must be true since there is no y in the evaluated integral:

        >>> i.free_symbols == {x}
        True
        >>> i.doit()
        2*x**3/3 - x/2 - 1/6

        """

        # differentiate under the integral sign; we do not
        # check for regularity conditions (TODO), see issue 4215

        # get limits and the function
        f, limits = self.function, list(self.limits)

        # the order matters if variables of integration appear in the limits
        # so work our way in from the outside to the inside.
        limit = limits.pop(-1)
        if len(limit) == 3:
            x, a, b = limit
        elif len(limit) == 2:
            x, b = limit
            a = None
        else:
            a = b = None
            x = limit[0]

        if limits:  # f is the argument to an integral
            f = self.func(f, *tuple(limits))

        # assemble the pieces
        def _do(f, ab):
            dab_dsym = diff(ab, sym)
            if not dab_dsym:
                return S.Zero
            if isinstance(f, Integral):
                limits = [(x, x) if (len(l) == 1 and l[0] == x) else l
                          for l in f.limits]
                f = self.func(f.function, *limits)
            return f.subs(x, ab) * dab_dsym

        rv = 0
        if b is not None:
            rv += _do(f, b)
        if a is not None:
            rv -= _do(f, a)
        if len(limit) == 1 and sym == x:
            # the dummy variable *is* also the real-world variable
            arg = f
            rv += arg
        else:
            # the dummy variable might match sym but it's
            # only a dummy and the actual variable is determined
            # by the limits, so mask off the variable of integration
            # while differentiating
            u = Dummy('u')
            arg = f.subs(x, u).diff(sym).subs(u, x)
            rv += self.func(arg, Tuple(x, a, b))
        return rv
Exemple #20
0
 def bq(self):
     """ Denominator parameters of the hypergeometric function. """
     return Tuple(*self.args[1])
Exemple #21
0
 def ap(self):
     """ Numerator parameters of the hypergeometric function. """
     return Tuple(*self.args[0])
Exemple #22
0
    def __init__(self, data, **kwarg):
        """
        Creates a TableForm.

        Parameters:

            data ...
                            2D data to be put into the table; data can be
                            given as a Matrix

            headings ...
                            gives the labels for rows and columns:

                            Can be a single argument that applies to both
                            dimensions:

                                - None ... no labels
                                - "automatic" ... labels are 1, 2, 3, ...

                            Can be a list of labels for rows and columns:
                            The lables for each dimension can be given
                            as None, "automatic", or [l1, l2, ...] e.g.
                            ["automatic", None] will number the rows

                            [default: None]

            alignments ...
                            alignment of the columns with:

                                - "left" or "<"
                                - "center" or "^"
                                - "right" or ">"

                            When given as a single value, the value is used for
                            all columns. The row headings (if given) will be
                            right justified unless an explicit alignment is
                            given for it and all other columns.

                            [default: "left"]

            formats ...
                            a list of format strings or functions that accept
                            3 arguments (entry, row number, col number) and
                            return a string for the table entry. (If a function
                            returns None then the _print method will be used.)

            wipe_zeros ...
                            Don't show zeros in the table.

                            [default: True]

            pad ...
                            the string to use to indicate a missing value (e.g.
                            elements that are None or those that are missing
                            from the end of a row (i.e. any row that is shorter
                            than the rest is assumed to have missing values).
                            When None, nothing will be shown for values that
                            are missing from the end of a row; values that are
                            None, however, will be shown.

                            [default: None]

        Examples
        ========

        >>> from diofant import TableForm, Matrix
        >>> TableForm([[5, 7], [4, 2], [10, 3]])
        5  7
        4  2
        10 3
        >>> TableForm([list('.'*i) for i in range(1, 4)], headings='automatic')
          | 1 2 3
        ---------
        1 | .
        2 | . .
        3 | . . .
        >>> TableForm([['.'*(j if not i%2 else 1) for i in range(3)]
        ...            for j in range(4)], alignments='rcl')
            .
          . . .
         .. . ..
        ... . ...
        """
        from diofant import Symbol, Matrix
        from diofant.core.sympify import sympify, SympifyError

        # We only support 2D data. Check the consistency:
        if isinstance(data, Matrix):
            data = data.tolist()
        _w = len(data[0])
        _h = len(data)

        # fill out any short lines
        pad = kwarg.get('pad', None)
        ok_None = False
        if pad is None:
            pad = " "
            ok_None = True
        pad = Symbol(pad)
        _w = max(len(line) for line in data)
        for i, line in enumerate(data):
            if len(line) != _w:
                line.extend([pad]*(_w - len(line)))
            for j, lj in enumerate(line):
                if lj is None:
                    if not ok_None:
                        lj = pad
                else:
                    try:
                        lj = sympify(lj)
                    except SympifyError:
                        lj = Symbol(str(lj))
                line[j] = lj
            data[i] = line
        _lines = Tuple(*data)

        headings = kwarg.get("headings", [None, None])
        if headings == "automatic":
            _headings = [range(1, _h + 1), range(1, _w + 1)]
        else:
            h1, h2 = headings
            if h1 == "automatic":
                h1 = range(1, _h + 1)
            if h2 == "automatic":
                h2 = range(1, _w + 1)
            _headings = [h1, h2]

        allow = ('l', 'r', 'c')
        alignments = kwarg.get("alignments", "l")

        def _std_align(a):
            a = a.strip().lower()
            if len(a) > 1:
                return {'left': 'l', 'right': 'r', 'center': 'c'}.get(a, a)
            else:
                return {'<': 'l', '>': 'r', '^': 'c'}.get(a, a)
        std_align = _std_align(alignments)
        if std_align in allow:
            _alignments = [std_align]*_w
        else:
            _alignments = []
            for a in alignments:
                std_align = _std_align(a)
                _alignments.append(std_align)
                if std_align not in ('l', 'r', 'c'):
                    raise ValueError('alignment "%s" unrecognized' %
                        alignments)
        if _headings[0] and len(_alignments) == _w + 1:
            _head_align = _alignments[0]
            _alignments = _alignments[1:]
        else:
            _head_align = 'r'
        if len(_alignments) != _w:
            raise ValueError(
                'wrong number of alignments: expected %s but got %s' %
                (_w, len(_alignments)))

        _column_formats = kwarg.get("formats", [None]*_w)

        _wipe_zeros = kwarg.get("wipe_zeros", True)

        self._w = _w
        self._h = _h
        self._lines = _lines
        self._headings = _headings
        self._head_align = _head_align
        self._alignments = _alignments
        self._column_formats = _column_formats
        self._wipe_zeros = _wipe_zeros
Exemple #23
0
    def __new__(cls, expr, *args, **kwargs):
        expr = sympify(expr)

        if not args:
            if expr.is_Order:
                variables = expr.variables
                point = expr.point
            else:
                variables = list(expr.free_symbols)
                point = [S.Zero]*len(variables)
        else:
            args = list(args if is_sequence(args) else [args])
            variables, point = [], []
            if is_sequence(args[0]):
                for a in args:
                    v, p = list(map(sympify, a))
                    variables.append(v)
                    point.append(p)
            else:
                variables = list(map(sympify, args))
                point = [S.Zero]*len(variables)

        if not all(isinstance(v, (Dummy, Symbol)) for v in variables):
            raise TypeError('Variables are not symbols, got %s' % variables)

        if len(list(uniq(variables))) != len(variables):
            raise ValueError('Variables are supposed to be unique symbols, got %s' % variables)

        if expr.is_Order:
            expr_vp = dict(expr.args[1:])
            new_vp = dict(expr_vp)
            vp = dict(zip(variables, point))
            for v, p in vp.items():
                if v in new_vp.keys():
                    if p != new_vp[v]:
                        raise NotImplementedError(
                            "Mixing Order at different points is not supported.")
                else:
                    new_vp[v] = p
            if set(expr_vp.keys()) == set(new_vp.keys()):
                return expr
            else:
                variables = list(new_vp.keys())
                point = [new_vp[v] for v in variables]

        if expr is S.NaN:
            return S.NaN

        if any(x in p.free_symbols for x in variables for p in point):
            raise ValueError('Got %s as a point.' % point)

        if variables:
            if any(p != point[0] for p in point):
                raise NotImplementedError
            if point[0] in [S.Infinity, S.NegativeInfinity]:
                s = {k: 1/Dummy() for k in variables}
                rs = {1/v: 1/k for k, v in s.items()}
            elif point[0] is not S.Zero:
                s = {k: Dummy() + point[0] for k in variables}
                rs = {v - point[0]: k - point[0] for k, v in s.items()}
            else:
                s = ()
                rs = ()

            expr = expr.subs(s)

            if expr.is_Add:
                from diofant import expand_multinomial
                expr = expand_multinomial(expr)

            if s:
                args = tuple(r[0] for r in rs.items())
            else:
                args = tuple(variables)

            if len(variables) > 1:
                # XXX: better way?  We need this expand() to
                # workaround e.g: expr = x*(x + y).
                # (x*(x + y)).as_leading_term(x, y) currently returns
                # x*y (wrong order term!).  That's why we want to deal with
                # expand()'ed expr (handled in "if expr.is_Add" branch below).
                expr = expr.expand()

            if expr.is_Add:
                lst = expr.extract_leading_order(args)
                expr = Add(*[f.expr for (e, f) in lst])

            elif expr:
                expr = expr.as_leading_term(*args)
                expr = expr.as_independent(*args, as_Add=False)[1]

                expr = expand_power_base(expr)
                expr = expand_log(expr)

                if len(args) == 1:
                    # The definition of O(f(x)) symbol explicitly stated that
                    # the argument of f(x) is irrelevant.  That's why we can
                    # combine some power exponents (only "on top" of the
                    # expression tree for f(x)), e.g.:
                    # x**p * (-x)**q -> x**(p+q) for real p, q.
                    x = args[0]
                    margs = list(Mul.make_args(
                        expr.as_independent(x, as_Add=False)[1]))

                    for i, t in enumerate(margs):
                        if t.is_Pow:
                            b, q = t.args
                            if b in (x, -x) and q.is_extended_real and not q.has(x):
                                margs[i] = x**q
                            elif b.is_Pow and not b.exp.has(x):
                                b, r = b.args
                                if b in (x, -x) and r.is_extended_real:
                                    margs[i] = x**(r*q)
                            elif b.is_Mul and b.args[0] is S.NegativeOne:
                                b = -b
                                if b.is_Pow and not b.exp.has(x):
                                    b, r = b.args
                                    if b in (x, -x) and r.is_extended_real:
                                        margs[i] = x**(r*q)

                    expr = Mul(*margs)

            expr = expr.subs(rs)

        if expr is S.Zero:
            return expr

        if expr.is_Order:
            expr = expr.expr

        if not expr.has(*variables):
            expr = S.One

        # create Order instance:
        vp = dict(zip(variables, point))
        variables.sort(key=default_sort_key)
        point = [vp[v] for v in variables]
        args = (expr,) + Tuple(*zip(variables, point))
        obj = Expr.__new__(cls, *args)
        return obj
Exemple #24
0
def test_count_ops_visual():
    ADD, MUL, POW, SIN, COS, EXP, AND, D, G = symbols(
        'Add Mul Pow sin cos exp And Derivative Integral'.upper())
    DIV, SUB, NEG = symbols('DIV SUB NEG')
    NOT, OR, AND, XOR, IMPLIES, EQUIVALENT, _ITE, BASIC, TUPLE = symbols(
        'Not Or And Xor Implies Equivalent ITE Basic Tuple'.upper())

    def count(val):
        return count_ops(val, visual=True)

    assert count(7) is Integer(0)
    assert count(-1) == NEG
    assert count(-2) == NEG
    assert count(Rational(2, 3)) == DIV
    assert count(pi/3) == DIV
    assert count(-pi/3) == DIV + NEG
    assert count(I - 1) == SUB
    assert count(1 - I) == SUB
    assert count(1 - 2*I) == SUB + MUL

    assert count(x) is Integer(0)
    assert count(-x) == NEG
    assert count(-2*x/3) == NEG + DIV + MUL
    assert count(1/x) == DIV
    assert count(1/(x*y)) == DIV + MUL
    assert count(-1/x) == NEG + DIV
    assert count(-2/x) == NEG + DIV
    assert count(x/y) == DIV
    assert count(-x/y) == NEG + DIV

    assert count(x**2) == POW
    assert count(-x**2) == POW + NEG
    assert count(-2*x**2) == POW + MUL + NEG

    assert count(x + pi/3) == ADD + DIV
    assert count(x + Rational(1, 3)) == ADD + DIV
    assert count(x + y) == ADD
    assert count(x - y) == SUB
    assert count(y - x) == SUB
    assert count(-1/(x - y)) == DIV + NEG + SUB
    assert count(-1/(y - x)) == DIV + NEG + SUB
    assert count(1 + x**y) == ADD + POW
    assert count(1 + x + y) == 2*ADD
    assert count(1 + x + y + z) == 3*ADD
    assert count(1 + x**y + 2*x*y + y**2) == 3*ADD + 2*POW + 2*MUL
    assert count(2*z + y + x + 1) == 3*ADD + MUL
    assert count(2*z + y**17 + x + 1) == 3*ADD + MUL + POW
    assert count(2*z + y**17 + x + sin(x)) == 3*ADD + POW + MUL + SIN
    assert count(2*z + y**17 + x + sin(x**2)) == 3*ADD + MUL + 2*POW + SIN
    assert count(2*z + y**17 + x + sin(
        x**2) + exp(cos(x))) == 4*ADD + MUL + 3*POW + COS + SIN

    assert count(Derivative(x, x)) == D
    assert count(Integral(x, x) + 2*x/(1 + x)) == G + DIV + MUL + 2*ADD
    assert count(Basic()) is Integer(0)

    assert count({x + 1: sin(x)}) == ADD + SIN
    assert count([x + 1, sin(x) + y, None]) == ADD + SIN + ADD
    assert count({x + 1: sin(x), y: cos(x) + 1}) == SIN + COS + 2*ADD
    assert count({}) is Integer(0)
    assert count([x + 1, sin(x)*y, None]) == SIN + ADD + MUL
    assert count([]) is Integer(0)

    assert count(Basic()) == 0
    assert count(Basic(Basic(), Basic(x, x + y))) == ADD + 2*BASIC
    assert count(Basic(x, x + y)) == ADD + BASIC
    assert count(Or(x, y)) == OR
    assert count(And(x, y)) == AND
    assert count(And(x**y, z)) == AND + POW
    assert count(Or(x, Or(y, And(z, a)))) == AND + OR
    assert count(Nor(x, y)) == NOT + OR
    assert count(Nand(x, y)) == NOT + AND
    assert count(Xor(x, y)) == XOR
    assert count(Implies(x, y)) == IMPLIES
    assert count(Equivalent(x, y)) == EQUIVALENT
    assert count(ITE(x, y, z)) == _ITE
    assert count([Or(x, y), And(x, y), Basic(x + y)]) == ADD + AND + BASIC + OR

    assert count(Basic(Tuple(x))) == BASIC + TUPLE
    # It checks that TUPLE is counted as an operation.

    assert count(Eq(x + y, 2)) == ADD
Exemple #25
0
 def an(self):
     """ First set of numerator parameters. """
     return Tuple(*self.args[0][0])
Exemple #26
0
    def _eval_subs(self, old, new):
        """
        Perform substitutions over non-dummy variables
        of an expression with limits.  Also, can be used
        to specify point-evaluation of an abstract antiderivative.

        Examples
        ========

        >>> from diofant import Sum, oo
        >>> from diofant.abc import s, n
        >>> Sum(1/n**s, (n, 1, oo)).subs(s, 2)
        Sum(n**(-2), (n, 1, oo))

        >>> from diofant import Integral
        >>> from diofant.abc import x, a
        >>> Integral(a*x**2, x).subs(x, 4)
        Integral(a*x**2, (x, 4))

        See Also
        ========

        variables : Lists the integration variables
        change_index : Perform mapping on the sum and product dummy variables

        """
        from diofant.core.function import AppliedUndef, UndefinedFunction
        func, limits = self.function, list(self.limits)

        # If one of the expressions we are replacing is used as a func index
        # one of two things happens.
        #   - the old variable first appears as a free variable
        #     so we perform all free substitutions before it becomes
        #     a func index.
        #   - the old variable first appears as a func index, in
        #     which case we ignore.  See change_index.

        # Reorder limits to match standard mathematical practice for scoping
        limits.reverse()

        if not isinstance(old, Symbol) or \
                old.free_symbols.intersection(self.free_symbols):
            sub_into_func = True
            for i, xab in enumerate(limits):
                if 1 == len(xab) and old == xab[0]:
                    xab = (old, old)
                limits[i] = Tuple(xab[0],
                                  *[l._subs(old, new) for l in xab[1:]])
                if len(xab[0].free_symbols.intersection(
                        old.free_symbols)) != 0:
                    sub_into_func = False
                    break
            if isinstance(old, AppliedUndef) or isinstance(
                    old, UndefinedFunction):
                sy2 = set(self.variables).intersection(set(new.atoms(Symbol)))
                sy1 = set(self.variables).intersection(set(old.args))
                if not sy2.issubset(sy1):
                    raise ValueError(
                        "substitution can not create dummy dependencies")
                sub_into_func = True
            if sub_into_func:
                func = func.subs(old, new)
        else:
            # old is a Symbol and a dummy variable of some limit
            for i, xab in enumerate(limits):
                if len(xab) == 3:
                    limits[i] = Tuple(xab[0],
                                      *[l._subs(old, new) for l in xab[1:]])
                    if old == xab[0]:
                        break
        # simplify redundant limits (x, x)  to (x, )
        for i, xab in enumerate(limits):
            if len(xab) == 2 and (xab[0] - xab[1]).is_zero:
                limits[i] = Tuple(xab[0], )

        # Reorder limits back to representation-form
        limits.reverse()

        return self.func(func, *limits)