Esempio n. 1
0
def least_flips_helper(is_model, inst, alpha, mgr, leastFlipsDict):
    sid = sdd.sdd_id(alpha)

    if sid in leastFlipsDict.keys():
        return leastFlipsDict[sid]

    flip_inst = inst[:]

    if sdd.sdd_node_is_true(alpha):
        return (my_inf, flip_inst) if is_model else (0, flip_inst)
    elif sdd.sdd_node_is_false(alpha):
        return (0, flip_inst) if is_model else (my_inf, flip_inst)

    if sdd.sdd_node_is_literal(alpha):
        level = abs(sdd.sdd_node_literal(alpha)) - 1
        if (inst[level] == 1) == (sdd.sdd_node_literal(alpha) > 0):
            if is_model:
                flip_inst[level] = 1 - inst[level]
                return (1, flip_inst)
            else:
                return (0, flip_inst)
        else:
            if is_model:
                return (0, flip_inst)
            else:
                flip_inst[level] = 1 - inst[level]
                return (1, flip_inst)

    node_elements = sdd.sdd_node_elements(alpha)
    m = sdd.sdd_node_size(alpha)
    assert m == 2

    prime1 = sdd.sddNodeArray_getitem(node_elements, 0)
    sub1 = sdd.sddNodeArray_getitem(node_elements, 1)
    prime0 = sdd.sddNodeArray_getitem(node_elements, 2)
    sub0 = sdd.sddNodeArray_getitem(node_elements, 3)

    if sdd.sdd_node_literal(prime1) < 0:
        prime1, prime0 = prime0, prime1
        sub1, sub0 = sub0, sub1

    level = abs(sdd.sdd_node_literal(prime1)) - 1

    result1, flip_inst1 = least_flips_helper(is_model, inst, sub1, mgr,
                                             leastFlipsDict)
    result0, flip_inst0 = least_flips_helper(is_model, inst, sub0, mgr,
                                             leastFlipsDict)

    if (result1 + (int)(inst[level] != 1)) < (result0 +
                                              (int)(inst[level] != 0)):
        result, flip_inst = result1 + (int)(inst[level] != 1), flip_inst1[:]
        if inst[level] == 0:
            flip_inst[level] = 1
    else:
        result, flip_inst = result0 + (int)(inst[level] != 0), flip_inst0[:]
        if inst[level] == 1:
            flip_inst[level] = 0

    leastFlipsDict[sid] = (result, flip_inst)
    return (result, flip_inst)
Esempio n. 2
0
def node_value(node, values, model):
    if sdd.sdd_node_is_true(node):
        return True
    elif sdd.sdd_node_is_false(node):
        return False
    elif sdd.sdd_node_is_literal(node):
        lit = sdd.sdd_node_literal(node)
        var = lit if lit > 0 else -lit
        lit = 1 if lit > 0 else 0
        return model[var] == lit
    else:
        sdd_id = sdd.sdd_id(node)
        return values[sdd_id]
Esempio n. 3
0
    def _to_formula(self, formula, current_node, cache=None):
        if cache is not None and int(current_node) in cache:
            return cache[int(current_node)]
        if self.get_manager().is_true(current_node):
            retval = formula.TRUE
        elif self.get_manager().is_false(current_node):
            retval = formula.FALSE
        elif sdd.sdd_node_is_literal(current_node):  # it's a literal
            lit = sdd.sdd_node_literal(current_node)
            at = self.var2atom[abs(lit)]
            node = self.get_node(at)
            if lit < 0:
                retval = -formula.add_atom(-lit,
                                           probability=node.probability,
                                           name=node.name,
                                           group=node.group)
            else:
                retval = formula.add_atom(lit,
                                          probability=node.probability,
                                          name=node.name,
                                          group=node.group)
        else:  # is decision
            size = sdd.sdd_node_size(current_node)
            elements = sdd.sdd_node_elements(current_node)
            primes = [
                sdd.sdd_array_element(elements, i)
                for i in range(0, size * 2, 2)
            ]
            subs = [
                sdd.sdd_array_element(elements, i)
                for i in range(1, size * 2, 2)
            ]

            # Formula: (p1^s1) v (p2^s2) v ...
            children = []
            for p, s in zip(primes, subs):
                p_n = self._to_formula(formula, p, cache)
                s_n = self._to_formula(formula, s, cache)
                c_n = formula.add_and((p_n, s_n))
                children.append(c_n)
            retval = formula.add_or(children)
        if cache is not None:
            cache[int(current_node)] = retval
        return retval
Esempio n. 4
0
def models(node, vtree):
    """A generator for the models of an SDD."""
    if sdd.sdd_vtree_is_leaf(vtree):
        var = sdd.sdd_vtree_var(vtree)
        if node is True or sdd.sdd_node_is_true(node):
            yield {var: 0}
            yield {var: 1}
        elif sdd.sdd_node_is_false(node):
            yield {}
        elif sdd.sdd_node_is_literal(node):
            lit = sdd.sdd_node_literal(node)
            sign = 0 if lit < 0 else 1
            yield {var: sign}
    else:
        left_vtree = sdd.sdd_vtree_left(vtree)
        right_vtree = sdd.sdd_vtree_right(vtree)
        if node is True or sdd.sdd_node_is_true(node):
            # sdd is true
            for left_model in models(True, left_vtree):
                for right_model in models(True, right_vtree):
                    yield _join_models(left_model, right_model)
        elif sdd.sdd_node_is_false(node):
            # sdd is false
            yield {}
        elif sdd.sdd_vtree_of(node) == vtree:
            # enumerate prime/sub pairs
            #elements = sdd.sdd_node_elements(node)
            elements = elements_as_list(node)
            for prime, sub in _pairs(elements):
                if sdd.sdd_node_is_false(sub): continue
                for left_model in models(prime, left_vtree):
                    for right_model in models(sub, right_vtree):
                        yield _join_models(left_model, right_model)
        else:  # gap in vtree
            if sdd.sdd_vtree_is_sub(sdd.sdd_vtree_of(node), left_vtree):
                for left_model in models(node, left_vtree):
                    for right_model in models(True, right_vtree):
                        yield _join_models(left_model, right_model)
            else:
                for left_model in models(True, left_vtree):
                    for right_model in models(node, right_vtree):
                        yield _join_models(left_model, right_model)
Esempio n. 5
0
def models(node, vtree):
    """A generator for the models of an SDD."""
    if sdd.sdd_vtree_is_leaf(vtree):
        var = sdd.sdd_vtree_var(vtree)
        if node is True or sdd.sdd_node_is_true(node):
            yield {var: 0}
            yield {var: 1}
        elif sdd.sdd_node_is_false(node):
            yield {}
        elif sdd.sdd_node_is_literal(node):
            lit = sdd.sdd_node_literal(node)
            sign = 0 if lit < 0 else 1
            yield {var: sign}
    else:
        left_vtree = sdd.sdd_vtree_left(vtree)
        right_vtree = sdd.sdd_vtree_right(vtree)
        if node is True or sdd.sdd_node_is_true(node):
            # sdd is true
            for left_model in models(True, left_vtree):
                for right_model in models(True, right_vtree):
                    yield _join_models(left_model, right_model)
        elif sdd.sdd_node_is_false(node):
            # sdd is false
            yield {}
        elif sdd.sdd_vtree_of(node) == vtree:
            # enumerate prime/sub pairs
            elements = sdd.sdd_node_elements(node)
            for prime, sub in _pairs(elements):
                if sdd.sdd_node_is_false(sub):
                    continue
                for left_model in models(prime, left_vtree):
                    for right_model in models(sub, right_vtree):
                        yield _join_models(left_model, right_model)
        else:  # gap in vtree
            if sdd.sdd_vtree_is_sub(sdd.sdd_vtree_of(node), left_vtree):
                for left_model in models(node, left_vtree):
                    for right_model in models(True, right_vtree):
                        yield _join_models(left_model, right_model)
            else:
                for left_model in models(True, left_vtree):
                    for right_model in models(node, right_vtree):
                        yield _join_models(left_model, right_model)