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)
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]
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
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)
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)