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