以下内容全是口胡,请谨慎观看 ——From ATP
参见高中数学必修五第三章
根据ATP的理解。。。线性规划就是设出一些变量,给出一些对于变量取值的限制,同时给出一个与这些变量相关的目标函数,要求在满足限制的前提下最大化或最小化目标函数。
举个例子:设有变量
就是一个线性规划啦。。(上面那一坨东西是ATP随便打上去的有没有解就不一定了= =)
形式化地,设
我们在这里仅讨论线性规划的标准型。线性规划的标准型表示如下:
但是很多时候好像遇到的线性规划并不是标准型?难道它们不能做吗。。。其实并不是,在大多数情况下,不是标准型的线性规划都可以通过做一些适当的转化表示成标准型。比如……
目标函数要求最小化(
首先线性规划的限制应该都是大于等于或者小于等于这种形式的(不然计算机怎么搞出“无限接近”这种类型的答案来= =),但是在标准型里面限制都要求是小于等于,如果遇到别的符号? 如果是带“
总之通过类似这样的变换我们可以把任意的线性规划转化为标准型,并且它们的最优解都是不变的。
求解线性规划最常用的算法是单纯形算法。它的理论时间复杂度是指数级别的。。但是跑得奇快无比啊并且也基本上卡不掉。。所以放心大胆用就是了。。
单纯形算法的几何意义很多地方都有解释。。但是这里ATP主要解释它在代数方面的原理。
首先,为了对线性规划使用单纯形算法,我们需要把线性规划转化为“松弛型”,也就是说把所有的不等式变为等式。以下都用m来表示限制个数,n来表示变量个数。
为了做到这一点,我们对于每一个形如
相对的那我们就把所有
那么我们把所有的
先贴代码,在下面解释:
double Simplex(){ int l,e; double t; while (true){ e=n+1; for (int i=1;i<=n;i++) if (C[i]>eps){e=i;break;} if (e==n+1) break; t=inf;l=0; for (int i=1;i<=m;i++) if (A[i][e]>eps&&t>B[i]/A[i][e]){ t=B[i]/A[i][e];l=i; } if (t==inf) return inf; pivot(l,e); } return v;}上面的Simplex过程是单纯形算法的主过程。首先每次先找到第一个系数大于0的非基变量。这里有一个叫做Bland法则的东西,就是说一定要选第一个系数大于0的,不然容易被特殊数据卡成死循环。。然而ATP并没有试过= =
选中的这个非基变量就是上面的e。如果没有找到这样的变量,说明算法已经完成了,目标函数中的所有系数都变成负数了,就可以退出了。否则我们要把目标函数中
不同的约束条件产生的
否则我们能够找到一个约束条件
基变量
于是上面的pivot过程就是来做这样的变形的。这玩意儿好像学名叫“转轴”操作,好像来源于单纯形算法的几何意义。。不管它不管它。
pivot过程是这样的:
void pivot(int l,int e){ B[l]/=A[l][e]; for (int i=1;i<=n;i++) if (i!=e) A[l][i]/=A[l][e]; A[l][e]=1/A[l][e]; for (int i=1;i<=m;i++) if (i!=l&&fabs(A[i][e])>eps){ B[i]-=B[l]*A[i][e]; for (int j=1;j<=n;j++) if (j!=e) A[i][j]-=A[l][j]*A[i][e]; A[i][e]=-A[l][e]*A[i][e]; } v+=C[e]*B[l]; for (int i=1;i<=n;i++) if (i!=e) C[i]-=C[e]*A[l][i]; C[e]=-C[e]*A[l][e];}这里的
为了替换方便我们要把
这样我们就完成了过程的第一步,也就是上面代码里前4行的内容。
接下来我们要对所有除了约束条件
很容易发现替换以后约束条件
最后是对于目标函数的处理,同样是把
最后当目标函数中所有系数都变成负数的时候,记录的v就是线性规划的最优解啦。
前面我们所有的讨论都基于一个假设:所有非基变量取0是一组可行解。
但是很多时候我们会碰到这样的线性规划:
把所有系数取反?但是取反这种操作是不会改变约束条件的本质的。这个时候我们就会用到对偶原理了
形式化的,对偶原理就是说:
这两个线性规划是等价的。
显然,如果我们遇到了一个这种所有非基变量取0不是可行解的线性规划,我们可以用对偶原理把它“转”一下,就会变成一个所有非基变量取0是可行解的线性规划,就可以用单纯形求解了。
证明?好像不大会用到,ATP也不会。。。
不过想要理解一下对偶原理的话,这篇文章还是不错的[戳这里]。。。
参考曹钦翔《线性规划与网络流》。。。
ATP其实没怎么看那个。。。
主要问题是感觉里面说的基本上就是如何把现成的网络流模型改造成线性规划。。。
但是既然都有了网络流模型干嘛还要改线性规划啊。。。(゚Д゚*)ノ
这种方法是ATP一开始看线性规划的时候稀里糊涂学过来的。。也没大用过。。在这里提一句吧。。
例:BZOJ1061 志愿者招募
用费用流做线性规划的时候,我们要做的第一步仍然是列出不等式并且把它们转化成松弛型。接下来以这个题的样例来举例说明操作过程。
首先设每一种志愿者的招募人数为
添加两个约束条件
我们把它们化成这种形式是有原因的,因为我们求解的方法是网络流,而这组等式满足一个十分关键的性质——它们相加的和等于0。这可以和网络流中的流量平衡结合起来。那么我们可以把上面的每个等式看成一个点并且按照变量的正负进行连边,并且设定“流出为正,流入为负”,那么源点S作为唯一只有流出流量的点,它流出的流量可以看成等式右边那些正数;汇点T作为唯一只有流入流量的点,它流入的流量可以看成等式右边那些负数。然后我们找到每个变量
其实这个过程就是将费用流问题转线性规划问题的逆过程。。
新闻热点
疑难解答