Beispiel #1
0
    def visit_literal(self, node: Node, children: List) -> 'Literal':
        from foil.models import Literal

        try:
            return Literal(children[1], children[0])
        except IndexError:
            return Literal(children[0], False)
Beispiel #2
0
def find_literal(
    hypotheses: List['Clause'],
    target: 'Literal',
    body: List['Literal'],
    background: List['Clause'],
    masks: List['Literal'],
    constants: List['Value'],
    positives: List['Assignment'],
    negatives: List['Assignment'],
) -> Optional[Candidate]:
    from foil.models import Atom
    from foil.models import Clause
    from foil.models import Literal
    from foil.models import Program

    candidate, table, bound = None, get_table([target, *body]), max_gain(
        positives, negatives)
    for mask in masks:
        for items in itemize(table, mask.arity):
            literal = Literal(Atom(mask.functor, items), mask.negated)
            world = Program(
                [*hypotheses,
                 Clause(target, [*body, literal]), *background]).ground()
            positives_i = extend(positives, literal, constants, world)
            negatives_i = extend(negatives, literal, constants, world)
            score = gain(positives, negatives, positives_i, negatives_i)
            if candidate and bound < candidate.score:
                break
            if candidate is None or score > candidate.score:
                candidate = Candidate(score, literal, positives_i, negatives_i)

    return candidate
Beispiel #3
0
    def test__get_arity(self):
        for i, entry in enumerate([
            (Literal.parse('func'), 0),
            (Literal.parse('func()'), 0),
            (Literal.parse('func(term)'), 1),
            (Literal.parse('func(term, 5.0)'), 2),
            (Literal.parse('func(term, 5.0, True)'), 3),
            (Literal.parse('~func'), 0),
            (Literal.parse('~func()'), 0),
            (Literal.parse('~func(term)'), 1),
            (Literal.parse('~func(term, 5.0)'), 2),
            (Literal.parse('~func(term, 5.0, True)'), 3),
        ]):
            atom, expected = entry
            with self.subTest(i=i, value=entry):
                result = atom.get_arity()

                assert_that(result, 'Literal.get_arity(self) -> int:') \
                    .is_equal_to(expected)
Beispiel #4
0
    def test__substitute(self):
        for i, entry in enumerate([
            (Literal.parse('pred.'), {}, Literal.parse('pred.')),
            (Literal.parse('pred.'), {'X': 'a'}, Literal.parse('pred.')),
            (Literal.parse('pred.'), {'Y': 'X'}, Literal.parse('pred.')),

            (Literal.parse('pred(a).'), {}, Literal.parse('pred(a).')),
            (Literal.parse('pred(a).'), {'X': 'a'}, Literal.parse('pred(a).')),
            (Literal.parse('pred(a).'), {'Y': 'X'}, Literal.parse('pred(a).')),

            (Literal.parse('pred(X).'), {}, Literal.parse('pred(X).')),
            (Literal.parse('pred(X).'), {'X': 'a'}, Literal.parse('pred(a).')),
            (Literal.parse('pred(X).'), {'Y': 'X'}, Literal.parse('pred(X).')),

            (Literal.parse('pred(Y).'), {}, Literal.parse('pred(Y).')),
            (Literal.parse('pred(Y).'), {'X': 'a'}, Literal.parse('pred(Y).')),
            (Literal.parse('pred(Y).'), {'Y': 'X'}, Literal.parse('pred(X).')),

            (Literal.parse('pred(X, Y).'), {}, Literal.parse('pred(X, Y).')),
            (Literal.parse('pred(X, Y).'), {'X': 'a'}, Literal.parse('pred(a, Y).')),
            (Literal.parse('pred(X, Y).'), {'Y': 'X'}, Literal.parse('pred(X, X).')),

            (Literal.parse('~pred.'), {}, Literal.parse('~pred.')),
            (Literal.parse('~pred.'), {'X': 'a'}, Literal.parse('~pred.')),
            (Literal.parse('~pred.'), {'Y': 'X'}, Literal.parse('~pred.')),

            (Literal.parse('~pred(a).'), {}, Literal.parse('~pred(a).')),
            (Literal.parse('~pred(a).'), {'X': 'a'}, Literal.parse('~pred(a).')),
            (Literal.parse('~pred(a).'), {'Y': 'X'}, Literal.parse('~pred(a).')),

            (Literal.parse('~pred(X).'), {}, Literal.parse('~pred(X).')),
            (Literal.parse('~pred(X).'), {'X': 'a'}, Literal.parse('~pred(a).')),
            (Literal.parse('~pred(X).'), {'Y': 'X'}, Literal.parse('~pred(X).')),

            (Literal.parse('~pred(Y).'), {}, Literal.parse('~pred(Y).')),
            (Literal.parse('~pred(Y).'), {'X': 'a'}, Literal.parse('~pred(Y).')),
            (Literal.parse('~pred(Y).'), {'Y': 'X'}, Literal.parse('~pred(X).')),

            (Literal.parse('~pred(X, Y).'), {}, Literal.parse('~pred(X, Y).')),
            (Literal.parse('~pred(X, Y).'), {'X': 'a'}, Literal.parse('~pred(a, Y).')),
            (Literal.parse('~pred(X, Y).'), {'Y': 'X'}, Literal.parse('~pred(X, X).')),

        ]):
            clause, subst, expected = entry
            with self.subTest(i=i, value=entry):
                result = clause.substitute(subst)

                assert_that(result, 'Clause.substitute(self, substitution: Substitution) -> Clause:') \
                    .is_equal_to(expected)
Beispiel #5
0
    def test__parse(self):
        for i, entry in enumerate([
            ('func.', Clause(Literal(Atom('func')))),
            ('func().', Clause(Literal(Atom('func', [])))),
            ('func(Var).', Clause(Literal(Atom('func', ['Var'])))),
            ('func(term).', Clause(Literal(Atom('func', ['term'])))),
            ('func(term, 5.0).', Clause(Literal(Atom('func', ['term', 5.0])))),
            ('func(term, 5.0, True).', Clause(Literal(Atom('func', ['term', 5.0, True])))),

            ('~func.', Clause(Literal(Atom('func'), True))),
            ('~func().', Clause(Literal(Atom('func', []), True))),
            ('~func(Var).', Clause(Literal(Atom('func', ['Var']), True))),
            ('~func(term).', Clause(Literal(Atom('func', ['term']), True))),
            ('~func(term, 5.0).', Clause(Literal(Atom('func', ['term', 5.0]), True))),
            ('~func(term, 5.0, True).', Clause(Literal(Atom('func', ['term', 5.0, True]), True))),

            ('func :- pred.', Clause(Literal(Atom('func')), [Literal(Atom('pred'))])),
            ('func() :- pred.', Clause(Literal(Atom('func', [])), [Literal(Atom('pred'))])),
            ('func(Var) :- pred.', Clause(Literal(Atom('func', ['Var'])), [Literal(Atom('pred'))])),
            ('func(term) :- pred.', Clause(Literal(Atom('func', ['term'])), [Literal(Atom('pred'))])),
            ('func(term, 5.0) :- pred.', Clause(Literal(Atom('func', ['term', 5.0])), [Literal(Atom('pred'))])),
            ('func(term, 5.0, True) :- pred.',
             Clause(Literal(Atom('func', ['term', 5.0, True])), [Literal(Atom('pred'))])),

            ('~func :- pred.', Clause(Literal(Atom('func'), True), [Literal(Atom('pred'))])),
            ('~func() :- pred.', Clause(Literal(Atom('func', []), True), [Literal(Atom('pred'))])),
            ('~func(Var) :- pred.', Clause(Literal(Atom('func', ['Var']), True), [Literal(Atom('pred'))])),
            ('~func(term) :- pred.', Clause(Literal(Atom('func', ['term']), True), [Literal(Atom('pred'))])),
            ('~func(term, 5.0) :- pred.', Clause(Literal(Atom('func', ['term', 5.0]), True), [Literal(Atom('pred'))])),
            ('~func(term, 5.0, True) :- pred.',
             Clause(Literal(Atom('func', ['term', 5.0, True]), True), [Literal(Atom('pred'))])),
        ]):
            content, expected = entry
            with self.subTest(i=i, value=entry):
                result = Clause.parse(content)

                assert_that(result, 'Clause.parse(content: str) -> Clause:') \
                    .is_equal_to(expected)
Beispiel #6
0
    def test__unify(self):
        for i, entry in enumerate([
            (Literal.parse('func'),
             Literal.parse('pred'),
             None),
            (Literal.parse('func'),
             Literal.parse('func'),
             {}),
            (Literal.parse('func()'),
             Literal.parse('pred()'),
             None),
            (Literal.parse('func()'),
             Literal.parse('func()'),
             {}),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('pred(term, 5.0)'),
             None),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('func(term, 5.0)'),
             {}),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('pred(term, 5.0)'),
             None),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('func(term, 5.0)'),
             {}),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('pred(5.0, term)'),
             None),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('func(5.0, term)'),
             None),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('pred(term)'),
             None),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('func(term)'),
             None),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('pred(5.0)'),
             None),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('func(5.0)'),
             None),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('pred(True)'),
             None),
            (Literal.parse('func(term, 5.0)'),
             Literal.parse('func(True)'),
             None),
            (Literal.parse('func(term, V1, V2)'),
             Literal.parse('pred(term, 5.0, True)'),
             None),
            (Literal.parse('func(term, V1, V2)'),
             Literal.parse('func(term, 5.0, True)'),
             {'V1': 5.0, 'V2': True}),
            (Literal.parse('func(term, V1, V2)'),
             Literal.parse('func(V0, 5.0, True)'),
             {'V0': 'term', 'V1': 5.0, 'V2': True}),
            (Literal.parse('func(term, 5.0, True)'),
             Literal.parse('func(term, V1, V2)'),
             {'V1': 5.0, 'V2': True}),
            (Literal.parse('func(term, V1, V2)'),
             Literal.parse('func(X, Y, Z)'),
             {'X': 'term', 'Y': 'V1', 'Z': 'V2'}),
            (Literal.parse('~func'),
             Literal.parse('~pred'),
             None),
            (Literal.parse('~func'),
             Literal.parse('~func'),
             {}),
            (Literal.parse('~func()'),
             Literal.parse('~pred()'),
             None),
            (Literal.parse('~func()'),
             Literal.parse('~func()'),
             {}),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~pred(term, 5.0)'),
             None),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~func(term, 5.0)'),
             {}),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~pred(term, 5.0)'),
             None),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~func(term, 5.0)'),
             {}),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~pred(5.0, term)'),
             None),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~func(5.0, term)'),
             None),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~pred(term)'),
             None),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~func(term)'),
             None),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~pred(5.0)'),
             None),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~func(5.0)'),
             None),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~pred(True)'),
             None),
            (Literal.parse('~func(term, 5.0)'),
             Literal.parse('~func(True)'),
             None),
            (Literal.parse('~func(term, V1, V2])'),
             Literal.parse('~pred(term, 5.0, True)'),
             None),
            (Literal.parse('~func(term, V1, V2)'),
             Literal.parse('~func(term, 5.0, True)'),
             {'V1': 5.0, 'V2': True}),
            (Literal.parse('~func(term, V1, V2)'),
             Literal.parse('~func(V0, 5.0, True)'),
             {'V0': 'term', 'V1': 5.0, 'V2': True}),
            (Literal.parse('~func(term, 5.0, True)'),
             Literal.parse('~func(term, V1, V2)'),
             {'V1': 5.0, 'V2': True}),
            (Literal.parse('~func(term, V1, V2)'),
             Literal.parse('~func(X, Y, Z)'),
             {'X': 'term', 'Y': 'V1', 'Z': 'V2'}),
        ]):
            atom1, atom2, expected = entry
            with self.subTest(i=i, value=entry):
                result = atom1.unify(atom2)

                assert_that(result, 'Literal.unify(self, other: Literal) -> Optional[Substitution]:') \
                    .is_equal_to(
                    expected)
Beispiel #7
0
    def test__is_ground(self):
        for i, entry in enumerate([
            (Literal.parse('func'), True),
            (Literal.parse('func()'), True),
            (Literal.parse('func(term)'), True),
            (Literal.parse('func(term, 5.0)'), True),
            (Literal.parse('func(term, 5.0, True)'), True),
            (Literal.parse('func(term, 5.0, True, Var)'), False),
            (Literal.parse('func(term, 5.0, True, _anon)'), False),
            (Literal.parse('~func'), True),
            (Literal.parse('~func()'), True),
            (Literal.parse('~func(term)'), True),
            (Literal.parse('~func(term, 5.0)'), True),
            (Literal.parse('~func(term, 5.0, True)'), True),
            (Literal.parse('~func(term, 5.0, True, Var)'), False),
            (Literal.parse('~func(term, 5.0, True, _anon)'), False),
        ]):
            atom, expected = entry
            with self.subTest(i=i, value=entry):
                result = atom.is_ground()

                assert_that(result, 'Literal.is_ground(self) -> bool:') \
                    .is_equal_to(expected)
Beispiel #8
0
    def test__get_mask(self):
        for i, entry in enumerate([
            (Literal.parse('func'), Mask(False, 'func', 0)),
            (Literal.parse('func()'), Mask(False, 'func', 0)),
            (Literal.parse('func(term)'), Mask(False, 'func', 1)),
            (Literal.parse('func(term, 5.0)'), Mask(False, 'func', 2)),
            (Literal.parse('func(term, 5.0, True)'), Mask(False, 'func', 3)),
            (Literal.parse('func(term, 5.0, True, X)'), Mask(False, 'func', 4)),

            (Literal.parse('~func'), Mask(True, 'func', 0)),
            (Literal.parse('~func()'), Mask(True, 'func', 0)),
            (Literal.parse('~func(term)'), Mask(True, 'func', 1)),
            (Literal.parse('~func(term, 5.0)'), Mask(True, 'func', 2)),
            (Literal.parse('~func(term, 5.0, True)'), Mask(True, 'func', 3)),
            (Literal.parse('~func(term, 5.0, True, X)'), Mask(True, 'func', 4)),
        ]):
            literal, expected = entry
            with self.subTest(i=i, value=entry):
                result = literal.get_mask()

                assert_that(result, 'Literal.get_mask(self) -> Mask:') \
                    .is_equal_to(expected)
Beispiel #9
0
    def test__get_complement(self):
        for i, entry in enumerate([
            (Literal.parse('func'), Literal.parse('~func')),
            (Literal.parse('func()'), Literal.parse('~func()')),
            (Literal.parse('func(term)'), Literal.parse('~func(term)')),
            (Literal.parse('func(term, 5.0)'), Literal.parse('~func(term, 5.0)')),
            (Literal.parse('func(term, 5.0, True)'), Literal.parse('~func(term, 5.0, True)')),
            (Literal.parse('func(term, 5.0, True, X)'), Literal.parse('~func(term, 5.0, True, X)')),

            (Literal.parse('~func'), Literal.parse('func')),
            (Literal.parse('~func()'), Literal.parse('func()')),
            (Literal.parse('~func(term)'), Literal.parse('func(term)')),
            (Literal.parse('~func(term, 5.0)'), Literal.parse('func(term, 5.0)')),
            (Literal.parse('~func(term, 5.0, True)'), Literal.parse('func(term, 5.0, True)')),
            (Literal.parse('~func(term, 5.0, True, X)'), Literal.parse('func(term, 5.0, True, X)')),
        ]):
            literal, expected = entry
            with self.subTest(i=i, value=entry):
                result = literal.get_complement()

                assert_that(result, 'Literal.get_complement(self) -> Literal:') \
                    .is_equal_to(expected)
Beispiel #10
0
    def test__parse(self):
        for i, entry in enumerate([
            ('func', Literal(Atom('func'))),
            ('func()', Literal(Atom('func', []))),
            ('func(term)', Literal(Atom('func', ['term']))),
            ('func(term, 5.0)', Literal(Atom('func', ['term', 5.0]))),
            ('func(term, 5.0, True)', Literal(Atom('func', ['term', 5.0, True]))),
            ('func(term, 5.0, True, X)', Literal(Atom('func', ['term', 5.0, True, 'X']))),

            ('~func', Literal(Atom('func'), True)),
            ('~func()', Literal(Atom('func', []), True)),
            ('~func(term)', Literal(Atom('func', ['term']), True)),
            ('~func(term, 5.0)', Literal(Atom('func', ['term', 5.0]), True)),
            ('~func(term, 5.0, True)', Literal(Atom('func', ['term', 5.0, True]), True)),
            ('~func(term, 5.0, True, X)', Literal(Atom('func', ['term', 5.0, True, 'X']), True)),

            ('~~func', Literal(Atom('func'))),
            ('~~func()', Literal(Atom('func', []))),
            ('~~func(term)', Literal(Atom('func', ['term']))),
            ('~~func(term, 5.0)', Literal(Atom('func', ['term', 5.0]))),
            ('~~func(term, 5.0, True)', Literal(Atom('func', ['term', 5.0, True]))),
            ('~~func(term, 5.0, True, X)', Literal(Atom('func', ['term', 5.0, True, 'X']))),

            ('~~~func', Literal(Atom('func'), True)),
            ('~~~func()', Literal(Atom('func', []), True)),
            ('~~~func(term)', Literal(Atom('func', ['term']), True)),
            ('~~~func(term, 5.0)', Literal(Atom('func', ['term', 5.0]), True)),
            ('~~~func(term, 5.0, True)', Literal(Atom('func', ['term', 5.0, True]), True)),
            ('~~~func(term, 5.0, True, X)', Literal(Atom('func', ['term', 5.0, True, 'X']), True)),
        ]):
            content, expected = entry
            with self.subTest(i=i, value=entry):
                result = Literal.parse(content)

                assert_that(result, 'Literal.parse(content: str) -> Literal:') \
                    .is_equal_to(expected)
from foil.learning import get_masks
from foil.learning import get_signature
from foil.learning import get_table
from foil.learning import Hypothesis
from foil.learning import itemize
from foil.learning import max_gain
from foil.models import Clause
from foil.models import Example
from foil.models import Literal
from foil.models import Mask
from foil.models import Program

hypotheses_0 = []
hypotheses_1 = [Clause.parse('path(X,Y) :- edge(X,Y).')]

target = Literal.parse('path(X,Y)')

body_0 = []
body_1 = [Literal.parse('edge(X,V0)')]

edge_x_y = Literal.parse('edge(X,Y)')
edge_x_v0 = Literal.parse('edge(X,V0)')
path_v0_y = Literal.parse('path(V0,Y)')
edge_v0_y = Literal.parse('edge(V0,Y)')

background = [
    Clause.parse('edge(0,1).'),
    Clause.parse('edge(0,3).'),
    Clause.parse('edge(1,2).'),
    Clause.parse('edge(3,2).'),
    Clause.parse('edge(3,4).'),
Beispiel #12
0
from foil.models import Example
from foil.models import Label
from foil.models import Literal
from foil.models import Problem
from foil.models import Program

if __name__ == '__main__':
    problem = Problem(
        Program.parse('edge(0,1). edge(0,3). edge(1,2). edge(3,2). edge(3,4). '
                      'edge(4,5). edge(4,6). edge(6,8). edge(7,6). edge(7,8).'),
        Literal.parse('path(X,Y)'),
        [
            Example({'X': 0, 'Y': 1}, Label.POSITIVE),
            Example({'X': 0, 'Y': 2}, Label.POSITIVE),
            Example({'X': 0, 'Y': 3}, Label.POSITIVE),
            Example({'X': 0, 'Y': 4}, Label.POSITIVE),
            Example({'X': 0, 'Y': 5}, Label.POSITIVE),
            Example({'X': 0, 'Y': 6}, Label.POSITIVE),
            Example({'X': 0, 'Y': 8}, Label.POSITIVE),
            Example({'X': 1, 'Y': 2}, Label.POSITIVE),
            Example({'X': 3, 'Y': 2}, Label.POSITIVE),
            Example({'X': 3, 'Y': 4}, Label.POSITIVE),
            Example({'X': 3, 'Y': 5}, Label.POSITIVE),
            Example({'X': 3, 'Y': 6}, Label.POSITIVE),
            Example({'X': 3, 'Y': 8}, Label.POSITIVE),
            Example({'X': 4, 'Y': 5}, Label.POSITIVE),
            Example({'X': 4, 'Y': 6}, Label.POSITIVE),
            Example({'X': 4, 'Y': 8}, Label.POSITIVE),
            Example({'X': 6, 'Y': 8}, Label.POSITIVE),
            Example({'X': 7, 'Y': 6}, Label.POSITIVE),
            Example({'X': 7, 'Y': 8}, Label.POSITIVE),
Beispiel #13
0
from foil.models import Program


class Measure:
    def __init__(self):
        self.elapsed = None

    def __enter__(self):
        self.elapsed = datetime.datetime.now()

    def __exit__(self, ty, val, tb):
        print('\nElapsed time: %s sec.\n' % (datetime.datetime.now() - self.elapsed))


if __name__ == '__main__':
    target = Literal.parse('path(X,Y)')
    examples = [
        Example({'X': 0, 'Y': 1}), Example({'X': 0, 'Y': 2}), Example({'X': 0, 'Y': 3}),
        Example({'X': 0, 'Y': 4}), Example({'X': 0, 'Y': 5}), Example({'X': 0, 'Y': 6}),
        Example({'X': 0, 'Y': 8}), Example({'X': 1, 'Y': 2}), Example({'X': 3, 'Y': 2}),
        Example({'X': 3, 'Y': 4}), Example({'X': 3, 'Y': 5}), Example({'X': 3, 'Y': 6}),
        Example({'X': 3, 'Y': 8}), Example({'X': 4, 'Y': 5}), Example({'X': 4, 'Y': 6}),
        Example({'X': 4, 'Y': 8}), Example({'X': 6, 'Y': 8}), Example({'X': 7, 'Y': 6}),
        Example({'X': 7, 'Y': 8}),
    ]
    background = [
        Clause.parse('edge(0,1).'), Clause.parse('edge(0,3).'), Clause.parse('edge(1,2).'),
        Clause.parse('edge(3,2).'), Clause.parse('edge(3,4).'), Clause.parse('edge(4,5).'),
        Clause.parse('edge(4,6).'), Clause.parse('edge(6,8).'), Clause.parse('edge(7,6).'),
        Clause.parse('edge(7,8).'),
    ]
Beispiel #14
0
from foil.models import Literal
from foil.models import Program

source = """
q(X,Y) :- p(Y,X).
p(1,2).
"""

if __name__ == '__main__':
    program = Program.parse(source)
    print(program)
    print()

    query = Literal.parse('q(2,1)')
    print('?-', query)

    derivation = program.resolve(query)
    if derivation:
        print('YES')
        for step in derivation:
            clause = program.get_clause(step.index)
            subst = '{%s}' % ', '.join('%s: %s' % (k, repr(v)) for k, v in step.substitution.items())
            print('    ', clause, '  /  ', subst, '  /  ', step.literal)
    else:
        print('NO')
    print()

    print('Done.')