def evaluate(self, rule, functor=None, arguments=None, ground_program=None): """Evaluate the given rule. :param rule: rule to evaluate :type rule: Rule :param functor: override rule functor :type functor: str :param arguments: query arguments (None if non-ground) :type arguments: list[tuple[Term]] | None :param ground_program: use pre-existing ground program (perform ground if None) :type ground_program: LogicFormula | None :return: dictionary of results :rtype: dict[Term, float] """ if ground_program is None: ground_program = self.ground(rule, functor, arguments) with Timer("Compiling", logger="probfoil"): knowledge = get_evaluatable().create_from(ground_program) with Timer("Evaluating", logger="probfoil"): result = knowledge.evaluate() return result
def load(self, data): """Load the settings from a data file. Initializes language, target and examples. :param data: data file :type data: DataFile """ self.language.load(data) # for types and modes if self._target is None: try: target = data.query('learn', 1)[0] target_functor, target_arity = target[0].args except IndexError: raise KnownError('No target specification found!') else: target_functor, target_arity = self._target.functor, self._target.args[ 0] target_arguments = [ Var(chr(65 + i)) for i in range(0, int(target_arity)) ] self._target = Term(str(target_functor), *target_arguments) # Find examples: # if example_mode is closed, we will only use examples that are defined in the data # this includes facts labeled with probability 0.0 (i.e. negative example) # otherwise, the examples will consist of all combinations of values appearing in the data # (taking into account type information) example_mode = data.query(Term('example_mode'), 1) if example_mode and str(example_mode[0][0]) == 'auto': types = self.language.get_argument_types(self._target.functor, self._target.arity) values = [self.language.get_type_values(t) for t in types] self._examples = list(product(*values)) elif example_mode and str(example_mode[0][0]) == 'balance': # Balancing based on count only pos_examples = [ r for r in data.query(self._target.functor, self._target.arity) ] pos_count = len(pos_examples) # get no. of positive examples types = self.language.get_argument_types(self._target.functor, self._target.arity) values = [self.language.get_type_values(t) for t in types] from random import shuffle neg_examples = list(product(*values)) shuffle(neg_examples) logger = logging.getLogger(self._logger) logger.debug('Generated negative examples:') for ex in neg_examples[:pos_count]: logger.debug(Term(self._target(*ex).with_probability(0.0))) self._examples = pos_examples + neg_examples[:pos_count] else: self._examples = [ r for r in data.query(self._target.functor, self._target.arity) ] with Timer('Computing scores', logger=self._logger): self._scores_correct = self._compute_scores_correct()
def ground(self, rule, functor=None, arguments=None): """Generate ground program for the given rule. :param rule: rule to evaluate :type rule: Rule :param functor: override rule functor :type functor: str :param arguments: query arguments (None if non-ground) :type arguments: list[tuple[Term]] | None :return: ground program :rtype: LogicFormula """ if rule is None: db = self._database target = Term(functor) else: db = self._database.extend() target = None for clause in rule.to_clauses(functor): target = clause.head db += clause if arguments is not None: queries = [target.with_args(*args) for args in arguments] else: queries = [target] with Timer("Grounding", logger="probfoil"): return self._database.engine.ground_all(db, queries=queries)
def main_mpe_semiring(args): inputfile = args.inputfile init_logger(args.verbose) if args.web: result_handler = print_result_json else: result_handler = print_result if args.output is not None: outf = open(args.output, 'w') else: outf = sys.stdout with Timer("Total"): try: pl = PrologFile(inputfile) lf = LogicFormula.create_from(model, label_all=True) prob, facts = mpe_semiring(lf, args.verbose) result_handler((True, (prob, facts)), outf) except Exception as err: trace = traceback.format_exc() err.trace = trace result_handler((False, err), outf)
def main_mpe_maxsat(args): inputfile = args.inputfile if args.web: result_handler = print_result_json else: result_handler = print_result if args.output is not None: outf = open(args.output, 'w') else: outf = sys.stdout with Timer("Total"): try: pl = PrologFile(inputfile) dag = LogicDAG.createFrom(pl, avoid_name_clash=True, label_all=True, labels=[('output', 1)]) prob, output_facts = mpe_maxsat(dag, verbose=args.verbose, solver=args.solver) result_handler((True, (prob, output_facts)), outf) except Exception as err: trace = traceback.format_exc() err.trace = trace result_handler((False, err), outf) if args.output is not None: outf.close()
def mpe_maxsat(dag, verbose=0, solver=None): if dag.queries(): print('%% WARNING: ignoring queries in file', file=sys.stderr) dag.clear_queries() logger = init_logger(verbose) logger.info('Ground program size: %s' % len(dag)) cnf = CNF.createFrom(dag) for qn, qi in cnf.evidence(): if not cnf.is_true(qi): cnf.add_constraint(TrueConstraint(qi)) queries = list(cnf.labeled()) logger.info('CNF size: %s' % cnf.clausecount) if not cnf.is_trivial(): solver = get_solver(solver) with Timer('Solving'): result = frozenset(solver.evaluate(cnf)) weights = cnf.extract_weights(SemiringProbability()) output_facts = None prob = 1.0 if result is not None: output_facts = [] if queries: for qn, qi, ql in queries: if qi in result: output_facts.append(qn) elif -qi in result: output_facts.append(-qn) for i, n, t in dag: if t == 'atom': if i in result: if not queries: output_facts.append(n.name) prob *= weights[i][0] elif -i in result: if not queries: output_facts.append(-n.name) prob *= weights[i][1] else: prob = 1.0 output_facts = [] return prob, output_facts
def mpe_maxsat(dag, verbose=0, solver=None, minpe=False): logger = init_logger(verbose) logger.info("Ground program size: %s" % len(dag)) cnf = CNF.createFrom(dag, force_atoms=True) for qn, qi in cnf.evidence(): if not cnf.is_true(qi): cnf.add_constraint(TrueConstraint(qi)) queries = list(cnf.labeled()) logger.info("CNF size: %s" % cnf.clausecount) if not cnf.is_trivial(): solver = get_solver(solver) with Timer("Solving"): result = frozenset(solver.evaluate(cnf, invert_weights=minpe)) weights = cnf.extract_weights(SemiringProbability()) output_facts = None prob = 1.0 if result is not None: output_facts = [] if queries: for qn, qi, ql in queries: if qi in result: output_facts.append(qn) elif -qi in result: output_facts.append(-qn) for i, n, t in dag: if t == "atom": if i in result: if not queries: output_facts.append(n.name) prob *= weights[i][0] elif -i in result: if not queries: output_facts.append(-n.name) prob *= weights[i][1] else: prob = 1.0 output_facts = [] return prob, output_facts
def main_mpe_maxsat(args): inputfile = args.inputfile if args.web: result_handler = print_result_json else: result_handler = print_result if args.output is not None: outf = open(args.output, "w") else: outf = sys.stdout with Timer("Total"): try: pl = PrologFile(inputfile) # filtered_pl = SimpleProgram() # has_queries = False # for statement in pl: # if 'query/1' in statement.predicates: # has_queries = True # else: # filtered_pl += statement # if has_queries: # print('%% WARNING: ignoring queries in file', file=sys.stderr) dag = LogicDAG.createFrom( pl, avoid_name_clash=True, label_all=True, labels=[("output", 1)] ) prob, output_facts = mpe_maxsat( dag, verbose=args.verbose, solver=args.solver, minpe=args.minpe ) result_handler((True, (prob, output_facts)), outf) except Exception as err: trace = traceback.format_exc() err.trace = trace result_handler((False, err), outf) if args.output is not None: outf.close()