Exemplo n.º 1
0
        def expand(prod):
            if not isinstance(prod, Product):
                return prod

            leading = []
            for i in prod.children:
                if isinstance(i, Sum):
                    break
                else:
                    leading.append(i)

            if len(leading) == len(prod.children):
                # no more sums found
                result = pymbolic.flattened_product(prod.children)
                return result
            else:
                sum = prod.children[len(leading)]
                assert isinstance(sum, Sum)
                rest = prod.children[len(leading)+1:]
                if rest:
                    rest = expand(Product(rest))
                else:
                    rest = 1

                result = self.collector(pymbolic.flattened_sum(
                       pymbolic.flattened_product(leading) * expand(sumchild*rest)
                       for sumchild in sum.children
                       ))
                return result
Exemplo n.º 2
0
def sexpr_to_pymbolic(expr):
    from pymbolic.primitives import Variable, Sum, Product, Power

    stack = []

    def error(token):
        raise ParserError("unexpected token at position %d (got '%r')" %
                          (token.pos, token))

    for token in tokenize(expr):
        if token.token_type in (TokenType.LPAREN, TokenType.IDENT):
            stack.append(token)

        elif token.token_type in (TokenType.FLOAT, TokenType.INT,
                                  TokenType.STRING):
            stack.append(token.data)

        elif token.token_type == TokenType.RPAREN:
            args = []
            while stack and not (isinstance(stack[-1], Token)
                                 and stack[-1].token_type == TokenType.LPAREN):
                args.append(stack.pop())
            if not stack:
                error(token)
            lparen = stack.pop()
            args = tuple(reversed(args))

            if not args:
                error(token)
            sym = args[0]
            if not isinstance(sym, Token):
                error(lparen)
            assert sym.token_type == TokenType.IDENT

            if sym.data == "Sum":
                val = Sum(args[1:])
            elif sym.data == "Product":
                val = Product(args[1:])
            elif sym.data == "Power":
                val = Power(*args[1:])
            elif sym.data == "Var":
                val = Variable(*args[1:])
            else:
                error(sym)

            stack.append(val)

        elif token.token_type == TokenType.END:
            if len(stack) != 1:
                error(token)
            if isinstance(stack[0], Token):
                error(token)

            return stack[0]
Exemplo n.º 3
0
        def vec_dot(lvec, rvec):
            if lvec.shape != rvec.shape:
                raise ValueError('mismatched dimensions: %s and %s' %
                                 (str(lvec.shape), str(rvec.shape)))
            if lvec.shape[0] != 1 and lvec.shape[0] != 1:
                raise ValueError("expected vectors, got %s matrix instead" %
                                 str(lvec.shape))

            lvec, rvec = lvec.flatten(), rvec.flatten()
            return Sum(
                tuple(Product((el1, el2)) for el1, el2 in zip(lvec, rvec)))
Exemplo n.º 4
0
    def __call__(self, array):
        """
        Computes the determinant of array, the given matrix.

        :param array: a `numpy.ndarray` representing the matrix

        :return: An expression tree that can be simplified further into the
        value of the determinant of `array`.

        :raise TypeError: if not array is not of type `numpy.ndarray`
        :raise ValueError: if array is not square in shape
        """

        if not isinstance(array, np.ndarray):
            raise TypeError('expected numpy.ndarray, got %s instead' %
                            str(type(array)))

        rows, cols = array.shape
        if rows != cols:
            raise ValueError('non-square matrix')
        if rows == 1:
            return array[0][0]
        if rows == 2:
            return Sum((Product((array[0][0], array[1][1])),
                        Product((-array[0][1], array[1][0]))))

        triu = array[np.triu_indices(rows, k=1)]
        tril = array[np.tril_indices(rows, k=-1)]
        if not np.any(triu) or not np.any(tril):
            # upper or lower triangular matrix
            return Product(tuple(entry for entry in array.diagonal()))

        def _minor(arr, i, j):
            return np.delete(np.delete(arr, i, axis=0), j, axis=1)

        def _coeff_det(coeff, j):
            return Product((coeff if j % 2 == 0 else -coeff,
                            Call(self, (_minor(array, 0, j), ))))

        coeffs = array[0]
        return Sum(tuple(_coeff_det(c, j) for j, c in enumerate(coeffs)))
Exemplo n.º 5
0
        def get_neg_product(expr):
            from pymbolic.primitives import is_zero, Product

            if isinstance(expr, Product) \
                    and len(expr.children) and is_zero(expr.children[0]+1):
                if len(expr.children) == 2:
                    # only the minus sign and the other child
                    return expr.children[1]
                else:
                    return Product(expr.children[1:])
            else:
                return None
Exemplo n.º 6
0
def test_pymbolic_sexprs():
    def check_round_trip(expr):
        assert sexpr_to_pymbolic(pymbolic_to_sexpr(expr)) == expr

    from pymbolic.primitives import Variable, Sum, Product, Power
    check_round_trip(Variable("x"))
    check_round_trip(1)
    check_round_trip(-11)
    check_round_trip(1.1)
    check_round_trip(1.1e-2)
    check_round_trip(Sum((7, )))
    check_round_trip(Sum((1, 2, 3)))
    check_round_trip(
        Sum((1, Product((2, 3, Power(1, Sum((Product((-1, 2)), 2))))), 3)))
    check_round_trip(Product((1, 2, 3)))
    check_round_trip(Power(1, Variable("x")))
    check_round_trip(Power(Power(1, 2), 3))
    check_round_trip(Power(1, Power(2, 3)))
    check_round_trip(Power(Power(Sum((1, 2)), 3), 3.5))

    from pymbolic import parse
    check_round_trip(
        parse("c_m2l * (40 * ((p_fmm + 1)**2)"
              "** 1.5 * (p_qbx + 1) ** 0.5 + 1)"))

    def check_error(expr):
        with pytest.raises(ParserError):
            sexpr_to_pymbolic(expr)

    check_error("")
    check_error("(")
    check_error(")")
    check_error("()")
    check_error("1 2 3")
    check_error("(Var ''')")
    check_error("(Power (Var 'x'")
    check_error("(Product 1 2) (Sum 1 2)")
    check_error("(Sum (Sum 1 2) 3")
    check_error("(Error)")
    check_error("Sum")
Exemplo n.º 7
0
        def mat_mul(op1, op2):
            if not isinstance(op1, np.ndarray) or not isinstance(
                    op2, np.ndarray):
                return op1 * op2

            if op1.shape[1] != op2.shape[0]:
                # mat1 cols must equal mat2 rows
                raise ValueError('mismatched dimensions %s and %s' %
                                 (str(op1.shape), str(op2.shape)))

            return np.array(
                [[Product((el1, el2)) for el1, el2 in zip(row1, row2)]
                 for row1, row2 in zip(op1.transpose(), op2)])
Exemplo n.º 8
0
 def _coeff_det(coeff, j):
     return Product((coeff if j % 2 == 0 else -coeff,
                     Call(self, (_minor(array, 0, j), ))))