예제 #1
0
def test_1_3_expression_parser_math_ops():
    """Testing handling of mathematical operations by expression parsers:

    See Also
    --------
    :class:`ExpressionParser`: Detailed documentation of expression parser attributes and methods.
    :class:`LambdaExpressionParser`: Documentation of a non-symbolic expression parser.
    """

    # define test cases
    math_expressions = [("4 + 5", 9.),                # simple addition
                        ("4 - 5", -1.),               # simple subtraction
                        ("4. * 5.", 20.),             # simple multiplication
                        ("4. / 5.", 0.8),             # simple division
                        ("4.^2.", 16.),               # simple exponentiation
                        ("4. + -5.", -1.),            # negation of variable
                        ("4. * -2.", -8.),            # negation of variable in higher-order operation
                        ("4. + 5. * 2.", 14.),        # multiplication before addition
                        ("(4. + 5.) * 2.", 18.),      # parentheses before everything
                        ("4. * 5.^2.", 100.)          # exponentiation before multiplication
                        ]

    # test expression parser on expression results using tensorflow backend
    #######################################################################

    # define backend
    b = TensorflowBackend()

    # evaluate expressions
    for expr, target in math_expressions:

        # tensorflow-based parser
        p = ExpressionParser(expr_str=expr, args={}, backend=b)
        p.parse_expr()
        result = p.rhs_eval.numpy() if hasattr(p.rhs_eval, 'numpy') else p.rhs_eval
        if hasattr(result, 'eval'):
            result = result.eval()
        assert result == pytest.approx(target, rel=1e-6)

    # test expression parser on expression results using numpy backend
    ##################################################################

    # define backend
    b = NumpyBackend()

    # evaluate expressions
    for expr, target in math_expressions:
        # tensorflow-based parser
        p = ExpressionParser(expr_str=expr, args={}, backend=b)
        p.parse_expr()
        result = p.rhs_eval.numpy() if hasattr(p.rhs_eval, 'numpy') else p.rhs_eval
        if hasattr(result, 'eval'):
            result = result.eval()
        assert result == pytest.approx(target, rel=1e-6)
예제 #2
0
def test_1_6_expression_parser_funcs():
    """Testing handling of function calls by expression parsers:

    See Also
    --------
    :class:`ExpressionParser`: Detailed documentation of expression parser attributes and methods.
    :class:`LambdaExpressionParser`: Documentation of a non-symbolic expression parser.
    """

    # define variables
    A = np.array(np.random.randn(10, 10), dtype=np.float32)

    # define valid test cases
    expressions = [("abs(5.)", 5.),  # simple function call
                   ("abs(-5.)", 5.),  # function call of negative arg
                   ("abs(4. * -2. + 1)", 7.),  # function call on mathematical expression
                   ("int64(4 > 5)", 0),  # function call on boolean expression
                   ("abs(A[2, :])",
                    np.abs(A[2, :])),  # function call on indexed variable
                   ("abs(sin(1.5))",
                    np.abs(np.sin(1.5))),  # nested function calls
                   ]

    # define invalid test cases
    expressions_wrong = ["abs((4.)",       # wrong parentheses I
                         "abs[4.]",        # wrong parentheses II
                         "abs(0. True)",   # no comma separation on arguments
                         "abs(0.,1,5,3)",  # wrong argument number
                         ]

    # test function calling on tensorflow-based parser
    ##################################################

    # define backend
    b = TensorflowBackend()
    args = parse_dict({'A': {'vtype': 'constant', 'value': A, 'shape': A.shape, 'dtype': A.dtype}}, backend=b)

    # start testing: valid cases
    for expr, target in expressions:
        # tensorflow-based parser
        p = ExpressionParser(expr_str=expr, args=args, backend=b)
        p.parse_expr()
        result = p.rhs_eval.numpy() if hasattr(p.rhs_eval, 'numpy') else p.rhs_eval
        if hasattr(result, 'eval'):
            result = result.eval()
        assert result == pytest.approx(target, rel=1e-6)

    # invalid cases
    for expr in expressions_wrong:

        # tensorflow-based parser
        with pytest.raises((IndexError, ValueError, SyntaxError, TypeError, BaseException)):
            p = ExpressionParser(expr_str=expr, args=args, backend=b)
            p.parse_expr()

    # test function calling on numpy-based parser
    #############################################

    # define backend
    b = NumpyBackend()

    # define variables
    args = parse_dict({'A': {'vtype': 'constant', 'value': A, 'shape': A.shape, 'dtype': A.dtype}}, backend=b)

    # start testing: valid cases
    for expr, target in expressions:
        # tensorflow-based parser
        p = ExpressionParser(expr_str=expr, args=args, backend=b)
        p.parse_expr()
        result = p.rhs_eval.numpy() if hasattr(p.rhs_eval, 'numpy') else p.rhs_eval
        if hasattr(result, 'eval'):
            result = result.eval()
        assert result == pytest.approx(target, rel=1e-6)

    # invalid cases
    for expr in expressions_wrong[:-1]:
        # tensorflow-based parser
        with pytest.raises((IndexError, ValueError, SyntaxError, TypeError, BaseException)):
            p = ExpressionParser(expr_str=expr, args=args, backend=b)
            p.parse_expr()
예제 #3
0
def test_1_5_expression_parser_indexing():
    """Testing handling of indexing operations by expression parsers:

    See Also
    --------
    :class:`ExpressionParser`: Detailed documentation of expression parser attributes and methods.
    :class:`LambdaExpressionParser`: Documentation of a non-symbolic expression parser.
    """

    # test indexing ability of tensorflow-based parser
    ##################################################

    # define backend
    b = TensorflowBackend()

    # define variables
    A = np.array(np.random.randn(10, 10), dtype=np.float32)
    B = np.eye(10, dtype=np.float32) == 1
    arg_dict = {'A': {'vtype': 'constant', 'value': A, 'shape': A.shape, 'dtype': A.dtype},
                'B': {'vtype': 'constant', 'value': B, 'shape': B.shape, 'dtype': B.dtype},
                'd': {'vtype': 'constant', 'value': 4, 'Shape': (), 'dtype': 'int32'}}
    args = parse_dict(arg_dict, backend=b)

    # define valid test cases
    indexed_expressions = [("A[:]", A[:]),               # single-dim indexing I
                           ("A[0]", A[0]),               # single-dim indexing II
                           ("A[-2]", A[-2]),             # single-dim indexing III
                           ("A[0:5]", A[0:5]),           # single-dim slicing I
                           ("A[-1:0:-1]", A[-1:0:-1]),   # single-dim slicing II
                           ("A[4,5]", A[4, 5]),          # two-dim indexing I
                           ("A[5,0:-2]", A[5, 0:-2]),    # two-dim indexing II
                           ("A[A > 0.]", A[A > 0.]),     # boolean indexing
                           ("A[B]", A[B]),               # indexing with other array
                           ("A[d:8 - 1]",                # using variables as indices
                            A[4:8 - 1]),
                           ]

    # test expression parsers on expression results
    for expr, target in indexed_expressions:

        # tensorflow-based parser
        p = ExpressionParser(expr_str=expr, args=args, backend=b)
        p.parse_expr()
        result = p.rhs_eval.numpy() if hasattr(p.rhs_eval, 'numpy') else p.rhs_eval
        if hasattr(result, 'eval'):
            result = result.eval()
        assert result == pytest.approx(target, rel=1e-6)

    # define invalid test cases
    indexed_expressions_wrong = ["A[1.2]",       # indexing with float variables
                                 "A[all]",       # indexing with undefined key words
                                 "A[-11]",       # index out of bounds
                                 "A[0:5:2:1]",   # too many arguments for slicing
                                 "A[-1::0:-1]",  # wrong slicing syntax II
                                 ]

    # test expression parsers on expression results
    for expr in indexed_expressions_wrong:

        # tensorflow-based parser
        with pytest.raises((IndexError, ValueError, SyntaxError, TypeError, BaseException)):
            p = ExpressionParser(expr_str=expr, args=args, backend=b)
            p.parse_expr()

    # test indexing ability of numpy-based parser
    #############################################

    # define backend
    b = NumpyBackend()
    args = parse_dict(arg_dict, backend=b)

    # test expression parsers on expression results
    for expr, target in indexed_expressions:
        p = ExpressionParser(expr_str=expr, args=args, backend=b)
        p.parse_expr()
        result = p.rhs_eval.numpy() if hasattr(p.rhs_eval, 'numpy') else p.rhs_eval
        if hasattr(result, 'eval'):
            result = result.eval()
        assert result == pytest.approx(target, rel=1e-6)

    # test expression parsers on expression results
    for expr in indexed_expressions_wrong:
        with pytest.raises((IndexError, ValueError, SyntaxError, TypeError, BaseException)):
            p = ExpressionParser(expr_str=expr, args=args, backend=b)
            p.parse_expr()
            p.op.eval()
예제 #4
0
def test_1_4_expression_parser_logic_ops():
    """Testing handling of logical operations by expression parsers:

    See Also
    --------
    :class:`ExpressionParser`: Detailed documentation of expression parser attributes and methods.
    :class:`LambdaExpressionParser`: Documentation of a non-symbolic expression parser.
    """

    # define test cases
    logic_expressions = ["4 == 4",                # simple equals
                         "4 != 5",                # simple not-equals
                         "4 < 5",                 # simple less
                         "5 > 4",                 # simple larger
                         "4 <= 4",                # less equals I
                         "4 <= 5",                # less equals II
                         "5 >= 5",                # larger equals I
                         "5 >= 4",                # larger equals II
                         ]

    # test expression parsers on expression results with tensforflow backend
    ########################################################################

    # define backend
    b = TensorflowBackend()

    # correct expressions
    for expr in logic_expressions:
        p = ExpressionParser(expr_str=expr, args={}, backend=b)
        p.parse_expr()
        result = p.op.numpy() if hasattr(p.op, 'numpy') else p.op
        assert result

    # false logical expression
    expr = "5 >= 6"

    # tensorflow-based parser
    p = ExpressionParser(expr_str=expr, args={}, backend=b)
    p.parse_expr()
    result = p.rhs_eval.numpy() if hasattr(p.rhs_eval, 'numpy') else p.rhs_eval
    if hasattr(result, 'eval'):
        result = result.eval()
    assert not result

    # test expression parsers on expression results with numpy backend
    ##################################################################

    # define backend
    b = NumpyBackend()

    # correct expressions
    for expr in logic_expressions:

        # numpy-based parser
        p = ExpressionParser(expr_str=expr, args={}, backend=b)
        p.parse_expr()
        result = p.rhs_eval.numpy() if hasattr(p.rhs_eval, 'numpy') else p.rhs_eval
        if hasattr(result, 'eval'):
            result = result.eval()
        assert result

    # false logical expression
    expr = "5 >= 6"

    # tensorflow-based parser
    p = ExpressionParser(expr_str=expr, args={}, backend=b)
    p.parse_expr()
    result = p.rhs_eval.numpy() if hasattr(p.rhs_eval, 'numpy') else p.rhs_eval
    if hasattr(result, 'eval'):
        result = result.eval()
    assert not result