Networkx Kernighan-Lin多分区

问题描述

我制作了一个图,并通过Kernighan-Lin划分算法将其分为2部分。在NetworkX软件包中,python仅对两个分区具有Kernighan-Lin算法,但对于多分区,我需要它。如何将其从两个分区更改为多分区?

我编写了一个示例图代码,还有Kernighan-Lin算法。

from collections import defaultdict
from itertools import islice
from operator import itemgetter
import networkx as nx
from networkx.utils import not_implemented_for,py_random_state
from networkx.algorithms.community.community_utils import is_partition

G = nx.Graph()
G.add_node('a')
G.add_node('b')
G.add_node('c')
G.add_node('d')
G.add_node('e')
G.add_node('f')
G.add_edge('a','b')
G.add_edge('c','b')
G.add_edge('d','e')
G.add_edge('e','f')

__all__ = ['kernighan_lin_bisection']

def _compute_delta(G,A,B,weight):
    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,u,weight):
    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 _,d in G.edges(v,1)
        if nbr in A:
            delta[nbr] -= 2 * w
        if nbr in B:
            delta[nbr] += 2 * w
    return delta

def _kernighan_lin_pass(G,weight):
    multigraph = G.is_multigraph()
    delta = _compute_delta(G,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,v))
        if len(gain) == 0:
            break
        maxg,v = max(gain,key=itemgetter(0))
        swapped |= {u,v}
        gains.append((maxg,v))
        delta = _update_delta(delta,A - swapped,B - swapped,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 partition is None:
        nodes = list(G)
        seed.shuffle(nodes)
        h = len(nodes) // 2
        partition = (nodes[:h],nodes[h:])
    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 = _kernighan_lin_pass(G,weight)
        csum = list(nx.utils.accumulate(g for g,v in gains))
        max_cgain = max(csum)
        if max_cgain <= 0:
            break
        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

def main() -> None:
kl = kernighan_lin_bisection(G,seed=None)
print(f'= {kl}')

if __name__ == '__main__':
    main()

解决方法

您可以使用Metis算法来具有多个分区

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...