Beispiel #1
0
def test_objects_full():
    _unify.add((Foo, Foo, dict), unify_object)
    _unify.add((Bar, Bar, dict), unify_object)
    _reify.add((Foo, dict), reify_object)
    _reify.add((Bar, dict), reify_object)

    assert unify_object(Foo(1, Bar(2)), Foo(1, Bar(var(3))), {}) == {var(3): 2}
    assert reify(Foo(var('a'), Bar(Foo(var('b'), 3))),
                 {var('a'): 1, var('b'): 2}) == Foo(1, Bar(Foo(2, 3)))
Beispiel #2
0
def test_objects_full():
    _unify.add((Foo, Foo, dict), unify_object)
    _unify.add((Bar, Bar, dict), unify_object)
    _reify.add((Foo, dict), reify_object)
    _reify.add((Bar, dict), reify_object)

    assert unify_object(Foo(1, Bar(2)), Foo(1, Bar(var(3))), {}) == {var(3): 2}
    assert reify(Foo(var('a'), Bar(Foo(var('b'), 3))),
                 {var('a'): 1, var('b'): 2}) == Foo(1, Bar(Foo(2, 3)))
Beispiel #3
0
def test_unify_isinstance_list():
    class Foo2(Foo): pass
    x = var('x')
    y = var('y')
    f, g = Foo2(1, 2), Foo2(x, y)

    _unify.add((Foo, Foo, dict), unify_object)
    _reify.add((Foo, dict), reify_object)

    assert unify(f, g, {})
    assert reify(g, {x: 1, y: 2}) == f
Beispiel #4
0
def test_objects_full():
    _unify.add((Foo, Foo, Mapping), _unify_object)
    _unify.add((Bar, Bar, Mapping), _unify_object)
    _reify.add((Foo, Mapping), _reify_object)
    _reify.add((Bar, Mapping), _reify_object)

    x, y = var(), var()
    assert unify(Foo(1, 2), Bar(1), {}) is False
    assert unify(Foo(1, Bar(2)), Foo(1, Bar(x)), {}) == {x: 2}
    assert reify(Foo(x, Bar(Foo(y, 3))), {
        x: 1,
        y: 2
    }) == Foo(1, Bar(Foo(2, 3)))

    class SubFoo(Foo):
        pass

    assert unify(Foo(1, 2), SubFoo(1, 2), {}) is False
Beispiel #5
0
    lcons_ = lcons
    rcons_ = rcons

    if isinstance(lcons, Iterator):
        lcons, lcons_ = tee(lcons)

    if isinstance(rcons, Iterator):
        rcons, rcons_ = tee(rcons)

    try:
        s = yield _unify(car(lcons), car(rcons), s)

        if s is not False:
            s = yield _unify(cdr(lcons_), cdr(rcons_), s)
    except ConsError:
        yield False
    else:
        yield s


_unify.add((ConsPair, (ConsPair, MaybeCons), Mapping), _unify_Cons)
_unify.add((MaybeCons, ConsPair, Mapping), _unify_Cons)


@_reify.register(ConsPair, Mapping)
def _reify_Cons(lcons, s):
    rcar = yield _reify(car(lcons), s)
    rcdr = yield _reify(cdr(lcons), s)
    yield construction_sentinel
    yield cons(rcar, rcdr)
Beispiel #6
0

# Unfortunately, `multipledispatch` doesn't use `isinstance` on the arguments,
# so it won't use our fancy setup for `isinstance(x, ConsPair)` and we have to
# specify--and check--each `cons`-amenable type explicitly.
def _cons_unify(lcons, rcons, s):

    if not is_cons(lcons) or not is_cons(rcons):
        # One of the arguments is necessarily a `ConsPair` object,
        # but the other could be an empty iterable, which isn't a
        # `cons`-derivable object.
        return False

    s = unify(car(lcons), car(rcons), s)
    if s is not False:
        return unify(cdr(lcons), cdr(rcons), s)
    return False


_unify.add((ConsPair, (ConsPair, list, tuple, Iterator, OrderedDict), dict),
           _cons_unify)
_unify.add(((list, tuple, Iterator, OrderedDict), ConsPair, dict),
           _cons_unify)


@_reify.register(ConsPair, dict)
def reify_cons(lcons, s):
    rcar = reify(car(lcons), s)
    rcdr = reify(cdr(lcons), s)
    return cons(rcar, rcdr)
Beispiel #7
0
try:  # noqa: C901
    import unification
    from packaging import version

    if version.parse(unification.__version__) < version.parse("0.4.0"):
        raise ModuleNotFoundError()

    from unification.core import _reify, _unify, construction_sentinel, isvar
except ModuleNotFoundError:
    pass
else:

    def _unify_ExpressionTuple(u, v, s):
        yield _unify(getattr(u, "_tuple", u), getattr(v, "_tuple", v), s)

    _unify.add((ExpressionTuple, ExpressionTuple, Mapping), _unify_ExpressionTuple)
    _unify.add((tuple, ExpressionTuple, Mapping), _unify_ExpressionTuple)
    _unify.add((ExpressionTuple, tuple, Mapping), _unify_ExpressionTuple)

    def _unify_KwdPair(u, v, s):
        s = yield _unify(u.arg, v.arg, s)
        if s is not False:
            s = yield _unify(u.value, v.value, s)
        yield s

    _unify.add((KwdPair, KwdPair, Mapping), _unify_KwdPair)

    def _reify_ExpressionTuple(u, s):
        # The point of all this: we don't want to lose the expression
        # tracking/caching information.
        res = yield _reify(u._tuple, s)
Beispiel #8
0
def unifiable_with_term(cls):
    _reify.add((cls, dict), reify_term)
    _unify.add((cls, cls, dict), unify_term)
    return cls
Beispiel #9
0
import theano.tensor as tt

from kanren.term import term, operator, arguments

from unification.core import _reify, _unify, reify

from ..meta import metatize
from ..unify import unify_MetaSymbol
from ..etuple import ExpressionTuple, etuplize
from .meta import TheanoMetaSymbol


tt_class_abstractions = tuple(c.base for c in TheanoMetaSymbol.base_subclasses())

_unify.add(
    (TheanoMetaSymbol, tt_class_abstractions, dict),
    lambda u, v, s: unify_MetaSymbol(u, metatize(v), s),
)
_unify.add(
    (tt_class_abstractions, TheanoMetaSymbol, dict),
    lambda u, v, s: unify_MetaSymbol(metatize(u), v, s),
)
_unify.add(
    (tt_class_abstractions, tt_class_abstractions, dict),
    lambda u, v, s: unify_MetaSymbol(metatize(u), metatize(v), s),
)


def _reify_TheanoClasses(o, s):
    meta_obj = metatize(o)
    return reify(meta_obj, s)
Beispiel #10
0
    elif u != v:
        return False
    if s:
        # If these two meta objects unified, and one has a logic
        # variable as its base object, consider the unknown base
        # object unified by the other's base object (if any).
        # This way, the original base objects can be recovered during
        # reification (preserving base object equality and such).
        if isinstance(u.obj, Var) and v.obj:
            s[u.obj] = v.obj
        elif isinstance(v.obj, Var) and u.obj:
            s[v.obj] = u.obj
    return s


_unify.add((MetaSymbol, MetaSymbol, dict), unify_MetaSymbol)
_unify.add((MetaSymbol, tt_class_abstractions, dict),
           lambda u, v, s: unify_MetaSymbol(u, MetaSymbol.from_obj(v), s))
_unify.add((tt_class_abstractions, MetaSymbol, dict),
           lambda u, v, s: unify_MetaSymbol(MetaSymbol.from_obj(u), v, s))
_unify.add((tt_class_abstractions, tt_class_abstractions, dict),
           lambda u, v, s: unify_MetaSymbol(MetaSymbol.from_obj(u),
                                            MetaSymbol.from_obj(v), s))


def _reify_MetaSymbol(o, s):
    if isinstance(o.obj, Var):
        obj = s.get(o.obj, o.obj)
    else:
        obj = None
Beispiel #11
0
    elif u != v:
        return False
    if s:
        # If these two meta objects unified, and one has a logic
        # variable as its base object, consider the unknown base
        # object unified by the other's base object (if any).
        # This way, the original base objects can be recovered during
        # reification (preserving base object equality and such).
        if isinstance(u.obj, Var) and v.obj:
            s[u.obj] = v.obj
        elif isinstance(v.obj, Var) and u.obj:
            s[v.obj] = u.obj
    return s


_unify.add((MetaSymbol, MetaSymbol, Mapping), unify_MetaSymbol)


def _reify_MetaSymbol(o, s):
    if isinstance(o.obj, Var):
        # We allow reification of the base object field for
        # a meta object.
        # TODO: This is a weird thing that we should probably reconsider.
        # It's part of the functionality that allows base objects to fill-in
        # as logic variables, though.
        obj = s.get(o.obj, o.obj)
    else:
        # Otherwise, if there's a base object, it should indicate that there
        # are no logic variables or meta terms.
        # TODO: Seems like we should be able to skip the reify and comparison
        # below.
Beispiel #12
0
def test_unify_nonstandard_object():
    _unify.add((ast.AST, ast.AST, Mapping), _unify_object)
    x = var()
    assert unify(ast.Num(n=1), ast.Num(n=1), {}) == {}
    assert unify(ast.Num(n=1), ast.Num(n=2), {}) is False
    assert unify(ast.Num(n=1), ast.Num(n=x), {}) == {x: 1}
Beispiel #13
0
        return res.outputs


apply.add((Op, ExpressionTuple), apply_Op_ExpressionTuple)


def _unify_etuplize_first_arg(u, v, s):
    try:
        u_et = etuplize(u, shallow=True)
        yield _unify(u_et, v, s)
    except TypeError:
        yield False
        return


_unify.add((Op, ExpressionTuple, Mapping), _unify_etuplize_first_arg)
_unify.add((ExpressionTuple, Op, Mapping),
           lambda u, v, s: _unify_etuplize_first_arg(v, u, s))

_unify.add((Type, ExpressionTuple, Mapping), _unify_etuplize_first_arg)
_unify.add((ExpressionTuple, Type, Mapping),
           lambda u, v, s: _unify_etuplize_first_arg(v, u, s))


def _unify_Variable_Variable(u, v, s):
    # Avoid converting to `etuple`s, when possible
    if u == v:
        yield s
        return

    if not u.owner and not v.owner:
Beispiel #14
0
from kanren.term import operator, arguments

from unification.core import _reify, _unify, reify

from cons.core import _car, _cdr

from etuples import etuplize

from .meta import TFlowMetaSymbol
from ..meta import metatize
from ..dispatch import unify_MetaSymbol

tf_class_abstractions = tuple(c.base for c in TFlowMetaSymbol.base_subclasses())

_unify.add(
    (TFlowMetaSymbol, tf_class_abstractions, Mapping),
    lambda u, v, s: unify_MetaSymbol(u, metatize(v), s),
)
_unify.add(
    (tf_class_abstractions, TFlowMetaSymbol, Mapping),
    lambda u, v, s: unify_MetaSymbol(metatize(u), v, s),
)
_unify.add(
    (tf_class_abstractions, tf_class_abstractions, Mapping),
    lambda u, v, s: unify_MetaSymbol(metatize(u), metatize(v), s),
)


def _reify_TFlowClasses(o, s):
    meta_obj = metatize(o)
    return reify(meta_obj, s)
Beispiel #15
0
    elif u != v:
        return False
    if s:
        # If these two meta objects unified, and one has a logic
        # variable as its base object, consider the unknown base
        # object unified by the other's base object (if any).
        # This way, the original base objects can be recovered during
        # reification (preserving base object equality and such).
        if isinstance(u.obj, Var) and v.obj:
            s[u.obj] = v.obj
        elif isinstance(v.obj, Var) and u.obj:
            s[v.obj] = u.obj
    return s


_unify.add((MetaSymbol, MetaSymbol, dict), unify_MetaSymbol)

_tuple__unify = _unify.dispatch(tuple, tuple, dict)

_unify.add((ExpressionTuple, (tuple, ExpressionTuple), dict),
           lambda x, y, s: _tuple__unify(x, y, s))
_unify.add((tuple, ExpressionTuple, dict),
           lambda x, y, s: _tuple__unify(x, y, s))


def _reify_MetaSymbol(o, s):
    if isinstance(o.obj, Var):
        # We allow reification of the base object field for
        # a meta object.
        # TODO: This is a weird thing that we should probably reconsider.
        # It's part of the functionality that allows base objects to fill-in
Beispiel #16
0
def unifiable_with_term(cls):
    _reify.add((cls, Mapping), reify_term)
    _unify.add((cls, cls, Mapping), unify_term)
    return cls
Beispiel #17
0
        return False


# Unfortunately, `multipledispatch` doesn't use `isinstance` on the arguments,
# so it won't use our fancy setup for `isinstance(x, ConsPair)` and we have to
# specify--and check--each `cons`-amenable type explicitly.
def _cons_unify(lcons, rcons, s):

    if not is_cons(lcons) or not is_cons(rcons):
        # One of the arguments is necessarily a `ConsPair` object,
        # but the other could be an empty iterable, which isn't a
        # `cons`-derivable object.
        return False

    s = unify(car(lcons), car(rcons), s)
    if s is not False:
        return unify(cdr(lcons), cdr(rcons), s)
    return False


_unify.add((ConsPair, (ConsPair, list, tuple, Iterator, OrderedDict), dict),
           _cons_unify)
_unify.add(((list, tuple, Iterator, OrderedDict), ConsPair, dict), _cons_unify)


@_reify.register(ConsPair, dict)
def reify_cons(lcons, s):
    rcar = reify(car(lcons), s)
    rcdr = reify(cdr(lcons), s)
    return cons(rcar, rcdr)