コード例 #1
0
def test_assoccomm():
    from symbolic_pymc.relations import buildo

    x, a, b, c = tt.dvectors('xabc')
    test_expr = x + 1
    q = var('q')

    res = run(1, q, buildo(tt.add, test_expr.owner.inputs, test_expr))
    assert q == res[0]

    res = run(1, q, buildo(q, test_expr.owner.inputs, test_expr))
    assert tt.add == res[0].reify()

    res = run(1, q, buildo(tt.add, q, test_expr))
    assert mt(tuple(test_expr.owner.inputs)) == res[0]

    res = run(0, var('x'), eq_comm(mt.mul(a, b), mt.mul(b, var('x'))))
    assert (mt(a), ) == res

    res = run(0, var('x'), eq_comm(mt.add(a, b), mt.add(b, var('x'))))
    assert (mt(a), ) == res

    res = run(0, var('x'), (eq_assoc, mt.add(a, b, c), mt.add(a, var('x'))))

    # TODO: `res[0]` should return `etuple`s.  Since `eq_assoc` effectively
    # picks apart the results of `arguments(...)`, I don't know if we can
    # keep the `etuple`s around.  We might be able to convert the results
    # to `etuple`s automatically by wrapping `eq_assoc`, though.
    res_obj = etuple(*res[0]).eval_obj
    assert res_obj == mt(b + c)

    res = run(0, var('x'), (eq_assoc, mt.mul(a, b, c), mt.mul(a, var('x'))))
    res_obj = etuple(*res[0]).eval_obj
    assert res_obj == mt(b * c)
コード例 #2
0
def test_seq_apply_anyo_misc():
    q_lv = var('q')

    assert len(run(0, q_lv, seq_apply_anyo(eq, [1, 2, 3], [1, 2, 3]))) == 1

    assert len(run(0, q_lv, seq_apply_anyo(eq, [1, 2, 3], [1, 3, 3]))) == 0

    def one_to_threeo(x, y):
        return conde([eq(x, 1), eq(y, 3)])

    res = run(0, q_lv,
              seq_apply_anyo(one_to_threeo, [1, 2, 4, 1, 4, 1, 1], q_lv))

    assert res[0] == [3, 2, 4, 3, 4, 3, 3]

    assert len(
        run(4, q_lv,
            seq_apply_anyo(math_reduceo, [etuple(mul, 2, var('x'))],
                           q_lv))) == 0

    test_res = run(4, q_lv,
                   seq_apply_anyo(math_reduceo, [etuple(add, 2, 2), 1], q_lv))
    assert test_res == ([etuple(mul, 2, 2), 1], )

    test_res = run(4, q_lv,
                   seq_apply_anyo(math_reduceo, [1, etuple(add, 2, 2)], q_lv))
    assert test_res == ([1, etuple(mul, 2, 2)], )

    test_res = run(4, q_lv, seq_apply_anyo(math_reduceo, q_lv, var('z')))
    assert all(isinstance(r, list) for r in test_res)

    test_res = run(4, q_lv,
                   seq_apply_anyo(math_reduceo, q_lv, var('z'), tuple()))
    assert all(isinstance(r, tuple) for r in test_res)
コード例 #3
0
def test_pprint():
    pretty_mod = pytest.importorskip("IPython.lib.pretty")
    et = etuple(1,
                etuple("a", *range(20)),
                etuple(3, "b"),
                blah=etuple('c', 0))
    assert pretty_mod.pretty(
        et
    ) == "e(\n  1,\n  e('a', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19),\n  e(3, 'b'),\n  blah=e(c, 0))"
コード例 #4
0
 def distributes(in_lv, out_lv):
     return (
         lallgreedy,
         # lhs == A * (x + b)
         (eq, etuple(mt.dot, var('A'), etuple(mt.add, var('x'),
                                              var('b'))), etuplize(in_lv)),
         # rhs == A * x + A * b
         (eq,
          etuple(mt.add, etuple(mt.dot, var('A'), var('x')),
                 etuple(mt.dot, var('A'), var('b'))), out_lv))
コード例 #5
0
def test_str():
    et = etuple(1, etuple("a", 2), etuple(3, "b"))
    assert repr(
        et
    ) == "ExpressionTuple((1, ExpressionTuple(('a', 2)), ExpressionTuple((3, 'b'))))"
    assert str(et) == 'e(1, e(a, 2), e(3, b))'

    kw = KwdPair('a', 1)

    assert repr(kw) == "KwdPair('a', 1)"
    assert str(kw) == 'a=1'
コード例 #6
0
def test_graph_applyo_misc():
    q_lv = var('q')
    expr = etuple(add, etuple(mul, 2, 1), etuple(add, 1, 1))
    assert len(
        run(0, q_lv, graph_applyo(eq, expr, expr, preprocess_graph=None))) == 1

    expr2 = etuple(add, etuple(mul, 2, 1), etuple(add, 2, 1))
    assert len(
        run(0, q_lv, graph_applyo(eq, expr, expr2,
                                  preprocess_graph=None))) == 0

    assert len(
        run(0, q_lv, graph_applyo(eq,
                                  etuple(),
                                  etuple(),
                                  preprocess_graph=None))) == 1

    def one_to_threeo(x, y):
        return conde([eq(x, 1), eq(y, 3)])

    res = run(
        0, q_lv,
        graph_applyo(one_to_threeo, [1, [1, 2, 4], 2, [[4, 1, 1]], 1],
                     q_lv,
                     preprocess_graph=None))

    assert res[0] == [3, [3, 2, 4], 2, [[4, 3, 3]], 3]
コード例 #7
0
def test_etuple():
    """Test basic `etuple` functionality."""
    def test_op(*args):
        return tuple(object() for i in range(sum(args)))

    e1 = etuple(test_op, 1, 2)

    assert e1._eval_obj is ExpressionTuple.null

    with pytest.raises(ValueError):
        e1.eval_obj = 1

    e1_obj = e1.eval_obj
    assert len(e1_obj) == 3
    assert all(type(o) == object for o in e1_obj)

    # Make sure we don't re-create the cached `eval_obj`
    e1_obj_2 = e1.eval_obj
    assert e1_obj == e1_obj_2

    # Confirm that evaluation is recursive
    e2 = etuple(add, (object(), ), e1)

    # Make sure we didn't convert this single tuple value to
    # an `etuple`
    assert type(e2[1]) == tuple

    # Slices should be `etuple`s, though.
    assert isinstance(e2[:1], ExpressionTuple)
    assert e2[1] == e2[1:2][0]

    e2_obj = e2.eval_obj

    assert type(e2_obj) == tuple
    assert len(e2_obj) == 4
    assert all(type(o) == object for o in e2_obj)
    # Make sure that it used `e1`'s original `eval_obj`
    assert e2_obj[1:] == e1_obj

    # Confirm that any combination of `tuple`s/`etuple`s in
    # concatenation result in an `etuple`
    e_radd = (1, ) + etuple(2, 3)
    assert isinstance(e_radd, ExpressionTuple)
    assert e_radd == (1, 2, 3)

    e_ladd = etuple(1, 2) + (3, )
    assert isinstance(e_ladd, ExpressionTuple)
    assert e_ladd == (1, 2, 3)
コード例 #8
0
def math_reduceo(in_expr, out_expr):
    """Create a relation for a couple math-based identities."""
    x_lv = var()
    x_lv.token = f'x{x_lv.token}'

    return (lall,
            conde([
                eq(in_expr, etuple(add, x_lv, x_lv)),
                eq(out_expr, etuple(mul, 2, x_lv))
            ], [
                eq(in_expr, etuple(log, etuple(exp, x_lv))),
                eq(out_expr, x_lv)
            ]),
            conde([(isinstanceo, [in_expr,
                                  (float, int, ExpressionTuple)], True)],
                  [(isinstanceo, [out_expr,
                                  (float, int, ExpressionTuple)], True)]))
コード例 #9
0
def test_etuple():
    et = etuple(var('a'), )
    res = reify(et, {var('a'): 1})
    assert isinstance(res, ExpressionTuple)

    et = etuple(var('a'), )
    res = unify(et, (1, ))
    assert res == {var('a'): 1}

    from operator import add

    et = etuple(add, 1, 2)
    assert et.eval_obj == 3

    res = unify(et, cons(var('a'), var('b')))
    assert res == {var('a'): add, var('b'): et[1:]}

    assert ((res[var('a')], ) + res[var('b')])._eval_obj == 3
コード例 #10
0
def test_seq_apply_anyo_types():
    """Make sure that `applyo` preserves the types between its arguments."""
    q_lv = var()
    res = run(1, q_lv, seq_apply_anyo(lambda x, y: eq(x, y), [1], q_lv))
    assert res[0] == [1]
    res = run(1, q_lv, seq_apply_anyo(lambda x, y: eq(x, y), (1, ), q_lv))
    assert res[0] == (1, )
    res = run(
        1, q_lv,
        seq_apply_anyo(lambda x, y: eq(x, y), etuple(1, ), q_lv,
                       skip_op=False))
    assert res[0] == etuple(1, )
    res = run(1, q_lv, seq_apply_anyo(lambda x, y: eq(x, y), q_lv, (1, )))
    assert res[0] == (1, )
    res = run(1, q_lv, seq_apply_anyo(lambda x, y: eq(x, y), q_lv, [1]))
    assert res[0] == [1]
    res = run(
        1, q_lv,
        seq_apply_anyo(lambda x, y: eq(x, y), q_lv, etuple(1), skip_op=False))
    assert res[0] == etuple(1)
    res = run(1, q_lv, seq_apply_anyo(lambda x, y: eq(x, y), [1, 2], [1, 2]))
    assert len(res) == 1
    res = run(1, q_lv, seq_apply_anyo(lambda x, y: eq(x, y), [1, 2], [1, 3]))
    assert len(res) == 0
    res = run(1, q_lv, seq_apply_anyo(lambda x, y: eq(x, y), [1, 2], (1, 2)))
    assert len(res) == 0
    res = run(
        0, q_lv,
        seq_apply_anyo(lambda x, y: eq(y, etuple(mul, 2, x)),
                       etuple(add, 1, 2),
                       q_lv,
                       skip_op=True))
    assert len(res) == 3
    assert all(r[0] == add for r in res)
コード例 #11
0
def test_sexp_unify_reify():
    """Make sure we can unify and reify etuples/S-exps."""
    # Unify `A . (x + y)`, for `x`, `y` logic variables
    A = tf.compat.v1.placeholder(tf.float64, name='A',
                                 shape=tf.TensorShape([None, None]))
    x = tf.compat.v1.placeholder(tf.float64, name='x',
                                 shape=tf.TensorShape([None, 1]))
    y = tf.compat.v1.placeholder(tf.float64, name='y',
                                 shape=tf.TensorShape([None, 1]))

    z = tf.matmul(A, tf.add(x, y))

    z_sexp = etuplize(z, shallow=False)

    # Let's just be sure that the original TF objects are preserved
    assert z_sexp[1].eval_obj.reify() == A
    assert z_sexp[2][1].eval_obj.reify() == x
    assert z_sexp[2][2].eval_obj.reify() == y

    dis_pat = etuple(etuple(TFlowMetaOperator, mt.matmul.op_def, var()),
                     var('A'),
                     etuple(etuple(TFlowMetaOperator, mt.add.op_def, var()),
                            var('x'), var('y')))

    s = unify(dis_pat, z_sexp, {})

    assert s[var('A')].eval_obj == mt(A)
    assert s[var('x')].eval_obj == mt(x)
    assert s[var('y')].eval_obj == mt(y)

    # Now, we construct a graph that reflects the distributive property and
    # reify with the substitutions from the un-distributed form
    out_pat = etuple(mt.add,
                     etuple(mt.matmul, var('A'), var('x')),
                     etuple(mt.matmul, var('A'), var('y')))
    z_dist = reify(out_pat, s)

    # Evaluate the tuple-expression and get a meta object/graph
    z_dist_mt = z_dist.eval_obj

    # If all the logic variables were reified, we should be able to
    # further reify the meta graph and get a concrete TF graph
    z_dist_tf = z_dist_mt.reify()

    assert isinstance(z_dist_tf, tf.Tensor)

    # Check the first part of `A . x + A . y` (i.e. `A . x`)
    assert z_dist_tf.op.inputs[0].op.inputs[0] == A
    assert z_dist_tf.op.inputs[0].op.inputs[1] == x
    # Now, the second, `A . y`
    assert z_dist_tf.op.inputs[1].op.inputs[0] == A
    assert z_dist_tf.op.inputs[1].op.inputs[1] == y
コード例 #12
0
def test_seq_apply_anyo_reverse():
    """Test `seq_apply_anyo` in "reverse" (i.e. specify the reduced form and generate the un-reduced form)."""
    # Unbounded reverse
    q_lv = var()
    rev_input = [etuple(mul, 2, 1)]
    test_res = run(4, q_lv, (seq_apply_anyo, math_reduceo, q_lv, rev_input))
    assert test_res == ([etuple(add, 1, 1)],
                        [etuple(log, etuple(exp, etuple(mul, 2, 1)))])

    # Guided reverse
    test_res = run(4, q_lv,
                   (seq_apply_anyo, math_reduceo, [etuple(add, q_lv, 1)
                                                   ], [etuple(mul, 2, 1)]))

    assert test_res == (1, )
コード例 #13
0
def test_etuple_term():
    """Test `etuplize` and `etuple` interaction with `term`
    """
    # Make sure that we don't lose underlying `eval_obj`s
    # when taking apart and re-creating expression tuples
    # using `kanren`'s `operator`, `arguments` and `term`
    # functions.
    e1 = etuple(add, (object(), ), (object(), ))
    e1_obj = e1.eval_obj

    e1_dup = (operator(e1), ) + arguments(e1)

    assert isinstance(e1_dup, ExpressionTuple)
    assert e1_dup.eval_obj == e1_obj

    e1_dup_2 = term(operator(e1), arguments(e1))
    assert e1_dup_2 == e1_obj
コード例 #14
0
def test_etuple_term():
    """Test `etuplize` and `etuple` interaction with `term`
    """
    # Take apart an already constructed/evaluated meta
    # object.
    e2 = mt.add(mt.vector(), mt.vector())

    e2_et = etuplize(e2)

    assert isinstance(e2_et, ExpressionTuple)

    # e2_et_expect = etuple(
    #     mt.add,
    #     etuple(mt.TensorVariable,
    #            etuple(mt.TensorType,
    #                   'float64', (False,), None),
    #            None, None, None),
    #     etuple(mt.TensorVariable,
    #            etuple(mt.TensorType,
    #                   'float64', (False,), None),
    #            None, None, None),
    # )
    e2_et_expect = etuple(mt.add, e2.base_arguments[0], e2.base_arguments[1])
    assert e2_et == e2_et_expect
    assert e2_et.eval_obj is e2

    # Make sure expression expansion works from Theano objects, too.
    # First, do it manually.
    tt_expr = tt.vector() + tt.vector()

    mt_expr = mt(tt_expr)
    assert mt_expr.obj is tt_expr
    assert mt_expr.reify() is tt_expr
    e3 = etuplize(mt_expr)
    assert e3 == e2_et
    assert e3.eval_obj is mt_expr
    assert e3.eval_obj.reify() is tt_expr

    # Now, through `etuplize`
    e2_et_2 = etuplize(tt_expr)
    assert e2_et_2 == e3 == e2_et
    assert isinstance(e2_et_2, ExpressionTuple)
    assert e2_et_2.eval_obj == tt_expr
コード例 #15
0
def test_graph_applyo_reverse():
    """Test `graph_applyo` in "reverse" (i.e. specify the reduced form and generate the un-reduced form)."""
    q_lv = var('q')

    test_res = run(2, q_lv, fixedp_graph_applyo(math_reduceo, q_lv, 5))
    assert test_res == (etuple(log, etuple(exp, 5)),
                        etuple(log, etuple(exp, etuple(log, etuple(exp, 5)))))
    assert all(e.eval_obj == 5.0 for e in test_res)

    # Make sure we get some variety in the results
    test_res = run(2, q_lv,
                   fixedp_graph_applyo(math_reduceo, q_lv, etuple(mul, 2, 5)))
    assert test_res == (
        # Expansion of the term's root
        etuple(add, 5, 5),
        # Two step expansion at the root
        etuple(log, etuple(exp, etuple(add, 5, 5))),
        # Expansion into a sub-term
        # etuple(mul, 2, etuple(log, etuple(exp, 5)))
    )
    assert all(e.eval_obj == 10.0 for e in test_res)

    r_lv = var('r')
    test_res = run(4, [q_lv, r_lv],
                   fixedp_graph_applyo(math_reduceo, q_lv, r_lv))
    expect_res = ([etuple(add, 1, 1), etuple(mul, 2, 1)], [
        etuple(log, etuple(exp, etuple(add, 1, 1))),
        etuple(mul, 2, 1)
    ], [etuple(), etuple()], [
        etuple(add, etuple(mul, 2, 1), etuple(add, 1, 1)),
        etuple(mul, 2, etuple(mul, 2, 1))
    ])
    assert list(
        unify(a1, a2) and unify(b1, b2)
        for [a1, b1], [a2, b2] in zip(test_res, expect_res))
コード例 #16
0
    test_res = run(4, q_lv,
                   seq_apply_anyo(math_reduceo, [1, etuple(add, 2, 2)], q_lv))
    assert test_res == ([1, etuple(mul, 2, 2)], )

    test_res = run(4, q_lv, seq_apply_anyo(math_reduceo, q_lv, var('z')))
    assert all(isinstance(r, list) for r in test_res)

    test_res = run(4, q_lv,
                   seq_apply_anyo(math_reduceo, q_lv, var('z'), tuple()))
    assert all(isinstance(r, tuple) for r in test_res)


@pytest.mark.parametrize(
    'test_input, test_output',
    [([], ()), ([1], ()), ([
        etuple(add, 1, 1),
    ], ([etuple(mul, 2, 1)], )),
     ([1, etuple(add, 1, 1)], ([1, etuple(mul, 2, 1)], )),
     ([etuple(add, 1, 1), 1], ([etuple(mul, 2, 1), 1], )),
     ([etuple(mul, 2, 1), etuple(add, 1, 1), 1],
      ([etuple(mul, 2, 1), etuple(mul, 2, 1), 1], )),
     ([
         etuple(add, 1, 1),
         etuple(log, etuple(exp, 5)),
     ], ([etuple(mul, 2, 1), 5], [etuple(add, 1, 1), 5],
         [etuple(mul, 2, 1), etuple(log, etuple(exp, 5))]))])
def test_seq_apply_anyo(test_input, test_output):
    """Test `seq_apply_anyo` with fully ground terms (i.e. no logic variables)."""
    q_lv = var()
    test_res = run(0, q_lv,
                   (seq_apply_anyo, full_math_reduceo, test_input, q_lv))
コード例 #17
0
def test_etuple_kwargs():
    """Test keyword arguments and default argument values."""
    def test_func(a, b, c=None, d='d-arg', **kwargs):
        assert isinstance(c, (type(None), int))
        return [a, b, c, d]

    e1 = etuple(test_func, 1, 2)
    assert e1.eval_obj == [1, 2, None, 'd-arg']

    # Make sure we handle variadic args properly
    def test_func2(*args, c=None, d='d-arg', **kwargs):
        assert isinstance(c, (type(None), int))
        return list(args) + [c, d]

    e11 = etuple(test_func2, 1, 2)
    assert e11.eval_obj == [1, 2, None, 'd-arg']

    e2 = etuple(test_func, 1, 2, 3)
    assert e2.eval_obj == [1, 2, 3, 'd-arg']

    e3 = etuple(test_func, 1, 2, 3, 4)
    assert e3.eval_obj == [1, 2, 3, 4]

    e4 = etuple(test_func, 1, 2, c=3)
    assert e4.eval_obj == [1, 2, 3, 'd-arg']

    e5 = etuple(test_func, 1, 2, d=3)
    assert e5.eval_obj == [1, 2, None, 3]

    e6 = etuple(test_func, 1, 2, 3, d=4)
    assert e6.eval_obj == [1, 2, 3, 4]

    # Try evaluating nested etuples
    e7 = etuple(test_func,
                etuple(add, 1, 0),
                2,
                c=etuple(add, 1, etuple(add, 1, 1)))
    assert e7.eval_obj == [1, 2, 3, 'd-arg']

    # Try a function without an obtainable signature object
    e8 = etuple(enumerate,
                etuple(list, ['a', 'b', 'c', 'd']),
                start=etuple(add, 1, etuple(add, 1, 1)))
    assert list(e8.eval_obj) == [(3, 'a'), (4, 'b'), (5, 'c'), (6, 'd')]

    # Use "eval_obj" kwarg and make sure it doesn't end up in the `_tuple` object
    e9 = etuple(add, 1, 2, eval_obj=3)
    assert e9._tuple == (add, 1, 2)
    assert e9._eval_obj == 3
コード例 #18
0
def test_reduceo():
    q_lv = var()

    # Reduce/forward
    res = run(
        0, q_lv,
        full_math_reduceo(etuple(log, etuple(exp, etuple(log, 1))), q_lv))
    assert len(res) == 1
    assert res[0] == etuple(log, 1)

    res = run(
        0, q_lv,
        full_math_reduceo(
            etuple(log, etuple(exp, etuple(log, etuple(exp, 1)))), q_lv))
    assert res[0] == 1
    assert res[1] == etuple(log, etuple(exp, 1))

    # Expand/backward
    res = run(2, q_lv, full_math_reduceo(q_lv, 1))
    assert res[0] == etuple(log, etuple(exp, 1))
    assert res[1] == etuple(log, etuple(exp, etuple(log, etuple(exp, 1))))