def compute_estimated_cut(G, partition_dict, marked_nodes):
    """Compute overestimated cut value on a partial marked graph"""

    buffer_dict = dict(partition_dict)

    # cut marked nodes using strong minority
    gc.marked_nodes_could_be_cut(G, buffer_dict, marked_nodes)

    bk = set()  # decided nodes in partition_dict
    m = set()  # marked nodes in partition_dict

    for node in partition_dict:
        if partition_dict[node] == gc.MARKED:
            m.add(node)
        else:
            bk.add(node)

    b1k1 = set()  # decided and undecided nodes in buffer_dict

    for node in m:
        if buffer_dict[node] != gc.MARKED:
            b1k1.add(node)

    # nx.set_node_attributes(G, gc.PARTITION, buffer_dict)
    nx.set_node_attributes(G, buffer_dict, gc.PARTITION)

    result = (G.subgraph(m).number_of_edges() +
              gc.cut_edges(G.subgraph(bk | b1k1)) -
              gc.cut_edges(G.subgraph(b1k1)))

    return result
def complete_cut(G, partition_dict, nodes_stack):
    """Compute the maximum cut from a partial partitioned graph."""

    marked_nodes_stack = []

    while gc.could_be_cut(G, partition_dict):
        pass

    # filter away the decided nodes
    for i in nodes_stack:
        if partition_dict[i] is gc.UNDECIDED or partition_dict[i] is gc.MARKED:
            marked_nodes_stack.append(i)

    if not marked_nodes_stack:
        return partition_dict, gc.cut_edges(G, partition_dict)

    candidate = marked_nodes_stack.pop()

    # Complete cut
    blue_cut, blue_cut_val = aux_local_consistent_max_cut(
        G, dict(partition_dict), list(marked_nodes_stack), int(candidate),
        gc.BLUE)

    black_cut, black_cut_val = aux_local_consistent_max_cut(
        G, dict(partition_dict), list(marked_nodes_stack), int(candidate),
        gc.BLACK)

    if blue_cut_val > black_cut_val:
        return blue_cut, blue_cut_val
    return black_cut, black_cut_val
def aux_pruning_local_consistent_max_cut(G, partition_dict, degree_node_seq,
                                         candidate, partition_attribute):
    """Helper function to pruning_local_consistent_max_cut"""
    partition_dict[candidate] = partition_attribute

    # check consistency in the candidate and its neighbors only
    check_nodes = nx.neighbors(G, candidate)

    if not gc.is_cut_consistent(G, partition_dict, check_nodes):
        return None, 0

    if not degree_node_seq:
        return partition_dict, gc.cut_edges(G, partition_dict)

    while (gc.could_be_cut(G, partition_dict)):
        pass

    # pick a new candidate
    candidate = choose_new_candidate(partition_dict, degree_node_seq)

    blue_cut, blue_cut_val = aux_pruning_local_consistent_max_cut(
        G, dict(partition_dict), list(degree_node_seq), candidate, gc.BLUE)

    black_cut, black_cut_val = aux_pruning_local_consistent_max_cut(
        G, dict(partition_dict), list(degree_node_seq), candidate, gc.BLACK)

    if blue_cut is None and black_cut is None:
        return None, 0

    # Choose best cut according to the effective cut value
    if blue_cut_val > black_cut_val:
        return blue_cut, blue_cut_val
    return black_cut, black_cut_val
def greedy_choice(G, candidate, blue_nodes, black_nodes, visited):
    """Helper function to greedy cut"""

    G.node[candidate][gc.PARTITION] = gc.BLUE
    blue_cut_val = gc.cut_edges(nx.subgraph(G, visited))

    G.node[candidate][gc.PARTITION] = gc.BLACK
    black_cut_val = gc.cut_edges(nx.subgraph(G, visited))

    if blue_cut_val > black_cut_val:
        G.node[candidate][gc.PARTITION] = gc.BLUE
        blue_nodes.add(candidate)
    else:
        black_nodes.add(candidate)

    return blue_nodes, black_nodes
Beispiel #5
0
def ising_ground_truth(cf, info_mtx, fig_save_path=""):
    print("Running the Ground Truth...")
    ising_model = Ising_model(cf, info_mtx)
    dim = info_mtx.shape[0]
    if cf.pb_type == "maxcut":
        # 1/2\sum_edges 1-node1*node2 = 1/2*num_edges - 1/2*\sum_edges node1*node2
        graph = ising_model.graph
        start_time = time.time()
        result = ising.search(graph,
                              num_states=3,
                              show_progress=True,
                              chunk_size=0)
        end_time = time.time()
        energy = result.energies[0]
        state = decode_state(result.states[0], dim, list(range(dim)))
        num_edges = info_mtx.sum() / 2
        score = num_edges / 2 - energy
        score1 = ising_model(state)
        if abs((score - score1) / score) > 1e-2:
            raise ("Mismatched energy - result1={}, result2={}".format(
                score, score1))

        # plot the graph
        # Laplacian matrices are real and symmetric, so we can use eigh,
        # the variation on eig specialized for Hermetian matrices.
        G = laplacian_to_graph(info_mtx)

        # Laplacian matrices are real and symmetric, so we can use eigh,
        # the variation on eig specialized for Hermetian matrices.
        # method from maxCutPy
        gt.execution_time(mc.local_consistent_max_cut, 1, G)
        score1 = gc.cut_edges(G)
        if abs((score - score1)) != 0:
            raise ("Mismatched maxcut - result1={}, result2={}".format(
                score, score1))

        nbunch = G.nodes()
        for i in nbunch:
            G.node[i]['partition'] = state[i]
        gd.draw_cut_graph(G)
        plt.savefig(fig_save_path)
        plt.close()
    if cf.pb_type == "spinglass":
        # \sum_edges J_ij*node1*node2
        graph = ising_model.graph
        start_time = time.time()
        result = ising.search(graph,
                              num_states=3,
                              show_progress=True,
                              chunk_size=0)
        end_time = time.time()
        energy = result.energies[0]
        state = decode_state(result.states[0], dim, list(range(dim)))
        energy1 = ising_model(state)
        if abs((energy - energy1) / energy) > 1e-2:
            raise ("Mismatched energy - result1={}, result2={}".format(
                energy, energy1))
        score = energy
    time_elapsed = end_time - start_time
    return score, state, time_elapsed
def second_lemma(G):
    """Compute second lemma."""
    cut_edges = gc.cut_edges(G)
    uncut_edges = G.number_of_edges() - cut_edges

    numerator = float(uncut_edges - cut_edges)
    denominator = float(G.number_of_edges())

    return numerator / denominator
def compare_cut_algorithm_results(cut_alg, results_graphs, test_name=''):

    graphs_dict = gg.read_from_file(results_graphs + '.dat')
    location = cut_alg.__name__

    error_list = []
    results_dict = defaultdict(list)

    print('Algorithm: ' + str(cut_alg.__name__))
    print('Benchamark: ' + results_graphs)
    print('Starting..:)')
    print('Graph\Result Epsilon\tCurrent Epsilon')

    i = 0

    for opt_eps in sorted(graphs_dict.iterkeys()):
        for A, c in graphs_dict[opt_eps]:

            G = nx.from_numpy_matrix(A)
            cut_alg(G)

            if gc.cut_edges(G) < G.number_of_edges() / 2:
                print('####### ERROR 1 #######')
                error_list.append(G)

            if gc.are_undecided_nodes(G):
                print('####### ERROR 2 #######')
                error_list.append(G)

            this_eps = gc.compute_epsilon(G)
            print(str(i) + '\t' + str(opt_eps) + '\t' + str(this_eps))
            results_dict[opt_eps].append(this_eps)

            i += 1

    gg.write_to_file(results_dict,
                     test_name + 'results_' + results_graphs + '.dat',
                     location)

    if len(error_list) != 0:
        gg.write_to_file(error_list,
                         test_name + 'errors_' + results_graphs + '.dat',
                         location)
def brute_force_max_cut(G):
    """Compute maximum cut of a graph considering all the possible cuts."""

    max_cut_value = 0
    max_cut_ind = 0

    n = G.number_of_nodes()

    for i in range(1, 2**(n - 1)):
        cut_graph = nx.Graph(G)

        gc.binary_cut(cut_graph, i)
        value = gc.cut_edges(cut_graph)

        if value > max_cut_value:
            max_cut_value = value
            max_cut_ind = i

    gc.binary_cut(G, max_cut_ind)
    return gc.partition_dictionary(G), max_cut_value
def plot_graph(cf, L, save_path):
    if cf.pb_type == "maxcut":
        seed = cf.random_seed
        # Laplacian matrices are real and symmetric, so we can use eigh,
        # the variation on eig specialized for Hermetian matrices.
        # method from maxCutPy
        time = gt.execution_time(mc.local_consistent_max_cut, 1, G)
        result = gc.cut_edges(G)
        return time, result
    if cf.pb_type == "spinglass":

        def decode_state(state_repr, no_spins, labels):
            state = {}
            for i in range(no_spins):
                state[labels[no_spins - (i + 1)]] = 1 if state_repr % 2 else -1
                state_repr //= 2
            return state

        def check(dic, graph):
            total = 0
            for edge, energy in graph.items():
                total += energy * dic[edge[0]] * dic[edge[1]]
            return total

        J = L
        graph = {}
        shape = J.shape
        size = int(shape[0] * shape[1])
        for i in range(shape[0]):
            for j in range(shape[1]):
                graph[(i, j)] = J[i, j]
        result = ising.search(graph, num_states=4)
        print(result.energies, result.states)
        print(decode_state(result.states[0], size, list(range(size))))
        print(
            check(decode_state(result.states[0], size, list(range(size))),
                  graph))
def trevisan_approximation_alg(G):

    B, K = recursive_spectral_cut(G)
    # set blue and black nodes in graph G
    gc.set_partitions(G, B, K)
    return gc.cut_edges(G)