一、算法描述
问题描述:已知站点,线路,线路-站点数据,求指定点之间的:
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