Graph Theory of Mathematical Modeling

1 Basic concepts of graphs


A graph in graph theory is a graph composed of a number of given points and a line connecting the two points. This graph is usually used to describe a specific relationship between certain things. Points are used to represent things, and A line connecting two points indicates that there is a relationship between the corresponding two things.

A graph can be described in mathematical language as: G(V(G),E(G)). V(vertex)Refers to the vertex set of the graph, E(edge)and refers to the edge set of the graph.

Depending on whether the edges have direction, graphs can be divided into undirected graphs and directed graphs . In addition, some graphs may have weights on their edges, and such graphs are called weighted graphs .

Insert image description here

2 How to make pictures

2.1 Draw directly


URL of online drawing tool

Insert image description here

2.2 Programming and drawing


Undirected graph

  • graph(s,t): can create edges between corresponding nodes in sand and generate a grapht
  • graph(s,t,w): An edge can be created between corresponding nodes in sand with a weight and generate a graphtw

To make a directed graph, just graphchange digraphto .

1️⃣ Undirected graph

% 无权重,也可以说每条边的权重默认为1
s1 = [1,2,3,4];
t1 = [2,3,1,1];
% 函数graph(s,t):可在 s 和 t 中的对应节点之间创建边,并生成一个图
% s 和 t 都必须具有相同的元素数;这些节点必须都是从1开始的正整数,或都是字符串元胞数组。
G1 = graph(s1, t1);
plot(G1)

% 注意字符串元胞数组是用大括号包起来的哦
s2 = {
    
    '学校','电影院','网吧','酒店'};
t2 = {
    
    '电影院','酒店','酒店','KTV'};
G2 = graph(s2, t2);
plot(G2, 'linewidth', 2)  % 设置线的宽度
% 下面的命令是在画图后不显示坐标
set( gca, 'XTick', [], 'YTick', [] );  

% 有权重
s = [1,2,3,4];
t = [2,3,1,1];
w = [3,8,9,2];
% 函数graph(s,t,w):可在 s 和 t 中的对应节点之间以w的权重创建边,并生成一个图
G = graph(s, t, w);
plot(G, 'EdgeLabel', G.Edges.Weight, 'linewidth', 2) 
set( gca, 'XTick', [], 'YTick', [] );  

Insert image description here
Insert image description here

❗️Note:

  • Note, the numbers can only be numbered consecutively starting from 1 (otherwise an error will be reported). Do not define the numbers casually by yourself, because the default numbering is consecutive, and it is possible not to write it.
s = [1,2,3,50];
t = [2,3,1,1];
G = graph(s, t);
plot(G)

Insert image description here

2️⃣ Directed graph

% 无权图 digraph(s,t)
s = [1,2,3,4,1];
t = [2,3,1,1,4];
G1 = digraph(s, t);
plot(G1)
set( gca, 'XTick', [], 'YTick', [] );  

% 有权图 digraph(s,t,w)
s = [1,2,3,4];
t = [2,3,1,1];
w = [3,8,9,2];
G2 = digraph(s, t, w);
plot(G2, 'EdgeLabel', G.Edges.Weight, 'linewidth', 2) 
set( gca, 'XTick', [], 'YTick', [] );  

Insert image description here

☀️ Summary:

  • The graphs produced by Matlab are not very beautiful. If there are relatively few nodes, it is recommended to use online

3 Weighted adjacency matrix


3.1 Undirected graph


Insert image description here

3.2 Directed graph


Insert image description here

4 Dijkstra’s algorithm

4.1 Algorithm Overview


There are a total of nine locations from 0 to 8 in the picture. If the locations are connected by a straight line, it means that the two places can be reached directly. The value next to the straight line indicates the distance between the two places.

The starting point is 0 and the end point is 4. How to take the shortest distance?


Insert image description here

Use Dijkstraalgorithms to solve the above problems

1️⃣ Initialization

Visited: All nodes are unvisited;
Distance: The distance between all nodes is Inf;
Parent: The parent node (previous node) of all nodes is -1, indicating that it does not exist

Insert image description here

1️⃣ The starting point is 0, update the table:

  • The access status of node 0 changes to 1
  • The distance corresponding to node 0 becomes 0
  • The parent node of node 0 is represented by 0. Of course, it can be represented by other symbols.

Insert image description here

2️⃣ Update the information of the node (B) adjacent to node 0 (A). Note that the B node here is not visited.

  • If the distance between A and B + the distance between A is less than the distance between B, then we update the distance between B to a smaller distance, update the parent node of B to A, and include the nodes with a smaller distance into the visited in node

Insert image description here

Insert image description here

3️⃣ Update the information of the node (B) adjacent to node 1 (A). Note that the B node here is not visited.

  • If the distance between A and B + the distance between A is less than the distance between B, then we update the distance between B to a smaller distance, update the parent node of B to A, and include the nodes with a smaller distance into the visited in node

Insert image description here

Insert image description here

4️⃣ Repeat the above steps and finally get:

Insert image description here

Based on the above results, we can get the shortest path from node 0 to node 4:

Insert image description here

DijkstraThe algorithm is generally used to find the shortest path in undirected graphs, and can also be used in directed graphs. However, Dijkstraa shortcoming of the algorithm is that it cannot be used to process graphs with negative weights.

Insert image description here


Bellman‐Fordalgorithm


In order to solve Dijkstrathe shortcoming that the algorithm cannot be used to deal with graphs with negative weights, Bellman‐Fordan algorithm is proposed

In fact, Bellman‐Fordthe algorithm no longer distinguishes nodes into visited or not , because Bellman‐Fordthe algorithm uses loops to update weights, and every loop, Bellman‐Fordthe algorithm updates the information of all nodes.

Bellman‐FordThe algorithm does not support graphs containing negative weight cycles (nor does Floyd's algorithm)

Insert image description here

4.2 Code implementation


[P,d] = shortestpath(G,start,end [,'Method',algorithm])

  • Function: Return the shortest path from node to node Gin the graphstartend

  • Input parameters:

    • G: Input graph ( graphobject or digraphobject)
    • start: starting node
    • end: target node
    • [,‘Method’,algorithm]: is an optional parameter, indicating the algorithm for calculating the shortest path. Generally we do not need to set it manually, the default isauto
      Insert image description here
  • Output parameters:

    • Pnodes passed by the shortest path
    • dshortest distance

Sample code:

%% 注意:以下代码需要较新版本的matlab才能运行(最好是2016版本及以上)
% 如果运行出错请下载新版的matlab代码再运行

% 注意哦,Matlab中的图节点要从1开始编号,所以这里把0全部改为了9
% 编号最好是从1开始连续编号,不要自己随便定义编号
s = [9 9 1 1 2 2 2 7 7 6 6  5  5 4];
t = [1 7 7 2 8 3 5 8 6 8 5  3  4 3];
w = [4 8 3 8 2 7 4 1 6 6 2 14 10 9];
G = graph(s,t,w);
plot(G, 'EdgeLabel', G.Edges.Weight, 'linewidth', 2) 
set( gca, 'XTick', [], 'YTick', [] );  
[P,d] = shortestpath(G, 9, 4)  %注意:该函数matlab2015b之后才有哦

% 在图中高亮我们的最短路径
myplot = plot(G, 'EdgeLabel', G.Edges.Weight, 'linewidth', 2);  %首先将图赋给一个变量
highlight(myplot, P, 'EdgeColor', 'r')   %对这个变量即我们刚刚绘制的图形进行高亮处理(给边加上r红色)

% 求出任意两点的最短路径矩阵
D = distances(G)   %注意:该函数matlab2015b之后才有
D(1,2)  % 1 -> 2的最短路径
D(9,4)  % 9 -> 4的最短路径

% 找出给定范围内的所有点  nearest(G,s,d)
% 返回图形 G 中与节点 s 的距离在 d 之内的所有节点
[nodeIDs,dist] = nearest(G, 2, 10)   %注意:该函数matlab2016a之后才有

Output graphics:

Insert image description here

5 Floyd's algorithm

5.1 Algorithm Overview


FloydThe algorithm is an algorithm for solving the shortest path between any two points. It can correctly handle the shortest path problem of undirected graphs or directed graphs (negative weights are allowed, but negative weight loops cannot exist).

FloydCompared with the algorithm Dijkstraor Bellman‐Fordthe algorithm, the algorithm can find the shortest path between any two points at once . The latter two algorithms can only calculate the shortest path between the given starting point and the end point after one run. Of course, Floydthe calculation time of the algorithm is also higher than that of the latter two algorithms. The core steps of the algorithm consist of three layers of loops.

Algorithm animation display

Insert image description here
From the two conclusions observed above, it is not difficult for us to extract the following idea:

  • Suppose there is a starting point A and an end point B, then for any other intermediate point M: ,
    D(A,B) ≤ D(A,M) + D(M,B)here, D(X,Y) represents the shortest distance between the two points X and Y.

Therefore, the core of Floyd's algorithm actually lies in a three-layer loop

5.2 Code implementation


☀️Realize the distance of the shortest path between any two points


Insert image description here


☀️Find the shortest path (record the points passed by the shortest path)


Insert image description here

Insert image description here

Convert pseudocode to Matlab code :

Insert image description here


1️⃣ Define Floydalgorithm functionsFloyd_algorithm.m

function [dist,path] = Floyd_algorithm(D)
%% 该函数用于求解一个权重邻接矩阵任意两个节点之间的最短路径
% 输入:
%        D是权重邻接矩阵
% 输出:
%        dist是最短距离矩阵,其元素dist_ij表示表示i,j两个节点的最短距离
%        path是路径矩阵,其元素path_ij表示起点为i,终点为j的两个节点之间的最短路径要经过的节点

n = size(D,1);  % 计算节点的个数

% 初始化dist矩阵
dist = D;

% 下面我们来初始化path矩阵
path = zeros(n);
for j = 1:n
    path(:,j) = j;   % 将第j列的元素变为j
end
for i = 1:n
    path(i,i) = -1;  % 将主对角线元素变为-1
end

% 下面开始三个循环
for k=1:n    % 中间节点k从1- n 循环
   for i=1:n     % 起始节点i从1- n 循环
      for j=1:n    % 终点节点j从1-n 循环
          if dist(i,j)>dist(i,k)+dist(k,j)  % 如果i,j两个节点间的最短距离大于i和k的最短距离+k和j的最短距离
             dist(i,j)=dist(i,k)+dist(k,j);  % 那么我们就令这两个较短的距离之和取代i,j两点之间的最短距离
             path(i,j)=path(i,k);   % 起点为i,终点为j的两个节点之间的最短路径要经过的节点更新为path(i,k)
             % 注意,上面一行语句不能写成path(i,j) = k
          end
      end
   end
end

end

2️⃣ Define a function that prints the shortest path between any two nodesprint_path.m

function [] = print_path(path,dist,i,j)
%% 该函数的作用是打印从i到j经过的最短路径
% 输入:
%        path是使用floyd算法求出来的路径矩阵
%        dist是使用floyd算法求出来的最短距离矩阵
%        i是起始节点的编号
%        j是终点节点的编号
% 输出:无

if i == j
    warning('起点和终点相同,请检查后重新输入')  % 在屏幕中提示警告信息
    return;  % 不运行下面的语句,直接退出函数
end
if path(i,j) == j   % 如果path(i,j) = j,则有两种可能:
% (1)如果dist(i,j) 为 Inf , 则说明从i到j没有路径可以到达
    if dist(i,j) == Inf
        disp(['从',num2str(i),'到',num2str(j),'没有路径可以到达'])
% (2)如果dist(i,j) 不为 Inf , 则说明从i到j可直接到达,且为最短路径
    else
        disp(['从',num2str(i),'到',num2str(j),'的最短路径为'])
        disp([num2str(i),' ---> ',num2str(j)])
        disp(['最短距离为',num2str(dist(i,j))])
    end
else  % 如果path(i,j) ~= j,则说明中间经过了其他节点:
    k = path(i,j);
    result = [num2str(i),' ---> '];  % 初始化要打印的这个字符串
    while k ~= j  % 只要k不等于j, 就一直循环下去
        result = [result , num2str(k) , ' ---> ' ];  % i先走到k这个节点处
        k = path(k,j);
    end
    result = [result , num2str(k)];
    disp(['从',num2str(i),'到',num2str(j),'的最短路径为'])
    disp(result)
    disp(['最短距离为',num2str(dist(i,j))])
end

end

Insert image description here


3️⃣ Define a function that prints all the shortest paths between any two nodesprint_all_path.m

function [] = print_all_path(D)
%% 该函数的作用是求解一个权重邻接矩阵任意两个节点之间的最短路径,并打印所有的结果出来
% 输入:
%        D是权重邻接矩阵
% 输出:无

[dist,path] = Floyd_algorithm(D);   % 调用之前的Floyd_algorithm函数
n = size(D,1);
if n == 1
    warning('请输入至少两阶以上的权重邻接矩阵')   % 在屏幕中提示警告信息
    return;   % 不运行下面的语句,直接退出函数
end

for i = 1:n
    for j = 1:n
        if i ~= j  % 不等号用~=表示
            print_path(path,dist,i,j);   % 调用之前的print_path函数
            disp('-------------------------------------------')
            disp('  ')
        end
    end
end

end

Insert image description here


4️⃣ Convert the graph into a weighted adjacency matrix D and call Floydthe function of the algorithm

%% 首先将图转换为权重邻接矩阵D
n = 5;  %一共五个节点
D = ones(n) ./ zeros(n);  % 全部元素初始化为Inf【有向图】
for i = 1:n
    D(i,i) = 0;  % 主对角线元素为0
end
D(1,2) = 3;
D(1,3) = 8;
D(1,5) = -4;
D(2,5) = 7;
D(2,4) = 1;
D(3,2) = 4;
D(4,3) = -5;
D(5,4) = 6;
D(4,1) = 2;

%% 调用Floyd_algorithm函数求解
[dist,path] = Floyd_algorithm(D)

print_path(path,dist,1,5)
print_path(path,dist,1,4)
print_path(path,dist,3,1)

clc
disp('下面我们打印任意两点之间的最短距离:')
print_all_path(D)

6 Questions to Think About


Find the shortest path between any two points

Insert image description here

Reference answer:

%% 首先将图转换为权重邻接矩阵D
n = 9; %一共9个节点
D = zeros(n); % 全部元素初始化为0 【无向图】
% 因为是无向图,所以权重邻接矩阵是一个对称矩阵
D(1,2) = 4; D(1,8) = 8;
D(2,8) = 3; D(2,3) = 8;
D(8,9) = 1; D(8,7) = 6;
D(9,7) = 6; D(9,3) = 2;
D(7,6) = 2; D(3,4) = 7;
D(3,6) = 4; D(6,4) = 14;
D(4,5) = 9; D(6,5) = 10;
D = D+D'; % 这个操作可以得到对称矩阵的另一半
for i = 1:n
for j = 1:n
if (i ~= j) && (D(i,j) == 0) 
D(i,j) = Inf; % 将非主对角线上的0元素全部变为Inf
end
end
end
%% 调用Floyd_algorithm函数求解
[dist,path] = Floyd_algorithm(D)

Guess you like

Origin blog.csdn.net/hu_wei123/article/details/130163290