Exemplo n.º 1
0
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
Exemplo n.º 3
0
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)
Exemplo n.º 5
0
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')
Exemplo n.º 6
0
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")
Exemplo n.º 7
0
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("---")
Exemplo n.º 8
0
    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
Exemplo n.º 9
0
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("---")
Exemplo n.º 10
0
    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]])
Exemplo n.º 11
0
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))
Exemplo n.º 12
0
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
Exemplo n.º 13
0
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
Exemplo n.º 14
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]])
Exemplo n.º 15
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("")
Exemplo n.º 16
0
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
Exemplo n.º 17
0
    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"
                )
Exemplo n.º 18
0
    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)"])
Exemplo n.º 19
0
    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)
Exemplo n.º 20
0
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
Exemplo n.º 21
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))
Exemplo n.º 22
0
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
Exemplo n.º 23
0
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
Exemplo n.º 24
0
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))
Exemplo n.º 25
0
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)]
Exemplo n.º 26
0
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
Exemplo n.º 27
0
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) ]
Exemplo n.º 28
0
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
Exemplo n.º 29
0
""")

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)
Exemplo n.º 30
0
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)
Exemplo n.º 31
0
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'))
Exemplo n.º 32
0
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 ===")