예제 #1
0
def exprcondpair_new(cls, expr, cond):
    expr = as_Basic(expr)
    if cond == True:
        return Tuple.__new__(cls, expr, true)
    elif cond == False:
        return Tuple.__new__(cls, expr, false)

    if not isinstance(cond, Boolean):
        raise TypeError(filldedent('''
            Second argument must be a Boolean,
            not `%s`''' % func_name(cond)))
    return Tuple.__new__(cls, expr, cond)
예제 #2
0
파일: piecewise.py 프로젝트: Lenqth/sympy
    def __new__(cls, expr, cond):
        expr = as_Basic(expr)
        if cond == True:
            return Tuple.__new__(cls, expr, true)
        elif cond == False:
            return Tuple.__new__(cls, expr, false)
        elif isinstance(cond, Basic) and cond.has(Piecewise):
            cond = piecewise_fold(cond)
            if isinstance(cond, Piecewise):
                cond = cond.rewrite(ITE)

        if not isinstance(cond, Boolean):
            raise TypeError(filldedent('''
                Second argument must be a Boolean,
                not `%s`''' % func_name(cond)))
        return Tuple.__new__(cls, expr, cond)
예제 #3
0
    def shape(self):
        """Returns a list with dimensions of each index.

        Dimensions is a property of the array, not of the indices.  Still, if
        the ``IndexedBase`` does not define a shape attribute, it is assumed
        that the ranges of the indices correspond to the shape of the array.

        >>> from sympy import IndexedBase, Idx, symbols
        >>> n, m = symbols('n m', integer=True)
        >>> i = Idx('i', m)
        >>> j = Idx('j', m)
        >>> A = IndexedBase('A', shape=(n, n))
        >>> B = IndexedBase('B')
        >>> A[i, j].shape
        (n, n)
        >>> B[i, j].shape
        (m, m)
        """
        from sympy.utilities.misc import filldedent

        if self.base.shape:
            return self.base.shape
        sizes = []
        for i in self.indices:
            upper = getattr(i, 'upper', None)
            lower = getattr(i, 'lower', None)
            if None in (upper, lower):
                raise IndexException(filldedent("""
                    Range is not defined for all indices in: %s""" % self))
            try:
                size = upper - lower + 1
            except TypeError:
                raise IndexException(filldedent("""
                    Shape cannot be inferred from Idx with
                    undefined range: %s""" % self))
            sizes.append(size)
        return Tuple(*sizes)
예제 #4
0
파일: integrals.py 프로젝트: pyc111/sympy
    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

        >>> from sympy import Integral
        >>> from sympy.abc import x, y
        >>> i = Integral(x + y, y, (y, 1, x))
        >>> i.diff(x)
        Integral(x + y, (y, x)) + Integral(1, (y, 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
        set([x])
        >>> i.doit()
        -1/6 - x/2 + 2*x**3/3

        """

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

        # 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 = Integral(f, *tuple(limits))

        # assemble the pieces
        rv = 0
        if b is not None:
            rv += f.subs(x, b)*diff(b, sym)
        if a is not None:
            rv -= f.subs(x, a)*diff(a, sym)
        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 += Integral(arg, Tuple(x, a, b))
        return rv
예제 #5
0
    def __init__(self, name, expr, argument_sequence=None):
        """Initialize a Routine instance.

        ``name``
            A string with the name of this routine in the generated code
        ``expr``
            The sympy expression that the Routine instance will represent.  If
            given a list or tuple of expressions, the routine will be
            considered to have multiple return values.
        ``argument_sequence``
            Optional list/tuple containing arguments for the routine in a
            preferred order.  If omitted, arguments will be ordered
            alphabetically, but with all input aguments first, and then output
            or in-out arguments.

        A decision about whether to use output arguments or return values,
        is made depending on the mathematical expressions.  For an expression
        of type Equality, the left hand side is made into an OutputArgument
        (or an InOutArgument if appropriate).  Else, the calculated
        expression is the return values of the routine.

        A tuple of exressions can be used to create a routine with both
        return value(s) and output argument(s).

        """
        arg_list = []

        if is_sequence(expr):
            if not expr:
                raise ValueError("No expression given")
            expressions = Tuple(*expr)
        else:
            expressions = Tuple(expr)

        # local variables
        local_vars = set([i.label for i in expressions.atoms(Idx)])

        # symbols that should be arguments
        symbols = expressions.atoms(Symbol) - local_vars

        # Decide whether to use output argument or return value
        return_val = []
        output_args = []
        for expr in expressions:
            if isinstance(expr, Equality):
                out_arg = expr.lhs
                expr = expr.rhs
                if isinstance(out_arg, Indexed):
                    dims = tuple([(S.Zero, dim - 1) for dim in out_arg.shape])
                    symbol = out_arg.base.label
                elif isinstance(out_arg, Symbol):
                    dims = []
                    symbol = out_arg
                else:
                    raise CodeGenError(
                        "Only Indexed or Symbol can define output arguments")

                if expr.has(symbol):
                    output_args.append(
                        InOutArgument(symbol, out_arg, expr, dimensions=dims))
                else:
                    output_args.append(
                        OutputArgument(symbol, out_arg, expr, dimensions=dims))

                # avoid duplicate arguments
                symbols.remove(symbol)
            else:
                return_val.append(Result(expr))

        # setup input argument list
        array_symbols = {}
        for array in expressions.atoms(Indexed):
            array_symbols[array.base.label] = array

        for symbol in sorted(symbols, key=str):
            if symbol in array_symbols:
                dims = []
                array = array_symbols[symbol]
                for dim in array.shape:
                    dims.append((S.Zero, dim - 1))
                metadata = {'dimensions': dims}
            else:
                metadata = {}

            arg_list.append(InputArgument(symbol, **metadata))

        output_args.sort(key=lambda x: str(x.name))
        arg_list.extend(output_args)

        if argument_sequence is not None:
            # if the user has supplied IndexedBase instances, we'll accept that
            new_sequence = []
            for arg in argument_sequence:
                if isinstance(arg, IndexedBase):
                    new_sequence.append(arg.label)
                else:
                    new_sequence.append(arg)
            argument_sequence = new_sequence

            missing = filter(lambda x: x.name not in argument_sequence,
                             arg_list)
            if missing:
                raise CodeGenArgumentListError(
                    "Argument list didn't specify: %s" %
                    ", ".join([str(m.name) for m in missing]), missing)

            # create redundant arguments to produce the requested sequence
            name_arg_dict = dict([(x.name, x) for x in arg_list])
            new_args = []
            for symbol in argument_sequence:
                try:
                    new_args.append(name_arg_dict[symbol])
                except KeyError:
                    new_args.append(InputArgument(symbol))
            arg_list = new_args

        self.name = name
        self.arguments = arg_list
        self.results = return_val
        self.local_vars = local_vars
예제 #6
0
 def __new__(cls, expr, cond):
     if cond is True:
         cond = ExprCondPair.true_sentinel
     return Tuple.__new__(cls, expr, cond)
예제 #7
0
    def _regular_point_ellipse(self, a, b, c, d, e, f):
        D = 4 * a * c - b**2
        ok = D

        if not ok:
            raise ValueError("Rational Point on the conic does not exist")

        if a == 0 and c == 0:
            K = -1
            L = 4 * (d * e - b * f)
        elif c != 0:
            K = D
            L = 4 * c**2 * d**2 - 4 * b * c * d * e + 4 * a * c * e**2 + 4 * b**2 * c * f - 16 * a * c**2 * f
        else:
            K = D
            L = 4 * a**2 * e**2 - 4 * b * a * d * e + 4 * b**2 * a * f

        ok = L != 0 and not (K > 0 and L < 0)
        if not ok:
            raise ValueError("Rational Point on the conic does not exist")

        K = Rational(K).limit_denominator(10**12)
        L = Rational(L).limit_denominator(10**12)

        k1, k2 = K.p, K.q
        l1, l2 = L.p, L.q
        g = gcd(k2, l2)

        a1 = (l2 * k2) / g
        b1 = (k1 * l2) / g
        c1 = -(l1 * k2) / g
        a2 = sign(a1) * core(abs(a1), 2)
        r1 = sqrt(a1 / a2)
        b2 = sign(b1) * core(abs(b1), 2)
        r2 = sqrt(b1 / b2)
        c2 = sign(c1) * core(abs(c1), 2)
        r3 = sqrt(c1 / c2)

        g = gcd(gcd(a2, b2), c2)
        a2 = a2 / g
        b2 = b2 / g
        c2 = c2 / g

        g1 = gcd(a2, b2)
        a2 = a2 / g1
        b2 = b2 / g1
        c2 = c2 * g1

        g2 = gcd(a2, c2)
        a2 = a2 / g2
        b2 = b2 * g2
        c2 = c2 / g2

        g3 = gcd(b2, c2)
        a2 = a2 * g3
        b2 = b2 / g3
        c2 = c2 / g3

        x, y, z = symbols("x y z")
        eq = a2 * x**2 + b2 * y**2 + c2 * z**2

        solutions = diophantine(eq)

        if len(solutions) == 0:
            raise ValueError("Rational Point on the conic does not exist")

        flag = False
        for sol in solutions:
            syms = Tuple(*sol).free_symbols
            rep = {s: 3 for s in syms}
            sol_z = sol[2]

            if sol_z == 0:
                flag = True
                continue

            if not (isinstance(sol_z, Integer) or isinstance(sol_z, int)):
                syms_z = sol_z.free_symbols

                if len(syms_z) == 1:
                    p = next(iter(syms_z))
                    p_values = Complement(
                        S.Integers, solveset(Eq(sol_z, 0), p, S.Integers))
                    rep[p] = next(iter(p_values))

                if len(syms_z) == 2:
                    p, q = list(ordered(syms_z))

                    for i in S.Integers:
                        subs_sol_z = sol_z.subs(p, i)
                        q_values = Complement(
                            S.Integers,
                            solveset(Eq(subs_sol_z, 0), q, S.Integers))

                        if not q_values.is_empty:
                            rep[p] = i
                            rep[q] = next(iter(q_values))
                            break

                if len(syms) != 0:
                    x, y, z = tuple(s.subs(rep) for s in sol)
                else:
                    x, y, z = sol
                flag = False
                break

        if flag:
            raise ValueError("Rational Point on the conic does not exist")

        x = (x * g3) / r1
        y = (y * g2) / r2
        z = (z * g1) / r3
        x = x / z
        y = y / z

        if a == 0 and c == 0:
            x_reg = (x + y - 2 * e) / (2 * b)
            y_reg = (x - y - 2 * d) / (2 * b)
        elif c != 0:
            x_reg = (x - 2 * d * c + b * e) / K
            y_reg = (y - b * x_reg - e) / (2 * c)
        else:
            y_reg = (x - 2 * e * a + b * d) / K
            x_reg = (y - b * y_reg - d) / (2 * a)

        return x_reg, y_reg
예제 #8
0
        cube_faces,
        octahedron_faces,
        dodecahedron_faces,
        icosahedron_faces,
    )


# -----------------------------------------------------------------------
#   Standard Polyhedron groups
#
#   These are generated using _pgroup_calcs() above. However to save
#   import time we encode them explicitly here.
# -----------------------------------------------------------------------

tetrahedron = Polyhedron(
    Tuple(0, 1, 2, 3),
    Tuple(Tuple(0, 1, 2), Tuple(0, 2, 3), Tuple(0, 1, 3), Tuple(1, 2, 3)),
    Tuple(
        Perm(1, 2, 3),
        Perm(3)(0, 1, 2),
        Perm(0, 3, 2),
        Perm(0, 3, 1),
        Perm(0, 1)(2, 3),
        Perm(0, 2)(1, 3),
        Perm(0, 3)(1, 2),
    ),
)

cube = Polyhedron(
    Tuple(0, 1, 2, 3, 4, 5, 6, 7),
    Tuple(
예제 #9
0
 def shape(self):
     return Tuple(*numpy.shape(self.arg))
예제 #10
0
    def fprint(self, printer, lhs=None):
        """Fortran print."""

        a = IndexedBase(self.first)
        b = IndexedBase(self.second)
        slc = Slice(None, None)
        rank = self.rank

        if rank > 2:
            raise NotImplementedError('TODO')

        if rank == 2:
            a_inds = [[slc, 0], [slc, 1], [slc, 2]]
            b_inds = [[slc, 0], [slc, 1], [slc, 2]]

            if self.first.order == 'C':
                for inds in a_inds:
                    inds.reverse()
            if self.second.order == 'C':
                for inds in b_inds:
                    inds.reverse()

            a = [a[tuple(inds)] for inds in a_inds]
            b = [b[tuple(inds)] for inds in b_inds]

        cross_product = [
            a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2],
            a[0] * b[1] - a[1] * b[0]
        ]

        cross_product = Tuple(*cross_product)
        cross_product = printer(cross_product)
        first = printer(self.first)
        order = self.order

        if lhs is not None:
            lhs = printer(lhs)

            if rank == 2:
                alloc = 'allocate({0}(0:size({1},1)-1,0:size({1},2)-1))'.format(
                    lhs, first)

            elif rank == 1:
                alloc = 'allocate({}(0:size({})-1)'.format(lhs, first)

        if rank == 2:

            if order == 'C':

                code = 'reshape({}, shape({}), order=[2,1])'.format(
                    cross_product, first)
            else:

                code = 'reshape({}, shape({})'.format(cross_product, first)

        elif rank == 1:
            code = cross_product

        if lhs is not None:
            code = '{} = {}'.format(lhs, code)

        #return alloc + '\n' + code
        return code
예제 #11
0
 def shape(self):
     return Tuple(self.arg.rank)
예제 #12
0
    def routine(self, name, expr, argument_sequence, local_vars, settings):
        """Specialized Routine creation for Cython."""

        if is_sequence(expr) and not isinstance(expr,
                                                (MatrixBase, MatrixExpr)):
            if not expr:
                raise ValueError("No expression given")
            expressions = Tuple(*expr)
        else:
            expressions = Tuple(expr)

        self.settings = settings

        # local variables
        idx_vars = set()
        symbol_idx_vars = set()
        for l in expressions.atoms(For):
            idx_vars.update({i for i in l.atoms(Idx)})
            # remove symbols that have the same name of Idx in loop
            name_idx = [i.label.name for i in l.atoms(Idx)]
            symbol_idx_vars.update(
                {i
                 for i in l.atoms(Symbol) if i.name in name_idx})

        score_table = {}
        for i in idx_vars:
            score_table[i] = 0

        def rate_index_position(p):
            return p * 5

        arrays = expressions.atoms(Indexed)
        for arr in arrays:
            for p, ind in enumerate(arr.indices):
                try:
                    score_table[ind] += rate_index_position(p)
                except KeyError:
                    pass

        idx_order = sorted(idx_vars, key=lambda x: score_table[x])

        # local variables
        local_vars = set() if local_vars is None else set(local_vars)

        # symbols that should be arguments
        symbol_indexed_local = set()
        for l in local_vars:
            for ll in l.atoms(IndexedBase):
                symbol_indexed_local.update(
                    ll.atoms(Symbol) - ll.shape.atoms(Symbol))

        symbols = expressions.free_symbols - idx_vars - local_vars - symbol_idx_vars - symbol_indexed_local

        new_symbols = set([])
        new_symbols.update(symbols)

        for symbol in symbols:
            if isinstance(symbol, Idx):
                new_symbols.remove(symbol)
                if symbol.label in idx_vars:
                    new_symbols.update(symbol.args[1].free_symbols)
                else:
                    new_symbols.update([symbol.label])
        symbols = new_symbols

        output_args, instructions = extract(expressions, symbols)

        arg_list = []

        # setup input argument list
        array_symbols = {}
        for array in expressions.atoms(Indexed):
            array_symbols[array.base.label] = array
        for array in expressions.atoms(MatrixSymbol):
            array_symbols[array] = array

        for symbol in sorted(symbols, key=str):
            if symbol in array_symbols:
                dims = []
                array = array_symbols[symbol]
                for dim in array.shape:
                    if dim != 1:
                        dims.append((S.Zero, dim - 1))
                metadata = {'dimensions': dims}
            else:
                metadata = {}

            arg_list.append(InputArgument(symbol, **metadata))

        output_args.sort(key=lambda x: str(x.name))
        arg_list.extend(output_args)

        if argument_sequence is not None:
            # if the user has supplied IndexedBase instances, we'll accept that
            new_sequence = []
            for arg in argument_sequence:
                if isinstance(arg, IndexedBase):
                    new_sequence.append(arg.label)
                else:
                    new_sequence.append(arg)
            argument_sequence = new_sequence

            missing = [x for x in arg_list if x.name not in argument_sequence]
            if missing:
                msg = "Argument list didn't specify: {0} "
                msg = msg.format(", ".join([str(m.name) for m in missing]))
                raise CodeGenArgumentListError(msg, missing)

            # create redundant arguments to produce the requested sequence
            name_arg_dict = {x.name: x for x in arg_list}
            new_args = []
            for symbol in argument_sequence:
                try:
                    new_args.append(name_arg_dict[symbol])
                except KeyError:
                    new_args.append(InputArgument(symbol))
            arg_list = new_args

        return Routine(name, arg_list, instructions, idx_order, local_vars,
                       settings)
예제 #13
0
파일: integrals.py 프로젝트: ness01/sympy
    def _eval_subs(self, old, new):
        """
        Substitute old with new in the integrand and the limits, but don't
        change anything that is (or corresponds to) a dummy variable of
        integration.

        The normal substitution semantics -- traversing all arguments looking
        for matching patterns -- should not be applied to the Integrals since
        changing the integration variables should also entail a change in the
        integration limits (which should be done with the transform method). So
        this method just makes changes in the integrand and the limits.

        Not all instances of a given variable are conceptually the same: the
        first argument of the limit tuple with length greater than 1 and any
        corresponding variable in the integrand are dummy variables while
        every other symbol is a symbol that will be unchanged when the integral
        is evaluated. For example, the dummy variables for ``i`` can be seen
        as symbols with a preppended underscore:

        >>> from sympy import Integral
        >>> from sympy.abc import a, b, x, y
        >>> i = Integral(a + x, (a, a, b))
        >>> i.as_dummy()
        Integral(_a + x, (_a, a, b))

        If you want to change the lower limit to 1 there is no reason to
        prohibit this since it is not conceptually related to the integration
        variable, _a. Nor is there reason to disallow changing the b to 1.

        If a second limit were added, however, as in:

        >>> i = Integral(x + a, (a, a, b), (b, 1, 2))

        the dummy variables become:

        >>> i.as_dummy()
        Integral(_a + x, (_a, a, _b), (_b, 1, 2))

        Note that the ``b`` of the first limit is now a dummy variable since
        ``b`` is a dummy variable in the second limit.

        The "evaluate at" form of an integral allows some flexibility in how
        the integral will be treated by subs: if there is no second argument,
        none of the symbols matching the integration symbol are considered to
        be dummy variables, but if an explicit expression is given for a limit
        then the usual interpretation of the integration symbol as a dummy
        symbol applies:

        >>> Integral(x).as_dummy() # implicit integration wrt x
        Integral(x, x)
        >>> Integral(x, x).as_dummy()
        Integral(x, x)
        >>> _.subs(x, 1)
        Integral(1, x)
        >>> i = Integral(x, (x, x))
        >>> i.as_dummy()
        Integral(_x, (_x, x))
        >>> i.subs(x, 1)
        Integral(x, (x, 1))

        Summary: no variable of the integrand or limit can be the target of
        substitution if it appears as a variable of integration in a limit
        positioned to the right of it. The only exception is for a variable
        that defines an indefinite integral limit (a single symbol): that
        symbol *can* be replaced in the integrand.

        >>> from sympy import Integral
        >>> from sympy.abc import a, b, c, x, y

        >>> i = Integral(a + x, (a, a, 3), (b, x, c))
        >>> i.free_symbols # only these can be changed
        set([a, c, x])
        >>> i.subs(a, c) # note that the variable of integration is unchanged
        Integral(a + x, (a, c, 3), (b, x, c))
        >>> i.subs(a + x, b) == i # there is no x + a, only x + <a>
        True
        >>> i.subs(x, y - c)
        Integral(a - c + y, (a, a, 3), (b, -c + y, c))
        """
        integrand, limits = self.function, self.limits
        old_atoms = old.free_symbols
        limits = list(limits)

        dummies = set()
        for i in xrange(-1, -len(limits) - 1, -1):
            xab = limits[i]
            if len(xab) == 1:
                continue
            if not dummies.intersection(old_atoms):
                limits[i] = Tuple(xab[0],
                                  *[l._subs(old, new) for l in xab[1:]])
            dummies.add(xab[0])
        if not dummies.intersection(old_atoms):
            integrand = integrand.subs(old, new)
        return Integral(integrand, *limits)
예제 #14
0
파일: integrals.py 프로젝트: ness01/sympy
    def __new__(cls, function, *symbols, **assumptions):
        """Create an unevaluated integral.

        Arguments are an integrand followed by one or more limits.

        If no limits are given and there is only one free symbol in the
        expression, that symbol will be used, otherwise an error will be
        raised.

        >>> from sympy import Integral
        >>> from sympy.abc import x, y
        >>> Integral(x)
        Integral(x, x)
        >>> Integral(y)
        Integral(y, y)

        When limits are provided, they are interpreted as follows (using
        ``x`` as though it were the variable of integration):

            (x,) or x - indefinite integral
            (x, a) - "evaluate at" integral
            (x, a, b) - definite integral

        Although the same integral will be obtained from an indefinite
        integral and an "evaluate at" integral when ``a == x``, they
        respond differently to substitution:

        >>> i = Integral(x, x)
        >>> at = Integral(x, (x, x))
        >>> i.doit() == at.doit()
        True
        >>> i.subs(x, 1)
        Integral(1, x)
        >>> at.subs(x, 1)
        Integral(x, (x, 1))

        The ``as_dummy`` method can be used to see which symbols cannot be
        targeted by subs: those with a preppended underscore cannot be
        changed with ``subs``. (Also, the integration variables themselves --
        the first element of a limit -- can never be changed by subs.)

        >>> i.as_dummy()
        Integral(x, x)
        >>> at.as_dummy()
        Integral(_x, (_x, x))

        """

        # 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 = piecewise_fold(sympify(function))

        if function is S.NaN:
            return S.NaN

        if symbols:
            limits, sign = _process_limits(*symbols)
        else:
            # no symbols provided -- let's compute full anti-derivative
            free = function.free_symbols
            if len(free) != 1:
                raise ValueError("specify variables of integration for %s" %
                                 function)
            limits, sign = [Tuple(s) for s in free], 1

        while isinstance(function, Integral):
            # denest the integrand
            limits = list(function.limits) + limits
            function = function.function

        obj = Expr.__new__(cls, **assumptions)
        arglist = [sign * function]
        arglist.extend(limits)
        obj._args = tuple(arglist)
        obj.is_commutative = all(s.is_commutative for s in obj.free_symbols)

        return obj
예제 #15
0
    def __new__(cls, corners, faces=[], pgroup=[]):
        """
        The constructor of the Polyhedron group object.

        It takes up to three parameters: the corners, faces, and
        allowed transformations.

        The corners/vertices are entered as a list of arbitrary
        expressions that are used to identify each vertex.

        The faces are entered as a list of tuples of indices; a tuple
        of indices identifies the vertices which define the face. They
        should be entered in a cw or ccw order; they will be standardized
        by reversal and rotation to be give the lowest lexical ordering.
        If no faces are given then no edges will be computed.

            >>> from sympy.combinatorics.polyhedron import Polyhedron
            >>> Polyhedron(list('abc'), [(1, 2, 0)]).faces
            {(0, 1, 2)}
            >>> Polyhedron(list('abc'), [(1, 0, 2)]).faces
            {(0, 1, 2)}

        The allowed transformations are entered as allowable permutations
        of the vertices for the polyhedron. Instance of Permutations
        (as with faces) should refer to the supplied vertices by index.
        These permutation are stored as a PermutationGroup.

        Examples
        ========

        >>> from sympy.combinatorics.permutations import Permutation
        >>> Permutation.print_cyclic = False
        >>> from sympy.abc import w, x, y, z

        Here we construct the Polyhedron object for a tetrahedron.

        >>> corners = [w, x, y, z]
        >>> faces = [(0,1,2), (0,2,3), (0,3,1), (1,2,3)]

        Next, allowed transformations of the polyhedron must be given. This
        is given as permutations of vertices.

        Although the vertices of a tetrahedron can be numbered in 24 (4!)
        different ways, there are only 12 different orientations for a
        physical tetrahedron. The following permutations, applied once or
        twice, will generate all 12 of the orientations. (The identity
        permutation, Permutation(range(4)), is not included since it does
        not change the orientation of the vertices.)

        >>> pgroup = [Permutation([[0,1,2], [3]]), \
                      Permutation([[0,1,3], [2]]), \
                      Permutation([[0,2,3], [1]]), \
                      Permutation([[1,2,3], [0]]), \
                      Permutation([[0,1], [2,3]]), \
                      Permutation([[0,2], [1,3]]), \
                      Permutation([[0,3], [1,2]])]

        The Polyhedron is now constructed and demonstrated:

        >>> tetra = Polyhedron(corners, faces, pgroup)
        >>> tetra.size
        4
        >>> tetra.edges
        {(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3)}
        >>> tetra.corners
        (w, x, y, z)

        It can be rotated with an arbitrary permutation of vertices, e.g.
        the following permutation is not in the pgroup:

        >>> tetra.rotate(Permutation([0, 1, 3, 2]))
        >>> tetra.corners
        (w, x, z, y)

        An allowed permutation of the vertices can be constructed by
        repeatedly applying permutations from the pgroup to the vertices.
        Here is a demonstration that applying p and p**2 for every p in
        pgroup generates all the orientations of a tetrahedron and no others:

        >>> all = ( (w, x, y, z), \
                    (x, y, w, z), \
                    (y, w, x, z), \
                    (w, z, x, y), \
                    (z, w, y, x), \
                    (w, y, z, x), \
                    (y, z, w, x), \
                    (x, z, y, w), \
                    (z, y, x, w), \
                    (y, x, z, w), \
                    (x, w, z, y), \
                    (z, x, w, y) )

        >>> got = []
        >>> for p in (pgroup + [p**2 for p in pgroup]):
        ...     h = Polyhedron(corners)
        ...     h.rotate(p)
        ...     got.append(h.corners)
        ...
        >>> set(got) == set(all)
        True

        The make_perm method of a PermutationGroup will randomly pick
        permutations, multiply them together, and return the permutation that
        can be applied to the polyhedron to give the orientation produced
        by those individual permutations.

        Here, 3 permutations are used:

        >>> tetra.pgroup.make_perm(3) # doctest: +SKIP
        Permutation([0, 3, 1, 2])

        To select the permutations that should be used, supply a list
        of indices to the permutations in pgroup in the order they should
        be applied:

        >>> use = [0, 0, 2]
        >>> p002 = tetra.pgroup.make_perm(3, use)
        >>> p002
        Permutation([1, 0, 3, 2])


        Apply them one at a time:

        >>> tetra.reset()
        >>> for i in use:
        ...     tetra.rotate(pgroup[i])
        ...
        >>> tetra.vertices
        (x, w, z, y)
        >>> sequentially = tetra.vertices

        Apply the composite permutation:

        >>> tetra.reset()
        >>> tetra.rotate(p002)
        >>> tetra.corners
        (x, w, z, y)
        >>> tetra.corners in all and tetra.corners == sequentially
        True

        Notes
        =====

        Defining permutation groups
        ---------------------------

        It is not necessary to enter any permutations, nor is necessary to
        enter a complete set of transforations. In fact, for a polyhedron,
        all configurations can be constructed from just two permutations.
        For example, the orientations of a tetrahedron can be generated from
        an axis passing through a vertex and face and another axis passing
        through a different vertex or from an axis passing through the
        midpoints of two edges opposite of each other.

        For simplicity of presentation, consider a square --
        not a cube -- with vertices 1, 2, 3, and 4:

        1-----2  We could think of axes of rotation being:
        |     |  1) through the face
        |     |  2) from midpoint 1-2 to 3-4 or 1-3 to 2-4
        3-----4  3) lines 1-4 or 2-3


        To determine how to write the permutations, imagine 4 cameras,
        one at each corner, labeled A-D:

        A       B          A       B
         1-----2            1-----3             vertex index:
         |     |            |     |                 1   0
         |     |            |     |                 2   1
         3-----4            2-----4                 3   2
        C       D          C       D                4   3

        original           after rotation
                           along 1-4

        A diagonal and a face axis will be chosen for the "permutation group"
        from which any orientation can be constructed.

        >>> pgroup = []

        Imagine a clockwise rotation when viewing 1-4 from camera A. The new
        orientation is (in camera-order): 1, 3, 2, 4 so the permutation is
        given using the *indices* of the vertices as:

        >>> pgroup.append(Permutation((0, 2, 1, 3)))

        Now imagine rotating clockwise when looking down an axis entering the
        center of the square as viewed. The new camera-order would be
        3, 1, 4, 2 so the permutation is (using indices):

        >>> pgroup.append(Permutation((2, 0, 3, 1)))

        The square can now be constructed:
            ** use real-world labels for the vertices, entering them in
               camera order
            ** for the faces we use zero-based indices of the vertices
               in *edge-order* as the face is traversed; neither the
               direction nor the starting point matter -- the faces are
               only used to define edges (if so desired).

        >>> square = Polyhedron((1, 2, 3, 4), [(0, 1, 3, 2)], pgroup)

        To rotate the square with a single permutation we can do:

        >>> square.rotate(square.pgroup[0]); square.corners
        (1, 3, 2, 4)

        To use more than one permutation (or to use one permutation more
        than once) it is more convenient to use the make_perm method:

        >>> p011 = square.pgroup.make_perm([0,1,1]) # diag flip + 2 rotations
        >>> square.reset() # return to initial orientation
        >>> square.rotate(p011); square.corners
        (4, 2, 3, 1)

        Thinking outside the box
        ------------------------

        Although the Polyhedron object has a direct physical meaning, it
        actually has broader application. In the most general sense it is
        just a decorated PermutationGroup, allowing one to connect the
        permutations to something physical. For example, a Rubik's cube is
        not a proper polyhedron, but the Polyhedron class can be used to
        represent it in a way that helps to visualize the Rubik's cube.

        >>> from sympy.utilities.iterables import flatten, unflatten
        >>> from sympy import symbols
        >>> from sympy.combinatorics import RubikGroup
        >>> facelets = flatten([symbols(s+'1:5') for s in 'UFRBLD'])
        >>> def show():
        ...     pairs = unflatten(r2.corners, 2)
        ...     print(pairs[::2])
        ...     print(pairs[1::2])
        ...
        >>> r2 = Polyhedron(facelets, pgroup=RubikGroup(2))
        >>> show()
        [(U1, U2), (F1, F2), (R1, R2), (B1, B2), (L1, L2), (D1, D2)]
        [(U3, U4), (F3, F4), (R3, R4), (B3, B4), (L3, L4), (D3, D4)]
        >>> r2.rotate(0) # cw rotation of F
        >>> show()
        [(U1, U2), (F3, F1), (U3, R2), (B1, B2), (L1, D1), (R3, R1)]
        [(L4, L2), (F4, F2), (U4, R4), (B3, B4), (L3, D2), (D3, D4)]

        Predefined Polyhedra
        ====================

        For convenience, the vertices and faces are defined for the following
        standard solids along with a permutation group for transformations.
        When the polyhedron is oriented as indicated below, the vertices in
        a given horizontal plane are numbered in ccw direction, starting from
        the vertex that will give the lowest indices in a given face. (In the
        net of the vertices, indices preceded by "-" indicate replication of
        the lhs index in the net.)

        tetrahedron, tetrahedron_faces
        ------------------------------

            4 vertices (vertex up) net:

                 0 0-0
                1 2 3-1

            4 faces:

            (0,1,2) (0,2,3) (0,3,1) (1,2,3)

        cube, cube_faces
        ----------------

            8 vertices (face up) net:

                0 1 2 3-0
                4 5 6 7-4

            6 faces:

            (0,1,2,3)
            (0,1,5,4) (1,2,6,5) (2,3,7,6) (0,3,7,4)
            (4,5,6,7)

        octahedron, octahedron_faces
        ----------------------------

            6 vertices (vertex up) net:

                 0 0 0-0
                1 2 3 4-1
                 5 5 5-5

            8 faces:

            (0,1,2) (0,2,3) (0,3,4) (0,1,4)
            (1,2,5) (2,3,5) (3,4,5) (1,4,5)

        dodecahedron, dodecahedron_faces
        --------------------------------

            20 vertices (vertex up) net:

                  0  1  2  3  4 -0
                  5  6  7  8  9 -5
                14 10 11 12 13-14
                15 16 17 18 19-15

            12 faces:

            (0,1,2,3,4)
            (0,1,6,10,5) (1,2,7,11,6) (2,3,8,12,7) (3,4,9,13,8) (0,4,9,14,5)
            (5,10,16,15,14) (
                6,10,16,17,11) (7,11,17,18,12) (8,12,18,19,13) (9,13,19,15,14)
            (15,16,17,18,19)

        icosahedron, icosahedron_faces
        ------------------------------

            12 vertices (face up) net:

                 0  0  0  0 -0
                1  2  3  4  5 -1
                 6  7  8  9  10 -6
                  11 11 11 11 -11

            20 faces:

            (0,1,2) (0,2,3) (0,3,4) (0,4,5) (0,1,5)
            (1,2,6) (2,3,7) (3,4,8) (4,5,9) (1,5,10)
            (2,6,7) (3,7,8) (4,8,9) (5,9,10) (1,6,10)
            (6,7,11,) (7,8,11) (8,9,11) (9,10,11) (6,10,11)

        >>> from sympy.combinatorics.polyhedron import cube
        >>> cube.edges
        {(0, 1), (0, 3), (0, 4), '...', (4, 7), (5, 6), (6, 7)}

        If you want to use letters or other names for the corners you
        can still use the pre-calculated faces:

        >>> corners = list('abcdefgh')
        >>> Polyhedron(corners, cube.faces).corners
        (a, b, c, d, e, f, g, h)

        References
        ==========

        [1] www.ocf.berkeley.edu/~wwu/articles/platonicsolids.pdf

        """
        faces = [minlex(f, directed=False, is_set=True) for f in faces]
        corners, faces, pgroup = args = \
            [Tuple(*a) for a in (corners, faces, pgroup)]
        obj = Basic.__new__(cls, *args)
        obj._corners = tuple(corners)  # in order given
        obj._faces = FiniteSet(faces)
        if pgroup and pgroup[0].size != len(corners):
            raise ValueError("Permutation size unequal to number of corners.")
        # use the identity permutation if none are given
        obj._pgroup = PermutationGroup((
            pgroup or [Perm(range(len(corners)))] ))
        return obj
예제 #16
0
 def _eval_subs(self, old, new):
     # only do substitutions in shape
     shape = Tuple(*self.shape)._subs(old, new)
     return MatrixSymbol(self.name, *shape)
예제 #17
0
    def routine(self, name, expr, argument_sequence, global_vars):
        """Creates an Routine object that is appropriate for this language.

        This implementation is appropriate for at least C/Fortran.  Subclasses
        can override this if necessary.

        Here, we assume at most one return value (the l-value) which must be
        scalar.  Additional outputs are OutputArguments (e.g., pointers on
        right-hand-side or pass-by-reference).  Matrices are always returned
        via OutputArguments.  If ``argument_sequence`` is None, arguments will
        be ordered alphabetically, but with all InputArguments first, and then
        OutputArgument and InOutArguments.

        This implementation is almost the same as the CodeGen class, but
        expensive calls to Basic.atoms() have been replaced with
        cheaper equivalents.

        """

        if is_sequence(expr) and not isinstance(expr, (MatrixBase, MatrixExpr)):
            if not expr:
                raise ValueError("No expression given")
            expressions = Tuple(*expr)
        else:
            expressions = Tuple(expr)

        expr_free_symbols = expressions.free_symbols

        # local variables
        local_vars = {i.label for i in expr_free_symbols if isinstance(i, Idx)}

        # global variables
        global_vars = set() if global_vars is None else set(global_vars)

        # symbols that should be arguments
        symbols = expr_free_symbols - local_vars - global_vars
        new_symbols = set([])
        new_symbols.update(symbols)

        for symbol in symbols:
            if isinstance(symbol, Idx):
                new_symbols.remove(symbol)
                new_symbols.update(symbol.args[1].free_symbols)
            if isinstance(symbol, Indexed):
                new_symbols.remove(symbol)
        symbols = new_symbols

        # Decide whether to use output argument or return value
        return_val = []
        output_args = []
        for expr in expressions:
            if isinstance(expr, Equality):
                out_arg = expr.lhs
                expr = expr.rhs
                if isinstance(out_arg, Indexed):
                    dims = tuple([ (S.Zero, dim - 1) for dim in out_arg.shape])
                    symbol = out_arg.base.label
                elif isinstance(out_arg, Symbol):
                    dims = []
                    symbol = out_arg
                elif isinstance(out_arg, MatrixSymbol):
                    dims = tuple([ (S.Zero, dim - 1) for dim in out_arg.shape])
                    symbol = out_arg
                else:
                    raise CodeGenError("Only Indexed, Symbol, or MatrixSymbol "
                                       "can define output arguments.")

                if expr.has(symbol):
                    output_args.append(
                        InOutArgument(symbol, out_arg, expr, dimensions=dims))
                else:
                    output_args.append(
                        OutputArgument(symbol, out_arg, expr, dimensions=dims))

                # avoid duplicate arguments
                symbols.remove(symbol)
            elif isinstance(expr, (ImmutableMatrix, MatrixSlice)):
                # Create a "dummy" MatrixSymbol to use as the Output arg
                out_arg = MatrixSymbol('out_%s' % abs(hash(expr)), *expr.shape)
                dims = tuple([(S.Zero, dim - 1) for dim in out_arg.shape])
                output_args.append(
                    OutputArgument(out_arg, out_arg, expr, dimensions=dims))
            else:
                return_val.append(Result(expr))

        arg_list = []

        # setup input argument list
        array_symbols = {}
        for array in [i for i in expr_free_symbols if isinstance(i, Indexed)]:
            array_symbols[array.base.label] = array
        for array in [i for i in expr_free_symbols if isinstance(i, MatrixSymbol)]:
            array_symbols[array] = array

        for symbol in sorted(symbols, key=str):
            if symbol in array_symbols:
                dims = []
                array = array_symbols[symbol]
                for dim in array.shape:
                    dims.append((S.Zero, dim - 1))
                metadata = {'dimensions': dims}
            else:
                metadata = {}

            arg_list.append(InputArgument(symbol, **metadata))

        output_args.sort(key=lambda x: str(x.name))
        arg_list.extend(output_args)

        if argument_sequence is not None:
            # if the user has supplied IndexedBase instances, we'll accept that
            new_sequence = []
            for arg in argument_sequence:
                if isinstance(arg, IndexedBase):
                    new_sequence.append(arg.label)
                else:
                    new_sequence.append(arg)
            argument_sequence = new_sequence

            missing = [x for x in arg_list if x.name not in argument_sequence]
            if missing:
                msg = "Argument list didn't specify: {0} "
                msg = msg.format(", ".join([str(m.name) for m in missing]))
                raise CodeGenArgumentListError(msg, missing)

            # create redundant arguments to produce the requested sequence
            name_arg_dict = {x.name: x for x in arg_list}
            new_args = []
            for symbol in argument_sequence:
                try:
                    new_args.append(name_arg_dict[symbol])
                except KeyError:
                    new_args.append(InputArgument(symbol))
            arg_list = new_args

        return Routine(name, arg_list, return_val, local_vars, global_vars)
예제 #18
0
 def __new__(cls, expr, cond):
     if cond is True:
         cond = ExprCondPair.true_sentinel
     return Tuple.__new__(cls, expr, cond)
예제 #19
0
def get_with_clauses(expr):
    # ...
    def _format_str(a):
        if isinstance(a, str):
            return a.strip('\'')
        else:
            return a

    # ...

    # ...
    d_attributs = {}
    d_args = {}
    # ...

    # ... we first create a dictionary of attributs
    if isinstance(expr, Variable):
        if expr.cls_base:
            d_attributs = expr.cls_base.attributs_as_dict
    elif isinstance(expr, ConstructorCall):
        attrs = expr.attributs
        for i in attrs:
            d_attributs[str(i).replace('self.', '')] = i
    # ...

    # ...
    if not d_attributs:
        raise ValueError('Can not find attributs')
    # ...

    # ...
    if isinstance(expr, Variable):
        cls_base = expr.cls_base

        if not cls_base:
            return None

        if not (('openacc' in cls_base.options) and
                ('with' in cls_base.options)):
            return None
    elif isinstance(expr, ConstructorCall):
        # arguments[0] is 'self'
        # TODO must be improved in syntax, so that a['value'] is a sympy object
        for a in expr.arguments[1:]:
            if isinstance(a, dict):
                # we add '_' tp be conform with the private variables convention
                d_args['_{0}'.format(a['key'])] = a['value']
    else:
        return None
    # ...

    # ... get initial values for all attributs
    #     TODO do we keep 'self' hard coded?
    d = {}
    for k, v in d_attributs.items():
        i = DottedName('self', k)
        d[k] = get_initial_value(expr, i)
    # ...

    # ... update the dictionary with the class parameters
    for k, v in d_args.items():
        d[k] = d_args[k]
    # ...

    # ... initial values for clauses
    _async = None
    _wait = None
    _num_gangs = None
    _num_workers = None
    _vector_length = None
    _device_type = None
    _if = None
    _reduction = None
    _copy = None
    _copyin = None
    _copyout = None
    _create = None
    _present = None
    _deviceptr = None
    _private = None
    _firstprivate = None
    _default = None
    # ...

    # ... async
    if not (d['_async'] is None):
        if not isinstance(d['_async'], Nil):
            ls = d['_async']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _async = ACC_Async(*ls)
    # ...

    # ... copy
    if not (d['_copy'] is None):
        if not isinstance(d['_copy'], Nil):
            ls = d['_copy']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _copy = ACC_Copy(*ls)
    # ...

    # ... copyin
    if not (d['_copyin'] is None):
        if not isinstance(d['_copyin'], Nil):
            ls = d['_copyin']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _copyin = ACC_Copyin(*ls)
    # ...

    # ... copyout
    if not (d['_copyout'] is None):
        if not isinstance(d['_copyout'], Nil):
            ls = d['_copyout']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _copyout = ACC_Copyout(*ls)
    # ...

    # ... create
    if not (d['_create'] is None):
        if not isinstance(d['_create'], Nil):
            ls = d['_create']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _create = ACC_Copyin(*ls)
    # ...

    # ... default
    if not (d['_default'] is None):
        if not isinstance(d['_default'], Nil):
            ls = d['_default']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls[0] = _format_str(ls[0])
            _default = ACC_Default(*ls)
    # ...

    # ... deviceptr
    if not (d['_deviceptr'] is None):
        if not isinstance(d['_deviceptr'], Nil):
            ls = d['_deviceptr']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _deviceptr = ACC_DevicePtr(*ls)
    # ...

    # ... devicetype
    if not (d['_device_type'] is None):
        if not isinstance(d['_device_type'], Nil):
            ls = d['_device_type']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _device_type = ACC_DeviceType(*ls)
    # ...

    # ... firstprivate
    if not (d['_firstprivate'] is None):
        if not isinstance(d['_firstprivate'], Nil):
            ls = d['_firstprivate']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _firstprivate = ACC_FirstPrivate(*ls)
    # ...

    # ... if
    #     TODO improve this to take any boolean expression for arg.
    #     see OpenACC specifications
    if not (d['_if'] is None):
        if not isinstance(d['_if'], Nil):
            arg = d['_if']
            ls = [arg]
            _if = ACC_If(*ls)
    # ...

    # ... num_gangs
    #     TODO improve this to take any int expression for arg.
    #     see OpenACC specifications
    if not (d['_num_gangs'] is None):
        if not isinstance(d['_num_gangs'], Nil):
            arg = d['_num_gangs']
            ls = [arg]
            _num_gangs = ACC_NumGangs(*ls)
    # ...

    # ... num_workers
    #     TODO improve this to take any int expression for arg.
    #     see OpenACC specifications
    if not (d['_num_workers'] is None):
        if not isinstance(d['_num_workers'], Nil):
            arg = d['_num_workers']
            ls = [arg]
            _num_workers = ACC_NumWorkers(*ls)
    # ...

    # ... present
    if not (d['_present'] is None):
        if not isinstance(d['_present'], Nil):
            ls = d['_present']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _present = ACC_Present(*ls)
    # ...

    # ... private
    if not (d['_private'] is None):
        if not isinstance(d['_private'], Nil):
            ls = d['_private']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _private = ACC_Private(*ls)
    # ...

    # ... reduction
    if not (d['_reduction'] is None):
        if not isinstance(d['_reduction'], Nil):
            ls = d['_reduction']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _reduction = ACC_Reduction(*ls)
    # ...

    # ... vector_length
    if not (d['_vector_length'] is None):
        if not isinstance(d['_vector_length'], Nil):
            arg = d['_vector_length']
            ls = [arg]
            _vector_length = ACC_VectorLength(*ls)
    # ...

    # ... wait
    if not (d['_wait'] is None):
        if not isinstance(d['_wait'], Nil):
            ls = d['_wait']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _wait = ACC_Wait(*ls)
    # ...

    # ...
    clauses = (_async, _wait, _num_gangs, _num_workers, _vector_length,
               _device_type, _if, _reduction, _copy, _copyin, _copyout,
               _create, _present, _deviceptr, _private, _firstprivate,
               _default)

    clauses = [i for i in clauses if not (i is None)]
    clauses = Tuple(*clauses)
    # ...

    return clauses
예제 #20
0
파일: piecewise.py 프로젝트: AALEKH/sympy
 def __new__(cls, expr, cond):
     return Tuple.__new__(cls, expr, cond)
예제 #21
0
def get_for_clauses(expr):
    # ...
    def _format_str(a):
        if isinstance(a, str):
            return a.strip('\'')
        else:
            return a

    # ...

    # ...
    d_attributs = {}
    d_args = {}
    # ...

    # ... we first create a dictionary of attributs
    if isinstance(expr, Variable):
        if expr.cls_base:
            d_attributs = expr.cls_base.attributs_as_dict
    elif isinstance(expr, ConstructorCall):
        attrs = expr.attributs
        for i in attrs:
            d_attributs[str(i).replace('self.', '')] = i
    # ...

    # ...
    if not d_attributs:
        raise ValueError('Can not find attributs')
    # ...

    # ...
    if isinstance(expr, Variable):
        cls_base = expr.cls_base

        if not cls_base:
            return None, None

        if not (('openacc' in cls_base.options) and
                ('iterable' in cls_base.options)):
            return None, None
    elif isinstance(expr, ConstructorCall):
        # arguments[0] is 'self'
        # TODO must be improved in syntax, so that a['value'] is a sympy object
        for a in expr.arguments[1:]:
            if isinstance(a, dict):
                # we add '_' tp be conform with the private variables convention
                d_args['_{0}'.format(a['key'])] = a['value']
    else:
        return None, None
    # ...

    # ... get initial values for all attributs
    #     TODO do we keep 'self' hard coded?
    d = {}
    for k, v in d_attributs.items():
        i = DottedName('self', k)
        d[k] = get_initial_value(expr, i)
    # ...

    # ... update the dictionary with the class parameters
    for k, v in d_args.items():
        d[k] = d_args[k]
    # ...

    # ... initial values for clauses
    _collapse = None
    _gang = None
    _worker = None
    _vector = None
    _seq = None
    _auto = None
    _tile = None
    _device_type = None
    _independent = None
    _private = None
    _reduction = None
    # ...

    # ... auto
    if not (d['_auto'] is None):
        if not isinstance(d['_auto'], Nil):
            _auto = ACC_Auto()
    # ...

    # ... collapse
    if not (d['_collapse'] is None):
        if not isinstance(d['_collapse'], Nil):
            ls = [d['_collapse']]
            _collapse = ACC_Collapse(*ls)
    # ...

    # ... device_type
    if not (d['_device_type'] is None):
        if not isinstance(d['_device_type'], Nil):
            ls = d['_device_type']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _device_type = ACC_DeviceType(*ls)
    # ...

    # ... gang
    if not (d['_gang'] is None):
        if not isinstance(d['_gang'], Nil):
            ls = d['_gang']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _gang = ACC_Gang(*ls)
    # ...

    # ... independent
    if not (d['_independent'] is None):
        if not isinstance(d['_independent'], Nil):
            _independent = ACC_Independent()
    # ...

    # ... private
    if not (d['_private'] is None):
        if not isinstance(d['_private'], Nil):
            ls = d['_private']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _private = ACC_Private(*ls)
    # ...

    # ... reduction
    if not (d['_reduction'] is None):
        if not isinstance(d['_reduction'], Nil):
            ls = d['_reduction']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _reduction = ACC_Reduction(*ls)
    # ...

    # ... seq
    if not (d['_seq'] is None):
        if not isinstance(d['_seq'], Nil):
            _seq = ACC_Seq()
    # ...

    # ... tile
    if not (d['_tile'] is None):
        if not isinstance(d['_tile'], Nil):
            ls = d['_tile']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _tile = ACC_Tile(*ls)
    # ...

    # ... vector
    if not (d['_vector'] is None):
        if not isinstance(d['_vector'], Nil):
            ls = d['_vector']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _vector = ACC_Vector(*ls)
    # ...

    # ... worker
    if not (d['_worker'] is None):
        if not isinstance(d['_worker'], Nil):
            ls = d['_worker']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            _worker = ACC_Worker(*ls)
    # ...

    # ...
    clauses = (_collapse, _gang, _worker, _vector, _seq, _auto, _tile,
               _device_type, _independent, _private, _reduction)

    clauses = [i for i in clauses if not (i is None)]
    clauses = Tuple(*clauses)
    # ...

    return clauses
예제 #22
0
파일: piecewise.py 프로젝트: B-Rich/sympy
 def __new__(cls, expr, cond):
     if cond == True:
         return Tuple.__new__(cls, expr, true)
     elif cond == False:
         return Tuple.__new__(cls, expr, false)
     return Tuple.__new__(cls, expr, cond)
 def args(self):
     return (Tuple(*self._basis), Tuple(*self._options.gens))
예제 #24
0
    def rational_parametrization(self, parameters=('t', 's'), reg_point=None):
        """
        Returns the rational parametrization of implict region.

        Examples
        ========

        >>> from sympy import Eq
        >>> from sympy.abc import x, y, z, s, t
        >>> from sympy.vector import ImplicitRegion

        >>> parabola = ImplicitRegion((x, y), y**2 - 4*x)
        >>> parabola.rational_parametrization()
        (4/t**2, 4/t)

        >>> circle = ImplicitRegion((x, y), Eq(x**2 + y**2, 4))
        >>> circle.rational_parametrization()
        (4*t/(t**2 + 1), 4*t**2/(t**2 + 1) - 2)

        >>> I = ImplicitRegion((x, y), x**3 + x**2 - y**2)
        >>> I.rational_parametrization()
        (t**2 - 1, t*(t**2 - 1))

        >>> cubic_curve = ImplicitRegion((x, y), x**3 + x**2 - y**2)
        >>> cubic_curve.rational_parametrization(parameters=(t))
        (t**2 - 1, t*(t**2 - 1))

        >>> sphere = ImplicitRegion((x, y, z), x**2 + y**2 + z**2 - 4)
        >>> sphere.rational_parametrization(parameters=(t, s))
        (-2 + 4/(s**2 + t**2 + 1), 4*s/(s**2 + t**2 + 1), 4*t/(s**2 + t**2 + 1))

        For some conics, regular_points() is unable to find a point on curve.
        To calulcate the parametric representation in such cases, user need
        to determine a point on the region and pass it using reg_point.

        >>> c = ImplicitRegion((x, y), (x  - 1/2)**2 + (y)**2 - (1/4)**2)
        >>> c.rational_parametrization(reg_point=(3/4, 0))
        (0.75 - 0.5/(t**2 + 1), -0.5*t/(t**2 + 1))

        References
        ==========

        - Christoph M. Hoffmann, "Conversion Methods between Parametric and
          Implicit Curves and Surfaces", Purdue e-Pubs, 1990. Available:
          https://docs.lib.purdue.edu/cgi/viewcontent.cgi?article=1827&context=cstech

        """
        equation = self.equation
        degree = self.degree

        if degree == 1:
            if len(self.variables) == 1:
                return (equation, )
            elif len(self.variables) == 2:
                x, y = self.variables
                y_par = list(solveset(equation, y))[0]
                return x, y_par
            else:
                raise NotImplementedError()

        point = ()

        # Finding the (n - 1) fold point of the monoid of degree
        if degree == 2:
            # For degree 2 curves, either a regular point or a singular point can be used.
            if reg_point is not None:
                # Using point provided by the user as regular point
                point = reg_point
            else:
                if len(self.singular_points()) != 0:
                    point = list(self.singular_points())[0]
                else:
                    point = self.regular_point()

        if len(self.singular_points()) != 0:
            singular_points = self.singular_points()
            for spoint in singular_points:
                syms = Tuple(*spoint).free_symbols
                rep = {s: 2 for s in syms}

                if len(syms) != 0:
                    spoint = tuple(s.subs(rep) for s in spoint)

                if self.multiplicity(spoint) == degree - 1:
                    point = spoint
                    break

        if len(point) == 0:
            # The region in not a monoid
            raise NotImplementedError()

        modified_eq = equation

        # Shifting the region such that fold point moves to origin
        for i, var in enumerate(self.variables):
            modified_eq = modified_eq.subs(var, var + point[i])
        modified_eq = expand(modified_eq)

        hn = hn_1 = 0
        for term in modified_eq.args:
            if total_degree(term) == degree:
                hn += term
            else:
                hn_1 += term

        hn_1 = -1 * hn_1

        if not isinstance(parameters, tuple):
            parameters = (parameters, )

        if len(self.variables) == 2:

            parameter1 = parameters[0]
            if parameter1 == 's':
                # To avoid name conflict between parameters
                s = _symbol('s_', real=True)
            else:
                s = _symbol('s', real=True)
            t = _symbol(parameter1, real=True)

            hn = hn.subs({self.variables[0]: s, self.variables[1]: t})
            hn_1 = hn_1.subs({self.variables[0]: s, self.variables[1]: t})

            x_par = (s * (hn_1 / hn)).subs(s, 1) + point[0]
            y_par = (t * (hn_1 / hn)).subs(s, 1) + point[1]

            return x_par, y_par

        elif len(self.variables) == 3:

            parameter1, parameter2 = parameters
            if parameter1 == 'r' or parameter2 == 'r':
                # To avoid name conflict between parameters
                r = _symbol('r_', real=True)
            else:
                r = _symbol('r', real=True)
            s = _symbol(parameter2, real=True)
            t = _symbol(parameter1, real=True)

            hn = hn.subs({
                self.variables[0]: r,
                self.variables[1]: s,
                self.variables[2]: t
            })
            hn_1 = hn_1.subs({
                self.variables[0]: r,
                self.variables[1]: s,
                self.variables[2]: t
            })

            x_par = (r * (hn_1 / hn)).subs(r, 1) + point[0]
            y_par = (s * (hn_1 / hn)).subs(r, 1) + point[1]
            z_par = (t * (hn_1 / hn)).subs(r, 1) + point[2]

            return x_par, y_par, z_par

        raise NotImplementedError()
예제 #25
0
def get_with_clauses(expr):
    # ...
    def _format_str(a):
        if isinstance(a, str):
            return a.strip('\'')
        else:
            return a
    # ...

    # ...
    d_attributs = {}
    d_args      = {}
    # ...

    # ... we first create a dictionary of attributs
    if isinstance(expr, Variable):
        if expr.cls_base:
            d_attributs = expr.cls_base.attributs_as_dict

    elif isinstance(expr, ConstructorCall):
        attrs = expr.attributs
        for i in attrs:
            d_attributs[str(i).replace('self.', '')] = i
    # ...

    # ...
    if not d_attributs:
        raise ValueError('Can not find attributs')
    # ...

    # ...
    if isinstance(expr, Variable):
        cls_base = expr.cls_base

        if not cls_base:
            return None

        if not(('openmp' in cls_base.options) and ('with' in cls_base.options)):
            return None
    elif isinstance(expr, ConstructorCall):
        # arguments[0] is 'self'
        # TODO must be improved in syntax, so that a['value'] is a sympy object
        for a in expr.arguments[1:]:
            if isinstance(a, dict):
                # we add '_' tp be conform with the private variables convention
                d_args['_{0}'.format(a['key'])] = a['value']
    else:
        return None
    # ...

    # ... get initial values for all attributs
    #     TODO do we keep 'self' hard coded?
    d = {}
    for k,v in d_attributs.items():
        i = DottedName('self', k)
        d[k] = get_initial_value(expr, i)
    # ...

    # ... update the dictionary with the class parameters
    for k,v in d_args.items():
        d[k] = d_args[k]
    # ...

    # ... initial values for clauses
    private      = None
    firstprivate = None
    shared       = None
    reduction    = None
    copyin       = None
    default      = None
    proc_bind    = None
    num_threads  = None
    if_test      = None
    # ...

    # ... private
    if not(d['_private'] is None):
        if not isinstance(d['_private'], Nil):
            ls = d['_private']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            private = OMP_Private(*ls)
    # ...

    # ... firstprivate
    if not(d['_firstprivate'] is None):
        if not isinstance(d['_firstprivate'], Nil):
            ls = d['_firstprivate']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            firstprivate = OMP_FirstPrivate(*ls)
    # ...

    # ... shared
    if not(d['_shared'] is None):
        if not isinstance(d['_shared'], Nil):
            ls = d['_shared']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            shared = OMP_Shared(*ls)
    # ...

    # ... reduction
    if not(d['_reduction'] is None):
        if not isinstance(d['_reduction'], Nil):
            ls = d['_reduction']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            reduction = OMP_Reduction(*ls)
    # ...

    # ... copyin
    if not(d['_copyin'] is None):
        if not isinstance(d['_copyin'], Nil):
            ls = d['_copyin']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            copyin = OMP_Copyin(*ls)
    # ...

    # ... default
    if not(d['_default'] is None):
        if not isinstance(d['_default'], Nil):
            ls = d['_default']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls[0] = _format_str(ls[0])
            default = OMP_Default(*ls)
    # ...

    # ... proc_bind
    if not(d['_proc_bind'] is None):
        if not isinstance(d['_proc_bind'], Nil):
            ls = d['_proc_bind']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls[0] = _format_str(ls[0])
            proc_bind = OMP_ProcBind(*ls)
    # ...

    # ... num_threads
    #     TODO improve this to take any int expression for arg.
    #     see OpenMP specifications for num_threads clause
    if not(d['_num_threads'] is None):
        if not isinstance(d['_num_threads'], Nil):
            arg = d['_num_threads']
            ls = [arg]
            num_threads = OMP_NumThread(*ls)
    # ...

    # ... if_test
    #     TODO improve this to take any boolean expression for arg.
    #     see OpenMP specifications for if_test clause
    if not(d['_if_test'] is None):
        if not isinstance(d['_if_test'], Nil):
            arg = d['_if_test']
            ls = [arg]
            if_test = OMP_If(*ls)
    # ...

    # ...
    clauses = (private, firstprivate, shared,
               reduction, default, copyin,
               proc_bind, num_threads, if_test)
    clauses = [i for i in clauses if not(i is None)]
    clauses = Tuple(*clauses)
    # ...

    return clauses
예제 #26
0
 def __str__(self):
     from sympy.core import Tuple
     return self.__class__.__name__ + str(Tuple(*[x[0] for x in self.args]))
예제 #27
0
def get_for_clauses(expr):
    # ...
    def _format_str(a):
        if isinstance(a, str):
            return a.strip('\'')
        else:
            return a
    # ...

    # ...
    d_attributs = {}
    d_args      = {}
    # ...

    # ... we first create a dictionary of attributs
    if isinstance(expr, Variable):
        if expr.cls_base:
            d_attributs = expr.cls_base.attributs_as_dict
    elif isinstance(expr, ConstructorCall):
        attrs = expr.attributs
        for i in attrs:
            d_attributs[str(i).replace('self.', '')] = i
    # ...

    # ...
    if not d_attributs:
        raise ValueError('Can not find attributs')
    # ...

    # ...
    if isinstance(expr, Variable):
        cls_base = expr.cls_base

        if not cls_base:
            return None, None

        if not(('openmp' in cls_base.options) and ('iterable' in cls_base.options)):
            return None, None
    elif isinstance(expr, ConstructorCall):
        # arguments[0] is 'self'
        # TODO must be improved in syntax, so that a['value'] is a sympy object
        for a in expr.arguments[1:]:
            if isinstance(a, dict):
                # we add '_' tp be conform with the private variables convention
                d_args['_{0}'.format(a['key'])] = a['value']
    else:
        return None, None
    # ...

    # ... get initial values for all attributs
    #     TODO do we keep 'self' hard coded?
    d = {}
    for k,v in d_attributs.items():
        i = DottedName('self', k)
        d[k] = get_initial_value(expr, i)
    # ...

    # ... update the dictionary with the class parameters
    for k,v in d_args.items():
        d[k] = d_args[k]
    # ...

    # ... initial values for clauses
    nowait       = None

    collapse     = None
    private      = None
    firstprivate = None
    lastprivate  = None
    reduction    = None
    schedule     = None
    ordered      = None
    linear       = None
    # ...

    # ... nowait
    nowait = d['_nowait']
    # ...

    # ... collapse
    if not(d['_collapse'] is None):
        if not isinstance(d['_collapse'], Nil):
            ls = [d['_collapse']]
            collapse = OMP_Collapse(*ls)
    # ...

    # ... private
    if not(d['_private'] is None):
        if not isinstance(d['_private'], Nil):
            ls = d['_private']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            private = OMP_Private(*ls)
    # ...

    # ... firstprivate
    if not(d['_firstprivate'] is None):
        if not isinstance(d['_firstprivate'], Nil):
            ls = d['_firstprivate']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            firstprivate = OMP_FirstPrivate(*ls)
    # ...

    # ... lastprivate
    if not(d['_lastprivate'] is None):
        if not isinstance(d['_lastprivate'], Nil):
            ls = d['_lastprivate']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            lastprivate = OMP_LastPrivate(*ls)
    # ...

    # ... reduction
    if not(d['_reduction'] is None):
        if not isinstance(d['_reduction'], Nil):
            ls = d['_reduction']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls = [_format_str(a) for a in ls]
            reduction = OMP_Reduction(*ls)
    # ...

    # ... schedule
    if not(d['_schedule'] is None):
        if not isinstance(d['_schedule'], Nil):
            ls = d['_schedule']
            if not isinstance(ls, (list, tuple, Tuple)):
                ls = [ls]

            ls[0] = _format_str(ls[0])
            schedule = OMP_Schedule(*ls)
    # ...

    # ... ordered
    if not(d['_ordered'] is None):
        if not isinstance(d['_ordered'], Nil):
            ls = d['_ordered']

            args = []
            if isinstance(ls, (int, sp_Integer)):
                args.append(ls)

            ordered = OMP_Ordered(*args)
    # ...

    # ... linear
    if not(d['_linear'] is None):
        if not isinstance(d['_linear'], Nil):
            # we need to convert Tuple to list here
            ls = list(d['_linear'])

            if len(ls) < 2:
                raise ValueError('Expecting at least 2 entries, '
                                 'given {0}'.format(len(ls)))

            variables = [a.strip('\'') for a in ls[0:-1]]
            ls[0:-1]  = variables

            linear = OMP_Linear(*ls)
    # ...

    # ...
    clauses = (private, firstprivate, lastprivate,
               reduction, schedule,
               ordered, collapse, linear)
    clauses = [i for i in clauses if not(i is None)]
    clauses = Tuple(*clauses)
    # ...

    # ...
    info = {}
    info['nowait'] = nowait
    # ...

    return info, clauses
예제 #28
0
 def __str__(self):
     from sympy.core import Tuple
     return "ProductOrder" + str(Tuple(*[x[0] for x in self.args]))
예제 #29
0
    def __new__(cls, partition, integer=None):
        """
        Generates a new IntegerPartition object from a list or dictionary.

        Explantion
        ==========

        The partition can be given as a list of positive integers or a
        dictionary of (integer, multiplicity) items. If the partition is
        preceded by an integer an error will be raised if the partition
        does not sum to that given integer.

        Examples
        ========

        >>> from sympy.combinatorics.partitions import IntegerPartition
        >>> a = IntegerPartition([5, 4, 3, 1, 1])
        >>> a
        IntegerPartition(14, (5, 4, 3, 1, 1))
        >>> print(a)
        [5, 4, 3, 1, 1]
        >>> IntegerPartition({1:3, 2:1})
        IntegerPartition(5, (2, 1, 1, 1))

        If the value that the partition should sum to is given first, a check
        will be made to see n error will be raised if there is a discrepancy:

        >>> IntegerPartition(10, [5, 4, 3, 1])
        Traceback (most recent call last):
        ...
        ValueError: The partition is not valid

        """
        if integer is not None:
            integer, partition = partition, integer
        if isinstance(partition, (dict, Dict)):
            _ = []
            for k, v in sorted(list(partition.items()), reverse=True):
                if not v:
                    continue
                k, v = as_int(k), as_int(v)
                _.extend([k]*v)
            partition = tuple(_)
        else:
            partition = tuple(sorted(map(as_int, partition), reverse=True))
        sum_ok = False
        if integer is None:
            integer = sum(partition)
            sum_ok = True
        else:
            integer = as_int(integer)

        if not sum_ok and sum(partition) != integer:
            raise ValueError("Partition did not add to %s" % integer)
        if any(i < 1 for i in partition):
            raise ValueError("All integer summands must be greater than one")

        obj = Basic.__new__(cls, Integer(integer), Tuple(*partition))
        obj.partition = list(partition)
        obj.integer = integer
        return obj
예제 #30
0
파일: integrals.py 프로젝트: pyc111/sympy
    def _eval_subs(self, old, new):
        """
        Substitute old with new in the integrand and the limits, but don't
        change anything that is (or corresponds to) a variable of integration.

        The normal substitution semantics -- traversing all arguments looking
        for matching patterns -- should not be applied to the Integrals since
        changing the integration variables should also entail a change in the
        integration limits (which should be done with the transform method). So
        this method just makes changes in the integrand and the limits.

        Not all instances of a given variable are conceptually the same: the
        first argument of the limit tuple and any corresponding variable in
        the integrand are dummy variables while every other symbol is a symbol
        that will be unchanged when the integral is evaluated. For example, in

            Integral(x + a, (a, a, b))

        the dummy variables are shown below with angle-brackets around them and
        will not be changed by this function:

            Integral(x + <a>, (<a>, a, b))

        If you want to change the lower limit to 1 there is no reason to
        prohibit this since it is not conceptually related to the integration
        variable, <a>. Nor is there reason to disallow changing the b to 1.

        If a second limit were added, however, as in:

            Integral(x + a, (a, a, b), (b, 1, 2))

        the dummy variables become:

            Integral(x + <a>, (<a>, a, <b>), (<b>, a, b))

        Note that the `b` of the first limit is now a dummy variable since `b` is a
        dummy variable in the second limit.

        Summary: no variable of the integrand or limit can be the target of
        substitution if it appears as a variable of integration in a limit
        positioned to the right of it.

        >>> from sympy import Integral
        >>> from sympy.abc import a, b, c, x, y

        >>> i = Integral(a + x, (a, a, 3), (b, x, c))
        >>> list(i.free_symbols) # only these can be changed
        [x, a, c]
        >>> i.subs(a, c) # note that the variable of integration is unchanged
        Integral(a + x, (a, c, 3), (b, x, c))
        >>> i.subs(a + x, b) == i # there is no x + a, only x + <a>
        True
        >>> i.subs(x, y - c)
        Integral(a + y - c, (a, a, 3), (b, y - c, c))
        """
        if self == old:
            return new
        integrand, limits = self.function, self.limits
        old_atoms = old.free_symbols
        limits = list(limits)

        # make limits explicit if they are to be targeted by old:
        # Integral(x, x) -> Integral(x, (x, x)) if old = x
        if old.is_Symbol:
            for i, l in enumerate(limits):
                if len(l) == 1 and l[0] == old:
                    limits[i] = Tuple(l[0], l[0])

        dummies = set()
        for i in xrange(-1, -len(limits) - 1, -1):
            xab = limits[i]
            if not dummies.intersection(old_atoms):
                limits[i] = Tuple(xab[0],
                                  *[l.subs(old, new) for l in xab[1:]])
            dummies.add(xab[0])
        if not dummies.intersection(old_atoms):
            integrand = integrand.subs(old, new)
        return Integral(integrand, *limits)
예제 #31
0
 def __new__(cls, expr, cond):
     return Tuple.__new__(cls, expr, cond)
예제 #32
0
 def _handle_irel(self, x, handler):
     """Return either None (if the conditions of self depend only on x) else
     a Piecewise expression whose expressions (handled by the handler that
     was passed) are paired with the governing x-independent relationals,
     e.g. Piecewise((A, a(x) & b(y)), (B, c(x) | c(y)) ->
     Piecewise(
         (handler(Piecewise((A, a(x) & True), (B, c(x) | True)), b(y) & c(y)),
         (handler(Piecewise((A, a(x) & True), (B, c(x) | False)), b(y)),
         (handler(Piecewise((A, a(x) & False), (B, c(x) | True)), c(y)),
         (handler(Piecewise((A, a(x) & False), (B, c(x) | False)), True))
     """
     # identify governing relationals
     rel = self.atoms(Relational)
     irel = list(
         ordered([
             r for r in rel
             if x not in r.free_symbols and r not in (S.true, S.false)
         ]))
     if irel:
         args = {}
         exprinorder = []
         for truth in product((1, 0), repeat=len(irel)):
             reps = dict(zip(irel, truth))
             # only store the true conditions since the false are implied
             # when they appear lower in the Piecewise args
             if 1 not in truth:
                 cond = None  # flag this one so it doesn't get combined
             else:
                 andargs = Tuple(*[i for i in reps if reps[i]])
                 free = list(andargs.free_symbols)
                 if len(free) == 1:
                     from sympy.solvers.inequalities import (
                         reduce_inequalities, _solve_inequality)
                     try:
                         t = reduce_inequalities(andargs, free[0])
                         # ValueError when there are potentially
                         # nonvanishing imaginary parts
                     except (ValueError, NotImplementedError):
                         # at least isolate free symbol on left
                         t = And(*[
                             _solve_inequality(a, free[0], linear=True)
                             for a in andargs
                         ])
                 else:
                     t = And(*andargs)
                 if t is S.false:
                     continue  # an impossible combination
                 cond = t
             expr = handler(self.xreplace(reps))
             if isinstance(expr, self.func) and len(expr.args) == 1:
                 expr, econd = expr.args[0]
                 cond = And(econd, True if cond is None else cond)
             # the ec pairs are being collected since all possibilities
             # are being enumerated, but don't put the last one in since
             # its expr might match a previous expression and it
             # must appear last in the args
             if cond is not None:
                 args.setdefault(expr, []).append(cond)
                 # but since we only store the true conditions we must maintain
                 # the order so that the expression with the most true values
                 # comes first
                 exprinorder.append(expr)
         # convert collected conditions as args of Or
         for k in args:
             args[k] = Or(*args[k])
         # take them in the order obtained
         args = [(e, args[e]) for e in uniq(exprinorder)]
         # add in the last arg
         args.append((expr, True))
         # if any condition reduced to True, it needs to go last
         # and there should only be one of them or else the exprs
         # should agree
         trues = [i for i in range(len(args)) if args[i][1] is S.true]
         if not trues:
             # make the last one True since all cases were enumerated
             e, c = args[-1]
             args[-1] = (e, S.true)
         else:
             assert len(set([e for e, c in [args[i] for i in trues]])) == 1
             args.append(args.pop(trues.pop()))
             while trues:
                 args.pop(trues.pop())
         return Piecewise(*args)
예제 #33
0
파일: piecewise.py 프로젝트: penenkel/sympy
 def __new__(cls, expr, cond):
     if cond == True:
         return Tuple.__new__(cls, expr, true)
     elif cond == False:
         return Tuple.__new__(cls, expr, false)
     return Tuple.__new__(cls, expr, cond)
예제 #34
0
def test_has():
    a, b, c = symbols("a, b, c", cls=Dummy)
    f = Hyper_Function([2, -a], [b])
    assert f.has(a)
    assert f.has(Tuple(b))
    assert not f.has(c)
예제 #35
0
def cse(exprs,
        symbols=None,
        optimizations=None,
        postprocess=None,
        order='canonical',
        ignore=()):
    """ Perform common subexpression elimination on an expression.

    Parameters
    ==========

    exprs : list of sympy expressions, or a single sympy expression
        The expressions to reduce.
    symbols : infinite iterator yielding unique Symbols
        The symbols used to label the common subexpressions which are pulled
        out. The ``numbered_symbols`` generator is useful. The default is a
        stream of symbols of the form "x0", "x1", etc. This must be an
        infinite iterator.
    optimizations : list of (callable, callable) pairs
        The (preprocessor, postprocessor) pairs of external optimization
        functions. Optionally 'basic' can be passed for a set of predefined
        basic optimizations. Such 'basic' optimizations were used by default
        in old implementation, however they can be really slow on larger
        expressions. Now, no pre or post optimizations are made by default.
    postprocess : a function which accepts the two return values of cse and
        returns the desired form of output from cse, e.g. if you want the
        replacements reversed the function might be the following lambda:
        lambda r, e: return reversed(r), e
    order : string, 'none' or 'canonical'
        The order by which Mul and Add arguments are processed. If set to
        'canonical', arguments will be canonically ordered. If set to 'none',
        ordering will be faster but dependent on expressions hashes, thus
        machine dependent and variable. For large expressions where speed is a
        concern, use the setting order='none'.
    ignore : iterable of Symbols
        Substitutions containing any Symbol from ``ignore`` will be ignored.

    Returns
    =======

    replacements : list of (Symbol, expression) pairs
        All of the common subexpressions that were replaced. Subexpressions
        earlier in this list might show up in subexpressions later in this
        list.
    reduced_exprs : list of sympy expressions
        The reduced expressions with all of the replacements above.

    Examples
    ========

    >>> from sympy import cse, SparseMatrix
    >>> from sympy.abc import x, y, z, w
    >>> cse(((w + x + y + z)*(w + y + z))/(w + x)**3)
    ([(x0, w + y + z)], [x0*(x + x0)/(w + x)**3])

    Note that currently, y + z will not get substituted if -y - z is used.

     >>> cse(((w + x + y + z)*(w - y - z))/(w + x)**3)
     ([(x0, w + x)], [(w - y - z)*(x0 + y + z)/x0**3])

    List of expressions with recursive substitutions:

    >>> m = SparseMatrix([x + y, x + y + z])
    >>> cse([(x+y)**2, x + y + z, y + z, x + z + y, m])
    ([(x0, x + y), (x1, x0 + z)], [x0**2, x1, y + z, x1, Matrix([
    [x0],
    [x1]])])

    Note: the type and mutability of input matrices is retained.

    >>> isinstance(_[1][-1], SparseMatrix)
    True

    The user may disallow substitutions containing certain symbols:
    >>> cse([y**2*(x + 1), 3*y**2*(x + 1)], ignore=(y,))
    ([(x0, x + 1)], [x0*y**2, 3*x0*y**2])

    """
    from sympy.matrices import (MatrixBase, Matrix, ImmutableMatrix,
                                SparseMatrix, ImmutableSparseMatrix)

    # Handle the case if just one expression was passed.
    if isinstance(exprs, (Basic, MatrixBase)):
        exprs = [exprs]

    copy = exprs
    temp = []
    for e in exprs:
        if isinstance(e, (Matrix, ImmutableMatrix)):
            temp.append(Tuple(*e._mat))
        elif isinstance(e, (SparseMatrix, ImmutableSparseMatrix)):
            temp.append(Tuple(*e._smat.items()))
        else:
            temp.append(e)
    exprs = temp
    del temp

    if optimizations is None:
        optimizations = list()
    elif optimizations == 'basic':
        optimizations = basic_optimizations

    # Preprocess the expressions to give us better optimization opportunities.
    reduced_exprs = [preprocess_for_cse(e, optimizations) for e in exprs]

    excluded_symbols = set().union(
        *[expr.atoms(Symbol) for expr in reduced_exprs])

    if symbols is None:
        symbols = numbered_symbols()
    else:
        # In case we get passed an iterable with an __iter__ method instead of
        # an actual iterator.
        symbols = iter(symbols)

    symbols = filter_symbols(symbols, excluded_symbols)

    # Find other optimization opportunities.
    opt_subs = opt_cse(reduced_exprs, order)

    # Main CSE algorithm.
    replacements, reduced_exprs = tree_cse(reduced_exprs, symbols, opt_subs,
                                           order, ignore)

    # Postprocess the expressions to return the expressions to canonical form.
    exprs = copy
    for i, (sym, subtree) in enumerate(replacements):
        subtree = postprocess_for_cse(subtree, optimizations)
        replacements[i] = (sym, subtree)
    reduced_exprs = [
        postprocess_for_cse(e, optimizations) for e in reduced_exprs
    ]

    # Get the matrices back
    for i, e in enumerate(exprs):
        if isinstance(e, (Matrix, ImmutableMatrix)):
            reduced_exprs[i] = Matrix(e.rows, e.cols, reduced_exprs[i])
            if isinstance(e, ImmutableMatrix):
                reduced_exprs[i] = reduced_exprs[i].as_immutable()
        elif isinstance(e, (SparseMatrix, ImmutableSparseMatrix)):
            m = SparseMatrix(e.rows, e.cols, {})
            for k, v in reduced_exprs[i]:
                m[k] = v
            if isinstance(e, ImmutableSparseMatrix):
                m = m.as_immutable()
            reduced_exprs[i] = m

    if postprocess is None:
        return replacements, reduced_exprs

    return postprocess(replacements, reduced_exprs)