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]])
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]
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("")
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]])
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))
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)"])
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
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)]
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))
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 ===")
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)
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)
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)
# 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))
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]
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))
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) ]
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'))
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)