예제 #1
0
def sorted_apply(sdd_list, manager, apply_func):
    """
    Performs an apply operation on a list of sdds. Does this sorted in the sense that two smaller sdds will be
    applied before applying to larger sdds
    :param sdd_list: the sdds
    :param manager: the manager
    :param apply_func: an apply function (conjoin or disjoin); this function must increase reference count of its result
    :return: An SDD: the result of the apply. This SDD has +1 reference count.
    """
    for sdd in sdd_list:
        sddm.sdd_ref(sdd, manager)
    while len(sdd_list) > 2:
        sdd_list = sort_sdds(sdd_list)
        sdd1 = sdd_list[0]
        sdd2 = sdd_list[1]
        new = apply_func([sdd1, sdd2], manager)
        sdd_list.remove(sdd1)
        sddm.sdd_deref(sdd1, manager)
        sdd_list.remove(sdd2)
        sddm.sdd_deref(sdd2, manager)
        sdd_list.append(new)

    result = apply_func(sdd_list, manager)
    for sdd in sdd_list:
        sddm.sdd_deref(sdd, manager)
    return result
예제 #2
0
    def first_iteration(self, parameters):
        """ Initialises the compiler with a set of parameters
        Ensures that for each SDD in the image of lit2sdd, the reference count is one.
        :param parameters: the set of "open" atoms, aka parameters of the logic program
        :return: nothing
        """
        self.manager = sddm.sdd_manager_create(len(parameters), 1)
        largest_atom_num_used = 0
        #print("=========================== In the first iteration: =============================")
        for param in parameters:
            largest_atom_num_used += 1
            self.param2sddNum[param] = largest_atom_num_used
            sdd4lit = sddm.sdd_manager_literal(largest_atom_num_used, self.manager)
            self.lit2sdd[param] = sdd4lit
            sdd4neglit = sdd_negate(sdd4lit, self.manager)
            self.lit2sdd[param.negate()] = sdd4neglit
            sddm.sdd_ref(sdd4lit, self.manager)
            sddm.sdd_ref(sdd4neglit, self.manager)

            #sddm.sdd_save_as_dot(str(largest_atom_num_used),sdd4lit)
            #sddm.sdd_save_as_dot("not_"+str(largest_atom_num_used),sdd4neglit)

        #print(self.lit2sdd,len(self.lit2sdd))
        #print(sddm.sdd_manager_size(self.manager))
        #print("===========================END In the first iteration: =============================")


        return
예제 #3
0
def sdd_negate(sdd, manager):
    """
    Negates the input sdd
    :param sdd: The sdd to negate
    :param manager: the manager managing the input sdd
    :return: An SDD: the negation of the input sdd. This SDD has +1 reference count.
    """
    result = sddm.sdd_negate(sdd, manager)
    sddm.sdd_ref(result, manager)
    return result
예제 #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
예제 #5
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
예제 #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
예제 #7
0
def sdd_conjoin(sdd_list, manager):
    """
    Conjoins 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 conjunction of the input sdds. This SDD has +1 reference count.
    """

    #print("lenth of sdd_list = ",len(sdd_list))


    ####try divide and conquer, auto_SDD minimization
    '''if sdd_list is None:
        print("sdd_list is None")
        exit(0)
    elif len(sdd_list) == 1:
        alpha = sddm.sdd_manager_true(manager)
        beta = sddm.sdd_conjoin(alpha,sdd_list[0],manager)
        sddm.sdd_ref(beta, manager)
        sddm.sdd_deref(alpha, manager)
        alpha = beta
        sddm.sdd_ref(sdd_list[0], manager)

        return sdd_list[0]
    else:
        mid = len(sdd_list)//2
        left = sdd_conjoin(sdd_list[:mid], manager)
        right = sdd_conjoin(sdd_list[mid:], manager)


        bigger =  sddm.sdd_conjoin(left, right, manager)
        sddm.sdd_deref(left, manager)
        sddm.sdd_deref(right, manager)
        sddm.sdd_ref(bigger, manager)

        return bigger'''


    alpha = sddm.sdd_manager_true(manager)
    for sdd in sdd_list:
        beta = sddm.sdd_conjoin(alpha, sdd, manager)
        sddm.sdd_ref(beta, manager)
        sddm.sdd_deref(alpha, manager)
        alpha = beta

    return alpha
예제 #8
0
def sdd_forall(variables, sdd, manager):
    """
    Returns the formula
        \forall v_1, v_2, ..., v_n: sdd
    where v_i are the vars in vars
    :param variables: variables to quantify universally over
    :param sdd: the sdd to quantify
    :param manager: a manager managing both the sdd and vars
    :return: The resulting SDD. This SDD has +1 reference count
    """
    result = sdd
    sddm.sdd_ref(result, manager)
    for var in variables:
        newresult = sddm.sdd_forall(var, result, manager)
        sddm.sdd_ref(newresult, manager)
        sddm.sdd_deref(result, manager)
        result = newresult
    return result
예제 #9
0
 def get_literal_sdd_leaf(self, lit):
     """
     Returns an SDD representing the literal value.
     In case of a negated literal, returns the negation of the sdd representing the underlying atom
     :param lit: the literal to represent
     :return: An sdd representing this literal. Increases the reference count of this sdd by one
     """
     negated = lit.negated
     if negated:
         lit = lit.negate()
     num = self.get_sdd_var_num(lit)
     result = sddm.sdd_manager_literal(num, self.manager)
     sddm.sdd_ref(result, self.manager)
     if negated:
         newresult = sdd_negate(result, self.manager)
         sddm.sdd_deref(result, self.manager)
         result = newresult
     return result
예제 #10
0
    def get_entire_program_as_sdd(self):
        """
        Returns an SDD representing the entire logic program.
        :return: an SDD representing the entire logic program
        """
        if self._entire_program_as_sdd is not None:
            return self._entire_program_as_sdd

        equivalences = []

        for atom, sdd in self.atom2sdd.items():
            sdd_var_num = self.get_sdd_var_num(atom)
            sdd4atom = sddm.sdd_manager_literal(sdd_var_num, self.manager)
            sddm.sdd_ref(sdd4atom, self.manager)
            equiv = sdd_equiv(sdd4atom, sdd, self.manager)
            sddm.sdd_deref(sdd4atom, self.manager)
            equivalences.append(equiv)

        equivalences.append(self.constraint)
        sddm.sdd_ref(self.constraint, self.manager)

        equivalences = sort_sdds(equivalences)




        result = sdd_conjoin(equivalences, self.manager)



        for sdd in equivalences:
            sddm.sdd_ref(sdd, self.manager)

        self._entire_program_as_sdd = result
        return result
예제 #11
0
def sdd_equiv(sdd1, sdd2, manager):
    """
    Returns the sdd: sdd1 <=> sdd2
    :param sdd1: An input SDD
    :param sdd2: An input SDD
    :param manager: the manager managing the input sdds
    :return: An SDD: the sdd representing sdd1 <=> sdd2. This SDD has +1 reference count.
    """

    """
    sdd1n = sdd_negate(sdd1, manager)
    sddm.sdd_ref(sdd1n, manager)
    sdd2n = sdd_negate(sdd2, manager)
    sddm.sdd_ref(sdd2n, manager)
    sdde1 = sdd_conjoin([sdd1, sdd2], manager)
    sddm.sdd_ref(sdde1, manager)
    sdde2 = sdd_conjoin([sdd1n, sdd2n], manager)
    sddm.sdd_ref(sdde2, manager)
    sddequiv = sdd_disjoin([sdde1, sdde2], manager)
    sddm.sdd_ref(sddequiv, manager)
    """

    sdd1n = sdd_negate(sdd1, manager)
    sddm.sdd_ref(sdd1n, manager)
    sdd2n = sdd_negate(sdd2, manager)
    sddm.sdd_ref(sdd2n, manager)
    sdde1 = sdd_disjoin([sdd1, sdd2n], manager)
    sddm.sdd_ref(sdde1, manager)
    sdde2 = sdd_disjoin([sdd1n, sdd2], manager)
    sddm.sdd_ref(sdde2, manager)
    sddequiv = sdd_conjoin([sdde1, sdde2], manager)
    sddm.sdd_ref(sddequiv, manager)

    sddm.sdd_deref(sdd1n, manager)
    sddm.sdd_deref(sdd2n, manager)
    sddm.sdd_deref(sdde1, manager)
    sddm.sdd_deref(sdde2, manager)
    return sddequiv