利用python实现贪心算法求解最大独立集

前言

关于最大独立集以及本博客内贪心算法的思想见本人的另一篇博客,这里实现的是贪心算法3.

贪心算法求解最大独立集_keep_humble的博客-CSDN博客https://blog.csdn.net/qq_43270444/article/details/128571589?spm=1001.2014.3001.5501

代码实现

import random
import networkx as nx
import matplotlib.pyplot as plt



# 创建图
def create_graph(V,E):
    G = nx.Graph()
    G.add_nodes_from(V)
    G.add_edges_from(E)

    # 将生成的图 G 打印出来
    pos = nx.circular_layout(G)
    options = {
        "with_labels": True,
        "font_size": 20,
        "font_weight": "bold",
        "font_color": "white",
        "node_size": 2000,
        "width": 2
    }
    nx.draw_networkx(G, pos, **options)
    ax = plt.gca()
    ax.margins(0.20)
    plt.axis("off")
    plt.show()
    return G

# 获取图G内顶点的度以及其邻居节点
def get_info(V,E):
    G = create_graph(V,E)
    Adj_matrix = nx.adjacency_matrix(G)

    # 转换为二维数组矩阵
    A = Adj_matrix.todense()
    
    # 通过访问邻接矩阵获取图内每个顶点的度以及其邻居节点,并将信息存储到字典info内
    info = {}
    for i in range(len(A)):
        # 统计节点的度
        node = 0
        # 统计节点的邻居节点
        adj = []
        for j in range(len(A)):
            if j <= len(V):
                node += A.item(i,j)
                if A.item(i,j) == 1:
                    adj.append(j)
        print('节点{}的度为{},邻居信息为{}'.format(V[i],node,adj))
        info[i] = adj
   
    print('当前图G内各顶点的度以及邻居顶点信息为{}'.format(info))
    
    # 返回图内信息
    return info



# 计算顶点i的支撑
def s(i,info):
    m = 0
    # 获取顶点i的邻居
    neibor = info[i]
    if len(neibor) == 0:
        m = 0
#         print('顶点{}为孤立点,支撑为0'.format(i))
    else:
        # 计算顶点i邻居节点的支撑(度之和)
        for j in range(0,len(neibor)):
            m  += len(info[neibor[j]])
    return m



# 向顶点子集I内添加节点a
def step1(info,I):
    # 统计每个节点的度
    node = []
    for key,value in info.items():
        # 需要注意的是,列表node中默认无重复元素
        node.append(len(value))
    
    # 寻找最小度
    min_node = min(node)
    
    # 最小度的顶点,存储到列表node_set中
    node_set = []
    for i in range(0,len(info)):
        if len(info[i]) == min_node:
            node_set.append(i)
            
    # 初始化顶点子集I为空集,首选向I内添加度最小的顶点       
    if len(node_set) == 1:
        I.append(node_set[0])
        a = node_set[0]
    else:
        # 计算node_set内元素的支撑,对应信息存储到列表k内,选择最大支撑
        k = []
        info1 = {}
        for j in range(0,len(node_set)):
            # 调用计算支撑的函数
            k.append(s(node_set[j],info))
            # 将顶点j以及其支撑存储到字典info1中
            info1[node_set[j]] = s(node_set[j],info)
            
            
        # 获取最大支撑的数值
        max_k = max(k)
        print('当前最小度顶点有:{},对应的支撑为{}'.format(node_set,k))
        
        # 将支撑度最大的顶点信息存储到列表q内
        q = []
        for key,value in info1.items():
            if value == max_k:
                q.append(key)
            
        
        # 将度最小,支撑最大的顶点加入到I中
        if len(q) == 1:
            I.append(q[0])
            a = q[0]
        else:
            # 随机生成0-len(q)中的整数
            t = random.randint(0,len(q)-1)
            print('当前支撑度最大的顶点有:{},随机生成数为:{}'.format(q,t))
            I.append(q[t])
            a = q[t]
    return a,I






# 更新图G,从图G内删除顶点i和顶点i的邻居节点,以及相关联的边。
def step2(i,info):
    # 获取顶点i的邻居节点信息
    neigor = info[i]
    
    # 将顶点i从图G中删除,V1内存储删除i后的其余节点
    V1 = []
    for m in range(0,len(V)):
        if V[m] != i:
            V1.append(V[m])
        
    # 将顶点i的邻居节点从图G中删除
    for j in range(0,len(neigor)):
        V2 = []
        for m in range(0,len(V1)):
            if V1[m] != neigor[j]:
                V2.append(V1[m])
        V1 = V2
    
    # 删除和顶点i相关联的边
    update_E1 = []
    for j in range(0,len(E)):
        if i not in E[j]:
            update_E1.append(E[j])
            
    # 删除和顶点i的邻居节点相关联的边
  
    for j in range(0,len(neigor)):
        update_E = []
        for k in range(0,len(update_E1)):
            if neigor[j] not in update_E1[k]:
                # 保证边集内无重复元素
                if update_E1[k] not in update_E:
                    update_E.append(update_E1[k])
        # 更新当前的边集
        update_E1 = update_E
        
    # 返回更新后的顶点集合以及边集
    return V1,update_E1





# 主函数  
V = [0,1,2,3,4]  
E = [(0, 1), (1, 2),(2,3),(3,4),(0,4)]
initial_I = []



while len(E)!=0:
    #获取当前图G信息
    info = get_info(V,E)
    
    
    # 将顶点a加入到I内
    a,I = step1(info,initial_I)
    print('当前的独立集I = {}'.format(I))
    
    # 更新图G
    V,E = step2(a,info)
    print('更新后的图G,V={},E= {}'.format(V,E))
    print('\n')
    
    initial_I = I

if len(E) == 0:
    # 将零图内的顶点加入到I内
    for i in range(0,len(V)):
        I.append(V[i])
    print('利用贪心算法得到的近似解为:{}'.format(I))

上述代码中涉及如何根据邻接矩阵获取图G内每个顶点的度以及邻居节点,如何从图G内删除指定顶点以及与指定顶点相关联的边。我以一个5顶点的2正则图运行了上述代码,效果如下:

 如有错误,欢迎指正~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值