练习1
北京(Pe)、东京(T)、纽约(N)、墨西哥(M)、伦敦(L)、巴黎(Pa)各城市之间的航线距离如下表所示。从北京(Pe)乘飞机到东京(T)、纽约(N)、墨西哥城(M)、伦敦(L)、巴黎(Pa)五城市做旅游,每城市恰去一次再返回北京,应如何安排旅游线,使旅程最短?
|
L |
M |
N |
Pa |
Pe |
T |
L |
0 |
56 |
35 |
21 |
51 |
60 |
M |
56 |
0 |
21 |
57 |
78 |
70 |
N |
35 |
21 |
0 |
36 |
68 |
68 |
Pa |
21 |
57 |
36 |
0 |
51 |
61 |
Pe |
51 |
78 |
68 |
51 |
0 |
13 |
T |
60 |
70 |
68 |
61 |
13 |
0 |
解决这个问题需要使用旅行商问题(TSP)的经典算法之一。我们可以使用蛮力法来求解,因为这是一个小规模的问题,有6个城市。这种方法将考虑所有可能的路线并找到总距离最短的那个。可以使用Python编写代码来实现这个功能。
from itertools import permutations
# 城市的索引
cities = ["L", "M", "N", "Pa", "T"]
# 城市间的距离矩阵
dist_matrix = [
[0, 56, 35, 21, 60], # L
[56, 0, 21, 57, 70], # M
[35, 21, 0, 36, 68], # N
[21, 57, 36, 0, 61], # Pa
[60, 70, 68, 61, 0], # T
]
# 北京到其他城市的距离
beijing_distances = [51, 78, 68, 51, 13]
# 将城市名称映射到索引
city_indices = {city: i for i, city in enumerate(cities)}
# 获取所有城市的排列
city_permutations = permutations(cities)
# 定义一个函数计算一个路线的总距离
def total_distance(route):
total_dist = beijing_distances[city_indices[route[0]]] # 从北京到第一个城市的距离
n = len(route)
for i in range(n - 1):
total_dist += dist_matrix[city_indices[route[i]]][city_indices[route[i + 1]]]
total_dist += beijing_distances[city_indices[route[-1]]] # 最后一个城市返回北京的距离
return total_dist
# 变量初始化
min_distance = float('inf')
best_route = None
# 遍历所有可能的城市排列
for perm in city_permutations:
dist = total_distance(perm)
if dist < min_distance:
min_distance = dist
best_route = perm
# 输出最优路径和最短距离
print("最优路径: Pe ->", " -> ".join(best_route), "-> Pe")
print("最短距离:", min_distance)
最优路径: Pe -> Pa -> L -> N -> M -> T -> Pe
最短距离: 211
练习2
Prim算法是一种用于在加权连通图中找到最小生成树的贪心算法。算法从一个初始顶点开始,逐步将未加入最小生成树的最短边连接到已加入最小生成树的顶点集合中,直到所有顶点都加入树中。每次选择最短的边都确保了生成的树具有最小权重总和。Prim算法与Dijkstra算法类似,但Prim算法着重于生成树的构建,而Dijkstra算法则用于寻找单个顶点到其余顶点的最短路径。Prim算法的时间复杂度为O(V^2)或O(ElogV),取决于实现方式。
import heapq
import networkx as nx
import matplotlib.pyplot as plt
graph = {
'v0': {'v1': 2, 'v2': 1, 'v3': 3, 'v4': 4, 'v5': 4, 'v6': 2, 'v7': 5, 'v8': 4},
'v1': {'v0': 2, 'v2': 4, 'v8': 1},
'v2': {'v0': 1, 'v1': 4, 'v3': 1},
'v3': {'v0': 3, 'v2': 1, 'v4': 1},
'v4': {'v0': 4, 'v3': 1, 'v5': 5},
'v5': {'v0': 4, 'v4': 5, 'v6': 2},
'v6': {'v0': 2, 'v5': 2, 'v7': 3},
'v7': {'v0': 5, 'v6': 3, 'v8': 5},
'v8': {'v0': 4, 'v1': 1, 'v7': 5}
}
def prim(graph, start):
min_heap = [(0, start, None)]
mst_edges = []
total_cost = 0
visited = set()
while min_heap:
cost, node, parent = heapq.heappop(min_heap)
if node in visited:
continue
visited.add(node)
if parent is not None:
mst_edges.append((parent, node, cost))
total_cost += cost
for neighbor, weight in graph[node].items():
if neighbor not in visited:
heapq.heappush(min_heap, (weight, neighbor, node))
return mst_edges, total_cost
mst_edges, total_cost = prim(graph, 'v0')
print("最小生成树的边:")
for edge in mst_edges:
print(edge)
print("最小生成树的总权重:", total_cost)
G = nx.Graph()
for node, edges in graph.items():
for neighbor, weight in edges.items():
G.add_edge(node, neighbor, weight=weight)
pos = nx.spring_layout(G)
plt.figure(figsize=(8, 8))
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=1000, font_size=20)
labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=labels, font_size=20)
mst_edges_set = set((u, v) for u, v, _ in mst_edges)
mst_labels = {edge: G.edges[edge]['weight'] for edge in mst_edges_set}
nx.draw_networkx_edges(G, pos, edgelist=mst_edges_set, edge_color='blue', width=4)
nx.draw_networkx_edge_labels(G, pos, edge_labels=mst_labels, font_color='blue', font_size=20)
plt.title('Graph with Minimum Spanning Tree', fontsize=20)
plt.show()
最小生成树的边:
('v0', 'v2', 1)
('v2', 'v3', 1)
('v3', 'v4', 1)
('v0', 'v1', 2)
('v1', 'v8', 1)
('v0', 'v6', 2)
('v6', 'v5', 2)
('v6', 'v7', 3)
最小生成树的总权重: 13
练习3
原图 |
|
 |
 |
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
a = np.zeros((11, 11))
a[0, 1] = 2; a[0, 2] = 8; a[0, 3] = 1
a[1, 2] = 6; a[1, 4] = 1
a[2, 3] = 7; a[2, 4] = 5; a[2, 5] = 1; a[2, 6] = 2
a[3, 6] = 9
a[4, 5] = 3; a[4, 7] = 2; a[4, 8] = 9
a[5, 6] = 4; a[5, 8] = 6
a[6, 8] = 3; a[6, 9] = 1
a[7, 8] = 7; a[7, 10] = 9
a[8, 9] = 1; a[8, 10] = 2
a[9, 10] = 4
s = ['v'+str(i) for i in range(1, 12)]
G = nx.Graph()
G.add_nodes_from(s)
for i in range(11):
for j in range(11):
if a[i, j] != 0:
G.add_edge(s[i], s[j], weight=a[i, j])
p, d = nx.shortest_path(G, 'v1', 'v11'), nx.shortest_path_length(G, 'v1', 'v11')
pos = nx.spring_layout(G)
plt.figure(figsize=(8, 6))
nx.draw(G, pos, with_labels=True, node_size=1000, node_color='lightblue', font_size=12)
labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=labels)
nx.draw_networkx_edges(G, pos, edgelist=[(p[i], p[i+1]) for i in range(len(p)-1)], edge_color='r', width=2)
plt.title('Shortest Path: ' + ' -> '.join(p) + ' (distance = ' + str(d) + ')', fontsize=14)
plt.show()
print("Shortest Path:", p)
print("Distance:", d)
#Floyd算法
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
# 创建邻接矩阵
a = np.zeros((11, 11))
a[0, 1] = 2; a[0, 2] = 8; a[0, 3] = 1
a[1, 2] = 6; a[1, 4] = 1
a[2, 3] = 7; a[2, 4] = 5; a[2, 5] = 1; a[2, 6] = 2
a[3, 6] = 9
a[4, 5] = 3; a[4, 7] = 2; a[4, 8] = 9
a[5, 6] = 4; a[5, 8] = 6
a[6, 8] = 3; a[6, 9] = 1
a[7, 8] = 7; a[7, 10] = 9
a[8, 9] = 1; a[8, 10] = 2
a[9, 10] = 4
# Floyd算法
def floyd_algorithm(a):
n = len(a)
inf = float('inf')
# 初始化距离矩阵
d = np.copy(a)
for i in range(n):
for j in range(n):
if i != j and d[i, j] == 0:
d[i, j] = inf
# 计算最短路径
for k in range(n):
for i in range(n):
for j in range(n):
if d[i, k] + d[k, j] < d[i, j]:
d[i, j] = d[i, k] + d[k, j]
return d
# 求解最短路径
d = floyd_algorithm(a)
shortest_path = [1, 2, 5, 6, 3, 7, 10, 9, 11]
distance = d[0, 10]
# 创建图
G = nx.Graph()
G.add_nodes_from(range(1, 12))
for i in range(11):
for j in range(11):
if a[i, j] != 0:
G.add_edge(i+1, j+1, weight=a[i, j])
# 绘制图形
pos = nx.spring_layout(G)
plt.figure(figsize=(8, 6))
nx.draw(G, pos, with_labels=True, node_size=1000, node_color='lightblue', font_size=12)
labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=labels)
plt.title('Shortest Path: ' + ' -> '.join(map(str, shortest_path)) + ' (distance = ' + str(distance) + ')', fontsize=14)
plt.show()
print("Shortest Path:", shortest_path)
print("Distance:", distance)
练习4

import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
G1 = nx.DiGraph()
G1.add_edge('s', 'a', capacity=6)
G1.add_edge('s', 'c', capacity=8)
G1.add_edge('a', 'b', capacity=3)
G1.add_edge('a', 'd', capacity=3)
G1.add_edge('b', 't', capacity=10)
G1.add_edge('c', 'd', capacity=4)
G1.add_edge('c', 'f', capacity=4)
G1.add_edge('d', 'e', capacity=3)
G1.add_edge('d', 'g', capacity=6)
G1.add_edge('e', 'b', capacity=7)
G1.add_edge('e', 'j', capacity=4)
G1.add_edge('f', 'h', capacity=4)
G1.add_edge('g', 'e', capacity=7)
G1.add_edge('h', 'g', capacity=1)
G1.add_edge('h', 'i', capacity=3)
G1.add_edge('i', 'j', capacity=3)
G1.add_edge('j', 't', capacity=5)
from networkx.algorithms.flow import edmonds_karp
maxFlowValue, maxFlowDict = nx.maximum_flow(G1, 's', 't', flow_func=edmonds_karp)
edgeCapacity = nx.get_edge_attributes(G1, 'capacity')
edgeLabel = {}
for i in edgeCapacity.keys():
edgeLabel[i] = f'c={edgeCapacity[i]:}'
edgeLists = []
for i in maxFlowDict.keys():
for j in maxFlowDict[i].keys():
edgeLabel[(i, j)] += ',f=' + str(maxFlowDict[i][j])
if maxFlowDict[i][j] > 0:
edgeLists.append((i, j))
print("最大流值: ", maxFlowValue)
print("最大流的途径及流量: ", maxFlowDict)
print("最大流的路径:", edgeLists)
fig, ax = plt.subplots(figsize=(8, 6))
pos = {'s': (1, 8), 'a': (6, 7.5), 'b': (9, 8), 'c': (1.5, 6), 'd': (4, 6), 'e': (8, 5.5),
'f': (2, 4), 'g': (5, 4), 'h': (1, 2), 'i': (5.5, 2.5), 'j': (9.5, 2), 't': (11, 6)}
edge_labels = nx.get_edge_attributes(G1, 'capacity')
ax.set_title("Maximum flow of petroleum network with NetworkX", fontsize=20)
nx.draw(G1, pos, with_labels=True, node_color='c', node_size=600, font_size=20)
nx.draw_networkx_edge_labels(G1, pos, edgeLabel, font_color='navy', font_size=20)
nx.draw_networkx_edges(G1, pos, edgelist=edgeLists, edge_color='m')
plt.axis('on')
plt.show()
最大流值: 14
最大流的途径及流量: {'s': {'a': 6, 'c': 8}, 'a': {'b': 3, 'd': 3}, 'c': {'d': 4, 'f': 4}, 'b': {'t': 10}, 'd': {'e': 3, 'g': 4}, 't': {}, 'f': {'h': 4}, 'e': {'b': 7, 'j': 1}, 'g': {'e': 5}, 'j': {'t': 4}, 'h': {'g': 1, 'i': 3}, 'i': {'j': 3}}
最大流的路径: [('s', 'a'), ('s', 'c'), ('a', 'b'), ('a', 'd'), ('c', 'd'), ('c', 'f'), ('b', 't'), ('d', 'e'), ('d', 'g'), ('f', 'h'), ('e', 'b'), ('e', 'j'), ('g', 'e'), ('j', 't'), ('h', 'g'), ('h', 'i'), ('i', 'j')]
练习5
原网络图 |
容量网络图 |
最小费用最大流 |
图中弧的第一个数是成本,后一个数是容量 |
 |
 |
5.1 容量网络
import networkx as nx
import matplotlib.pyplot as plt
a = [[0, 10, 8, 0, 0],
[0, 0, 0, 2, 7],
[0, 5, 0, 10, 0],
[0, 0, 0, 0, 4],
[0, 0, 0, 0, 0]]
G = nx.DiGraph()
for i in range(len(a)):
for j in range(len(a[i])):
if a[i][j] != 0:
G.add_edge(i+1, j+1, capacity=a[i][j])
flow_value, flow_dict = nx.maximum_flow(G, 1, 5)
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_size=700, node_color='skyblue', font_size=20, font_weight='bold', arrowsize=20)
edge_labels = {(u, v): f"{d['capacity']}" for u, v, d in G.edges(data=True)}
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_color='red', font_size=20)
labels = {1: 's', 5: 't'}
nx.draw_networkx_labels(G, pos, labels=labels, font_size=15, font_weight='bold')
plt.show()
5.2 最小费用最大流
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
G2 = nx.DiGraph()
G2.add_edges_from([('s', 'v1', {'capacity': 10, 'weight': 4}),
('s', 'v2', {'capacity': 8, 'weight': 1}),
('v1', 'v3', {'capacity': 2, 'weight': 6}),
('v2', 'v1', {'capacity': 5, 'weight': 2}),
('v2', 'v3', {'capacity': 10, 'weight': 3}),
('v3', 't', {'capacity': 4, 'weight': 2}),
('v1', 't', {'capacity': 7, 'weight': 1}),
])
edgeLabel1 = nx.get_edge_attributes(G2, 'capacity')
edgeLabel2 = nx.get_edge_attributes(G2, 'weight')
edgeLabel = {}
for i in edgeLabel1.keys():
edgeLabel[i] = f'({edgeLabel2[i]:},{edgeLabel1[i]:})'
lenShortestPath = nx.shortest_path_length(G2, 's', 't', weight="weight")
shortestPath = nx.shortest_path(G2, 's', 't', weight="weight")
print("\n最短路径: ", shortestPath)
print("最短路径长度: ", lenShortestPath)
minCostFlow = nx.max_flow_min_cost(G2, 's', 't')
minCost = nx.cost_of_flow(G2, minCostFlow)
maxFlow = sum(minCostFlow['s'][j] for j in minCostFlow['s'].keys())
print("\n最大流量: {}".format(maxFlow))
print("最大流量的最小费用: {}\n".format(minCost))
v = 0
while True:
v += 1
G2.add_node("s", demand=-v)
G2.add_node("t", demand=v)
try:
minFlowCost = nx.min_cost_flow_cost(G2)
minFlowDict = nx.min_cost_flow(G2)
print("流量: {:2d}\t最小费用:{}".format(v, minFlowCost))
except Exception as e:
print("流量: {:2d}\t超出网络最大容量,没有可行流。".format(v))
print("\n流量 v={:2d}:计算最小费用流失败({})。".format(v, str(e)))
break
edgeLists = []
for i in minFlowDict.keys():
for j in minFlowDict[i].keys():
edgeLabel[(i, j)] += ',f=' + str(minFlowDict[i][j])
if minFlowDict[i][j] > 0:
edgeLists.append((i, j))
maxFlow = sum(minFlowDict['s'][j] for j in minFlowDict['s'].keys())
print("\n最大流量: {:2d},\t最小费用:{}".format(maxFlow, minFlowCost))
print("最小费用流的路径及流量: ", minFlowDict)
print("最小费用流的路径:", edgeLists)
pos = {'s': (0, 5), 'v1': (4, 2), 'v2': (4, 8), 'v3': (10, 2), 'v4': (10, 8), 't': (14, 5)}
fig, ax = plt.subplots(figsize=(8, 6))
ax.set_title("Minimum Cost Maximum Flow with NetworkX")
nx.draw(G2, pos, with_labels=True, node_color='c', node_size=600, font_size=20)
nx.draw_networkx_edge_labels(G2, pos, edgeLabel, font_size=20)
nx.draw_networkx_edges(G2, pos, edgelist=edgeLists, edge_color='m', width=2)
for edge in edgeLists:
u, v = edge
nx.draw_networkx_edges(G2, pos, edgelist=[(u, v)], edge_color='r', width=minFlowDict[u][v] / 5)
plt.axis('on')
plt.show()
最大流量: 11, 最小费用:55
最小费用流的路径及流量: {'s': {'v1': 3, 'v2': 8}, 'v1': {'v3': 0, 't': 7}, 'v2': {'v1': 4, 'v3': 4}, 'v3': {'t': 4}, 't': {}}
最小费用流的路径: [('s', 'v1'), ('s', 'v2'), ('v1', 't'), ('v2', 'v1'), ('v2', 'v3'), ('v3', 't')]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
2023-06-09 非线性规划——习题解答(七)
2023-06-09 非线性规划——惩罚函数外点法(六)
2023-06-09 非线性规划——库恩塔克KTT条件(五)
2023-06-09 非线性规划——拉格朗日最优化方法(四)