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