首页 > 编程语言 >利用【MATLAB】和【Python】进行【图与网络模型】的高级应用与分析】

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

时间:2024-07-21 22:53:49浏览次数:18  
标签:dist Python 模型 邻接矩阵 edges MATLAB 顶点 inf cost

目录

一、图与网络的基本概念

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     0
     1     0     1     1
     1     1     0     1
     0     1     1     0

有向图的邻接矩阵:
     0     1     0     0
     0     0     1     0
     0     0     0     1
     1     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:n
            if A(u, v) > 0 && ~visited(v)
                alt = dist(u) + A(u, v);
                if alt < dist(v)
                    dist(v) = alt;
                    path(v) = u;
                end
            end
        end
    end
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);
顶点的最短距离:
     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 heapq

def dijkstra(A, start_node):
    n = len(A)
    dist = [float('inf')] * n
    dist[start_node] = 0
    visited = [False] * n
    path = [-1] * n
    queue = [(0, start_node)]
    
    while queue:
        d, u = heapq.heappop(queue)
        if visited[u]:
            continue
        visited[u] = True
        
        for v, weight in enumerate(A[u]):
            if weight > 0 and not visited[v]:
                alt = dist[u] + weight
                if alt < dist[v]:
                    dist[v] = alt
                    path[v] = u
                    heapq.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:n
        for j = i+1:n
            if A(i, j) > 0
                edges = [edges; i, j, A(i, j)];
            end
        end
    end
    edges = sortrows(edges, 3);
    
    parent = 1:n;
    mst_edges = [];
    mst_weight = 0;
    
    function p = find(parent, x)
        if parent(x) == x
            p = x;
        else
            p = find(parent, parent(x));
            parent(x) = p;
        end
    end

    for 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 ~= pv
            mst_edges = [mst_edges; u, v];
            mst_weight = mst_weight + w;
            parent(pu) = pv;
        end
    end
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);
最小生成树的边:
     3     4
     1     4
     1     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_v

def 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 = 0
    
    for weight, u, v in edges:
        if uf.find(u) != uf.find(v):
            uf.union(u, v)
            mst_edges.append((u, v))
            mst_weight += weight
    
    return 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:n
        for i = 1:n
            for j = 1:n
                if dist(i, k) + dist(k, j) < dist(i, j)
                    dist(i, j) = dist(i, k) + dist(k, j);
                end
            end
        end
    end
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_suppliers
        for j = 1:n_demands
            total_cost = total_cost + supplies(i) * cost_matrix(i, j);
        end
    end
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);

  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 np

def floyd_warshall(A):
    n = len(A)
    dist = np.array(A, dtype=float)
    dist[dist == 0] = np.inf
    np.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 = 0
    for 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等工具,可以大大简化计算过程,提高工作效率。在实际应用中,图与网络模型广泛用于通信网络建设、物流运输规划等领域,具有重要的现实意义。希望这篇详细的博客总结能够帮助您理解和应用图与网络模型的基本概念、算法及其在实际问题中的应用。

标签:dist,Python,模型,邻接矩阵,edges,MATLAB,顶点,inf,cost
From: https://blog.csdn.net/2303_77720864/article/details/140594882

相关文章

  • python_wholeweek1
    目录(day1-7)一周的学习1.计算机之编程什么是编程语言什么是编程为什么要编程2.计算机组成原理计算机五大组成CPU控制器运算器内存外存输入设备输出设备(I/O设备)32位和64位32位64位多核CPU硬盘工作原理机械硬盘工作原理固态硬盘工作原理3.计算机操作系统文件是什么?应用程序是什......
  • python模块与包
    python模块与包1.模块(是一个python文件)自定义模块:(1)新建一个py文件在同一个project里然后可以用import先导入再在main里使用main.py importcc.ad(2,5)c.py defad(s,y):print(s+y)导入模块中的方法会自动实行被调用模块里所有所有语句(2)导入不同模块同一方法......
  • Python网络数据可视化全攻略【方法与技巧详解】
    ......
  • Python爬虫实战案例(爬取文字)
    爬取豆瓣电影的数据首先打开"豆瓣电影Top250"这个网页:按F12,找到网络;向上拉动,找到名称栏中的第一个,单机打开;可以在标头里看到请求URL和请求方式,复制URL(需要用到);在表头的最下面有"User-Agent",也复制下来(也可以下载pipinstallfake_useragent库,用别人写好的UA)。定位......
  • Python项目|基于Python+Django实现购物商城系统
    作者主页:编程千纸鹤作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待......
  • 基于gunicorn+flask+docker模型高并发部署(详细教程)
    关注我,持续分享逻辑思维&管理思维&面试题;可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导;推荐专栏《10天学会使用asp.net编程AI大模型》,目前已完成所有内容。一顿烧烤不到的费用,让人能紧跟时代的浪潮。从普通网站,到公众号、小程序,再到AI大模型网站。干货满满。学成后可......
  • 时间序列分析方法汇总对比及优缺点和适用情况(下)-- 11. 卡尔曼滤波 12. 广义自回归条件
    目录11.卡尔曼滤波(KalmanFilter)12.广义自回归条件异方差模型(GARCH)13.贝叶斯结构时间序列模型(BayesianStructuralTimeSeries,BSTS)14.动态因子模型(DynamicFactorModel,DFM)15.隐马尔科夫模型(HiddenMarkovModel,HMM)16.分段线性回归(PiecewiseLinearRegress......
  • 常见的Python编程题目及其代码(十二)-- 56. 检查字符串是否只包含数字57. 找到列表中出
    目录56.检查字符串是否只包含数字57.找到列表中出现次数最多的元素58.计算字符串中的元音数59.计算字符串中的辅音数60.找到字符串中的最长单词 56.检查字符串是否只包含数字s="12345"print(s.isdigit())57.找到列表中出现次数最多的元素fromcollection......
  • Python 简介
    什么是Python        Python的设计理念为优雅、明确、简单。实际上,Python也是按照这个理念做的,以至于现在网上流传着“人生苦短,我用Python”的说法。可见Python有着简单、开发速度快、节省时间和精力等特点。        Python本身并非所有的特性和功能都集成......
  • python 8 模块
    1.自定义模块及调用模块一:name='yyy'definfo():print('daydayup')模块二:name='lll2'age=16definfo():print('dayup2')函数importmy_infoprint(my_info.name)my_info.info()print('-'*40)impo......