Example #1
0
    def visit_clause(self, node: Node, children: List) -> 'Clause':
        from foil.models import Clause

        try:
            return Clause(children[0], children[1])
        except IndexError:
            return Clause(children[0])
Example #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
Example #3
0
def find_clause(
    hypotheses: List['Clause'],
    target: 'Literal',
    background: List['Clause'],
    masks: List['Mask'],
    constants: List['Value'],
    positives: List['Assignment'],
    negatives: List['Assignment'],
) -> Optional[Hypothesis]:
    from foil.models import Clause

    body, positives, negatives = [], [*positives], [*negatives]
    while negatives:
        candidate = find_literal(hypotheses, target, body, background, masks,
                                 constants, positives, negatives)
        if candidate is None:
            break

        positives = candidate.positives
        negatives = candidate.negatives
        body.append(candidate.literal)

    if not body:
        return None  # TODO Needed?

    return Hypothesis(Clause(target, body), positives)
    def test__foil(self):
        for i, entry in enumerate([
            (pos_0_0, neg_0_0, [
                Clause.parse('path(X,Y) :- edge(X,Y).'),
                Clause.parse('path(X,Y) :- edge(X,V0), path(V0,Y).'),
            ]),
        ]):
            positives, negatives, expected = entry
            with self.subTest(i=i, value=entry):
                result = foil(target, background, masks, constants, positives,
                              negatives)

                assert_that(
                    result,
                    'foil(target: Literal, background: List[Clause], positives: List[Assignment],'
                    ' negatives: List[Assignment]) -> List[Clause]:',
                ).is_equal_to(expected)
    def test__find_clause(self):
        for i, entry in enumerate([
            (hypotheses_0, pos_0_0, neg_0_0,
             Hypothesis(Clause(target, [edge_x_y]), pos_0_1)),
            (hypotheses_1, pos_1_0, neg_1_0,
             Hypothesis(Clause(target, [edge_x_v0, path_v0_y]), pos_1_2)),
        ]):
            hypotheses, positives, negatives, expected = entry
            with self.subTest(i=i, value=entry):
                result = find_clause(hypotheses, target, background, masks,
                                     constants, positives, negatives)

                assert_that(
                    result,
                    'find_clause(hypotheses: List[Clause], target: Literal, background: List[Clause], '
                    'literals: List[Literal], constants: List[Value], positives: List[Assignment], '
                    'negatives: List[Assignment]) -> Optional[Hypothesis]:',
                ).is_equal_to(expected)
    def test__extend(self):
        for i, entry in enumerate([
            (pos_0_0, hypotheses_0, [], edge_x_y, pos_0_1),
            (neg_0_0, hypotheses_0, [], edge_x_y, neg_0_1),
            (pos_1_0, hypotheses_1, [], edge_x_v0, pos_1_1),
            (neg_1_0, hypotheses_1, [], edge_x_v0, neg_1_1),
            (pos_1_1, hypotheses_1, [edge_x_v0], path_v0_y, pos_1_2),
            (neg_1_1, hypotheses_1, [edge_x_v0], path_v0_y, neg_1_2),
            (pos_1_1, hypotheses_1, [edge_x_v0], edge_v0_y, pos_1_3),
            (neg_1_1, hypotheses_1, [edge_x_v0], edge_v0_y, neg_1_3),
        ]):
            examples, hypotheses, body, literal, expected = entry
            world = Program(
                [*hypotheses,
                 Clause(target, [*body, literal]), *background]).ground()
            with self.subTest(i=i, value=entry):
                result = extend(examples, literal, constants, world)

                if not expected:
                    assert_that(result, 'extend').is_empty()
                else:
                    assert_that(result, 'extend').contains_only(*expected)
Example #7
0
    def test__is_ground(self):
        for i, entry in enumerate([
            (Clause.parse('func.'), True),
            (Clause.parse('func().'), True),
            (Clause.parse('func(Var).'), False),
            (Clause.parse('func(term).'), True),
            (Clause.parse('func(term, 5.0).'), True),
            (Clause.parse('func(term, 5.0, True).'), True),
            (Clause.parse('~func.'), True),
            (Clause.parse('~func().'), True),
            (Clause.parse('~func(Var).'), False),
            (Clause.parse('~func(term).'), True),
            (Clause.parse('~func(term, 5.0).'), True),
            (Clause.parse('~func(term, 5.0, True).'), True),

            (Clause.parse('func :- pred.'), True),
            (Clause.parse('func() :- pred.'), True),
            (Clause.parse('func(Var) :- pred.'), False),
            (Clause.parse('func(term) :- pred.'), True),
            (Clause.parse('func(term, 5.0) :- pred.'), True),
            (Clause.parse('func(term, 5.0, True) :- pred.'), True),
            (Clause.parse('~func :- pred.'), True),
            (Clause.parse('~func() :- pred.'), True),
            (Clause.parse('~func(Var) :- pred.'), False),
            (Clause.parse('~func(term) :- pred.'), True),
            (Clause.parse('~func(term, 5.0) :- pred.'), True),
            (Clause.parse('~func(term, 5.0, True) :- pred.'), True),

            (Clause.parse('func :- ~pred.'), True),
            (Clause.parse('func() :- ~pred.'), True),
            (Clause.parse('func(Var) :- ~pred.'), False),
            (Clause.parse('func(term) :- ~pred.'), True),
            (Clause.parse('func(term, 5.0) :- ~pred.'), True),
            (Clause.parse('func(term, 5.0, True) :- ~pred.'), True),
            (Clause.parse('~func :- ~pred.'), True),
            (Clause.parse('~func() :- ~pred.'), True),
            (Clause.parse('~func(Var) :- ~pred.'), False),
            (Clause.parse('~func(term) :- ~pred.'), True),
            (Clause.parse('~func(term, 5.0) :- ~pred.'), True),
            (Clause.parse('~func(term, 5.0, True) :- ~pred.'), True),
        ]):
            clause, expected = entry
            with self.subTest(i=i, value=entry):
                result = clause.is_ground()

                assert_that(result, 'Clause.is_ground(self) -> bool:') \
                    .is_equal_to(expected)
Example #8
0
    def test__get_arity(self):
        for i, entry in enumerate([
            (Clause.parse('func.'), 0),
            (Clause.parse('func().'), 0),
            (Clause.parse('func(Var).'), 0),
            (Clause.parse('func(term).'), 0),
            (Clause.parse('func(term, 5.0).'), 0),
            (Clause.parse('func(term, 5.0, True).'), 0),
            (Clause.parse('~func.'), 0),
            (Clause.parse('~func().'), 0),
            (Clause.parse('~func(Var).'), 0),
            (Clause.parse('~func(term).'), 0),
            (Clause.parse('~func(term, 5.0).'), 0),
            (Clause.parse('~func(term, 5.0, True).'), 0),

            (Clause.parse('func :- pred.'), 1),
            (Clause.parse('func() :- pred.'), 1),
            (Clause.parse('func(Var) :- pred.'), 1),
            (Clause.parse('func(term) :- pred.'), 1),
            (Clause.parse('func(term, 5.0) :- pred.'), 1),
            (Clause.parse('func(term, 5.0, True) :- pred.'), 1),
            (Clause.parse('~func :- pred.'), 1),
            (Clause.parse('~func() :- pred.'), 1),
            (Clause.parse('~func(Var) :- pred.'), 1),
            (Clause.parse('~func(term) :- pred.'), 1),
            (Clause.parse('~func(term, 5.0) :- pred.'), 1),
            (Clause.parse('~func(term, 5.0, True) :- pred.'), 1),

            (Clause.parse('func :- ~pred.'), 1),
            (Clause.parse('func() :- ~pred.'), 1),
            (Clause.parse('func(Var) :- ~pred.'), 1),
            (Clause.parse('func(term) :- ~pred.'), 1),
            (Clause.parse('func(term, 5.0) :- ~pred.'), 1),
            (Clause.parse('func(term, 5.0, True) :- ~pred.'), 1),
            (Clause.parse('~func :- ~pred.'), 1),
            (Clause.parse('~func() :- ~pred.'), 1),
            (Clause.parse('~func(Var) :- ~pred.'), 1),
            (Clause.parse('~func(term) :- ~pred.'), 1),
            (Clause.parse('~func(term, 5.0) :- ~pred.'), 1),
            (Clause.parse('~func(term, 5.0, True) :- ~pred.'), 1),
        ]):
            clause, expected = entry
            with self.subTest(i=i, value=entry):
                result = clause.get_arity()

                assert_that(result, 'Clause.get_arity(self) -> int:') \
                    .is_equal_to(expected)
Example #9
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)
Example #10
0
from foil.learning import get_closure
from foil.learning import get_constants
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).'),
Example #11
0
        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).'),
    ]

    for i in range(10):
        with Measure():
            print()
            constants = get_constants([target, *{l for c in background for l in c.literals}])
            print()
            world = Program(background).ground()
            print()
            positives, negatives = get_closure(target, constants, world, examples)
            print()
            masks = get_masks([target, *{l for c in background for l in c.literals}])