コード例 #1
0
ファイル: test_engine.py プロジェクト: PietroTotis/ArgProblog
    def test_anonymous_variable(self):
        """Anonymous variables are distinct"""

        program = """
            p(_,X,_) :- X = 3.

            q(1,2,3).
            q(1,2,4).
            q(2,3,5).
            r(Y) :- q(_,Y,_).

        """

        engine = DefaultEngine()
        db = engine.prepare(PrologString(program))
        self.assertEqual(
            list(
                map(
                    list,
                    engine.query(
                        db, Term("p", Constant(1), Constant(3), Constant(2))),
                )),
            [[Constant(1), Constant(3), Constant(2)]],
        )

        self.assertEqual(list(map(list, engine.query(db, Term("r", None)))),
                         [[2], [3]])
コード例 #2
0
ファイル: lfi.py プロジェクト: miguelvidex/ProbLog
def extract_evidence(pl):
    engine = DefaultEngine()
    atoms = engine.query(pl, Term('evidence', None, None))
    atoms1 = engine.query(pl, Term('evidence', None))
    atoms2 = engine.query(pl, Term('observe', None))
    for atom in atoms1 + atoms2:
        atom = atom[0]
        if atom.is_negated():
            atoms.append((-atom, Term('false')))
        else:
            atoms.append((atom, Term('true')))
    return [(at, str2bool(vl)) for at, vl in atoms]
コード例 #3
0
def do_inference(a, b, terms, program):
    engine = DefaultEngine()
    xs = engine.prepare(program)

    print("[%s]是[%s]的 --> " % (b, a), end="")
    for key in terms:
        query_term = terms[key](a, b)
        res = engine.query(xs, query_term)
        if bool(res):
            print(terms[key], end=" ")
    print("")
コード例 #4
0
    def test_compare(self) :
        """Comparison operator"""

        program = """
            morning(Hour) :- Hour >= 6, Hour =< 10.
        """

        engine = DefaultEngine()
        db = engine.prepare( PrologString(program) )

        self.assertEqual( list(map(list,engine.query(db, Term('morning', Constant(8)) ))), [[8]])
コード例 #5
0
def main(filename, output):

    model = PrologFile(filename)

    engine = DefaultEngine(label_all=True)

    with Timer("parsing"):
        db = engine.prepare(model)

    print("\n=== Database ===")
    print(db)

    print("\n=== Queries ===")
    queries = engine.query(db, Term("query", None))
    print("Queries:", ", ".join([str(q[0]) for q in queries]))

    print("\n=== Evidence ===")
    evidence = engine.query(db, Term("evidence", None, None))
    print("Evidence:", ", ".join(["%s=%s" % ev for ev in evidence]))

    print("\n=== Ground Program ===")
    with Timer("ground"):
        gp = engine.ground_all(db)
    print(gp)

    print("\n=== Acyclic Ground Program ===")
    with Timer("acyclic"):
        gp = LogicDAG.createFrom(gp)
    print(gp)

    print("\n=== Conversion to CNF ===")
    with Timer("convert to CNF"):
        cnf = CNF.createFrom(gp)

    with open(output, "w") as f:
        f.write(cnf.to_dimacs(weighted=False, names=True))
コード例 #6
0
ファイル: test_engine.py プロジェクト: PietroTotis/ArgProblog
    def test_nonground_query_ad(self):
        """Non-ground call to annotated disjunction"""

        program = """
            0.1::p(a); 0.2::p(b).
            query(p(_)).
        """

        engine = DefaultEngine()
        db = engine.prepare(PrologString(program))

        result = None
        for query in engine.query(db, Term("query", None)):
            result = engine.ground(db, query[0], result, label="query")

        found = [str(x) for x, y in result.queries()]

        self.assertCollectionEqual(found, ["p(a)", "p(b)"])
コード例 #7
0
ファイル: classification.py プロジェクト: sircanist/tilde
def get_labels_single_example_keys(example: SimpleProgram,
                                   rules: SimpleProgram,
                                   prediction_goal: Term,
                                   index_of_label_arg: int,
                                   possible_labels: Iterable[str],
                                   background_knowledge=None,
                                   debug_printing=False) -> List[str]:
    """
    Classifies a single example and returns a list of its labels
    :param prediction_goal: 
    :param example:
    :param rules:
    :param possible_labels:
    :return:
    """
    eng = DefaultEngine()
    eng.unknown = 1

    if background_knowledge is not None:
        db = eng.prepare(background_knowledge)
        for statement in example:
            db += statement
        for rule in rules:
            db += rule
    else:
        db = eng.prepare(rules)
        for statement in example:
            db += statement

    if debug_printing:
        print('\nQueried database:')
        for statement in db:
            print('\t' + str(statement))

    query_results = eng.query(db, prediction_goal)

    labels_ex = []
    for query_result in query_results:
        labels_ex.append(query_result[index_of_label_arg])
    return labels_ex
コード例 #8
0
ファイル: engine.py プロジェクト: vishalbelsare/mdp-problog
class Engine(object):
    """
    Adapter class to Problog grounding and query engine.

    :param program: a valid MDP-ProbLog program
    :type program: str
    """
    def __init__(self, program):
        self._engine = DefaultEngine()
        self._db = self._engine.prepare(PrologString(program))
        self._gp = None
        self._knowledge = None

    def declarations(self, declaration_type):
        """
        Return a list of all terms of type `declaration_type`.

        :param declaration_type: declaration type.
        :type declaration_type: str
        :rtype: list of problog.logic.Term
        """
        return [
            t[0]
            for t in self._engine.query(self._db, Term(declaration_type, None))
        ]

    def assignments(self, assignment_type):
        """
        Return a dictionary of assignments of type `assignment_type`.

        :param assignment_type: assignment type.
        :type assignment_type: str
        :rtype: dict of (problog.logic.Term, problog.logic.Constant) items.
        """
        return dict(
            self._engine.query(self._db, Term(assignment_type, None, None)))

    def get_instructions_table(self):
        """
        Return the table of instructions separated by instruction type
        as described in problog.engine.ClauseDB.

        :rtype: dict of (str, list of (node,namedtuple))
        """
        instructions = {}
        for node, instruction in enumerate(self._db._ClauseDB__nodes):
            instruction_type = str(instruction)
            instruction_type = instruction_type[:instruction_type.find('(')]
            if instruction_type not in instructions:
                instructions[instruction_type] = []
            assert (self._db.get_node(node) == instruction)  # sanity check
            instructions[instruction_type].append((node, instruction))
        return instructions

    def add_fact(self, term, probability=None):
        """
        Add a new `term` with a given `probability` to the program database.
        Return the corresponding node number.

        :param term: a predicate
        :type term: problog.logic.Term
        :param probability: a number in [0,1]
        :type probability: float
        :rtype: int
        """
        return self._db.add_fact(term.with_probability(Constant(probability)))

    def get_fact(self, node):
        """
        Return the fact in the table of instructions corresponding to `node`.

        :param node: identifier of fact in table of instructions
        :type node: int
        :rtype: problog.engine.fact
        """
        fact = self._db.get_node(node)
        if not str(fact).startswith('fact'):
            raise IndexError('Node `%d` is not a fact.' % node)
        return fact

    def add_rule(self, head, body):
        """
        Add a new rule defined by a `head` and `body` arguments
        to the program database. Return the corresponding node number.

        :param head: a predicate
        :type head: problog.logic.Term
        :param body: a list of literals
        :type body: list of problog.logic.Term or problog.logic.Not
        :rtype: int
        """
        b = body[0]
        for term in body[1:]:
            b = b & term
        rule = head << b
        return self._db.add_clause(rule)

    def get_rule(self, node):
        """
        Return the rule in the table of instructions corresponding to `node`.

        :param node: identifier of rule in table of instructions
        :type node: int
        :rtype: problog.engine.clause
        """
        rule = self._db.get_node(node)
        if not str(rule).startswith('clause'):
            raise IndexError('Node `%d` is not a rule.' % node)
        return rule

    def add_assignment(self, term, value):
        """
        Add a new utility assignment of `value` to `term` in the program database.
        Return the corresponding node number.

        :param term: a predicate
        :type term: problog.logic.Term
        :param value: a numeric value
        :type value: float
        :rtype: int
        """
        args = (term.with_probability(None), Constant(1.0 * value))
        utility = Term('utility', *args)
        return self._db.add_fact(utility)

    def get_assignment(self, node):
        """
        Return the assignment in the table of instructions corresponding to `node`.

        :param node: identifier of assignment in table of instructions
        :type node: int
        :rtype: pair of (problog.logic.Term, problog.logic.Constant)
        """
        fact = self._db.get_node(node)
        if not (str(fact).startswith('fact') and fact.functor == 'utility'):
            raise IndexError('Node `%d` is not an assignment.' % node)
        return (fact.args[0], fact.args[1])

    def add_annotated_disjunction(self, facts, probabilities):
        """
        Add a new annotated disjunction to the program database from
        a list of `facts` and its `probabilities`.
        Return a list of choice nodes.

        :param facts: list of probabilistic facts
        :type  facts: list of problog.logic.Term
        :param probabilities: list of valid individual probabilities
                              such that the total probability is less
                              than or equal to 1.0
        :type probabilities: list of float in [0.0, 1.0]
        :rtype: list of int
        """
        disjunction = [
            f.with_probability(Constant(p))
            for f, p in zip(facts, probabilities)
        ]
        self._db += AnnotatedDisjunction(heads=disjunction,
                                         body=Constant('true'))

        choices = []
        for node, term in enumerate(self._db._ClauseDB__nodes):
            if str(term).startswith('choice'):
                choices.append((term, node))

        nodes = []
        for term in disjunction:
            term = term.with_probability(None)
            for choice, node in choices:
                if term in choice.functor.args:
                    nodes.append(node)
        return nodes

    def get_annotated_disjunction(self, nodes):
        """
        Return the list of choice nodes in the table of instructions
        corresponding to `nodes`.

        :param nodes: list of node identifiers
        :type nodes: list of int
        :rtype: list of problog.engine.choice
        """
        choices = [self._db.get_node(node) for node in nodes]
        for choice in choices:
            if not str(choice).startswith('choice'):
                raise IndexError('Node `%d` is not a choice node.' % choice)
        return choices

    def relevant_ground(self, queries):
        """
        Create ground program with respect to `queries`.

        :param queries: list of predicates
        :type queries: list of problog.logic.Term
        """
        self._gp = self._engine.ground_all(self._db, queries=queries)

    def compile(self, terms=[]):
        """
        Create compiled knowledge database from ground program.
        Return mapping of `terms` to nodes in the compiled knowledge database.

        :param terms: list of predicates
        :type terms: list of problog.logic.Term
        :rtype: dict of (problog.logic.Term, int)
        """
        self._knowledge = get_evaluatable(None).create_from(self._gp)
        term2node = {}
        for term in terms:
            term2node[term] = self._knowledge.get_node_by_name(term)
        return term2node

    def evaluate(self, queries, evidence):
        """
        Compute probabilities of `queries` given `evidence`.

        :param queries: mapping of predicates to nodes
        :type queries: dict of (problog.logic.Term, int)
        :param evidence: mapping of predicate and evidence weight
        :type evidence: dictionary of (problog.logic.Term, {0, 1})
        :rtype: list of (problog.logic.Term, [0.0, 1.0])
        """
        evaluator = self._knowledge.get_evaluator(semiring=None,
                                                  evidence=None,
                                                  weights=evidence)
        return [(query, evaluator.evaluate(queries[query]))
                for query in sorted(queries, key=str)]
コード例 #9
0
ファイル: prolog_ipynotebook.py プロジェクト: sircanist/tilde
pl = SimpleProgram()
pl += mother_child(trude, sally)
pl += father_child(tom, sally)
pl += father_child(tom, erica)
pl += father_child(mike, tom)
pl += sibling(X, Y) << (parent_child(Z, X) & parent_child(Z, Y))
pl += parent_child(X, Y) << father_child(X, Y)
pl += parent_child(X, Y) << mother_child(X, Y)

engine = DefaultEngine()
db = engine.prepare(pl)


print(db)
query_term = sibling(tom, sally)
res = engine.query(db, query_term)
print ('%s? %s' % (query_term, bool(res)))

query_term = sibling(sally, erica)
res = engine.query(db, query_term)
print(res)
print ('%s? %s' % (query_term, bool(res)))

# NOTE: variables can be replaced by None of a negative number
# the difference is that each None is a different variable,
# while each variable with the same negative number is the same variable
query_term = sibling(None, None)
res = engine.query(db, query_term)

for args in res:
    print(query_term(*args))
コード例 #10
0
ファイル: constraint.py プロジェクト: PietroTotis/ArgProblog
def main(argv, handle_output=None):
    args = argparser().parse_args(argv)

    verbose = args.verbose
    filename = args.filename

    if verbose:
        debug("Loading...")
    problog_model = PrologFile(filename, factory=ConstraintFactory())

    engine = DefaultEngine()
    database = engine.prepare(problog_model)

    # Ground the constraints
    if verbose:
        debug("Grounding...")
    target = engine.ground(database,
                           Term("constraint", None, None),
                           label="constraint")

    queries = [q[0] for q in engine.query(database, Term("query", None))]
    for query in queries:
        target = engine.ground(database, query, label="query", target=target)

    if verbose > 1:
        print(target, file=sys.stderr)

    has_prob_constraint = False
    for name, index in target.get_names(label="constraint"):
        if index is not None:
            if name.args[1].functor == "ensure_prob":
                has_prob_constraint = True

    # Compile and turn into CP-problem
    if has_prob_constraint:
        if verbose:
            debug("Probabilistic constraints detected.")

        if verbose:
            debug("Compiling...")
        sdd = SDD.create_from(target)
        formula = sdd.to_formula()
        # Convert to flatzinc
        if verbose:
            debug("Converting...")
        fzn = formula_to_flatzinc_float(formula)
        sdd.clear_labeled("constraint")

        if verbose > 1:
            print(fzn, file=sys.stderr)

        # Solve the flatzinc model
        if verbose:
            debug("Solving...")
        sols = list(solve(fzn))

        has_solution = False
        for i, res in enumerate(sols):
            if verbose:
                debug("Evaluating solution %s/%s..." % (i + 1, len(sols)))
            # target.lookup_evidence = {}
            weights = sdd.get_weights()
            # ev_nodes = []
            for k, v in res.items():
                sddvar = formula.get_node(k).identifier
                sddatom = sdd.var2atom[sddvar]
                sddname = sdd.get_name(sddatom)
                weights[sddatom] = v
            for k, v in sdd.evaluate().items():
                if v > 0.0:
                    print(k, v)
            print("----------")
            has_solution = True
        if has_solution:
            print("==========")
        else:
            print("=== UNSATISFIABLE ===")

    else:
        formula = LogicDAG()
        break_cycles(target, formula)

        if verbose:
            debug("Converting...")
        fzn = formula_to_flatzinc_bool(formula)

        if verbose > 1:
            print(fzn, file=sys.stderr)

        if verbose:
            debug("Solving...")
        sols = list(solve(fzn))

        has_solution = False
        for i, res in enumerate(sols):
            if verbose:
                debug("Evaluating solution %s/%s..." % (i + 1, len(sols)))

            if verbose:
                debug("Compressing...")
            new_formula = compress(formula, res)

            if verbose:
                debug("Compiling...")
            sdd = SDD.create_from(new_formula)

            if verbose:
                debug("Evaluating...")
            for k, v in sdd.evaluate().items():
                if v > 0.0:
                    print(k, v)
            print("----------")
            has_solution = True
        if has_solution:
            print("==========")
        else:
            print("=== UNSATISFIABLE ===")
コード例 #11
0
setting_parser = SettingParser.get_key_settings_parser()
setting_parser.parse(file_name_settings)

background_knw = parse_background_knowledge(file_name_background)

examples = parse_examples_key_format_with_key(file_name_labeled_examples)

engine = DefaultEngine()
engine.unknown = 1

db = engine.prepare(background_knw)
query_body = Term('machine')(Var('A'), Var('B')) \
             & (Term('worn')(Var('A'), Var('C')) & (Term('not_replaceable')(Var('C'))))
query_head = (Term('predicateToQuery')(Var('A'), Var('C'), Var('B')))
query_rule_for_db = (query_head << query_body)
# db += query

for example in examples:
    db_example = db.extend()
    for statement in example:
        db_example += statement
    db_example += query_rule_for_db
    # for statement in db:
    #     print(statement)
    # for statement in db_example:
    #     print(statement)
    # print("query:", query_rule_for_db)
    example_satisfies_query = engine.query(db_example, query_head)
    print(example_satisfies_query)
コード例 #12
0
    def load(cls, filedata):
        engine = DefaultEngine()

        cores_l = []
        cores = []
        modes = []
        types = {}
        constants = {}
        constant_modes = []
        
        # Load the cores.
        cores_str = '\n'.join(filedata.get('CORES', []))
        for core in PrologString(cores_str):
            core_literals = Clause.literals_from_logic(core)
            cores_l.append(core_literals)

        # Load the modes.
        modes_str = '\n'.join(filedata.get('MODES', []))
        for mode_term in PrologString(modes_str):
            if mode_term.is_negated():
                mode_term = -mode_term
                modes.append((False, mode_term))
            else:
                modes.append((True, mode_term))
            for i, a in enumerate(mode_term.args):
                if cls.mode_is_constant(a):
                    constant_modes.append((mode_term.signature, i))

        # Load the types.
        all_types = set()
        types_str = '\n'.join(filedata.get('TYPES', []))
        for type_term in PrologString(types_str):
            predicate = type_term.signature
            argtypes = type_term.args
            for argtype in argtypes:
                all_types.add(argtype)
            types[predicate] = argtypes

        # Load the constants.
        constants_str = '\n'.join(filedata.get('CONSTANTS', []))
        constants_db = engine.prepare(PrologString(constants_str))
        for t in all_types:
            values = [x[0] for x in engine.query(constants_db, t(None))]
            if values:
                constants[t] = values

        # Change variables in cores
        for core_l in cores_l:
            core = []
            varreplace = {}
            vars_head = set()
            vars_body = set()
            new_vars = 0
            for lit in core_l:
                if lit.is_negated():
                    negated = True
                    lit = -lit
                else:
                    negated = False
                new_args = []
                for arg_i, arg_v in enumerate(lit.args):
                    if isinstance(arg_v, Var) or is_variable(arg_v):
                        if arg_v in varreplace:
                            new_var = varreplace[arg_v]
                            new_args.append(new_var)
                        else:
                            if lit.signature not in types:
                                raise InvalidLanguage('No type specified for predicate \'%s\'.' % lit.signature)
                            argtype = types[lit.signature][arg_i]
                            new_var = TypedVar(new_vars, argtype)
                            new_vars += 1
                            varreplace[arg_v] = new_var
                            new_args.append(new_var)
                        if negated:
                            vars_body.add(new_var)
                        else:
                            vars_head.add(new_var)
                    else:
                        new_args.append(arg_v)
                new_lit = lit(*new_args)
                if negated:
                    new_lit = -new_lit
                core.append(new_lit)
            for var in vars_head - vars_body:
                core.insert(0, -Term('#', var.type, var))
                # raise InvalidLanguage('Core rule is not range-restricted.')
            cores.append(Clause.from_list(core))

        from problog.logic import Clause as ClauseP
        background = []
        for pred, args in types.items():
            pred = pred.rsplit('/', 1)[0]
            for i, a in enumerate(args):
                argl = [None] * len(args)
                argl[i] = 0
                background.append(ClauseP(Term('#', a, 0), Term(pred, *argl)))

        # Verify the extracted information:
        #  - we need at least one core
        if not cores:
            raise InvalidLanguage('At least one core is required.')
        #  - we need at least one mode
        if not modes:
            raise InvalidLanguage('At least one mode is required.')
        #  - only + and c allowed in positive modes
        for pn, mode in modes:
            if pn:
                for arg in mode.args:
                    if cls.mode_is_add(arg):
                        raise InvalidLanguage('New variables are not allowed in head of clause: \'%s\'.' % mode)
        #  - we need types for all modes
        missing_types = []
        for _, mode in modes:
            if mode.signature not in types:
                missing_types.append(mode.signature)
        if missing_types:
            raise InvalidLanguage('Types are missing for %s.' % and_join(missing_types))

        #  - when a 'c' mode is used, we need constants for that type
        missing_constants = set()
        for cs, ci in constant_modes:
            argtype = types[cs][ci]
            if argtype not in constants:
                missing_constants.add(argtype)
        if missing_constants:
            raise InvalidLanguage('Constants are missing for type %s.' % and_join(missing_constants))

        return CModeLanguage(cores, modes, types, constants, background)
コード例 #13
0
engine = DefaultEngine()

times_query = []
times_query_extended = []

db = engine.prepare(
    p)  # This compiles the Prolog model into an internal format.
# This step is optional, but it might be worthwhile if you
#  want to query the same model multiple times.

db2 = db.extend()
db2 += Term('query')(query1)

for i in range(0, 100):
    start = timeit.default_timer()
    results = engine.query(db, query1)
    end = timeit.default_timer()
    gc.collect()
    times_query.append(end - start)
    # print([query1(*args) for args in results])
    print(results)

for i in range(0, 100):
    start = timeit.default_timer()
    query_result = problog.get_evaluatable().create_from(
        db, engine=engine).evaluate()
    end = timeit.default_timer()
    gc.collect()
    times_query_extended.append(end - start)
    print(query_result)
コード例 #14
0
ファイル: mach_prologstring.py プロジェクト: sircanist/tilde
# db logic program + example + queries
db_lp_q = db_lp.extend()
for q in query_terms:
    db_lp_q += q
# ========================================================
# db logic program + example
db_lp_q_ex = db_lp_q.extend()  # type: ClauseDB
for e in example1_prolog_string:
    db_lp_q_ex += e

# printing
for s in db_lp:
    print(s)
for s in db_lp_q:
    print(s)
for s in db_lp_q_ex:
    print(s)

query_results = problog.get_evaluatable().create_from(db_lp_q_ex,
                                                      engine=eng).evaluate()
for key in query_results:
    value = query_results[key]
    print(value)

print(query_results)

query = Term('sendback')
results = eng.query(db_lp_q_ex, query)

print('Is example 1 of class', query, ' ? :', bool(results))
コード例 #15
0
class FOIL:
    # extra terms is list of dicts: key is term name, value is the full declaration in prolog, arity is the number of variables of the term
    def __init__(self,
                 pos_examples,
                 neg_examples,
                 extra_terms=[],
                 target_name='target'):
        # Define the language of terms
        self.target = Term(target_name)
        self.equal = Term('equal')
        self.pos_examples = pos_examples
        self.neg_examples = neg_examples
        self.examples = pos_examples + neg_examples
        self.extra_terms = extra_terms
        #TODO: check extra terms arity, if greater than target arity, create more variables
        n_target_variables = len(self.examples[0])
        target_variables_names = [
            'X' + str(i) for i in range(1, n_target_variables + 1)
        ]
        self.X = list(map(Var, target_variables_names))
        constants = set()
        for example in self.examples:
            constants.update(example)
        self.c = list(map(Term, [str(constant) for constant in constants]))
        # Initialize the logic program
        self.pl = SimpleProgram()
        self.pl += self.equal(self.X[0], self.X[0])
        self.pl += self.target(*tuple(self.X))
        for extra_term in self.extra_terms:
            self.pl += PrologString(extra_term)
        self.predicates = [self.equal]  # + list(extra_terms.keys())
        self.engine = DefaultEngine()
        self.db = self.engine.prepare(self.pl)
        self.original_rule = list(self.pl)[1]
        self.new_body_literals = []
        print(list(self.pl))

    def generate_candidates(self):
        candidate_literals = []
        for predicate in self.predicates:
            # TODO: adapt to serve other predicates besides equal
            # First test each variable equal to constant
            for i_x in range(len(self.X)):
                for i_c in range(len(self.c)):
                    candidate_literals.append(
                        self.equal(self.X[i_x], self.c[i_c]))
            # Second test each variable equal to another variable
            for i_x in range(len(self.X)):
                for i_xx in range(i_x + 1, len(self.X)):
                    candidate_literals.append(
                        self.equal(self.X[i_x], self.X[i_xx]))
        return candidate_literals

    def state(self, state):
        return tuple([self.c[s_c] for s_c in state])

    def pos_neg_examples_bindings(self, rule, db):
        pos_bindings = []
        neg_bindings = []
        for i_pos in range(len(self.pos_examples)):
            query_term = rule(*self.state(self.pos_examples[i_pos]))
            res = self.engine.query(db, query_term)
            binding = bool(res)
            if binding:
                pos_bindings.append(i_pos)
        for i_neg in range(len(self.neg_examples)):
            query_term = rule(*self.state(self.neg_examples[i_neg]))
            res = self.engine.query(db, query_term)
            binding = bool(res)
            if binding:
                neg_bindings.append(i_neg)
        return pos_bindings, neg_bindings

    def add_literal_to_goal(self, literal):
        if len(self.new_body_literals) == 0:
            new_goal = self.original_rule << literal
        else:
            new_body = literal
            for l in self.new_body_literals:
                new_body = new_body & l
            new_goal = self.original_rule << new_body
        new_pl = SimpleProgram()

        new_pl += list(self.pl)[0]
        new_pl += new_goal
        new_db = self.engine.prepare(new_pl)
        return new_db, new_pl

    def foil_gain(self, literal, rule):
        # n pos and neg bindings for Rule
        p_r, n_r = self.pos_neg_examples_bindings(rule, self.db)
        new_db, _ = self.add_literal_to_goal(literal)
        # n pos and neg bindings for Rule + Literal
        p_r_l, n_r_l = self.pos_neg_examples_bindings(rule, new_db)
        t = len(set(p_r).intersection(set(p_r_l)))
        foil_gain = t * (
            log(len(p_r_l) + 1 / (len(p_r_l) + len(n_r_l) + 1), 2) -
            log(len(p_r) + 1 / (len(p_r) + len(n_r) + 1), 2))
        return foil_gain

    def run(self):
        new_rule_pos = self.pos_examples
        while len(new_rule_pos) > 0:
            rule = self.target
            new_rule_neg = self.neg_examples
            while len(new_rule_neg) > 0:
                candidate_literals = self.generate_candidates()
                foil_gains = []
                for literal in candidate_literals:
                    foil_gains.append(self.foil_gain(literal, rule))
                max_ig = max(foil_gains)
                max_ig_index = foil_gains.index(max_ig)
                new_literal = candidate_literals[max_ig_index]
                self.db, self.pl = self.add_literal_to_goal(new_literal)
                self.new_body_literals.append(new_literal)
                new_rule_pos_bind, new_rule_neg_bind = self.pos_neg_examples_bindings(
                    rule, self.db)
                new_rule_neg = [
                    self.neg_examples[neg_index]
                    for neg_index in new_rule_neg_bind
                ]
            new_rule_pos_covered = [
                self.pos_examples[pos_index] for pos_index in new_rule_pos_bind
            ]
            new_rule_pos = [
                pos for pos in new_rule_pos if pos not in new_rule_pos_covered
            ]
        return list(self.pl)[1]
コード例 #16
0
ファイル: step-by-step.py プロジェクト: Nicolas-Boltz/problog
def main(filename, with_dot, knowledge):

    dotprefix = None
    if with_dot:
        dotprefix = os.path.splitext(filename)[0] + "_"

    model = PrologFile(filename)

    engine = DefaultEngine(label_all=True)

    with Timer("parsing"):
        db = engine.prepare(model)

    print("\n=== Database ===")
    print(db)

    print("\n=== Queries ===")
    queries = engine.query(db, Term("query", None))
    print("Queries:", ", ".join([str(q[0]) for q in queries]))

    print("\n=== Evidence ===")
    evidence = engine.query(db, Term("evidence", None, None))
    print("Evidence:", ", ".join(["%s=%s" % ev for ev in evidence]))

    print("\n=== Ground Program ===")
    with Timer("ground"):
        gp = engine.ground_all(db)
    print(gp)

    if dotprefix != None:
        with open(dotprefix + "gp.dot", "w") as f:
            print(gp.toDot(), file=f)

    print("\n=== Acyclic Ground Program ===")
    with Timer("acyclic"):
        gp = gp.makeAcyclic()
    print(gp)

    if dotprefix != None:
        with open(dotprefix + "agp.dot", "w") as f:
            print(gp.toDot(), file=f)

    if knowledge == "sdd":
        print("\n=== SDD compilation ===")
        with Timer("compile"):
            nnf = SDD.createFrom(gp)

        if dotprefix != None:
            nnf.saveSDDToDot(dotprefix + "sdd.dot")

    else:
        print("\n=== Conversion to CNF ===")
        with Timer("convert to CNF"):
            cnf = CNF.createFrom(gp)

        print("\n=== Compile to d-DNNF ===")
        with Timer("compile"):
            nnf = DDNNF.createFrom(cnf)

    if dotprefix != None:
        with open(dotprefix + "nnf.dot", "w") as f:
            print(nnf.toDot(), file=f)

    print("\n=== Evaluation result ===")
    with Timer("evaluate"):
        result = nnf.evaluate()

    for it in result.items():
        print("%s : %s" % (it))
コード例 #17
0
ファイル: engine.py プロジェクト: thiagopbueno/mdp-problog
class Engine(object):
    """
    Adapter class to Problog grounding and query engine.

    :param program: a valid MDP-ProbLog program
    :type program: str
    """

    def __init__(self, program):
        self._engine = DefaultEngine()
        self._db = self._engine.prepare(PrologString(program))
        self._gp = None
        self._knowledge = None

    def declarations(self, declaration_type):
        """
        Return a list of all terms of type `declaration_type`.

        :param declaration_type: declaration type.
        :type declaration_type: str
        :rtype: list of problog.logic.Term
        """
        return [t[0] for t in self._engine.query(self._db, Term(declaration_type, None))]

    def assignments(self, assignment_type):
        """
        Return a dictionary of assignments of type `assignment_type`.

        :param assignment_type: assignment type.
        :type assignment_type: str
        :rtype: dict of (problog.logic.Term, problog.logic.Constant) items.
        """
        return dict(self._engine.query(self._db, Term(assignment_type, None, None)))

    def get_instructions_table(self):
        """
        Return the table of instructions separated by instruction type
        as described in problog.engine.ClauseDB.

        :rtype: dict of (str, list of (node,namedtuple))
        """
        instructions = {}
        for node, instruction in enumerate(self._db._ClauseDB__nodes):
            instruction_type = str(instruction)
            instruction_type = instruction_type[:instruction_type.find('(')]
            if instruction_type not in instructions:
                instructions[instruction_type] = []
            assert(self._db.get_node(node) == instruction)  # sanity check
            instructions[instruction_type].append((node, instruction))
        return instructions

    def add_fact(self, term, probability=None):
        """
        Add a new `term` with a given `probability` to the program database.
        Return the corresponding node number.

        :param term: a predicate
        :type term: problog.logic.Term
        :param probability: a number in [0,1]
        :type probability: float
        :rtype: int
        """
        return self._db.add_fact(term.with_probability(Constant(probability)))

    def get_fact(self, node):
        """
        Return the fact in the table of instructions corresponding to `node`.

        :param node: identifier of fact in table of instructions
        :type node: int
        :rtype: problog.engine.fact
        """
        fact = self._db.get_node(node)
        if not str(fact).startswith('fact'):
            raise IndexError('Node `%d` is not a fact.' % node)
        return fact

    def add_rule(self, head, body):
        """
        Add a new rule defined by a `head` and `body` arguments
        to the program database. Return the corresponding node number.

        :param head: a predicate
        :type head: problog.logic.Term
        :param body: a list of literals
        :type body: list of problog.logic.Term or problog.logic.Not
        :rtype: int
        """
        b = body[0]
        for term in body[1:]:
            b = b & term
        rule = head << b
        return self._db.add_clause(rule)

    def get_rule(self, node):
        """
        Return the rule in the table of instructions corresponding to `node`.

        :param node: identifier of rule in table of instructions
        :type node: int
        :rtype: problog.engine.clause
        """
        rule = self._db.get_node(node)
        if not str(rule).startswith('clause'):
            raise IndexError('Node `%d` is not a rule.' % node)
        return rule

    def add_assignment(self, term, value):
        """
        Add a new utility assignment of `value` to `term` in the program database.
        Return the corresponding node number.

        :param term: a predicate
        :type term: problog.logic.Term
        :param value: a numeric value
        :type value: float
        :rtype: int
        """
        args = (term.with_probability(None), Constant(1.0 * value))
        utility = Term('utility', *args)
        return self._db.add_fact(utility)

    def get_assignment(self, node):
        """
        Return the assignment in the table of instructions corresponding to `node`.

        :param node: identifier of assignment in table of instructions
        :type node: int
        :rtype: pair of (problog.logic.Term, problog.logic.Constant)
        """
        fact = self._db.get_node(node)
        if not (str(fact).startswith('fact') and fact.functor == 'utility'):
            raise IndexError('Node `%d` is not an assignment.' % node)
        return (fact.args[0], fact.args[1])

    def add_annotated_disjunction(self, facts, probabilities):
        """
        Add a new annotated disjunction to the program database from
        a list of `facts` and its `probabilities`.
        Return a list of choice nodes.

        :param facts: list of probabilistic facts
        :type  facts: list of problog.logic.Term
        :param probabilities: list of valid individual probabilities
                              such that the total probability is less
                              than or equal to 1.0
        :type probabilities: list of float in [0.0, 1.0]
        :rtype: list of int
        """
        disjunction = [ f.with_probability(Constant(p)) for f, p in zip(facts, probabilities) ]
        self._db += AnnotatedDisjunction(heads=disjunction, body=Constant('true'))

        choices = []
        for node, term in enumerate(self._db._ClauseDB__nodes):
            if str(term).startswith('choice'):
                choices.append((term, node))

        nodes = []
        for term in disjunction:
            term = term.with_probability(None)
            for choice, node in choices:
                if term in choice.functor.args:
                    nodes.append(node)
        return nodes

    def get_annotated_disjunction(self, nodes):
        """
        Return the list of choice nodes in the table of instructions
        corresponding to `nodes`.

        :param nodes: list of node identifiers
        :type nodes: list of int
        :rtype: list of problog.engine.choice
        """
        choices = [ self._db.get_node(node) for node in nodes ]
        for choice in choices:
            if not str(choice).startswith('choice'):
                raise IndexError('Node `%d` is not a choice node.' % choice)
        return choices

    def relevant_ground(self, queries):
        """
        Create ground program with respect to `queries`.

        :param queries: list of predicates
        :type queries: list of problog.logic.Term
        """
        self._gp = self._engine.ground_all(self._db, queries=queries)

    def compile(self, terms=[]):
        """
        Create compiled knowledge database from ground program.
        Return mapping of `terms` to nodes in the compiled knowledge database.

        :param terms: list of predicates
        :type terms: list of problog.logic.Term
        :rtype: dict of (problog.logic.Term, int)
        """
        self._knowledge = get_evaluatable(None).create_from(self._gp)
        term2node = {}
        for term in terms:
            term2node[term] = self._knowledge.get_node_by_name(term)
        return term2node

    def evaluate(self, queries, evidence):
        """
        Compute probabilities of `queries` given `evidence`.

        :param queries: mapping of predicates to nodes
        :type queries: dict of (problog.logic.Term, int)
        :param evidence: mapping of predicate and evidence weight
        :type evidence: dictionary of (problog.logic.Term, {0, 1})
        :rtype: list of (problog.logic.Term, [0.0, 1.0])
        """
        evaluator = self._knowledge.get_evaluator(semiring=None, evidence=None, weights=evidence)
        return [ (query, evaluator.evaluate(queries[query])) for query in sorted(queries, key=str) ]
コード例 #18
0
bond(1,d1_14,d1_16,1).
bond(1,d1_11,d1_17,7).
bond(1,d1_17,d1_18,7).
bond(1,d1_18,d1_19,7).
bond(1,d1_19,d1_20,7).
bond(1,d1_20,d1_12,7).
bond(1,d1_17,d1_21,1).
bond(1,d1_18,d1_22,1).
bond(1,d1_20,d1_23,1).
bond(1,d1_24,d1_19,1).
bond(1,d1_24,d1_25,2).
bond(1,d1_24,d1_26,2).
""")

db = engine.prepare(p)
results = engine.query(db, to_query)
print(results)
# ==== EINDE MANIER 1

# ==== MANIER 2: in stukken opgedeeld ====#
background_knowledge = PrologString("""
equals(V_0,V_0) :- true.
dmuta(V_0,pos) :- logmutag(V_0,V_1), V_1>0.
dmuta(V_0,neg) :- logmutag(V_0,V_1), V_1=<0.
sbond(V_0,V_1,V_2,V_3) :- bond(V_0,V_1,V_2,V_3); bond(V_0,V_2,V_1,V_3).
allnum(V_0,V_1,V_2,V_3) :- logmutag(V_0,V_1), logp(V_0,V_2), lumo(V_0,V_3).
""")

query = Term('dmuta')(Var('V_0'), Var('V_1')) & Term('atom')(
    Var('V_0'), Var('V_2'), Var('V_3'), Constant('27'), Var('V_4'))
コード例 #19
0
def test_problog():

    from problog.program import PrologString
    from problog import get_evaluatable

    text = open("translator_knowledgebase.prolog", 'r').read()
    pl_model = PrologString(text)
    engine = DefaultEngine()
    db = engine.prepare(pl_model)

    cbr_gene = Term("cbr_gene")
    doid = Term("doid")
    hgnc_id = Term("hgnc_id")
    hetio_cell = Term("hetio_cell")
    translates = Term("translates")
    path_to = Term("path_to")
    query_term = path_to(cbr_gene, hetio_cell, None)

    doid_to_hgnc = path_to(doid, hgnc_id, None)
    res = engine.query(db, doid_to_hgnc)
    print('%s? %s' % (doid_to_hgnc, res))

    reify = Term("reify")
    drug = Term("tS")
    res = engine.query(db, reify(drug, None, None))
    print('%s? %s' % (reify, res))

    type_matrix = Term("type_matrix")
    disease = Term("tD")
    gene = Term("tG")
    res = engine.query(db, type_matrix(disease, None, None, gene, None, None))
    print('%s? %s' % (reify, res))
    parse_terms = lambda t: list(
        map(
            lambda s: Term(s),
            str(t).replace("[", "").replace("]", "").replace(",", "").split(" "
                                                                            )))
    for r in res:
        L = parse_terms(r[2])
        R = parse_terms(r[5])
        print(" : %s %s " % (L, R))
        for anL in L:
            for anR in R:
                path = path_to(anL, anR, None)
                res = engine.query(db, path)
                if len(res) > 0:
                    print('   -- %s? => %s' % (path, res))

    a = Term("A")
    b = Term("B")
    c = Term("concat_str")
    query = Term("query")
    q = c(a, b, None)
    res = engine.query(db, q)
    print('%s? %s' % (q, res))

    a = Term("a")
    instanceof = Term("instance_of")
    q = instanceof(a, None)
    res = engine.query(db, q)
    print("%s %s" % (q, res))

    sys.exit(0)