def _primes_two(alpha, variables, cache1, cache2, pmgr, mgr): if len(variables) == 0: if sdd.sdd_node_is_false(alpha): return sdd.sdd_manager_false(pmgr) if sdd.sdd_node_is_true(alpha): return sdd.sdd_manager_true(pmgr) key = (len(variables), sdd.sdd_id(alpha)) if key in cache1: global cache_hits cache_hits += 1 if cache_hits % 1000 == 0: print "cache-hits-update:", cache_hits return cache1[key] var, remaining = variables[0], variables[1:] alpha0 = sdd.sdd_condition(-var, alpha, mgr) alpha1 = sdd.sdd_condition(var, alpha, mgr) primes0 = _primes_two(alpha0, remaining, cache1, cache2, pmgr, mgr) primes1 = _primes_two(alpha1, remaining, cache1, cache2, pmgr, mgr) qrimes0 = _keep_imp(primes0, alpha1, remaining, cache1, cache2, pmgr, mgr) qrimes1 = _keep_imp(primes1, alpha0, remaining, cache1, cache2, pmgr, mgr) gamma = sdd.sdd_disjoin(qrimes0, qrimes1, pmgr) gamma = sdd.sdd_conjoin(_sdd_unused(var, pmgr), gamma, pmgr) kappa = sdd.sdd_conjoin(primes0, sdd.sdd_negate(qrimes0, pmgr), pmgr) kappa = sdd.sdd_conjoin(kappa, _sdd_used_neg(var, pmgr), pmgr) gamma = sdd.sdd_disjoin(gamma, kappa, pmgr) kappa = sdd.sdd_conjoin(primes1, sdd.sdd_negate(qrimes1, pmgr), pmgr) kappa = sdd.sdd_conjoin(kappa, _sdd_used_pos(var, pmgr), pmgr) gamma = sdd.sdd_disjoin(gamma, kappa, pmgr) cache1[key] = gamma return gamma
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 enumerate_primes(primes, pmgr, var_count): pvtree = sdd.sdd_manager_vtree(pmgr) while not sdd.sdd_node_is_false(primes): mincard = sdd.sdd_global_minimize_cardinality(primes, pmgr) for model in models.models(mincard, pvtree): term = prime_to_dict(model, var_count) yield term primes = sdd.sdd_conjoin(primes, sdd.sdd_negate(mincard, pmgr), pmgr)
def _primes_one_given_term(alpha, variables, inst, cache, cache_dummy, pmgr, mgr): if len(variables) == 0: if sdd.sdd_node_is_true(alpha): return sdd.sdd_manager_true(pmgr) if sdd.sdd_node_is_false(alpha): return sdd.sdd_manager_false(pmgr) #add cases for true/false key = (len(variables), sdd.sdd_id(alpha)) if key in cache: return cache[key] var, remaining = variables[0], variables[1:] val, remaining_val = inst[0], inst[1:] beta2 = sdd.sdd_forall(var, alpha, mgr) gamma2 = _primes_one_given_term(beta2, remaining, remaining_val, cache, cache_dummy, pmgr, mgr) gamma9 = gamma2 pvar = 3 * (var - 1) + 1 kappa2 = sdd.sdd_manager_literal(-pvar, pmgr) gamma2 = sdd.sdd_conjoin(gamma2, kappa2, pmgr) if val == 0: beta0 = sdd.sdd_condition(-var, alpha, mgr) gamma0 = _primes_one_given_term(beta0, remaining, remaining_val, cache, cache_dummy, pmgr, mgr) gamma0 = sdd.sdd_conjoin(gamma0, sdd.sdd_negate(gamma9, pmgr), pmgr) kappa0 = sdd.sdd_conjoin(sdd.sdd_manager_literal(-(pvar + 1), pmgr), sdd.sdd_manager_literal((pvar + 2), pmgr), pmgr) kappa0 = sdd.sdd_conjoin(kappa0, sdd.sdd_manager_literal(pvar, pmgr), pmgr) gamma0 = sdd.sdd_conjoin(gamma0, kappa0, pmgr) #gamma0 = sdd.sdd_conjoin(gamma0,sdd.sdd_negate(gamma9,pmgr),pmgr) if val == 1: beta1 = sdd.sdd_condition(var, alpha, mgr) gamma1 = _primes_one_given_term(beta1, remaining, remaining_val, cache, cache_dummy, pmgr, mgr) gamma1 = sdd.sdd_conjoin(gamma1, sdd.sdd_negate(gamma9, pmgr), pmgr) kappa1 = sdd.sdd_conjoin(sdd.sdd_manager_literal((pvar + 1), pmgr), sdd.sdd_manager_literal(-(pvar + 2), pmgr), pmgr) kappa1 = sdd.sdd_conjoin(kappa1, sdd.sdd_manager_literal(pvar, pmgr), pmgr) gamma1 = sdd.sdd_conjoin(gamma1, kappa1, pmgr) #gamma1 = sdd.sdd_conjoin(gamma1,sdd.sdd_negate(gamma9,pmgr),pmgr) if val == 0: gamma = sdd.sdd_disjoin(gamma0, gamma2, pmgr) if val == 1: gamma = sdd.sdd_disjoin(gamma1, gamma2, pmgr) #gamma = sdd.sdd_disjoin(sdd.sdd_disjoin(gamma0, gamma1, pmgr), gamma2, pmgr) #if len(variables) > 60: # print len(variables), sdd.sdd_manager_count(mgr) cache[key] = gamma return gamma
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)
def _keep_imp(beta, alpha, variables, cache1, cache2, pmgr, mgr): #if len(variables) == 0: if sdd.sdd_node_is_false(beta): return sdd.sdd_manager_false(pmgr) if sdd.sdd_node_is_false(alpha): return sdd.sdd_manager_false(pmgr) if sdd.sdd_node_is_true(alpha): return beta key = (len(variables), sdd.sdd_id(alpha), sdd.sdd_id(beta)) if key in cache2: global cache_hits cache_hits += 1 #if cache_hits % 1000 == 0: print "cache-hits-update:", cache_hits return cache2[key] var, remaining = variables[0], variables[1:] pvar = 3 * (var - 1) + 1 alpha0 = sdd.sdd_condition(-var, alpha, mgr) alpha1 = sdd.sdd_condition(var, alpha, mgr) beta0 = sdd.sdd_condition(pvar, beta, pmgr) beta0 = sdd.sdd_condition(-(pvar + 1), beta0, pmgr) #beta0 = sdd.sdd_condition( (pvar+2),beta0,pmgr) beta1 = sdd.sdd_condition(pvar, beta, pmgr) beta1 = sdd.sdd_condition((pvar + 1), beta1, pmgr) #beta1 = sdd.sdd_condition(-(pvar+2),beta1,pmgr) betad = sdd.sdd_condition(-pvar, beta, pmgr) P = _keep_imp(betad, alpha0, remaining, cache1, cache2, pmgr, mgr) Q = _keep_imp(betad, alpha1, remaining, cache1, cache2, pmgr, mgr) R0 = _keep_imp(beta0, alpha0, remaining, cache1, cache2, pmgr, mgr) R1 = _keep_imp(beta1, alpha1, remaining, cache1, cache2, pmgr, mgr) gamma = sdd.sdd_conjoin(P, Q, pmgr) gamma = sdd.sdd_conjoin(_sdd_unused(var, pmgr), gamma, pmgr) kappa = sdd.sdd_conjoin(_sdd_used_neg(var, pmgr), R0, pmgr) gamma = sdd.sdd_disjoin(gamma, kappa, pmgr) kappa = sdd.sdd_conjoin(_sdd_used_pos(var, pmgr), R1, pmgr) gamma = sdd.sdd_disjoin(gamma, kappa, pmgr) cache2[key] = gamma return gamma
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 zero_normalize_sdd(alpha,alpha_vtree,vtree,manager): if sdd.sdd_node_is_false(alpha): return alpha #if vtree == sdd.sdd_vtree_of(alpha): if vtree == alpha_vtree: return alpha if sdd.sdd_vtree_is_leaf(vtree): var = sdd.sdd_vtree_var(vtree) nlit = sdd.sdd_manager_literal(-var,manager) return nlit left,right = sdd.sdd_vtree_left(vtree),sdd.sdd_vtree_right(vtree) beta_left = zero_normalize_sdd(alpha,alpha_vtree,left,manager) beta_right = zero_normalize_sdd(alpha,alpha_vtree,right,manager) beta = sdd.sdd_conjoin(beta_left,beta_right,manager) return beta
def _primes_one(alpha, variables, cache, cache_dummy, pmgr, mgr): if len(variables) == 0: if sdd.sdd_node_is_true(alpha): return sdd.sdd_manager_true(pmgr) if sdd.sdd_node_is_false(alpha): return sdd.sdd_manager_false(pmgr) #add cases for true/false key = (len(variables), sdd.sdd_id(alpha)) if key in cache: global cache_hits cache_hits += 1 #if cache_hits % 1000 == 0: print "cache-hits-update:", cache_hits return cache[key] var, remaining = variables[0], variables[1:] beta2 = sdd.sdd_forall(var, alpha, mgr) gamma2 = _primes_one(beta2, remaining, cache, cache_dummy, pmgr, mgr) gamma9 = gamma2 pvar = 3 * (var - 1) + 1 kappa2 = sdd.sdd_manager_literal(-pvar, pmgr) gamma2 = sdd.sdd_conjoin(gamma2, kappa2, pmgr) beta0 = sdd.sdd_condition(-var, alpha, mgr) gamma0 = _primes_one(beta0, remaining, cache, cache_dummy, pmgr, mgr) gamma0 = sdd.sdd_conjoin(gamma0, sdd.sdd_negate(gamma9, pmgr), pmgr) kappa0 = sdd.sdd_conjoin(sdd.sdd_manager_literal(-(pvar + 1), pmgr), sdd.sdd_manager_literal((pvar + 2), pmgr), pmgr) kappa0 = sdd.sdd_conjoin(kappa0, sdd.sdd_manager_literal(pvar, pmgr), pmgr) gamma0 = sdd.sdd_conjoin(gamma0, kappa0, pmgr) #gamma0 = sdd.sdd_conjoin(gamma0,sdd.sdd_negate(gamma9,pmgr),pmgr) beta1 = sdd.sdd_condition(var, alpha, mgr) gamma1 = _primes_one(beta1, remaining, cache, cache_dummy, pmgr, mgr) gamma1 = sdd.sdd_conjoin(gamma1, sdd.sdd_negate(gamma9, pmgr), pmgr) kappa1 = sdd.sdd_conjoin(sdd.sdd_manager_literal((pvar + 1), pmgr), sdd.sdd_manager_literal(-(pvar + 2), pmgr), pmgr) kappa1 = sdd.sdd_conjoin(kappa1, sdd.sdd_manager_literal(pvar, pmgr), pmgr) gamma1 = sdd.sdd_conjoin(gamma1, kappa1, pmgr) #gamma1 = sdd.sdd_conjoin(gamma1,sdd.sdd_negate(gamma9,pmgr),pmgr) gamma = sdd.sdd_disjoin(gamma0, gamma1, pmgr) gamma = sdd.sdd_disjoin(gamma, gamma2, pmgr) cache[key] = gamma return gamma
def is_false(self, node): return sdd.sdd_node_is_false(node)
def _encode_grid_aux(source,sink,nodes,graph,manager, base=None,cache=None,verbose=False): nodes = sorted(nodes) key = (source,tuple(nodes)) if cache and key in cache: return cache[key] if True: # INITIALIZATION FOR (S,T) PATHS if sink not in nodes: # unreachable return sdd.sdd_manager_false(manager) if len(nodes) == 1: # must be sink return sdd.sdd_manager_true(manager) if not g.reachable(source,sink,nodes): alpha = sdd.sdd_manager_false(manager) cache[key] = alpha return alpha if source == sink: # turn off all other edges alpha = sdd.sdd_manager_true(manager) sdd.sdd_ref(alpha,manager) my_nodes = list(nodes) my_nodes.remove(source) for node in my_nodes: # for all unused nodes edges = graph.incident_edges(node,nodes=nodes) sdd_vars = [ graph.edge_to_index[edge] + 1 for edge in edges ] all_false = all_false_term(sdd_vars,manager) alpha,tmp = sdd.sdd_conjoin(alpha,all_false,manager),alpha sdd.sdd_ref(alpha,manager); sdd.sdd_deref(tmp,manager) cache[key] = alpha return alpha alpha = sdd.sdd_manager_false(manager) sdd.sdd_ref(alpha,manager) else: # INITIALIZATION FOR ALL PATHS STARTING FROM S # empty graph, source should equal sink if len(nodes) == 1: return sdd.sdd_manager_true(manager) # initial case: no more paths alpha = sdd.sdd_manager_true(manager) sdd.sdd_ref(alpha,manager) my_nodes = list(nodes) my_nodes.remove(source) for node in my_nodes: # for all unused nodes edges = graph.incident_edges(node,nodes=nodes) sdd_vars = [ graph.edge_to_index[edge] + 1 for edge in edges ] all_false = all_false_term(sdd_vars,manager) alpha,tmp = sdd.sdd_conjoin(alpha,all_false,manager),alpha sdd.sdd_ref(alpha,manager); sdd.sdd_deref(tmp,manager) # after this, try to extend the paths # first, find incident edges edges = graph.incident_edges(source,nodes=nodes) sdd_vars = [ graph.edge_to_index[edge] + 1 for edge in edges ] all_false = all_false_term(sdd_vars,manager) sdd.sdd_ref(all_false,manager) # for each incident edge my_nodes = list(nodes) my_nodes.remove(source) for edge,sdd_var in zip(edges,sdd_vars): # recurse neighbor = Graph.neighbor(source,edge) gamma = _encode_grid_aux(neighbor,sink,my_nodes,graph,manager, base=base,cache=cache,verbose=verbose) if sdd.sdd_node_is_false(gamma): continue # exactly one edge on sdd_lit = sdd.sdd_manager_literal(sdd_var,manager) beta = sdd.sdd_exists(sdd_var,all_false,manager) beta = sdd.sdd_conjoin(beta,sdd_lit,manager) beta = sdd.sdd_conjoin(beta,gamma,manager) # accumulate alpha,tmp = sdd.sdd_disjoin(alpha,beta,manager),alpha sdd.sdd_ref(alpha,manager); sdd.sdd_deref(tmp,manager) sdd.sdd_deref(all_false,manager) cache[key] = alpha return alpha
def is_false(self, node): assert node is not None return sdd.sdd_node_is_false(node)