예제 #1
0
def compile_tree(node,
                 tree_state,
                 sdd_state,
                 label="0",
                 st=None,
                 path_sdd=None):
    if st is None: st = ""
    mgr = sdd_state.manager
    if path_sdd is None:
        path_sdd = sdd.sdd_manager_true(mgr)

    tree = tree_state.tree
    children = tree.successors(node)
    if len(children) == 0:
        node_label = node.attr['label']
        node_label = node_label.split(':')[-1].strip().split(' ')[0]
        if label == node_label:
            # disjoin path
            #print st
            alpha = sdd.sdd_disjoin(sdd_state.alpha, path_sdd, mgr)
            sdd.sdd_deref(sdd_state.alpha, mgr)
            sdd.sdd_ref(alpha, mgr)
            sdd_state.alpha = alpha
    else:
        for child in children:
            edge = tree.get_edge(node, child)
            var = node.attr['label'].split(' ')[-1]
            val = edge.attr['label'].split(' ')[-1]
            child_st = st + "%s:%s " % (var, val)

            # extend path
            base_var = "_".join(var.split('_')[:-1]) + "_%d"
            cur_index = int(var.split('_')[-1])
            low_index, high_index = 0, tree_state.constraint_info[base_var][0]

            beta = sdd.sdd_manager_false(mgr)
            if val == ">=":
                for i in xrange(cur_index + 1, high_index):
                    sdd_lit = tree_state.domain[base_var % i]
                    beta = sdd.sdd_disjoin(
                        beta, sdd.sdd_manager_literal(sdd_lit, mgr), mgr)
            else:  # val == "<"
                for i in xrange(low_index, cur_index + 1):
                    sdd_lit = tree_state.domain[base_var % i]
                    beta = sdd.sdd_disjoin(
                        beta, sdd.sdd_manager_literal(sdd_lit, mgr), mgr)

            sdd_var = tree_state.domain[var]
            new_path_sdd = sdd.sdd_conjoin(path_sdd, beta, mgr)
            sdd_state.used_vars.add(sdd_var)

            child_st = st + "%s:%s " % (var, val)
            sdd.sdd_ref(new_path_sdd, mgr)
            compile_tree(child,
                         tree_state,
                         sdd_state,
                         label=label,
                         st=child_st,
                         path_sdd=new_path_sdd)
            sdd.sdd_deref(new_path_sdd, mgr)
예제 #2
0
def _encode_graph(g,manager):

    # init structures
    cache = defaultdict(dict)
    base = sdd.sdd_manager_true(manager)

    sink = g.nodes[-1]
    alpha = _encode_grid_aux(g.source,sink,g.nodes,g,manager,
                             base=base,cache=cache,verbose=False)

    # deref everything in cache
    for key in cache:
        beta = cache[key]
        sdd.sdd_deref(beta,manager)

    #sdd.sdd_ref(alpha,manager)

    return alpha
예제 #3
0
def is_monotone(alpha, manager):
    """ A function alpha is monotone iff f|~x |= f|x for all X.
    """
    result = True
    var_count = sdd.sdd_manager_var_count(manager)
    sdd.sdd_ref(alpha, manager)
    for x in xrange(1, var_count + 1):
        f_x = sdd.sdd_condition(x, alpha, manager)
        sdd.sdd_ref(f_x, manager)
        f_nx = sdd.sdd_condition(-x, alpha, manager)
        sdd.sdd_ref(f_nx, manager)
        # f|~x |= f|x iff f|~x ^ f|x == f|~x
        f_both = sdd.sdd_conjoin(f_x, f_nx, manager)
        if f_both != f_x:
            result = False
        sdd.sdd_deref(f_x, manager), sdd.sdd_deref(f_nx, manager)
        if result is False: break
    sdd.sdd_deref(alpha, manager)
    return result
예제 #4
0
 def deref(self, *nodes):
     for node in nodes:
         sdd.sdd_deref(node, self.__manager)
예제 #5
0
def run():
    with timer.Timer("reading dataset"):
        dataset = util.read_binary_dataset(test_filename)
        domain = util.read_header(test_filename)
        '''
        if OPTIONS.majority_circuit_opt:
            l = len(domain)
            for k in xrange(num_trees):
                domain["Tree_%d" % k] = l+k
        '''

    with timer.Timer("initializing manager"):
        # start sdd manager
        var_count = len(domain) - 1
        vtree = sdd.sdd_vtree_new(var_count, "balanced")
        manager = sdd.sdd_manager_new(vtree)
        #sdd.sdd_manager_auto_gc_and_minimize_on(manager)
        #sdd.sdd_manager_auto_gc_and_minimize_off(manager)
        sdd_state = SddState(vtree, manager)

    with timer.Timer("reading constraints"):
        constraint_sdd, constraint_info = encode_logical_constraints(
            constraint_filename, manager, domain)
        sdd.sdd_ref(constraint_sdd, manager)

    with timer.Timer("reading trees"):
        tree_states = []
        for filename in sorted(glob.glob(tree_basename.replace('%d', '*'))):
            tree = pygv.AGraph(filename)
            tree_state = TreeState(tree, domain, constraint_info)
            tree_states.append(tree_state)
            #tree.layout(prog='dot')
            #tree.draw(filename+".png")
        #num_trees = len(tree_states)

    with timer.Timer("compiling trees"):
        forest_sdds, _ = izip(*forest_sdds_iter(tree_states, sdd_state))
        #forest_sdds = list(forest_sdds_iter(tree_states,sdd_state))

        forest_sdds = [
            (tree_state, tree_sdd)
            for tree_state, tree_sdd in zip(tree_states, forest_sdds)
        ]
        cmpf = lambda x, y: cmp(sdd.sdd_size(x[1]), sdd.sdd_size(y[1]))
        forest_sdds.sort(cmp=cmpf)
        tree_states = [tree_state for tree_state, tree_sdd in forest_sdds]

        #ACACAC
        sdd.sdd_manager_auto_gc_and_minimize_off(manager)
        sdd.sdd_manager_minimize_limited(manager)
        stats = SddSizeStats()
        for tree_state, tree_sdd in forest_sdds:
            stats.update(tree_sdd)
            sdd.sdd_deref(tree_sdd, manager)
        sdd.sdd_manager_garbage_collect(manager)
        forest_sdds, used_vars_list = izip(
            *forest_sdds_iter(tree_states, sdd_state))
    print stats

    with timer.Timer("compiling all", prefix="| "):
        alpha = compile_all(forest_sdds, used_vars_list, num_trees, domain,
                            manager, constraint_sdd)

    with timer.Timer("evaluating"):
        msg = util.evaluate_dataset_all_sdd(dataset, alpha, manager)
    print "|     trees : %d" % num_trees
    print "--- evaluating majority vote on random forest (compiled):"
    print msg
    print "|  all size :", sdd.sdd_size(alpha)
    print "|  all count:", sdd.sdd_count(alpha)
    print " model count:", sdd.sdd_global_model_count(alpha, manager)

    with timer.Timer("checking monotonicity"):
        result = is_monotone(alpha, manager)
    print "Is monotone?", result

    #for tree_sdd in forest_sdds: sdd.sdd_deref(tree_sdd,manager)
    print "===================="
    print "before garbage collecting..."
    print "live size:", sdd.sdd_manager_live_count(manager)
    print "dead size:", sdd.sdd_manager_dead_count(manager)
    print "garbage collecting..."
    sdd.sdd_manager_garbage_collect(manager)
    print "live size:", sdd.sdd_manager_live_count(manager)
    print "dead size:", sdd.sdd_manager_dead_count(manager)

    vtree = sdd.sdd_manager_vtree(manager)
    print "Writing sdd file %s and vtree file %s" % (sdd_filename,
                                                     vtree_filename)
    sdd.sdd_save(sdd_filename, alpha)
    sdd.sdd_vtree_save(vtree_filename, vtree)

    print "Writing constraint sdd file %s and constraint vtree file %s" % (
        constraint_sdd_filename, constraint_vtree_filename)
    sdd.sdd_save(constraint_sdd_filename, constraint_sdd)
    sdd.sdd_vtree_save(constraint_vtree_filename, vtree)
예제 #6
0
def compile_all(forest_sdds,
                used_vars_list,
                num_trees,
                domain,
                manager,
                constraint_sdd=None):
    half = int(math.ceil(num_trees / 2.0))
    true_sdd = sdd.sdd_manager_true(manager)
    false_sdd = sdd.sdd_manager_false(manager)
    last_size = 2**16

    if not constraint_sdd:
        constraint_sdd = sdd.sdd_manager_true(manager)
    true_sdd = constraint_sdd

    sdd.sdd_ref(true_sdd, manager)

    to_compile_sdds = [tree_sdd for tree_sdd in forest_sdds]
    used_vars_list = [used_vars for used_vars in used_vars_list]
    '''
    if OPTIONS.majority_circuit_opt:
        majority_sdds = [sdd.sdd_manager_literal(domain["Tree_%d" % i], manager) for i in xrange(num_trees)]    
        for single_sdd in majority_sdds:
            sdd.sdd_ref(single_sdd, manager)
        to_compile_sdds = majority_sdds
        used_vars_list = [set() for _ in forest_sdds]
    '''

    cur = [true_sdd, false_sdd]
    used_vars = set()

    for k in xrange(num_trees):
        last, cur = cur, []

        tree_index = pick_next_tree(used_vars_list, used_vars)
        tree_sdd = to_compile_sdds[tree_index]
        used_vars |= used_vars_list[tree_index]
        to_compile_sdds = to_compile_sdds[:tree_index] + to_compile_sdds[
            tree_index + 1:]
        used_vars_list = used_vars_list[:tree_index] + used_vars_list[
            tree_index + 1:]

        for i in xrange(min(half, k + 1) + 1):
            cur_sdd = last[i]
            #cur_sdd = sdd.sdd_conjoin(sdd.sdd_negate(tree_sdd,manager),cur_sdd,manager)
            """
            elif i+(num_trees-k) < half: # don't bother
                cur_sdd = sdd.sdd_manager_false(manager)
            """
            if i == 0:
                pass
            elif i > 0:
                alpha = sdd.sdd_conjoin(tree_sdd, last[i - 1], manager)
                sdd.sdd_deref(last[i - 1], manager)
                cur_sdd = sdd.sdd_disjoin(cur_sdd, alpha, manager)
            sdd.sdd_ref(cur_sdd, manager)
            cur.append(cur_sdd)

            if sdd.sdd_manager_dead_count(manager) >= 2 * last_size:
                sdd.sdd_manager_garbage_collect(manager)
            if sdd.sdd_manager_live_count(manager) >= 2 * last_size:
                print "*",
                sdd.sdd_manager_minimize_limited(manager)
                last_size = 2 * last_size

        if k >= half: sdd.sdd_deref(last[-2], manager)
        sdd.sdd_deref(tree_sdd, manager)
        cur.append(false_sdd)

        print "%d" % (num_trees - k),
        sys.stdout.flush()
        #print "%d/%d" % (k,num_trees)
        print "live size:", sdd.sdd_manager_live_count(manager)
        #print "dead size:", sdd.sdd_manager_dead_count(manager)
        sdd.sdd_manager_garbage_collect(manager)
        #sdd.sdd_manager_minimize_limited(manager)

    #for alpha in cur: sdd.sdd_deref(alpha,manager)
    ret = cur[-2]
    '''
    if OPTIONS.majority_circuit_opt:
        # save ret (the majority circuit)
        # save each individual tree_sdd
        vtree = sdd.sdd_manager_vtree(manager)
        majority_sdd_filename = "%s_majority.sdd" % sdd_basename
        majority_vtree_filename = "%s_majority.vtree" % sdd_basename
        print "Writing majority sdd file %s and majority vtree file %s" % (majority_sdd_filename, majority_vtree_filename)
        sdd.sdd_save(majority_sdd_filename,ret)
        sdd.sdd_vtree_save(majority_vtree_filename,vtree)

        print "Writing individual tree sdds..."
        for k,tree_sdd in enumerate(forest_sdds):
            tree_name = "tree_%d" % k
            tree_sdd_filename = "%s_majority_%s.sdd" % (sdd_basename, tree_name)
            sdd.sdd_save(tree_sdd_filename, tree_sdd)

        gamma = sdd.sdd_manager_true(manager)
        for k,tree_sdd in enumerate(forest_sdds):
            new_gamma = sdd.sdd_conjoin(gamma, tree_sdd, manager)
            sdd.sdd_ref(new_gamma, manager)
            sdd.sdd_deref(gamma, manager)
            gamma = new_gamma

            if sdd.sdd_manager_dead_count(manager) >= 2*last_size:
                sdd.sdd_manager_garbage_collect(manager)
            if sdd.sdd_manager_live_count(manager) >= 2*last_size:
                print "*",
                sdd.sdd_manager_minimize_limited(manager)
                last_size = 2*last_size

            print "%d" % k,
            sys.stdout.flush()
            print "live size:", sdd.sdd_manager_live_count(manager)
        ret = sdd.sdd_conjoin(ret, gamma, manager)
        
        #existential quantification
        print "Existential quantification..."
        exists_map = sdd.new_intArray(len(domain))
        for i in xrange(len(domain)):
            sdd.intArray_setitem(exists_map,i,0)
        for i in xrange(num_trees):
            lit = domain["Tree_%d" % i]
            sdd.intArray_setitem(exists_map,lit,1)
        ret = sdd.sdd_exists_multiple(exists_map, ret, manager)
    '''

    return ret
예제 #7
0
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
예제 #8
0
 def deref(self, *nodes):
     for node in nodes:
         assert node is not None
         sdd.sdd_deref(node, self.__manager)