def __parse_lpad(self, lpad): self.__weights = Weights() self.__logicProgram = LogicProgram() self.__constraints = [] self.__rule_counter = 0 for line in open(lpad): line = line.strip() self.__parse_AD(line)
def __call__(self,logic_program,weights,queries,evidence): self.__original_program = logic_program self.__original_weights = weights self.__new_program = LogicProgram() self.__new_weights = Weights() self.__built_rules = {} for lit in queries | evidence: self.__get_rule(lit) new_evidence = set([]) for lit in evidence: if lit.truth_value: for (new_lit,_) in self.__built_rules[lit]: new_evidence.add(new_lit) else: for (new_lit,_) in self.__built_rules[-lit]: new_evidence.add(-new_lit) return self.__new_program, self.__new_weights, new_evidence
class GroundProbLogParser: def __call__(self, lpad, queries, evidence): self.__parse_queries(queries) self.__parse_evidence(evidence) self.__parse_lpad(lpad) return (self.__logicProgram, self.__constraints, self.__weights, self.__queries, self.__evidence) def __parse_queries(self, queries): self.__queries = set([]) for line in open(queries): self.__queries.add(Literal.parse(line.strip())) def __parse_evidence(self, evidence): self.__evidence = set([]) for line in open(evidence): atom = line.split()[0] truth = line.split()[1] if truth == 'true': self.__evidence.add(Literal(atom, True)) elif truth == 'false': self.__evidence.add(Literal(atom, False)) else: raise ParseError('The truth value for evidence: ' + atom + ' should be true/false') def __parse_lpad(self, lpad): self.__weights = Weights() self.__logicProgram = LogicProgram() self.__constraints = [] self.__rule_counter = 0 for line in open(lpad): line = line.strip() self.__parse_AD(line) def __parse_AD(self, ad): p = RuleParser() (head, body) = p(ad) head = self.__calculate_probabilities(head) choices = self.__get_choices(head) self.__make_rules(choices, body) self.__make_constraints(choices, body) def __calculate_probabilities(self, head): new_head = [] for (prob, atom) in head: if '/' in prob: parts = prob, atom.split('/') new_head.append((float(parts[0]) / float(parts[1]), atom)) else: new_head.append((float(prob), atom)) return new_head def __get_choices(self, head): total_prob = 0 result = [] for i in range(0, len(head)): (prob, atom) = head[i] total_prob += prob self.__weights[atom] = 1.0 self.__weights[-atom] = 1.0 choice = Literal( 'choice_node_' + str(self.__rule_counter) + '_' + str(i), True) self.__weights[choice] = prob self.__weights[-choice] = 1.0 result.append((atom, choice)) if total_prob > 1: raise ParseError( 'the total probability of a rule is bigger than one: ' + head) nillChoice = Literal( 'choice_node_' + str(self.__rule_counter) + '_' + str(len(head)), True) self.__weights[nillChoice] = round(1 - total_prob) self.__weights[-nillChoice] = 1.0 result.append((None, nillChoice)) self.__rule_counter += 1 return result def __make_rules(self, choices, body): for (head, choice) in choices: if head: body_copy = [choice] for atom in body: body_copy.append(atom) self.__logicProgram.add_rule(head, body_copy) def __make_constraints(self, choices, body): if len(choices) > 1: for i in range(0, len(choices) - 1): for j in range(i + 1, len(choices)): self.__constraints.append([-choices[i][1], -choices[j][1]]) constraint = [] for (_, choice) in choices: constraint.append(choice) if body != ['true']: for atom in body: constraint.append(-atom) for (_, choice) in choices: self.__constraints.append([-choice, atom]) self.__constraints.append(constraint)
class LoopBreaker: def __call__(self,logic_program,weights,queries,evidence): self.__original_program = logic_program self.__original_weights = weights self.__new_program = LogicProgram() self.__new_weights = Weights() self.__built_rules = {} for lit in queries | evidence: self.__get_rule(lit) new_evidence = set([]) for lit in evidence: if lit.truth_value: for (new_lit,_) in self.__built_rules[lit]: new_evidence.add(new_lit) else: for (new_lit,_) in self.__built_rules[-lit]: new_evidence.add(-new_lit) return self.__new_program, self.__new_weights, new_evidence def __get_rule(self,lit,ancestors=set([])): if lit.truth_value: atom = lit else: atom = -lit ancestors = set([]) for (new_atom,cycles) in self.__built_rules.get(atom,[]): if cycles <= ancestors: break else: (new_atom,cycles) = self.__build_rule(atom,ancestors) if lit.truth_value: return (new_atom,cycles) else: return (-new_atom,cycles) def __build_rule(self,atom,ancestors): if atom in self.__original_program: all_new_rules = [] all_new_cycles = set([]) for rule in self.__original_program[atom]: if not rule & ancestors: new_cycles = set([]) new_rule = set([]) for lit in rule: (new_lit,cycles) = self.__get_rule(lit,ancestors | set([atom])) if new_lit: new_cycles = new_cycles | cycles new_rule.add(new_lit) else: new_cycles = cycles break else: all_new_rules.append(new_rule) all_new_cycles = all_new_cycles | new_cycles else: all_new_cycles = all_new_cycles | (rule & ancestors) all_new_cycles = all_new_cycles - set([atom]) if all_new_rules: if all_new_cycles: new_atom = Literal(atom.atom + '_' + str(len(self.__built_rules.get(atom,[]))),True) else: new_atom = atom self.__new_weights[new_atom] = self.__original_weights[atom] self.__new_weights[-new_atom] = self.__original_weights[-atom] for rule in all_new_rules: self.__new_program.add_rule(new_atom, rule) result = (new_atom,all_new_cycles) if atom in self.__built_rules: self.__built_rules[atom].append(result) else: self.__built_rules[atom] = [result] return result else: return (None,all_new_cycles) else: self.__new_weights[atom] = self.__original_weights[atom] self.__new_weights[-atom] = self.__original_weights[-atom] result = (atom,set([])) self.__built_rules[atom] = [result] return result