def run_eval_neg(filename, **other): from .data import read_data, concat, Interpretations, Instance from problog.program import PrologString # from problog.logic import AnnotatedDisjunction, Clause print("starting eval") data = read_data(filename) rules = concat(data['RULES']) engine = DefaultEngine() engine.prepare(PrologString(':- unknown(fail).')) background_pl = concat(data.get('BACKGROUND', [])) examples = data.get('!', []) examples_db = [ engine.prepare(PrologString(background_pl + example_pl)) for example_pl in examples ] instances = Interpretations( [Instance(example_db) for example_db in examples_db], PrologString(background_pl)) for rule in PrologString(rules): clause = Clause.from_logic(rule) print('Evaluation of rule:', clause) if not clause.validate(instances, engine): print('\tRule is invalid') #for ex, success in enumerate(clause.successes): # if not success: # print('\t\tExample %s:' % (ex + 1), success) else: print('\tRule is valid.')
def load_data(filename, engine=None): if engine is None: engine = DefaultEngine() engine.prepare(PrologString(':- unknown(fail).')) data = read_data(filename) background_pl = list(PrologString('\n'.join(data.get('BACKGROUND', [])))) language = CModeLanguage.load(data) background_pl += language.background examples = data.get('', []) examples_db = [ engine.prepare(background_pl + list(PrologString(example_pl))) for example_pl in examples ] instances = Interpretations( [Instance(example_db) for example_db in examples_db], background_pl) neg_examples = data.get('!', []) #print("the negative examples are {}".format("".join(neg_examples))) neg_examples_db = [ engine.prepare(background_pl + list(PrologString(neg_example_pl))) for neg_example_pl in neg_examples ] neg_instances = Interpretations( [Instance(neg_example_db) for neg_example_db in neg_examples_db], background_pl) return language, instances, neg_instances, engine
def get_labels_single_example_models(example: SimpleProgram, rules: SimpleProgram, possible_labels: Iterable[str], background_knowledge=None, debug_printing=False) -> List[str]: """ Classifies a single example and returns a list of its labels :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)) # print('\n') result_list = [] for label in possible_labels: db_to_query = db.extend() db_to_query += Term('query')(label) start_time = time.time() result = problog.get_evaluatable().create_from(db_to_query, engine=eng).evaluate() end_time = time.time() print("call time:", end_time - start_time) if result[label] > 0.5: result_list.append(label) return result_list
def _run_tests(): from problog.program import PrologString from problog.engine import DefaultEngine p = PrologString(""" coin(c1). coin(c2). 0.4::heads(C); 0.6::tails(C) :- coin(C). win :- heads(C). """) engine = DefaultEngine() db = engine.prepare(p) # tasks = [ # ([Term("win")], []), # ([Term("win")], [(Term("heads", Term("c1")), True)]), # ([Term("win")], [(Term("heads", Term("c1")), False)]), # ] # for q,e in tasks: # qs.prepare_query(q, e) # print(qs.evaluate_queries()) qs = QuerySession(engine, db) inline_queries = [" win | heads(c1).", "win | \+heads(c1).", "win."] for iq in inline_queries: q, e = qs.transform_inline_query(PrologString(iq)[0]) qs.prepare_query(q, e) result = qs.evaluate_queries() print(result)
class LabelCollector: """" IMPORTANT: * ONLY for KEYS format * has a lot of overlap with Classifier """ def __init__(self, predicate_to_query, index_of_label_var, background_knowledge=None, debug_printing=False, engine: GenericEngine = None): if engine is None: self.engine = DefaultEngine() self.engine.unknown = 1 else: self.engine = engine if background_knowledge is not None: self.db = self.engine.prepare(background_knowledge) else: self.db = None self.predicate_to_query = predicate_to_query self.labels = set() # type: Set[Label] self.index_of_label_var = index_of_label_var self.debug_printing = debug_printing def get_labels(self) -> Set[Label]: return self.labels def extract_labels(self, example_collection: ExampleCollection): raise NotImplementedError('Abstract method')
def main(): p = PrologString(""" mother_child(trude, sally). father_child(tom, sally). father_child(tom, erica). father_child(mike, tom). sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y). parent_child(X, Y) :- father_child(X, Y). parent_child(X, Y) :- mother_child(X, Y). """) sibling = Term('sibling') query_term = sibling(None, None) engine = DefaultEngine() # prepare the model for querying model_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. times_query = test_query_method1(engine, model_db, query_term) times_query_extended = test_query_method2(engine, model_db, query_term) print("average duration query:", statistics.mean(times_query), "seconds") print("average duration query:", statistics.mean(times_query_extended), "seconds")
def run_tests_with_static_methods(): from problog.program import PrologString from problog.engine import DefaultEngine from problog.logic import Term, Var p = PrologString(""" coin(c1). coin(c2). 0.4::heads(C); 0.6::tails(C) :- coin(C). win :- heads(C). """) qs, evs = ([Term("win")], [(Term("heads", Term("c1")), False)]) # For now engine = DefaultEngine() db = engine.prepare(p) labels = (LogicFormula.LABEL_QUERY, LogicFormula.LABEL_EVIDENCE_POS, LogicFormula.LABEL_EVIDENCE_NEG) lf = LogicFormula() lf = AMCQuery.ground_query_evidence(engine, db, qs, evs, lf, labels) circuit = AMCQuery.compile_to_circuit(lf, "ddnnf") prob_sr = SemiringProbability() results, ground_evidence = AMCQuery.evaluate_circuit( circuit, labels, prob_sr) print("evidence: ", ground_evidence) for r in results: print(r) print("---")
def run(self): global DEBUG_FLAG data = self.preprocess_metafunctions() if DEBUG_FLAG: self.display_preprocessed_code(data) model = PrologString(data) if DEBUG_FLAG: print '=' * 80 print "BEFORE ESCAPING" print '=' * 80 for elem in model: print clause2str(elem) print '=' * 80 model = escape_metafunctions(model) if DEBUG_FLAG: print '=' * 80 print "AFTER ESCAPING" print '=' * 80 for elem in model: print clause2str(elem) print '=' * 80 engine = DefaultEngine(label_all=True) engine.add_builtin(METAMETAFUNCTION_FUNCTOR, 2, BooleanBuiltIn(self.builtin_metafunction)) engine.add_builtin('declare', 2, BooleanBuiltIn(self.builtin_declare)) engine.add_builtin('declare', 3, BooleanBuiltIn(self.builtin_declare)) db = engine.prepare(model) if DEBUG_FLAG: print "=" * 80 print "DATABASE" print "=" * 80 for elem in db: print elem print "=" * 80 gp = LogicFormula( keep_all=True, keep_order=True, keep_duplicates=True, avoid_name_clash=True ) gp = engine.ground_all(db, target=gp) if DEBUG_FLAG: print "=" * 80 print "GROUND PROGRAM (GROUNDER)" print "=" * 80 for elem in gp.enum_clauses(): print elem print "=" * 80 clauses = [] facts = [] for clause in unescape_metafunctions(gp.enum_clauses()): if isinstance(clause, Clause): clauses.append(clause) else: facts.append(clause) query_atoms = gp._names['query'] return self.builtin_declare.declarations, clauses + facts, query_atoms
def run_test_with_query_instance(): from problog.program import PrologString from problog.engine import DefaultEngine from problog.logic import Term, Var p = PrologString(""" coin(c1). coin(c2). 0.4::heads(C); 0.6::tails(C) :- coin(C). win :- heads(C). """) from .formula_wrapper import FormulaWrapper s_qs, s_evs = ([Term("win")], [(Term("heads", Term("c1")), False)]) # For now engine = DefaultEngine() probsr = SemiringProbability() fw = FormulaWrapper(engine.prepare(p)) qobj = AMCQuery(s_qs, s_evs, fw, target_class=DDNNF, semiring=probsr) qobj.ground(engine) result, ground_evidence = qobj.evaluate(engine) print("evidence: ", ground_evidence) for r in result: print(r) print("---")
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 sample( filename, N=1, with_facts=False, oneline=False ) : pl = PrologFile(filename) engine = DefaultEngine() db = engine.prepare(pl) for i in range(0, N) : result = engine.ground_all(db, target=SampledFormula()) print ('====================') print (result.toString(db, with_facts, oneline))
def get_labels_single_example_probabilistic_models( example: SimpleProgram, rules: SimpleProgram, possible_labels: Iterable[str], background_knowledge=None, debug_printing=False) -> List[str]: """ Classifies a single example and returns a list of its labels :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)) # print('\n') query_terms = [Term('query')(label) for label in possible_labels] db_to_query = db.extend() for query_term in query_terms: db_to_query += query_term query_results = problog.get_evaluatable().create_from( db_to_query, engine=eng).evaluate() return query_results
def get_example_databases( simple_program_examples: Iterable[SimpleProgramExampleWrapper], background_knowledge: Optional[LogicProgram] = None, models=False, engine=None) -> List[ClauseDBExampleWrapper]: if engine is None: engine = DefaultEngine() engine.unknown = 1 clausedb_examples = [] # type: List[ClauseDBExampleWrapper] if background_knowledge is not None: db = engine.prepare(background_knowledge) # type: ClauseDB for example in simple_program_examples: db_example = db.extend() # type: ClauseDB for statement in example: db_example += statement example_wrapper = ClauseDBExampleWrapper(logic_program=db_example) clausedb_examples.append(example_wrapper) if example.classification_term is not None: example_wrapper.classification_term = example.classification_term if example.key is not None: example_wrapper.key = example.key if models: example_wrapper.label = example.label else: for example in simple_program_examples: db_example = engine.prepare( example.logic_program) # type: ClauseDB example_wrapper = ClauseDBExampleWrapper(logic_program=db_example) clausedb_examples.append(example_wrapper) if example.classification_term is not None: example_wrapper.classification_term = example.classification_term if example.key is not None: example_wrapper.key = example.key if models: example_wrapper.label = example.label return clausedb_examples
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 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 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
def get_full_background_knowledge_clausedb(self, engine=None) -> ClauseDB: if self.full_background_knowledge_clausedb is not None: return self.full_background_knowledge_clausedb else: if engine is None: engine = DefaultEngine() engine.unknown = 1 full_bg_kw = self.get_full_background_knowledge_simple_program() if full_bg_kw is not None: self.full_background_knowledge_clausedb = engine.prepare( full_bg_kw) # ClauseDB return self.full_background_knowledge_clausedb else: raise Exception( "No sense in making an empty ClauseDB for an empty background knowledge" )
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 _run_sl_operators_on_semiring(self, givensemiring, program=None): engine = DefaultEngine() if program == None: program = self._slproblog_program db = engine.prepare(PrologString(program)) semiring = givensemiring knowledge = get_evaluatable(None, semiring=semiring) formula = knowledge.create_from(db, engine=engine, database=db) res = formula.evaluate(semiring=semiring) ret = {} for k, v in res.items(): if isinstance(semiring, BetaSemiring): ret[k] = moment_matching(semiring.parse(v)) else: ret[k] = semiring.parse(v) return self._order_dicts(ret)
def estimate( filename, N=1 ) : from collections import defaultdict pl = PrologFile(filename) engine = DefaultEngine() db = engine.prepare(pl) estimates = defaultdict(float) counts = 0.0 for i in range(0, N) : result = engine.ground_all(db, target=SampledFormula()) for k, v in result.queries() : if v == 0 : estimates[k] += 1.0 counts += 1.0 for k in estimates : estimates[k] = estimates[k] / counts return estimates
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))
parent_child = Term('parent_child') X, Y, Z = map(Var, 'XYZ') trude, sally, tom, erica, mike = map(Term, ['trude', 'sally', 'tom', 'erica', 'mike']) # Define the program 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
class AIController(PlayerController): '''Intelligenza artificiale Contiene i metodi per la gestione delle decisioni prese dal maziere ''' ''' conoscenza del dt_problog''' conoscenza = [] ''' conoscenza del problog (calcolo inferenza) ''' conoscenza_prob = [] vincita_attuale = 0 def __init__(self, nome, soldi, prolog): '''COSTRUTTORE chiama il costruttore della superclasse PlayerController ed istanzia gli oggetti per la gestione delle query problog :type nome: string :param nome: nome del giocatore :type soldi: float :param soldi: soldi del giocatore :type prolog: PrologController :param prolog: Oggetto PrologController che estende la classe Prolog del modulo pyswip ''' super(AIController, self).__init__(nome, soldi, prolog) self.read_file(path='controller/dt_problog.pl', path1='controller/knowledge_problog.pl') self.learn() def read_file(self, path, path1): '''Legge i file .pl contenenti la conoscenza problog e crea una lista contenente tutti i predicati ''' try: with open(path) as kn_file: self.conoscenza = kn_file.read() with open(path1) as kn_file: for row in kn_file: self.conoscenza_prob.append(row.rstrip('\n')) self.conoscenza_prob = list( filter(('').__ne__, self.conoscenza_prob)) except Exception as e: print(e) def learn(self): '''Construisce gli oggetti problog per la valutazione dell'inferenza''' try: knowledge_str = '' for predicate in self.conoscenza_prob: knowledge_str += predicate + '\n' knowledge_str = PrologString(knowledge_str) self.problog = DefaultEngine() self.knowledge_database = self.problog.prepare(knowledge_str) except Exception as e: print(e) def get_used_card_evidence(self, prolog): '''construisce la lista contenente le stringhe delle evidenze per il DTProblog''' ret_list = [] for card in prolog.uscite: ret_list.append('evidence(not ' + str(card) + ').\n') return ret_list def get_utility(self, prolog): '''constuisce la lista delle utility per il DTProblog''' vs_score, utility = prolog.get_utility() ret_list = [] for i in range(len(vs_score)): ret_list.append( f'utility(vinco({self.punteggio},{vs_score[i]}), {utility[i]}).\n' ) ret_list.append( f'utility(perdo({self.punteggio},{vs_score[i]}), {-1*utility[i]}).\n' ) ret_list.append( f'utility(sballo({self.punteggio}), {-1*prolog.get_winnable_bet()}).\n' ) vincita, _ = prolog.get_gain() prob_di_migliorare = self.query('prob_di_migliorare', self.punteggio, evidence=self.get_used_card(prolog)) util = 0 for i in range(len(vincita)): util += prob_di_migliorare * vincita[i] ret_list.append(f'utility(miglioro({self.punteggio}), {util}).\n') ''' prob_di_migliorare = self.query('prob_di_migliorare',self.punteggio,evidence = self.get_used_card(prolog)) for i in range(len(vincita)): ret_list.append(f'utility(miglioro({self.punteggio}), {prob_di_migliorare*vincita[i]}).\n') ''' return ret_list def decidi(self, prolog): '''prende la decisione''' temp = self.conoscenza evidence = self.get_used_card_evidence(prolog) for ev in evidence: temp += ev utilities = self.get_utility(prolog) for ut in utilities: temp += ut program = PrologString(temp) decisions, _, _ = dtproblog(program) for _, value in decisions.items(): if value == 1: return True print('STO\n') return False def eval_query(self, term, *args, **kwargs): try: if args: t = '\'' + term + '\'' termine = f'Term({t},' for termine_arg in args: if isinstance(termine_arg, str): termine += 'Term(\'' + termine_arg + '\')' + ',' elif isinstance(termine_arg, int) or isinstance( termine_arg, float): termine += 'Constant(' + str(termine_arg) + ')' + ',' termine = termine[:-1] + ')' query_term = eval(termine) else: query_term = Term(term) evidenze = [] if kwargs: for i in kwargs['evidence']: # Term(Constant(1),Term('spade')) i = i.replace('card(', '').replace(' ', '').replace(')', '').split(',') term_str = f'Term(\'card\',Constant({i[0]}), Term(\'{i[1]}\'))' tupla = (eval(term_str), False) evidenze.append(tupla) lf = self.problog.ground_all(self.knowledge_database, queries=[query_term], evidence=evidenze) return get_evaluatable().create_from(lf).evaluate() except Exception as e: print(e) print("QUESTA SOPRA è L'ECCEZIONE") return None def query(self, term, *args, **kwargs): # print(ai.query('prob_di_sballare', 7, evidence=['card(2,bastoni)'])) query_result = self.eval_query(term, *args, **kwargs) if len(query_result) > 1: res = [] for prob_res in query_result.values(): res.append(prob_res) else: for prob_res in query_result.values(): res = prob_res return res def get_used_card(self, prolog): '''ritorna una lista di stringhe contenenti le carte uscite''' uscite = [] for card in prolog.uscite: uscite.append(str(card)) return uscite
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)]
def sample_object(pl, N=1): engine = DefaultEngine() db = engine.prepare(pl) result = [engine.ground_all(db, target=SampledFormula()) for i in range(N)] return result, db
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) ]
class GDLIIIProblogRep(object): def __init__(self, program, fformat): #GlobalEngine self._engine = DefaultEngine() gdl_parser = GDLIIIParser() self._model = gdl_parser.output_model(program, fformat) self._baseModelFile = self._model.as_problog() self._playerList = [] self._randomIdentifier = Constant(0) #Hardcoded to give the random player a specific constant id as we apply some special rules to the random player worlds = self._initialiseKB() self._cur_node = GDLNode(worlds, GameData(self._playerList, self._randomIdentifier)) self._moveList = dict([(i,None) for i in self._playerList]) self.terminal = False def getMoveList(self): return self._moveList def undo(self, increment=1): for _ in range(increment): self._cur_node = self._cur_node.parent self._moveList = dict([(i,None) for i in self._playerList]) if self.terminal: self.terminal = False def getLegalMovesForPlayer(self, player): return self._cur_node.legal_moves[player] def _resetKnowledgeBase(self): self._kb = self._engine.prepare(self._baseModelFile) def getPlayersPossibleWorlds(self, player): return self._cur_node.worlds[player] #Assumption, term contains a single argument def extractSingleArg(self,nArg, term): return term.args[nArg] #Recommended to never call this function with step > 1 as it will likely take a long time, exponential time complexity for values of step > 0. def query(self, player, query, step=0): if step == 0: return self._cur_node.raw_query(player, Term('thinks', player, query)) else: world_set = set([self._cur_node]) for _ in range(step): #Create set of all possible move sequences from perspective of player action_set = set() for world in world_set: action_set = action_set.union(set([i for i in world.get_legal_moves()[player].keys()])) legal_moves_seqs = [{k:(None if k != player else a) for k in self._playerList} for a in action_set] #Generate possible (but not always valid) successor worlds new_set = set() for world in world_set: for actions in legal_moves_seqs: new_set.add(world.generate_speculative_worlds(player, actions)) world_set = new_set query_dict = {} size = len(world_set) for w in world_set: for (item,val) in w.raw_query(player, Term('thinks', player, query)).items(): if item in query_dict.keys(): query_dict[item] += val/size else: query_dict[item] = val/size return query_dict #Private def _initialiseKB(self): self._kb = self._engine.prepare(self._baseModelFile) initialState = \ set(map(lambda a: Term('ptrue', a[0].args[0]), self._engine.ground_all(self._kb, queries=[Term('init',Var('_'))]).get_names())) players = \ set(map(lambda a: a[0], self._engine.ground_all(self._kb, queries=[Term('role',Var('_'))]).get_names())) #Not needed, but dont care to remove right now self._step = 0 playerWorldState = {} for playerNum in map(lambda a: a.args[0], players): knowledge = map(lambda a: Term('thinks', playerNum, a.args[0]), initialState) playerPreds = initialState.union(set(knowledge)) self._playerList.append(playerNum) #Each player starts with a single initial world if playerNum == self._randomIdentifier: #Random Specific world has no thinks predicates playerWorldState[playerNum] = [RandomWorld(self._engine, self._baseModelFile, self._step, 1, initialState, playerNum)] else: playerWorldState[playerNum] = [World(self._engine, self._baseModelFile, self._step, 1, playerPreds, playerNum)] return playerWorldState def applyActionsToModelAndUpdate(self): if (None in self._moveList.values()): raise Exception("Error: Must have submitted moves for all players before proceeding") self._cur_node = self._cur_node.get_next_node(self._moveList) #Assume, there is at least one player if len([(k,v) for (k,v) in self._cur_node.raw_query(\ self._playerList[0], Term('terminal')).items() if v > 0]) > 0: self.terminal = True self._step += 1 self._moveList = dict([(i,None) for i in self._playerList]) def submitAction(self, action, player): if ( action not in self.getLegalMovesForPlayer(player)): raise Exception("{} is not a legal action".format(action)) self._moveList[player] = action
""") query = PrologString( "solve([_,_,_,2,3,_,_,_,5,_,4,2,_,9,_,_,_,3,3,_,_,_,_,8,7,_,_,_,_,7,_,_,_,_,5,6,_,9,_,7,2,_,_,1,4,5,_,_,9,_,_,_,_,_,6,_,_,_,_,2,8,4,9,_,_,8,_,_,1,_,_,7,2,5,_,_,_,9,6,_,_])." ) query1 = None for item in query: query1 = item 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)
file_name_labeled_examples = 'D:\\KUL\\KUL MAI\\Masterproef\\data\\ACE-examples-data\\ace\\mach\\keys-experimental\\mach.kb' file_name_settings = 'D:\\KUL\\KUL MAI\\Masterproef\\data\\ACE-examples-data\\ace\\mach\\keys-experimental\\mach.s' file_name_background = 'D:\\KUL\\KUL MAI\\Masterproef\\data\\ACE-examples-data\\ace\\mach\\keys-experimental\\mach.bg' 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)
bond(1,d1_13,d1_15,1). 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 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 ===")