一、一些废话
哦莫,终于到了我最喜欢且不会的东西了,动态规划,求解最优路径,学会这玩意就能处理简单的TSP问题了,那么让我们来看看怎么用Matlab实现。
二、最短路径求解
2.1 稀疏矩阵
哦莫,果然上来就是我不会的,那我们来试试吧!
clear all
clc
w=zeros(4);
w(1,2)=3;w(1,3)=4;w(1,4)=5;
w(2,3)=8;w(2,4)=8;
G=sparse(w)
clear all
clc
%sparse([起点集合],[对应终点集合],[对应权重集合])
G = sparse([1 1 1 2 2],[2 3 4 3 4],[3 4 5 8 8]);
s=sparse(G)
这两个代码运行出来的结果是一样的:
2.2 最短路径
2.2.1 有向图
先跟着弄一个有向图,代码如下,代码中G为稀疏矩阵,0/false为无向图,1/true为有向图:
clear all
clc
G = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],[35 85 47 27 13 38 29 28 31 21 17])
view(biograph(G,[],'ShowWeights','on'))
运行一下得到如下图,哦莫除了figure竟然还有biograph viewer:
接下来要求最优路径,那咱咋弄呢,川川说加一行代码,就可以,如下:
clear all
clc
G = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],[35 85 47 27 13 38 29 28 31 21 17])
view(biograph(G,[],'ShowWeights','on'))
graphallshortestpaths(G)
然后就出来了这ans:
ans =0 112 45 48 17 7796 0 47 58 27 8751 77 0 13 68 4238 64 50 0 55 2969 95 28 31 0 6072 35 21 34 62 0
根据结果推算1到6的最优路径是多少呢?
第一行可以推出,从1先到5,距离最短只要17;
那么我们看第五行,最短是28,所以我们从5到3;
跳到第三行后,我们看第三行,第三行最短的是13,所以我们3到4;
跳到第四行,最短29,到6,至此,结束,我们来计算下总距离:
17+28+13+29=87,最优路径为1-5-3-4-6。
这个时候,川川给出了一个function,可以免去这些个计算的困扰,我们来试下:
function [min,path]=dijkstra(w,start,terminal)
n=size(w,1); label(start)=0; f(start)=start;
for i=1:nif i~=startlabel(i)=inf;
end, end
s(1)=start; u=start;
while length(s)<nfor i=1:nins=0;for j=1:length(s)if i==s(j)ins=1;endendif ins==0v=i;if label(v)>(label(u)+w(u,v))label(v)=(label(u)+w(u,v)); f(v)=u;end endend
v1=0;k=inf;for i=1:nins=0;for j=1:length(s)if i==s(j)ins=1;endendif ins==0v=i;if k>label(v)k=label(v); v1=v;endendends(length(s)+1)=v1; u=v1;
end
min=label(terminal); path(1)=terminal;
i=1;
while path(i)~=startpath(i+1)=f(path(i));i=i+1 ;
end
path(i)=start;
L=length(path);
path=path(L:-1:1);
主要的代码也需要发生变化:
a = zeros(6);
a = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],[35 85 47 27 13 38 29 28 31 21 17])
a = a + a';
a(a==0) = inf; % 零元素换成inf
a(eye(6,6)==1)=0; % 对角线换成 0
view(biograph(a,[],'ShowWeights','on'))
[min,path]=dijkstra(a,1,6) % dijkstra模型求解节点一到节点六最短路径
最终我们得到如下结果:
min =66path =1 5 3 6
真的很nice(不过这里我有个小小的疑问,为什么上下两个求解不同捏,后续我再做探究)
(这里先存疑,等下午重新改改代码看看,等一波修正)
2.2.2 无向图
继续沿用前一小问,构造稀疏矩阵,代码如下:
clear all
clc
W = [35 85 47 27 13 38 29 28 31 21 17];
G = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],W)
UG = tril(G + G')
view(biograph(UG,[],'ShowArrows','off','ShowWeights','on'))
运行一下得到如下图:
一样可以调用函数:
clear all
clc
W = [35 85 47 27 13 38 29 28 31 21 17];
G = sparse([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],W);
UG = tril(G + G')
view(biograph(UG,[],'ShowArrows','off','ShowWeights','on'))
graphallshortestpaths(UG,'directed',false)
结果如下:
ans =0 44 45 38 17 6644 0 47 58 27 3545 47 0 13 28 2138 58 13 0 31 2917 27 28 31 0 4966 35 21 29 49 0
我们同2.2.1一样分析:
17+27+35=79,1-5-2-6
当然使用shortestpath一样可以更方便!
clc
clear all
% 构造邻接矩阵
G = zeros(6);
G = graph([6 1 2 2 3 4 4 5 5 6 1],[2 6 3 5 4 1 6 3 4 3 5],[35 85 47 27 13 38 29 28 31 21 17])
plot(G,'EdgeLabel',G.Edges.Weight)
[P,d] = shortestpath(G,1,6)
答案如下:
P =1 5 3 6d =66
至此,结束。
(为啥呢为啥呢,为啥又不一样的答案呢,等会和川川探讨一波)