Esempio n. 1
0
    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
Esempio n. 2
0
    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()
Esempio n. 3
0
    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)
Esempio n. 4
0
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)
Esempio n. 5
0
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()
Esempio n. 6
0
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
Esempio n. 7
0
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
Esempio n. 8
0
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()