运输问题的匈牙利解法和表上作业法
- 格式:docx
- 大小:311.18 KB
- 文档页数:13
运输问题的求解方法(过程)——表上作业法的解题思路和原理、具体步骤。
运输问题是一种常见的工业应用问题,涉及到如何安排运输工具和货物,以最小化总成本或最大化利润。
表上作业法(Tableau Programming)是解决运输问题的一种有效方法,其解题思路和原理、具体步骤如下:1. 确定问题的状态在表上作业法中,我们需要先确定问题的状态。
状态是指某个特定时间段内,某个运输问题需要满足的条件。
例如,在一个例子中,我们可以将运输问题的状态定义为“需要从A城市运输货物到B城市,运输工具数量为3,运输距离为100公里”。
2. 定义状态转移方程接下来,我们需要定义状态转移方程,以描述在不同状态下可能采取的行动。
例如,在这个问题中,我们可以定义一个状态转移方程,表示当运输工具数量为2时,货物可以运输到B城市,而运输距离为80公里。
3. 确定最优解一旦我们定义了状态转移方程,我们就可以计算出在不同状态下的最优解。
例如,在这个问题中,当运输工具数量为2时,货物可以运输到B城市,运输距离为80公里,总成本为200元。
因此,该状态下的最优解是运输距离为80公里,运输工具数量为2,总成本为200元。
4. 确定边界条件最后,我们需要确定边界条件,以确保问题的状态不会无限制地变化。
例如,在这个问题中,当运输工具数量为3时,运输距离为120公里,超过了B城市的运输距离范围。
因此,我们需要设置一个限制条件,以确保运输工具数量不超过3,且运输距离不超过120公里。
表上作业法是一种简单有效的解决运输问题的方法,其原理和具体步骤如下。
通过定义状态转移方程、确定最优解、确定边界条件,我们可以计算出问题的最优解,从而实现最小化总成本和最大化利润的目标。
运筹学运输问题,表上作业法运筹学李细霞 2013物流工程1班 2014~2015学年第二学期运筹学运输问题,表上作业法课程主要内容绪论线性规划及单纯形法对偶理论与灵敏度分析目标规划整数规划运输问题动态规划图与网络运筹学运输问题,表上作业法第三章运输问题Transportation problem运筹学运输问题,表上作业法学习目标什么是运输问题?复杂运输问题如何解决运输问题?运筹学运输问题,表上作业法用单纯形法求解线性规划问题的步骤基本可行解基变换初始解最优性检验调整检验数18运筹学运输问题,表上作业法表上作业法单纯形法在求解运输问题时的一种简化方法运筹学运输问题,表上作业法表上作业法步骤1.西北角法 2.最小元素法3.伏格尔法闭回路法初始方案最优性检验方案调整1.闭回路法2.位势法20运筹学运输问题,表上作业法B1 A1 A2 A3 销量B2B3B4 10 8 5 6产量 7 4 9总产=总销31 7 311 94 632 10 5运筹学运输问题,表上作业法最小元素法西北角法初始方案的确定伏格尔法运筹学运输问题,表上作业法西北角法B1 A1 A2 A3 销量3 4有何疑问?B2 4 2B3B4产量32 3 67 4 93656Z cij xij 3 3 11 4 9 2 2 2 10 3 5 6 108i 1 j 123 运筹学运输问题,表上作业法西北角法的优劣?太简单咯!最优解有点望尘莫及呢24。
运输问题的求解方法(过程)——表上作业法的解题思路和原理、具体步骤。
运输问题是指在给定的供应地和需求地之间,选择最佳的运输方案,使总运输成本最低的问题。
表上作业法是一种常用的解决运输问题的方法,它基于线性规划的思想,通过逐步逼近最优解的方式来求解运输问题。
表上作业法的原理是将运输问题转化为一个线性规划问题,通过构建一个供需平衡表来描述运输问题。
在该表中,将供应地和需求地分别作为行和列,并在表中填入运输量的变量。
同时,引入一个辅助表来记录每个供应地和需求地的运输量。
具体的求解步骤如下:1. 构建供需平衡表:将给定的供应地和需求地以及对应的运输量填入表格中,并计算每个供应地和需求地的供应总量和需求总量。
2. 确定初始基本可行解:根据运输量的限制条件,确定一个初始的基本可行解。
可以选择将某些运输量设置为0,使得每个供应地和需求地都满足其供应总量和需求总量。
3. 计算单位运输成本:根据给定的运输成本,计算每个供应地和需求地之间的单位运输成本,填入表格中。
4. 判断最优解条件:检查当前的基本可行解是否满足最优解的条件。
如果每个供应地和需求地都满足其供应总量和需求总量,并且没有其他更低成本的运输方案,则当前解为最优解。
5. 迭代改进解:如果当前解不满足最优解的条件,则需要进行迭代改进。
在每一次迭代中,选择一个非基本变量(即非0运输量)进行改变,并计算改变后的基本可行解。
6. 更新供需平衡表和辅助表:根据改变后的基本可行解,更新供需平衡表和辅助表的运输量,并重新计算单位运输成本。
7. 重复步骤4-6,直到找到最优解为止。
通过以上的步骤,表上作业法能够有效地求解运输问题,并得到最优的运输方案。
它在实践中广泛应用于物流管理、供应链优化等领域,为运输问题的决策提供了科学的依据。
运筹学课程设计指派问题的匈牙利法专业:姓名:学号:1.算法思想:匈牙利算法的基本思想是修改效益矩阵的行或列,使得每一行或列中至少有一个为零的元素,经过修正后,直至在不同行、不同列中至少有一个零元素,从而得到与这些零元素相对应的一个完全分配方案。
当它用于效益矩阵时,这个完全分配方案就是一个最优分配,它使总的效益为最小。
这种方法总是在有限步內收敛于一个最优解。
该方法的理论基础是:在效益矩阵的任何行或列中,加上或减去一个常数后不会改变最优分配。
2.算法流程或步骤:1.将原始效益矩阵C的每行、每列各元素都依次减去该行、该列的最小元素,使每行、每列都至少出现一个0元素,以构成等价的效益矩阵C’。
2.圈0元素。
在C’中未被直线通过的含0元素最少的行(或列)中圈出一个0元素,通过这个0元素作一条竖(或横)线。
重复此步,若这样能圈出不同行不同列的n个0元素,转第四步,否则转第三步。
3.调整效益矩阵。
在C’中未被直线穿过的数集D中,找出最小的数d,D中所有数都减去d,C’中两条直线相交处的数都加的d。
去掉直线,组成新的等价效益矩阵仍叫C’,返回第二步。
X=0,这就是一种最优分配。
最低总4.令被圈0元素对应位置的X ij=1,其余ij耗费是C中使X=1的各位置上各元素的和。
ij算法流程图:3.算法源程序:#include<iostream.h>typedef struct matrix{float cost[101][101];int zeroelem[101][101];float costforout[101][101];int matrixsize;int personnumber;int jobnumber;}matrix;matrix sb;int result[501][2];void twozero(matrix &sb);void judge(matrix &sb,int result[501][2]);void refresh(matrix &sb);void circlezero(matrix &sb);matrix input();void output(int result[501][2],matrix sb);void zeroout(matrix &sb);matrix input(){matrix sb;int m;int pnumber,jnumber;int i,j;float k;char w;cout<<"指派问题的匈牙利解法:"<<endl;cout<<"求最大值,请输入1;求最小值,请输入0:"<<endl;cin>>m;while(m!=1&&m!=0){cout<<"请输入1或0:"<<endl;cin>>m;}cout<<"请输入人数(人数介于1和100之间):"<<endl;cin>>pnumber;while(pnumber<1||pnumber>100){cout<<"请输入合法数据:"<<endl;cin>>pnumber;}cout<<"请输入工作数(介于1和100之间):"<<endl;cin>>jnumber;while(jnumber<1||jnumber>100){cout<<"请输入合法数据:"<<endl;cin>>jnumber;}cout<<"请输入"<<pnumber<<"行"<<jnumber<<"列的矩阵,同一行内以空格间隔,不同行间以回车分隔,以$结束输入:\n";for(i=1;i<=pnumber;i++)for(j=1;j<=jnumber;j++){cin>>sb.cost[i][j];sb.costforout[i][j]=sb.cost[i][j];}cin>>w;if(jnumber>pnumber)for(i=pnumber+1;i<=jnumber;i++)for(j=1;j<=jnumber;j++){sb.cost[i][j]=0;sb.costforout[i][j]=0;}else{if(pnumber>jnumber)for(i=1;i<=pnumber;i++)for(j=jnumber+1;j<=pnumber;j++){sb.cost[i][j]=0;sb.costforout[i][j]=0;}}sb.matrixsize=pnumber;if(pnumber<jnumber)sb.matrixsize=jnumber;sb.personnumber=pnumber;sb.jobnumber=jnumber;if(m==1){k=0;for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)if(sb.cost[i][j]>k)k=sb.cost[i][j];for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)sb.cost[i][j]=k-sb.cost[i][j];}return sb;}void circlezero(matrix &sb){int i,j;float k;int p;for(i=0;i<=sb.matrixsize;i++)sb.cost[i][0]=0;for(j=1;j<=sb.matrixsize;j++)sb.cost[0][j]=0;for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)if(sb.cost[i][j]==0){sb.cost[i][0]++;sb.cost[0][j]++;sb.cost[0][0]++;}for(i=0;i<=sb.matrixsize;i++)for(j=0;j<=sb.matrixsize;j++)sb.zeroelem[i][j]=0;k=sb.cost[0][0]+1;while(sb.cost[0][0]<k){k=sb.cost[0][0];for(i=1;i<=sb.matrixsize;i++){if(sb.cost[i][0]==1){for(j=1;j<=sb.matrixsize;j++)if(sb.cost[i][j]==0&&sb.zeroelem[i][j]==0)break;sb.zeroelem[i][j]=1;sb.cost[i][0]--;sb.cost[0][j]--;sb.cost[0][0]--;if(sb.cost[0][j]>0)for(p=1;p<=sb.matrixsize;p++)if(sb.cost[p][j]==0&&sb.zeroelem[p][j]==0){sb.zeroelem[p][j]=2;sb.cost[p][0]--;sb.cost[0][j]--;sb.cost[0][0]--;}}}for(j=1;j<=sb.matrixsize;j++){if(sb.cost[0][j]==1){for(i=1;i<=sb.matrixsize;i++)if(sb.cost[i][j]==0&&sb.zeroelem[i][j]==0)break;sb.zeroelem[i][j]=1;sb.cost[i][0]--;sb.cost[0][j]--;sb.cost[0][0]--;if(sb.cost[i][0]>0)for(p=1;p<=sb.matrixsize;p++)if(sb.cost[i][p]==0&&sb.zeroelem[i][p]==0){sb.zeroelem[i][p]=2;sb.cost[i][0]--;sb.cost[0][p]--;sb.cost[0][0]--;}}}}if(sb.cost[0][0]>0)twozero(sb);elsejudge(sb,result);}void twozero(matrix &sb){int i,j;int p,q;int m,n;float k;matrix st;for(i=1;i<=sb.matrixsize;i++)if(sb.cost[i][0]>0)break;if(i<=sb.matrixsize){for(j=1;j<=sb.matrixsize;j++){st=sb;if(sb.cost[i][j]==0&&sb.zeroelem[i][j]==0){sb.zeroelem[i][j]=1;sb.cost[i][0]--;sb.cost[0][j]--;sb.cost[0][0]--;for(q=1;q<=sb.matrixsize;q++)if(sb.cost[i][q]==0&&sb.zeroelem[i][q]==0){sb.zeroelem[i][q]=2;sb.cost[i][0]--;sb.cost[0][q]--;sb.cost[0][0]--;}for(p=1;p<=sb.matrixsize;p++)if(sb.cost[p][j]==0&&sb.zeroelem[p][j]==0){sb.zeroelem[p][j]=2;sb.cost[p][0]--;sb.cost[0][j]--;sb.cost[0][0]--;}k=sb.cost[0][0]+1;while(sb.cost[0][0]<k){k=sb.cost[0][0];for(p=i+1;p<=sb.matrixsize;p++){if(sb.cost[p][0]==1){for(q=1;q<=sb.matrixsize;q++)if(sb.cost[p][q]==0&&sb.zeroelem[p][q]==0)break;sb.zeroelem[p][q]=1;sb.cost[p][0]--;sb.cost[0][q]--;sb.cost[0][0]--;for(m=1;m<=sb.matrixsize;m++)if(sb.cost[m][q]=0&&sb.zeroelem[m][q]==0){sb.zeroelem[m][q]=2;sb.cost[m][0]--;sb.cost[0][q]--;sb.cost[0][0]--;}}}for(q=1;q<=sb.matrixsize;q++){if(sb.cost[0][q]==1){for(p=1;p<=sb.matrixsize;p++)if(sb.cost[p][q]==0&&sb.zeroelem[p][q]==0)break;sb.zeroelem[p][q]=1;sb.cost[p][q]--;sb.cost[0][q]--;sb.cost[0][0]--;for(n=1;n<=sb.matrixsize;n++)if(sb.cost[p][n]==0&&sb.zeroelem[p][n]==0){sb.zeroelem[p][n]=2;sb.cost[p][0]--;sb.cost[0][n]--;sb.cost[0][0]--;}}}}if(sb.cost[0][0]>0)twozero(sb);elsejudge(sb,result);}sb=st;}}}void judge(matrix &sb,int result[501][2]){int i,j;int m;int n;int k;m=0;for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==1)m++;if(m==sb.matrixsize){k=1;for(n=1;n<=result[0][0];n++){for(i=1;i<=sb.matrixsize;i++){for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==1)break;if(i<=sb.personnumber&&j<=sb.jobnumber)if(j!=result[k][1])break;k++;}if(i==sb.matrixsize+1)break;elsek=n*sb.matrixsize+1;}if(n>result[0][0]){k=result[0][0]*sb.matrixsize+1;for(i=1;i<=sb.matrixsize;i++)for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==1){result[k][0]=i;result[k++][1]=j;}result[0][0]++;}}else{refresh(sb);}}void refresh(matrix &sb){int i,j;float k;int p;k=0;for(i=1;i<=sb.matrixsize;i++){for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==1){sb.zeroelem[i][0]=1;break;}}while(k==0){k=1;for(i=1;i<=sb.matrixsize;i++)if(sb.zeroelem[i][0]==0){sb.zeroelem[i][0]=2;for(j=1;j<=sb.matrixsize;j++)if(sb.zeroelem[i][j]==2){sb.zeroelem[0][j]=1;}}for(j=1;j<=sb.matrixsize;j++){if(sb.zeroelem[0][j]==1){sb.zeroelem[0][j]=2;for(i=1;i<=sb.matrixsize;i++)if(sb.zeroelem[i][j]==1){sb.zeroelem[i][0]=0;k=0;}}}}p=0;k=0;for(i=1;i<=sb.matrixsize;i++){if(sb.zeroelem[i][0]==2){for(j=1;j<=sb.matrixsize;j++){if(sb.zeroelem[0][j]!=2)if(p==0){k=sb.cost[i][j];p=1;}else{if(sb.cost[i][j]<k)k=sb.cost[i][j];}}}}for(i=1;i<=sb.matrixsize;i++){if(sb.zeroelem[i][0]==2)for(j=1;j<=sb.matrixsize;j++)sb.cost[i][j]=sb.cost[i][j]-k;}for(j=1;j<=sb.matrixsize;j++){if(sb.zeroelem[0][j]==2)for(i=1;i<=sb.matrixsize;i++)sb.cost[i][j]=sb.cost[i][j]+k;}for(i=0;i<=sb.matrixsize;i++)for(j=0;j<=sb.matrixsize;j++)sb.zeroelem[i][j]=0;circlezero(sb);}void zeroout(matrix &sb){int i,j;float k;for(i=1;i<=sb.matrixsize;i++){k=sb.cost[i][1];for(j=2;j<=sb.matrixsize;j++)if(sb.cost[i][j]<k)k=sb.cost[i][j];for(j=1;j<=sb.matrixsize;j++)sb.cost[i][j]=sb.cost[i][j]-k;}for(j=1;j<=sb.matrixsize;j++){k=sb.cost[1][j];for(i=2;i<=sb.matrixsize;i++)if(sb.cost[i][j]<k)k=sb.cost[i][j];for(i=1;i<=sb.matrixsize;i++)sb.cost[i][j]=sb.cost[i][j]-k;}}void output(int result[501][2],matrix sb) {int k;int i;int j;int p;char w;float v;v=0;for(i=1;i<=sb.matrixsize;i++){v=v+sb.costforout[i][result[i][1]];}cout<<"最优解的目标函数值为"<<v;k=result[0][0];if(k>5){cout<<"解的个数超过了限制."<<endl;k=5;}for(i=1;i<=k;i++){cout<<"输入任意字符后输出第"<<i<<"种解."<<endl;cin>>w;p=(i-1)*sb.matrixsize+1;for(j=p;j<p+sb.matrixsize;j++)if(result[j][0]<=sb.personnumber&&result[j][1]<=sb.jobnumber)cout<<"第"<<result[j][0]<<"个人做第"<<result[j][1]<<"件工作."<<endl;}}void main(){result[0][0]=0;sb=input();zeroout(sb);circlezero(sb);output(result,sb);}4. 算例和结果:自己运算结果为:->⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡3302102512010321->⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡330110241200032034526635546967562543----⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎣⎡可以看出:第1人做第4件工作;第2人做第1件工作;第3人做第3件工作;第4人做第2件工作。
用改进的匈牙利算法求解运输问题李雪娇,于洪珍中国矿业大学信电学院,江苏徐州 (221008)Email :liaohuchushan@摘 要:本文提出用改进的匈牙利算法求解运输问题。
此算法不但可以直接求取最优解,而且在运量受限制的运输问题中有很好的应用。
关键词:改进,匈牙利算法,运输问题,最优解0. 引言在现实生活中,我们常常会遇到许多运输问题。
运输问题的求解多采用表上作业法。
在此方法中,我们需要先利用最小元素法或西北角法求出一组基本可行解,再对此解检验其最优性。
若此解非最优解,则又要进行解的改进。
这一过程比较麻烦,尤其对一些结构不太大的模型,编程时往往过于繁琐。
同时,经典运输问题在实际应用中有很大的局限性, 对一些运输量受限制或运输能力受限制的运输问题,我们无法用表上作业法直接求取。
在此,我们采用改进的匈牙利算法处理这类运输问题。
为了便于描述,设物资供应量12[...]m A a a a =,物资需求量12[...]n B b b b =,从到i A j B 的单物的物资运价,最小运输量 (假设m )。
i j C i j L n >1. 匈牙利算法[1][4]匈牙利算法的基本思想是修改效益矩阵的行和列,使得每行和每列中至少有一个零元素。
经过一定的变换,得到不同行、不同列只有一个零元素。
从而得到一个与这些零元素相匹配的完全分配方案。
这种方法总是在有限步内收敛于一个最优解。
该方法的理论基础是:在效益矩阵的任何行或列中,加上或减去一个常数后不会改变最优解的分配。
求解步骤如下:第一步:使指派问题的系数矩阵经变换后,在各行各列中都出现零元素,即从系数矩阵的每行(或列)元素中减去该行(或列)的最小元素。
第二步:寻求找n 个独立的零元素,以得到最优解:(1)从只有一个0元素的行(或列)开始,对这个0元素加圈,记为θ。
然后划去此元素所在列(或行)的其他0元素,记作∅。
反复进行,直到所有的0元素被划完。
(2)若仍有没有划圈的0元素,则从剩有0元素最少的行开始,比较这行0元素所在各列中0元素的数目,选择0元素少的那列的0元素加圈θ,然后划掉同行同列的其他0元素,反复进行直到所有的0元素被划掉或圈出。
运筹学课程设计报告书---运输问题的表上作业法运筹学课程设计报告书专业班级学号姓名LMZZ日期2011.09.01设计题目:运输问题的表上作业法设计方案:运输问题是一种应用广泛的网络最优化模型,该问题的主要目的是为物资调运、车辆高度选择最经济的运输路线。
有些问题,如m 台机床加工零件问题、工厂合理布局问题,虽要求与提法不同,经适当变化也可以使用本模型求得最佳方案。
运输问题的一般提法:某种物资有m 个产地Ai ,产量是ai (i =1,2,…,m ),有m 个销售地Bi ,销量(需求量)是bj(j=1,2,…,m)。
若从Ai 运到Bi 单位运价为dij(i=1,2,…,m;j=1,2,…,m),又假设产销平衡,即∑∑===m i n j j ib a 11问如何安排运输可使总运费最小?若用x ij (i=1,2,…,m;j=1,2,…,n)表示由A i 运到B j 的运输量,则平衡运输问题可写出以下线性规划模型:∑∑===m i n j ij ij x d Z 11min约束条件==≥====∑∑==),...,2,1;...,2,1(0)...,2,1()...,2,1(11n j m i x n j b x m i a x ij m i j ij n j i ij表上作业法原理同于单纯形法,首先给出一个初始的调运方案(实际上是初始基本可行解),求出各非基变量的检验数去判定当前解是否为最优解,若不是则进行方案调整(即从一个基本可行解转换成另一个基本可行解),再判定是否为最优解,重复以上步骤,直到获得最优解为止。
这些步骤在表上进行十分方便。
操作过程在表上进行方案实施:通过运输问题在C++程序中的运用,从而实现方案的最优。
程序主要分两部:(1)求解,(2)最优解判断结果与结论:程序运行过程中,依次输入所需要的运价,产量,销量等数据,单击回车可以再次现实所需数据,按任意键可以运行至求出初始可行解并显示,再次按任意键程序进行最优解的判断,并求出最优解,显示在程序页面上,从而可以得到该运输问题的最优方案。
运输问题的解法运输问题是一类特殊的线性规划问题,最早是从物质调运工作中提出的,后来又有许多其它问题也归结到这一类问题中。
正是由于它的特殊结构,我们不是采用线性规划的单纯方法求解,而是根据单纯形方法的基本原理结合运输问题的具体特性须用表上作业的方法求解。
§1 运输问题的数学模型及其特性1.1 运输问题的数学模型设有 个地点(称为产地或发地) 的某种物资调至 个地点(称为销地或收地),各个发点需要调出的物资量分别为个单位,各个收点需要调进的物资量分别为 个单位。
已知每个发点到每个收点的物资每单位运价为 ,现问如何调运,才能使总的运费最小。
我们把它列在一张表上(称为运价表)。
设表示从产地运往销地的运价( =1,2,…, ; =1,2,…,)。
表3-1如果(总发量)(总收量),我们有如下线性规划问题:m mA A A ,,,21 n nB B B ,,,21 ma a a ,,,21 nb b b ,,,21 iA jB ijc ijx iA jB i m jn(3.1)(3.1)式称为产销平衡运输问题的数学模型。
当(总发量)(总收量)时。
即当产大于销()时,其数学模型为(3.2)当销大于产()时,其数学模型为(3.3)因为产销不平衡的运输问题可以转化为产销平衡的运输问题。
所以我们先讨论产销平衡的运输问题的求解。
运输问题有个未知量,个约束方程。
例如当≈40,=70时(3.1)式就有2800个未知量,110个方程,若用前面的单纯形法求解,计算工作量是相当大的。
我们必须寻找特殊解法。
∑∑===m i nj ijij x c z 11min ⎪⎪⎪⎪⎩⎪⎪⎪⎪⎨⎧==≥====∑∑==),,2,1;,2,1(0),,2,1(),,2,1(11n j m i x n j b x m I a x ij j mi ij i nj ij ∑∑==≠nj jm i i ba 11∑∑==>nj jm i i ba 11∑∑===m i nj ijij x c z 11min ⎪⎪⎪⎪⎩⎪⎪⎪⎪⎨⎧==≥===≤∑∑==),,2,1;,2,1(0),,2,1(),,2,1(11n j m i x n j b x m I a x ij j mi ij i nj ij ∑∑==<nj jm i i ba 11∑∑===m i nj ijij x c z 11min ⎪⎪⎪⎪⎩⎪⎪⎪⎪⎨⎧==≥=≤==∑∑==),,2,1;,2,1(0),,2,1(),,2,1(11n j m i x n j b x m I a x ij j mi ij i nj ij mn n m +m n1.2 运输问题的特性由于运输问题也是线性规划问题,根据线性规划的一般原理,如果它的最优解存在,一定可以在基可行解中找到。
因此,我们先求运输问题(3.1)的约束方程组的系数矩阵的秩()等于多少。
(3.1)式有个约束,将前个约束相加得, (3.4)将后个约束相加,得, (3.5)因为,,所以,(3.4)式与(3.5)式是相同得。
由此可见,这个约束不是独立的。
我们可以证明:当所有的,都大于零时,任何个约束都是相互独立的。
即,系数矩阵A 的秩,事实上,… … … …注意到在中去掉第1行而取出第2,第3,…,第行,又取出与所对对应的列,则由这些取出的行和列的交叉处的元素构成的一个级子式r A n m +m ∑∑∑====mi im i nj ija x111n ∑∑∑====ni jn j mi ijb x111∑∑===nj jmi i ba 11n m +ia jb 1-+n m 1)(-+=n m A r 11x 12x n x121x 22x n x 21m x 2m x mn x ⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎦⎤⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎣⎡=111111111111111111 A A n m +1312111211,,,,,,,m n x x x x x x A 1-+n m D所以 ,由此可知,运输问题的任何一组基都由 个变量组成。
第一,所有未划去的行列中找出最小元素(若有几个元素同时最小,则可任取其一),在该元素所在的变量处填上尽可能大的数字,并作上标记;第二,划去已被满足的行或列的空格,若表中某一变量处填入一数后,使该变量所在之行和所在之列同时被满足,遇只能划去一行或一列,而不能将两者同时划去;第三.上述步骤,直至所有的空格都已填数或被划去为止。
§2 运输问题的表上作业法2.1 初始解的求法同单纯形法一样,首先要求初始调运方案必须是一个基可行解,初始解一般来说不是最优解,主要希望给出求初始解的方法简便可行,且有较好的效果。
这种方法很多,最常 见的是左上角法(或西北角法)、最小元素法和Vogl 近似法(VAM)。
后两法的效果较好,在此我们仅对最小元素法加以介绍。
最小元素法的所谓元素就是指单位运价。
此法的基本思想是:运价最便宜的优先调运,现通过例子来说明。
例1 设有某种物质要从三个仓库运往四个销售点。
各发点(仓库)的发货量、各收点(销售点)的收货量以及到的单位运费如表3-2( =1,2,3; =1,2,3,4).组织运输才能使总运费最少?表3-21111111111≠=⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯=D 1)(-+=n m A r 1-+n m 321,,A A A .,,,4321B B B B iA jB ijC ij由表3-2知,总的发量=总的收量,供销平衡。
现从取最小值的格子开始(若有几个 同时取最小值,则可取其中之一)。
在本例中 最小。
这说明,将 的物质调给是最便宜的,故应给所对应的变量 以尽可能大的数值。
显然应取。
在处填上7。
由于的 需求已经得到满足(或者说 列已被满足),故应为零,在处打×将列划去,并将的发量相应地改为2(见表3-3)。
在表3-3未划线的格子中,最小的为。
有 即令,并在第二列的其它空格(即在 )处打×,于是第二列又被划去,且 的发量只有1了。
表3-3ijc ijc 113=c 1A 3B 13c 13x 7)7,9m in(13==x 13x 3B 3B 3323,x x 3323,x x 3B 1A ijc 622=c )9,10m in(22=x 922=x 3212,x x 2A接下去的做法是:在 处填上2,此时, 的发量已分配完毕(一般说成: 行被满足),故应在第一行的其它空格处(实际上只有)打上×,划去第一行。
在处填上1,在第二行的其它空格处(实际上只有了)打上×,划去第二行。
在处填上1,在第一列的其它空格处(实际上已无空格)打上×,划去第一列。
在处填上5,在第四列(或第3行)的其它空格处(实际上已无空格)打上×,划去第四列(或第三行),见表3-4。
至此,所有方格都已填上数或打上×,总共填了3+4-1=6个数(等于基变量的个数)其余方格均已打×。
每填一数就划去了一行或一列,总共划去的行数与列数之和也是6。
可以证明,用最小元素法所得到的一组解 是基可行解,而且填数处是基变量,打×处是非基变量。
它对应的目标函数为在用最小元素法确定初始调运方案的 基本步骤:11x 1A 1A 14x 21x 24x 31x 34x ijx 184516114961117129=⨯+⨯+⨯+⨯+⨯+⨯=z值得注意的是,如是空格,但的需求已满足,(或的物质已调完)不需要(或不可能)再调运物质到,此时必须禽,以保证最后填数的个数个。
这一点对于以下的计算是重要的。
2.2验数的求法表上作业法同单纯形法一样,也是利用检验数判别已取得的解是否为最优解。
表上作业法求检验数一般有两种方法:位势法和闭回路法。
这里我们先介绍位势法。
1 位势法首先构造位势表我们将运价表中对应于表3-4有运量处划方格,然后在表的右边添加一列,下面添加一行。
并且在添加的行、列里填上一些数,使得表中任何划了方格的对应运价正好等于它所在行及所在列中新填入数字之和。
(见表3-5)具体作法如下:将行右边空格填入零,则列、列下面的空格中必须分别填入9、1。
由于11=9+2,所以,行的右边空格必须填入2。
类似地,列的下面应该填入4(因6=4+2),行的右边只能填5(因14=9+5),最后,由,所以,列必须填入11。
这样就得到了表3-5.这个表称为位势表,新填入的数字分别称为行位势和列位势。
并分别记为和(=1,2,3;=1,2,3,4)。
ijxjBiAiA j B0=ijx1-+nm 1A1B3B2A2B3A1634=C4Biαjβi j再求检验数设所在的格子的检验数为,则我们可以证明=-(+)( =1,2,…, ; =1,2,…, ),(3.6)并且当所有的0时,对应的调运方案是最优方案。
表3-5显然,对于那些在方中已确定了调运量的格子的检验数应该为零,即有=+,上面我们在求行位势与列位势时就利用了这一关系。
下面我们来求其余格子所对ijx ijσijσijc iαjβi m j n ≥ijσijσijc iαjβ应的检验数。
;;;;;;2 闭回路法首先介绍闭回路的概念:如果已确定了某一调运方案,我们从某一空格出发(无调运量的格子),沿水平方向或垂直方向前进,遇到某一个适当有调运量的格子就转向继续前进。
如此继续下去,经过若干次,就一定回到原来出发的空格。
这样形成的一条由水平和垂直线段组成的封闭折线称为闭回路。
在表上作业法中,闭回路中重要的概念之一,它既可以计算检验数又可以调整调运方案。
由于数字格对应着基变量,其检验数均为零,而我们考虑的是非基变量的检验数,所以只研究从空格出发所形成的闭回路。
由闭回路的构成可见,除起点是空格外,其余所有的拐角点都是填有调运量的。
我们可以证明一个重要的事实:从每一个空格出发都存在唯一的闭回路。
例如在表3-5所示的初始调运方案中作出从(3.2)对应的空格为起点的闭回路为(3,2) (2,2) (2,1) (3,1) (3,2)这条闭合回路,除出发格(3,2)为空格外,其余都是数字格,如表3-6所示。
14)40(18)(211212=+-=+-=βασc 1)110(10)(211414-=+-=+-=βασc 5)12(8)(322323=+-=+-=βασc 5)112(18)(422424=+-=+-=βασc 3)45(12)(233232=+-=+-=βασc 4)15(2)(333333-=+-=+-=βασc ︒90→→→→为确定空格( )的检验数,便可以从空格( )出发作闭回路,并对该回路的顶点进行编号,即以( )格为第一个顶点,所经过的顶点依次为第二个、第三个……。
则闭回路上奇数顶点的单位运价之和减去偶数顶点的单位运价之和所得到的差,就是空格( )的检验数。