运输
问题
摘要
本文根据运输公司提供的提货点到各个客户点的路程数据,利用线性规划的优化方法与动态优化模型——最短路径问题进行求解,得到相关问题的模型。
针对问题一 ,我们采用Dijkstra 算法,将问题转化为线性规划模型求解得出当运送员在给第二个客户卸货完成的时,若要他先给客户10送货,此时尽可能短的行使路线为:
109832V V V V V →→→→,总行程85公里。
针对问题二,我们首先利用prim 算法求解得到一棵最小生成树:
再采用Dijkstra 算法求得客户2返回提货点的最短线路为12V V →故可得到一条理想的回路是:121098436751V V V V V V V V V V V →→→→→→→→→→
后来考虑到模型的推广性,将问题看作是哈密顿回路的问题,建立相应的线性规划模型求解,最终找到一条满足条件的较理想的的货车送货的行车路线:
121098436751V V V V V V V V V V V →→→→→→→→→→。
针对问题三,我们首先直接利用问题二得一辆车的最优回路,以货车容量为限定条件,建立相应的规划模型并设计一个简单的寻路算法,最终可为公司确定合理的一号运输方案:两辆车全程总和为295公里(见正文);然后建立线性规划模型得出二号运输方案:两辆车全程总和为290公里(见正文);最后再进一步优化所建的线性规划模型,为运输公
针对问题四,我们首先用Dijkstra 算法确定提货点到每个客户点间的最短路线,然后结合一些限定条件建立一个目标模型,设计一个较好的解决方案进行求解可得到一种很理
该方案得到运输总费用是645元。
关键字:Dijkstra 算法, prim 算法, 哈密顿回路
问题重述
某运输公司为10个客户配送货物,假定提货点就在客户1所在的位置,从第i 个客户
到第j个客户的路线距离(单位公里)用下面矩阵中的(,)
i j(,1,,10)
i j=位置上的数表示(其
中∞表示两个客户之间无直接的路线到达)。
1、运送员在给第二个客户卸货完成的时候,临时接到新的调度通知,让他先给客户10送
货,已知送给客户10的货已在运送员的车上,请帮运送员设计一个到客户10的尽可能
短的行使路线(假定上述矩阵中给出了所有可能的路线选择)。
2、现运输公司派了一辆大的货车为这10个客户配送货物,假定这辆货车一次能装满10个
客户所需要的全部货物,请问货车从提货点出发给10个客户配送完货物后再回到提货
点所行使的尽可能短的行使路线?对所设计的算法进行分析。
3、现因资源紧张,运输公司没有大货车可以使用,改用两辆小的货车配送货物。每辆小货
车的容量为50个单位,每个客户所需要的货物量分别为8,13,6,9,7,15,10,5,
12,9个单位,请问两辆小货车应该分别给那几个客户配送货物以及行使怎样的路线使
它们从提货点出发最后回到提货点所行使的距离之和尽可能短?对所设计的算法进行分
析。
4、如果改用更小容量的车,每车容量为25个单位,但用车数量不限,每个客户所需要的货物量同第3问,
并假设每出一辆车的出车费为100元,运货的价格为1元/公里(不考虑空车返回的费用),请问如何安
排车辆才能使得运输公司运货的总费用最省?
问题1
【模型分析与假设】
运送员在给第二个客户卸完货后,即从此处赶到第十个客户处,路程越短越好,是一个最短路径问题,为此我们采用Dijkstra算法,考虑到建模的方便我们将问题转化为线性规划模型进行求解。
下面是一些变量的假设与说明:
X为0,1变量,其值为1代表行车路线经过第j个客户,为0则代表不经过。
1.
ij
C为题中给出的邻接矩阵对应位置的值。
2.
ij
3.为了表达的方便,将邻接矩阵的第一行与第二行互换,第一列与第二列互换。(因为求的是客户2至客户10的最短线路,而非提货点至客户10)同时将矩阵中数据0或∞用一个足够大的数999代替。(这是因为目标函数是求最小值)
【模型建立与求解】
建立问题的模型(1)是:
将其转化为lingo代码(见附录[1])后,求解可得以下结果:
Global optimal solution found at iteration: 19
Objective value: 85.00000
Variable Value Reduced Cost
X( 1, 3) 1.000000 30.00000
X( 3, 8) 1.000000 25.00000
X( 8, 9) 1.000000 10.00000
X( 9, 10) 1.000000 20.00000
至此可以知道,运送员应该走的最好路线是:
总行程为85公里。
【模型检验与评价】
该模型是基于Dijkstra算法的基础上转化为线性规划模型来求最短路径的模型,优点是实现较简单,也容易求解;但有个令人不是很满意的地方就是其模式固定,要求任两个客户点间最短距离时,
需将其一客户的位置与提货点互换,另一个客户的位置则需与客户10的位置互换,将其看成原始的提货点到客户10最短距离的模型进行求解,这样较为烦琐,有待改进。
问题2
【模型分析】
很明显运输公司分别要对10个客户供货,必须访问每个客户,但问题要求我们建立相应模型寻找一条尽可能短的行车路线,首先不考虑送货员把10个客户所需的货送完货后不返回提货点的情
2V (客户2)返回1V
从上分析知送货员从提货点1出发,要走遍客户2,3,…,n 各至少一次,最后返提货点1。
为了更方便地建立起模型首先作以下假设与说明:
1.ij X 为0,1整形变量,其值为1代表行车路线经过第j 个客户,为0则代表不经过。 2.ij C 为客户i 到j 的距离(题中给出的邻接矩阵的数据)。
3.为了数据的方便处理,先将邻接矩阵中的数据∞用一个足够大的数999代替。
4.访问客户i 后必须要有一个即将访问的确切客户;访问客户j 前必须要有一个刚刚访问过的确切客户。故我们用以下条件来分别保证我们的假设。
到此我们得到了一个模型,它是一个指派问题的整数规划模型。其目标是使式子:∑∑==*10
110
1i j ij ij X C
在约束条件下取得最小值。
5.哈密顿图优化问题[5],须添加一个额外变量()10,,3,2 =i u i
,目的是为了更好的防止子巡回
的产生,即须附加一个约束条件:
到现在我就可以建立以下模型对问题求解了。 【模型建立与求解】
可建立问题的模型(2)为: 同样借助数学软件求解可得结果: 从中可以找出一条较为理想的回路是:
可见按此模型求解的结果与采用prim 算法求解的结果是一样的。
问题3
【模型分析与猜想】
用两辆容量为50单位的小货车运货,在每个客户所需固定货物量的情况下,要使得行程之和最短,我们假设每个客户的货物都由同一辆货车提供,这样只要找出两条尽可能短
的回路,并保证每条线路客户总需求量在50个单位以内。实际
上这样的两条回路是存在的:由题二得到了一条哈密顿回路
可根据货物需求量的大小将其分为前后两部分,并将之分别构成回路。(注:由于提货点在客户1所在的位置,故不必考虑为客户1送货的情况。)
为了更好地建立模型,先作以下定义:
『定义1:』 顺序集合???
???→→→→→→→→→→=1221010998844336677551,,,,,,,,,V V V V V V V V V V V V V V V V V V V V N 代表由模型(2)求解得出的
哈密顿回路的路径全集(集合中的元素是不可调换的,故称它为顺序集合);
『定义2:』 函数()i N Get 为集合N 中第i 个元素终点所对应的下标。(即若i=3,则,()73=N Get ) 『定义3:』 函数()i N U 为集合N 中第i 个元素终点所对客户的货物需求量(即若i=3则
())(33N Get T N U =)其中(()10,,2,1,
i T 为向量: ()9,12,5,10,15,7,9,6,13,8的第i 个分量的值)。
接下来我们设计一个简单的算法来寻找较好的路径: Step1:根据以下模型获得一个值k ; Step2:依k 的取值分两条路径:
Step3:利用模型(1)分别求得()k N Get V 到1V 的最短路径:()1V V K N Get →→ 以及
1V 到()1+K N Get V 的最短路径:()11+→→K N Get V V
依据模型很容易求得:k=5
(因为根据模型(1)很容易可以确定4V 至1V 的最短路径是14V V →,1V 至8V 的最短路径是
851V V V →→,但在代用模型(1)的时候须注意的是相应的客户位置的变换,可参照问题
一的求解决方法。)
由此可得两车所行驶的距离之和(单位:公里): 【结果优化】
从以上得到的两条行车路线来看,两车得经过经过了客户5,根据算法二号车必客户5
才能保证行程较短,而根据模型(1)易知路径71V V →优于751V V V →→,因此可优化一号车路线为:143671V V V V V V →→→→→,经检验优化后的两条行车路线上客户货物需求量总和分别是40与46均不超过货车的容量50,故认为此方案更优,这样我们可以给运输公司提供的一号
很明显,以上猜想得到的模型来求解这一问题,存在着很大的缺陷,那就是没有更好说服力,不能让人感到很满意,不过这个结果也是很客观的,不会很差。因此我们想通建立以下模型来弥补这一缺陷。 【模型建立与求解】
若对以上猜得到的一种模型不够满意,我们同样可以建立相应的线性规划模型对以上的运输方案进一步优化,考虑到本问题与问题二有相似之处即要考虑回到提货点的情形,因此我们可以在模型(2)上进行改进, 在保证二号不超载(不超出容量)的前提下,先确定第一辆车的最优路径,首先对模型中将会用的变量作一些简单的定义或说明:
1.j D 为每个客户的需货量,它是在向量()9,12,5,10,15,7,9,6,13,8的每j 个分量,据上分析
知:503610110
1
≤*≤
∑∑==j i j ij
D X
(不考虑客户1的需求量,因为它在提货点)。
2.由于这里是分两条路线分别给10个客户送货,就没有必要设计每条路线都能够访问每个客户点,但要保证送货员能回提货点,且均从提货点出发回到提货点,则送货员进入一个客户同时也必须出来。故我们用以下条件来分别保证我们的假设:
到此我们得到了一个模型,它是一个指派问题的整数规划模型。其目标是使式子:∑∑==*10
110
1i j ij ij X C
在约束条件下取得最小值。
其余变量的假设与问题二的假设一致。 故可建立模型(3)如下:
在5036≤≤j D
约束下,参加附录[3]的代码,在lingo 中求解可得以下结果:
路线的选择,(以长度为95公里的路线为例)只需将模型(3)中的条件:0
10
1
10
1
∑∑===-j j ij ij X X
与∑∑==≥10110
1
i j ij K X 改为条件()i j j Xij ≠==且10,6,4,3,21
即要保证第二辆访问到所有第一辆车未访问过的客户,允许其访问第一辆车访问过的客户,故模型基本上不用改动。同样参照参加附录[3]的代码,可求得上述路线对应的另一条
【模型优化】
从以上产生的结果中很容易,往往第一辆车通过的线路,有些第二辆车也要经过,并不能保证两条线路完全独立,显然这样话,我们可以确定第一辆车的线路的时候让其线路上的货物承受量大一点,两车都经过的让第二辆车去送货,这样模型(3)很可能就存在缺陷了,这是由于对条件:
503610
110
1≤*≤∑∑==j i j ij D X 的上界进行约束引起的,因此我们可以这个条件的上界放大,给模型有更大
的自由选择空间,可将它改为:863610110
1
≤*≤∑∑==j i j ij D X
,再用上述方法可以求解,但此最后形成运输方案的时候应该多考虑另一个因素,即哪些客户的货
【结果分析与评价】
虽然我们猜想模型很简单,但它是解决本问题的关键,也是我们建模思路的切入点,通过这个模型的建立与求解我们逐渐发现问题的所在,故而引导我们对自己所建的模型一步一步地优化,最终得到一个非常理想的三号运输方案,当然我们模型也存在不少问题,例如我们没有用一个统一的模型来同时得出两辆车的最优路线,这是我们觉得比较郁闷的地方,我们将慢慢地对其不断改进与完善。
问题4
【模型分析与假设】
由于出车费100一辆,相当于100公里的行程费用,当行程超200公里时是否以多出车来换取小行程呢?我们认为没必要:其一从题中给出的数据阵可以看出行程超过200公里该车至少经过4个客户点,其总货物需求量超过小车的容量,是不可取的;其二即使可行,但要保证加车后,两辆车总行程要控制在100公里以内也不是一件容易的事。从此两个原因可以看出我们不必考虑加车的方案,即根据客户总需求量与货车的容量可决定只派4辆车为客户送货即可。
为了更好的解决问题,我们首先作一些定义: 『定义1:』 集合()()()(){}10,,3,2,,,,,,,,1,1 ==k j i k j j i i k Lue k 代表提货点1到第k 个客户的最
短路径;
『定义2:』 函数()k Lue LEN 为提货点1到第k 个客户的路径长度(单位:公里); 例如若 则有 其中()10,,3,2,,
, =j i C j i 代表题中所给的数据阵对应位置的值
『定义3:』 函数()k Lue UN 为从提货点1到第k 个客户的路经客户所需的货物量的总和;例如若 则有 其中(()10,,2,1,
U i 为向量: ()9,12,5,10,15,7,9,6,13,8的第i 个分量的值)
考虑到每辆车的出发点均是提货点1首先用Dijkstra 算法类似问题一分别求得提货点1到各客户点的最短路径,分别为:
()(){}2,5,5,12=Lue ,()(){}3,4,4,13=Lue ,(){}4,14=Lue , (){}5,15=Lue ,()(){}6,7,7,16=Lue ,(){}7,17=Lue , ()(){}8,5,5,18=Lue ,(){}9,19=Lue ,()(){}10,9,9,110=Lue ;
从中可发现不等式:()25≤k Lue UN 均成立。从而我们可设计一种比较好的方解决方案如下: Step1:初始化集合{}10,3,2 ==k Lue N k Step2: 若()k j Lue Lue j
k ≠?,则册去j Lue ,只取路径集k Lue ,更新集合N ;
Step3: 若()k j Lue Lue j k ≠Φ
≠ ,将其中一条路径删去子路径j k Lue Lue ,有以下两种情形:
(ⅰ)、先初始化一个临时集合M=N ,若删去路径k Lue 的子路径j k Lue Lue 更新集合M ,将路径
j k k Lue Lue Lue -接到集合M 中的每个路径上,并以()25≤-j k k Lue Lue Lue UN 为条件计算这
些路径转到路径j k k Lue Lue Lue -的最短路径,选出函数()j k k Lue Lue Lue LEN -值最小的一条路径记为k Lue ;
(ⅱ)、先初始化一个临时集合H=N ,若删去路径j Lue 的子路径j k Lue Lue 更新集合M ,将路径
j k j Lue Lue Lue -接到集合M 中的每个路径上,并以()25≤-j k j Lue Lue Lue UN 为条件计算这
些路径转到路径j k j Lue Lue Lue -的最短路径,选出函数()j k j Lue Lue Lue LEN -值最小的一条路径记为k Lue ;
Step4: 比较Step3中得出(ⅰ)与(ⅱ)得出的路径k Lue 的()k Lue LEN 值的大小,选取小的若(ⅰ)的小让集合M 代替N ,否则让集合H 代替N 。 【模型建立与求解】
由分析知可以建立问题的模型(目标函数):
依解决方案,能得出运输公司所派出的4辆车所走的路线及每条线上的货物总需求量如下表: 、
费用:
【模型检验】
我们设计的解决方案是以Dijkstra 算法为基础,以小车容量为约束条件得出的一种解决问题的方法,从模型分析可以看出我们没有必要去考虑以加车的方法来换取短路线的方案,因此直接根据客户的总需货量可以知道,至少需要4辆小车来送货。从得出的运输方案来看,这种办法确实是可行了,且并不会很差。
结果分析
在问题一中可以看出,这就是一个任意两点的最优路径的问题,若要求两点的最短路径,只需把其中一个看成起点,另一个看成终点(即问题中的提货点与客户10),然后套用模型(1)求解就可得到一条最短路径,这就是Dijkstra算法的运用。
从问题二的结果中,可以发现这个问题实质上就是一个旅行商问题,即一个从一个点出发遍历每个顶点一次仅此一次然后回到起点,它没有一个成熟算法,即得到的结果不一次是最优的回路,但至少是比较好的了。这类问题还可以用prim算法与Dijkstra算法一起解决。
对于问题三我们先通过常归思维去分析问题,得到的一号运输方案与后面建模得到二、三号运输方案来看,相差并不是会很大,这也正说明了我们设计的算法也是比较符合实际的,准确性也是比较高的。
对于问题四我们自己设计一个算法来解决问题,得到相应的结果验证了我们算法是可行的也是可靠的,但是局限性好大,也许这一算法仅适用于这类问题,不过我们将会尽最大努力地改进。
模型评价
从我们建立的模型来看,无论是理论上或者是和现实的接近性上,都是比较合理的,我们主要从模型的假设合理性、建模的创造性、运算的效率和结果的正确性对其作出客观的评价:
首先,我们的假设均考虑客观性合乎情理,模型(1)与模型(2)在现实中也可以广泛的应用,与现实状况紧密相连;例如:最优路径问题与哈密顿回路问题,在现实生活已经应运范围很广了。
其次是建模的合理性分析,我们的模型的建立,经过很严密的分析,具一般性。
再就是模型求解的效率性了,由于本题目的数据量不大,我们的程序运行均能瞬间完成。
最后就是结果的正确性了,通过模型的求解,我们得到与现实很接近的结果,可以说是合理、正确的。
参考文献
[1] 朱德通《最优化模型与实验》同济大学出版社, 2003年。
[2] 《现代应用数学手册运筹学与最优化理论卷》清华大学出版社。
[3] 殷剑宏吴开亚《图论及其算法》中国科学技术大学出版社 2003年。
[4] 严蔚敏吴伟民《数据结构(C语言版)》清华大学出版社。
[5] 姜启源谢金星叶俊《数学建摸》高等教育出版社 2003年。
附录
[1] !第1小题目;
model:
sets:
v/1..10/;
TL(v,v):c,x;
Endsets
min=@sum(TL(I,J):c(I,J)*x(I,J));
@for(TL(I,J):@bin(x(I,J)));
@for(v(I):@bin(@sum(v(J):x(I,J))));
@for(v(J):@bin(@sum(v(I):x(I,J))));
@sum(v(J): x(1,J))-@sum(v(J): x(J,1))=1;
@sum( v(J): x(10,J))-@sum( v(J): x(J,10))=-1;
@for(v(I)|I #ne# 1 #and# I #ne# 10:
@sum(v(J): x(I,J))-@sum(v(J): x(J,I))=0);
data:
c=999 50 30 999 35 ………………
………………… 60 999 30 999;
Enddata
end
[2] !第2小题目;
model:
sets:!定义集;
v / 1.. 10/: u;
link( v, v):C, x;
endsets
n = @size( v);
min = @sum( link: C* x);!目标函数;
@FOR( v(K):!开往第K个客户;
@sum( v( I)| I #ne# K: x( I, K)) = 1;
@sum( v( J)| J #ne# K: x(K,J)) = 1;!离开开往第K个客户; );
@for(v(I)|I #gt# 1:!不走走过的路;
@for( v( J)| J#gt#1 #and# I #ne# J:
u(I)-u(J)+n*x(I,J)<=n-1));
@for( link: @bin( x));!定义X为0\1变量;
@for( link: @gin( x));!定义X为整形变量;
data: !这里是数据;
C =0 50 999 40 25 ……………………
…………………… 999 60 999 30 0;
Enddata
End
[3] !第3小题目;
model:
sets:!定义集;
v / 1.. 10/: u,D;
link( v, v):C,y, x;
endsets
min = @sum( link: C*x);
@sum(v( I)| I #ne# 1: x(I, 1))=1;
@sum(v( I)| I #ne# 1: x(1,I))=1;
@FOR( v(K):
@sum( v( I)| I #ne# K: x( I, K))<1;
@sum( v( J)| J #ne# K: x(K,J))<1);
@FOR( v(K):
@bin(@sum( v( I)| I #ne# K: x( I, K)));
@bin(@sum( v( J)| J #ne# K: x(K,J))));
@sum(v(I)| I #ne#6 :x(I,6))=1;
!@sum(v(I)| I #ne#10 :x(I,10))=1;
!@sum(v(I)| I #ne#4 :x(I,4))=1;
!@sum(v(I)| I #ne#2:x(I,2))=1;
!@sum(v(I)| I #ne#3:x(I,3))=1;
!@sum(v(I)| I #ne#5:x(I,5))=1;
!@sum(v(I)| I #ne#8:x(I,8))=1;
!@sum(v(I)| I #ne#7:x(I,7))=1;
!@sum(link(I,J)|I #ne# J:x(I,J))>4
@sum(link(I,J)|I #ne# J:x(I,J)*D(J))>36
@sum(link(I,J)|I #ne# J:x(I,J)*D(J))<86;
@for(v(I):
@sum(v(J): x(I,J))-@sum(v(J): x(J,I))=0);
@for(v(I)|I #gt# 1:!不走走过的路;
@for( v( J)| J#gt#1 #and# I #ne# J:
u(I)-u(J)+10*x(I,J)<=9));
@for( link: @bin( x));
@for( link: @gin( x));
data: !这里是数据;
D=8,13,6,9,7,15,10,5,12,9;
C=0 50 999 40 25 ……………………
…………………… 999 60 999 30 0; enddata
end