综合算法04—非排序换乘算法

一、算法描述

问题描述:已知站点,线路,线路-站点数据,求指定点之间的:

1、直达线路
2、一次换乘线路
3、两次换乘线路

模块1:直达线路算法
Step1:S为过起点A的线路集合,T为过终点B的线路集合;
Step2:ZDXL为直达线路,ZDXL=S∩T;ZDD为在直达线路上的点
Step3:若某条线路上起点在终点后面,则该线路不是直达线路(区分上下行)

模块2:一次换乘线路算法
Step1:与起点直达的点的集合zhan_A,与终点直达的点的集合zhan_B;
Step2:剔除在起讫点直达线路上的点ZDD_AB;
Step4:一次换乘点HCD_1ci=zhan_A∩zhan_B;
Step5:针对每一个换乘点i,再利用模块1的直达算法求得起点到每一个换乘点的直达线路;同理求得换乘点到终点的直达线路;则一次换乘线路为两段直达线路的组合。

模块3:二次换乘线路算法
Step1:找到与A直达的点的集合Z2,S2为过Z2的线路;
Step2:求与Z2直达的点集合并剔除直达点和一次换乘点记为zhan_2_A;
Step3:二次换乘点HCD_2ci=zhan_2_A∩zhan_B;
Step4:起点不变,以HCD_2ci为终点,调用一次换乘算法求得一次换乘点HCD_1,则起点、一次换乘点、二次换乘点、终点被确定;
Step5:分段,第一段:【起点,一次换乘点】;第二段:【一次换乘点,二次换乘点】,第三段:【二次换乘点,终点】;
Step6:分别对三段调用直达算法求得各段的直达线路,则二次换乘方案为三段直达线路的组合。

总算法:
Step1:数据准备,输入或调用编辑好的路网数据,输入起点和终点;
Step2:调用直达函数,输出直达方案(不排序);
Step3:调用一次换乘函数,输出一次换乘方案(不排序);
Step4:调用二次换乘函数,输出二次换乘方案(不排序)。

补充说明:
如有换乘路径,但换乘点在直达线路上,算法认为没有必要换乘,即舍去该换乘方案,然而有时候舍去的方案可能费用更省,在此不再深究。
例如:从v2到v9有很多条路径,但由于其他路径的换乘点在直达线路L1或L4上,故不管其路径费用是多少都舍弃其他方案。

二、算法程序

使用说明:将以下代码分别保存为m文件放在同一个目录下,注意名称不能写错,修改案例请打开luwangshuju.m,运行程序请打开huanchengsuanfa.m。

1. fuhaoshuoming.m

fprintf('=======================================================================\n');
fprintf('                   《换乘方案算法——不对方案排序》\n');
fprintf('运行环境:MATLAB 8.3.0.532 \n');
fprintf('作者信息:兰州交通大学  刘志祥   QQ:531548824\n');
fprintf('说明:本程序用于在已知路网数据时,通过输入起讫点求直达、一次、二次换乘方案。\n')
fprintf('=======================================================================\n\n');
%《路网数据符号》
% luwangshuju-路网数据,包括站数据(点编号),线数据(线编号),站—线数据(线路包含的站点)
% A-起点
% B-终点
% zhan-站集合,本程序中站点以V开头编号
% xian-线集合,可理解为公交车名称,如k102等
% zhan_xian-线与站的关系,表示线路上有哪些站点

%《数据处理符号》
% zhan_xian_01-线与站的01矩阵,行表示线,列表示站,0表示不在该线,1表示在该线上
% xian_zhan_01-站与线的01矩阵,行表示站,列表示线,0表示线不经过站,1表示经过,与zhan_xian_01互为转置矩阵

%《直达算法符号》
% S-经过起点的所有线路集合
% T-经过终点的所有线路集合
% ZDXL-直达线路,是S与T的交集
% ZDD-直达线路上的点

%《一次换乘算法符号》
% D_A-与A直达的点的集合(矩阵的行是线,列是站,表示线路是否经过该站点)
% D_B-与B直达的点的集合(同上)
% Z2-为与A直达的点
% X2-为Z2所在的线路
% S2-过与A直达的点的线路
% E2-把与A直达的点zhan_A看作起点,与该点直达的点的集合,即S2上的点
% zhan_A-与起点A直达的点的集合(剔除直达点后)
% xian_A-表示zhan_A所在的线路集合(一一对应)
% zhan_B-与终点B直达的点的集合(剔除起讫点直达线路点后的)
% xian_B-表示zhan_B所在的线路集合(一一对应)
% HCX_1ci_qianmian-一次换乘的前段线路
% HCX_1ci_houmian-一次换乘的末段线路
% HCD_1ci-一次换乘点
% HCX_1ci-一次换乘线集合(第1行表示前段线路,第2行表示末段线路)

%《二次换乘算法符号》
% Point-二次换乘4个关键点【起点 换乘点1 换乘点2 终点】
% HCD_1-换乘点1
% HCD_2-换乘点2
% HCX_1-前段线路【起点-换乘点1】
% HCX_2-中段线路【换乘点1-换乘点2】
% HCX_3-末段线路【换乘点2-终点】

%《总换乘算法符号》
% ZDX_AB-起讫点间的直达线
% ZDD_AB-起讫点间的直达点
% HCX_1ci_AB-起讫点直接的一次换乘线
% HCD_1ci_AB-起讫点直接的一次换乘点
% HCX_2ci_AB-起讫点直接的二次换乘线
% HCD_2ci_AB-起讫点直接的一次换乘点

%其他符号见程序内注释


2. luwangshuju.m

%==========================================================================
% 路网数据
% 运行可得基础路网数据
% 主要计算结果:【输入起讫点 得到路网的站-线-权数据 】
%==========================================================================
%% 输入始发点和目的地
qidian=2;
zhongdian=9;
A=qidian;
B=zhongdian;
%% 数据for换乘算法
% %例1
% %==========================================================================
% zhan=[1 2 3 4 5 6 7 8 9];                                                   %站数据
% xian={1 2 3 4 5 6};                                                         %线路数据
% xian_zhan={[1 2 4 6],[1 3 5 7 8],[9 2 5 6],[6 4 2 1],[8 7 5 3 1],[6 5 2 9]};%线路包含哪些站
% %==========================================================================

%例2
%==========================================================================
zhan=[1 2 3 4 5 6 7 8 9 10 11 12 13];                                       %站数据
xian=[1 2 3 4 5 6];                                                         %线路数据
xian_zhan={[1 2 3 6 9 8 7 4],[10 4 5 6 11],[12 2 5 8 13],[4 7 8 9 6 3 2 1],...
    [11 6 5 4 10],[13 8 5 2 12]};                                           %线路包含哪些站,注意要和roadnet对应起来,如果线路的始发站和终点站直接相连,即为环线。
%==========================================================================


3. shujuchuli.m

% =========================================================================
% 数据处理
% 运算依赖于luwangshuju.m
% 主要运算结果【得到普通线站关系的01矩阵】...
%==========================================================================

%% 线_站单元数组转换为01矩阵
%==========================================================================
xian_zhan_01=zeros(length(xian),length(zhan));
for i=1:length(xian)
    xian_zhan_01(i,xian_zhan{i})=1;
end
zhan_xian_01=xian_zhan_01';

%==========================================================================


4. zhida.m
%==========================================================================
% 直达方案
% 运算依赖于luwangshuju.m shujuchuli.m
% 主要计算结果:【ZDXL ZDD】
%==========================================================================
%% step1 起终点线路统计
%==========================================================================
S=find(zhan_xian_01(A,:)==1);                 %经过起点的所有线路集合
T=find(zhan_xian_01(B,:)==1);                 %经过终点的所有线路集合
%==========================================================================
%% step2 求直达路线
%==========================================================================
ZDXL=intersect(S,T);                          %直达线路就是S和T的交集
ZDXL_wuxiang=ZDXL;                            %记录无向直达线路,为后面一次换乘时删除直达点做准备
[m,n]=find(1==xian_zhan_01(ZDXL_wuxiang,:));  %直达点就是直达线路上的站点
ZDD=unique(n)';                               %直达点整理——去重
%==========================================================================
%% step3 区分上下行线路
%==========================================================================
for i=1:length(ZDXL)
    if find(A==cell2mat(xian_zhan(ZDXL_wuxiang(i))))>...
            find(B==cell2mat(xian_zhan(ZDXL_wuxiang(i))))
        ZDXL=setdiff(ZDXL,ZDXL_wuxiang(i));
    end
end
if isempty(ZDXL)
    ZDXL=[];
end
if isempty(ZDD)
    ZDD=[];
end
%==========================================================================
%% step4 主要计算结果
%==========================================================================
% ZDXL
% ZDD
%==========================================================================

5. yicihuancheng.m

% =========================================================================
% 一次换乘方案
% 运算依赖于luwangshuju.m shujuchuli.m zhida.m
% 主要计算结果:【HCD_1ci  HCX_1ci】
%==========================================================================

%% step1 找到一次换乘点
%==========================================================================
D_A=zeros(size(xian_zhan_01,1),size(xian_zhan_01,2));  %初始化,使得D_A,D_B具有和矩阵xian_zhan_01同样的维数(形状相同)
D_B=D_A;
D_A(S,:)=xian_zhan_01(S,:);                            %找出与起点直达的点的集合,并对应于线路S
D_B(T,:)=xian_zhan_01(T,:);                            %找出与终点直达的点的集合,并对应于线路T
D_A(ZDXL_wuxiang,:)=0;                                 %剔除直达线路上的点,(直达线路没有必要下车后再乘坐同一线路)
D_B(ZDXL_wuxiang,:)=0;                                 %删除直达线路上的点时必须确保该线路的返程线路上的点也被删除,因此这里用无向直达线路剔除法
[xian_A,zhan_A]=find(D_A==1);                          %找到与起点直达的点,并列出其所在的线路
[xian_B,zhan_B]=find(D_B==1);                          %找到与终点直达的点,并列出其所在的线路
HCD_1ci=intersect(zhan_A,zhan_B)';                     %换乘点即为剔除直达线路点后,既与起点直达又与终点直达的点
%==========================================================================

%% step2 分段求直达线路
%==========================================================================
if isempty(HCD_1ci)==0                 %若换乘点存在,继续执行
    %第一段:起点-换乘点的直达线路
    count=0;
    for i=1:length(HCD_1ci)
        A=qidian;
        B=HCD_1ci(i);
        zhida;
        count=count+1;
        HCX_1ci_qianmian(count)={ZDXL};
    end
    
    %第二段:换乘点-终点的直达线路
    count=0;
    for i=1:length(HCD_1ci)
        A=HCD_1ci(i);
        B=zhongdian;
        zhida;
        count=count+1;
        HCX_1ci_houmian(count)={ZDXL};
    end
else
    HCD_1ci=[];                      %若没有换乘点,为了方便矩阵运算,令其为空矩阵
    HCX_1ci_qianmian=[];             %没有换乘点也就不存在换乘线,为了方便矩阵运算,令其为空矩阵
    HCX_1ci_houmian=[];
end
%==========================================================================

%% step3 组合:第一行表示换乘前的线路,第二行表示换乘后的线路
%==========================================================================
HCX_1ci=[HCX_1ci_qianmian;HCX_1ci_houmian];                                    %第一行的第一个集合表示采用第一个换乘点的换乘前的线路,同理第二个集合表示采用第二个换乘点的换乘前的线路,类推。
%==========================================================================

%% step4 输出主要计算结果
%%==========================================================================
% HCX_1ci
% HCD_1ci
%%==========================================================================

6. ercihuancheng.m

%==========================================================================
% 二次换乘方案
% 运算依赖于luwangshuju.m shujuchuli.m zhida.m yicihuancheng.m huanchengsuanfa.m
% 主要计算结果:【起点 换乘点1 换乘点2 终点】  【换乘线1 换乘线2 换乘线3】
%==========================================================================

%% 1.求第2次换乘点
%==========================================================================
E2=D_A;                            %与A直达的点的集合(矩阵的行是线路,列是站点,表示线路是否包含该站点)
[X2,Z2]=find(D_A==1);              %Z2为与A直达的点,X2为Z2所在的线路
Z2=setdiff(Z2,qidian);
Z2=setdiff(Z2,ZDD_AB);
Z2=setdiff(Z2,HCD_1ci_AB);
count=0;
if isempty(Z2)==0
    for i=1:length(Z2)
        count=count+1;
        S2(count)={find(zhan_xian_01(Z2(i),:)==1)};
    end
    S2=unique(cell2mat(S2));        %过与A直达的点的线路
    E2(S2,:)=xian_zhan_01(S2,:);    %把与A直达的点看作起点,求与该起点直达的点的集合
    [xian_2_A,zhan_2_A]=find(E2==1);%找到[与起点直达的点的直达点对应的线路,与起点直达的点的直达点]
    zhan_2_A=unique(zhan_2_A);
    zhan_2_A=setdiff(zhan_2_A,ZDD_AB);
    zhan_2_A=setdiff(zhan_2_A,HCD_1ci_AB);
    HCD_2ci_AB=intersect(zhan_2_A,zhan_B)'; %找到二次换乘点
else
    HCD_2ci_AB=[];
end
%==========================================================================

%% 2.确定第1次和第2次换乘点
%==========================================================================
if isempty(HCD_2ci_AB)==0            %如果存在二次换乘点,继续求二次换乘方案
    for j=1:length(HCD_2ci_AB)       %j是针对二次换乘点的标号
        A=qidian;
        B=HCD_2ci_AB(j);             %重新定义起点和终点
        zhida;
        yicihuancheng;
        HCD_1ci=setdiff(HCD_1ci,ZDD_AB);
        HCD_1ci=setdiff(HCD_1ci,HCD_1ci_AB);
        HCD_1(j)={HCD_1ci};
    end
    HCD_1;
    HCD_2= {HCD_2ci_AB};
    %======================================================================
    
    %% 3.确定关键节点(【起点-换乘点1-换乘点2-终点】)
    %======================================================================
    count=0;
    for i=1:length(HCD_1)
        for j=1:length(HCD_1{i})
            count=count+1;
            p1(count)=qidian;          %起点
            p2(count)=HCD_1{i}(j);     %换乘点1
            p3(count)=HCD_2{1}(i);     %换乘点2
            p4(count)=zhongdian;       %终点
        end
    end
    Point=[p1;p2;p3;p4];
    %======================================================================
    
    %% 4.分三段求直达线路
    %% 4.1 第1段:起点——换乘点1的路线
    %======================================================================
    count=0;
    for i=1:length(p1)
        A=p1(i);
        B=p2(i);
        zhida;
        count=count+1;
        HCX_1(count)={ZDXL};
    end
    %======================================================================
    
    %% 4.2 第2段:换乘点1——换乘点2的路线
    %======================================================================
    count=0;
    for i=1:length(p1)
        A=p2(i);
        B=p3(i);
        zhida;
        count=count+1;
        HCX_2(count)={ZDXL};
    end
    %======================================================================
    
    %% 4.3 第3段:换乘点2——终点的路线
    %======================================================================
    count=0;
    for i=1:length(p1)
        A=p3(i);
        B=p4(i);
        zhida;
        count=count+1;
        HCX_3(count)={ZDXL};
    end
    %======================================================================    
    
else
    %% 5. 没有二次换乘点,方案为空
    %======================================================================
    Point=[];
    HCX_1=[];
    HCX_2=[];
    HCX_3=[];
    HCD_1=[];
    HCD_2=[];
    HCX=[];
    %==========================================================================
end
HCX=[HCX_1;HCX_2;HCX_3];


7. geshihuashuchu.m
%==========================================================================
% 按格式输出
% 运算依赖于huanchengsuanfa.m
% 主要结果:【输出直达方案 输出一次换乘方案 输出二次换乘方案】
%==========================================================================
%% 直达方案
fprintf('\n======================================================================\n')
fprintf('直达方案:\n')
if isempty(ZDX_AB)==0
    for i=1:length(ZDX_AB)
        fprintf('方案%d->:%d站上车,乘坐线路%d,到%d站下车;\n',i,qidian,ZDX_AB(i),zhongdian);
    end
else
    fprintf('没有直达线路,请参照换乘方案!\n');
end
fprintf('======================================================================\n\n')

%% 一次换乘方案
fprintf('======================================================================\n')
fprintf('一次换乘方案:\n')
HCX_1ci_AB=cell2mat(HCX_1ci_AB);
if isempty(HCX_1ci_AB)==0
    for i=1:size(HCX_1ci_AB,2)
        fprintf('方案%d->:%d站上车,乘坐线路%d,到%d站下车;%d站上车,乘坐线路%d,到%d站下车.\n',i,qidian,HCX_1ci_AB(1,i),HCD_1ci_AB(1,i),HCD_1ci_AB(1,i),HCX_1ci_AB(2,i),zhongdian);
    end
else
    fprintf('没有一次换乘线路.\n\n');
end
fprintf('======================================================================\n\n')

%% 二次换乘方案
fprintf('======================================================================\n')
fprintf('二次换乘方案:\n')
HCX_2ci_AB=cell2mat(HCX_2ci_AB);
if isempty(HCX_2ci_AB)==0
    for i=1:size(HCX_2ci_AB,2)
        fprintf('方案%d->:%d站上车,乘坐线路%d,到%d站下车;%d站上车,乘坐线路%d,到%d站下车;%d站上车,乘坐线路%d,到%d站下车.\n',...
            i,qidian,HCX_2ci_AB(1,i),HCD_2ci_AB(2,i),HCD_2ci_AB(2,i),HCX_2ci_AB(2,i),HCD_2ci_AB(3,i),HCD_2ci_AB(3,i),HCX_2ci_AB(3,i),zhongdian);
    end
else
    fprintf('没有二次换乘线路.\n\n');
end
fprintf('======================================================================\n\n')

8. huanchengsuanfa.m

% =========================================================================
% 换乘算法主程序(main)
% 运算依赖于luwangshuju.m shujuchuli.m zhida.m yicihuancheng.m
% ercihuancheng.m geshihuashuchu.m
% 主要结果:求出【直达方案 一次换乘方案 二次换乘方案】的数据
% =========================================================================
clear
clc
fuhaoshuoming
%% 数据准备
luwangshuju;
shujuchuli;
%==========================================================================
if ~ismember([A B],zhan)|A==B
    %======================================================================
    clc
    warning('!!起讫点输入错误,重新输入请按任意键...')
    pause
    huanchengsuanfa
    %======================================================================
else
    
    %% 1.求直达方案
    %======================================================================
    zhida;             %调用直达函数(查看zhida.m)
    ZDX_AB=ZDXL;       %起讫点间的直达线路
    ZDD_AB=ZDD;        %起讫点的直达线路上的点
    %======================================================================
    
    %% 2.求一次换乘方案
    %======================================================================
    yicihuancheng;     %调用一次换乘函数(查看yicihuancheng.m)
    HCX_1ci_AB=HCX_1ci;%起讫点间的一次换乘线,按行分别表示首段和末段的线路
    HCD_1ci_AB=HCD_1ci;%起讫点的一次换乘线路上的点
    %======================================================================
    
    %% 3.求二次换乘方案
    %======================================================================
    ercihuancheng;    %调用二次换乘函数(查看ercihuancheng.m)
    HCX_2ci_AB=HCX;   %起讫点间的二次换乘线,按行分别表示首段、中间、末段的线路
    HCD_2ci_AB=Point; %起讫点间二次换乘的4个关键点,确定分段的点
    %======================================================================
    
    %% 4.格式化输出
    %======================================================================
    geshihuashuchu
    %======================================================================
end

三、算例及运算结果

1.算例1

路网如图1所示,已知站数据、线数据及站-线数据。给定起点v4,终点v8。求路径方案。

1.1 运行结果

修改luwangshuju.m——qidian=4;zhongdian=8;

>> huanchengsuanfa

=======================================================================
                   《换乘方案算法——不对方案排序》
运行环境:MATLAB 8.3.0.532 
作者信息:兰州交通大学  刘志祥   QQ:531548824
说明:本程序用于在已知路网数据时,通过输入起讫点求直达、一次、二次换乘方案。
=======================================================================


======================================================================
直达方案:
没有直达线路,请参照换乘方案!
======================================================================


======================================================================
一次换乘方案:
方案1->:4站上车,乘坐线路4,到1站下车;1站上车,乘坐线路2,到8站下车.
======================================================================


======================================================================
二次换乘方案:
方案1->:4站上车,乘坐线路4,到2站下车;2站上车,乘坐线路3,到5站下车;5站上车,乘坐线路2,到8站下车.
方案2->:4站上车,乘坐线路1,到6站下车;6站上车,乘坐线路6,到5站下车;5站上车,乘坐线路2,到8站下车.
======================================================================


2.算例2

路网如图2所示,已知站数据、线数据及站-线数据。给定起点v2,终点v9。求路径方案。


图2 简单网络结构图


2.1运行结果

修改luwangshuju.m——qidian=2;zhongdian=9;

>> huanchengsuanfa

=======================================================================
                   《换乘方案算法——不对方案排序》
运行环境:MATLAB 8.3.0.532 
作者信息:兰州交通大学  刘志祥   QQ:531548824
说明:本程序用于在已知路网数据时,通过输入起讫点求直达、一次、二次换乘方案。
=======================================================================

======================================================================
直达方案:
方案1->:2站上车,乘坐线路1,到9站下车;
======================================================================

======================================================================
一次换乘方案:
没有一次换乘线路.
======================================================================

======================================================================
二次换乘方案:
没有二次换乘线路.
======================================================================

四、结论与展望

在路网站点、线路、站点-线路关系已知时,通过输入起讫点可以计算出直达路径及一次、二次换乘路径。但是算法罗列了所有路径,当路网变得复杂时,该算法将失去实际意义,所以算法需要改进,需要将多余的路径过滤,或许可以通过定义有效路径的方法对路径过滤并排序。


五、代码下载

代码下载地址:http://download.csdn.net/download/lzx19901012/9709091

猜你喜欢

转载自blog.csdn.net/lzx19901012/article/details/53580486