def enumerate_facts(self, Q, C, infer_step): """ enumerate a set of necessary and sufficient ground atoms Inputs ------ Q : (Set[.logic.Atom], Set[.logic.Atom], Set[.logic.Atom], Set[.logic.Atom]) inductive logic programming problem (P, N, B, L) C : List[.logic.Clause] set of clauses from the clause-generation step infer_step : int number of steps of forward-chaining inference Returns ------- G : List[.logic.Atom] set of enumerated ground atoms """ pos_examples = Q.pos neg_examples = Q.neg backgrounds = Q.bk G = set(pos_examples + neg_examples + backgrounds) G_next = G G_past = G head_unifier_dic = {} for i in range(infer_step): S = set() for clause in C: for fi, fact in enumerate(G_next): if (clause.head, fact) in head_unifier_dic: unify_flag, theta_list = unify([fact, clause.head]) else: unify_flag, theta_list = unify([fact, clause.head]) head_unifier_dic[(clause.head, fact) ] = unify_flag, theta_list if unify_flag: clause_ = subs_list(clause, theta_list) B_i_list = clause_.body S = S.union(set(B_i_list)) G = G.union(S) G_past = G_past.union(G_next) G_next = S.difference(G_past) # SPECIAL p_ = Predicate('.', 1) false = Atom(p_, [Const('__F__')]) true = Atom(p_, [Const('__T__')]) G_given = set([false, true] + pos_examples + neg_examples + backgrounds) G_inter = G.intersection(G_given) G_add = G.difference(G_inter) return [false, true] + backgrounds + pos_examples + neg_examples + list(G_add)
def __init__(self, n=30, noise_rate=0.0): self.name = "member" self.pos_examples = [] self.neg_examples = [] self.backgrounds = [] self.init_clauses = [] p_ = Predicate('.', 1) false = Atom(p_, [Const('__F__')]) true = Atom(p_, [Const('__T__')]) self.facts = [false, true] self.lang = None self.noise_rate = noise_rate self.n = n self.max_len = 4 self.symbols = list('abc')
def get_neg_examples(self): i = 0 while i < self.n: n1 = random.randint(0, int(self.max_len)) n2 = random.randint(0, int(self.max_len)) n3 = random.randint(int(self.max_len / 2), self.max_len) ls1 = random_choices(self.symbols, k=n1) ls2 = random_choices(self.symbols, k=n2) ls3 = random_choices(self.symbols, k=n3) term1 = list_to_term(ls1, self.funcs[0]) term2 = list_to_term(ls2, self.funcs[0]) term3 = list_to_term(ls3, self.funcs[0]) a1 = random.choice(self.symbols) n2 = random.randint(1, int(self.max_len)) n3 = random.randint(1, int(self.max_len)) ls2 = random_choices(self.symbols, k=n2) ls3 = random_choices(self.symbols, k=n3) if a1 in ls2 and delete(a1, ls2) != ls3: term1 = Const(a1) term2 = list_to_term(ls2, self.funcs[0]) term3 = list_to_term(ls3, self.funcs[0]) atom = Atom(self.preds[0], [term1, term2, term3]) if not atom in self.neg_examples: self.neg_examples.append(atom) i += 1
def get_backgrounds(self): # pass #self.backgrounds.append(Atom(self.preds[0], [Const('*'), Const('*')])) for s in self.symbols: atom = Atom(self.preds[0], [Const(s), list_to_term([s], self.funcs[0])]) self.backgrounds.append(atom)
def list_to_examples(ls, pred, f): atoms = [] for x in ls: list_term = list_to_term(ls, f) atom = Atom(pred, [Const(x), list_term]) atoms.append(atom) return atoms
def __get_neg_examples(self): for i in range(self.max_n): for j in range(self.max_n): if (i != 0 or j != 0): sum_ = i + j if sum_ + 1 <= self.max_n + self.max_n: self.neg_examples.append( Atom(self.preds[0], [ int_to_term(i), int_to_term(j), int_to_term(sum_ + 1) ])) if sum_ - 1 >= 0: self.neg_examples.append( Atom(self.preds[0], [ int_to_term(i), int_to_term(j), int_to_term(sum_ - 1) ]))
def get_pos_examples(self): i = 0 while len(self.pos_examples) < self.n: n = random.randint(2, self.max_len) x = random.choice(self.symbols) ls = random_choices(self.symbols, k=n) if x in ls: term1 = Const(x) term2 = list_to_term(ls, self.funcs[0]) atom = Atom(self.preds[0], [term1, term2]) self.pos_examples.append(atom)
def __get_pos_examples(self): for i in range(self.max_n): for j in range(self.max_n): # if i == 0 and j == 0: # continue sum_ = i + j atom = Atom( self.preds[0], [int_to_term(i), int_to_term(j), int_to_term(sum_)]) if not atom in self.pos_examples: self.pos_examples.append(atom) atom = Atom( self.preds[0], [int_to_term(j), int_to_term(i), int_to_term(sum_)]) if not atom in self.pos_examples: self.pos_examples.append(atom)
def get_neg_examples(self): while (len(self.neg_examples) < self.n): i = random.randint(0, self.max_n) j = random.randint(0, self.max_n) sum_ = random.randint(0, self.max_n * 2) atom = Atom(self.preds[0], [int_to_term(i), int_to_term(j), int_to_term(sum_)]) if not atom in self.neg_examples and i + j != sum_: self.neg_examples.append(atom)
def get_pos_examples(self): while (len(self.pos_examples) < self.n): i = random.randint(0, self.max_n) j = random.randint(0, self.max_n) sum_ = i + j atom = Atom(self.preds[0], [int_to_term(i), int_to_term(j), int_to_term(sum_)]) if not atom in self.pos_examples: if not (i == 0 and j == 0): self.pos_examples.append(atom)
def get_facts(self): terms = [] for i in range(1, self.max_len + 1): i_len_list = list(itertools.product(self.symbols, repeat=i)) for l in i_len_list: term = list_to_term(l, self.funcs[0]) terms.append(term) # generate facts args1 = [term for term in terms if term.max_depth() <= 0] args2 = [term for term in terms] for pair in list(itertools.product(args1, args2)): self.facts.append(Atom(self.preds[0], list(pair)))
def get_pos_examples(self): i = 0 while len(self.pos_examples) < self.n: n1 = random.randint(1, int(self.max_len)) n2 = random.randint(1, int(self.max_len)) _ls1 = random_choices(self.symbols, k=n1) ls2 = random_choices(self.symbols, k=n2) ls1_list = get_sublist(_ls1) for ls1 in ls1_list: ls3 = ls1 + ls2 term1 = list_to_term(ls1, self.funcs[0]) term2 = list_to_term(ls2, self.funcs[0]) term3 = list_to_term(ls3, self.funcs[0]) atom = Atom(self.preds[0], [term1, term2, term3]) if not atom in self.pos_examples: self.pos_examples.append(atom) i += 1 ls3 = ls2 + ls1 term3 = list_to_term(ls3, self.funcs[0]) atom = Atom(self.preds[0], [term2, term1, term3]) if not atom in self.pos_examples: self.pos_examples.append(atom) i += 1
def get_neg_examples(self): i = 0 while i < self.n: n = random.randint(1, self.max_len) # 長さnで満たすもの出すまで繰り返し flag = True while flag: x = random.choice(self.symbols) ls = random_choices(self.symbols, n) if not x in ls: atom = Atom( self.preds[0], [Const(x), list_to_term(ls, self.funcs[0])]) self.neg_examples.append(atom) i += 1 flag = False
def get_pos_examples(self): i = 0 while len(self.pos_examples) < self.n: a1 = random.choice(self.symbols) n2 = random.randint(1, int(self.max_len)) ls2 = random_choices(self.symbols, k=n2) if a1 in ls2: term1 = Const(a1) term2 = list_to_term(ls2, self.funcs[0]) term3 = list_to_term(delete(a1, ls2), self.funcs[0]) atom = Atom(self.preds[0], [term1, term2, term3]) if not atom in self.pos_examples: self.pos_examples.append(atom) i += 1
def get_neg_examples(self): i = 0 while i < self.n: n1 = random.randint(0, int(self.max_len)) n2 = random.randint(0, int(self.max_len)) n3 = random.randint(int(self.max_len / 2), self.max_len) ls1 = random_choices(self.symbols, k=n1) ls2 = random_choices(self.symbols, k=n2) ls3 = random_choices(self.symbols, k=n3) term1 = list_to_term(ls1, self.funcs[0]) term2 = list_to_term(ls2, self.funcs[0]) term3 = list_to_term(ls3, self.funcs[0]) if ls1 + ls2 != ls3: atom = Atom(self.preds[0], [term1, term2, term3]) if not atom in self.neg_examples: self.neg_examples.append(atom) i += 1
def subs(exp, target_var, const): """ Substitute var = const Inputs ------ exp : .logic.CLause .logic.Atom .logic.FuncTerm .logic.Const .logic.Var logical expression atom, clause, or term target_var : .logic.Var target variable of the substitution const : .logic.Const constant to be substituted Returns ------- exp : .logic.CLause .logic.Atom .logic.FuncTerm .logic.Const .logic.Var result of the substitution logical expression atom, clause, or term """ if type(exp) == Clause: head = subs(exp.head, target_var, const) body = [subs(bi, target_var, const) for bi in exp.body] return Clause(head, body) elif type(exp) == Atom: terms = [subs(term, target_var, const) for term in exp.terms] return Atom(exp.pred, terms) elif type(exp) == FuncTerm: args = [subs(arg, target_var, const) for arg in exp.args] return FuncTerm(exp.func_symbol, args) elif type(exp) == Var: if exp.name == target_var.name: return const else: return exp elif type(exp) == Const: return exp else: assert 1 == 0, 'Unknown type in substitution: ' + str(exp)
def add_atom(self, clause): """ add p(x_1, ..., x_n) to the body """ # Check body length if (len(clause.body) >= self.max_body_len) or (len(clause.all_consts()) >= 1): return [] refined_clauses = [] for p in self.lang.preds: var_candidates = clause.all_vars() # Select X_1, ..., X_n for new atom p(X_1, ..., X_n) # 1. Selection 2. Ordering for vs in itertools.permutations(var_candidates, p.arity): new_atom = Atom(p, vs) head = clause.head if new_atom != head and not (new_atom in clause.body): new_body = clause.body + [new_atom] new_clause = Clause(head, new_body) refined_clauses.append(new_clause) return refined_clauses
def get_backgrounds(self): # pass atom = Atom(self.preds[0], [Const('*'), Const('*'), Const('*')]) self.backgrounds.append(atom)
def get_clauses(self): clause1 = Clause(Atom(self.preds[0], [Var('X'), Var('Y')]), []) self.clauses = [clause1]
def get_backgrounds(self): # pass zero = Const('0') self.backgrounds.append(Atom(self.preds[0], [zero, zero, zero]))
def get_backgrounds(self): # for s in self.symbols: # atom = Atom(self.preds[0], [Const(s), Const(s)]) # self.backgrounds.append(atom) for s in self.symbols: self.backgrounds.append(Atom(self.preds[0], [Const(s), Const(s)]))
def to_atom(t1, t2, pred): return Atom(pred, [t1, t2])