Python seeks traversal, shortest path, minimum spanning tree, traveling salesman problem and drawing display

1. Source data

insert image description here

Two, python program

(1) Data preprocessing

import numpy as np
import pandas as pd
from scipy.sparse import coo_matrix
import networkx as nx
import matplotlib.pyplot as plt

# 避免图片无法显示中文
plt.rcParams['font.sans-serif']=['SimHei']
# 显示所有列
pd.set_option('display.max_columns', None)
pd.set_option('display.width', 1000)

# 读取数据
data=pd.read_excel('data.xlsx',sheet_name='Sheet1',index_col=0)
data=data.fillna(0)
print('矩阵的空值以0填充:\n',data)
coo=coo_matrix(np.array(data))
# 矩阵行列的索引默认从0开始改成从1开始
coo.row+=1
coo.col+=1
data=[int(i) for i in coo.data]
coo_tuple=list(zip(coo.row,coo.col,data))
coo_list=[]
for i in coo_tuple:
    coo_list.append(list(i))

# 出发点
start_node=1
# 目的地
target_node=14
# 设置各顶点坐标(只是方便绘图,并不是实际位置)
pos={
    
    1:(1,8),2:(4,10),3:(11,11),4:(14,8),5:(5,7),6:(10,6),7:(3,5),8:(6,4),9:(8,4),10:(14,5),11:(2,3),12:(5,1),13:(8,1),14:(13,3)}

The output is as follows:

矩阵的空值以0填充:
       1     2     3     4     5     6     7     8     9     10    11    12    13    14
1    0.0  23.0   0.0   0.0  54.0   0.0  55.0   0.0   0.0   0.0  26.0   0.0   0.0   0.0
2   23.0   0.0  56.0   0.0  18.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0
3    0.0  56.0   0.0  50.0  44.0  61.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0
4    0.0   0.0  50.0   0.0   0.0  28.0   0.0   0.0   0.0  27.0   0.0   0.0   0.0   0.0
5   54.0  18.0  44.0   0.0   0.0  51.0  34.0  56.0  48.0   0.0   0.0   0.0   0.0   0.0
6    0.0   0.0  61.0  28.0  51.0   0.0   0.0   0.0  27.0  42.0   0.0   0.0   0.0   0.0
7   55.0   0.0   0.0   0.0  34.0   0.0   0.0  36.0   0.0   0.0   0.0  38.0   0.0   0.0
8    0.0   0.0   0.0   0.0  56.0   0.0  36.0   0.0  29.0   0.0   0.0  33.0   0.0   0.0
9    0.0   0.0   0.0   0.0  48.0  27.0   0.0  29.0   0.0  61.0   0.0  29.0  42.0  36.0
10   0.0   0.0   0.0  27.0   0.0  42.0   0.0   0.0  61.0   0.0   0.0   0.0   0.0  25.0
11  26.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0  24.0   0.0   0.0
12   0.0   0.0   0.0   0.0   0.0   0.0  38.0  33.0  29.0   0.0  24.0   0.0  30.0   0.0
13   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0  42.0   0.0   0.0  30.0   0.0  47.0
14   0.0   0.0   0.0   0.0   0.0   0.0   0.0   0.0  36.0  25.0   0.0   0.0  47.0   0.0

(2) Traversal: depth-first and breadth-first

# 创建空的无向图
G=nx.Graph()
# 给无向图的边赋予权值
G.add_weighted_edges_from(coo_list)

# dfs深度优先
print('\n深度优先遍历:')
# 从源头开始在深度优先搜索中生成边
print(list(nx.dfs_edges(G,source=start_node)))
# 返回从源头开始的深度优先搜索构造的定向树
T_dfs=nx.dfs_tree(G,source=start_node)
print(T_dfs.nodes)

# bfs广度优先
print('\n广度优先遍历:')
# 从源头开始在广度优先搜索中生成边
print(list(nx.bfs_edges(G,source=start_node)))
# 返回从源头开始的广度优先搜索构造的定向树
T_bfs=nx.bfs_tree(G,source=start_node)
print(T_bfs.nodes)

The output is as follows:

深度优先遍历:
[(1, 2), (2, 3), (3, 4), (4, 6), (6, 5), (5, 7), (7, 8), (8, 9), (9, 10), (10, 14), (14, 13), (13, 12), (12, 11)]
[1, 2, 3, 4, 6, 5, 7, 8, 9, 10, 14, 13, 12, 11]

广度优先遍历:
[(1, 2), (1, 5), (1, 7), (1, 11), (2, 3), (5, 6), (5, 8), (5, 9), (7, 12), (3, 4), (6, 10), (9, 13), (9, 14)]
[1, 2, 5, 7, 11, 3, 6, 8, 9, 12, 4, 10, 13, 14]

(3) Find the shortest path: dijkstra algorithm and floyd algorithm

# 单源最短路径dijkstra迪杰斯特拉算法求最短路径和最短路程
min_path_dijkstra=nx.dijkstra_path(G,source=start_node,target=target_node)
min_path_length_dijkstra=nx.dijkstra_path_length(G,source=start_node,target=target_node)
print('\ndijkstra算法:顶点%d到顶点%d的最短路径:%s,最短路程:%d'%(start_node,target_node,min_path_dijkstra,min_path_length_dijkstra))

# 多源最短路径floyd弗洛伊德算法求最短路径和最短路程
index_floyd=list(nx.floyd_warshall(G,weight='weight'))
min_path_length_floyd=nx.floyd_warshall_numpy(G,weight='weight')
min_path_length_floyd=pd.DataFrame(data=min_path_length_floyd,index=index_floyd,columns=index_floyd)
print('\nfloyd算法:各顶点之间的最短路程矩阵:\n',min_path_length_floyd)

The output is as follows:

dijkstra算法:顶点1到顶点14的最短路径:[1, 11, 12, 9, 14],最短路程:115

floyd算法:各顶点之间的最短路程矩阵:
        1      2     5      7      11     3      4     6      10     8     9      12     13     14
1     0.0   23.0  41.0   55.0   26.0   79.0  120.0  92.0  134.0   83.0  79.0   50.0   80.0  115.0
2    23.0    0.0  18.0   52.0   49.0   56.0   97.0  69.0  111.0   74.0  66.0   73.0  103.0  102.0
5    41.0   18.0   0.0   34.0   67.0   44.0   79.0  51.0   93.0   56.0  48.0   72.0   90.0   84.0
7    55.0   52.0  34.0    0.0   62.0   78.0  113.0  85.0  126.0   36.0  65.0   38.0   68.0  101.0
11   26.0   49.0  67.0   62.0    0.0  105.0  108.0  80.0  114.0   57.0  53.0   24.0   54.0   89.0
3    79.0   56.0  44.0   78.0  105.0    0.0   50.0  61.0   77.0  100.0  88.0  116.0  130.0  102.0
4   120.0   97.0  79.0  113.0  108.0   50.0    0.0  28.0   27.0   84.0  55.0   84.0   97.0   52.0
6    92.0   69.0  51.0   85.0   80.0   61.0   28.0   0.0   42.0   56.0  27.0   56.0   69.0   63.0
10  134.0  111.0  93.0  126.0  114.0   77.0   27.0  42.0    0.0   90.0  61.0   90.0   72.0   25.0
8    83.0   74.0  56.0   36.0   57.0  100.0   84.0  56.0   90.0    0.0  29.0   33.0   63.0   65.0
9    79.0   66.0  48.0   65.0   53.0   88.0   55.0  27.0   61.0   29.0   0.0   29.0   42.0   36.0
12   50.0   73.0  72.0   38.0   24.0  116.0   84.0  56.0   90.0   33.0  29.0    0.0   30.0   65.0
13   80.0  103.0  90.0   68.0   54.0  130.0   97.0  69.0   72.0   63.0  42.0   30.0    0.0   47.0
14  115.0  102.0  84.0  101.0   89.0  102.0   52.0  63.0   25.0   65.0  36.0   65.0   47.0    0.0

(4) Draw the original picture

plt.figure()
plt.suptitle('原图')
# 绘制无向加权图
nx.draw(G,pos,with_labels=True)
# 显示无向加权图的边的权值
labels=nx.get_edge_attributes(G,'weight')
# 设置顶点颜色
nx.draw_networkx_nodes(G,pos,node_color='yellow',edgecolors='red')
# 显示边的权值
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels,font_color='purple',font_size=10)
nx.draw_networkx_nodes(G,pos,nodelist=[start_node],node_color='#00ff00',edgecolors='red')

The output is as follows:
insert image description here

(5) Find the minimum spanning tree: kruskal algorithm and prim algorithm

plt.figure()
plt.suptitle('kruskal算法或prim算法:最小生成树')
T=nx.minimum_spanning_tree(G,algorithm='kruskal')
# T=nx.minimum_spanning_tree(G,algorithm='prim')
# T=nx.minimum_spanning_tree(G,algorithm='boruvka')
# 绘制无向加权图
nx.draw(G,pos,with_labels=True)
# 设置最小生成树的顶点颜色
nx.draw_networkx_nodes(G,pos,nodelist=T.nodes,node_color='yellow',edgecolors='red')
# 设置最小生成树的边颜色和宽度
nx.draw_networkx_edges(G,pos,edgelist=T.edges,edge_color='blue',width=5)
# 显示无向加权图的边的权值
labels=nx.get_edge_attributes(G,'weight')
# 显示边的权值
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels,font_color='purple',font_size=10)
nx.draw_networkx_nodes(G,pos,nodelist=[start_node],node_color='#00ff00',edgecolors='red')

The output is as follows:
insert image description here

(6) Traveling salesman problem

plt.figure()
plt.suptitle('旅行商问题')
tsp=nx.approximation.traveling_salesman_problem(G,weight='weight')
tsp_edges=[]
tsp_length=0
for i in range(0,len(tsp)-1):
    tsp_edges.append([tsp[i],tsp[i+1]])
print('\n旅行商问题:',tsp_edges)
# 绘制无向加权图
nx.draw(G,pos,with_labels=True)
# 显示无向加权图的边的权值
labels=nx.get_edge_attributes(G,'weight')
# 设置顶点颜色
nx.draw_networkx_nodes(G,pos,node_color='yellow',edgecolors='red')
nx.draw_networkx_nodes(G,pos,nodelist=[start_node],node_color='#00ff00',edgecolors='red')
# 设置边颜色和宽度
nx.draw_networkx_edges(G,pos,edgelist=tsp_edges,edge_color='blue',width=5,arrows=True,arrowstyle='->',arrowsize=15)
# 显示边的权值
nx.draw_networkx_edge_labels(G,pos,edge_labels=labels,font_color='purple',font_size=10)
plt.show()

The output is as follows:
insert image description here

旅行商问题: [[1, 11], [11, 12], [12, 13], [13, 9], [9, 14], [14, 10], [10, 4], [4, 6], [6, 9], [9, 8], [8, 7], [7, 5], [5, 3], [3, 2], [2, 1]]

Guess you like

Origin blog.csdn.net/m0_67790374/article/details/129775170