【数学建模】 复杂网络与图论模型

文章目录

  • 复杂网络与图论模型
    • 1. 复杂网络概念与理论
      • 1.1 复杂网络中的基本概念
      • 1.2 复杂网络中的统计指标
    • 2. 图论算法:遍历,二分图与最小生成树
      • 2.1 图的遍历算法
        • 深度优先搜索(DFS)
        • 广度优先搜索(BFS)
      • 2.2 二分图最大匹配
      • 2.3 最小生成树
        • Kruskal算法
        • Prim算法
    • 3. 图论算法:最短路径与最大流问题
      • 3.1 最短路径问题
        • Dijkstra算法
        • Bellman-Ford算法
      • 3.2 最大流问题
        • Ford-Fulkerson算法
        • Edmonds-Karp算法
    • 4. 使用Networkx完成复杂网络建模
      • 4.1 介绍Networkx
      • 4.2 Networkx基本操作
      • 4.3 Networkx例子和代码实现
        • 4.3.1 创建和可视化图
        • 4.3.2 图的遍历
        • 4.3.3 最短路径
        • 4.3.4 最小生成树
        • 4.3.5 最大流
      • 4.4 综合示例:社交网络分析
    • 5. 图论算法:TSP问题与VRP问题
      • 5.1 TSP问题(旅行商问题)
        • 5.1.1 定义
        • 5.1.2 解决方法
        • 5.1.3 Python实现示例
      • 5.2 VRP问题(车辆路径规划问题)
        • 5.2.1 定义
        • 5.2.2 解决方法
        • 5.2.3 Python实现示例
    • 6. 学习心得

复杂网络与图论模型

1. 复杂网络概念与理论

复杂网络是指由大量节点(Node)和边(Edge)构成的网络,其结构和功能复杂多样,无法通过简单的规律描述。复杂网络广泛存在于自然界和人类社会中,如互联网、社交网络、生物网络等。

1.1 复杂网络中的基本概念

  1. 节点(Node)和边(Edge):节点是网络中的基本单位,可以代表人、计算机、基因等。边是连接节点的线,可以表示人际关系、通信线路、基因相互作用等。

  2. 度(Degree):节点的度是指连接到该节点的边的数量。度分为入度(In-degree)和出度(Out-degree),分别表示指向该节点的边的数量和从该节点出发的边的数量。

  3. 路径(Path):在网络中,路径是指从一个节点到另一个节点的边的序列。最短路径(Shortest Path)是指连接两个节点的路径中边的数量最少的路径。

  4. 邻居(Neighbor):节点的邻居是指与该节点直接相连的节点。一个节点的度也可以理解为它的邻居数量。

  5. 连通性(Connectivity):网络的连通性描述了网络中节点之间的可达性。如果网络中的任意两个节点之间都有路径相连,则该网络是连通的。

  6. 聚类系数(Clustering Coefficient):聚类系数是描述节点的邻居之间互相连接的紧密程度的指标。高聚类系数表明网络中有很多小团体或子群体。

  7. 网络直径(Diameter):网络直径是指网络中所有最短路径中的最长路径的长度,即从一个节点到另一个节点的最长最短路径。

  8. 中心性(Centrality):中心性是用来衡量节点在网络中重要程度的指标,常见的中心性指标有度中心性、接近中心性(Closeness Centrality)、中介中心性(Betweenness Centrality)等。

1.2 复杂网络中的统计指标

  1. 度分布(Degree Distribution):度分布是指网络中节点的度的分布情况。度分布可以帮助我们了解网络的整体结构特征。常见的度分布有泊松分布、幂律分布等。

  2. 平均路径长度(Average Path Length):平均路径长度是指网络中所有节点对之间最短路径长度的平均值。它反映了网络中信息传递的效率。

  3. 聚类系数分布(Clustering Coefficient Distribution):聚类系数分布描述了网络中不同度的节点的聚类系数的分布情况。可以揭示网络中不同类型节点的聚团特性。

  4. 连通分量(Connected Components):连通分量是指在网络中,每个节点都可以通过路径到达其他节点的最大子网络。研究连通分量可以帮助我们理解网络的整体连通性。

  5. 网络模体(Network Motifs):网络模体是指在网络中反复出现的子结构。识别网络模体可以帮助我们发现网络的基本构建模块和功能单元。

  6. 节点强度(Node Strength):节点强度是指一个节点所有连接边的权重之和。在加权网络中,节点强度是度的加权版本。

  7. 网络的加权聚类系数(Weighted Clustering Coefficient):在加权网络中,考虑边的权重后重新计算的聚类系数。可以更准确地描述网络的局部结构特征。

  8. 网络熵(Network Entropy):网络熵是用来衡量网络结构复杂度的指标。熵越高,网络结构越复杂。

这些统计指标可以帮助我们从不同角度理解和分析复杂网络的结构和功能特性。通过对这些指标的研究,可以揭示网络的整体规律,指导网络的设计和优化。

2. 图论算法:遍历,二分图与最小生成树

图论算法在计算机科学和网络分析中具有重要地位。以下内容详细介绍了图的遍历算法、二分图最大匹配算法以及最小生成树算法。

2.1 图的遍历算法

图的遍历包括深度优先搜索(DFS)和广度优先搜索(BFS)。这些算法用于访问图中的所有节点。

深度优先搜索(DFS)

深度优先搜索是一种从起始节点开始,沿着每一个分支尽可能深入到一个节点再返回的遍历算法。

Python 代码示例:

# 深度优先搜索算法
def dfs(graph, start, visited=None):if visited is None:visited = set()visited.add(start)print(start, end=' ')for next in graph[start] - visited:dfs(graph, next, visited)return visited# 图的表示(邻接表)
graph = {'A': {'B', 'C'},'B': {'A', 'D', 'E'},'C': {'A', 'F'},'D': {'B'},'E': {'B', 'F'},'F': {'C', 'E'}
}# 调用DFS
dfs(graph, 'A')
广度优先搜索(BFS)

广度优先搜索是一种从起始节点开始,逐层访问邻接节点的遍历算法。

Python 代码示例:

from collections import deque# 广度优先搜索算法
def bfs(graph, start):visited = set()queue = deque([start])visited.add(start)while queue:vertex = queue.popleft()print(vertex, end=' ')for neighbor in graph[vertex]:if neighbor not in visited:visited.add(neighbor)queue.append(neighbor)# 图的表示(邻接表)
graph = {'A': {'B', 'C'},'B': {'A', 'D', 'E'},'C': {'A', 'F'},'D': {'B'},'E': {'B', 'F'},'F': {'C', 'E'}
}# 调用BFS
bfs(graph, 'A')

2.2 二分图最大匹配

二分图最大匹配是指在一个二分图中找到最大数量的匹配边,使得每个顶点至多属于一条匹配边。Hungarian算法是解决这个问题的经典算法。

Python 代码示例:

# Hungarian Algorithm for Maximum Bipartite Matching# 检查从 u 出发是否有增广路径
def bpm(graph, u, matchR, seen):for v in range(len(graph[0])):if graph[u][v] and not seen[v]:seen[v] = Trueif matchR[v] == -1 or bpm(graph, matchR[v], matchR, seen):matchR[v] = ureturn Truereturn False# 主函数,返回最大匹配数
def maxBPM(graph):matchR = [-1] * len(graph[0])result = 0for i in range(len(graph)):seen = [False] * len(graph[0])if bpm(graph, i, matchR, seen):result += 1return result# 图的表示(邻接矩阵)
graph = [[0, 1, 1, 0, 0, 0],[1, 0, 0, 1, 0, 0],[0, 0, 1, 0, 1, 0],[0, 0, 0, 1, 0, 1],[0, 1, 0, 0, 0, 1]
]# 调用函数
print("最大匹配数是", maxBPM(graph))

2.3 最小生成树

最小生成树(MST)是指在一个加权无向图中,选取若干边,使得这些边构成的子图是一个生成树,且所有边权之和最小。Kruskal算法和Prim算法是解决MST的经典算法。

Kruskal算法

Python 代码示例:

class Graph:def __init__(self, vertices):self.V = verticesself.graph = []def add_edge(self, u, v, w):self.graph.append([u, v, w])def find(self, parent, i):if parent[i] == i:return ireturn self.find(parent, parent[i])def union(self, parent, rank, x, y):root_x = self.find(parent, x)root_y = self.find(parent, y)if rank[root_x] < rank[root_y]:parent[root_x] = root_yelif rank[root_x] > rank[root_y]:parent[root_y] = root_xelse:parent[root_y] = root_xrank[root_x] += 1def kruskal_mst(self):result = []i = e = 0self.graph = sorted(self.graph, key=lambda item: item[2])parent = []rank = []for node in range(self.V):parent.append(node)rank.append(0)while e < self.V - 1:u, v, w = self.graph[i]i += 1x = self.find(parent, u)y = self.find(parent, v)if x != y:e += 1result.append([u, v, w])self.union(parent, rank, x, y)print("构成最小生成树的边:")for u, v, weight in result:print(f"{u} -- {v} == {weight}")# 创建图
g = Graph(4)
g.add_edge(0, 1, 10)
g.add_edge(0, 2, 6)
g.add_edge(0, 3, 5)
g.add_edge(1, 3, 15)
g.add_edge(2, 3, 4)# 调用Kruskal算法
g.kruskal_mst()
Prim算法

Python 代码示例:

import sysclass Graph:def __init__(self, vertices):self.V = verticesself.graph = [[0 for column in range(vertices)]for row in range(vertices)]def print_mst(self, parent):print("构成最小生成树的边:")for i in range(1, self.V):print(f"{parent[i]} -- {i} == {self.graph[i][parent[i]]}")def min_key(self, key, mst_set):min = sys.maxsizefor v in range(self.V):if key[v] < min and not mst_set[v]:min = key[v]min_index = vreturn min_indexdef prim_mst(self):key = [sys.maxsize] * self.Vparent = [None] * self.Vkey[0] = 0mst_set = [False] * self.Vparent[0] = -1for _ in range(self.V):u = self.min_key(key, mst_set)mst_set[u] = Truefor v in range(self.V):if self.graph[u][v] and not mst_set[v] and key[v] > self.graph[u][v]:key[v] = self.graph[u][v]parent[v] = uself.print_mst(parent)# 创建图
g = Graph(5)
g.graph = [[0, 2, 0, 6, 0],[2, 0, 3, 8, 5],[0, 3, 0, 0, 7],[6, 8, 0, 0, 9],[0, 5, 7, 9, 0]
]# 调用Prim算法
g.prim_mst()

上述代码实现了图的遍历、二分图最大匹配和最小生成树的常见算法,并包括详细的注释以便理解和应用。

3. 图论算法:最短路径与最大流问题

图论算法中的最短路径和最大流问题在网络优化、交通规划等领域有广泛应用。以下详细介绍了最短路径问题和最大流问题,并附上了建模过程和Python代码示例。

3.1 最短路径问题

最短路径问题是指在图中寻找从一个节点到另一个节点的最短路径。常见的算法有Dijkstra算法和Bellman-Ford算法。

Dijkstra算法

Dijkstra算法用于计算加权图中单源最短路径,要求边的权重为非负。

例子:

假设我们有一个图,其中节点代表城市,边的权重代表城市之间的距离。我们要找到从城市A到其他所有城市的最短路径。

Python代码示例:

import heapqdef dijkstra(graph, start):# 初始化距离表,所有节点距离为无穷大distances = {vertex: float('infinity') for vertex in graph}distances[start] = 0priority_queue = [(0, start)]while priority_queue:current_distance, current_vertex = heapq.heappop(priority_queue)if current_distance > distances[current_vertex]:continuefor neighbor, weight in graph[current_vertex].items():distance = current_distance + weightif distance < distances[neighbor]:distances[neighbor] = distanceheapq.heappush(priority_queue, (distance, neighbor))return distances# 图的表示(邻接表)
graph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}# 调用Dijkstra算法
distances = dijkstra(graph, 'A')
print("从A到各节点的最短路径:", distances)
Bellman-Ford算法

Bellman-Ford算法用于处理含有负权边的图,能够检测负权环。

例子:

假设我们有一个图,其中节点代表城市,边的权重代表城市之间的费用。我们要找到从城市A到其他所有城市的最短路径。

Python代码示例:

def bellman_ford(graph, start):distance = {vertex: float('infinity') for vertex in graph}distance[start] = 0for _ in range(len(graph) - 1):for vertex in graph:for neighbor, weight in graph[vertex].items():if distance[vertex] + weight < distance[neighbor]:distance[neighbor] = distance[vertex] + weightfor vertex in graph:for neighbor, weight in graph[vertex].items():if distance[vertex] + weight < distance[neighbor]:raise ValueError("Graph contains a negative-weight cycle")return distance# 图的表示(邻接表)
graph = {'A': {'B': 1, 'C': 4},'B': {'A': 1, 'C': 2, 'D': 5},'C': {'A': 4, 'B': 2, 'D': 1},'D': {'B': 5, 'C': 1}
}# 调用Bellman-Ford算法
distances = bellman_ford(graph, 'A')
print("从A到各节点的最短路径:", distances)

3.2 最大流问题

最大流问题是指在一个流网络中,从源点到汇点的最大流量。常见的算法有Ford-Fulkerson算法和Edmonds-Karp算法。

Ford-Fulkerson算法

Ford-Fulkerson算法基于增广路径寻找最大流量。

例子:

假设我们有一个流网络,其中节点代表管道连接点,边的权重代表管道的容量。我们要找到从源点S到汇点T的最大流量。

Python代码示例:

from collections import defaultdictclass Graph:def __init__(self, vertices):self.graph = defaultdict(list)self.V = verticesdef add_edge(self, u, v, w):self.graph[u].append([v, w])def bfs(self, s, t, parent):visited = [False] * (self.V)queue = []queue.append(s)visited[s] = Truewhile queue:u = queue.pop(0)for ind, val in enumerate(self.graph[u]):v = val[0]if visited[v] == False and val[1] > 0:queue.append(v)visited[v] = Trueparent[v] = ureturn visited[t]def ford_fulkerson(self, source, sink):parent = [-1] * (self.V)max_flow = 0while self.bfs(source, sink, parent):path_flow = float("Inf")s = sinkwhile s != source:for v, w in self.graph[parent[s]]:if v == s:path_flow = min(path_flow, w)s = parent[s]v = sinkwhile v != source:u = parent[v]for ind, val in enumerate(self.graph[u]):if val[0] == v:self.graph[u][ind][1] -= path_flowfor ind, val in enumerate(self.graph[v]):if val[0] == u:self.graph[v][ind][1] += path_flowv = parent[v]max_flow += path_flowreturn max_flow# 创建图
g = Graph(6)
g.add_edge(0, 1, 16)
g.add_edge(0, 2, 13)
g.add_edge(1, 2, 10)
g.add_edge(1, 3, 12)
g.add_edge(2, 1, 4)
g.add_edge(2, 4, 14)
g.add_edge(3, 2, 9)
g.add_edge(3, 5, 20)
g.add_edge(4, 3, 7)
g.add_edge(4, 5, 4)source = 0
sink = 5print("从源点到汇点的最大流量:", g.ford_fulkerson(source, sink))
Edmonds-Karp算法

Edmonds-Karp算法是Ford-Fulkerson算法的实现,使用BFS寻找增广路径。

例子:

与Ford-Fulkerson算法相同,我们有一个流网络,其中节点代表管道连接点,边的权重代表管道的容量。我们要找到从源点S到汇点T的最大流量。

Python代码示例:

from collections import dequeclass Graph:def __init__(self, graph):self.graph = graphself.ROW = len(graph)def bfs(self, s, t, parent):visited = [False] * (self.ROW)queue = deque([s])visited[s] = Truewhile queue:u = queue.popleft()for ind, val in enumerate(self.graph[u]):if visited[ind] == False and val > 0:queue.append(ind)visited[ind] = Trueparent[ind] = ureturn visited[t]def edmonds_karp(self, source, sink):parent = [-1] * (self.ROW)max_flow = 0while self.bfs(source, sink, parent):path_flow = float("Inf")s = sinkwhile s != source:path_flow = min(path_flow, self.graph[parent[s]][s])s = parent[s]v = sinkwhile v != source:u = parent[v]self.graph[u][v] -= path_flowself.graph[v][u] += path_flowv = parent[v]max_flow += path_flowreturn max_flow# 图的表示(邻接矩阵)
graph = [[0, 16, 13, 0, 0, 0],[0, 0, 10, 12, 0, 0],[0, 4, 0, 0, 14, 0],[0, 0, 9, 0, 0, 20],[0, 0, 0, 7, 0, 4],[0, 0, 0, 0, 0, 0]
]# 创建图
g = Graph(graph)source = 0
sink = 5print("从源点到汇点的最大流量:", g.edmonds_karp(source, sink))

上述代码详细展示了最短路径问题和最大流问题的解决方法,包括Dijkstra算法、Bellman-Ford算法、Ford-Fulkerson算法和Edmonds-Karp算法的实现。

4. 使用Networkx完成复杂网络建模

4.1 介绍Networkx

NetworkX是一个Python库,用于创建、操作和研究复杂网络的结构、动态和功能。它提供了多种数据结构来表示图(无向图、有向图、多重图等),并包含了许多用于图论分析和可视化的工具和算法。

4.2 Networkx基本操作

  1. 图的创建:可以使用不同的方法创建各种类型的图。
  2. 添加节点和边:通过简单的方法添加节点和边。
  3. 图的属性:可以为图、节点和边添加属性。
  4. 图的分析:使用各种算法进行图的分析,例如最短路径、最小生成树、最大流等。
  5. 图的可视化:可以利用Matplotlib等库对图进行可视化。

4.3 Networkx例子和代码实现

以下是使用NetworkX进行复杂网络建模的例子。

4.3.1 创建和可视化图
import networkx as nx
import matplotlib.pyplot as plt# 创建一个无向图
G = nx.Graph()# 添加节点
G.add_node(1)
G.add_nodes_from([2, 3, 4])# 添加边
G.add_edge(1, 2)
G.add_edges_from([(2, 3), (3, 4)])# 绘制图
nx.draw(G, with_labels=True)
plt.show()
4.3.2 图的遍历
# 深度优先搜索
dfs_edges = list(nx.dfs_edges(G, source=1))
print("深度优先搜索遍历边:", dfs_edges)# 广度优先搜索
bfs_edges = list(nx.bfs_edges(G, source=1))
print("广度优先搜索遍历边:", bfs_edges)
4.3.3 最短路径
# 添加权重边
G.add_weighted_edges_from([(1, 2, 1), (2, 3, 2), (3, 4, 1), (1, 4, 3)])# Dijkstra算法求最短路径
shortest_path = nx.dijkstra_path(G, source=1, target=4)
print("最短路径:", shortest_path)
4.3.4 最小生成树
# 计算最小生成树
mst = nx.minimum_spanning_tree(G)
print("最小生成树的边:", list(mst.edges(data=True)))# 绘制最小生成树
nx.draw(mst, with_labels=True)
plt.show()
4.3.5 最大流
# 创建有向图
DG = nx.DiGraph()
DG.add_weighted_edges_from([(1, 2, 16), (1, 3, 13), (2, 3, 10), (2, 4, 12),(3, 2, 4), (3, 5, 14), (4, 3, 9), (4, 6, 20),(5, 4, 7), (5, 6, 4)])# 计算最大流
flow_value, flow_dict = nx.maximum_flow(DG, 1, 6)
print("最大流量:", flow_value)
print("流经各边的流量:", flow_dict)

4.4 综合示例:社交网络分析

假设我们有一个简单的社交网络,其中节点代表人,边代表两人之间的友谊。

# 创建一个社交网络图
social_network = nx.Graph()# 添加节点(用户)
social_network.add_nodes_from(['Alice', 'Bob', 'Catherine', 'David', 'Eve'])# 添加边(友谊关系)
social_network.add_edges_from([('Alice', 'Bob'), ('Alice', 'Catherine'),('Bob', 'David'), ('Catherine', 'David'),('David', 'Eve'), ('Eve', 'Alice')])# 分析社交网络
print("节点数:", social_network.number_of_nodes())
print("边数:", social_network.number_of_edges())
print("Alice的度:", social_network.degree('Alice'))
print("Alice到David的最短路径:", nx.shortest_path(social_network, source='Alice', target='David'))# 可视化社交网络
nx.draw(social_network, with_labels=True, node_color='lightblue', node_size=500, edge_color='gray')
plt.show()

NetworkX提供了丰富的功能和灵活的API,可以方便地进行复杂网络的建模、分析和可视化。通过使用NetworkX,我们可以更好地理解和处理各种类型的网络问题。

5. 图论算法:TSP问题与VRP问题

TSP问题(旅行商问题)和VRP问题(车辆路径规划问题)都是组合优化中的经典问题,具有广泛的实际应用。以下详细介绍这两个问题的定义、求解方法及其在现实生活中的应用。

5.1 TSP问题(旅行商问题)

5.1.1 定义

旅行商问题(TSP, Traveling Salesman Problem)描述了一位旅行商需要访问一组城市,并找到一条最短的路径,使得他从起始城市出发,访问每个城市一次,最终回到起始城市。TSP的目标是最小化旅行总距离或总成本。

5.1.2 解决方法

由于TSP问题是NP难问题,没有已知的多项式时间复杂度算法可以求解所有实例。常见的解决方法包括:

  • 穷举法:尝试所有可能的路径组合,计算每条路径的总距离。对于少量城市,这种方法可行,但城市数量较多时,计算量会急剧增加。
  • 近似算法:例如最近邻算法、贪心算法等,它们通常无法保证找到最优解,但能在较短时间内找到一个近似最优解。
  • 启发式和元启发式算法:如模拟退火算法、遗传算法和蚁群优化算法等,这些方法通过模拟自然过程或生物行为来寻找近似解,通常可以在可接受的时间内找到一个较优的解。
5.1.3 Python实现示例

以下示例使用NetworkX库创建一个TSP问题的实例,并使用近似算法(最近邻算法)求解:

import networkx as nx
import matplotlib.pyplot as plt# 创建一个包含节点和边的图(城市和路径)
G = nx.Graph()
G.add_weighted_edges_from([('A', 'B', 4), ('A', 'C', 2), ('A', 'D', 7),('B', 'C', 1), ('B', 'D', 5),('C', 'D', 3)
])# 绘制图
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=500, edge_color='gray')
labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=labels)
plt.show()# 最近邻算法求解TSP
def nearest_neighbor_tsp(G, start):path = [start]nodes = set(G.nodes)nodes.remove(start)current = startwhile nodes:next_node = min(nodes, key=lambda node: G[current][node]['weight'])path.append(next_node)nodes.remove(next_node)current = next_nodepath.append(start)return path# 求解TSP
start_city = 'A'
tsp_path = nearest_neighbor_tsp(G, start_city)
print("TSP路径:", tsp_path)

5.2 VRP问题(车辆路径规划问题)

5.2.1 定义

车辆路径规划问题(VRP, Vehicle Routing Problem)描述了一组车辆需要从一个或多个配送中心出发,按照一定规则访问一组客户或城市,完成货物配送任务。目标是最小化总行驶距离、时间或成本,同时满足车辆容量、时间窗口等约束条件。

5.2.2 解决方法

VRP问题同样是NP难问题,其求解方法包括:

  • 精确算法:例如分支定界法(Branch and Bound)、动态规划等,适用于小规模问题。
  • 近似算法:例如贪心算法、启发式算法等,适用于较大规模问题,但无法保证最优解。
  • 元启发式算法:如模拟退火、遗传算法、蚁群优化等,适用于大规模问题,通常能找到较优的解。
5.2.3 Python实现示例

以下示例使用NetworkX和基于启发式方法的基本VRP求解:

import networkx as nx
import matplotlib.pyplot as plt
from itertools import permutations# 创建一个包含节点和边的图(客户和路径)
G = nx.Graph()
G.add_weighted_edges_from([('Depot', 'A', 10), ('Depot', 'B', 20), ('Depot', 'C', 15),('A', 'B', 35), ('A', 'C', 25), ('B', 'C', 30)
])# 假设车辆的容量为2,客户的需求为1
customers = {'A': 1, 'B': 1, 'C': 1}
vehicle_capacity = 2# 绘制图
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_color='lightblue', node_size=500, edge_color='gray')
labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=labels)
plt.show()# 简单的VRP求解方法(基于穷举法和分配法)
def vrp(G, depot, customers, vehicle_capacity):routes = []customers_list = list(customers.keys())min_distance = float('inf')best_route = Nonefor perm in permutations(customers_list):route = [depot] + list(perm) + [depot]capacity = vehicle_capacitydistance = 0valid = Truefor i in range(len(route) - 1):if route[i] in customers:capacity -= customers[route[i]]if capacity < 0:valid = Falsebreakdistance += G[route[i]][route[i+1]]['weight']if valid and distance < min_distance:min_distance = distancebest_route = routereturn best_route, min_distance# 求解VRP
best_route, min_distance = vrp(G, 'Depot', customers, vehicle_capacity)
print("最佳路径:", best_route)
print("最短距离:", min_distance)

TSP问题和VRP问题在现实生活中有着重要的应用,如物流配送、交通路线规划等。尽管这两个问题都是NP难问题,但通过近似算法、启发式和元启发式方法,我们能够在合理的时间内找到满意的解决方案。NetworkX库提供了丰富的图论工具,可以帮助我们轻松地进行复杂网络的建模和分析。

6. 学习心得

本次学习增强了我对图论和复杂网络的理解,了解复杂网络的基本概念,树的基本要素包括节点、边、权值、父节点、根节点和叶子节点;图的遍历算法:包括深度优先搜索(DFS)和广度优先搜索(BFS)。
同时掌握了利用Python库进行网络建模和算法实现的技能,如了解了TSP和VRP问题的定义和求解方法,并通过Python代码进行了实际求解;使用NetworkX进行基本图操作、图的遍历、最短路径、最小生成树、最大流以及社交网络分析。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/862831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Postman接口测试工具的原理及应用详解(六)

本系列文章简介&#xff1a; 在当今软件开发的世界中&#xff0c;接口测试作为保证软件质量的重要一环&#xff0c;其重要性不言而喻。随着前后端分离开发模式的普及&#xff0c;接口测试已成为连接前后端开发的桥梁&#xff0c;确保前后端之间的数据交互准确无误。在这样的背景…

[ruby on rails]rails6.0升级6.1

1.准备工作 在开始升级过程之前&#xff0c;我们有一些建议的准备工作。 升级的时候&#xff0c;最好一个版本一个版本升级&#xff0c;比如6.0到6.1再到7.0&#xff0c;不要一次从6.0到7.0至少80%的测试覆盖率&#xff0c;测试真的很重要&#xff0c;能确保升级快速完成。本…

SpringCloud - 微服务

SpringCloud 是一个用于构建微服务的开源框架&#xff0c;它提供了一系列用于微服务架构的工具和组件&#xff0c;包括服务注册与发现、负载均衡、熔断器、路由等1。以下是关于 SpringCloud 的详细介绍&#xff1a; 1. 服务注册与发现&#xff1a;SpringCloud 提供了服务注册与…

【每日一练】python运算符

1. 算术运算符 编写一个Python程序&#xff0c;要求用户输入两个数&#xff0c;并执行以下运算&#xff1a;加法、减法、乘法、求余、除法、以及第一个数的第二个数次方。将结果打印出来。 a input("请输入第一个数&#xff1a;") b input("请输入第二个数&…

Word中输入文字时,后面的文字消失

当在Word中输入文字时&#xff0c;如果发现后面的文字消失&#xff0c;通常是由以下3个原因造成的&#xff1a; 检查Insert键状态&#xff1a;首先确认是否误按了Insert键。如果是&#xff0c;请再次按下Insert键以切换回插入模式。在插入模式下&#xff0c;新输入的文字会插入…

15秒下雨短视频:成都柏煜文化传媒有限公司

15秒下雨短视频&#xff1a;瞬间的诗意与情感共鸣 在数字时代的浪潮中&#xff0c;短视频以其独特的魅力&#xff0c;成为了人们生活中不可或缺的一部分。其中&#xff0c;一段仅15秒的下雨短视频&#xff0c;成都柏煜文化传媒有限公司 或许在时间长河中只是一瞬间&#xff0c…

adb删除系统应用

连接手机到电脑&#xff1a; 使用 USB 数据线将手机连接到电脑&#xff0c;并确保已启用 USB 调试模式。 打开命令提示符或终端&#xff1a; 在电脑上打开命令提示符&#xff08;Windows&#xff09;或终端&#xff08;Mac、Linux&#xff09;。 检查设备连接&#xff1a; 输…

集群分布式储存

硬件&#xff1a; 存储柜 软件 &#xff1a; software define storage 分布式存储 是一种独特的系统架构由一组能够通过网络连通&#xff0c;为了完成共同任务而协调任务的计算机节点组成分布式是为了使用廉价的普通的计算机完成复杂的计算和存储任务目的就是利用更多的机…

PLC 上位机 下位机 嵌入式 区别

PLC&#xff08;可编程逻辑控制器&#xff09;、上位机、下位机以及嵌入式系统是在工业自动化和控制系统中常见的概念&#xff0c;它们在功能定位、处理能力以及通信协议等方面有所区别。具体分析如下&#xff1a; 功能定位 PLC&#xff1a;直接与传感器、执行器等硬件相连的设…

关于日常开发和面试——集合List及数组避坑之一二

1、集合与循环的碰撞 关于在循环中对集合进行新增或删除元素操作的问题。这是一个常见的陷阱&#xff0c;因为这样做可能导致迭代器失效或者遍历到不应该访问的元素。 以下是一个简单的示例代码&#xff0c;展示了为什么不能在循环中对集合进行新增或删除元素操作&#xff1a…

【详细】CNN中的卷积计算是什么-实例讲解

本文来自《老饼讲解-BP神经网络》https://www.bbbdata.com/ 目录 一、 CNN的基础卷积计算1.1.一个例子了解CNN的卷积计算是什么1.2.卷积层的生物意义 二、卷积的拓展&#xff1a;多输入通道与多输出通道2.1.多输入通道卷积2.2.多输出通道卷积 三、卷积的实现3.1.pytorch实现卷积…

Redis 缓存预热、缓存雪崩、缓存击穿、缓存穿透业务实践

0、前言 本文所有代码可见 > 【gitee code demo】 本文会涉及 缓存预热、缓存雪崩、缓存击穿、缓存穿透介绍和解决方案业务实践 1、缓存预热 1.1、描述 提前将热点数据加载到缓存&#xff0c;提前响应&#xff0c;降低后端数据源访问压力 1.2、实践 Autowiredprivate R…

3、微服务设计为什么要选择DDD

微服务设计为什么要选择DDD 1 软件架构的演进史 在深入探讨为什么在微服务设计中选择领域驱动设计&#xff08;DDD&#xff09;之前&#xff0c;我们先来了解一下软件架构的发展和演变历史。软件架构的演进通常与设备和技术的发展密切相关&#xff0c;随着设备和技术的不断进…

搭建Renesas R7FA8D1BHECBD-BTB的开发调试环境(DAP-LINK: N32G45XVL-STB)

目录 概述 1 软硬件 1.1 软硬件环境信息 1.2 开发板信息 1.3 调试器信息 2 FSP和KEIL产生测试项目 2.1 FSP生成项目 2.2 Keil中配置 3 硬件连接框图 4 一个测试案例 4.1 功能介绍 4.2 定时器函数 5 测试 搭建Renesas R7FA8D1BHECBD-BTB的开发调试环境&#xff08…

MySQL【触发器、存储过程、函数、范式】

day53 MySQL 触发器 创建触发器&#xff1a;&#xff08;before &#xff1a; 前置触发器、after &#xff1a;后置触发器&#xff09; 语法&#xff1a; delimiter xx 指定分隔符xxcreate trigger 触发器名 [before | after] 触发事件 on 表名 for each row 执行语句begin…

java LinkedList 怎么保证线程安全

在 Java 中&#xff0c;LinkedList 本身并不是线程安全的。如果需要在多线程环境中使用 LinkedList&#xff0c;可以采取以下几种方法来保证线程安全性&#xff1a; 1. 使用 Collections.synchronizedList Java 提供了一个实用的方法 Collections.synchronizedList 来包装 Li…

重磅!UOSDN焕新,开启创新之旅!

亲爱的开发者们 经过精心打磨和优化 全新改版的UOSDN&#xff08;统信开发者支持网络&#xff09; 已经正式上线啦&#xff01; 我们致力于为您打造一个更加便捷、高效、富有创意和互动性的开发平台&#xff0c;详情&#x1f449;https://uosdn.uniontech.com/ 以UOSDN作为载…

数字信号处理实验四(FIR数字滤波器设计)

FIR数字滤波器设计&#xff08;2学时&#xff09; 要求&#xff1a; 设计一个最小阶次的低通FIR数字滤波器&#xff0c;性能指标为&#xff1a;通带0Hz~1500Hz&#xff0c;阻带截止频率2000Hz&#xff0c;通带波动不大于1%&#xff0c;阻带波动不大于1%&#xff0c;采样频率为8…

【Chrome开发者工具概览】

Chrome开发者工具概览 一、开启 Chrome 开发者工具1. 如何打开开发者工具2. 主要组成部分 二、Elements 栏的使用1. 修改页面元素2. 调整 CSS 样式3. 搜索功能 三、Console 栏的探索1. 执行 JavaScript2. 调试技巧3. 监听事件和修改元素 四、利用 Sources 栏调试代码1. 查看源代…

常见的反爬手段和解决思路(爬虫与反爬虫)

常见的反爬手段和解决思路&#xff08;爬虫与反爬虫&#xff09; 学习目标1 服务器反爬的原因2 服务器长反什么样的爬虫&#xff08;1&#xff09;十分低级的应届毕业生&#xff08;2&#xff09;十分低级的创业小公司&#xff08;3&#xff09;不小心写错了没人去停止的失控小…