Esempio n. 1
0
 def get_literal_value(self, lit):
     """
     Returns an SDD representing the literal value. For each literal this will be (the negation of) an sdd variable
     If an input atom has no sdd var representation yet, a new sdd variable is created
     :param lit: the literal to represent
     :return: An sdd representing this literal.
     """
     if not lit.negated:
         result = self.atom2sdd.setdefault(lit, sddm.sdd_manager_false(self.manager))
         sddm.sdd_ref(result, self.manager)
         return result
     else:
         result = self.atom2sdd.setdefault(lit.negate(), sddm.sdd_manager_false(self.manager))
         result = sdd_negate(result, self.manager)
         # Note: sdd_negate increases the reference count by one.
         return result
Esempio n. 2
0
    def compile_new_proof(self, head, new_proof):
        """
        Compiles a new proof for head
        :param head: the head whose sdd should be updated
        :param new_proof: a formula representing a new proof for head. I.e., a formula such that
        lit2sdd(head) should be updated to lit2sdd(head) | compile(new_proof)
        :return True if lit2sdd[head] has changed; False otherwise
        """

        if head not in self.lit2sdd:
            self.lit2sdd[head] = sddm.sdd_manager_false(self.manager)

        sdd_head_changed = True
        sdd_head_old = self.lit2sdd[head]

        new_sdd = compile_formula(new_proof, self.manager, self.get_literal_value)
        # new_sdd is an SDD represeting the new proof



        final_sdd = sdd_disjoin([self.lit2sdd[head], new_sdd], self.manager)
        # final_sdd is an SDD represeting the new value of lit2sdd[head]
        sddm.sdd_deref(new_sdd, self.manager)
        self.lit2sdd[head] = final_sdd

        if sdd_head_old == self.lit2sdd[head]:
            sdd_head_changed = False
        sddm.sdd_deref(sdd_head_old, self.manager)

        return sdd_head_changed
Esempio n. 3
0
 def compile_default(self, lits):
     """
     Sets the literals in lits to their default value (false) if they are not compiled yet
     :param lits: The set of literals that should have a value after calling this method
     :return:
     """
     for lit in lits:
         self.lit2sdd.setdefault(lit, sddm.sdd_manager_false(self.manager))
Esempio n. 4
0
 def get_literal_value(self, lit):
     """
     Returns an SDD representing the literal value.
     This basically looks up lit in lit2sdd, returning a false SDD in case this literal
     is not yet present in the mapping
     :param lit: the literal to represent
     :return: An sdd representing this literal. Increases the reference count of this sdd by one
     """
     result = self.lit2sdd.setdefault(lit, sddm.sdd_manager_false(self.manager))
     sddm.sdd_ref(result, self.manager)
     return result
Esempio n. 5
0
 def set_value_to(self, lit, formula):
     """
     Sets the value of lit in lit2sdd to the value obtained by compiling the formula
     :param lit: the literal whose value should change
     :param formula: the formula representing the new value of lit
     :return:
     """
     orig_value = self.lit2sdd.get(lit, sddm.sdd_manager_false(self.manager))
     new_value = compile_formula(formula, self.manager, self.get_literal_value)
     sddm.sdd_deref(orig_value, self.manager)
     self.lit2sdd[lit] = new_value
Esempio n. 6
0
def sdd_disjoin(sdd_list, manager):
    """
    Disjoins all the input sdds to one large sdd
    :param sdd_list: a list of input sdds
    :param manager: the manager managing all of the input sdds
    :return: An SDD: the disjunction of the input sdds. This SDD has +1 reference count.
    """

    import time
    alpha = sddm.sdd_manager_false(manager)
    for sdd in sdd_list:
        beta = sddm.sdd_disjoin(alpha, sdd, manager)
        sddm.sdd_ref(beta, manager)
        sddm.sdd_deref(alpha, manager)
        alpha = beta
    return alpha
Esempio n. 7
0
def compile_formula(formula, manager, get_literal_value):

    """
    Compiles the input formula for the given manager.
    :param formula: the logical formula to compile to an sdd
    :param manager: the manager managing all sdds
    :param get_literal_value: a function that returns for each literal an sdd, used to compile leafs of the formula
            this function is supposed to increase the reference count of the SDD it outputs by one!
    :return: An SDD represeting the formula. This SDD has +1 reference count.
    """
    # Flyweights doen iets raar met types. type(formula) is ground.LIterals werkt bijvoorbeeld niet.
    # Daarom de lelijke hacks
    if formula is logic.TrueForm():
        return sddm.sdd_manager_true(manager)
    elif formula is logic.FalseForm():
        return sddm.sdd_manager_false(manager)
    elif isinstance(formula, type(logic.Literal("", True))):
        result = get_literal_value(formula)
        # Note: get_literal_value does the increment of the reference count
        return result
    elif type(formula) is logic.Disjunction:
        compiled_subforms = []
        for subform in formula.subforms:
            compiled_subform = compile_formula(subform, manager, get_literal_value)
            compiled_subforms.append(compiled_subform)
        result = sdd_disjoin(compiled_subforms, manager)
        # Note: sdd_disjoin does the increment of the reference count
        for compiled_form in compiled_subforms:
            sddm.sdd_deref(compiled_form, manager)
        return result
    elif type(formula) is logic.Conjunction:
        compiled_subforms = []
        for subform in formula.subforms:
            compiled_subform = compile_formula(subform, manager, get_literal_value)
            compiled_subforms.append(compiled_subform)
        result = sdd_conjoin(compiled_subforms, manager)
        # Note: sdd_conjoin does the increment of the reference count
        for compiled_form in compiled_subforms:
            sddm.sdd_deref(compiled_form, manager)
        return result
    else:
        print(type(formula))
        raise NotImplementedError
Esempio n. 8
0
 def backup_neg_literals(self):
     """
     Backups all SDDs associated to negative literals and replaces those SDDs by "True".
     This is used to prepare a logic program for unfounded set computation.
     NOTE: if some atom is already interpreted two-valued, its negative literal will not be updated.
     :return: the set of literals whose value has changed.
     """
     changed = []
     self.backup_sdd = OrderedDict()
     for lit, sdd in self.lit2sdd.items():
         to_backup = lit.negated
         to_backup &= (sdd != sddm.sdd_manager_true(self.manager))
         true_sdd = self.lit2sdd.get(lit.negate(), sddm.sdd_manager_false(self.manager))
         neg_true_sdd = sdd_negate(true_sdd, self.manager)
         to_backup &= (sdd != neg_true_sdd)
         sddm.sdd_deref(neg_true_sdd, self.manager)
         if to_backup:
             self.backup_sdd[lit] = sdd
             changed.append(lit)
             self.lit2sdd[lit] = sddm.sdd_manager_true(self.manager)
     return changed