def is_monotonic(alpha, mgr, num_features, constraint_sdd):

    counterexample = [[None, None] for _ in xrange(num_features)]
    for i in xrange(num_features):
        beta1 = sdd.sdd_condition(i + 1, alpha, mgr)
        beta2 = sdd.sdd_condition(-(i + 1), alpha, mgr)
        beta3 = sdd.sdd_conjoin(beta1, beta2, mgr)

        # check if f|x does not entail f|!x
        gamma = sdd.sdd_conjoin(
            sdd.sdd_conjoin(sdd.sdd_negate(beta2, mgr), beta1, mgr),
            constraint_sdd, mgr)
        model = next(models.models(gamma, sdd.sdd_manager_vtree(mgr)))
        counterexample[i][0] = [v for _, v in model.items()]
        if counterexample[i][0]:
            counterexample[i][0][i] = 1

        # check if f|!x does not entail f|x
        gamma = sdd.sdd_conjoin(
            sdd.sdd_conjoin(sdd.sdd_negate(beta1, mgr), beta2, mgr),
            constraint_sdd, mgr)
        model = next(models.models(gamma, sdd.sdd_manager_vtree(mgr)))
        counterexample[i][1] = [v for _, v in model.items()]
        if counterexample[i][1]:
            counterexample[i][1][i] = 0

    for c in counterexample:
        if c[0] and c[1]:
            return False, counterexample
    return True, counterexample
def primes_by_length(primes, pmgr, var_count):
    by_length = defaultdict(list)
    pvtree = sdd.sdd_manager_vtree(pmgr)
    for model in models.models(primes, pvtree):
        term = prime_to_dict(model, var_count)
        by_length[len(term)].append(term)
    return by_length
def run_prime_implicant_query(alpha, mgr, num_features, models_list):
    #print num_features, models_list
    for model_list in models_list:
        gamma, pmgr, pvtree2 = primes_given_term(alpha, model_list, mgr,
                                                 _primes_one_given_term)
        pvtree = sdd.sdd_manager_vtree(pmgr)
        pi_str = []

        gamma = sdd.sdd_global_minimize_cardinality(gamma, pmgr)
        for prime_model in models.models(gamma, pvtree):
            try:
                term = prime_to_dict(prime_model, num_features)
                term_str = " ".join([("*" if var not in term else
                                      "1" if term[var] == 1 else "0")
                                     for var in xrange(1, num_features + 1)])
                pi_str.append(term_str)
            except:
                pi_str = [
                    "Key error. Make sure instance is is a model of the SDD."
                ]
        pi_str.sort(key=lambda x: x.count('*'), reverse=True)

        print "Model: " + str(model_list) + ""
        print "PI explanations:"
        for pi in pi_str[:3]:
            print str(pi)

        sdd.sdd_vtree_free(pvtree2)
        sdd.sdd_manager_free(pmgr)
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)