Networkx - Kernighan-Lin Извлечение дополнительной информации из исходного кода - PullRequest
0 голосов
/ 28 марта 2020

Привет, я в настоящее время использую kernighan_lin_bisection как часть библиотеки networkx для вычисления алгоритма на случайном графе, созданном с помощью заданного начального числа. Мне нужно извлекать размер обрезки на каждой итерации, я не могу найти это нигде в документации, однако есть функция для извлечения cut_size, (nx, cut_size ())

Код ниже является исходным кодом для функция kernighan lin:

def _compute_delta(G, A, B, weight):
# helper to compute initial swap deltas for a pass
delta = defaultdict(float)
for u, v, d in G.edges(data=True):
    w = d.get(weight, 1)
    if u in A:
        if v in A:
            delta[u] -= w
            delta[v] -= w
        elif v in B:
            delta[u] += w
            delta[v] += w
    elif u in B:
        if v in A:
            delta[u] += w
            delta[v] += w
        elif v in B:
            delta[u] -= w
            delta[v] -= w
return delta

def _update_delta(delta, G, A, B, u, v, weight):
    # helper to update swap deltas during single pass
    for _, nbr, d in G.edges(u, data=True):
        w = d.get(weight, 1)
        if nbr in A:
            delta[nbr] += 2 * w
        if nbr in B:
            delta[nbr] -= 2 * w
    for _, nbr, d in G.edges(v, data=True):
        w = d.get(weight, 1)
        if nbr in A:
            delta[nbr] -= 2 * w
        if nbr in B:
            delta[nbr] += 2 * w
    return delta

def _kernighan_lin_pass(G, A, B, weight):
    # do a single iteration of Kernighan–Lin algorithm
    # returns list of  (g_i,u_i,v_i) for i node pairs u_i,v_i
    multigraph = G.is_multigraph()
    delta = _compute_delta(G, A, B, weight)
    swapped = set()
    gains = []
    while len(swapped) < len(G):
        gain = []
        for u in A - swapped:
            for v in B - swapped:
                try:
                    if multigraph:
                        w = sum(d.get(weight, 1) for d in G[u][v].values())
                    else:
                        w = G[u][v].get(weight, 1)
                except KeyError:
                    w = 0
                gain.append((delta[u] + delta[v] - 2 * w, u, v))
        if len(gain) == 0:
            break
        maxg, u, v = max(gain, key=itemgetter(0))
        swapped |= {u, v}
        gains.append((maxg, u, v))
        delta = _update_delta(delta, G, A - swapped, B - swapped, u, v, weight)
    return gains

@py_random_state(4)
@not_implemented_for('directed')
def kernighan_lin_bisection(G, partition=None, max_iter=10, weight='weight',
                            seed=None):

    # If no partition is provided, split the nodes randomly into a
    # balanced partition.
    if partition is None:
        nodes = list(G)
        seed.shuffle(nodes)
        h = len(nodes) // 2
        partition = (nodes[:h], nodes[h:])
    # Make a copy of the partition as a pair of sets.
    try:
        A, B = set(partition[0]), set(partition[1])
    except:
        raise ValueError('partition must be two sets')
    if not is_partition(G, (A, B)):
        raise nx.NetworkXError('partition invalid')
    for i in range(max_iter):
        # `gains` is a list of triples of the form (g, u, v) for each
        # node pair (u, v), where `g` is the gain of that node pair.
        gains = _kernighan_lin_pass(G, A, B, weight)
        csum = list(nx.utils.accumulate(g for g, u, v in gains))
        max_cgain = max(csum)
        if max_cgain <= 0:
            break
        # Get the node pairs up to the index of the maximum cumulative
        # gain, and collect each `u` into `anodes` and each `v` into
        # `bnodes`, for each pair `(u, v)`.
        index = csum.index(max_cgain)
        nodesets = islice(zip(*gains[:index + 1]), 1, 3)
        anodes, bnodes = (set(s) for s in nodesets)
        A |= bnodes
        A -= anodes
        B |= anodes
        B -= bnodes
    return A, B

Я пытался просто использовать _kernighan_lin_pass, но я не уверен, какими будут мои другие входные данные, и не смог найти это в документах для расшифровки, поэтому мое следующее решение было попытаться извлечь массив усиления, созданный в функции. Я добавил его в оператор return (внизу), но все равно не могу получить его в качестве переменной при запуске программы. Спасибо за любую помощь, спасибо!

...