当前位置: 首页 > news >正文

利用【MATLAB】和【Python】进行【图与网络模型】的高级应用与分析】

目录

一、图与网络的基本概念

1. 无向图与有向图

2. 简单图、完全图、赋权图

3. 顶点的度

4. 子图与连通性

5. 图的矩阵表示

MATLAB代码实例

Python代码实例 

二、最短路径问题

1. 最短路径问题的定义

2. Dijkstra算法

MATLAB代码实例

Python代码实例

三、最小生成树问题

1. 最小生成树的定义

2. Kruskal算法

MATLAB代码实例

Python代码实例

注意的细节知识点

四、钢管订购和运输问题

1. 问题描述

2. 问题分析

需要综合考虑订购费用、运输费用和铺设费用。

3. 模型的建立与求解

MATLAB代码实例

Python代码实例 

五、MATLAB工具箱的应用

1. MATLAB在图与网络中的应用

MATLAB代码实例

结论

​编辑


ce6fbd68767d465bbe94b775b8b811db.png

731bd47804784fa2897220a90a387b28.gif

专栏:数学建模学习笔记

一、图与网络的基本概念

1. 无向图与有向图

  • 无向图:由顶点集合和边集合组成,边是无方向的。表示为 G=(V,E),其中 V 是顶点集合, E 是边集合。
  • 有向图:边是有方向的,从一个顶点指向另一个顶点。表示为 G=(V,E),其中每条边用有序对表示。

2. 简单图、完全图、赋权图

  • 简单图:无重复边和自环的图。
  • 完全图:每对顶点之间都有边的图, Kn​ 表示n个顶点的完全图。
  • 赋权图:边带有权值的图,用于表示边的某种属性,如距离、费用等。

3. 顶点的度

  • :与顶点相连的边的数目。在无向图中,顶点的度即为相连边的数目。在有向图中,入度为指向该顶点的边数,出度为从该顶点出发的边数。

4. 子图与连通性

  • 子图:由原图的一部分顶点和边组成的图。
  • 连通性:图中任意两顶点之间存在路径。无向图称为连通图,有向图称为强连通图。

5. 图的矩阵表示

  • 邻接矩阵:表示顶点之间是否有边的矩阵。若顶点 i 和顶点 j 之间有边,则矩阵A[i][j] 为1,否则为0。
  • 关联矩阵:表示顶点和边关系的矩阵。若边ek​ 连接顶点 vi​ 和 vj​,则矩阵 A[i][k] 和]A[j][k] 分别为1。

MATLAB代码实例

% MATLAB代码
% 创建无向图和有向图的邻接矩阵表示% 无向图的邻接矩阵
A_undirected = [0 1 1 0; 1 0 1 1; 1 1 0 1; 0 1 1 0];% 有向图的邻接矩阵
A_directed = [0 1 0 0; 0 0 1 0; 0 0 0 1; 1 0 0 0];% 显示邻接矩阵
disp('无向图的邻接矩阵:');
disp(A_undirected);disp('有向图的邻接矩阵:');
disp(A_directed);% 创建图对象并可视化
G_undirected = graph(A_undirected);
G_directed = digraph(A_directed);% 绘制图
figure;
subplot(1,2,1);
plot(G_undirected);
title('无向图');subplot(1,2,2);
plot(G_directed);
title('有向图');
无向图的邻接矩阵:0     1     1     01     0     1     11     1     0     10     1     1     0有向图的邻接矩阵:0     1     0     00     0     1     00     0     0     11     0     0     0

邻接矩阵表示无向图的邻接矩阵:A_undirected 是一个4x4矩阵,其中 A_undirected(i, j) 表示顶点 i 和顶点 j 之间是否有边。对于无向图,矩阵是对称的。
有向图的邻接矩阵:A_directed 是一个4x4矩阵,其中 A_directed(i, j) 表示顶点 i 到顶点 j 之间是否有边。对于有向图,矩阵不是对称的。
显示邻接矩阵使用 disp 函数显示无向图和有向图的邻接矩阵,以便于检查矩阵的正确性。
创建图对象并可视化graph(A_undirected) 创建无向图对象。
digraph(A_directed) 创建有向图对象。
使用 plot 函数可视化图对象。subplot 函数将图分成两部分,分别显示无向图和有向图。

Python代码实例 

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.font_manager import FontProperties# 设置中文字体
font = FontProperties(fname=r"C:\Windows\Fonts\simsun.ttc", size=15)# 无向图的邻接矩阵
A_undirected = np.array([[0, 1, 1, 0],[1, 0, 1, 1],[1, 1, 0, 1],[0, 1, 1, 0]
])# 有向图的邻接矩阵
A_directed = np.array([[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1],[1, 0, 0, 0]
])# 使用邻接矩阵创建无向图和有向图
G_undirected = nx.from_numpy_array(A_undirected)
G_directed = nx.from_numpy_array(A_directed, create_using=nx.DiGraph)# 绘制无向图
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
nx.draw(G_undirected, with_labels=True, node_color='skyblue', edge_color='black', node_size=1500, font_size=20)
plt.title('无向图', fontproperties=font)# 绘制有向图
plt.subplot(1, 2, 2)
nx.draw(G_directed, with_labels=True, node_color='lightgreen', edge_color='red', node_size=1500, font_size=20, arrows=True)
plt.title('有向图', fontproperties=font)plt.show()

注意的细节知识点邻接矩阵表示确保邻接矩阵的对称性(对于无向图)。
邻接矩阵的大小应为 n x n,其中 n 是顶点数量。
显示矩阵使用 disp 或 print 函数显示矩阵,便于检查矩阵的正确性。
创建图对象使用 graph 和 digraph 函数分别创建无向图和有向图对象。
确保输入的邻接矩阵符合图的类型(无向或有向)。
可视化图使用 plot 函数可视化图对象,便于直观理解图的结构。
在Python中,可以使用 networkx 库中的 draw 函数进行可视化,matplotlib 库中的 subplot 函数分割图形窗口。
MATLAB和Python的差异MATLAB中的 graph 和 digraph 函数对应于Python中的 nx.Graph 和 nx.DiGraph。
MATLAB中的 disp 函数对应于Python中的 print 函数。
MATLAB中的 plot 函数对应于Python中的 nx.draw 函数。

二、最短路径问题

1. 最短路径问题的定义

  • 最短路径问题是寻找从一个顶点到另一个顶点的路径,使得路径上的边权值和最小。

2. Dijkstra算法

  • 适用于非负权图的单源最短路径问题。
  • 算法步骤:
    1. 初始化:设置起点到自己的距离为0,其他顶点为无穷大。
    2. 选择未处理的顶点中距离最小的顶点,将其标记为已处理。
    3. 更新该顶点的邻接顶点的距离。
    4. 重复步骤2和3,直到所有顶点都被处理。

MATLAB代码实例

% MATLAB代码
% Dijkstra算法实现
function [dist, path] = dijkstra(A, start_node)n = size(A, 1); % 顶点数量dist = inf(1, n); % 初始化距离dist(start_node) = 0;visited = false(1, n); % 访问标记path = -ones(1, n); % 路径for i = 1:n% 选择未处理顶点中距离最小的顶点[~, u] = min(dist + visited * inf);visited(u) = true;% 更新邻接顶点的距离for v = 1:nif A(u, v) > 0 && ~visited(v)alt = dist(u) + A(u, v);if alt < dist(v)dist(v) = alt;path(v) = u;endendendend
end% 示例图的邻接矩阵
A = [0 10 20 0 0;10 0 5 1 0;20 5 0 2 3;0 1 2 0 4;0 0 3 4 0];% 计算从起点1到其他顶点的最短路径
[start_node] = 1;
[dist, path] = dijkstra(A, start_node);% 显示结果
disp('顶点的最短距离:');
disp(dist);
disp('最短路径:');
disp(path);% 可视化结果
G = digraph(A);
figure;
h = plot(G, 'EdgeLabel', G.Edges.Weight);
highlight(h, path, 'EdgeColor', 'r', 'LineWidth', 2);
title('Dijkstra最短路径');
顶点的最短距离:0    10    20   Inf   Inf最短路径:-1     1     1    -1    -1

 

初始化n = size(A, 1):获取图中顶点的数量。
dist = inf(1, n):初始化每个顶点的距离为无穷大。
dist(start_node) = 0:起点到自身的距离为0。
visited = false(1, n):初始化访问标记。
path = -ones(1, n):初始化路径数组。
主循环for i = 1:n:对每个顶点进行迭代。
[~, u] = min(dist + visited * inf):选择未处理顶点中距离最小的顶点。
visited(u) = true:将该顶点标记为已处理。
更新邻接顶点的距离for v = 1:n:对每个邻接顶点进行迭代。
if A(u, v) > 0 && ~visited(v):如果顶点 v 与顶点 u 之间有边且未被访问。
alt = dist(u) + A(u, v):计算通过顶点 u 到顶点 v 的距离。
if alt < dist(v):如果通过 u 到 v 的距离小于当前已知的 v 的距离。
dist(v) = alt:更新 v 的距离。
path(v) = u:更新 v 的路径。

Python代码实例

import heapqdef dijkstra(A, start_node):n = len(A)dist = [float('inf')] * ndist[start_node] = 0visited = [False] * npath = [-1] * nqueue = [(0, start_node)]while queue:d, u = heapq.heappop(queue)if visited[u]:continuevisited[u] = Truefor v, weight in enumerate(A[u]):if weight > 0 and not visited[v]:alt = dist[u] + weightif alt < dist[v]:dist[v] = altpath[v] = uheapq.heappush(queue, (alt, v))return dist, path# 示例图的邻接矩阵
A = [[0, 10, 20, 0, 0],[10, 0, 5, 1, 0],[20, 5, 0, 2, 3],[0, 1, 2, 0, 4],[0, 0, 3, 4, 0]
]# 计算从起点0到其他顶点的最短路径
start_node = 0
dist, path = dijkstra(A, start_node)# 显示结果
print('顶点的最短距离:', dist)
print('最短路径:', path)
顶点的最短距离: [0, 10, 13, 11, 15]
最短路径: [-1, 0, 3, 1, 3]

三、最小生成树问题

1. 最小生成树的定义

  • 最小生成树(MST)是包含图中所有顶点且边权值和最小的生成树。

2. Kruskal算法

  • 适用于任意图。
  • 算法步骤:
    1. 将图中的边按权值从小到大排序。
    2. 依次选择权值最小的边,若该边的加入不形成圈,则将其加入生成树。
    3. 重复步骤2,直到生成树包含所有顶点。

MATLAB代码实例

% MATLAB代码
% Kruskal算法实现
function [mst_edges, mst_weight] = kruskal(A)n = size(A, 1);edges = [];for i = 1:nfor j = i+1:nif A(i, j) > 0edges = [edges; i, j, A(i, j)];endendendedges = sortrows(edges, 3);parent = 1:n;mst_edges = [];mst_weight = 0;function p = find(parent, x)if parent(x) == xp = x;elsep = find(parent, parent(x));parent(x) = p;endendfor k = 1:size(edges, 1)u = edges(k, 1);v = edges(k, 2);w = edges(k, 3);pu = find(parent, u);pv = find(parent, v);if pu ~= pvmst_edges = [mst_edges; u, v];mst_weight = mst_weight + w;parent(pu) = pv;endend
end% 示例图的邻接矩阵
A = [0 10 6 5;10 0 0 15;6 0 0 4;5 15 4 0];% 计算最小生成树
[mst_edges, mst_weight] = kruskal(A);% 显示结果
disp('最小生成树的边:');
disp(mst_edges);
disp('最小生成树的权重:');
disp(mst_weight);% 可视化结果
G = graph(A);
figure;
h = plot(G, 'EdgeLabel', G.Edges.Weight);
highlight(h, mst_edges(:,1), mst_edges(:,2), 'EdgeColor', 'r', 'LineWidth', 2);
title('Kruskal最小生成树');
最小生成树的边:3     41     41     2最小生成树的权重:19

 

初始化n = size(A, 1):获取图中顶点的数量。
edges = []:初始化边的列表。
使用嵌套循环遍历邻接矩阵,收集所有边的信息。
边的排序edges = sortrows(edges, 3):按边的权值从小到大排序。
并查集的初始化parent = 1:n:初始化每个顶点的父节点为自身。
mst_edges = []:初始化最小生成树的边列表。
mst_weight = 0:初始化最小生成树的权重和。
并查集查找函数function p = find(parent, x):递归查找顶点的根节点,并进行路径压缩。

Python代码实例

class UnionFind:def __init__(self, n):self.parent = list(range(n))def find(self, u):if self.parent[u] != u:self.parent[u] = self.find(self.parent[u])return self.parent[u]def union(self, u, v):root_u = self.find(u)root_v = self.find(v)if root_u != root_v:self.parent[root_u] = root_vdef kruskal(A):n = len(A)edges = [(A[i][j], i, j) for i in range(n) for j in range(i + 1, n) if A[i][j] > 0]edges.sort()uf = UnionFind(n)mst_edges = []mst_weight = 0for weight, u, v in edges:if uf.find(u) != uf.find(v):uf.union(u, v)mst_edges.append((u, v))mst_weight += weightreturn mst_edges, mst_weight# 示例图的邻接矩阵
A = [[0, 10, 6, 5],[10, 0, 0, 15],[6, 0, 0, 4],[5, 15, 4, 0]
]# 计算最小生成树
mst_edges, mst_weight = kruskal(A)# 显示结果
print('最小生成树的边:', mst_edges)
print('最小生成树的权重:', mst_weight)

注意的细节知识点

  1. 初始化

    • 确保并查集正确初始化,每个顶点的父节点为自身。
  2. 边的收集与排序

    • 收集所有边的信息,并按权值从小到大排序,以便于后续选择最小权值边。
  3. 并查集查找函数

    • 使用递归查找顶点的根节点,并进行路径压缩,提高查找效率。
  4. 边的选择与合并

    • 在选择边时,确保不会形成圈,使用并查集的查找和合并操作。
    • 更新最小生成树的边和权重,确保最小生成树的正确性。

四、钢管订购和运输问题

1. 问题描述

  • 需要从多个钢厂订购钢管,并将其运输到施工地点,铺设天然气主管道。
  • 图中表示钢厂、枢纽点和施工地点,边的权值表示运输距离。

2. 问题分析

  • 分解为两个子问题:从钢厂到枢纽点的运输和从枢纽点到施工地点的铺设。
  • 需要综合考虑订购费用、运输费用和铺设费用。

3. 模型的建立与求解

  • 运费矩阵的计算模型:计算从供应点到需求点的最小购运费。
  • 总费用的数学规划模型:包括订购费用、运输费用和铺设管道的运费。
  • 模型求解:利用Floyd算法计算最短路径,运用数学规划模型优化总费用。

MATLAB代码实例

% MATLAB代码
% 构造铁路距离赋权图
function dist = floyd_warshall(A)n = size(A, 1);dist = A;dist(dist == 0) = inf;dist(1:n+1:end) = 0;for k = 1:nfor i = 1:nfor j = 1:nif dist(i, k) + dist(k, j) < dist(i, j)dist(i, j) = dist(i, k) + dist(k, j);endendendend
end% 示例图的邻接矩阵
A = [0 10 inf inf inf;10 0 5 inf inf;inf 5 0 3 inf;inf inf 3 0 1;inf inf inf 1 0];% 计算最短路径
dist = floyd_warshall(A);% 计算总费用的数学规划模型
function total_cost = steel_pipeline_optimization(supplies, demands, cost_matrix)n_suppliers = length(supplies);n_demands = length(demands);total_cost = 0;for i = 1:n_suppliersfor j = 1:n_demandstotal_cost = total_cost + supplies(i) * cost_matrix(i, j);endend
end% 示例数据
supplies = [100, 200, 150];
demands = [50, 100, 200, 100];
cost_matrix = [2, 4, 5, 6;3, 2, 7, 4;6, 5, 2, 3];% 计算总费用
total_cost = steel_pipeline_optimization(supplies, demands, cost_matrix);% 显示结果
disp('总费用:');
disp(total_cost);% 可视化结果
figure;
imagesc(dist);
colorbar;
title('Floyd-Warshall最短路径距离矩阵');
xlabel('目标节点');
ylabel('起始节点');

 

  1. Floyd-Warshall算法

    • function dist = floyd_warshall(A):定义Floyd-Warshall算法函数。
    • n = size(A, 1):获取图中顶点的数量。
    • dist = A:初始化距离矩阵。
    • dist(dist == 0) = inf:将邻接矩阵中的0(无边)替换为无穷大。
    • dist(1:n+1:end) = 0:对角线上的元素设为0,表示自身到自身的距离为0。
    • for k = 1:n, for i = 1:n, for j = 1:n:三重循环更新距离矩阵。
    • if dist(i, k) + dist(k, j) < dist(i, j):如果通过顶点 k 的路径更短,则更新距离。
    • dist(i, j) = dist(i, k) + dist(k, j):更新距离矩阵。
  1. 总费用的数学规划模型

    • function total_cost = steel_pipeline_optimization(supplies, demands, cost_matrix):定义总费用计算函数。
    • n_suppliers = length(supplies):获取供应点数量。
    • n_demands = length(demands):获取需求点数量。
    • total_cost = 0:初始化总费用。
    • for i = 1:n_suppliers, for j = 1:n_demands:双重循环遍历供应点和需求点。
    • total_cost = total_cost + supplies(i) * cost_matrix(i, j):累加各供应点到各需求点的费用。

Python代码实例 

import numpy as npdef floyd_warshall(A):n = len(A)dist = np.array(A, dtype=float)dist[dist == 0] = np.infnp.fill_diagonal(dist, 0)for k in range(n):for i in range(n):for j in range(n):if dist[i, k] + dist[k, j] < dist[i, j]:dist[i, j] = dist[i, k] + dist[k, j]return dist# 示例图的邻接矩阵
A = [[0, 10, float('inf'), float('inf'), float('inf')],[10, 0, 5, float('inf'), float('inf')],[float('inf'), 5, 0, 3, float('inf')],[float('inf'), float('inf'), 3, 0, 1],[float('inf'), float('inf'), float('inf'), 1, 0]
]# 计算最短路径
dist = floyd_warshall(A)def steel_pipeline_optimization(supplies, demands, cost_matrix):total_cost = 0for i in range(len(supplies)):for j in range(len(demands)):total_cost += supplies[i] * cost_matrix[i][j]return total_cost# 示例数据
supplies = [100, 200, 150]
demands = [50, 100, 200, 100]
cost_matrix = [[2, 4, 5, 6],[3, 2, 7, 4],[6, 5, 2, 3]
]# 计算总费用
total_cost = steel_pipeline_optimization(supplies, demands, cost_matrix)# 显示结果
print('总费用:', total_cost)
总费用: 7300

五、MATLAB工具箱的应用

1. MATLAB在图与网络中的应用

  • MATLAB提供了强大的工具箱,用于处理图与网络问题。通过编写脚本和函数,可以实现图的生成、算法的实现及结果的可视化。

MATLAB代码实例

% 创建图对象并可视化
G = graph([1 2 2 3 3 4 4 5 5], [2 3 4 4 5 5 1 1 2], [10 20 30 40 50 60 70 80 90]);% 可视化图
figure;
plot(G, 'EdgeLabel', G.Edges.Weight);
title('图的可视化');% 计算最短路径
[start_node, end_node] = deal(1, 5);
[dist, path] = shortestpath(G, start_node, end_node);% 显示最短路径
disp('最短路径:');
disp(path);% 计算最小生成树
T = minspantree(G);
figure;
plot(T, 'EdgeLabel', T.Edges.Weight);
title('最小生成树');
最短路径:80

 

结论

图与网络模型是解决复杂系统问题的重要工具,通过合理的算法和数学模型,可以有效地解决最短路径、最小生成树等问题。利用MATLAB和Python等工具,可以大大简化计算过程,提高工作效率。在实际应用中,图与网络模型广泛用于通信网络建设、物流运输规划等领域,具有重要的现实意义。希望这篇详细的博客总结能够帮助您理解和应用图与网络模型的基本概念、算法及其在实际问题中的应用。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Android init 中的wait_for_property指令
  • matlab 异常值检测与处理——Robust Z-score法
  • XMl基本操作
  • 义务外贸wordpress独立站主题
  • WPF中MVVM常用的框架
  • 对JVM及Java并发编程的简单了解
  • 汇总国内镜像提供了Redis的下载地址
  • 【Vue3】选项式 API
  • 大语言模型-基础及拓展应用
  • HTML+CSS+JS精美气泡提示框
  • Linux系统编程:自定义协议(序列化和反序列化)
  • Shell 构建flutter + Navtive 生成IPA
  • 240719_图像二分类任务中图像像素值的转换-[0,255]-[0,1]
  • 无法启动此程序,因为计算机丢失api-ms-win-core-path-l1-1-0.dll的解决方案
  • SQL执行流程、SQL执行计划、SQL优化
  • 【React系列】如何构建React应用程序
  • angular学习第一篇-----环境搭建
  • django开发-定时任务的使用
  • Gradle 5.0 正式版发布
  • JavaScript的使用你知道几种?(上)
  • Java教程_软件开发基础
  • Just for fun——迅速写完快速排序
  • Laravel 菜鸟晋级之路
  • SpiderData 2019年2月16日 DApp数据排行榜
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 开发基于以太坊智能合约的DApp
  • 前端性能优化--懒加载和预加载
  • 如何使用 OAuth 2.0 将 LinkedIn 集成入 iOS 应用
  • 少走弯路,给Java 1~5 年程序员的建议
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • MyCAT水平分库
  • Python 之网络式编程
  • ​zookeeper集群配置与启动
  • ​十个常见的 Python 脚本 (详细介绍 + 代码举例)
  • # 服务治理中间件详解:Spring Cloud与Dubbo
  • #162 (Div. 2)
  • #单片机(TB6600驱动42步进电机)
  • (2024)docker-compose实战 (8)部署LAMP项目(最终版)
  • (3)医疗图像处理:MRI磁共振成像-快速采集--(杨正汉)
  • (4)(4.6) Triducer
  • (第9篇)大数据的的超级应用——数据挖掘-推荐系统
  • (二)PySpark3:SparkSQL编程
  • (二)换源+apt-get基础配置+搜狗拼音
  • (一) 初入MySQL 【认识和部署】
  • (转)nsfocus-绿盟科技笔试题目
  • (转载)(官方)UE4--图像编程----着色器开发
  • **登录+JWT+异常处理+拦截器+ThreadLocal-开发思想与代码实现**
  • .NET 2.0中新增的一些TryGet,TryParse等方法
  • .net MySql
  • .Net Remoting常用部署结构
  • .net 按比例显示图片的缩略图
  • .NET 项目中发送电子邮件异步处理和错误机制的解决方案