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)
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
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)
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)
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)
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)
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)
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)
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)
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).'),
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),
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).'), ]
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.')