極大連通子圖原理介紹及代碼實現Python3版

原理介紹

圖分爲無向圖和有向圖。

  • 無向圖中的極大連通子圖也叫連通分量。無向圖可以分成兩種類型:連通的無向圖、不連通的無向圖。連通的無向圖只有一個極大連通子圖,即它本身,因爲不存在另一個連通的子圖包含的點和邊比它本身還要多,所以叫作極大連通子圖。不連通的無向圖可以拆分爲若干個連通的無向圖,如果我們在拆分時注意把能連通的點邊都放在一個連通子圖中,使這個連通子圖足夠大,以至於再多包含一個點或邊它就變成不連通的了,我們稱這個連通子圖爲極大連通子圖,也叫連通分量。
  • 有向圖可以分爲強連通圖、弱連通圖、單向連通圖、不連通圖。極大連通子圖一般只在強連通圖中討論,即強連通分量。

代碼實現

# -*- coding:utf-8 -*-  
#====#====#====#====  
# __author__ = "liubc"
#FileName: *.py  
#Version:1.0.0 
#CreateTime:xxxx-xx-xx 
#====#====#====#====

from collections import deque
import sys

import matplotlib.pyplot as plt
import networkx as nx
import time
import openpyxl

'''求解極大連通子圖'''
# 定義graph
G = nx.Graph()
class ConnectedSubgraph:
    '''
        function:
            讀入Excel文檔(默認帶權重)
        input:
            file:輸入表格(xlsx格式):第一列爲源項目,第二列爲引用項目,第三列爲權重(可選)
        output:
            nodes:節點(項目)
            edges:邊(依賴關係)
        '''
    @classmethod
    def readExcel(cls, file):
        nodes = []
        edges = []
        # 輸入的表格必須整行整列(即m*n矩陣中的每個單元格不能爲空)
        wb = openpyxl.load_workbook(file)
        mySheet = wb['Sheet1']
        m_rows = mySheet.max_row
        n_columns = mySheet.max_column
        for i in range(1, m_rows + 1):
            mylist = []
            for j in range(1, n_columns + 1):
                key = mySheet.cell(i, j).value
                mylist.append(key)
                if (j < 3) and (key not in nodes):
                    nodes.append(key)
            tup = tuple(mylist)
            edges.append(tup)
        wb.save(file)
        return cls(nodes, edges)


    def __init__(self, nodes, edges):
        self.nodes = nodes
        self.edges = edges
        dict = {}
        mylist1 = []
        mylist2 = []
        for edge in edges:
            node1 = edge[0]
            node2 = edge[1]
            mylist1.append(node1)
            mylist2.append(node2)
        for key in nodes:
            num1 = mylist1.count(key)
            num2 = mylist2.count(key)
            num = num1 + num2
            dict[key] = num
        self.nodesdegree = dict


    '''
    function:
        讀入節點和邊
    input:
        nodes:節點(項目)
        edges:邊(依賴關係)
        weight_b:是否帶權重(默認爲true)
    '''
    def addNodesEdges(self, weight_b):
        # 定義graph
        self.weight_b = weight_b
        G.add_nodes_from(self.nodes)
        if self.weight_b:
            G.add_weighted_edges_from(self.edges)
        else:
            G.add_edges_from(self.edges)
        return


    '''
    function:
        將極大連通子圖寫入Excel文檔(默認帶權重)
    input:
        mylist:連通子圖
    output:
        file:輸出表格(xlsx格式):第一列爲源項目,第二列爲引用項目,第三列爲權重(可選)
    '''
    def writeGraph(self, file):
        # 寫文件
        wb = openpyxl.Workbook()  # 創建新的excel文件,一個工作簿(workbook)在創建的時候同時至少也新建了一張工作表(worksheet)
        # wb.save(file)
        wb.create_sheet(index=0, title="Sheet1")  # 可通過index控制創建的表的位置
        sheet_names = wb.sheetnames  # 獲取所有表名
        sheet1 = wb[sheet_names[0]]  # 打開第一個 sheet 工作表

        i = 1
        print("寫入極大連通子圖")
        for sublist in nx.connected_components(G):
            j = 1
            for key in sublist:
                sheet1.cell(row=i, column=j, value=key)
                j += 1
            i += 1
            #print("寫入極大連通子圖數:", i)
        wb.save(file)
        return

    '''
    計算極大連通子圖中不同圖的數量及節點個數
    統計極大連通子圖
        input:
            mylist:連通子圖
    '''
    def count(self):
        dict = {}
        for tmp_list in nx.connected_components(G):
            length = len(tmp_list)
            ret = dict.get(length)
            if ret == None:
                dict[length] = 1
            else:
                dict[length] = ret + 1
        items = sorted(dict.items(), key=lambda item: item[0])
        for key in items:
            print(key)
            # print('\n')
        return

    '''
    過濾社區中節點數小於threshold的極大連通子圖
    input:
        mylist:極大連通子圖 nx.connected_components(G)
        threshold:節點閾值
    output:
        節點列表
    '''
    def filtercommunity(self, threshold):
        dataset = []
        for tmplist in nx.connected_components(G):
            if len(tmplist) > threshold:
                for key in tmplist:
                    if key not in dataset:
                        dataset.append(key)
        self.dataset = dataset.copy()
        return


    '''
    求最大的極大連通子圖
    '''
    def maxSubGraph(self):
        maxsubgraph = []
        max = 0
        for tmplist in nx.connected_components(G):
            if max < len(tmplist):
                max = len(tmplist)
                maxsubgraph.clear()
                maxsubgraph = tmplist.copy()
        self.max = max
        self.maxsubgraph = maxsubgraph
        dataset = []
        for key in maxsubgraph:
            if key not in dataset:
                dataset.append(key)
        self.dataset = dataset
        print('最大連通子圖的項目數:', max)
        return



    '''
    function:
        顯示圖形
    input:
        mylist:連通子圖
    '''
    def show(self):
        nx.draw(G, with_labels=True, font_weight='bold')
        plt.axis('on')
        plt.xticks([])
        plt.yticks([])
        plt.show()
        return



 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章