%问题描述:已知路网节点编号和节点间边的长度(或时间);考虑换乘后最大绕行不超过1.5倍最短距离,换乘时间
%用估计值2.5分钟/次;若是直达线路,其距离不得超过3倍的最短距离,否则认为直达线路设置不合理。求出网络中
%各点之间满足上述要求的所有路径,并用路径路段的0-1关系矩阵表示.
function [W_Section,Line_Section_01Mat]=KSP2pMXF(Road_Net,Line_Station)
tic
%% 程序功能
%路段自动编号(上下行作为2个路段分别对待)
%将路径-节点转换为路径-路段(将来的配流都是针对路段)
%求出一般定义的K短路
%求出各条路径的换乘点
%求出各条路径的换乘费用
%求出各条路径的总费用(不换乘&换乘)
%本程序中的换乘仅指一次换乘,本研究假定不会选择三次以及以上换乘次数
%求各点间的符合要求的路径路段关系矩阵(作为Frank_Wolfe算法的已知条件)
%***********************************************************************
%程序完成时间:2015-12-24
%运行测试环境:MATLAB 8.3.0.532
%制作人:兰州交通大学 刘志祥
%***********************************************************************
%% 变量说明
% KPaths: K短路路径集合
% KCosts-: K短路费用集合
% Kmax: 指定的K短路路径数量(若大于全部路径数,多余的部分会自动舍去)
% a: 路段编号
% P: 保存当前已找到的路径
% X: P的子集,表示一个路径
% path_number: 路径编号
% current_P: 当前路径编号(P_)
% size_X: X的大小
% w_index_in_path: 偏差节点在当前路径中的位置
% KSP(Original,Destination).: 结构体,为了集中展现结果
% Road_Net: 路网矩阵,带权的邻接方阵
% Line_Station: 路网路线集合
% Section_Station: 路段(Section)是由哪两个节点(Station)组成的
% W_Section: 路段权重
% W_Line_Section: 路线上各路段的权重
% Original: 起点
% Destination: 终点
% path_0: 直达路线(一条直达路线上可能有不只一个的直达路径)
% Transfer_Station: 可能的换乘点
% Cost_of_Transfer: 换乘一次要增加的费用
% H: 可容忍的绕路倍数
% path_k1: 途经起始点到第一个换乘点的所有点的直达路线集合
% path_k2: 途经所有换乘点的路线集合
% path_k3: 途经最后一个换乘点到终点的所有点路径集合
% Irrespective_of_the_Transfer_KPaths_number: 不考虑换乘的K短路按升序排列编号
% Irrespective_of_the_Transfer_KPaths: 不考虑换乘的K短路路径
% Irrespective_of_the_Transfer_KCosts: 不考虑换乘的K短路费用
% Transfer_Station_of_Path: 路径上的换乘点
% Times_of_Transfer: 换乘次数
% KCosts_of_Transfer: 换乘的额外费用
% Consider_the_Transfer_KCosts: 考虑换乘的费用
% Consider_not_consider_KPaths_number: 考虑换乘后的路径排序(对应于不考虑换乘的排序)
% Consider_the_Transfer_KPaths: 考虑换乘后升序的K短路费用
%% 模块1:输入并处理相关的路网数据
%例
% Road_Net =[
% 0 2 Inf 1 Inf Inf Inf Inf Inf
% 2 0 3 Inf 3 Inf Inf Inf Inf
% Inf 3 0 Inf Inf 2 Inf Inf Inf
% 1 Inf Inf 0 3 Inf 5 Inf Inf
% Inf 3 Inf 3 0 1 Inf 2 Inf
% Inf Inf 2 Inf 1 0 Inf Inf 3
% Inf Inf Inf 5 Inf Inf 0 2 Inf
% Inf Inf Inf Inf 2 Inf 2 0 4
% Inf Inf Inf Inf Inf 3 Inf 4 0];
% Line_Station={[1 2 3 6 9 8 7 4],[2 5 8 9],[1 4 5 6]};
Original=1; %起点从1开始
Destination=0; %终点从0开始,因为while循环采用了先处理措施
while Original<=size(Road_Net)
Destination=Destination+1;
if Destination>size(Road_Net)
Destination=1;
Original=Original+1;
if Original>size(Road_Net)
break
end
end
save test Original Destination Road_Net Line_Station %保存当前节点
clear all %清理所有数据,实现防错并加速
load test Original Destination Road_Net Line_Station %加载节点以实现迭代
fprintf('正在计算 %2d-%2d 间的数据,请稍后...\n',Original,Destination);
%% 定义变量及常量
Cost_of_Transfer=2.5; %预定义换乘时间,本文的换乘时间指平均换乘时间,只要发生换乘就会多话费这么多时间
H=1.5; %预定义的最大绕路倍数
a=0; %路段编号初始化
Kmax=100; %预定义的路径数量,这里尽可能取大,因为绕路倍数能够自动过滤不需要计算的k(启发式算法)
%% 根据路网对路段进行自动标号并求出每个路段的距离
for i=1:length(Road_Net)
for j=1:length(Road_Net)
if Road_Net(i,j)~=0&Road_Net(i,j)~=inf
a=a+1;
[Section_Station{a},W_Section{a}]=dijkstra(Road_Net,i,j);
end
end
end
%% 根据路段标号和路线-节点关系,求出路线-路段的0-1矩阵
Line_Section_01Mat=zeros(length(Line_Station),length(Section_Station)); %线路-路径0-1矩阵,表示某线路是否包含该路段
m=1;
while m<=length(Line_Station)
for i=2:length(Line_Station{m})
for k=1:length(Section_Station)
if isequal(Section_Station{k},Line_Station{m}([i-1 i]))
Line_Section_01Mat(m,k)=1;
end
end
end
m=m+1;
end
%% 路线-节点改为路线-路段
for i=1:length(Line_Station)
a=0;
for j=2:length(Line_Station{i})
for k=1:length(Section_Station)
if Line_Station{i}([j-1,j])==Section_Station{k}
a=a+1;
Line_Section{i}(a)=k;
W_Line_Section{i}(a)=W_Section(k);
end
end
end
end
%% 模块2:K短路算法
%% Step_0判断可行性
if Original > size(Road_Net,1)|| Destination > size(Road_Net,1)
warning('起点或终点不在指定路网中!');
KPaths=[];
KCosts=[];
else
%% Step_1调用Dijkstra算法求出最短路路径及费用
k=1;
[path costs]=dijkstra(Road_Net, Original, Destination);
if isempty(path)
KPaths=[];
KCosts=[];
else
%% Step_2初始化
path_number = 1;
P{path_number,1}= path;
P{path_number,2}= costs;
current_P = path_number;
size_X=1;
X{size_X}={path_number; path; costs};
S(path_number)= path(1);
KPaths{k}= path;
KCosts{k}= costs;
while (k<Kmax && size_X ~=0)
%% 若超出(H+1)*costs的费用,删除该路径及费用值
if KCosts{k}>H*costs
k=k-1;
KCosts=KCosts(1:k);
KPaths=KPaths(1:k);
break
end
%% Step_3关闭已搜索的路径
for i=1:length(X)
if X{i}{1}== current_P
size_X = size_X - 1;
X(i)=[];
break;
end
end
P_= P{current_P,1};
%% Step_4找偏差节点w的位置i
w = S(current_P);
for i=1:length(P_)
if w==P_(i)
w_index_in_path=i;
end
end
%% Step_5更新路网矩阵
for index_dev_vertex= w_index_in_path:length(P_)- 1
temp_luwangjuzhen = Road_Net;
for i = 1: index_dev_vertex-1
v = P_(i);
temp_luwangjuzhen(v,:)=inf;
temp_luwangjuzhen(:,v)=inf;
end
SP_sameSubPath=[];
index =1;
SP_sameSubPath{index}=P_;
for i=1:length(KPaths)
if length(KPaths{i})>= index_dev_vertex
if P_(1:index_dev_vertex)== KPaths{i}(1:index_dev_vertex)
index = index+1;
SP_sameSubPath{index}=KPaths{i};
end
end
end
v_ = P_(index_dev_vertex);