线性规划之单纯形小结

1 篇文章 0 订阅
1 篇文章 0 订阅

学了单纯形决定写个小结,方便以后复习。
这里只打算写结论和实现过程,证明什么的统统没有

定义

标准型

最大化

j=1ncjxj

满足
j=1naijxjbii=1,2,...,mxj0j=1,2,...,n

松弛型

每个约束都引入一个松弛变量 xn+i
最大化

j=1ncjxj

满足
xn+i=bij=1naijxji=1,2,...,mxj0j=1,2,...,n+m

对偶性

给定上面的标准型线性规划,定义其对偶线性规划为

最小化

i=1mbiyi

满足
i=1maijyicjj=1,2,...,nyi0i=1,2,...,m

此对偶线性规划的最优值等于原始线性规划的最优值。

转化到标准型

对于最小化目标函数,取反转化成最大化。
对于等式约束,拆成两个大于等于和小于等于的不等式约束。
符号与标准型相反的约束,取反。
对于取值范围无限制的变量 xi ,用两个新变量 xi1 xi2 来表示,其中 xi=xi1xi2xi1,xi20

更简洁的表示形式

称松弛型中左边的变量为基本变量右边的变量为非基本变量
用集合 N 表示非基本变量下标集合,B表示基本变量下标集合,总有 |N|=n |B|=m NB={1,2,...,n+m}

z 来表示目标函数值,并添加一个常数项v

最大化

z=v+jNcjxj

满足
xi=bijNaijxjiBxj0jNB

其他

满足所有约束的一组 x 称为可行解
非基本变量(等式右边)0得到的解称为基本解,可以知道此时 xn+i=bi
若基本解满足所有约束则称为基本可行解

单纯形算法

方便起见先假设初始状态得到的基本解可行,即所有的 bi 非负。

主要思想

每次选择一个非基本变量 xi (称为替入变量),满足对应的目标函数上的系数 ci 为正,增大它的值直到某个基本变量(称为替出变量)变为 0 。然后重写松弛型,交换替入变量和替出变量,并更新目标函数和其他约束上的系数。
每一轮迭代后,目标函数的值将不变或增大。

转动

假设我们已经找到了替入变量xe和替出变量 xl ,接下来的操作是重写松弛型。
首先要先交换 xe xl 的位置,变 xe 为基本变量。
其次是把新式子带入其他约束和目标函数中,得到新的松弛型。

代码

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]-=a[i][e]*b[l];
        for (int j=1;j<=n;j++)
            if (j!=e) a[i][j]-=a[i][e]*a[l][j];
        a[i][e]*=-a[l][e];
    }
    v+=c[e]*b[l];
    for (int i=1;i<=n;i++)
        if (i!=e) c[i]-=a[l][i]*c[e];
    c[e]*=-a[l][e];
}

选择替入变量和替出变量

选择一个系数在目标函数中为正值的非基本变量 xe ,若不存在(即目标函数所有系数均 0 )说明目标函数已达到最优值
检查每个约束,找出一个约束,使得该约束限制 xe 可取的最大值尽量小,设这个约束的基本变量为 xl 。若没有约束可以限制 xe 的取值,说明该目标函数无界
由于所有的非基本变量都为0,因此第 i 个约束可以写成xi=biaiexe。当 aie0 时, xe 无限制,否则 xe 最多可增加到 bi/aie ,此时 xi=0
因此找到满足 aie>0 bi/aie 最小的 i 即可。

代码

double SIMPLEX(){
    for (;1;){
        int e=-1,l=-1;
        for (int i=1;i<=n;i++)
            if (c[i]>eps){
                e=i;break;
            }
        if (e==-1) break;
        double tmp=inf;
        for (int i=1;i<=m;i++)
            if (a[i][e]>eps && b[i]/a[i][e]<tmp)
                l=i,tmp=b[i]/a[i][e];
        if (l==-1) return inf;
        PIVOT(l,e);
    }
    return v;
}

还存在的问题

在OI中遇到的许多问题(比如网络流)都可以直接使用单纯形。虽然单纯形算法不是多项式时间算法,但是实际运行效果往往较好。对于题目中的原始线性规划,当初始基本解不是可行解时,一般可以通过转化成对偶线性规划来得到基本可行解。

需要注意的是单纯形算法求出的解是在实数范围内,许多题目可能会要求整数解,但是一般可以转化成线性规划的问题(比如网络流)通常有些奇怪的性质(咦?)使得实数解和整数解的最优目标值一样。即使单纯形算法并不能得到正确的答案也能骗到十分可观的分数。

因此如果只是想大概地了解一下单纯形算法并使用,看到这里就可以辣。

初始基本可行解

前面说到初始基本解可能并不可行,因此我们需要找到一个基本可行解,或者判断该线性规划不存在可行解。

辅助线性规划

L是原始线性规划,我们构造一个辅助线性规划 Laux ,需要增加一个新变量 x0

最大化

x0

满足
j=1naijxjx0bii=1,2,...,mxj0j=0,1,...,n

Laux 的最优目标值为0,那么 L 是可行的,否则不可行

判定可行性

L初始基本解不可行(即存在 bi 是负数)时, Laux 的初始基本解一定也不可行。

此时在 Laux 中找到一个 l 使得bl的值最小。然后以 x0 为替入变量, xl 为替出变量,执行一个转动(PIVOT)操作,由此产生的 Laux 基本解一定是可行的。然后对 Laux 执行SIMPLEX操作,求出最优目标值。

Laux 最优解目标值为0,说明 L 是可行的。

求出基本可行解

由于x0可能仍是基本变量,因此选择任意一个满足 a0e0 eN 作为替入变量,执行一个转动操作把 x0 从基本解中移除。然后从约束中删除所有 x0 项,并恢复 L 的原始目标函数。原始目标函数可能包含了当前的基本变量和非基本变量,用等式右边来目标函数替换基本变量即可。

退化

单纯形算法每次迭代都会使目标函数不变或增大,这其中可能会出现一种退化情况,即循环现象,使得算法不会终止。

Bland规则:在选择替入变量和替出变量时,总是选择满足条件的下标中最小的,这样可以避免循环。算法最多在Cmn+m次迭代内终止。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值